public Dictionary <DeckMutationStrategy, double> MutationCounts; // how many times this particular mutation strategy should be applied to this player public TournamentPlayer Mutate(Tournament tournament) { // determine approximately how many mutations we want to do double previousNumMutations = 0; foreach (KeyValuePair <DeckMutationStrategy, double> entry in this.MutationCounts) { previousNumMutations += entry.Value; } // Choose an exponential random number of mutations to actually do, with mean equal to numMutations double randFraction = this.Random.NextDouble(); double desiredNumMutations = Math.Exp(randFraction * 2 * Math.Log(previousNumMutations)); if (desiredNumMutations < 2) { desiredNumMutations = 2; } // keep track of which mutations are done this time Dictionary <DeckMutationStrategy, double> currentMutationCounts = new Dictionary <DeckMutationStrategy, double>(this.MutationCounts.Count); foreach (DeckMutationStrategy strategy in this.MutationCounts.Keys) { currentMutationCounts[strategy] = 0; } TournamentPlayer player = this.Clone(); // Now determine which mutations to do double numMutations; for (numMutations = 0; numMutations < desiredNumMutations; numMutations++) { // Choose a mutation strategy double randomNumber = this.Random.NextDouble() * previousNumMutations; foreach (KeyValuePair <DeckMutationStrategy, double> entry in this.MutationCounts) { if (randomNumber <= entry.Value) { // mutate using this strategy DeckMutationStrategy strategy = entry.Key; player = strategy.DesignNewDeck(player, tournament); currentMutationCounts[strategy]++; break; } else { // keep looking randomNumber -= entry.Value; } } } // update the mutation counts of the new player so that it knows how it got to its state and it can continue to mutate at a similar rate Dictionary <DeckMutationStrategy, double> childMutations = new Dictionary <DeckMutationStrategy, double>(); foreach (DeckMutationStrategy strategy in currentMutationCounts.Keys) { // add a little to make sure no strategy gets completely forgotten, and then normalize the counts again childMutations[strategy] = (currentMutationCounts[strategy] + 1) * (numMutations / (numMutations + currentMutationCounts.Count())); } player.MutationCounts = childMutations; return(player); }
public Game NewGame(TournamentPlayer player1, TournamentPlayer player2) { List <TournamentPlayer> players = new List <TournamentPlayer>(); players.Add(player1); players.Add(player2); foreach (ReadableCard card in player1.MainDeck) { if (player2.MainDeck.Contains(card)) { Console.WriteLine("Error: two players have the same instance of a card in their deck"); } } return(this.NewGame(players)); }
public TournamentPlayer DesignNewDeck(TournamentPlayer player, Tournament Tournament) { TournamentPlayer newPlayer = player.Clone(); // Choose a new random card IList <ReadableCard> legalCards = player.Referee.LegalCards; WritableCard newCard = legalCards[player.Random.Next(legalCards.Count)].Clone((WritableCard)null); newCard.ID = IDFactory.NewID(); // replace an existing card with the new card newPlayer.RemoveCard(newPlayer.MainDeck.First()); newPlayer.AddCard(newCard); return(newPlayer); }
public TournamentPlayer Clone() { TournamentPlayer clone = new TournamentPlayer(); clone.Random = this.Random; clone.Referee = this.Referee; clone.Strategy = this.Strategy; clone.mainDeck = new LinkedList <ReadableCard>(); foreach (ReadableCard card in this.mainDeck) { clone.mainDeck.AddLast(card.Clone((WritableCard)null)); } clone.NumWins = this.NumWins; clone.NumLosses = this.NumLosses; return(clone); }
public Writable_GamePlayer(TournamentPlayer source) { this.Initialize(); // copy the deck and keep a pointer to the strategy LinkedList <ReadableCard> cards = new LinkedList <ReadableCard>(); foreach (ReadableCard readableCard in source.MainDeck) { WritableCard writableCard = readableCard.Clone((WritableCard)null); writableCard.ControllerID = this.GetID((Readable_GamePlayer)null); cards.AddLast(writableCard); } this.Deck = WritableQueue <ReadableCard> .ShuffledQueue(cards); this.sourcePlayer = source; }
public void Run() { while (true) { TournamentPlayer bestPlayer = this.Players[0]; // play a bunch of games, giving lower-ranked players the opportunity to rise to the top for (int i = this.Players.Count - 2; i >= 0; i--) { if (this.random.Next(2) == 0) { this.PlayGame(i, i + 1); } else { this.PlayGame(i + 1, i); } } // If the best players has changed, then print the current best player and continue if (this.Players[0] != bestPlayer) { Console.WriteLine("Best deck:"); foreach (ReadableCard card in this.Players[0].SortedDeck) { Console.WriteLine(card.Name); } bestPlayer = this.Players[0]; } Console.WriteLine("Win ratio: " + bestPlayer.NumWins + "/" + (bestPlayer.NumWins + bestPlayer.NumLosses)); // Choose a player with rank better than median, make a mutated version, insert the mutated version at the median, and remove the worst-ranked player int middleIndex = this.Players.Count / 2; int indexToClone = this.random.Next(middleIndex); TournamentPlayer newPlayer = this.Players[indexToClone].Mutate(this); this.Players.Insert(middleIndex, newPlayer); this.Players.RemoveAt(this.Players.Count - 1); } }
public void PlayGame(int player1Index, int player2Index) { List <TournamentPlayer> players = new List <TournamentPlayer>(); TournamentPlayer player1 = this.Players[player1Index]; TournamentPlayer player2 = this.Players[player2Index]; players.Add(this.Players[player1Index]); players.Add(this.Players[player2Index]); Game game = this.referee.NewGame(players); if (player1Index == 0 || player2Index == 0) { game.ShouldPrint = true; } game.Play(); if (game.GetWinner() != null) { TournamentPlayer winner = game.GetWinner().SourcePlayer; int winnerIndex, loserIndex; TournamentPlayer loser = null; if (winner == player1) { winnerIndex = player1Index; loserIndex = player2Index; } else { if (winner == player2) { winnerIndex = player2Index; loserIndex = player1Index; } else { return; } } loser = this.Players[loserIndex]; winner.NumWins++; loser.NumLosses++; if (winnerIndex > 0) { // improve winner's rank by 1 this.Players.RemoveAt(winnerIndex); winnerIndex--; this.Players.Insert(winnerIndex, winner); if (winnerIndex == loserIndex) { return; } } // worsen losers's rank by 1 if (loserIndex < players.Count - 1) { this.Players.RemoveAt(loserIndex); loserIndex++; this.Players.Insert(loserIndex, loser); } } }