private Node TreePolicy(Node node) { var state = node.State; while (state?.State != State.COMPLETE && node.TurnDepth < TurnDepth) { if (state == null) { return(node); } if (FullyExpanded(node)) { var selectionStrategy = SelectionStrategies.GetSelectionStrategy(Selection); var stateRateStrategy = StateRateStrategies.GetStateRateStrategy(StateRate); node = ChildSelection.SelectBestChild(state, node, EXPLORATION_CONSTANT, player, selectionStrategy, stateRateStrategy); state = state.Simulate(new List <PlayerTask> { node.Action })[node.Action]; } else { return(Expand(node, state)); } } return(node); }
private float DefaultPolicyHeuristic(Node node) { float result = 0; POGame state = node.State; int currentTurnDepth = node.TurnDepth; while (state.State != State.COMPLETE && (node.Action.PlayerTaskType == PlayerTaskType.END_TURN ? currentTurnDepth < TurnDepth - 1 : currentTurnDepth < TurnDepth)) { Controller currentPlayer = state.CurrentPlayer; List <PlayerTask> actions = currentPlayer.Options(); List <PlayerTask> oldActions = new List <PlayerTask>(actions); bool uncertainity = currentPlayer.Options() .Any(option => option.PlayerTaskType == PlayerTaskType.PLAY_CARD && option.Source.Card.Name == "No Way!"); // end potential infinite loop of 0 cost spells (happend few times with a mage) if (currentPlayer.CardsPlayedThisTurn.Count > 50) { break; } if (uncertainity) { // depending on active player choose one: // 1) simulate player's card draw // 2) simulate opponent's possible actions actions = state.CurrentPlayer.PlayerId == player.PlayerId ? ActionEstimator.DrawSimulation(currentPlayer) : ActionEstimator.ActionEstimaton(state, currentPlayer); } var bestPair = state.Simulate(actions.Any() ? actions : oldActions) .Where(pair => pair.Value != null) .OrderBy(pair => StateRateStrategies.GetStateRateStrategy(StateRateStrategy.Greedy)(pair.Value, currentPlayer)) .Last(); //Console.WriteLine(currentTurnDepth + ", " + bestPair.Key); if (bestPair.Key.PlayerTaskType == PlayerTaskType.END_TURN) { currentTurnDepth++; } state = bestPair.Value; // this should be redundant.. but, you know.. just in case.. if (state == null) { return(0.5f); } } var firstPlayer = state.CurrentPlayer.PlayerId == player.PlayerId ? state.CurrentPlayer : state.CurrentOpponent; result = StateRateStrategies.GetStateRateStrategy(StateRateStrategy.Greedy)(state, firstPlayer); return(result); }
private KeyValuePair <int, float> DefaultPolicy(POGame state, Node node) { KeyValuePair <int, float> result = new KeyValuePair <int, float>(state.CurrentPlayer.PlayerId, 0.5f); while (state.State != State.COMPLETE) { List <PlayerTask> actions = state.CurrentPlayer.Options(); List <PlayerTask> oldActions = new List <PlayerTask>(actions); bool uncertainity = state.CurrentPlayer.Options() .Any(option => option.PlayerTaskType == PlayerTaskType.PLAY_CARD && option.Source.Card.Name == "No Way!"); Controller currentPlayer = state.CurrentPlayer; if (uncertainity) { // player's drawn cards are also unknown -> need to simulate actions = state.CurrentPlayer.PlayerId == player.PlayerId ? ActionEstimator.DrawSimulation(currentPlayer) : ActionEstimator.ActionEstimaton(state, currentPlayer); } var bestPair = state.Simulate(actions.Any() ? actions : oldActions) .Where(pair => pair.Value != null) .OrderBy(pair => StateRateStrategies.GetStateRateStrategy(StateRateStrategy.Greedy)(pair.Value, player)) .Last(); //Console.WriteLine("Choosing: " + bestAction); state = bestPair.Value; // this should be redundant.. but, you know.. just in case.. if (state == null) { return(new KeyValuePair <int, float>(currentPlayer.PlayerId, 0.5f)); } } if (state.CurrentPlayer.PlayState == PlayState.CONCEDED || state.CurrentPlayer.PlayState == PlayState.LOST) { result = new KeyValuePair <int, float>(state.CurrentPlayer.PlayerId, 0); } else if (state.CurrentPlayer.PlayState == PlayState.WON) { result = new KeyValuePair <int, float>(state.CurrentPlayer.PlayerId, 1); } else if (state.CurrentPlayer.PlayState == PlayState.TIED) { result = new KeyValuePair <int, float>(state.CurrentPlayer.PlayerId, 0.5f); } return(result); }
public PlayerTask Search() { List <PlayerTask> options = player.Options(); if (options.Count == 1 && options[0].PlayerTaskType == PlayerTaskType.END_TURN) { return(options.First()); } StopWatch.Start(); var selectionStrategy = SelectionStrategies.GetSelectionStrategy(Selection); var stateRateStrategy = StateRateStrategies.GetStateRateStrategy(StateRate); while (StopWatch.ElapsedMilliseconds < COMPUTATIONAL_BUDGET) { POGame state = InitialState.getCopy(); Node lastNode = TreePolicy(Root); float delta = DefaultPolicyHeuristic(lastNode); Backup(lastNode, delta); } StopWatch.Stop(); return(ChildSelection.SelectBestChild(InitialState, Root, EXPLORATION_CONSTANT, player, selectionStrategy, stateRateStrategy).Action); }
private List <PlayerTask> ActionEstimaton(POGame state, Controller player) { // estimate best action for upcoming game state which depends on probability of opponent's actions // a.k.a. simulate his possibilities (remove incomplete information) and choose most promising //Console.WriteLine("Estimator " + player.PlayerId); var history = player.PlayHistory; List <Card> remainingCards = new List <Card>(DecksDict[deckName]); List <Card> playedCards = history.Select(h => h.SourceCard).ToList(); int removed = 0; HashSet <PlayerTask> subactions = new HashSet <PlayerTask>(); List <PlayerTask> resultActions = new List <PlayerTask>(); //Console.WriteLine(opponent); // removing played cards foreach (Card playedCard in playedCards) { remainingCards.Remove(playedCard); } // removing unknown cards from hand for (int i = 0; i < player.HandZone.Count; i++) { IPlayable handCard = player.HandZone[i]; if (handCard.Card.Name == "No Way!") { player.HandZone.Remove(i); removed++; // performing remove on the iterated object so I need to adjust // the iterator to reflect the object's items count change i--; } else { remainingCards.Remove(handCard.Card); } } //Console.WriteLine(String.Format("Removed {0} unknown cards", removed)); // adding cards to hand for simualtion foreach (Card deckCard in remainingCards) { if (deckCard.Cost <= player.BaseMana) { if (player.HandZone.IsFull) { player.Options() .Where(option => option.PlayerTaskType == PlayerTaskType.PLAY_CARD) .ToList() .ForEach(option => subactions.Add(option)); clearHand(player); } player.HandZone.Add(Entity.FromCard(in player, deckCard)); } else { player.Options() .Where(option => option.PlayerTaskType == PlayerTaskType.PLAY_CARD) .ToList() .ForEach(option => subactions.Add(option)); clearHand(player); break; } } ; // choosing best subactions resultActions.AddRange( subactions .Where(action => action.PlayerTaskType == PlayerTaskType.PLAY_CARD) .OrderBy(action => StateRateStrategies .GetStateRateStrategy(StateRateStrategy.Greedy)(state, player)) .TakeLast(removed) ); // adding other tasks such as attack, end turn, etc.. resultActions.AddRange(player.Options()); // now adding corresponding cards of chosen best tasks to player's hand foreach (PlayerTask task in resultActions) { if (task.PlayerTaskType == PlayerTaskType.PLAY_CARD && task.HasSource && !player.HandZone.IsFull && !player.HandZone.Contains(task.Source)) { player.HandZone.Add(task.Source); } } //resultActions.ForEach(action => Console.WriteLine(action)); //Console.WriteLine(); return(resultActions.Count > 0 ? resultActions : player.Options()); void clearHand(Controller pplayer) { while (pplayer.HandZone.Count() > 0) { pplayer.HandZone.Remove(0); } //Console.WriteLine("Hand cleared: " + pplayer.HandZone.Count()); //printPlayerHand(pplayer); } }