コード例 #1
0
        /// <summary>
        /// runs the main brain a few times after mutating it and returns its average score
        /// </summary>
        /// <param name="mutateMagnitude">The magnitude by which mutations can happen</param>
        /// <param name="iterations">The number of times the snake plays the game before returning the average score.</param>
        /// <param name="mutateNRR">Determines how much mutation magnitude distrubution conforms to a normal distribution.</param>
        /// <returns>the average score</returns>
        private double ModeTrainAI(double mutateMagnitude = .1, int mutateNRR = 4, int iterations = 100, int mutationChance = 5)
        {
            SnakeBrain.Mutate(mutateMagnitude, mutateNRR, mutationChance);
            double averageScore = 0;

            for (int i = 0; i < iterations; i++)
            {
                NewBoard(i);
                while (Board1.Progress1Tick())
                {
                    RunBrain();
                }
                averageScore += CalculateScore();
            }
            return(averageScore / iterations);
        }
コード例 #2
0
        /// <summary>
        /// runs the main brain a few times after mutating it and returns its average score
        /// </summary>
        /// <param name="mutateMagnitude">The magnitude by which mutations can happen</param>
        /// <param name="iterations">The number of times the snake plays the game before returning the average score.</param>
        /// <param name="mutateNRR">Determines how much mutation magnitude distrubution conforms to a normal distribution.</param>
        /// <param name="randomly">Whether or not to use deterministic brain changes</param>
        /// <param name="incrementor">if non-random then this must should increment by 1 each call</param>
        /// <returns>the average score</returns>
        private double ModeTrainAI(double mutateMagnitude = .1, int mutateNRR = 4, int iterations = 100, int nrOfMutations = 2, bool randomly = false, int incrementor = 0)
        {
            if (randomly)
            {
                SnakeBrain.Mutate(mutateMagnitude, mutateNRR, nrOfMutations);
            }
            double averageScore = 0;

            for (int i = 0; i < iterations; i++)
            {
                NewBoard(i);
                while (Board1.Progress1Tick())
                {
                    RunBrain(Board1, SnakeBrain);
                }
                averageScore += CalculateScore(Board1);
            }
            return(averageScore / iterations);
        }
コード例 #3
0
        private void RunBrain()
        {
            double[] tailDistances = new double[4] {
                Board1.WidthHeight - 1,
                Board1.WidthHeight - 1,
                Board1.WidthHeight - 1,
                Board1.WidthHeight - 1
            };
            for (int i = 0; i < Board1.TailLength; i++)
            {
                if (Board1.TailY[i] == Board1.SnakeHeadY)
                {
                    tailDistances[0] = Math.Min(tailDistances[0], Board1.DistanceLeft(Board1.SnakeHeadX, Board1.TailX[i]));
                    tailDistances[2] = Math.Min(tailDistances[2], Board1.DistanceRight(Board1.SnakeHeadX, Board1.TailX[i]));
                }
                if (Board1.TailX[i] == Board1.SnakeHeadX)
                {
                    tailDistances[1] = Math.Min(tailDistances[1], Board1.DistanceUp(Board1.SnakeHeadY, Board1.TailY[i]));
                    tailDistances[3] = Math.Min(tailDistances[3], Board1.DistanceDown(Board1.SnakeHeadY, Board1.TailY[i]));
                }
            }
            int[] foodDistances = new int[4] {
                Board1.DistanceLeft(Board1.SnakeHeadX, Board1.FoodX),
                Board1.DistanceUp(Board1.SnakeHeadY, Board1.FoodY),
                Board1.DistanceRight(Board1.SnakeHeadX, Board1.FoodX),
                Board1.DistanceDown(Board1.SnakeHeadY, Board1.FoodY)
            };



            int k = (int)Board1.SnakeDirection;

            int horizontalDistance;
            int verticalDistance;

            if (foodDistances[k] > foodDistances[(k + 2) % 4])
            {
                verticalDistance = -foodDistances[(k + 2) % 4];
            }
            else
            {
                verticalDistance = foodDistances[k];
            }
            if (foodDistances[(k + 1) % 4] > foodDistances[(k + 3) % 4])
            {
                horizontalDistance = -foodDistances[(k + 3) % 4];
            }
            else
            {
                horizontalDistance = foodDistances[(k + 1) % 4];
            }


            double[] perceptronsValues = new double[4]
            {
                //a bearing value to the next food piece relative to the current snake heading.
                //vertical goes into the x argument to make sure that a dead ahead food direction leads to a value of 0
                Math.Atan2(horizontalDistance, verticalDistance),
                //whether or not a tail piece is ahead of, to the left of or to the right of the snake head
                tailDistances[k],
                tailDistances[(k + 3) % 4],
                tailDistances[(k + 1) % 4],
            };

            //calculate what the brain "thinks" that it should do
            double[] brainThoughts = SnakeBrain.InputToOutput(perceptronsValues);

            double maxvalue = brainThoughts.Max();

            for (int i = 0; i < 3; i++)
            {
                if (maxvalue == brainThoughts[i])
                {
                    if (i == 1)
                    {
                        Board1.ChangeDirection(Board.Direction.right);
                    }
                    else if (i == 2)
                    {
                        Board1.ChangeDirection(Board.Direction.left);
                    }
                }
            }
        }