예제 #1
0
        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]);
        }
예제 #2
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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        public PlayerTask GetMoveRandom(POGame.POGame poGame)
        {
            List <PlayerTask> options = poGame.CurrentPlayer.Options();

            return(options[Rnd.Next(options.Count)]);
        }
예제 #6
0
파일: MCTS.cs 프로젝트: marcopolo59470/HSAI
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
 public override PlayerTask GetMove(POGame.POGame poGame)
 {
     throw new NotImplementedException();
 }
예제 #9
0
 /// <summary>
 /// TODO: API
 /// </summary>
 /// <param name="game"></param>
 /// <returns></returns>
 public abstract MCTSNode simulate(POGame.POGame game);
예제 #10
0
 public MCTSNode(POGame.POGame poGame)
 {
     this.poGame = poGame;
 }
예제 #11
0
        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);
        }
예제 #12
0
        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);
예제 #14
0
        /// <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);
        }
예제 #15
0
 /// <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));
 }
예제 #16
0
        /// <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());
        }
예제 #17
0
 /// <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)));
 }
예제 #18
0
 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)
 {
 }
예제 #20
0
        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;
             *      }
             * }*/
        }
예제 #21
0
        private PlayerTask GetGreedyBestTask(POGame.POGame poGame, List <PlayerTask> options)
        {
            var bestTasks = TyStateUtility.GetSimulatedBestTasks(1, poGame, options, _analyzer);

            return(bestTasks[0].task);
        }
예제 #22
0
 public abstract PlayerTask GetMove(POGame.POGame poGame);
예제 #23
0
 private void OnMyTurnBegin(POGame.POGame state)
 {
     _isTurnBegin   = false;
     _turnTimeStart = TyUtility.GetSecondsSinceStart();
 }
예제 #24
0
 public TySimResult(POGame.POGame state, PlayerTask task, float value)
 {
     this.state = state;
     this.value = value;
     this.task  = task;
 }
예제 #25
0
 private static PlayerTask randomTask(POGame.POGame poGame, Random Rnd)
 {
     return(poGame.CurrentPlayer.Options()[Rnd.Next(0, poGame.CurrentPlayer.Options().Count - 1)]);
 }