private void OnClickStartPlaytest(object sender, EventArgs e) { try { AgentStorageManager storageManager = new AgentStorageManager(); agent = storageManager.LoadAgentBinary(openAgentTextBox.Text); level = storageManager.LoadObject <SnakeLevel>(openLevelTextBox.Text); level.SnakeSettings.RandomNumberGenerator = new RandomNumberGenerator(); SnakePlayTestSimulator snakePlayTestSimulator = new SnakePlayTestSimulator(level); Playtest playtest = new Playtest(snakePlayTestSimulator, (TestType)playtestTypesList.SelectedIndex); playtestResults = playtest.RunPlaytest(agent, Convert.ToInt32(numberOfSimulations.Value)); failedSimulationsAbsolute.Text = $"Number of failed tests: {playtestResults.NumberOfFailedTests} of {playtestResults.TestResults.Count}"; failedSimulationsPercent.Text = $"Percentage tests failed: {playtestResults.FailedPercentage}%"; resultsChart.Series[0].Points.Clear(); resultsChart.Series[1].Points.Clear(); resultsChart.Series[0].Points.AddXY("Failed", playtestResults.FailedPercentage); resultsChart.Series[1].Points.AddXY("Passed", 100 - playtestResults.FailedPercentage); resultsLayout.Show(); } catch (Exception exception) { MessageBox.Show($"Playtest failed! Error: {exception.Message}"); } }
/// <summary> /// Runs a playtest using the specified agent. /// </summary> /// <param name="savedAgent"></param> /// <param name="simulationCount">The number of playtests</param> /// <returns></returns> public PlaytestResults RunPlaytest(SavedAgent savedAgent, int simulationCount) { List <PlaytestResult> testResults = new List <PlaytestResult>(); ShowProgressBar(); for (int i = 0; i < simulationCount; i++) { testResults.Add(playTestSimulator.RunSimulation(savedAgent, testType, true)); progressBar.Maximum = simulationCount + 1; progressBar.Value = simulationCount + 1; progressBar.Maximum = simulationCount; progressBar.Value = i; progressBar.Refresh(); progressForm.Refresh(); } PlaytestResults playtestResults = new PlaytestResults(testResults); progressForm.Close(); return(playtestResults); }
/// <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); }