Esempio n. 1
0
        public void Reset(bool resetStats = true)
        {
            Logger.WriteLine("-------- Reset ---------", "Game");

            ReplayMaker.Reset();
            Player.Reset();
            Opponent.Reset();

            Entities.Clear();
            SavedReplay         = false;
            OpponentSecretCount = 0;
            OpponentSecrets.ClearSecrets();
            NoMatchingDeck = false;

            if (!IsInMenu && resetStats)
            {
                if (CurrentGameMode == GameMode.Ranked)
                {
                    Logger.WriteLine("Resetting gamemode to casual", "Game");
                    CurrentGameMode = GameMode.Casual;
                }
                CurrentGameStats = new GameStats(GameResult.None, "", "")
                {
                    PlayerName = "", OpponentName = "", Region = CurrentRegion
                };
                _gameModeDetectionComplete = false;
            }
            _hsLogLines = new List <string>();

            if (Core.Game != null && Core.Overlay != null)
            {
                Helper.UpdatePlayerCards();
                Helper.UpdateOpponentCards();
            }
        }
Esempio n. 2
0
        public void Reset(bool resetStats = true)
        {
            Logger.WriteLine("-------- Reset ---------", "Game");

            ReplayMaker.Reset();
            Player.Reset();
            Opponent.Reset();

            Entities.Clear();
            SavedReplay         = false;
            OpponentSecretCount = 0;
            OpponentSecrets.ClearSecrets();
            NoMatchingDeck = false;

            if (!IsInMenu && resetStats)
            {
                if (CurrentGameMode != GameMode.Spectator)
                {
                    CurrentGameMode = GameMode.None;
                }
                CurrentGameStats = new GameStats(GameResult.None, "", "")
                {
                    PlayerName = "", OpponentName = "", Region = CurrentRegion
                };
            }
            _hsLogLines = new List <string>();

            if (Helper.MainWindow.Overlay != null)
            {
                Helper.UpdatePlayerCards();
                Helper.UpdateOpponentCards();
            }
        }
        private void ZonePositionChange(IHsGameState gameState, int id, IGame game)
        {
            var entity     = game.Entities[id];
            var zone       = entity.GetTag(ZONE);
            var controller = entity.GetTag(CONTROLLER);

            if (zone == (int)HAND)
            {
                if (controller == game.Player.Id)
                {
                    ReplayMaker.Generate(HandPos, id, ActivePlayer.Player, game);
                }
                else if (controller == game.Opponent.Id)
                {
                    ReplayMaker.Generate(HandPos, id, ActivePlayer.Opponent, game);
                }
            }
            else if (zone == (int)PLAY)
            {
                if (controller == game.Player.Id)
                {
                    ReplayMaker.Generate(BoardPos, id, ActivePlayer.Player, game);
                }
                else if (controller == game.Opponent.Id)
                {
                    ReplayMaker.Generate(BoardPos, id, ActivePlayer.Opponent, game);
                }
            }
        }
        public void Reset(bool resetStats = true)
        {
            Log.Info("-------- Reset ---------");

            ReplayMaker.Reset();
            Player.Reset();
            Opponent.Reset();

            Entities.Clear();
            SavedReplay         = false;
            OpponentSecretCount = 0;
            OpponentSecrets.ClearSecrets();

            if (!IsInMenu && resetStats)
            {
                if (CurrentGameMode == GameMode.Ranked)
                {
                    Log.Info("Resetting gamemode to casual");
                    CurrentGameMode = GameMode.Casual;
                }
                CurrentGameStats = new GameStats(GameResult.None, "", "")
                {
                    PlayerName = "", OpponentName = "", Region = CurrentRegion
                };
                _gameModeDetectionComplete = false;
            }
            PowerLog.Clear();

            if (Core.Game != null && Core.Overlay != null)
            {
                Core.UpdatePlayerCards(true);
                Core.UpdateOpponentCards(true);
            }
        }
Esempio n. 5
0
        private static void ZonePositionChange(IHsGameState gameState, int id, IGame game, int controller)
        {
            var entity = game.Entities[id];
            var zone   = entity.GetTag(ZONE);

            if (zone == (int)HAND)
            {
                if (controller == game.Player.Id)
                {
                    ReplayMaker.Generate(HandPos, id, ActivePlayer.Player, game);
                    gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Player, entity, HAND, gameState.GetTurnNumber());
                }
                else if (controller == game.Opponent.Id)
                {
                    ReplayMaker.Generate(HandPos, id, ActivePlayer.Opponent, game);
                    gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Opponent, entity, HAND, gameState.GetTurnNumber());
                }
            }
            else if (zone == (int)PLAY)
            {
                if (controller == game.Player.Id)
                {
                    ReplayMaker.Generate(BoardPos, id, ActivePlayer.Player, game);
                    gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Player, entity, PLAY, gameState.GetTurnNumber());
                }
                else if (controller == game.Opponent.Id)
                {
                    ReplayMaker.Generate(BoardPos, id, ActivePlayer.Opponent, game);
                    gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Opponent, entity, PLAY, gameState.GetTurnNumber());
                }
            }
        }
Esempio n. 6
0
        public void Reset(bool resetStats = true)
        {
            Log.Info("-------- Reset ---------");

            ReplayMaker.Reset();
            Player.Reset();
            Opponent.Reset();
            Entities.Clear();
            SavedReplay         = false;
            OpponentSecretCount = 0;
            OpponentSecrets.ClearSecrets();
            _spectator       = null;
            _currentGameMode = GameMode.None;
            _currentFormat   = null;
            if (!IsInMenu && resetStats)
            {
                CurrentGameStats = new GameStats(GameResult.None, "", "")
                {
                    PlayerName = "", OpponentName = "", Region = CurrentRegion
                }
            }
            ;
            PowerLog.Clear();

            if (Core.Game != null && Core.Overlay != null)
            {
                Core.UpdatePlayerCards(true);
                Core.UpdateOpponentCards(true);
            }
        }
Esempio n. 7
0
        public void Reset(bool resetStats = true)
        {
            Logger.WriteLine(">>>>>>>>>>> Reset <<<<<<<<<<<", "Game");

            ReplayMaker.Reset();
            PlayerDrawn.Clear();
            PlayerDrawnIdsTotal.Clear();
            Entities.Clear();
            PlayerId            = -1;
            OpponentId          = -1;
            SavedReplay         = false;
            PlayerHandCount     = 0;
            PlayerFatigueCount  = 0;
            OpponentSecretCount = 0;
            OpponentCards.Clear();
            OpponentHandCount              = 0;
            OpponentFatigueCount           = 0;
            OpponentDeckCount              = 30;
            PlayerDeckSize                 = 30;
            SecondToLastUsedId             = null;
            OpponentHandAge                = new int[MaxHandSize];
            OpponentHandMarks              = new CardMark[MaxHandSize];
            OpponentStolenCardsInformation = new Card[MaxHandSize];
            OpponentSecrets.ClearSecrets();
            NoMatchingDeck = false;
            _playingAs     = null;

            for (var i = 0; i < MaxHandSize; i++)
            {
                OpponentHandAge[i]   = -1;
                OpponentHandMarks[i] = CardMark.None;
            }

            // Assuming opponent has coin, corrected if we draw it
            OpponentHandMarks[DefaultCoinPosition] = CardMark.Coin;
            OpponentHandAge[DefaultCoinPosition]   = 0;
            OpponentHasCoin = true;

            SetAsideCards.Clear();
            OpponentReturnedToDeck.Clear();

            //if(CurrentGameMode == GameMode.Ranked) //otherwise switching from playing ranked to casual causes problems
            //	CurrentGameMode = GameMode.Casual;


            if (!IsInMenu && resetStats)
            {
                if (CurrentGameMode != GameMode.Spectator)
                {
                    CurrentGameMode = GameMode.None;
                }
                CurrentGameStats = new GameStats(GameResult.None, PlayingAgainst, PlayingAs)
                {
                    PlayerName   = PlayerName,
                    OpponentName = OpponentName,
                    Region       = CurrentRegion
                };
            }
            hsLogLines = new List <string>();
        }
 private void ProposeKeyPoint(KeyPointType type, int id, ActivePlayer player)
 {
     if (_proposedKeyPoint != null)
     {
         ReplayMaker.Generate(_proposedKeyPoint.Type, _proposedKeyPoint.Id, _proposedKeyPoint.Player);
     }
     _proposedKeyPoint = new ReplayKeyPoint(null, type, id, player);
 }
 public void ProposeKeyPoint(KeyPointType type, int id, ActivePlayer player)
 {
     if (ProposedKeyPoint != null)
     {
         ReplayMaker.Generate(ProposedKeyPoint.Type, ProposedKeyPoint.Id, ProposedKeyPoint.Player, _game);
     }
     ProposedKeyPoint = new ReplayKeyPoint(null, type, id, player);
 }
 public void GameEndKeyPoint(bool victory, int id)
 {
     if (ProposedKeyPoint != null)
     {
         ReplayMaker.Generate(ProposedKeyPoint.Type, ProposedKeyPoint.Id, ProposedKeyPoint.Player, _game);
         ProposedKeyPoint = null;
     }
     ReplayMaker.Generate(victory ? KeyPointType.Victory : KeyPointType.Defeat, id, ActivePlayer.Player, _game);
 }
 private void GameEndKeyPoint(bool victory, int id)
 {
     if (_proposedKeyPoint != null)
     {
         ReplayMaker.Generate(_proposedKeyPoint.Type, _proposedKeyPoint.Id, _proposedKeyPoint.Player);
         _proposedKeyPoint = null;
     }
     ReplayMaker.Generate(victory ? KeyPointType.Victory : KeyPointType.Defeat, id, ActivePlayer.Player);
 }
Esempio n. 12
0
        public void HandleInMenu()
        {
            if (Game.IsInMenu)
            {
                return;
            }

            if (Config.Instance.RecordReplays && Game.Entities.Count > 0 && !Game.SavedReplay && Game.CurrentGameStats != null &&
                Game.CurrentGameStats.ReplayFile == null && RecordCurrentGameMode)
            {
                Game.CurrentGameStats.ReplayFile = ReplayMaker.SaveToDisk();
            }

            SaveAndUpdateStats();

            Game.IsInMenu = true;
            TurnTimer.Instance.Stop();
            Helper.MainWindow.Overlay.HideTimers();
            Helper.MainWindow.Overlay.HideSecrets();
            if (Config.Instance.KeyPressOnGameEnd != "None" && Helper.MainWindow.EventKeys.Contains(Config.Instance.KeyPressOnGameEnd))
            {
                SendKeys.SendWait("{" + Config.Instance.KeyPressOnGameEnd + "}");
                Logger.WriteLine("Sent keypress: " + Config.Instance.KeyPressOnGameEnd, "GameEventHandler");
            }
            if (!Config.Instance.KeepDecksVisible)
            {
                var deck = DeckList.Instance.ActiveDeckVersion;
                if (deck != null)
                {
                    Game.SetPremadeDeck((Deck)deck.Clone());
                }
            }
            if (!Game.IsUsingPremade)
            {
                Game.DrawnLastGame = new List <Card>(Game.PlayerDrawn);
            }
            HsLogReader.Instance.ClearLog();
            if (!Config.Instance.KeepDecksVisible)
            {
                Game.Reset(false);
            }
            if (Game.CurrentGameStats != null && Game.CurrentGameStats.Result != GameResult.None)
            {
                Game.CurrentGameStats = null;
            }
            if (Game.CurrentGameMode == GameMode.Spectator)
            {
                SetGameMode(GameMode.None);
            }
            GameEvents.OnInMenu.Execute();
        }
        public void TagChange(IHsGameState gameState, GAME_TAG tag, int id, int value, IGame game, bool isCreationTag = false)
        {
            if (gameState.LastId != id)
            {
                if (gameState.ProposedKeyPoint != null)
                {
                    ReplayMaker.Generate(gameState.ProposedKeyPoint.Type, gameState.ProposedKeyPoint.Id, gameState.ProposedKeyPoint.Player, game);
                    gameState.ProposedKeyPoint = null;
                }
            }
            gameState.LastId = id;
            if (id > gameState.MaxId)
            {
                gameState.MaxId = id;
            }
            if (!game.Entities.ContainsKey(id))
            {
                game.Entities.Add(id, new Entity(id));
            }

            if (!gameState.DeterminedPlayers)
            {
                var entity = game.Entities[id];
                if (tag == CONTROLLER && entity.IsInHand && string.IsNullOrEmpty(entity.CardId))
                {
                    DeterminePlayers(gameState, game, value);
                }
            }

            var prevValue = game.Entities[id].GetTag(tag);

            game.Entities[id].SetTag(tag, value);

            if (isCreationTag)
            {
                var action = _tagChangeActions.FindAction(tag, game, gameState, id, value, prevValue);
                if (action != null)
                {
                    _creationTagActionQueue.Enqueue(new Tuple <int, Action>(id, action));
                }
            }
            else
            {
                _tagChangeActions.FindAction(tag, game, gameState, id, value, prevValue)?.Invoke();
            }
        }
Esempio n. 14
0
        public static void Reset(bool resetStats = true)
        {
            Logger.WriteLine(">>>>>>>>>>> Reset <<<<<<<<<<<");

            ReplayMaker.Reset();
            PlayerDrawn.Clear();
            Entities.Clear();
            PlayerId            = -1;
            OpponentId          = -1;
            SavedReplay         = false;
            PlayerHandCount     = 0;
            OpponentSecretCount = 0;
            OpponentCards.Clear();
            OpponentHandCount              = 0;
            OpponentDeckCount              = 30;
            SecondToLastUsedId             = null;
            OpponentHandAge                = new int[MaxHandSize];
            OpponentHandMarks              = new CardMark[MaxHandSize];
            OpponentStolenCardsInformation = new Card[MaxHandSize];
            OpponentSecrets.ClearSecrets();

            for (var i = 0; i < MaxHandSize; i++)
            {
                OpponentHandAge[i]   = -1;
                OpponentHandMarks[i] = CardMark.None;
            }

            // Assuming opponent has coin, corrected if we draw it
            OpponentHandMarks[DefaultCoinPosition] = CardMark.Coin;
            OpponentHandAge[DefaultCoinPosition]   = 0;
            OpponentHasCoin = true;

            SetAsideCards.Clear();
            OpponentReturnedToDeck.Clear();
            if (!IsInMenu && resetStats)
            {
                CurrentGameStats = new GameStats(GameResult.None, PlayingAgainst, PlayingAs)
                {
                    PlayerName   = PlayerName,
                    OpponentName = OpponentName
                };
            }
            hsLogLines = new List <string>();
        }
Esempio n. 15
0
        private async Task SaveReplays()
        {
            if (!_savedReplay && _game.CurrentGameStats != null)
            {
                _savedReplay = true;
                await LogIsComplete();

                var powerLog = new List <string>();
                foreach (var stored in _game.StoredPowerLogs.Where(x => x.Item1 == _game.MetaData.ServerInfo.GameHandle))
                {
                    powerLog.AddRange(stored.Item2);
                }
                powerLog.AddRange(_game.PowerLog);

                var createGameCount = 0;
                powerLog = powerLog.TakeWhile(x => !(x.Contains("CREATE_GAME") && createGameCount++ == 1)).ToList();

                if (Config.Instance.RecordReplays && RecordCurrentGameMode && _game.Entities.Count > 0 && !_game.SavedReplay &&
                    _game.CurrentGameStats.ReplayFile == null)
                {
                    _game.CurrentGameStats.ReplayFile = ReplayMaker.SaveToDisk(_game.CurrentGameStats, powerLog);
                }

                if (Config.Instance.HsReplayAutoUpload && UploadCurrentGameMode)
                {
                    var log = powerLog.ToArray();
                    var validationResult = LogValidator.Validate(log);
                    if (validationResult.IsValid)
                    {
                        LogUploader.Upload(log, (GameMetaData)_game.MetaData.Clone(), _game.CurrentGameStats).Forget();
                    }
                    else
                    {
                        Log.Error("Invalid log: " + validationResult.Reason);
                        Influx.OnEndOfGameUploadError(validationResult.Reason);
                    }
                }
            }
        }
Esempio n. 16
0
        public void Reset(bool resetStats = true)
        {
            Log.Info("-------- Reset ---------");

            ReplayMaker.Reset();
            Player.Reset();
            Opponent.Reset();
            if (!_matchInfoCacheInvalid && MatchInfo?.LocalPlayer != null && MatchInfo.OpposingPlayer != null)
            {
                Player.Name   = MatchInfo.LocalPlayer.Name;
                Opponent.Name = MatchInfo.OpposingPlayer.Name;
                Player.Id     = MatchInfo.LocalPlayer.Id;
                Opponent.Id   = MatchInfo.OpposingPlayer.Id;
            }
            Entities.Clear();
            SavedReplay         = false;
            OpponentSecretCount = 0;
            OpponentSecrets.ClearSecrets();
            _spectator       = null;
            _currentGameMode = GameMode.None;
            _currentGameType = GameType.GT_UNKNOWN;
            _currentFormat   = FormatType.FT_UNKNOWN;
            if (!IsInMenu && resetStats)
            {
                CurrentGameStats = new GameStats(GameResult.None, "", "")
                {
                    PlayerName = "", OpponentName = "", Region = CurrentRegion
                }
            }
            ;
            PowerLog.Clear();

            if (Core.Game != null && Core.Overlay != null)
            {
                Core.UpdatePlayerCards(true);
                Core.UpdateOpponentCards(true);
            }
        }
Esempio n. 17
0
        public void TagChange(IHsGameState gameState, GameTag tag, int id, int value, IGame game, bool isCreationTag = false)
        {
            if (!game.Entities.ContainsKey(id))
            {
                game.Entities.Add(id, new Entity(id));
            }
            var prevValue = game.Entities[id].GetTag(tag);

            if (value == prevValue)
            {
                return;
            }
            if (gameState.LastId != id)
            {
                if (gameState.ProposedKeyPoint != null)
                {
                    ReplayMaker.Generate(gameState.ProposedKeyPoint.Type, gameState.ProposedKeyPoint.Id, gameState.ProposedKeyPoint.Player, game);
                    gameState.ProposedKeyPoint = null;
                }
            }
            gameState.LastId = id;

            game.Entities[id].SetTag(tag, value);

            if (isCreationTag)
            {
                var action = _tagChangeActions.FindAction(tag, game, gameState, id, value, prevValue);
                if (action != null)
                {
                    _creationTagActionQueue.Enqueue(new Tuple <int, Action>(id, action));
                }
            }
            else
            {
                _tagChangeActions.FindAction(tag, game, gameState, id, value, prevValue)?.Invoke();
            }
        }
        public void TagChange(IHsGameState gameState, string rawTag, int id, string rawValue, IGame game, bool isRecursive = false)
        {
            if (gameState.LastId != id)
            {
                game.SecondToLastUsedId = gameState.LastId;
                if (gameState.ProposedKeyPoint != null)
                {
                    ReplayMaker.Generate(gameState.ProposedKeyPoint.Type, gameState.ProposedKeyPoint.Id, gameState.ProposedKeyPoint.Player, game);
                    gameState.ProposedKeyPoint = null;
                }
            }
            gameState.LastId = id;
            if (!game.Entities.ContainsKey(id))
            {
                game.Entities.Add(id, new Entity(id));
            }
            GAME_TAG tag;

            if (!Enum.TryParse(rawTag, out tag))
            {
                int tmp;
                if (int.TryParse(rawTag, out tmp) && Enum.IsDefined(typeof(GAME_TAG), tmp))
                {
                    tag = (GAME_TAG)tmp;
                }
            }
            var value    = HsLogReaderV2.ParseTagValue(tag, rawValue);
            var prevZone = game.Entities[id].GetTag(GAME_TAG.ZONE);

            game.Entities[id].SetTag(tag, value);

            if (tag == GAME_TAG.CONTROLLER && gameState.WaitForController != null && game.PlayerId == -1)
            {
                var p1 = game.Entities.FirstOrDefault(e => e.Value.GetTag(GAME_TAG.PLAYER_ID) == 1).Value;
                var p2 = game.Entities.FirstOrDefault(e => e.Value.GetTag(GAME_TAG.PLAYER_ID) == 2).Value;
                if (gameState.CurrentEntityHasCardId)
                {
                    if (p1 != null)
                    {
                        p1.IsPlayer = value == 1;
                    }
                    if (p2 != null)
                    {
                        p2.IsPlayer = value != 1;
                    }
                    game.PlayerId   = value;
                    game.OpponentId = value == 1 ? 2 : 1;
                }
                else
                {
                    if (p1 != null)
                    {
                        p1.IsPlayer = value != 1;
                    }
                    if (p2 != null)
                    {
                        p2.IsPlayer = value == 1;
                    }
                    game.PlayerId   = value == 1 ? 2 : 1;
                    game.OpponentId = value;
                }
            }
            var controller = game.Entities[id].GetTag(GAME_TAG.CONTROLLER);
            var player     = game.Entities[id].HasTag(GAME_TAG.CONTROLLER) ? (controller == game.PlayerId ? "FRIENDLY" : "OPPOSING") : "";
            var cardId     = game.Entities[id].CardId;

            if (tag == GAME_TAG.ZONE)
            {
                //Logger.WriteLine("--------" + player + " " + game.Entities[id].CardId + " " + (TAG_ZONE)prevZone + " -> " +
                //                 (TAG_ZONE)value);

                if (((TAG_ZONE)value == TAG_ZONE.HAND || ((TAG_ZONE)value == TAG_ZONE.PLAY) && game.IsMulliganDone) && gameState.WaitForController == null)
                {
                    if (!game.IsMulliganDone)
                    {
                        prevZone = (int)TAG_ZONE.DECK;
                    }
                    if (controller == 0)
                    {
                        game.Entities[id].SetTag(GAME_TAG.ZONE, prevZone);
                        gameState.WaitForController = new { Tag = rawTag, Id = id, Value = rawValue };
                        //Logger.WriteLine("CURRENTLY NO CONTROLLER SET FOR CARD, WAITING...");
                        return;
                    }
                }
                switch ((TAG_ZONE)prevZone)
                {
                case TAG_ZONE.DECK:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.HAND:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerDraw(cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Draw, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentDraw(gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Draw, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.REMOVEDFROMGAME:
                    case TAG_ZONE.GRAVEYARD:
                    case TAG_ZONE.SETASIDE:
                    case TAG_ZONE.PLAY:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerDeckDiscard(cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.DeckDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentDeckDiscard(cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.DeckDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.SECRET:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerSecretPlayed(cardId, gameState.GetTurnNumber(), true);
                            gameState.ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentSecretPlayed(cardId, -1, gameState.GetTurnNumber(), true, id);
                            gameState.ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Player);
                        }
                        break;
                    }
                    break;

                case TAG_ZONE.HAND:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.PLAY:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerPlay(cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Play, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentPlay(cardId, game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION), gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Play, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.REMOVEDFROMGAME:
                    case TAG_ZONE.GRAVEYARD:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerHandDiscard(cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.HandDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentHandDiscard(cardId, game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION), gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.HandDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.SECRET:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerSecretPlayed(cardId, gameState.GetTurnNumber(), false);
                            gameState.ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentSecretPlayed(cardId, game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION), gameState.GetTurnNumber(), false, id);
                            gameState.ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.DECK:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerMulligan(cardId);
                            gameState.ProposeKeyPoint(KeyPointType.Mulligan, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentMulligan(game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION));
                            gameState.ProposeKeyPoint(KeyPointType.Mulligan, id, ActivePlayer.Opponent);
                        }
                        break;
                    }
                    break;

                case TAG_ZONE.PLAY:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.HAND:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerBackToHand(cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.PlayToHand, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentPlayToHand(cardId, gameState.GetTurnNumber(), id);
                            gameState.ProposeKeyPoint(KeyPointType.PlayToHand, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.DECK:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerPlayToDeck(cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.PlayToDeck, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentPlayToDeck(cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.PlayToDeck, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.GRAVEYARD:
                        if (game.Entities[id].HasTag(GAME_TAG.HEALTH))
                        {
                            if (controller == game.PlayerId)
                            {
                                gameState.ProposeKeyPoint(KeyPointType.Death, id, ActivePlayer.Player);
                            }
                            else if (controller == game.OpponentId)
                            {
                                gameState.ProposeKeyPoint(KeyPointType.Death, id, ActivePlayer.Opponent);
                            }
                        }
                        break;
                    }
                    break;

                case TAG_ZONE.SECRET:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.SECRET:
                    case TAG_ZONE.GRAVEYARD:
                        if (controller == game.PlayerId)
                        {
                            gameState.ProposeKeyPoint(KeyPointType.SecretTriggered, id, ActivePlayer.Player);
                        }
                        if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentSecretTrigger(cardId, gameState.GetTurnNumber(), id);
                            gameState.ProposeKeyPoint(KeyPointType.SecretTriggered, id, ActivePlayer.Opponent);
                        }
                        break;
                    }
                    break;

                case TAG_ZONE.GRAVEYARD:
                case TAG_ZONE.SETASIDE:
                case TAG_ZONE.CREATED:
                case TAG_ZONE.INVALID:
                case TAG_ZONE.REMOVEDFROMGAME:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.PLAY:
                        if (controller == game.PlayerId)
                        {
                            gameState.ProposeKeyPoint(KeyPointType.Summon, id, ActivePlayer.Player);
                        }
                        if (controller == game.OpponentId)
                        {
                            gameState.ProposeKeyPoint(KeyPointType.Summon, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.HAND:
                        if (controller == game.PlayerId)
                        {
                            gameState.GameHandler.HandlePlayerGet(cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Obtain, id, ActivePlayer.Player);
                        }
                        else if (controller == game.OpponentId)
                        {
                            gameState.GameHandler.HandleOpponentGet(gameState.GetTurnNumber(), id);
                            gameState.ProposeKeyPoint(KeyPointType.Obtain, id, ActivePlayer.Opponent);
                        }
                        break;
                    }
                    break;
                }
            }
            else if (tag == GAME_TAG.PLAYSTATE)
            {
                if (value == (int)TAG_PLAYSTATE.QUIT)
                {
                    gameState.GameHandler.HandleConcede();
                }
                if (!gameState.GameEnded)
                {
                    if (game.Entities[id].IsPlayer)
                    {
                        if (value == (int)TAG_PLAYSTATE.WON)
                        {
                            gameState.GameEndKeyPoint(true, id);
                            gameState.GameHandler.HandleWin();
                            gameState.GameHandler.HandleGameEnd();
                            gameState.GameEnded = true;
                        }
                        else if (value == (int)TAG_PLAYSTATE.LOST)
                        {
                            gameState.GameEndKeyPoint(false, id);
                            gameState.GameHandler.HandleLoss();
                            gameState.GameHandler.HandleGameEnd();
                            gameState.GameEnded = true;
                        }
                        else if (value == (int)TAG_PLAYSTATE.TIED)
                        {
                            gameState.GameEndKeyPoint(false, id);
                            gameState.GameHandler.HandleTied();
                            gameState.GameHandler.HandleGameEnd();
                        }
                    }
                }
            }
            else if (tag == GAME_TAG.CURRENT_PLAYER && value == 1)
            {
                var activePlayer = game.Entities[id].IsPlayer ? ActivePlayer.Player : ActivePlayer.Opponent;
                gameState.GameHandler.TurnStart(activePlayer, gameState.GetTurnNumber());
                if (activePlayer == ActivePlayer.Player)
                {
                    gameState.PlayerUsedHeroPower = false;
                }
                else
                {
                    gameState.OpponentUsedHeroPower = false;
                }
            }
            else if (tag == GAME_TAG.NUM_ATTACKS_THIS_TURN && value > 0)
            {
                if (controller == game.PlayerId)
                {
                    gameState.ProposeKeyPoint(KeyPointType.Attack, id, ActivePlayer.Player);
                }
                else if (controller == game.OpponentId)
                {
                    gameState.ProposeKeyPoint(KeyPointType.Attack, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == GAME_TAG.ZONE_POSITION)
            {
                var zone = game.Entities[id].GetTag(GAME_TAG.ZONE);
                if (zone == (int)TAG_ZONE.HAND)
                {
                    if (controller == game.PlayerId)
                    {
                        ReplayMaker.Generate(KeyPointType.HandPos, id, ActivePlayer.Player, game);
                    }
                    else if (controller == game.OpponentId)
                    {
                        ReplayMaker.Generate(KeyPointType.HandPos, id, ActivePlayer.Opponent, game);
                    }
                }
                else if (zone == (int)TAG_ZONE.PLAY)
                {
                    if (controller == game.PlayerId)
                    {
                        ReplayMaker.Generate(KeyPointType.BoardPos, id, ActivePlayer.Player, game);
                    }
                    else if (controller == game.OpponentId)
                    {
                        ReplayMaker.Generate(KeyPointType.BoardPos, id, ActivePlayer.Opponent, game);
                    }
                }
            }
            else if (tag == GAME_TAG.CARD_TARGET && value > 0)
            {
                if (controller == game.PlayerId)
                {
                    gameState.ProposeKeyPoint(KeyPointType.PlaySpell, id, ActivePlayer.Player);
                }
                else if (controller == game.OpponentId)
                {
                    gameState.ProposeKeyPoint(KeyPointType.PlaySpell, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == GAME_TAG.EQUIPPED_WEAPON && value == 0)
            {
                if (controller == game.PlayerId)
                {
                    gameState.ProposeKeyPoint(KeyPointType.WeaponDestroyed, id, ActivePlayer.Player);
                }
                else if (controller == game.OpponentId)
                {
                    gameState.ProposeKeyPoint(KeyPointType.WeaponDestroyed, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == GAME_TAG.EXHAUSTED && value > 0)
            {
                if (game.Entities[id].GetTag(GAME_TAG.CARDTYPE) == (int)TAG_CARDTYPE.HERO_POWER)
                {
                    if (controller == game.PlayerId)
                    {
                        gameState.ProposeKeyPoint(KeyPointType.HeroPower, id, ActivePlayer.Player);
                    }
                    else if (controller == game.OpponentId)
                    {
                        gameState.ProposeKeyPoint(KeyPointType.HeroPower, id, ActivePlayer.Opponent);
                    }
                }
            }
            else if (tag == GAME_TAG.CONTROLLER && game.Entities[id].IsInZone(TAG_ZONE.SECRET))
            {
                if (value == game.PlayerId)
                {
                    gameState.GameHandler.HandleOpponentSecretTrigger(cardId, gameState.GetTurnNumber(), id);
                    gameState.ProposeKeyPoint(KeyPointType.SecretStolen, id, ActivePlayer.Player);
                }
                else if (value == game.OpponentId)
                {
                    gameState.ProposeKeyPoint(KeyPointType.SecretStolen, id, ActivePlayer.Player);
                }
            }
            else if (tag == GAME_TAG.FATIGUE)
            {
                if (controller == game.PlayerId)
                {
                    gameState.GameHandler.HandlePlayerFatigue(Convert.ToInt32(rawValue));
                }
                else if (controller == game.OpponentId)
                {
                    gameState.GameHandler.HandleOpponentFatigue(Convert.ToInt32(rawValue));
                }
            }
            if (gameState.WaitForController != null)
            {
                if (!isRecursive)
                {
                    TagChange(gameState, (string)gameState.WaitForController.Tag, (int)gameState.WaitForController.Id, (string)gameState.WaitForController.Value, game, true);
                    gameState.WaitForController = null;
                }
            }
        }
Esempio n. 19
0
        public void TagChange(IHsGameState gameState, string rawTag, int id, string rawValue, IGame game, bool isRecursive = false)
        {
            if (gameState.LastId != id)
            {
                //game.SecondToLastUsedId = gameState.LastId;
                if (gameState.ProposedKeyPoint != null)
                {
                    ReplayMaker.Generate(gameState.ProposedKeyPoint.Type, gameState.ProposedKeyPoint.Id, gameState.ProposedKeyPoint.Player, game);
                    gameState.ProposedKeyPoint = null;
                }
            }
            gameState.LastId = id;
            if (id > gameState.MaxId)
            {
                gameState.MaxId = id;
            }
            if (!game.Entities.ContainsKey(id))
            {
                game.Entities.Add(id, new Entity(id));
            }
            GAME_TAG tag;

            if (!Enum.TryParse(rawTag, out tag))
            {
                int tmp;
                if (int.TryParse(rawTag, out tmp) && Enum.IsDefined(typeof(GAME_TAG), tmp))
                {
                    tag = (GAME_TAG)tmp;
                }
            }
            var value     = LogReaderHelper.ParseTagValue(tag, rawValue);
            var prevValue = game.Entities[id].GetTag(tag);

            game.Entities[id].SetTag(tag, value);


            if (tag == CONTROLLER && gameState.WaitForController != null && game.Player.Id == -1)
            {
                var p1 = game.Entities.FirstOrDefault(e => e.Value.GetTag(PLAYER_ID) == 1).Value;
                var p2 = game.Entities.FirstOrDefault(e => e.Value.GetTag(PLAYER_ID) == 2).Value;
                if (gameState.CurrentEntityHasCardId)
                {
                    if (p1 != null)
                    {
                        p1.IsPlayer = value == 1;
                    }
                    if (p2 != null)
                    {
                        p2.IsPlayer = value != 1;
                    }
                    game.Player.Id   = value;
                    game.Opponent.Id = value % 2 + 1;
                }
                else
                {
                    if (p1 != null)
                    {
                        p1.IsPlayer = value != 1;
                    }
                    if (p2 != null)
                    {
                        p2.IsPlayer = value == 1;
                    }
                    game.Player.Id   = value % 2 + 1;
                    game.Opponent.Id = value;
                }
            }
            var controller = game.Entities[id].GetTag(CONTROLLER);
            var cardId     = game.Entities[id].CardId;

            if (tag == ZONE)
            {
                if (((TAG_ZONE)value == HAND ||
                     ((TAG_ZONE)value == PLAY || (TAG_ZONE)value == DECK) && game.IsMulliganDone) &&
                    gameState.WaitForController == null)
                {
                    if (!game.IsMulliganDone)
                    {
                        prevValue = (int)DECK;
                    }
                    if (controller == 0)
                    {
                        game.Entities[id].SetTag(ZONE, prevValue);
                        gameState.WaitForController = new { Tag = rawTag, Id = id, Value = rawValue };
                        return;
                    }
                }
                switch ((TAG_ZONE)prevValue)
                {
                case DECK:
                    switch ((TAG_ZONE)value)
                    {
                    case HAND:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerDraw(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(Draw, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            if (!string.IsNullOrEmpty(game.Entities[id].CardId))
                            {
#if DEBUG
                                Log.Debug($"Opponent Draw (EntityID={id}) already has a CardID. Removing. Blizzard Pls.");
#endif
                                game.Entities[id].CardId = string.Empty;
                            }
                            gameState.GameHandler.HandleOpponentDraw(game.Entities[id], gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(Draw, id, ActivePlayer.Opponent);
                        }
                        break;

                    case SETASIDE:
                    case REMOVEDFROMGAME:
                        if (controller == game.Player.Id)
                        {
                            if (gameState.JoustReveals > 0)
                            {
                                gameState.JoustReveals--;
                                break;
                            }
                            gameState.GameHandler.HandlePlayerRemoveFromDeck(game.Entities[id], gameState.GetTurnNumber());
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            if (gameState.JoustReveals > 0)
                            {
                                gameState.JoustReveals--;
                                break;
                            }
                            gameState.GameHandler.HandleOpponentRemoveFromDeck(game.Entities[id], gameState.GetTurnNumber());
                        }
                        break;

                    case GRAVEYARD:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerDeckDiscard(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(DeckDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentDeckDiscard(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(DeckDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case PLAY:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerDeckToPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(DeckDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentDeckToPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(DeckDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.SECRET:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerSecretPlayed(game.Entities[id], cardId, gameState.GetTurnNumber(), true);
                            gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentSecretPlayed(game.Entities[id], cardId, -1, gameState.GetTurnNumber(), true, id);
                            gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Player);
                        }
                        break;

                    default:
                        Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}");
                        break;
                    }
                    break;

                case HAND:
                    switch ((TAG_ZONE)value)
                    {
                    case PLAY:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(Play, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentPlay(game.Entities[id], cardId, game.Entities[id].GetTag(ZONE_POSITION),
                                                                     gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(Play, id, ActivePlayer.Opponent);
                        }
                        break;

                    case REMOVEDFROMGAME:
                    case SETASIDE:
                    case GRAVEYARD:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerHandDiscard(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(HandDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentHandDiscard(game.Entities[id], cardId, game.Entities[id].GetTag(ZONE_POSITION),
                                                                            gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(HandDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.SECRET:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerSecretPlayed(game.Entities[id], cardId, gameState.GetTurnNumber(), false);
                            gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentSecretPlayed(game.Entities[id], cardId, game.Entities[id].GetTag(ZONE_POSITION),
                                                                             gameState.GetTurnNumber(), false, id);
                            gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Opponent);
                        }
                        break;

                    case DECK:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerMulligan(game.Entities[id], cardId);
                            gameState.ProposeKeyPoint(Mulligan, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentMulligan(game.Entities[id], game.Entities[id].GetTag(ZONE_POSITION));
                            gameState.ProposeKeyPoint(Mulligan, id, ActivePlayer.Opponent);
                        }
                        break;

                    default:
                        Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}");
                        break;
                    }
                    break;

                case PLAY:
                    switch ((TAG_ZONE)value)
                    {
                    case HAND:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerBackToHand(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(PlayToHand, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentPlayToHand(game.Entities[id], cardId, gameState.GetTurnNumber(), id);
                            gameState.ProposeKeyPoint(PlayToHand, id, ActivePlayer.Opponent);
                        }
                        break;

                    case DECK:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerPlayToDeck(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(PlayToDeck, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentPlayToDeck(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(PlayToDeck, id, ActivePlayer.Opponent);
                        }
                        break;

                    case REMOVEDFROMGAME:
                    case SETASIDE:
                    case GRAVEYARD:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerPlayToGraveyard(game.Entities[id], cardId, gameState.GetTurnNumber());
                            if (game.Entities[id].HasTag(HEALTH))
                            {
                                gameState.ProposeKeyPoint(Death, id, ActivePlayer.Player);
                            }
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentPlayToGraveyard(game.Entities[id], cardId, gameState.GetTurnNumber(),
                                                                                gameState.PlayersTurn());
                            if (game.Entities[id].HasTag(HEALTH))
                            {
                                gameState.ProposeKeyPoint(Death, id, ActivePlayer.Opponent);
                            }
                        }
                        break;

                    default:
                        Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}");
                        break;
                    }
                    break;

                case TAG_ZONE.SECRET:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.SECRET:
                    case GRAVEYARD:
                        if (controller == game.Player.Id)
                        {
                            gameState.ProposeKeyPoint(SecretTriggered, id, ActivePlayer.Player);
                        }
                        if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentSecretTrigger(game.Entities[id], cardId, gameState.GetTurnNumber(), id);
                            gameState.ProposeKeyPoint(SecretTriggered, id, ActivePlayer.Opponent);
                        }
                        break;

                    default:
                        Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}");
                        break;
                    }
                    break;

                case GRAVEYARD:
                case SETASIDE:
                case CREATED:
                case TAG_ZONE.INVALID:
                case REMOVEDFROMGAME:
                    switch ((TAG_ZONE)value)
                    {
                    case PLAY:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerCreateInPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(Summon, id, ActivePlayer.Player);
                        }
                        if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentCreateInPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(Summon, id, ActivePlayer.Opponent);
                        }
                        break;

                    case DECK:
                        if (controller == game.Player.Id)
                        {
                            if (gameState.JoustReveals > 0)
                            {
                                break;
                            }
                            gameState.GameHandler.HandlePlayerGetToDeck(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(CreateToDeck, id, ActivePlayer.Player);
                        }
                        if (controller == game.Opponent.Id)
                        {
                            if (gameState.JoustReveals > 0)
                            {
                                break;
                            }
                            gameState.GameHandler.HandleOpponentGetToDeck(game.Entities[id], gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(CreateToDeck, id, ActivePlayer.Opponent);
                        }
                        break;

                    case HAND:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerGet(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(Obtain, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentGet(game.Entities[id], gameState.GetTurnNumber(), id);
                            gameState.ProposeKeyPoint(Obtain, id, ActivePlayer.Opponent);
                        }
                        break;

                    default:
                        Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}");
                        break;
                    }
                    break;

                default:
                    Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}");
                    break;
                }
            }
            else if (tag == PLAYSTATE)
            {
                if (value == (int)CONCEDED)
                {
                    gameState.GameHandler.HandleConcede();
                }
                if (!gameState.GameEnded)
                {
                    if (game.Entities[id].IsPlayer)
                    {
                        switch ((TAG_PLAYSTATE)value)
                        {
                        case WON:
                            gameState.GameEndKeyPoint(true, id);
                            gameState.GameHandler.HandleWin();
                            gameState.GameHandler.HandleGameEnd();
                            gameState.GameEnded = true;
                            break;

                        case LOST:
                            gameState.GameEndKeyPoint(false, id);
                            gameState.GameHandler.HandleLoss();
                            gameState.GameHandler.HandleGameEnd();
                            gameState.GameEnded = true;
                            break;

                        case TIED:
                            gameState.GameEndKeyPoint(false, id);
                            gameState.GameHandler.HandleTied();
                            gameState.GameHandler.HandleGameEnd();
                            break;
                        }
                    }
                }
            }
            else if (tag == CARDTYPE && value == (int)TAG_CARDTYPE.HERO)
            {
                SetHeroAsync(id, game, gameState);
            }
            else if (tag == CURRENT_PLAYER && value == 1)
            {
                var activePlayer = game.Entities[id].IsPlayer ? ActivePlayer.Player : ActivePlayer.Opponent;
                gameState.GameHandler.TurnStart(activePlayer, gameState.GetTurnNumber());
                if (activePlayer == ActivePlayer.Player)
                {
                    gameState.PlayerUsedHeroPower = false;
                }
                else
                {
                    gameState.OpponentUsedHeroPower = false;
                }
            }
            else if (tag == LAST_CARD_PLAYED)
            {
                gameState.LastCardPlayed = value;
            }
            else if (tag == DEFENDING)
            {
                if (controller == game.Opponent.Id)
                {
                    gameState.GameHandler.HandleDefendingEntity(value == 1 ? game.Entities[id] : null);
                }
            }
            else if (tag == ATTACKING)
            {
                if (controller == game.Player.Id)
                {
                    gameState.GameHandler.HandleAttackingEntity(value == 1 ? game.Entities[id] : null);
                }
            }
            else if (tag == PROPOSED_DEFENDER)
            {
                game.OpponentSecrets.ProposedDefenderEntityId = value;
            }
            else if (tag == PROPOSED_ATTACKER)
            {
                game.OpponentSecrets.ProposedAttackerEntityId = value;
            }
            else if (tag == NUM_MINIONS_PLAYED_THIS_TURN && value > 0)
            {
                if (gameState.PlayersTurn())
                {
                    gameState.GameHandler.HandlePlayerMinionPlayed();
                }
            }
            else if (tag == PREDAMAGE && value > 0)
            {
                if (gameState.PlayersTurn())
                {
                    gameState.GameHandler.HandleOpponentDamage(game.Entities[id]);
                }
            }
            else if (tag == NUM_TURNS_IN_PLAY && value > 0)
            {
                if (!gameState.PlayersTurn())
                {
                    gameState.GameHandler.HandleOpponentTurnStart(game.Entities[id]);
                }
            }
            else if (tag == NUM_ATTACKS_THIS_TURN && value > 0)
            {
                if (controller == game.Player.Id)
                {
                    gameState.ProposeKeyPoint(Attack, id, ActivePlayer.Player);
                }
                else if (controller == game.Opponent.Id)
                {
                    gameState.ProposeKeyPoint(Attack, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == ZONE_POSITION)
            {
                var entity = game.Entities[id];
                var zone   = entity.GetTag(ZONE);
                if (zone == (int)HAND)
                {
                    if (controller == game.Player.Id)
                    {
                        ReplayMaker.Generate(HandPos, id, ActivePlayer.Player, game);
                        gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Player, entity, HAND, gameState.GetTurnNumber());
                    }
                    else if (controller == game.Opponent.Id)
                    {
                        ReplayMaker.Generate(HandPos, id, ActivePlayer.Opponent, game);
                        gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Opponent, entity, HAND, gameState.GetTurnNumber());
                    }
                }
                else if (zone == (int)PLAY)
                {
                    if (controller == game.Player.Id)
                    {
                        ReplayMaker.Generate(BoardPos, id, ActivePlayer.Player, game);
                        gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Player, entity, PLAY, gameState.GetTurnNumber());
                    }
                    else if (controller == game.Opponent.Id)
                    {
                        ReplayMaker.Generate(BoardPos, id, ActivePlayer.Opponent, game);
                        gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Opponent, entity, PLAY, gameState.GetTurnNumber());
                    }
                }
            }
            else if (tag == CARD_TARGET && value > 0)
            {
                if (controller == game.Player.Id)
                {
                    gameState.ProposeKeyPoint(PlaySpell, id, ActivePlayer.Player);
                }
                else if (controller == game.Opponent.Id)
                {
                    gameState.ProposeKeyPoint(PlaySpell, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == EQUIPPED_WEAPON && value == 0)
            {
                if (controller == game.Player.Id)
                {
                    gameState.ProposeKeyPoint(WeaponDestroyed, id, ActivePlayer.Player);
                }
                else if (controller == game.Opponent.Id)
                {
                    gameState.ProposeKeyPoint(WeaponDestroyed, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == EXHAUSTED && value > 0)
            {
                if (game.Entities[id].GetTag(CARDTYPE) == (int)TAG_CARDTYPE.HERO_POWER)
                {
                    if (controller == game.Player.Id)
                    {
                        gameState.ProposeKeyPoint(HeroPower, id, ActivePlayer.Player);
                    }
                    else if (controller == game.Opponent.Id)
                    {
                        gameState.ProposeKeyPoint(HeroPower, id, ActivePlayer.Opponent);
                    }
                }
            }
            else if (tag == CONTROLLER && prevValue > 0)
            {
                if (value == game.Player.Id)
                {
                    if (game.Entities[id].IsInZone(TAG_ZONE.SECRET))
                    {
                        gameState.GameHandler.HandleOpponentStolen(game.Entities[id], cardId, gameState.GetTurnNumber());
                        gameState.ProposeKeyPoint(SecretStolen, id, ActivePlayer.Player);
                    }
                    else if (game.Entities[id].IsInZone(PLAY))
                    {
                        gameState.GameHandler.HandleOpponentStolen(game.Entities[id], cardId, gameState.GetTurnNumber());
                    }
                }
                else if (value == game.Opponent.Id)
                {
                    if (game.Entities[id].IsInZone(TAG_ZONE.SECRET))
                    {
                        gameState.GameHandler.HandleOpponentStolen(game.Entities[id], cardId, gameState.GetTurnNumber());
                        gameState.ProposeKeyPoint(SecretStolen, id, ActivePlayer.Player);
                    }
                    else if (game.Entities[id].IsInZone(PLAY))
                    {
                        gameState.GameHandler.HandlePlayerStolen(game.Entities[id], cardId, gameState.GetTurnNumber());
                    }
                }
            }
            else if (tag == FATIGUE)
            {
                if (controller == game.Player.Id)
                {
                    gameState.GameHandler.HandlePlayerFatigue(Convert.ToInt32(rawValue));
                }
                else if (controller == game.Opponent.Id)
                {
                    gameState.GameHandler.HandleOpponentFatigue(Convert.ToInt32(rawValue));
                }
            }
            if (gameState.WaitForController != null)
            {
                if (!isRecursive)
                {
                    TagChange(gameState, (string)gameState.WaitForController.Tag, (int)gameState.WaitForController.Id,
                              (string)gameState.WaitForController.Value, game, true);
                    gameState.WaitForController = null;
                }
            }
        }
        private void TagChange(string rawTag, int id, string rawValue, bool isRecursive = false)
        {
            if (_lastId != id)
            {
                Game.SecondToLastUsedId = _lastId;
                if (_proposedKeyPoint != null)
                {
                    ReplayMaker.Generate(_proposedKeyPoint.Type, _proposedKeyPoint.Id, _proposedKeyPoint.Player);
                    _proposedKeyPoint = null;
                }
            }
            _lastId = id;
            if (!Game.Entities.ContainsKey(id))
            {
                Game.Entities.Add(id, new Entity(id));
            }
            GAME_TAG tag;

            if (!Enum.TryParse(rawTag, out tag))
            {
                int tmp;
                if (int.TryParse(rawTag, out tmp) && Enum.IsDefined(typeof(GAME_TAG), tmp))
                {
                    tag = (GAME_TAG)tmp;
                }
            }
            var value    = ParseTagValue(tag, rawValue);
            var prevZone = Game.Entities[id].GetTag(GAME_TAG.ZONE);

            Game.Entities[id].SetTag(tag, value);

            if (tag == GAME_TAG.CONTROLLER && _waitForController != null && Game.PlayerId == -1)
            {
                if (_currentEntityHasCardId)
                {
                    Game.Entities.First(e => e.Value.GetTag(GAME_TAG.PLAYER_ID) == 1).Value.IsPlayer = value == 1;
                    Game.Entities.First(e => e.Value.GetTag(GAME_TAG.PLAYER_ID) == 2).Value.IsPlayer = value != 1;
                    Game.PlayerId   = value;
                    Game.OpponentId = value == 1 ? 2 : 1;
                }
                else
                {
                    Game.Entities.First(e => e.Value.GetTag(GAME_TAG.PLAYER_ID) == 1).Value.IsPlayer = value != 1;
                    Game.Entities.First(e => e.Value.GetTag(GAME_TAG.PLAYER_ID) == 2).Value.IsPlayer = value == 1;
                    Game.PlayerId   = value == 1 ? 2 : 1;
                    Game.OpponentId = value;
                }
            }
            var    controller = Game.Entities[id].GetTag(GAME_TAG.CONTROLLER);
            string player     = Game.Entities[id].HasTag(GAME_TAG.CONTROLLER)
                                                ? (controller == Game.PlayerId ? "FRIENDLY" : "OPPOSING")
                                                : "";
            var cardId = Game.Entities[id].CardId;

            if (tag == GAME_TAG.ZONE)
            {
                //Logger.WriteLine("--------" + player + " " + Game.Entities[id].CardId + " " + (TAG_ZONE)prevZone + " -> " +
                //                 (TAG_ZONE)value);

                if (((TAG_ZONE)value == TAG_ZONE.HAND || ((TAG_ZONE)value == TAG_ZONE.PLAY) && Game.IsMulliganDone) &&
                    _waitForController == null)
                {
                    if (!Game.IsMulliganDone)
                    {
                        prevZone = (int)TAG_ZONE.DECK;
                    }
                    if (controller == 0)
                    {
                        Game.Entities[id].SetTag(GAME_TAG.ZONE, prevZone);
                        _waitForController = new { Tag = rawTag, Id = id, Value = rawValue };
                        //Logger.WriteLine("CURRENTLY NO CONTROLLER SET FOR CARD, WAITING...");
                        return;
                    }
                }
                switch ((TAG_ZONE)prevZone)
                {
                case TAG_ZONE.DECK:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.HAND:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerDraw(cardId, GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.Draw, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentDraw(GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.Draw, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.REMOVEDFROMGAME:
                    case TAG_ZONE.GRAVEYARD:
                    case TAG_ZONE.SETASIDE:
                    case TAG_ZONE.PLAY:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerDeckDiscard(cardId, GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.DeckDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentDeckDiscard(cardId, GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.DeckDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.SECRET:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerSecretPlayed(cardId, GetTurnNumber(), true);
                            ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentSecretPlayed(cardId, -1, GetTurnNumber(), true, id);
                            ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Player);
                        }
                        break;
                    }
                    break;

                case TAG_ZONE.GRAVEYARD:
                    break;

                case TAG_ZONE.HAND:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.PLAY:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerPlay(cardId, GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.Play, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentPlay(cardId, Game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION), GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.Play, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.REMOVEDFROMGAME:
                    case TAG_ZONE.GRAVEYARD:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerHandDiscard(cardId, GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.HandDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentHandDiscard(cardId, Game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION),
                                                                   GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.HandDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.SECRET:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerSecretPlayed(cardId, GetTurnNumber(), false);
                            ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentSecretPlayed(cardId, Game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION),
                                                                    GetTurnNumber(), false, id);
                            ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.DECK:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerMulligan(cardId);
                            ProposeKeyPoint(KeyPointType.Mulligan, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentMulligan(Game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION));
                            ProposeKeyPoint(KeyPointType.Mulligan, id, ActivePlayer.Opponent);
                        }
                        break;
                    }
                    break;

                case TAG_ZONE.PLAY:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.HAND:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerBackToHand(cardId, GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.PlayToHand, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentPlayToHand(cardId, GetTurnNumber(), id);
                            ProposeKeyPoint(KeyPointType.PlayToHand, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.DECK:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerPlayToDeck(cardId, GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.PlayToDeck, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentPlayToDeck(cardId, GetTurnNumber());
                        }
                        ProposeKeyPoint(KeyPointType.PlayToDeck, id, ActivePlayer.Opponent);
                        break;

                    case TAG_ZONE.GRAVEYARD:
                        if (Game.Entities[id].HasTag(GAME_TAG.HEALTH))
                        {
                            if (controller == Game.PlayerId)
                            {
                                ProposeKeyPoint(KeyPointType.Death, id, ActivePlayer.Player);
                            }
                            else if (controller == Game.OpponentId)
                            {
                                ProposeKeyPoint(KeyPointType.Death, id, ActivePlayer.Opponent);
                            }
                        }
                        break;
                    }
                    break;

                case TAG_ZONE.SECRET:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.SECRET:
                    case TAG_ZONE.GRAVEYARD:
                        if (controller == Game.PlayerId)
                        {
                            ProposeKeyPoint(KeyPointType.SecretTriggered, id, ActivePlayer.Player);
                        }
                        if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentSecretTrigger(cardId, GetTurnNumber(), id);
                            ProposeKeyPoint(KeyPointType.SecretTriggered, id, ActivePlayer.Opponent);
                        }
                        break;
                    }
                    break;

                case TAG_ZONE.SETASIDE:
                case TAG_ZONE.CREATED:
                case TAG_ZONE.INVALID:
                case TAG_ZONE.REMOVEDFROMGAME:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.PLAY:
                        if (controller == Game.PlayerId)
                        {
                            ProposeKeyPoint(KeyPointType.Summon, id, ActivePlayer.Player);
                        }
                        if (controller == Game.OpponentId)
                        {
                            ProposeKeyPoint(KeyPointType.Summon, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.HAND:
                        if (controller == Game.PlayerId)
                        {
                            _gameHandler.HandlePlayerGet(cardId, GetTurnNumber());
                            ProposeKeyPoint(KeyPointType.Obtain, id, ActivePlayer.Player);
                        }
                        else if (controller == Game.OpponentId)
                        {
                            _gameHandler.HandleOpponentGet(GetTurnNumber(), id);
                            ProposeKeyPoint(KeyPointType.Obtain, id, ActivePlayer.Opponent);
                        }
                        break;
                    }
                    break;
                }
            }
            else if (tag == GAME_TAG.PLAYSTATE && !_gameEnded)
            {
                if (Game.Entities[id].IsPlayer)
                {
                    if (value == (int)TAG_PLAYSTATE.WON)
                    {
                        GameEndKeyPoint(true, id);
                        _gameHandler.HandleGameEnd();
                        _gameHandler.HandleWin(false);
                        _gameEnded = true;
                    }
                    else if (value == (int)TAG_PLAYSTATE.LOST)
                    {
                        GameEndKeyPoint(false, id);
                        _gameHandler.HandleGameEnd();
                        _gameHandler.HandleLoss(false);
                        _gameEnded = true;
                    }
                }
                else
                {
                    if (value == (int)TAG_PLAYSTATE.WON)
                    {
                        GameEndKeyPoint(false, Game.Entities.First(x => x.Value.IsPlayer).Key);
                        _gameHandler.HandleGameEnd();
                        _gameHandler.HandleLoss(false);
                        _gameEnded = true;
                    }
                    else if (value == (int)TAG_PLAYSTATE.LOST)
                    {
                        GameEndKeyPoint(true, Game.Entities.First(x => x.Value.IsPlayer).Key);
                        _gameHandler.HandleGameEnd();
                        _gameHandler.HandleWin(false);
                        _gameEnded = true;
                    }
                }
            }
            else if (tag == GAME_TAG.CURRENT_PLAYER && value == 1)
            {
                _gameHandler.TurnStart(Game.Entities[id].IsPlayer ? ActivePlayer.Player : ActivePlayer.Opponent, GetTurnNumber());
            }
            else if (tag == GAME_TAG.NUM_ATTACKS_THIS_TURN && value > 0)
            {
                if (controller == Game.PlayerId)
                {
                    ProposeKeyPoint(KeyPointType.Attack, id, ActivePlayer.Player);
                }
                else if (controller == Game.OpponentId)
                {
                    ProposeKeyPoint(KeyPointType.Attack, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == GAME_TAG.ZONE_POSITION)
            {
                var zone = Game.Entities[id].GetTag(GAME_TAG.ZONE);
                if (zone == (int)TAG_ZONE.HAND)
                {
                    if (controller == Game.PlayerId)
                    {
                        ReplayMaker.Generate(KeyPointType.HandPos, id, ActivePlayer.Player);
                    }
                    else if (controller == Game.OpponentId)
                    {
                        ReplayMaker.Generate(KeyPointType.HandPos, id, ActivePlayer.Opponent);
                    }
                }
                else if (zone == (int)TAG_ZONE.PLAY)
                {
                    if (controller == Game.PlayerId)
                    {
                        ReplayMaker.Generate(KeyPointType.BoardPos, id, ActivePlayer.Player);
                    }
                    else if (controller == Game.OpponentId)
                    {
                        ReplayMaker.Generate(KeyPointType.BoardPos, id, ActivePlayer.Opponent);
                    }
                }
            }
            else if (tag == GAME_TAG.CARD_TARGET && value > 0)
            {
                if (controller == Game.PlayerId)
                {
                    ProposeKeyPoint(KeyPointType.PlaySpell, id, ActivePlayer.Player);
                }
                else if (controller == Game.OpponentId)
                {
                    ProposeKeyPoint(KeyPointType.PlaySpell, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == GAME_TAG.EQUIPPED_WEAPON && value == 0)
            {
                if (controller == Game.PlayerId)
                {
                    ProposeKeyPoint(KeyPointType.WeaponDestroyed, id, ActivePlayer.Player);
                }
                else if (controller == Game.OpponentId)
                {
                    ProposeKeyPoint(KeyPointType.WeaponDestroyed, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == GAME_TAG.EXHAUSTED && value > 0)
            {
                if (Game.Entities[id].GetTag(GAME_TAG.CARDTYPE) == (int)TAG_CARDTYPE.HERO_POWER)
                {
                    if (controller == Game.PlayerId)
                    {
                        ProposeKeyPoint(KeyPointType.HeroPower, id, ActivePlayer.Player);
                    }
                    else if (controller == Game.OpponentId)
                    {
                        ProposeKeyPoint(KeyPointType.HeroPower, id, ActivePlayer.Opponent);
                    }
                }
            }
            else if (tag == GAME_TAG.CONTROLLER && Game.Entities[id].IsInZone(TAG_ZONE.SECRET))
            {
                if (value == Game.PlayerId)
                {
                    _gameHandler.HandleOpponentSecretTrigger(cardId, GetTurnNumber(), id);
                    ProposeKeyPoint(KeyPointType.SecretStolen, id, ActivePlayer.Player);
                }
                else if (value == Game.OpponentId)
                {
                    ProposeKeyPoint(KeyPointType.SecretStolen, id, ActivePlayer.Player);
                }
            }
            if (_waitForController != null)
            {
                if (!isRecursive)
                {
                    TagChange((string)_waitForController.Tag, (int)_waitForController.Id, (string)_waitForController.Value, true);
                    _waitForController = null;
                }
            }
        }
Esempio n. 21
0
        public void TagChange(IHsGameState gameState, string rawTag, int id, string rawValue, IGame game, bool isRecursive = false)
        {
            if (gameState.LastId != id)
            {
                //game.SecondToLastUsedId = gameState.LastId;
                if (gameState.ProposedKeyPoint != null)
                {
                    ReplayMaker.Generate(gameState.ProposedKeyPoint.Type, gameState.ProposedKeyPoint.Id, gameState.ProposedKeyPoint.Player, game);
                    gameState.ProposedKeyPoint = null;
                }
            }
            gameState.LastId = id;
            if (id > gameState.MaxId)
            {
                gameState.MaxId = id;
            }
            if (!game.Entities.ContainsKey(id))
            {
                game.Entities.Add(id, new Entity(id));
            }
            GAME_TAG tag;

            if (!Enum.TryParse(rawTag, out tag))
            {
                int tmp;
                if (int.TryParse(rawTag, out tmp) && Enum.IsDefined(typeof(GAME_TAG), tmp))
                {
                    tag = (GAME_TAG)tmp;
                }
            }
            var value     = LogReaderHelper.ParseTagValue(tag, rawValue);
            var prevValue = game.Entities[id].GetTag(tag);

            game.Entities[id].SetTag(tag, value);

            if (tag == CONTROLLER && gameState.WaitForController != null && game.Player.Id == -1)
            {
                DeterminePlayers(gameState, game, value);
            }

            var controller = game.Entities[id].GetTag(CONTROLLER);
            var cardId     = game.Entities[id].CardId;

            switch (tag)
            {
            case ZONE:
                if (((TAG_ZONE)value == HAND || ((TAG_ZONE)value == PLAY || (TAG_ZONE)value == DECK) && game.IsMulliganDone) && gameState.WaitForController == null)
                {
                    if (!game.IsMulliganDone)
                    {
                        prevValue = (int)DECK;
                    }
                    if (controller == 0)
                    {
                        game.Entities[id].SetTag(ZONE, prevValue);
                        gameState.WaitForController = new { Tag = rawTag, Id = id, Value = rawValue };
                        return;
                    }
                }
                ZoneChange(gameState, id, game, value, prevValue, controller, cardId);
                break;

            case PLAYSTATE:
                PlaystateChange(gameState, id, game, value);
                break;

            case CARDTYPE:
                CardTypeChange(gameState, id, game, value);
                break;

            case CURRENT_PLAYER:
                CurrentPlayerChange(gameState, id, game, value);
                break;

            case LAST_CARD_PLAYED:
                LastCardPlayedChange(gameState, value);
                break;

            case DEFENDING:
                DefendingChange(gameState, id, game, controller, value);
                break;

            case ATTACKING:
                AttackingChange(gameState, id, game, controller, value);
                break;

            case PROPOSED_DEFENDER:
                ProposedDefenderChange(game, value);
                break;

            case PROPOSED_ATTACKER:
                ProposedAttackerChange(game, value);
                break;

            case NUM_MINIONS_PLAYED_THIS_TURN:
                NumMinionsPlayedThisTurnChange(gameState, value);
                break;

            case PREDAMAGE:
                PredamageChange(gameState, id, game, value);
                break;

            case NUM_TURNS_IN_PLAY:
                NumTurnsInPlayChange(gameState, id, game, value);
                break;

            case NUM_ATTACKS_THIS_TURN:
                NumAttacksThisTurnChange(gameState, id, game, value, controller);
                break;

            case ZONE_POSITION:
                ZonePositionChange(gameState, id, game, controller);
                break;

            case CARD_TARGET:
                CardTargetChange(gameState, id, game, value, controller);
                break;

            case EQUIPPED_WEAPON:
                EquippedWeaponChange(gameState, id, game, value, controller);
                break;

            case EXHAUSTED:
                ExhaustedChange(gameState, id, game, value, controller);
                break;

            case CONTROLLER:
                ControllerChange(gameState, id, game, prevValue, value, cardId);
                break;

            case FATIGUE:
                FatigueChange(gameState, rawValue, game, controller);
                break;
            }
            if (gameState.WaitForController != null && !isRecursive)
            {
                TagChange(gameState, (string)gameState.WaitForController.Tag, (int)gameState.WaitForController.Id,
                          (string)gameState.WaitForController.Value, game, true);
                gameState.WaitForController = null;
            }
        }
Esempio n. 22
0
        public void TagChange(IHsGameState gameState, string rawTag, int id, string rawValue, IGame game, bool isRecursive = false)
        {
            if (gameState.LastId != id)
            {
                //game.SecondToLastUsedId = gameState.LastId;
                if (gameState.ProposedKeyPoint != null)
                {
                    ReplayMaker.Generate(gameState.ProposedKeyPoint.Type, gameState.ProposedKeyPoint.Id, gameState.ProposedKeyPoint.Player, game);
                    gameState.ProposedKeyPoint = null;
                }
            }
            gameState.LastId = id;
            if (!game.Entities.ContainsKey(id))
            {
                game.Entities.Add(id, new Entity(id));
            }
            GAME_TAG tag;

            if (!Enum.TryParse(rawTag, out tag))
            {
                int tmp;
                if (int.TryParse(rawTag, out tmp) && Enum.IsDefined(typeof(GAME_TAG), tmp))
                {
                    tag = (GAME_TAG)tmp;
                }
            }
            var value    = HsLogReaderV2.ParseTagValue(tag, rawValue);
            var prevZone = game.Entities[id].GetTag(GAME_TAG.ZONE);

            game.Entities[id].SetTag(tag, value);

            if (tag == GAME_TAG.CONTROLLER && gameState.WaitForController != null && game.Player.Id == -1)
            {
                var p1 = game.Entities.FirstOrDefault(e => e.Value.GetTag(GAME_TAG.PLAYER_ID) == 1).Value;
                var p2 = game.Entities.FirstOrDefault(e => e.Value.GetTag(GAME_TAG.PLAYER_ID) == 2).Value;
                if (gameState.CurrentEntityHasCardId)
                {
                    if (p1 != null)
                    {
                        p1.IsPlayer = value == 1;
                    }
                    if (p2 != null)
                    {
                        p2.IsPlayer = value != 1;
                    }
                    game.Player.Id   = value;
                    game.Opponent.Id = value == 1 ? 2 : 1;
                }
                else
                {
                    if (p1 != null)
                    {
                        p1.IsPlayer = value != 1;
                    }
                    if (p2 != null)
                    {
                        p2.IsPlayer = value == 1;
                    }
                    game.Player.Id   = value == 1 ? 2 : 1;
                    game.Opponent.Id = value;
                }
            }
            var controller = game.Entities[id].GetTag(GAME_TAG.CONTROLLER);
            var player     = game.Entities[id].HasTag(GAME_TAG.CONTROLLER) ? (controller == game.Player.Id ? "FRIENDLY" : "OPPOSING") : "";
            var cardId     = game.Entities[id].CardId;

            if (tag == GAME_TAG.ZONE)
            {
                //Logger.WriteLine("--------" + player + " " + game.Entities[id].CardId + " " + (TAG_ZONE)prevZone + " -> " +
                //                 (TAG_ZONE)value);

                if (((TAG_ZONE)value == TAG_ZONE.HAND || ((TAG_ZONE)value == TAG_ZONE.PLAY || (TAG_ZONE)value == TAG_ZONE.DECK) && game.IsMulliganDone) && gameState.WaitForController == null)
                {
                    if (!game.IsMulliganDone)
                    {
                        prevZone = (int)TAG_ZONE.DECK;
                    }
                    if (controller == 0)
                    {
                        game.Entities[id].SetTag(GAME_TAG.ZONE, prevZone);
                        gameState.WaitForController = new { Tag = rawTag, Id = id, Value = rawValue };
                        //Logger.WriteLine("CURRENTLY NO CONTROLLER SET FOR CARD, WAITING...");
                        return;
                    }
                }
                switch ((TAG_ZONE)prevZone)
                {
                case TAG_ZONE.DECK:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.HAND:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerDraw(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Draw, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            if (!string.IsNullOrEmpty(game.Entities[id].CardId))
                            {
#if DEBUG
                                Logger.WriteLine(string.Format("Opponent Draw (EntityID={0}) already has a CardID. Removing. Blizzard Pls.", id), "TagChange");
#endif
                                game.Entities[id].CardId = string.Empty;
                            }
                            gameState.GameHandler.HandleOpponentDraw(game.Entities[id], gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Draw, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.SETASIDE:
                    case TAG_ZONE.REMOVEDFROMGAME:
                        if (controller == game.Player.Id)
                        {
                            if (gameState.JoustReveals > 0)
                            {
                                gameState.JoustReveals--;
                                break;
                            }
                            gameState.GameHandler.HandlePlayerRemoveFromDeck(game.Entities[id], gameState.GetTurnNumber());
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            if (gameState.JoustReveals > 0)
                            {
                                gameState.JoustReveals--;
                                break;
                            }
                            gameState.GameHandler.HandleOpponentRemoveFromDeck(game.Entities[id], gameState.GetTurnNumber());
                        }
                        break;

                    case TAG_ZONE.GRAVEYARD:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerDeckDiscard(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.DeckDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentDeckDiscard(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.DeckDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.PLAY:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerDeckToPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.DeckDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentDeckToPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.DeckDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.SECRET:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerSecretPlayed(game.Entities[id], cardId, gameState.GetTurnNumber(), true);
                            gameState.ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentSecretPlayed(game.Entities[id], cardId, -1, gameState.GetTurnNumber(), true, id);
                            gameState.ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Player);
                        }
                        break;

                    default:
                        Logger.WriteLine(string.Format("WARNING - unhandled zone change (id={0}): {1} -> {2}", id, (TAG_ZONE)prevZone, (TAG_ZONE)value), "TagChange");
                        break;
                    }
                    break;

                case TAG_ZONE.HAND:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.PLAY:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Play, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentPlay(game.Entities[id], cardId, game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION), gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Play, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.REMOVEDFROMGAME:
                    case TAG_ZONE.GRAVEYARD:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerHandDiscard(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.HandDiscard, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentHandDiscard(game.Entities[id], cardId, game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION), gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.HandDiscard, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.SECRET:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerSecretPlayed(game.Entities[id], cardId, gameState.GetTurnNumber(), false);
                            gameState.ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentSecretPlayed(game.Entities[id], cardId, game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION), gameState.GetTurnNumber(), false, id);
                            gameState.ProposeKeyPoint(KeyPointType.SecretPlayed, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.DECK:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerMulligan(game.Entities[id], cardId);
                            gameState.ProposeKeyPoint(KeyPointType.Mulligan, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentMulligan(game.Entities[id], game.Entities[id].GetTag(GAME_TAG.ZONE_POSITION));
                            gameState.ProposeKeyPoint(KeyPointType.Mulligan, id, ActivePlayer.Opponent);
                        }
                        break;

                    default:
                        Logger.WriteLine(string.Format("WARNING - unhandled zone change (id={0}): {1} -> {2}", id, (TAG_ZONE)prevZone, (TAG_ZONE)value), "TagChange");
                        break;
                    }
                    break;

                case TAG_ZONE.PLAY:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.HAND:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerBackToHand(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.PlayToHand, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentPlayToHand(game.Entities[id], cardId, gameState.GetTurnNumber(), id);
                            gameState.ProposeKeyPoint(KeyPointType.PlayToHand, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.DECK:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerPlayToDeck(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.PlayToDeck, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentPlayToDeck(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.PlayToDeck, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.GRAVEYARD:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerPlayToGraveyard(game.Entities[id], cardId,
                                                                              gameState.GetTurnNumber());
                            if (game.Entities[id].HasTag(GAME_TAG.HEALTH))
                            {
                                gameState.ProposeKeyPoint(KeyPointType.Death, id, ActivePlayer.Player);
                            }
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentPlayToGraveyard(game.Entities[id], cardId,
                                                                                gameState.GetTurnNumber(), gameState.PlayersTurn());
                            if (game.Entities[id].HasTag(GAME_TAG.HEALTH))
                            {
                                gameState.ProposeKeyPoint(KeyPointType.Death, id, ActivePlayer.Opponent);
                            }
                        }
                        break;

                    default:
                        Logger.WriteLine(string.Format("WARNING - unhandled zone change (id={0}): {1} -> {2}", id, (TAG_ZONE)prevZone, (TAG_ZONE)value), "TagChange");
                        break;
                    }
                    break;

                case TAG_ZONE.SECRET:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.SECRET:
                    case TAG_ZONE.GRAVEYARD:
                        if (controller == game.Player.Id)
                        {
                            gameState.ProposeKeyPoint(KeyPointType.SecretTriggered, id, ActivePlayer.Player);
                        }
                        if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentSecretTrigger(game.Entities[id], cardId, gameState.GetTurnNumber(), id);
                            gameState.ProposeKeyPoint(KeyPointType.SecretTriggered, id, ActivePlayer.Opponent);
                        }
                        break;

                    default:
                        Logger.WriteLine(string.Format("WARNING - unhandled zone change (id={0}): {1} -> {2}", id, (TAG_ZONE)prevZone, (TAG_ZONE)value), "TagChange");
                        break;
                    }
                    break;

                case TAG_ZONE.GRAVEYARD:
                case TAG_ZONE.SETASIDE:
                case TAG_ZONE.CREATED:
                case TAG_ZONE.INVALID:
                case TAG_ZONE.REMOVEDFROMGAME:
                    switch ((TAG_ZONE)value)
                    {
                    case TAG_ZONE.PLAY:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerCreateInPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Summon, id, ActivePlayer.Player);
                        }
                        if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentCreateInPlay(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Summon, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.DECK:
                        if (controller == game.Player.Id)
                        {
                            if (gameState.JoustReveals > 0)
                            {
                                break;
                            }
                            gameState.GameHandler.HandlePlayerGetToDeck(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.CreateToDeck, id, ActivePlayer.Player);
                        }
                        if (controller == game.Opponent.Id)
                        {
                            if (gameState.JoustReveals > 0)
                            {
                                break;
                            }
                            gameState.GameHandler.HandleOpponentGetToDeck(game.Entities[id], gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.CreateToDeck, id, ActivePlayer.Opponent);
                        }
                        break;

                    case TAG_ZONE.HAND:
                        if (controller == game.Player.Id)
                        {
                            gameState.GameHandler.HandlePlayerGet(game.Entities[id], cardId, gameState.GetTurnNumber());
                            gameState.ProposeKeyPoint(KeyPointType.Obtain, id, ActivePlayer.Player);
                        }
                        else if (controller == game.Opponent.Id)
                        {
                            gameState.GameHandler.HandleOpponentGet(game.Entities[id], gameState.GetTurnNumber(), id);
                            gameState.ProposeKeyPoint(KeyPointType.Obtain, id, ActivePlayer.Opponent);
                        }
                        break;

                    default:
                        Logger.WriteLine(string.Format("WARNING - unhandled zone change (id={0}): {1} -> {2}", id, (TAG_ZONE)prevZone, (TAG_ZONE)value), "TagChange");
                        break;
                    }
                    break;

                default:
                    Logger.WriteLine(string.Format("WARNING - unhandled zone change (id={0}): {1} -> {2}", id, (TAG_ZONE)prevZone, (TAG_ZONE)value), "TagChange");
                    break;
                }
            }
            else if (tag == GAME_TAG.PLAYSTATE)
            {
                if (value == (int)TAG_PLAYSTATE.QUIT)
                {
                    gameState.GameHandler.HandleConcede();
                }
                if (!gameState.GameEnded)
                {
                    if (game.Entities[id].IsPlayer)
                    {
                        if (value == (int)TAG_PLAYSTATE.WON)
                        {
                            gameState.GameEndKeyPoint(true, id);
                            gameState.GameHandler.HandleWin();
                            gameState.GameHandler.HandleGameEnd();
                            gameState.GameEnded = true;
                        }
                        else if (value == (int)TAG_PLAYSTATE.LOST)
                        {
                            gameState.GameEndKeyPoint(false, id);
                            gameState.GameHandler.HandleLoss();
                            gameState.GameHandler.HandleGameEnd();
                            gameState.GameEnded = true;
                        }
                        else if (value == (int)TAG_PLAYSTATE.TIED)
                        {
                            gameState.GameEndKeyPoint(false, id);
                            gameState.GameHandler.HandleTied();
                            gameState.GameHandler.HandleGameEnd();
                        }
                    }
                }
            }
            else if (tag == GAME_TAG.CURRENT_PLAYER && value == 1)
            {
                var activePlayer = game.Entities[id].IsPlayer ? ActivePlayer.Player : ActivePlayer.Opponent;
                gameState.GameHandler.TurnStart(activePlayer, gameState.GetTurnNumber());
                if (activePlayer == ActivePlayer.Player)
                {
                    gameState.PlayerUsedHeroPower = false;
                }
                else
                {
                    gameState.OpponentUsedHeroPower = false;
                }
            }
            else if (tag == GAME_TAG.DEFENDING)
            {
                if (player == "OPPOSING")
                {
                    gameState.GameHandler.HandleDefendingEntity(value == 1 ? game.Entities[id] : null);
                }
            }
            else if (tag == GAME_TAG.ATTACKING)
            {
                if (player == "FRIENDLY")
                {
                    gameState.GameHandler.HandleAttackingEntity(value == 1 ? game.Entities[id] : null);
                }
            }
            else if (tag == GAME_TAG.PROPOSED_DEFENDER)
            {
                game.OpponentSecrets.proposedDefenderEntityId = value;
            }
            else if (tag == GAME_TAG.PROPOSED_ATTACKER)
            {
                game.OpponentSecrets.proposedAttackerEntityId = value;
            }
            else if (tag == GAME_TAG.NUM_MINIONS_PLAYED_THIS_TURN && value > 0)
            {
                if (gameState.PlayersTurn())
                {
                    gameState.GameHandler.HandlePlayerMinionPlayed();
                }
            }
            else if (tag == GAME_TAG.PREDAMAGE && value > 0)
            {
                if (gameState.PlayersTurn())
                {
                    gameState.GameHandler.HandleOpponentDamage(game.Entities[id]);
                }
            }
            else if (tag == GAME_TAG.NUM_TURNS_IN_PLAY && value > 0)
            {
                if (!gameState.PlayersTurn())
                {
                    gameState.GameHandler.HandleOpponentTurnStart(game.Entities[id]);
                }
            }
            else if (tag == GAME_TAG.NUM_ATTACKS_THIS_TURN && value > 0)
            {
                if (controller == game.Player.Id)
                {
                    gameState.ProposeKeyPoint(KeyPointType.Attack, id, ActivePlayer.Player);
                }
                else if (controller == game.Opponent.Id)
                {
                    gameState.ProposeKeyPoint(KeyPointType.Attack, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == GAME_TAG.ZONE_POSITION)
            {
                var zone = game.Entities[id].GetTag(GAME_TAG.ZONE);
                if (zone == (int)TAG_ZONE.HAND)
                {
                    if (controller == game.Player.Id)
                    {
                        ReplayMaker.Generate(KeyPointType.HandPos, id, ActivePlayer.Player, game);
                        gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Player, TAG_ZONE.HAND, gameState.GetTurnNumber());
                    }
                    else if (controller == game.Opponent.Id)
                    {
                        ReplayMaker.Generate(KeyPointType.HandPos, id, ActivePlayer.Opponent, game);
                        gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Opponent, TAG_ZONE.HAND, gameState.GetTurnNumber());
                    }
                }
                else if (zone == (int)TAG_ZONE.PLAY)
                {
                    if (controller == game.Player.Id)
                    {
                        ReplayMaker.Generate(KeyPointType.BoardPos, id, ActivePlayer.Player, game);
                        gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Player, TAG_ZONE.PLAY, gameState.GetTurnNumber());
                    }
                    else if (controller == game.Opponent.Id)
                    {
                        ReplayMaker.Generate(KeyPointType.BoardPos, id, ActivePlayer.Opponent, game);
                        gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Opponent, TAG_ZONE.PLAY, gameState.GetTurnNumber());
                    }
                }
            }
            else if (tag == GAME_TAG.CARD_TARGET && value > 0)
            {
                if (controller == game.Player.Id)
                {
                    gameState.ProposeKeyPoint(KeyPointType.PlaySpell, id, ActivePlayer.Player);
                }
                else if (controller == game.Opponent.Id)
                {
                    gameState.ProposeKeyPoint(KeyPointType.PlaySpell, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == GAME_TAG.EQUIPPED_WEAPON && value == 0)
            {
                if (controller == game.Player.Id)
                {
                    gameState.ProposeKeyPoint(KeyPointType.WeaponDestroyed, id, ActivePlayer.Player);
                }
                else if (controller == game.Opponent.Id)
                {
                    gameState.ProposeKeyPoint(KeyPointType.WeaponDestroyed, id, ActivePlayer.Opponent);
                }
            }
            else if (tag == GAME_TAG.EXHAUSTED && value > 0)
            {
                if (game.Entities[id].GetTag(GAME_TAG.CARDTYPE) == (int)TAG_CARDTYPE.HERO_POWER)
                {
                    if (controller == game.Player.Id)
                    {
                        gameState.ProposeKeyPoint(KeyPointType.HeroPower, id, ActivePlayer.Player);
                    }
                    else if (controller == game.Opponent.Id)
                    {
                        gameState.ProposeKeyPoint(KeyPointType.HeroPower, id, ActivePlayer.Opponent);
                    }
                }
            }
            else if (tag == GAME_TAG.CONTROLLER)
            {
                if (value == game.Player.Id)
                {
                    if (game.Entities[id].IsInZone(TAG_ZONE.SECRET))
                    {
                        gameState.GameHandler.HandleOpponentStolen(game.Entities[id], cardId, gameState.GetTurnNumber());
                        gameState.ProposeKeyPoint(KeyPointType.SecretStolen, id, ActivePlayer.Player);
                    }
                    else if (game.Entities[id].IsInZone(TAG_ZONE.PLAY))
                    {
                        gameState.GameHandler.HandleOpponentStolen(game.Entities[id], cardId, gameState.GetTurnNumber());
                    }
                }
                else if (value == game.Opponent.Id)
                {
                    if (game.Entities[id].IsInZone(TAG_ZONE.SECRET))
                    {
                        gameState.GameHandler.HandleOpponentStolen(game.Entities[id], cardId, gameState.GetTurnNumber());
                        gameState.ProposeKeyPoint(KeyPointType.SecretStolen, id, ActivePlayer.Player);
                    }
                    else if (game.Entities[id].IsInZone(TAG_ZONE.PLAY))
                    {
                        gameState.GameHandler.HandlePlayerStolen(game.Entities[id], cardId, gameState.GetTurnNumber());
                    }
                }
            }
            else if (tag == GAME_TAG.FATIGUE)
            {
                if (controller == game.Player.Id)
                {
                    gameState.GameHandler.HandlePlayerFatigue(Convert.ToInt32(rawValue));
                }
                else if (controller == game.Opponent.Id)
                {
                    gameState.GameHandler.HandleOpponentFatigue(Convert.ToInt32(rawValue));
                }
            }
            if (gameState.WaitForController != null)
            {
                if (!isRecursive)
                {
                    TagChange(gameState, (string)gameState.WaitForController.Tag, (int)gameState.WaitForController.Id, (string)gameState.WaitForController.Value, game, true);
                    gameState.WaitForController = null;
                }
            }
        }