예제 #1
0
        /// <summary>
        /// Calculates the resulting fitness value by using the passed weights
        /// and returns the value in a FitnessInfo class together with other relevant info about the calculation.
        /// </summary>
        public IFitnessInfo CalculateFitness(double[] weightsForNeuralNetwork)
        {
            int    action              = 0;
            int    currentScore        = 0;
            int    movesSincePoint     = 0;
            int    movesTotal          = 0;
            double fitness             = 0;
            double averageMovesPerFood = 0;

            double[]    input = new double[ProgramSettings.NUMBER_OF_INPUT_NEURONS];
            EndGameInfo endGameInfo;

            // Setup new snake game and neural network
            neuralNetwork = new NeuralNetwork(NetworkSettings, weightsForNeuralNetwork);
            snakeGame     = new SnakeGame(SnakeSettings);

            // Make recorder
            if (record)
            {
                recorder = new FitnessCalculatorRecording(agentToRecord, NetworkSettings, SnakeSettings);
                recorder.TakeSnapShotInitial(snakeGame, movesSincePoint, movesTotal, input, neuralNetwork);
            }

            // Simulation begins
            do
            {
                input  = ConvertGridToInput(snakeGame.Grid, snakeGame.Snake, snakeGame.Food);
                action = neuralNetwork.CalculateOutput(input);
                snakeGame.UpdateDirection(action);
                // Check if got point
                if (snakeGame.Score != currentScore)
                {
                    movesSincePoint = 0;
                    currentScore    = snakeGame.Score;
                }
                else
                {
                    movesSincePoint++;
                }
                movesTotal++;
                if (record) // Save round info.
                {
                    recorder.TakeSnapShotRound(snakeGame, movesSincePoint, movesTotal, input, neuralNetwork);
                }
                FitnessRoundsCount++;
            } while(snakeGame.Snake.IsAlive && movesSincePoint < GetMaxMoves(snakeGame.Snake.Lenght));

            if (snakeGame.FoodEaten != 0)
            {
                averageMovesPerFood = movesTotal / (double)snakeGame.FoodEaten;
            }

            fitness     = snakeGame.Score;
            endGameInfo = new EndGameInfo(snakeGame, fitness, averageMovesPerFood, movesTotal);

            if (record)
            {
                recorder.TakeSnapShotEndGame(endGameInfo);
            }
            return(endGameInfo);
        }
        /// <summary>
        /// Runs a play test simulation of the saved agent and returns the result.
        /// </summary>
        /// <param name="savedAgent"></param>
        /// <param name="testType"></param>
        /// <param name="record"></param>
        /// <returns></returns>
        public PlaytestResult RunSimulation(SavedAgent savedAgent, TestType testType, bool record)
        {
            int               action                    = 0;
            int               movesTotal                = 0;
            int               currentScore              = 0;
            int               movesSincePoint           = 0;
            int               maxStepsBeforeTerminating = 1000;
            double            averageMovesPerFood       = 0;
            bool              isInBounds                = true;
            PlaytestRecording recorder                  = null;
            TestResult        testResult                = TestResult.Failed;

            NetworkSettings networkSettings = (savedAgent.geneticSettings.FitnessCalculator as SnakeFitnessCalculator).NetworkSettings;
            SnakeSettings   snakeSettings   = (savedAgent.geneticSettings.FitnessCalculator as SnakeFitnessCalculator).SnakeSettings;

            // Setup new snake game and neural network
            NeuralNetwork neuralNetwork = new NeuralNetwork(networkSettings, savedAgent.agent.Chromosome.ToArray());

            double[]  input     = new double[networkSettings.numberOfInputNeurons];
            SnakeGame snakeGame = new SnakeGame(snakeLevel);

            // Make recorder
            if (record)
            {
                recorder = new PlaytestRecording(savedAgent.agent, networkSettings, snakeSettings);
                recorder.TakeSnapShotInitial(snakeGame);
            }

            if (record) // Save round info.
            {
                recorder.TakeSnapShotRound(snakeGame);
            }

            // Check within bounds.
            if (testType == TestType.WithinBounds)
            {
                if (snakeGame.Grid.PointWithinGrid(snakeGame.Snake.Head.Point))
                {
                    testResult = TestResult.Passed;
                }
                else
                {
                    testResult = TestResult.Failed;
                    isInBounds = false;
                }
            }

            if (isInBounds)
            {
                do
                {
                    input  = ConvertGridToInput(snakeGame.Grid, snakeGame.Snake, snakeGame.Food);
                    action = neuralNetwork.CalculateOutput(input);
                    snakeGame.UpdateDirection(action);

                    // Check if got point
                    if (snakeGame.Score != currentScore)
                    {
                        movesSincePoint = 0;
                        currentScore    = snakeGame.Score;
                    }
                    else
                    {
                        movesSincePoint++;
                    }
                    movesTotal++;

                    if (record) // Save round info.
                    {
                        recorder.TakeSnapShotRound(snakeGame);
                    }
                    // Test within bounds.
                    if (testType == TestType.WithinBounds)
                    {
                        if (snakeGame.Grid.PointWithinGrid(snakeGame.Snake.Head.Point))
                        {
                            testResult = TestResult.Passed;
                        }
                        else
                        {
                            testResult = TestResult.Failed;
                            isInBounds = false;
                        }
                    }
                } while(snakeGame.Snake.IsAlive && movesSincePoint < maxStepsBeforeTerminating && isInBounds);
            }

            // Check if snake completed game.
            if (testType == TestType.CanComplete)
            {
                if (snakeGame.MaxScore != snakeGame.Score)
                {
                    testResult = TestResult.Failed;
                }
                else
                {
                    testResult = TestResult.Passed;
                }
            }

            // Get avg. moves per food.
            if (snakeGame.FoodEaten != 0)
            {
                averageMovesPerFood = movesTotal / (double)snakeGame.FoodEaten;
            }
            EndTestInfo endTestInfo = new EndTestInfo(snakeGame, movesTotal);

            if (record)
            {
                recorder.TakeSnapShotEndTest(endTestInfo);
            }

            PlaytestResult playtestResult = new PlaytestResult(testResult, recorder);

            return(playtestResult);
        }