/// <summary> /// The training will be started from randomly generated AIs /// </summary> /// <param name="gc"></param> public Simulation(Models.GameConfiguration gc) { this.gc = gc; ais = new AiPlayed[gc.NumberOfAIs]; for (int i = 0; i < ais.Length; i++) { ais[i] = new AiPlayed(new Brain(gc.NeuronCount, gc.LayerCount, gc.MemoryNeuronCount), ais.Length); } }
/// <summary> /// The training will be based on the given <paramref name="baseBrain"/>, with the first AI being the one given, and the rest being its children /// </summary> /// <param name="baseBrain"></param> /// <param name="gc"></param> public Simulation(Brain baseBrain, Models.GameConfiguration gc) { this.gc = gc; ais = new AiPlayed[gc.NumberOfAIs]; ais[0] = new AiPlayed(baseBrain, ais.Length); for (int i = 1; i < ais.Length; i++) { ais[i] = new AiPlayed(baseBrain.GenerateChild(gc.BaseEvolutionFactor), ais.Length); } }
/// <summary> /// Processes a single AI's fights. /// </summary> /// <param name="self">The AI to process</param> private void process(int self) { Random random = new Random(self); //Randomizing the order of the opponents avoids too much interblocking int[] opponents = Enumerable.Range(1, ais.Length - 1).OrderBy(x => random.Next()).ToArray(); foreach (int opponent in opponents) { int other = (self + opponent) % ais.Length; AiPlayed selfAi = ais[self]; AiPlayed otherAi = ais[other]; //To avoid deadlocks, we need to determine the order depending on the indexes if (self < other) { selfAi.Semaphore.WaitOne(); otherAi.Semaphore.WaitOne(); } else { otherAi.Semaphore.WaitOne(); selfAi.Semaphore.WaitOne(); } if (selfAi.GamesPlayed[other]) { //We already played against this opponent, go to the next one otherAi.Semaphore.Release(); selfAi.Semaphore.Release(); continue; } fight(selfAi, otherAi); selfAi.GamesPlayed[other] = true; otherAi.GamesPlayed[self] = true; otherAi.Semaphore.Release(); selfAi.Semaphore.Release(); } lock (doneCountLock) { doneCount++; Monitor.Pulse(doneCountLock); } }
/// <summary> /// Processes a fight between the two players /// </summary> /// <param name="player1"></param> /// <param name="player2"></param> private void fight(AiPlayed player1, AiPlayed player2) { Game game = new Game(gc, player1.Brain, player2.Brain); for (int i = 0; i < gc.GameLength; i++) { game.Update(); } int finalScore = player1.Brain.Score - player2.Brain.Score; int match = finalScore == 0 ? 0 : finalScore > 0 ? 1 : -1; player1.NetScore += finalScore - player2.Brain.Score; // Penalty for letting the other score player2.NetScore -= finalScore + player1.Brain.Score; // Penalty for letting the other score player1.NetMatches += match; player2.NetMatches -= match; player1.Brain.Score = 0; player2.Brain.Score = 0; }