public void Run()
        {
            if (!quiet)
            {
                Console.WriteLine("Tic Tac Toe Machine Learning Demonstration");
            }

            // Create starting state
            IState         state    = new TicTacToeState();
            TicTacToeState tttState = state as TicTacToeState;

            // Create players one and two
            Agent playerOne = new Agent();
            Agent playerTwo = new Agent();

            // Wire player behaviors to state events
            TicTacToeState.WireEvents(tttState, playerOne, playerTwo);

            // Conduct training
            if (!useInFile)
            {
                TicTacToeState.TrainZeroSum(training, !quiet, playerOne, playerTwo);
            }

            // Handle serialization
            if (useInFile)
            {
                Utilities.ReadInFile(inFile, playerOne, playerTwo);
            }
            if (useOutFile)
            {
                Utilities.WriteOutFile(outFile, playerOne);
            }

            // Determine victory, defeat, and cat's game events
            bool playerTwoVictory = false;
            Action <object, EventArgs> declareVictory = (object sender, EventArgs e) => playerTwoVictory = true;

            TicTacToeState.PlayerWinsO += declareVictory;

            bool playerTwoDefeat = false;
            Action <object, EventArgs> declareDefeat = (object sender, EventArgs e) => playerTwoDefeat = true;

            TicTacToeState.PlayerWinsX += declareDefeat;

            bool playerTwoDraw = false;
            Action <object, EventArgs> declareDraw = (object sender, EventArgs e) => playerTwoDraw = true;

            TicTacToeState.CatsGame += declareDraw;

            // Player competes with computer
            while (!playerTwoVictory && !playerTwoDraw && !playerTwoDefeat)
            {
                tttState = playerOne.Act(tttState.SuccessorsX) as TicTacToeState;

                // No need to GoalTest if game is over
                if (!playerTwoDraw)
                {
                    tttState.GoalTest();
                }

                if (!playerTwoVictory && !playerTwoDraw && !playerTwoDefeat)
                {
                    // Display move options
                    List <IState> options = tttState.SuccessorsO;

                    if (!playerTwoDraw)
                    {
                        // Prompt the user
                        TicTacToeState.PrintOptions(options);
                        Console.Write("Please select a move: ");
                        int moveIndex = Int32.Parse(Console.ReadLine()) - 1;

                        // Assign the state
                        tttState = options[moveIndex] as TicTacToeState;
                        tttState.GoalTest();
                    }
                }

                // Select outcome
                if (playerTwoVictory)
                {
                    Console.WriteLine("Human player wins!");
                }

                if (playerTwoDefeat)
                {
                    Console.WriteLine("Computer wins!");
                }

                if (playerTwoDraw)
                {
                    Console.WriteLine("Cat's game!");
                }
            }
        }
Esempio n. 2
0
        public static void TrainZeroSum(long practiceGames, bool showOutput, Agent agentOne, Agent agentTwo)
        {
            // Create starting state
            IState         state    = new TicTacToeState();
            TicTacToeState tttState = state as TicTacToeState;

            // Put agents in training mode
            agentOne.TrainingMode(1.0);
            agentTwo.TrainingMode(1.0);

            // Use repeated wins as a benchmark
            bool enoughTraining = false;
            long games          = 0;
            int  ticks          = 0;
            bool dotPrinted     = false;

            // Reset dotPrinted after it has moved on
            Action <object, EventArgs> resetDotPrinted = (object sender, EventArgs e) => dotPrinted = false;

            TicTacToeState.PlayerWinsX += resetDotPrinted;
            TicTacToeState.PlayerWinsO += resetDotPrinted;
            TicTacToeState.CatsGame    += resetDotPrinted;

            // Begin training progress bar
            if (showOutput)
            {
                Console.Write("[ ");
            }

            // Watch each agent evolve
            while (!enoughTraining)
            {
                // Train the first agent
                tttState = agentOne.Act(tttState.SuccessorsX) as TicTacToeState;
                tttState.GoalTest();

                games = agentOne.Victories + agentTwo.Victories + agentOne.Draws;

                // Account for every 1% of progress
                if (games % (practiceGames / 100) == 0 && !dotPrinted)
                {
                    // Update competitiveness at quarters
                    if (ticks % 25 == 0)
                    {
                        // Display quarter in progress bar
                        if (showOutput)
                        {
                            Console.Write($"[{ticks}]");
                        }

                        // Make each agent more competitive
                        agentOne.TrainingMode((100.0 - ticks) / 100.0);
                        agentTwo.TrainingMode((100.0 - ticks) / 100.0);
                    }

                    // Update ticks
                    ticks += 1;

                    // Don't include hundredth tick
                    if (ticks < 100 && showOutput)
                    {
                        Console.Write(".");
                    }

                    dotPrinted = true;
                }

                // Check if total number of practices have been met
                if (games >= practiceGames)
                {
                    enoughTraining = true;
                }

                // Train the second agent, assuming they are not sufficiently trained
                if (!enoughTraining)
                {
                    tttState = agentTwo.Act(tttState.SuccessorsO) as TicTacToeState;
                    tttState.GoalTest();

                    games = agentOne.Victories + agentTwo.Victories + agentOne.Draws;

                    // Account for every 1% of progress
                    if (games % (practiceGames / 100) == 0 && !dotPrinted)
                    {
                        // Update competitiveness at quarters
                        if (ticks % 25 == 0)
                        {
                            // Display quarter in progress bar
                            if (showOutput)
                            {
                                Console.Write($"[{ticks}]");
                            }

                            // Make each agent more competitive
                            agentOne.TrainingMode((100.0 - ticks) / 100.0);
                            agentTwo.TrainingMode((100.0 - ticks) / 100.0);
                        }

                        // Update ticks
                        ticks += 1;

                        // Don't include hundredth tick
                        if (ticks < 100 && showOutput)
                        {
                            Console.Write(".");
                        }

                        dotPrinted = true;
                    }

                    // Check if total number of practices have been met
                    if (games >= practiceGames)
                    {
                        enoughTraining = true;
                    }
                }
            }

            // End progress bar
            if (showOutput)
            {
                Console.WriteLine(" ]");
                Console.WriteLine("\n");
            }

            // Put agents in competitive mode
            agentOne.CompeteMode();
            agentTwo.CompeteMode();
        }