/// <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); }
/// <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); }
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); } } } }