public GameEffect ChooseBestAction(GameChoice choice, Game game) { game = game.Clone(); // Inform the game and its descendents that it is a hypothetical game, so all players use the strategy of the player doing the imagining Readable_GamePlayer chooser = game.Get_ReadableSnapshot(choice.ControllerID); game.Strategy = game.GetStrategy(chooser); IEnumerable <GameEffect> effects = choice.Options; // create the base game Analyzed_GameState rootState = new Analyzed_GameState(game, null, null, this.GameEvaluator.EstimateWinProbabilities(game)); rootState.ChoosingPlayerID = choice.ControllerID; // Put the first set of choices onto the starting gameState this.PutGameOptions(rootState, choice); // loop until we run out of time while (rootState.NumDescendents < this.NumTimeSteps) { // Find the current best path and explore it for one more time unit this.ProcessOnce(rootState); double winProbability = rootState.WinProbabilities[choice.ControllerID]; if (winProbability == 0 || winProbability == 1) { break; } } if (this.ShouldPrint) { Console.WriteLine("Plan for " + chooser.ToString()); rootState.printBestPath(); } return(rootState.FavoriteChild.SourceEffect); }
public override void Process(Game game) { foreach (GameEffect option in this.options) { option.ControllerID = this.ControllerID; } GameChoice choice = new GameChoice(this.options, this.Get_ControllerID()); game.AddChoice(choice); }
public GameChoice Get_NextChoice() { if (this.pendingEffects.Count > 0) { // a previous effect still requires a player to make a choice, so that must be done before moving on to normal options (like playing more cards, attacking, or ending the turn) GameChoice choice = this.pendingEffects.First(); this.pendingEffects.RemoveFirst(); return(choice); } // There aren't any effects still requiring user input, so now the active player can choose on of the usual choices (playing a card, attacking, ending the turn or whatever) Readable_GamePlayer activePlayer = this.ActivePlayer; return(new GameChoice(this.Referee.Get_AvailableGameActions(this, activePlayer), activePlayer.GetID((Readable_GamePlayer)null))); }
public void AddChoice(GameChoice choice) { if (choice.Options.Count() == 1) { // if there's only one option, we might as well resolve it now rather than queuing up a decision to ask the player about later GameEffect effect = choice.Options.First(); effect.Process(this); } else { // If an effect creates a choice, then that choice is processed before any previous choices (like attacking or ending the turn) this.pendingEffects.AddFirst(choice); } }
public void PlayOneAction() { GameChoice choice = this.Get_NextChoice(); GameStrategy strategy = this.GetStrategy(this.Get_ReadableSnapshot(choice.ControllerID)); GameEffect effect = strategy.ChooseBestAction(choice, this); if (!(choice.Options.Contains(effect))) { Console.WriteLine("GameStrategy " + strategy + " made an invalid choice: " + effect); effect = strategy.ChooseBestAction(choice, this); } if (this.ShouldPrint) { Console.WriteLine(effect.ToString(this)); } effect.Process(this); }
private void PutGameOptions(Analyzed_GameState gameState, GameChoice choice) { if (choice.Options.Count() < 1) { Console.WriteLine("Error: a GameChoice must always have options"); } gameState.ChoosingPlayerID = choice.ControllerID; foreach (GameEffect effect in choice.Options) { // quickly do a lazy clone of the game (we just use pointers to the other game until anything actually changes) Game newGame = gameState.Game.Clone(); // make a new effect and execute it GameEffect clonedEffect = effect.Clone((GameEffect)null); clonedEffect.Process(newGame); new Analyzed_GameState(newGame, gameState, effect, this.GameEvaluator.EstimateWinProbabilities(newGame)); } }