public override PlayerTask GetMove(POGame.POGame poGame)
        {
            if (!_hasInitialized)
            {
                CustomInit(poGame);
            }

            if (_isTurnBegin)
            {
                OnMyTurnBegin(poGame);
            }

            var options = poGame.CurrentPlayer.Options();

            PlayerTask choosenTask = ChooseTask(poGame, options);

            //should not happen, but if, just return anything:
            if (choosenTask == null)
            {
                if (TyConst.LOG_UNKNOWN_CORRECTIONS)
                {
                    TyDebug.LogError("Choosen task was null!");
                }

                choosenTask = options.GetUniformRandom(_random);
            }

            if (choosenTask.PlayerTaskType == PlayerTaskType.END_TURN)
            {
                OnMyTurnEnd();
            }

            return(choosenTask);
        }
Beispiel #2
0
        public static void CalculateValues(TyState playerState, TyState opponentState, Controller player, Controller opponent, PlayerTask task, Spell spell)
        {
            if (_spellDictionary == null)
            {
                Init();
            }

            //give reward/punishment if spells cost less/more than usual:
            float diff = (float)spell.Card.Cost - (float)spell.Cost;

            playerState.BiasValue += diff * 1.25f;

            var key = spell.Card.Name;

            if (_spellDictionary.ContainsKey(key))
            {
                var action = _spellDictionary[key];
                action(playerState, opponentState, player, opponent, task, spell);
            }

            else if (TyConst.LOG_UNKNOWN_SECRETS)
            {
                TyDebug.LogInfo("Unknown spell: " + task.FullPrint());
            }
        }
Beispiel #3
0
        public static void CalculateValues(TyState playerState, TyState opponentState, Controller player, Controller opponent)
        {
            if (_secretDictionary == null)
            {
                Init();
            }

            for (int i = 0; i < player.SecretZone.Count; i++)
            {
                var secret = player.SecretZone[i];
                var key    = secret.Card.Name;

                if (_secretDictionary.ContainsKey(key))
                {
                    var action = _secretDictionary[key];
                    action(playerState, opponentState, player, opponent, secret);
                }

                else
                {
                    if (TyConst.LOG_UNKNOWN_SECRETS)
                    {
                        TyDebug.LogWarning("Unknown secret: " + secret.Card.FullPrint());
                    }

                    playerState.BiasValue += secret.Card.Cost * SECRET_VALUE_FACTOR;
                }
            }
        }
        private void OnMyTurnEnd()
        {
            _isTurnBegin = true;

            var timeNeeded = TyUtility.GetSecondsSinceStart() - _turnTimeStart;

            if (AdjustEpisodeMultiplier && UsedAlgorithm == Algorithm.SearchTree)
            {
                const double MAX_DIFF = 4.0;
                double       diff     = Math.Min(TyConst.DECREASE_SIMULATION_TIME - timeNeeded, MAX_DIFF);
                double       factor   = 0.05;

                //reduce more if above the time limit:
                if (diff <= 0.0f)
                {
                    factor = 0.2;
                }

                //simulate at max this value * _defaultEpisodeMultiplier:
                const int MAX_EPISODE_MULTIPLIER = 4;
                _curEpisodeMultiplier = Math.Clamp(_curEpisodeMultiplier + (int)(factor * diff * _defaultEpisodeMultiplier),
                                                   _defaultEpisodeMultiplier,
                                                   _defaultEpisodeMultiplier * MAX_EPISODE_MULTIPLIER);
            }

            if (PrintTurnTime)
            {
                TyDebug.LogInfo("Turn took " + timeNeeded.ToString("0.000") + "s");
            }

            if (timeNeeded >= TyConst.MAX_TURN_TIME)
            {
                TyDebug.LogWarning("Turn took " + timeNeeded.ToString("0.000") + "s");
            }
        }
Beispiel #5
0
        /// <summary> Searches for XX/YY in the given text and parses it to int. </summary>
        private static bool FindNumberValues(string text, ref int first, ref int second)
        {
            Regex regex = new Regex("[0-9]+/[0-9]+");
            var   match = regex.Match(text);

            if (match.Success)
            {
                var numbers = match.Value.Split("/", StringSplitOptions.RemoveEmptyEntries);
                if (numbers.Length == 2)
                {
                    if (int.TryParse(numbers[0], out first))
                    {
                        if (int.TryParse(numbers[1], out second))
                        {
                            return(true);
                        }
                    }
                }
            }

            if (TyConst.LOG_UNKNOWN_CORRECTIONS)
            {
                TyDebug.LogError("Could find number values in " + text);
            }

            return(false);
        }
Beispiel #6
0
        public float GetStateValue(TyState playerState, TyState enemyState, Controller player, Controller opponent, PlayerTask task)
        {
            TyDebug.Assert(IsMyPlayer(player));
            TyDebug.Assert(!IsMyPlayer(opponent));

            if (EstimateSecretsAndSpells)
            {
                TySecretUtil.CalculateValues(playerState, enemyState, player, opponent);
                TySecretUtil.EstimateValues(enemyState, opponent);

                var spell = task.TryGetSpell();

                if (spell != null && !spell.IsSecret)
                {
                    TySpellUtil.CalculateValues(playerState, enemyState, player, opponent, task, spell);
                }
            }

            if (HasLost(enemyState))
            {
                return(Single.PositiveInfinity);
            }

            else if (HasLost(playerState))
            {
                return(Single.NegativeInfinity);
            }

            return(GetStateValueFor(playerState, enemyState) - GetStateValueFor(enemyState, playerState));
        }
Beispiel #7
0
        public TyStateWeights(params float[] defaultValues)
            : this()
        {
            TyDebug.Assert(defaultValues.Length == (int)WeightType.Count);

            for (int i = 0; i < _weights.Length; i++)
            {
                _weights[i] = defaultValues[i];
            }
        }
        /// <summary> False if there is not enough time left to do simulations. </summary>
        private bool IsAllowedToSimulate(double startTime, int curEpisode, int maxEpisode, int options)
        {
            double time = TyUtility.GetSecondsSinceStart() - startTime;

            if (time >= MAX_TIME)
            {
                TyDebug.LogWarning("Stopped simulations after " + time.ToString("0.000") + "s and " + curEpisode + " of " + maxEpisode + " episodes. Having " + options + " options.");
                return(false);
            }

            return(true);
        }
Beispiel #9
0
        private static void RemoveMinion(Minion minion, TyState ownerState, TyState opponentState, PlayerTask task)
        {
            //remove the minion value from the overall minion values and remove it from the board
            ownerState.MinionValues -= TyMinionUtil.ComputeMinionValue(minion);
            ownerState.NumMinionsOnBoard--;

            if (minion.HasDeathrattle)
            {
                if (!CorrectForSummonAndEquip(minion.Card, ownerState, opponentState) && TyConst.LOG_UNKNOWN_CORRECTIONS)
                {
                    TyDebug.LogError("Unknown deathrattle from " + minion.Card.FullPrint());
                    TyDebug.LogWarning("After task " + task.FullPrint());
                }
            }
        }
        /// <summary> Estimates how good the given child state is. </summary>
        public static float GetStateValue(POGame.POGame parent, POGame.POGame child, PlayerTask task, TyStateAnalyzer analyzer)
        {
            float valueFactor = 1.0f;

            TyState myState    = null;
            TyState enemyState = null;

            Controller player   = null;
            Controller opponent = null;

            //it's a buggy state, mostly related to equipping/using weapons on heroes etc.
            //in this case use the old state and estimate the new state manually:
            if (child == null)
            {
                player   = parent.CurrentPlayer;
                opponent = parent.CurrentOpponent;

                myState    = TyState.FromSimulatedGame(parent, player, task);
                enemyState = TyState.FromSimulatedGame(parent, opponent, null);

                //if the correction failes, assume the task is x% better/worse:
                if (!TyState.CorrectBuggySimulation(myState, enemyState, parent, task))
                {
                    valueFactor = 1.25f;
                }
            }

            else
            {
                player   = child.CurrentPlayer;
                opponent = child.CurrentOpponent;

                //happens sometimes even with/without TURN_END, idk
                if (!analyzer.IsMyPlayer(player))
                {
                    player   = child.CurrentOpponent;
                    opponent = child.CurrentPlayer;
                }

                myState    = TyState.FromSimulatedGame(child, player, task);
                enemyState = TyState.FromSimulatedGame(child, opponent, null);
            }

            TyDebug.Assert(analyzer.IsMyPlayer(player));
            TyDebug.Assert(!analyzer.IsMyPlayer(opponent));
            return(analyzer.GetStateValue(myState, enemyState, player, opponent, task) * valueFactor);
        }
        private PlayerTask GetSimulationTreeTask(POGame.POGame poGame, List <PlayerTask> options)
        {
            double time = TyUtility.GetSecondsSinceStart() - _turnTimeStart;

            if (time >= TyConst.MAX_TURN_TIME)
            {
                TyDebug.LogError("Turn takes too long, fall back to greedy.");
                return(GetGreedyBestTask(poGame, options));
            }

            _simTree.InitTree(_analyzer, poGame, options);

            //-1 because TurnEnd won't be looked at:
            int optionCount = options.Count - 1;
            int numEpisodes = (int)((optionCount) * _curEpisodeMultiplier);

            double simStart = TyUtility.GetSecondsSinceStart();

            /*
             * for (int i = 0; i < numEpisodes; i++)
             * {
             *      if (!IsAllowedToSimulate(simStart, i, numEpisodes, optionCount))
             *              break;
             *
             *      bool shouldExploit = ((double)i / (double)numEpisodes) > EXPLORE_TRESHOLD;
             *      _simTree.SimulateEpisode(_random, i, shouldExploit);
             * }
             *
             */
            int i = 0;

            while (IsAllowedToSimulate(simStart, i, numEpisodes, optionCount))
            {
                bool shouldExploit = ((double)i / (double)numEpisodes) > EXPLORE_TRESHOLD;
                _simTree.SimulateEpisode(_random, i, shouldExploit);
                i++;
            }

            var bestNode = _simTree.GetBestNode();

            return(bestNode.Task);
        }
Beispiel #12
0
        public static bool CorrectBuggySimulation(TyState lastPlayerState, TyState lastEnemyState, POGame.POGame lastState, PlayerTask task)
        {
            var taskType = task.PlayerTaskType;

            //Testing.TyDebug.LogError(task.FullPrint());

            bool corrected = false;

            if (taskType == PlayerTaskType.END_TURN)
            {
                CorrectTurnEnd(lastPlayerState, lastEnemyState, lastState, task, ref corrected);
            }

            else if (taskType == PlayerTaskType.HERO_ATTACK)
            {
                CorrectHeroAttack(lastPlayerState, lastEnemyState, lastState, task, ref corrected);
            }

            else if (taskType == PlayerTaskType.PLAY_CARD)
            {
                CorrectPlayCard(lastPlayerState, lastEnemyState, lastState, task, ref corrected);
            }

            else if (taskType == PlayerTaskType.MINION_ATTACK)
            {
                CorrectMinionAttack(lastPlayerState, lastEnemyState, lastState, task, ref corrected);
            }

            else if (taskType == PlayerTaskType.HERO_POWER)
            {
                CorrectHeroPower(lastPlayerState, lastEnemyState, lastState, task, ref corrected);
            }

            if (TyConst.LOG_UNKNOWN_CORRECTIONS && !corrected)
            {
                TyDebug.LogError("Unknown buggy PlayerTask: " + task.FullPrint());
            }

            return(corrected);
        }
Beispiel #13
0
 public bool IsMyPlayer(Controller c)
 {
     TyDebug.Assert(OwnPlayerId != -1);
     return(c.PlayerId == OwnPlayerId);
 }