private PlayerTask PlanNextTurn(POGame.POGame poGame) { var options = poGame.CurrentPlayer.Options(); if (options.Count == 1) { return(options[0]); } else { var minionAttacks = new List <PlayerTask>(); var faceAttacks = new List <PlayerTask>(); var heroAttacks = new List <PlayerTask>(); PlayerTask heroFace = null; var cards = new List <PlayerTask>(); int ourHealth = poGame.CurrentPlayer.Hero.Health + poGame.CurrentPlayer.Hero.Armor; int hisHealth = poGame.CurrentOpponent.Hero.Health + poGame.CurrentOpponent.Hero.Armor; int totalFaceDamage = 0; int totalIncomingFaceDamage = 0; // sort the moves foreach (PlayerTask task in options) { if (task.PlayerTaskType == PlayerTaskType.MINION_ATTACK) { if (task.Target == poGame.CurrentOpponent.Hero) { faceAttacks.Add(task); if (task.Source is Minion) { totalFaceDamage += ((Minion)task.Source).AttackDamage; } } else { minionAttacks.Add(task); } } else if (task.PlayerTaskType == PlayerTaskType.PLAY_CARD || task.PlayerTaskType == PlayerTaskType.HERO_POWER) { cards.Add(task); } else if (task.PlayerTaskType == PlayerTaskType.HERO_ATTACK) { heroAttacks.Add(task); if (task.Target == poGame.CurrentOpponent.Hero) { totalFaceDamage += poGame.CurrentPlayer.Hero.AttackDamage; heroFace = task; } } } foreach (var card in poGame.CurrentOpponent.BoardZone) { totalIncomingFaceDamage += card.AttackDamage * (card.HasWindfury ? 2 : 1); } // section card play var cardToPlay = BestCard(cards, poGame); if (cardToPlay != null) { return(cardToPlay); } // section minion attacks else if (faceAttacks.Count > 0 || minionAttacks.Count > 0) { if (faceAttacks.Count > 0 && (totalFaceDamage > totalIncomingFaceDamage && ourHealth > hisHealth || totalFaceDamage >= hisHealth)) { return(faceAttacks[0]); } else if (minionAttacks.Count > 0 && totalIncomingFaceDamage > ourHealth) { return(BestBoardCleaner(minionAttacks)); } else if (faceAttacks.Count > 0) { return(faceAttacks[0]); } else if (minionAttacks.Count > 0) { return(BestBoardCleaner(minionAttacks)); } } // section hero attacks else if (heroAttacks.Count > 0) { if (heroFace != null && totalFaceDamage >= hisHealth) { return(heroFace); } else if (ourHealth > 15) { PlayerTask best = null; var bestScore = 0; foreach (var attack in heroAttacks.Except(new PlayerTask[] { heroFace })) { var target = (Minion)attack.Target; var currentScore = (target.HasDivineShield || target.Health > poGame.CurrentPlayer.Hero.AttackDamage) ? 0 : target.AttackDamage; if (currentScore > bestScore) { best = attack; bestScore = currentScore; } } if (best != null && ourHealth - bestScore > 10) { return(best); } } else if (heroFace != null) { return(heroFace); } } } return(options[0]); }
/// <summary> /// TODO: API /// </summary> /// <param name="oppGame"></param> /// <param name="opponent">the controller of the opponent</param> /// <param name="predicitionMap">the map with all predictions</param> /// <param name="newSimulations"></param> /// <returns></returns> private double simulateOpponentWithPrediction(double lowerTimeBound, double timePerLeaf, POGame.POGame oppGame, Controller opponent, List <Prediction> predicitionMap, ref Dictionary <POGame.POGame, List <MCTSNode> > newSimulations) { double predictionScore = 0; if (predicitionMap?.Any() ?? false) { int denominator = predicitionMap.Count; var scorings = predicitionMap.GroupBy(p => p.Deck.Scoring) .Select(c => new MCTSNode.ScoreExt(((double)c.Count() / denominator), c.Key)) .OrderByDescending(s => s.Value).ToList(); // the simulation time for one prediction double timePerPrediction = timePerLeaf / predicitionMap.Count; // use prediction for each game for (int i = 0; i < predicitionMap.Count; i++) { Prediction prediction = predicitionMap[i]; var setasideZone = opponent.ControlledZones[Zone.SETASIDE] as SetasideZone; setasideZone = new SetasideZone(opponent); // create deck zone List <Card> deckCards = prediction.Deck.Cards; var deckZone = opponent.ControlledZones[Zone.DECK] as DeckZone; deckZone = new DeckZone(opponent); createZone(opponent, deckCards, deckZone, ref setasideZone); deckZone.Shuffle(); // create hand zone List <Card> handCards = prediction.Hand.Cards; var handZone = opponent.ControlledZones[Zone.HAND] as HandZone; handZone = new HandZone(opponent); createZone(opponent, handCards, handZone, ref setasideZone); var oppLeafNodes = new List <MCTSNode>(); IScore oppStrategy = prediction.Deck.Scoring; // forward game POGame.POGame forwardGame = oppGame.getCopy(); // upper time bound for simulation the opponent using the current prediction double oppSimulationTime = lowerTimeBound + (i + 1) * timePerPrediction / 2; // simulate opponent's moves while (forwardGame != null && forwardGame.State == State.RUNNING && forwardGame.CurrentPlayer.Id == opponent.Id) { // simulate var oppRoot = new MCTSNode(opponent.Id, scorings, forwardGame, null, null); MCTSNode bestOppNode = simulate(oppSimulationTime, oppRoot, ref oppLeafNodes); // get solution List <PlayerTask> solutions = bestOppNode.GetSolution(); for (int j = 0; j < solutions.Count && (forwardGame != null); j++) { PlayerTask oppTask = solutions[j]; Dictionary <PlayerTask, POGame.POGame> dir = forwardGame.Simulate(new List <PlayerTask> { oppTask }); forwardGame = dir[oppTask]; if (forwardGame != null && forwardGame.CurrentPlayer.Choice != null) { break; } } } // upper time bound for simulation the player using the forwarded game double simulationTime = oppSimulationTime + timePerPrediction / 2; double score = 0; var leafs = new List <MCTSNode>(); // simulate player using forwarded opponent game while (forwardGame != null && forwardGame.State == State.RUNNING && forwardGame.CurrentPlayer.Id == _playerId) { // simulate var root = new MCTSNode(_playerId, new List <MCTSNode.ScoreExt> { new MCTSNode.ScoreExt(1.0, _scoring) }, forwardGame, null, null); MCTSNode bestNode = simulate(simulationTime, root, ref leafs); // get solution List <PlayerTask> solutions = bestNode.GetSolution(); for (int j = 0; j < solutions.Count && (forwardGame != null); j++) { PlayerTask task = solutions[j]; Dictionary <PlayerTask, POGame.POGame> dir = forwardGame.Simulate(new List <PlayerTask> { task }); forwardGame = dir[task]; if (forwardGame != null && forwardGame.CurrentPlayer.Choice != null) { break; } } // TODO: maybe penalty forwardGame == null score = bestNode.TotalScore; } predictionScore += score; if (forwardGame != null) { newSimulations.Add(forwardGame, leafs); } } } return(predictionScore); }
public Node MonteCarloSearch(Node startNode, long startMillisecond, out LinkedList <int> optionList, int step) { Node currentNode = startNode; optionList = new LinkedList <int>(); int nmcsearch = step; while (currentNode.currentPOGame.CurrentPlayer.Id == startNode.currentPOGame.CurrentPlayer.Id && DateTimeOffset.Now.ToUnixTimeMilliseconds() - startMillisecond < this.oneOptionCalculateTime && nmcsearch < mcSearchDepth) { // random select a option List <PlayerTask> optionsList = currentNode.currentPOGame.CurrentPlayer.Options(); int nCurrentPlayerOptions = optionsList.Count(); int rndOptionNo = rnd.Next(nCurrentPlayerOptions); PlayerTask rndOption = optionsList[rndOptionNo]; //Debug.Assert(pogameAfterBestMove != null); Node tmpNode = currentNode.GetChild(rndOptionNo); while (nCurrentPlayerOptions > 1 && tmpNode != null && rndOption.PlayerTaskType == PlayerTaskType.END_TURN) { rndOptionNo = rnd.Next(nCurrentPlayerOptions); rndOption = optionsList[rndOptionNo]; //Debug.Assert(pogameAfterBestMove != null); tmpNode = currentNode.GetChild(rndOptionNo); } // save rndoptionNo which is Node j value optionList.AddLast(rndOptionNo); // if j child is existed if (tmpNode == null) { // simulate the option LinkedList <PlayerTask> options = new LinkedList <PlayerTask>(); options.AddLast(rndOption); Dictionary <PlayerTask, POGame.POGame> dict = currentNode.currentPOGame.Simulate(options.ToList <PlayerTask>()); POGame.POGame simulatedPOGame = null; dict.TryGetValue(rndOption, out simulatedPOGame); // some time simulate option returned POGame is null if (simulatedPOGame != null) { currentNode = currentNode.AddChild(currentNode, rndOption, rndOptionNo, simulatedPOGame); } else { break; } } // if not existed else { currentNode = tmpNode; } nmcsearch++; } return(currentNode); }
private List <Tuple <List <PlayerTask>, POGame.POGame> > DepthCardSearch(List <PlayerTask> cards, POGame.POGame poGame) { var result = new List <Tuple <List <PlayerTask>, POGame.POGame> >(); result.Add(Tuple.Create(new List <PlayerTask>(), poGame)); if (TurnStopwatch.Elapsed.TotalSeconds > 70) { var simulation = poGame.Simulate(cards) .Where(it => it.Value != null && Comp.Compare(it.Value, poGame) > 0); foreach (var(card, nextState) in simulation) { var nextDive = DepthCardSearch(nextState.Cards(), nextState); for (int i = 0; i < nextDive.Count; i++) { nextDive[i].Item1.Insert(0, card); } var best = nextDive.Where(it => it.Item2 != null).MaxElement(Comp, (it => it.Item2)); result.Add(best); } } return(result); }
public PlayerTask GetMoveRandom(POGame.POGame poGame) { List <PlayerTask> options = poGame.CurrentPlayer.Options(); return(options[Rnd.Next(options.Count)]); }
public static PlayerTask GetBestAction(POGame.POGame game, double seconds) { DateTime start = DateTime.Now; TaskNode root = new TaskNode(null, null, game.getCopy()); int i = 0; while (true) { if (TimeUp(start, seconds - 0.1)) { break; } try { TaskNode node = root.SelectNode(); if (TimeUp(start, seconds)) { break; } node = node.Expand(); if (TimeUp(start, seconds)) { break; } int r = node.SimulateGames(5); if (TimeUp(start, seconds)) { break; } node.Backpropagate(r); } catch (Exception e) { //Debug.WriteLine(e.Message); //Debug.WriteLine(e.StackTrace); } ++i; } TaskNode best = null; //Console.WriteLine($"Iterations: {i}, Time: " + (DateTime.Now-start).TotalMilliseconds + "ms"); foreach (TaskNode child in root.Children) { //Console.WriteLine("visits: " + child.TotNumVisits); //Console.WriteLine("wins: " + child.Wins); if (best == null || child.TotNumVisits > best.TotNumVisits || (child.TotNumVisits == best.TotNumVisits && child.Wins > best.Wins)) { best = child; } } //Console.WriteLine("best visits: " + best.TotNumVisits); //Console.WriteLine("best wins: " + best.Wins); if (best == null) { //Debug.WriteLine("best == null"); return(game.CurrentPlayer.Options()[0]); } //Console.WriteLine("best wins: " + best.Wins + " best visits: " + best.TotNumVisits); return(best.Action); }
public static int simulation_num = 5; //模擬次數,預設5 /* * public static PlayerTask GetBestAction_iteration(POGame.POGame game, int iterations) * { * TaskNode root = new TaskNode(null, null, game.getCopy()); * * for (int i = 0; i < iterations; ++i) * { * try * { * TaskNode node = root.SelectNode(); * node = node.Expand(); * int r = node.SimulateGames(simulation_num); * node.Backpropagate(r); * } * catch (Exception e) * { * Debug.WriteLine(e.Message); * Debug.WriteLine(e.StackTrace); * } * } * * TaskNode best = null; * * foreach (TaskNode child in root.Children) * { * Console.WriteLine("visits: " + child.TotNumVisits); * Console.WriteLine("wins: " + child.Wins); * * if (best == null || child.TotNumVisits > best.TotNumVisits) * { * best = child; * } * } * * //Console.WriteLine("best visits: " + best.TotNumVisits); * //Console.WriteLine("best wins: " + best.Wins); * * return best.Action; * } */ public static PlayerTask GetBestAction_second(POGame.POGame game, double seconds) { DateTime start = DateTime.Now; TaskNode root = new TaskNode(null, null, game.getCopy()); int i = 0; while (true) { if (TimeUp(start, seconds - 0.1)) { break; } //Board_Analysis(game);//場面分析函式 Controller my = game.CurrentPlayer; Controller op = game.CurrentOpponent; //分配數值 num_my_board = my.BoardZone.Count; num_op_board = op.BoardZone.Count; num_my_hand = my.HandZone.Count; num_op_hand = op.HandZone.Count; num_my_hero = my.Hero.Health; num_op_hero = op.Hero.Health; num_my_deck = my.DeckZone.Count; num_op_deck = op.DeckZone.Count; num_remaining_mana = my.RemainingMana; TreeScore.treescore.tree_score.tree_node = SabberStoneCoreAi.src.Program.main.node_string; c = Math.Round(TreeScore.treescore.tree_score.Node_Evaluation(num_my_board, num_op_board, num_my_hand, num_op_hand, num_my_hero, num_op_hero, num_my_deck, num_op_deck, num_remaining_mana), 2, MidpointRounding.AwayFromZero); //Console.WriteLine(num_my_board+" "+ num_op_board + " " + num_my_hand + " " + num_op_hand + " " + // num_my_hero + " " + num_op_hero + " " + num_my_deck + " " + num_op_deck + " " + num_remaining_mana); if (c < 0) { c = 0; } //Console.WriteLine("c=" + c); //simulation_num = (int) Math.Round(TreeScore.treescore.tree_score.Node_Evaluation(num_my_board, num_op_board, num_my_hand, num_op_hand, // num_my_hero, num_op_hero, num_my_deck, num_op_deck), 0, MidpointRounding.AwayFromZero); //if (simulation_num < 0) //{ // simulation_num = 1; //} //Console.WriteLine("模擬次數為:" + simulation_num); try { TaskNode node = root.SelectNode(); if (TimeUp(start, seconds)) { break; } node = node.Expand(); if (TimeUp(start, seconds)) { break; } int r = node.SimulateGames(simulation_num); //預設5 if (TimeUp(start, seconds)) { break; } node.Backpropagate(r); } catch (Exception e) { //Debug.WriteLine(e.Message); //Debug.WriteLine(e.StackTrace); } ++i; } TaskNode best = null; //Console.WriteLine($"Iterations: {i}, Time: " + (DateTime.Now-start).TotalMilliseconds + "ms"); foreach (TaskNode child in root.Children) { //Console.WriteLine("visits: " + child.TotNumVisits);//刪除註解 //Console.WriteLine("wins: " + child.Wins); if (best == null || child.TotNumVisits > best.TotNumVisits || (child.TotNumVisits == best.TotNumVisits && child.Wins > best.Wins)) { best = child; } } //Console.WriteLine("best visits: " + best.TotNumVisits); //Console.WriteLine("best wins: " + best.Wins); if (best == null) { //Debug.WriteLine("best == null"); return(game.CurrentPlayer.Options()[0]); } //Console.WriteLine("best wins: " + best.Wins + " best visits: " + best.TotNumVisits); return(best.Action); }
public override PlayerTask GetMove(POGame.POGame poGame) { throw new NotImplementedException(); }
/// <summary> /// TODO: API /// </summary> /// <param name="game"></param> /// <returns></returns> public abstract MCTSNode simulate(POGame.POGame game);
public MCTSNode(POGame.POGame poGame) { this.poGame = poGame; }
public static double ucb1Heuristic(Node node, int iterations, double EXPLORE_CONSTANT, ref POGame.POGame poGame, double SCORE_IMPORTANCE, ParametricGreedyAgent greedyAgent) { double value; if (node.timesVisited > 0) { List <PlayerTask> taskToSimulate = new List <PlayerTask>(); taskToSimulate.Add(node.task); POGame.POGame stateAfterSimulate = poGame.Simulate(taskToSimulate)[node.task]; double score = greedyAgent.scoreTask(poGame, stateAfterSimulate); value = (node.totalValue / (double)node.timesVisited) + EXPLORE_CONSTANT * Math.Sqrt(Math.Log(iterations) / node.timesVisited) + SCORE_IMPORTANCE * (score / (double)node.timesVisited); } else { value = Double.MaxValue; } return(value); }
public static double selectTreePolicy(string treePolicy, Node node, int iterations, double exploreConstant, ref POGame.POGame poGame, double scoreImportance, ParametricGreedyAgent greedyAgent) { double score; switch (treePolicy) { case "UCB1": score = ucb1(node, iterations, exploreConstant); break; case "UCB1Heuristic": score = ucb1Heuristic(node, iterations, exploreConstant, ref poGame, scoreImportance, greedyAgent); break; default: score = 0; break; } return(score); }
protected abstract List <PlayerTask> getSolutions(POGame.POGame poGame, int playerID, IScore scoring);
/// <summary> /// Returns a prediction of the opponent's hand cards, i.e. set of cards and there probability, /// based on the bi-gram map and cards which haven been played the opponent. /// </summary> /// <param name="cardCount">the number of sets which will by predicted</param> /// <param name="simulationGame">the game the prediction is performed on</param> /// <param name="playedCards">the cards which have been played by the opponent</param> /// <param name="boardCards">the board cards of the opponent</param> /// <param name="classPrediction">the prediction of the deck classes of the opponent</param> /// <returns>the set of cards and there probability</returns> private List <PredictedCards> predictCards(int cardCount, POGame.POGame simulationGame, PlayedCards playedCards, BoardCards boardCards, Dictionary <CardClass, double> classPrediction) { List <Dictionary <string, double> > occMaps = getOccurenceMaps(playedCards); var combinedOccMap = new Dictionary <string, double>(); foreach (Dictionary <string, double> occMap in occMaps) { occMap.ToList().ForEach(o => { string cardId = o.Key; double cardValue = o.Value; if (combinedOccMap.ContainsKey(cardId)) { // greedy approach if (combinedOccMap[cardId] < cardValue) { combinedOccMap[cardId] = cardValue; } } else { combinedOccMap.Add(cardId, cardValue); } }); } Dictionary <Card, double> playableCards = convertToCardMap(combinedOccMap, classPrediction); // get number of cards in relation to the class distribution of already drawn cards var tempPredictedCardGroups = new List <PredictedCards>(); classPrediction.ToList().ForEach(c => { // filter cards if they have already been exhausted or not var filterdPlayableCards = new PredictedCards( playableCards.Where(p => p.Key.Class == c.Key) .Where(p => { if (p.Key.Rarity == Rarity.LEGENDARY) { return(boardCards.Cards .Count(b => b == p.Key) < 1); } else { return(boardCards.Cards .Count(b => b == p.Key) < 2); } }).ToList()); int share = (int)(c.Value * cardCount); var predictedCards = new PredictedCards(filterdPlayableCards .CardEntries.Take(share) .ToList()); tempPredictedCardGroups.Add(predictedCards); }); var combinedPredictedCards = new PredictedCards( tempPredictedCardGroups.SelectMany(g => g.CardEntries) .ToList()); double sum = combinedPredictedCards.Sum; var predictedCardGroups = new List <PredictedCards>(); foreach (PredictedCards group in tempPredictedCardGroups) { var newGroup = new PredictedCards(); group.CardEntries // sort list .OrderByDescending(c => c.Value) .ToList().ForEach(c => newGroup.Add(c.Key, (c.Value / sum))); predictedCardGroups.Add(newGroup); } return(predictedCardGroups); }
/// <summary> Returns N sorted simulated TySimResults for the given start state. </summary> public static List <TySimResult> GetSimulatedBestTasks(int numTasks, POGame.POGame game, TyStateAnalyzer analyzer) { return(GetSimulatedBestTasks(numTasks, game, game.CurrentPlayer.Options(), analyzer)); }
/// <summary> /// TODO: API /// </summary> /// <param name="game"></param> /// <returns></returns> public override MCTSNode simulate(POGame.POGame game) { POGame.POGame gameCopy = game.getCopy(); // initials root node var initLeafs = new List <MCTSNode>(); var root = new MCTSNode(_playerId, new List <MCTSNode.ScoreExt> { new MCTSNode.ScoreExt(1.0, _scoring) }, gameCopy, null, null); // simulate MCTSNode bestNode = simulate(_deltaTime, root, ref initLeafs); // initials opponent's history if (_oppHistory == null) { List <PlayHistoryEntry> history = gameCopy.CurrentOpponent.PlayHistory; PlayHistoryEntry[] copyHistory = new PlayHistoryEntry[history.Count]; history.CopyTo(copyHistory); _oppHistory = copyHistory.ToList(); } var simulationQueue = new Queue <KeyValuePair <POGame.POGame, List <MCTSNode> > >(); simulationQueue.Enqueue(new KeyValuePair <POGame.POGame, List <MCTSNode> >(gameCopy, initLeafs)); int i = 0; while (i < _predictionParameters.SimulationDepth && simulationQueue.Count > 0) { // calculate the lower and upper time bound of the current depth double lowerSimulationTimeBound = _deltaTime + i * (2 * _deltaTime); KeyValuePair <POGame.POGame, List <MCTSNode> > simulation = simulationQueue.Dequeue(); POGame.POGame simulationGame = simulation.Key; List <MCTSNode> leafs = simulation.Value; leafs = leafs.Where(l => l.Game != null) .OrderByDescending(l => l.Score) .Take((leafs.Count > _predictionParameters.LeafCount) ? _predictionParameters.LeafCount : leafs.Count) .ToList(); if (leafs.Count() < 0) { return(bestNode); } Controller opponent = getOpponent(simulationGame); List <Prediction> predicitionMap = getPredictionMap(simulationGame, opponent); var oldSimulations = new Dictionary <POGame.POGame, List <MCTSNode> >(); // the simulation time for one leaf double timePerLeaf = (2 * _deltaTime) / leafs.Count; // get all games from all leaf nodes for (int j = 0; j < leafs.Count; j++) { // calculate the lower time bound of the current leaf double lowerLeafTimeBound = lowerSimulationTimeBound + j * timePerLeaf; MCTSNode leafNode = leafs[j]; POGame.POGame oppGame = leafNode.Game; double leafScore; // XXX: game can be null leafScore = simulateOpponentWithPrediction(lowerLeafTimeBound, timePerLeaf, oppGame, opponent, predicitionMap, ref oldSimulations); // back-propagate score backpropagate(leafNode, leafScore); } var newSimulations = new Dictionary <POGame.POGame, List <MCTSNode> >(); oldSimulations.ToList() .OrderByDescending(s => s.Value.Sum(l => l.TotalScore)) .Take((leafs.Count > _predictionParameters.OverallLeafCount) ? _predictionParameters.OverallLeafCount : leafs.Count) .ToList() .ForEach(l => newSimulations.Add(l.Key, l.Value)); // add new simulations foreach (KeyValuePair <POGame.POGame, List <MCTSNode> > sim in oldSimulations) { simulationQueue.Enqueue(sim); } i++; } return(root.Children .OrderByDescending(c => c.TotalScore) .First()); }
/// <summary> Returns N sorted simulated TySimResults for the given start state. </summary> public static List <TySimResult> GetSimulatedBestTasks(int numTasks, POGame.POGame game, List <PlayerTask> options, TyStateAnalyzer analyzer) { return(GetSortedBestTasks(numTasks, GetSimulatedGames(game, options, analyzer))); }
public override PlayerTask GetMove(POGame.POGame poGame) { //return GetMoveRandom(poGame); return(GetMoveSearchTree(poGame, 2)); }
public FlatMCOptionNode(FlatMCOptionNode parent, POGame.POGame game, int playerId, PlayerTask playerTask, IScore scoring) : base(parent, game, playerId, playerTask, scoring) { }
float[] HardCodedOptionRating(POGame.POGame poGame, List <PlayerTask> options) { Controller me = poGame.CurrentPlayer; Controller op = poGame.CurrentOpponent; int hp = me.Hero.Health; int opHp = op.Hero.Health; int heroDamage = me.Hero.TotalAttackDamage; int opHeroDamage = op.Hero.TotalAttackDamage; int handZoneCount = me.HandZone.Count; int opHandZoneCount = op.HandZone.Count; float averageHandCost = me.HandZone.GetAll().Sum(p => p.Cost) / ((handZoneCount == 0)? 1 : handZoneCount); int remainingCards = me.DeckZone.Count; int opRemainingCards = op.DeckZone.Count; int numberOfMinions = me.BoardZone.Count; int minionTotHealth = me.BoardZone.Sum(p => p.Health); int minionTotAttack = me.BoardZone.Sum(p => p.AttackDamage); int minionTotTauntHp = me.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health); int opNumberOfMinions = op.BoardZone.Count; int opMinionTotHealth = op.BoardZone.Sum(p => p.Health); int opMinionTotAttack = op.BoardZone.Sum(p => p.AttackDamage); int opMinionTotTauntHp = op.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health); float[] result = new float[options.Count]; for (int i = 0; i < options.Count; i++) { PlayerTask curOption = options[i]; if (curOption.PlayerTaskType == PlayerTaskType.MINION_ATTACK) { Minion minion = (Minion)curOption.Source; if (curOption.Target.Card.Type == SabberStoneCore.Enums.CardType.HERO) { if (minion.AttackDamage > opHp) { result[i] = 1f; } if (minionTotAttack > 1.3f * opMinionTotAttack && minionTotHealth > 1.3f * opMinionTotHealth) { result[i] += 0.5f; } result[i] += 0.3f; } if (curOption.Target.Card.Type == SabberStoneCore.Enums.CardType.MINION) { Minion targetMinion = (Minion)curOption.Target; if (minionTotAttack < 0.8f * opMinionTotAttack && minionTotHealth < 0.8f * opMinionTotHealth && minion.Health > targetMinion.AttackDamage) { result[i] += 0.5f; } if (minion.Health > targetMinion.AttackDamage && minion.AttackDamage > targetMinion.Health) { result[i] += 0.5f; } } if (minionTotAttack > 1.2f * opMinionTotAttack && minionTotHealth > 1.2f * opMinionTotHealth && opMinionTotTauntHp < 5) { result[i] += 0.1f; } result[i] += 0.1f; } if (curOption.PlayerTaskType == PlayerTaskType.PLAY_CARD) { if (curOption.Source.Card.Type == SabberStoneCore.Enums.CardType.MINION) { if (opNumberOfMinions > numberOfMinions && opMinionTotHealth > minionTotHealth || opMinionTotAttack > minionTotAttack) { result[i] += 0.5f; } result[i] += 0.5f; if (numberOfMinions == 0 && numberOfMinions == 0) { result[i] += 0.4f; } } if (curOption.Source.Card.Type == SabberStoneCore.Enums.CardType.WEAPON) { if (me.Hero.Damage <= 0) { result[i] += 0.4f; } } if (curOption.Source.Card.Type == SabberStoneCore.Enums.CardType.SPELL) { Spell curSpell = (Spell)curOption.Source; if (curOption.HasTarget && curOption.Target.Card.Type == SabberStoneCore.Enums.CardType.HERO) { result[i] += 0.2f; } if (curOption.HasTarget == false) { result[i] += 0.1f; } } } if (curOption.PlayerTaskType == PlayerTaskType.HERO_POWER) { if (me.HeroClass == SabberStoneCore.Enums.CardClass.SHAMAN) { result[i] += 0.2f; } if (me.HeroClass == SabberStoneCore.Enums.CardClass.MAGE && curOption.Target.Controller == me) { result[i] = -1f; } result[i] += 0.1f; } if (me.BaseMana <= 3 && me.RemainingMana >= 2 && (curOption.PlayerTaskType == PlayerTaskType.HERO_POWER || curOption.PlayerTaskType == PlayerTaskType.PLAY_CARD)) { result[i] += 0.5f; } if (curOption.PlayerTaskType == PlayerTaskType.END_TURN && me.RemainingMana > 0.5f * me.BaseMana) { result[i] = -0.5f; } if (curOption.PlayerTaskType == PlayerTaskType.HERO_ATTACK) { if (curOption.Target is Minion) { Minion curTarget = (Minion)curOption.Target; if (hp > curTarget.AttackDamage && curTarget.Health < heroDamage) { result[i] += 0.5f; } } if (curOption.Target is Hero) { Hero curTarget = (Hero)curOption.Target; if (hp > curTarget.AttackDamage && curTarget.Health < heroDamage) { result[i] += 0.5f; } } else { result[i] += 0.2f; } } } return(result); /*for (int i = 0; i < options.Count; i++) * { * * if (options[i].PlayerTaskType == PlayerTaskType.PLAY_CARD) * { * if (options[i].Source.Card.Type == SabberStoneCore.Enums.CardType.MINION) * { * * if (bestCard == null || options[i].Source.Card.Cost > bestCard.Cost) * { * bestCard = options[i].Source.Card; * id = i; * } * } * * } * * if (options[i].PlayerTaskType == PlayerTaskType.MINION_ATTACK) * { * if (options[i].Target != null && options[i].Target.Card.Type == SabberStoneCore.Enums.CardType.HERO) * hardMinionAttackOptionRating[i] = 1; * } * }*/ }
private PlayerTask GetGreedyBestTask(POGame.POGame poGame, List <PlayerTask> options) { var bestTasks = TyStateUtility.GetSimulatedBestTasks(1, poGame, options, _analyzer); return(bestTasks[0].task); }
public abstract PlayerTask GetMove(POGame.POGame poGame);
private void OnMyTurnBegin(POGame.POGame state) { _isTurnBegin = false; _turnTimeStart = TyUtility.GetSecondsSinceStart(); }
public TySimResult(POGame.POGame state, PlayerTask task, float value) { this.state = state; this.value = value; this.task = task; }
private static PlayerTask randomTask(POGame.POGame poGame, Random Rnd) { return(poGame.CurrentPlayer.Options()[Rnd.Next(0, poGame.CurrentPlayer.Options().Count - 1)]); }