public void Evaluate(List<IPlayer> players, Settings settings, bool champions, int games) { ResetScores(players); var seats = CreateSeats(players, settings.BigBlind * settings.StackSize); HandEngine engine = new HandEngine() { AnalyzeHands = true }; for (int i = 0, handsThisTourney = 0; seats.Count > 3 && handsThisTourney < settings.MaxHandsPerTourney; i = (i + 1) % seats.Count, handsThisTourney++) { ulong handNumber; handNumber = GamesPlayed++; HandHistory history = new HandHistory(seats.ToArray(), GamesPlayed, (uint)seats[i].SeatNumber, new double[] { settings.SmallBlind, settings.BigBlind }, 0, BettingStructure.Limit); engine.PlayHand(history); if (champions) LogHand(settings, history, handNumber > 1); RemoveBrokePlayers(settings, seats); } ScorePlayers(seats); }
public void Evaluate(List<IPlayer> players, Settings settings, bool champions, int games) { ResetScores(players); int[] handsPlayed = new int[players.Count]; List<int> availablePlayers = new List<int>(); for (int i = 0; i < players.Count; i++) availablePlayers.Add(i); double startingChips = settings.BigBlind * settings.StackSize; HandEngine engine = new HandEngine() { AnalyzeHands = false }; int handsThisGeneration = 0; while(availablePlayers.Count >= settings.PlayersPerGame) { ulong handNumber = GamesPlayed++; List<int> playerIndices = champions ? CreateShuffledChampionsList(settings) : availablePlayers.RandomSubset(settings.PlayersPerGame, random); var seats = CreateSeats(players, startingChips, playerIndices); HandHistory history = new HandHistory(seats, GamesPlayed, (uint)settings.PlayersPerGame, new double[] { settings.SmallBlind, settings.BigBlind }, 0, BettingStructure.Limit); engine.PlayHand(history); handsThisGeneration++; if (champions) LogHand(settings, history, handNumber > 1); if (handNumber % 100000 == 0) lock(LogLock) Console.WriteLine("Hand: {0}", handNumber); AddScores(startingChips, playerIndices, seats); IncrementHandsPlayedAndRemoveDone(games, handsPlayed, availablePlayers, playerIndices, champions); } //normalize win rates for (int i = 0; i < Scores.Count; i++) { Scores[i] /= (double)handsPlayed[i]; Scores[i] /= settings.BigBlind; if (Scores[i] > 2) Scores[i] = 2; else if (Scores[i] < -5) Scores[i] = -5; } }
static void Main(string[] args) { HandEngine engine = new HandEngine(); Console.WriteLine("Loading cached hands"); List<CachedHand> cachedHands; XmlSerializer ser = new XmlSerializer(typeof(CachedHands)); using (TextReader txt = new StreamReader("test.xml")) cachedHands = ((CachedHands)ser.Deserialize(txt)).Hands; var seats = new Seat[6]; seats[0] = new Seat(1, "AlwaysRaise", 100000, new AlwaysRaisePlayer()); seats[1] = new Seat(2, "AwaysCall", 100000, new AlwaysCallPlayer()); seats[2] = new Seat(3, "AwaysCall2", 100000, new AlwaysCallPlayer()); seats[3] = new Seat(4, "AwaysCall3", 100000, new AlwaysCallPlayer()); seats[4] = new Seat(5, "AwaysCall4", 100000, new AlwaysCallPlayer()); seats[5] = new Seat(6, "AwaysCall5", 100000, new AlwaysCallPlayer()); var blinds = new double[] { 1, 2 }; uint handNumber = 0; double maxDifference = 0; Console.WriteLine("Starting simulation"); DateTime start = DateTime.Now; for (; handNumber < 100; handNumber++) { HandHistory results = new HandHistory(seats, handNumber, handNumber % (uint)seats.Length + 1, blinds, 0, BettingStructure.NoLimit); engine.PlayHand(results, cachedHands[(int)handNumber]); double difference = Math.Abs(seats[0].Chips - seats[1].Chips); if (difference > maxDifference) maxDifference = difference; if (seats[0].Chips == 0 || seats[1].Chips == 0) break; } int time = DateTime.Now.Subtract(start).Milliseconds; Console.WriteLine("Time: {0}", time); Console.WriteLine("Hands: {0}", handNumber); Console.WriteLine("AlwaysRaise Bankroll: {0}", seats[0].Chips); Console.WriteLine("AlwaysCall Bankroll: {0}", seats[1].Chips); Console.WriteLine("Max Difference: {0}", maxDifference); }
public void EvaluatePopulation(Population pop, EvolutionAlgorithm ea) { var count = pop.GenomeList.Count; #region Reset the genomes for (var i = 0; i < count; i++) { pop.GenomeList[i].TotalFitness = EvolutionAlgorithm.MIN_GENOME_FITNESS; pop.GenomeList[i].EvaluationCount = 0; pop.GenomeList[i].Fitness = EvolutionAlgorithm.MIN_GENOME_FITNESS; } #endregion //TODO: Parallelize/Distribute this loop //Ideally we should have a distributed method which returns an array of //doubles to add to the genome fitnesses of each individual. for (var i = 0; i < count; i++) { Console.WriteLine("Individual #{0}", i + 1); var g = pop.GenomeList[i]; var network = g.Decode(ActivationFunction); if (network == null) { // Future genomes may not decode - handle the possibility. g.Fitness = EvolutionAlgorithm.MIN_GENOME_FITNESS; g.TotalFitness = g.Fitness; g.EvaluationCount = 1; continue; } HandEngine engine = new HandEngine(); //Run multiple hands per individual for (var curGame = 0; curGame < GamesPerEvaluation; curGame++) { #region Setup the players for this game var field = new List<Seat>(); var stacks = GetStacks(PlayersPerGame); var networks = new int[PlayersPerGame]; networks[0] = i; IPlayer hero = null;//new NeuralNetworkPlayer(InputGenerator, OutputInterpreter, // network, Rand); field.Add(new Seat(1, "Net_" + i, stacks[0], hero)); for (var curPlayer = 1; curPlayer < PlayersPerGame; curPlayer++) { INetwork nextNetwork = null; var next = 0; while (nextNetwork == null) { next = Rand.Next(0, count); nextNetwork = pop.GenomeList[next].Decode(ActivationFunction); } networks[curPlayer] = next; //"NeuralNet" + next, stacks[curPlayer], IPlayer villain = null;// new NeuralNetworkPlayer(InputGenerator, // OutputInterpreter, nextNetwork, Rand); field.Add(new Seat(curPlayer + 1, "Net" + next + "_Seat+ " + (curPlayer+1), stacks[curPlayer], villain)); } #endregion //Have the players play a single hand. HandHistory history = new HandHistory(field.ToArray(), (ulong)curGame+1, (uint)(curGame % PlayersPerGame + 1), new double[] { 1, 2 }, 0, BettingType); CachedHand hand = CachedHands[Rand.Next(CachedHands.Count)]; engine.PlayHand(history); #region Add the results to the players' fitness scores //We'll use the profit as the fitness function. //Alternatively, we could in the future experiment with using profit //as a percentage of the original stacks. Or we could use the square //of the profit (multiplying by -1 if the player lost money). for (var curResult = 0; curResult < PlayersPerGame; curResult++) { var curGenome = pop.GenomeList[networks[curResult]]; curGenome.TotalFitness += field[curResult].Chips - stacks[curResult]; curGenome.EvaluationCount++; } #endregion if (GamesPlayed % 10000 == 0) using (TextWriter writer = new StreamWriter("game_" + GamesPlayed + ".txt")) writer.WriteLine(history.ToString()); //increment the game counter GamesPlayed++; } } //Normalize the fitness scores to use the win-rate for (var i = 0; i < count; i++) { pop.GenomeList[i].Fitness = Math.Max(pop.GenomeList[i].Fitness, EvolutionAlgorithm.MIN_GENOME_FITNESS); pop.GenomeList[i].TotalFitness = Math.Max(pop.GenomeList[i].Fitness, EvolutionAlgorithm.MIN_GENOME_FITNESS); } }