예제 #1
0
        static void DrawBoard(Trainer trainer)
        {
            lock (DrawLock)
            {
                Console.SetCursorPosition(0, 0);
                var b = trainer.Game.Board;

                string upper = "   ┌───┬───┬───┬═══┬═══┬───┬───┬───┐";
                //string row =   "  │   │   │   │   │   │   │   │   │";
                string middle = "   ├───┼───┼───┼───┼───┼───┼───┼───┤";
                string lower  = "   └───┴───┴───┴═══┴═══┴───┴───┴───┘";
                string xlabel = "     a   b   c   d   e   f   g   h";

                Console.WriteLine(upper);
                for (int y = 8; y > 0; --y)
                {
                    Console.Write(" " + y + " │");
                    for (int x = 0; x < 8; ++x)
                    {
                        var card = b[x, y - 1].Card;
                        if (card == null)
                        {
                            Console.Write("   ");
                        }
                        else
                        {
                            var oldCol = Console.ForegroundColor;
                            Console.ForegroundColor = card.Owner.PlayerNumber == 1 ? ConsoleColor.Cyan : ConsoleColor.Red;
                            if (card is FirewallCard)
                            {
                                Console.Write(" F ");
                            }
                            else
                            {
                                var onlCard = card as OnlineCard;
                                if (onlCard == null)
                                {
                                    Console.Write("err");
                                }
                                else
                                {
                                    if (onlCard.Type == OnlineCardType.Unknown)
                                    {
                                        Console.Write(onlCard.HasBoost ? "-X-" : " X ");
                                    }
                                    else if (onlCard.Type == OnlineCardType.Link)
                                    {
                                        Console.Write(onlCard.HasBoost ? "-L-" : " L ");
                                    }
                                    else if (onlCard.Type == OnlineCardType.Virus)
                                    {
                                        Console.Write(onlCard.HasBoost ? "-V-" : " V ");
                                    }
                                    else
                                    {
                                        Console.Write("ERR");
                                    }
                                }
                            }
                            Console.ForegroundColor = oldCol;
                        }
                        Console.Write("│");
                    }
                    if (y == 8)
                    {
                        Console.WriteLine(" Stack: ");
                        Console.Write(middle + " P2: ");
                        DrawStack(9, trainer);
                        Console.WriteLine();
                    }
                    else if (y == 7)
                    {
                        Console.Write(" P1: ");
                        DrawStack(8, trainer);
                        Console.WriteLine();
                        Console.WriteLine(middle);
                    }
                    else if (y == 6)
                    {
                        Console.WriteLine(" Game Phase: " + trainer.Game.Phase + " ");
                        Console.WriteLine(middle + " Round: " + trainer.Round + "  ");
                    }
                    else if (y == 5)
                    {
                        Console.WriteLine(" Generation: " + (gen + 1) + "/" + maxGen + "  ");
                        Console.WriteLine(middle + " Progress: " + genProgress + "%  ");
                    }
                    else if (y == 2)
                    {
                        Console.WriteLine(" Board: ");
                        Console.WriteLine(middle + " X = Unknown");
                    }
                    else if (y == 1)
                    {
                        Console.WriteLine(" L = Link ");
                        Console.WriteLine(lower + " V = Virus");
                    }
                    else
                    {
                        Console.WriteLine();
                        if (y > 1)
                        {
                            Console.WriteLine(middle);
                        }
                    }
                }
                //Console.WriteLine(lower);
                Console.WriteLine(xlabel);
            }
        }
예제 #2
0
        static void Main(string[] args)
        {
            Console.WriteLine("NOU AI Trainer\n");
            Console.WriteLine("Select mode: ");
            Console.WriteLine("\t1: Genetic algorithm against MIA AI. (default)");
            Console.WriteLine("\t2: Backproagation learning from MIA AI.");
            var usrInput = Console.ReadLine();

            if (usrInput == "2")
            {
                BackPropTraining();
                return;
            }
            Console.Clear();
            Console.WriteLine("NOU AI Trainer\n");

            string dir       = "Nou_AI";
            string genTxt    = dir + "\\gen.txt";
            string genLogTxt = dir + "\\genLog.txt";
            Func <int, int, string> netFile = (a, b) => { return(dir + "\\net" + a + "." + b + ".txt"); };

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            if (File.Exists(genTxt))
            {
                uint.TryParse(File.ReadAllText(genTxt), out gen);
            }

            Console.WriteLine("Current generation: " + gen);
            Console.WriteLine("Please enter number of iterations: ");
            var inp = Console.ReadLine();

            if (!uint.TryParse(inp, out uint gen2Go))
            {
                Console.WriteLine("Not a number! Press any key to exit");
                Console.ReadKey();
                return;
            }
            Console.CursorVisible = false;

            Trainer.MaxRound = 15;

            // We have 50 AIs. All fight the same MIA instance.
            int    aiCnt         = 50; // Number of AIs per generation
            double mutationDelta = Nou.MutateDelta / 3;
            var    log           = new Dictionary <int, TrainingLog>();
            var    fac           = new NouFactory(); // Loads pretrained NouAi_0.txt

            for (int i = 0; i < aiCnt; ++i)
            {
                log.Add(i, new TrainingLog {
                    AI = (Nou)fac.CreateInstance(), ID = i
                });
            }

            // Check if there are saved nets on the hard drive
            if (gen > 0) // Ignore if we start from gen 0
            {
                for (int i = 0; i < aiCnt; ++i)
                {
                    log[i].AI.ReadFromFile(0, netFile(i, 0));
                    log[i].AI.ReadFromFile(1, netFile(i, 1));
                }
            }
            var rnd = new Random(); // Used for applying seed to MIA.

            genProgress = 0;
            maxGen      = gen + gen2Go;

            byte mutateFlags = 1; // Only train net1.

            // Cycle through all defined generations
            for (int it = 0; it < gen2Go; ++it)
            {
                genProgress = (int)(0.5 + 100.0 * ((1.0 * it) / gen2Go));

                int curGenSeed = rnd.Next();
                int nouSeed    = rnd.Next();

                #region NextGen Prep
                if (it > 0)
                {
                    // Based on 50 AIs:
                    // 1. Delete the 25 least scoring nets
                    // 2. Keep the best 5 nets untouched    //  +5 ->  5
                    // 3. Mutate the remaining 20 nets      // +20 -> 25
                    // 4. Create 4 copies of the 5 best
                    //    nets and mutate them              // +20 -> 45
                    // 5. Add 5 ranom nets                  //  +5 -> 50

                    // We do not create new randoms AIs.
                    // All our progress might get lost if a random ai accidentally scores high

                    // 1. + 2.
                    // Sort by score
                    var sortedList = log.Select(o => o.Value).OrderByDescending(o => o.Score).ToList();
                    log.Clear();                        // Clear list
                    for (int i = 0; i < aiCnt / 2; ++i) // Add the 25 best nets
                    {
                        sortedList[i].ID = i;           // Update ID
                        log.Add(i, sortedList[i]);
                    }
                    // 3. Mutate the last 20 nets in the new list
                    for (int i = 5; i < aiCnt / 2; ++i)
                    {
                        log[i].AI.Mutate(mutationDelta, mutateFlags);
                    }
                    // 4.
                    int fillerRatio = (aiCnt / 2 - 5) / 4; // =5 when aiCnt=50
                    int nId         = aiCnt / 2;
                    for (int iAi = 0; iAi < 5; iAi++)      // The first five AIs
                    {
                        for (int ii = 0; ii < fillerRatio; ++ii)
                        {
                            var nou = Nou.Copy(log[iAi].AI);
                            nou.Mutate(mutationDelta, mutateFlags);
                            log[nId] = new TrainingLog()
                            {
                                ID = nId, AI = nou
                            };
                            ++nId;
                        }
                    }
                    // 5.
                    while (log.Count < aiCnt)
                    {
                        log.Add(log.Count, new TrainingLog {
                            ID = log.Count, AI = (Nou)fac.CreateInstance()
                        });
                    }
                }

                // Reset score at the start of each generation
                for (int ai = 0; ai < aiCnt; ++ai)
                {
                    log[ai].Score = 0;
                }

                #endregion

                Trainer trainer = null;

                // Cycle through all AIs
                Parallel.ForEach(log.Select(o => o.Value), new ParallelOptions()
                {
                    MaxDegreeOfParallelism = 8
                }, (aiLog) =>
                {
                    Trainer trn = new Trainer();

                    var mia = new Mia();
                    mia.SetSeed(curGenSeed);
                    mia.Depth = 1;

                    if (aiLog.ID == 0)
                    {
                        trainer     = trn;
                        trn.AiDelay = 0; // This is the displayed trainer.
                    }

                    var waitHandle       = new AutoResetEvent(false);
                    EventHandler handler = (s, a) =>
                    {
                        if (trn.GameOver)
                        {
                            try { waitHandle.Set(); } catch { }
                        }
                    };
                    trn.NeedsUiUpdate += handler;

                    aiLog.AI.DeploySeed = nouSeed;
                    // Run game:
                    trn.StartGame(aiLog.AI, mia);

                    waitHandle.WaitOne(100 * Trainer.MaxRound); // Give 100ms per round
                    trn.NeedsUiUpdate -= handler;
                    trn.Abort          = true;

                    if (trn.Game.Phase == GamePhase.Player1Win)
                    {
                        Interlocked.Increment(ref nouWins);
                    }
                    else if (trn.Game.Phase == GamePhase.Player2Win)
                    {
                        Interlocked.Increment(ref miaWins);
                    }

                    // Post Game: Add score
                    aiLog.Score = aiLog.AI.Fitness();
                });
                genProgress = (int)(0.5 + 100.0 * ((it + 1.0) / gen2Go));
                if (trainer != null)
                {
                    DrawBoard(trainer);
                }

                // Log score to file
                ++gen;
                try
                {
                    var genSorted = log.Select(o => o.Value).OrderByDescending(o => o.Score).ToList();
                    using (var f = File.AppendText(genLogTxt))
                    {
                        f.WriteLine("Gen:\t" + gen + "\tScore:\t" + genSorted[0].Score.ToString(System.Globalization.CultureInfo.InvariantCulture));
                    }
                }
                catch { }
            }

            // Save all current Nets
            for (int i = 0; i < aiCnt; ++i)
            {
                log[i].AI.Net1.SaveAsFile(netFile(i, 0));
                log[i].AI.Net2.SaveAsFile(netFile(i, 1));
            }
            File.WriteAllText(genTxt, gen.ToString());

            System.Threading.Thread.Sleep(500); // Wait for UI updates
            Console.CursorVisible = true;
            Console.WriteLine("Finished. Press any key to exit");
            Console.ReadKey();
        }