public void Handle(string logLine, IHsGameState gameState, IGame game) { if (logLine.Contains("CREATE_GAME")) { gameState.GameHandler.HandleGameStart(); gameState.GameEnded = false; gameState.AddToTurn = -1; gameState.GameLoaded = true; gameState.LastGameStart = DateTime.Now; } else if (HsLogReaderConstants.GameEntityRegex.IsMatch(logLine)) { gameState.GameHandler.HandleGameStart(); gameState.GameEnded = false; gameState.AddToTurn = -1; var match = HsLogReaderConstants.GameEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id)); } gameState.CurrentEntityId = id; } else if (HsLogReaderConstants.PlayerEntityRegex.IsMatch(logLine)) { var match = HsLogReaderConstants.PlayerEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id)); } gameState.CurrentEntityId = id; } else if (HsLogReaderConstants.TagChangeRegex.IsMatch(logLine)) { var match = HsLogReaderConstants.TagChangeRegex.Match(logLine); var rawEntity = match.Groups["entity"].Value.Replace("UNKNOWN ENTITY ", ""); int entityId; if (rawEntity.StartsWith("[") && HsLogReaderConstants.EntityRegex.IsMatch(rawEntity)) { var entity = HsLogReaderConstants.EntityRegex.Match(rawEntity); var id = int.Parse(entity.Groups["id"].Value); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, id, match.Groups["value"].Value, game); } else if (int.TryParse(rawEntity, out entityId)) { _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entityId, match.Groups["value"].Value, game); } else { var entity = game.Entities.FirstOrDefault(x => x.Value.Name == rawEntity); if (entity.Value == null) { //while the id is unknown, store in tmp entities var tmpEntity = _tmpEntities.FirstOrDefault(x => x.Name == rawEntity); if (tmpEntity == null) { tmpEntity = new Entity(_tmpEntities.Count + 1); tmpEntity.Name = rawEntity; _tmpEntities.Add(tmpEntity); } GAME_TAG tag; Enum.TryParse(match.Groups["tag"].Value, out tag); var value = HsLogReaderV2.ParseTagValue(tag, match.Groups["value"].Value); tmpEntity.SetTag(tag, value); if (tmpEntity.HasTag(GAME_TAG.ENTITY_ID)) { var id = tmpEntity.GetTag(GAME_TAG.ENTITY_ID); if (game.Entities.ContainsKey(id)) { game.Entities[id].Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { game.Entities[id].SetTag(t.Key, t.Value); } _tmpEntities.Remove(tmpEntity); //Logger.WriteLine("COPIED TMP ENTITY (" + rawEntity + ")"); } else { Logger.WriteLine( "TMP ENTITY (" + rawEntity + ") NOW HAS A KEY, BUT GAME.ENTITIES DOES NOT CONTAIN THIS KEY", "LogReader"); } } } else { _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } } if (HsLogReaderConstants.EntityNameRegex.IsMatch(logLine)) { match = HsLogReaderConstants.EntityNameRegex.Match(logLine); var name = match.Groups["name"].Value; var player = int.Parse(match.Groups["value"].Value); if (player == 1) { gameState.GameHandler.HandlePlayerName(name); } else if (player == 2) { gameState.GameHandler.HandleOpponentName(name); } } } else if (HsLogReaderConstants.CreationRegex.IsMatch(logLine)) { var match = HsLogReaderConstants.CreationRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); var cardId = match.Groups["cardId"].Value; if (!game.Entities.ContainsKey(id)) { if (string.IsNullOrEmpty(cardId)) { if (gameState.KnownCardIds.TryGetValue(id, out cardId)) { Logger.WriteLine(string.Format("Found known cardId for entity {0}: {1}", id, cardId)); gameState.KnownCardIds.Remove(id); } } game.Entities.Add(id, new Entity(id) { CardId = cardId }); } gameState.CurrentEntityId = id; gameState.CurrentEntityHasCardId = !string.IsNullOrEmpty(cardId); } else if (HsLogReaderConstants.UpdatingEntityRegex.IsMatch(logLine)) { var match = HsLogReaderConstants.UpdatingEntityRegex.Match(logLine); var cardId = match.Groups["cardId"].Value; var rawEntity = match.Groups["entity"].Value; int entityId; if (rawEntity.StartsWith("[") && HsLogReaderConstants.EntityRegex.IsMatch(rawEntity)) { var entity = HsLogReaderConstants.EntityRegex.Match(rawEntity); entityId = int.Parse(entity.Groups["id"].Value); } else if (!int.TryParse(rawEntity, out entityId)) { entityId = -1; } if (entityId != -1) { gameState.CurrentEntityId = entityId; if (!game.Entities.ContainsKey(entityId)) { game.Entities.Add(entityId, new Entity(entityId)); } game.Entities[entityId].CardId = cardId; } if (gameState.JoustReveals > 0) { Entity currentEntity; if (game.Entities.TryGetValue(entityId, out currentEntity)) { if (currentEntity.IsControlledBy(game.Opponent.Id)) { gameState.GameHandler.HandleOpponentJoust(currentEntity, cardId, gameState.GetTurnNumber()); } else if (currentEntity.IsControlledBy(game.Player.Id)) { gameState.GameHandler.HandlePlayerJoust(currentEntity, cardId, gameState.GetTurnNumber()); } } //gameState.JoustReveals--; } } else if (HsLogReaderConstants.CreationTagRegex.IsMatch(logLine) && !logLine.Contains("HIDE_ENTITY")) { var match = HsLogReaderConstants.CreationTagRegex.Match(logLine); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, gameState.CurrentEntityId, match.Groups["value"].Value, game); } else if ((logLine.Contains("Begin Spectating") || logLine.Contains("Start Spectator")) && game.IsInMenu) { gameState.GameHandler.SetGameMode(GameMode.Spectator); } else if (logLine.Contains("End Spectator")) { gameState.GameHandler.SetGameMode(GameMode.Spectator); gameState.GameHandler.HandleGameEnd(); } else if (HsLogReaderConstants.ActionStartRegex.IsMatch(logLine)) { var playerEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GAME_TAG.PLAYER_ID) && e.Value.GetTag(GAME_TAG.PLAYER_ID) == game.Player.Id); var opponentEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GAME_TAG.PLAYER_ID) && e.Value.GetTag(GAME_TAG.PLAYER_ID) == game.Opponent.Id); var match = HsLogReaderConstants.ActionStartRegex.Match(logLine); var actionStartingCardId = match.Groups["cardId"].Value.Trim(); var actionStartingEntityId = int.Parse(match.Groups["id"].Value); if (string.IsNullOrEmpty(actionStartingCardId)) { Entity tmpEntity; if (game.Entities.TryGetValue(actionStartingEntityId, out tmpEntity)) { actionStartingCardId = tmpEntity.CardId; } } if (!string.IsNullOrEmpty(actionStartingCardId)) { if (actionStartingCardId == "BRM_007") //Gang Up { //if (playerEntity.Value != null && playerEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) == 1) //{ var target = match.Groups["target"].Value.Trim(); if (target.StartsWith("[") && HsLogReaderConstants.EntityRegex.IsMatch(target)) { var cardIdMatch = HsLogReaderConstants.CardIdRegex.Match(target); if (cardIdMatch.Success) { var targetCardId = cardIdMatch.Groups["cardId"].Value.Trim(); for (int i = 0; i < 3; i++) { var id = game.Entities.Count + i + 1; if (!gameState.KnownCardIds.ContainsKey(id)) { gameState.KnownCardIds.Add(id, targetCardId); } } } } //} } else if (actionStartingCardId == "GVG_056") //Iron Juggernaut { // burrowing mine will be the entity created next int id = game.Entities.Count + 1; //if(playerEntity.Value == null || playerEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) != 1) //{ if (!gameState.KnownCardIds.ContainsKey(id)) { gameState.KnownCardIds.Add(id, "GVG_056t"); } //} } else if (actionStartingCardId == "GVG_031") //Recycle { // Recycled card will be the entity created next int id = game.Entities.Count + 1; //if(playerEntity.Value == null || playerEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) != 1) //{ gameState.ProposeKeyPoint(KeyPointType.CreateToDeck, id, ActivePlayer.Player); var target = match.Groups["target"].Value.Trim(); if (target.StartsWith("[") && HsLogReaderConstants.EntityRegex.IsMatch(target)) { var cardIdMatch = HsLogReaderConstants.CardIdRegex.Match(target); if (cardIdMatch.Success) { var targetCardId = cardIdMatch.Groups["cardId"].Value.Trim(); if (!gameState.KnownCardIds.ContainsKey(id)) { gameState.KnownCardIds.Add(id, targetCardId); } } } //} } else if (actionStartingCardId == "GVG_035") //Malorne { // Malorne will be the entity created next int id = game.Entities.Count + 1; //if(playerEntity.Value == null || playerEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) != 1) //{ if (!gameState.KnownCardIds.ContainsKey(id)) { gameState.KnownCardIds.Add(id, "GVG_035"); } // } } else { if (playerEntity.Value != null && playerEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) == 1 && !gameState.PlayerUsedHeroPower || opponentEntity.Value != null && opponentEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) == 1 && !gameState.OpponentUsedHeroPower) { var card = Database.GetCardFromId(actionStartingCardId); if (card.Type == "Hero Power") { if (playerEntity.Value != null && playerEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) == 1) { gameState.GameHandler.HandlePlayerHeroPower(actionStartingCardId, gameState.GetTurnNumber()); gameState.PlayerUsedHeroPower = true; } else if (opponentEntity.Value != null) { gameState.GameHandler.HandleOpponentHeroPower(actionStartingCardId, gameState.GetTurnNumber()); gameState.OpponentUsedHeroPower = true; } } } } } } else if (logLine.Contains("BlockType=JOUST")) { gameState.JoustReveals = 2; } }
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 prevValue = game.Entities[id].GetTag(tag); 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 % 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(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) { 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) { prevValue = (int)TAG_ZONE.DECK; } if (controller == 0) { game.Entities[id].SetTag(GAME_TAG.ZONE, prevValue); gameState.WaitForController = new { Tag = rawTag, Id = id, Value = rawValue }; return; } } switch ((TAG_ZONE)prevValue) { 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)prevValue, (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)prevValue, (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)prevValue, (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)prevValue, (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)prevValue, (TAG_ZONE)value), "TagChange"); break; } break; default: Logger.WriteLine(string.Format("WARNING - unhandled zone change (id={0}): {1} -> {2}", id, (TAG_ZONE)prevValue, (TAG_ZONE)value), "TagChange"); break; } } else if (tag == GAME_TAG.PLAYSTATE) { if (value == (int)TAG_PLAYSTATE.CONCEDED) { 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.LAST_CARD_PLAYED) { gameState.LastCardPlayed = value; } 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 && 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(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; } } }
public void Handle(string logLine, IHsGameState gameState, IGame game) { if (logLine.Contains("CREATE_GAME")) { gameState.GameHandler.HandleGameStart(); gameState.GameEnded = false; gameState.AddToTurn = -1; gameState.GameLoaded = true; gameState.LastGameStart = DateTime.Now; } else if (HsLogReaderConstants.PowerTaskList.GameEntityRegex.IsMatch(logLine)) { gameState.GameHandler.HandleGameStart(); gameState.GameEnded = false; gameState.AddToTurn = -1; var match = HsLogReaderConstants.PowerTaskList.GameEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id)); } gameState.CurrentEntityId = id; } else if (HsLogReaderConstants.PowerTaskList.PlayerEntityRegex.IsMatch(logLine)) { var match = HsLogReaderConstants.PowerTaskList.PlayerEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id)); } gameState.CurrentEntityId = id; } else if (HsLogReaderConstants.PowerTaskList.TagChangeRegex.IsMatch(logLine)) { var match = HsLogReaderConstants.PowerTaskList.TagChangeRegex.Match(logLine); var rawEntity = match.Groups["entity"].Value.Replace("UNKNOWN ENTITY ", ""); int entityId; if (rawEntity.StartsWith("[") && HsLogReaderConstants.PowerTaskList.EntityRegex.IsMatch(rawEntity)) { var entity = HsLogReaderConstants.PowerTaskList.EntityRegex.Match(rawEntity); var id = int.Parse(entity.Groups["id"].Value); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, id, match.Groups["value"].Value, game); } else if (int.TryParse(rawEntity, out entityId)) { _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entityId, match.Groups["value"].Value, game); } else { var entity = game.Entities.FirstOrDefault(x => x.Value.Name == rawEntity); if (entity.Value == null) { entity = game.Entities.FirstOrDefault(x => x.Value.Name == "UNKNOWN HUMAN PLAYER"); if (entity.Value != null) { entity.Value.Name = rawEntity; } } if (entity.Value == null) { //while the id is unknown, store in tmp entities var tmpEntity = _tmpEntities.FirstOrDefault(x => x.Name == rawEntity); if (tmpEntity == null) { tmpEntity = new Entity(_tmpEntities.Count + 1); tmpEntity.Name = rawEntity; _tmpEntities.Add(tmpEntity); } GAME_TAG tag; Enum.TryParse(match.Groups["tag"].Value, out tag); var value = HsLogReaderV2.ParseTagValue(tag, match.Groups["value"].Value); tmpEntity.SetTag(tag, value); if (tmpEntity.HasTag(GAME_TAG.ENTITY_ID)) { var id = tmpEntity.GetTag(GAME_TAG.ENTITY_ID); if (game.Entities.ContainsKey(id)) { game.Entities[id].Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { game.Entities[id].SetTag(t.Key, t.Value); } _tmpEntities.Remove(tmpEntity); //Logger.WriteLine("COPIED TMP ENTITY (" + rawEntity + ")"); } else { Logger.WriteLine( "TMP ENTITY (" + rawEntity + ") NOW HAS A KEY, BUT GAME.ENTITIES DOES NOT CONTAIN THIS KEY", "LogReader"); } } } else { _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } } if (HsLogReaderConstants.PowerTaskList.EntityNameRegex.IsMatch(logLine)) { match = HsLogReaderConstants.PowerTaskList.EntityNameRegex.Match(logLine); var name = match.Groups["name"].Value; var player = int.Parse(match.Groups["value"].Value); if (player == game.Player.Id) { game.Player.Name = name; } else if (player == game.Opponent.Id) { game.Opponent.Name = name; } } } else if (HsLogReaderConstants.PowerTaskList.CreationRegex.IsMatch(logLine)) { var match = HsLogReaderConstants.PowerTaskList.CreationRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); var cardId = match.Groups["cardId"].Value; if (!game.Entities.ContainsKey(id)) { if (string.IsNullOrEmpty(cardId)) { if (gameState.KnownCardIds.TryGetValue(id, out cardId)) { Logger.WriteLine(string.Format("Found known cardId for entity {0}: {1}", id, cardId)); gameState.KnownCardIds.Remove(id); } } game.Entities.Add(id, new Entity(id) { CardId = cardId }); } gameState.CurrentEntityId = id; gameState.CurrentEntityHasCardId = !string.IsNullOrEmpty(cardId); } else if (HsLogReaderConstants.PowerTaskList.UpdatingEntityRegex.IsMatch(logLine)) { var match = HsLogReaderConstants.PowerTaskList.UpdatingEntityRegex.Match(logLine); var cardId = match.Groups["cardId"].Value; var rawEntity = match.Groups["entity"].Value; int entityId; if (rawEntity.StartsWith("[") && HsLogReaderConstants.PowerTaskList.EntityRegex.IsMatch(rawEntity)) { var entity = HsLogReaderConstants.PowerTaskList.EntityRegex.Match(rawEntity); entityId = int.Parse(entity.Groups["id"].Value); } else if (!int.TryParse(rawEntity, out entityId)) { entityId = -1; } if (entityId != -1) { gameState.CurrentEntityId = entityId; if (!game.Entities.ContainsKey(entityId)) { game.Entities.Add(entityId, new Entity(entityId)); } game.Entities[entityId].CardId = cardId; } if (gameState.JoustReveals > 0) { Entity currentEntity; if (game.Entities.TryGetValue(entityId, out currentEntity)) { if (currentEntity.IsControlledBy(game.Opponent.Id)) { gameState.GameHandler.HandleOpponentJoust(currentEntity, cardId, gameState.GetTurnNumber()); } else if (currentEntity.IsControlledBy(game.Player.Id)) { gameState.GameHandler.HandlePlayerJoust(currentEntity, cardId, gameState.GetTurnNumber()); } } //gameState.JoustReveals--; } } else if (HsLogReaderConstants.PowerTaskList.CreationTagRegex.IsMatch(logLine) && !logLine.Contains("HIDE_ENTITY")) { var match = HsLogReaderConstants.PowerTaskList.CreationTagRegex.Match(logLine); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, gameState.CurrentEntityId, match.Groups["value"].Value, game); } else if ((logLine.Contains("Begin Spectating") || logLine.Contains("Start Spectator")) && game.IsInMenu) { gameState.GameHandler.SetGameMode(GameMode.Spectator); } else if (logLine.Contains("End Spectator")) { gameState.GameHandler.SetGameMode(GameMode.Spectator); gameState.GameHandler.HandleGameEnd(); } else if (HsLogReaderConstants.PowerTaskList.ActionStartRegex.IsMatch(logLine)) { Entity actionEntity; var playerEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GAME_TAG.PLAYER_ID) && e.Value.GetTag(GAME_TAG.PLAYER_ID) == game.Player.Id); var opponentEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GAME_TAG.PLAYER_ID) && e.Value.GetTag(GAME_TAG.PLAYER_ID) == game.Opponent.Id); var match = HsLogReaderConstants.PowerTaskList.ActionStartRegex.Match(logLine); var actionStartingCardId = match.Groups["cardId"].Value.Trim(); var actionStartingEntityId = int.Parse(match.Groups["id"].Value); if (string.IsNullOrEmpty(actionStartingCardId)) { if (game.Entities.TryGetValue(actionStartingEntityId, out actionEntity)) { actionStartingCardId = actionEntity.CardId; } } if (game.Entities.TryGetValue(actionStartingEntityId, out actionEntity)) { // spell owned by the player if (actionEntity.HasTag(GAME_TAG.CONTROLLER) && actionEntity.GetTag(GAME_TAG.CONTROLLER) == game.Player.Id && actionEntity.GetTag(GAME_TAG.CARDTYPE) == (int)TAG_CARDTYPE.SPELL) { int targetEntityId = actionEntity.GetTag(GAME_TAG.CARD_TARGET); Entity targetEntity; var targetsMinion = game.Entities.TryGetValue(targetEntityId, out targetEntity); gameState.GameHandler.HandlePlayerSpellPlayed(targetsMinion); } } if (!string.IsNullOrEmpty(actionStartingCardId)) { if (match.Groups["type"].Value == "TRIGGER") { switch (actionStartingCardId) { case CardIds.Collectible.Rogue.TradePrinceGallywix: AddKnownCardId(gameState, game, game.Entities[gameState.LastCardPlayed].CardId); AddKnownCardId(gameState, game, CardIds.NonCollectible.Neutral.GallywixsCoinToken); break; case CardIds.Collectible.Druid.Malorne: AddKnownCardId(gameState, game, CardIds.Collectible.Druid.Malorne); break; } } else //POWER { switch (actionStartingCardId) { case CardIds.Collectible.Rogue.GangUp: AddTargetAsKnownCardId(gameState, game, match, 3); break; case CardIds.Collectible.Rogue.BeneathTheGrounds: AddKnownCardId(gameState, game, CardIds.NonCollectible.Rogue.AmbushToken, 3); break; case CardIds.Collectible.Warrior.IronJuggernaut: AddKnownCardId(gameState, game, CardIds.NonCollectible.Warrior.BurrowingMineToken); break; case CardIds.Collectible.Druid.Recycle: AddTargetAsKnownCardId(gameState, game, match); break; case CardIds.Collectible.Mage.ForgottenTorch: AddKnownCardId(gameState, game, CardIds.NonCollectible.Mage.RoaringTorchToken); break; case CardIds.Collectible.Warlock.CurseOfRafaam: AddKnownCardId(gameState, game, CardIds.NonCollectible.Warlock.CursedToken); break; case CardIds.Collectible.Neutral.AncientShade: AddKnownCardId(gameState, game, CardIds.NonCollectible.Neutral.AncientCurseToken); break; case CardIds.Collectible.Priest.Entomb: AddTargetAsKnownCardId(gameState, game, match); break; case CardIds.Collectible.Priest.ExcavatedEvil: AddKnownCardId(gameState, game, CardIds.Collectible.Priest.ExcavatedEvil); break; case CardIds.Collectible.Neutral.EliseStarseeker: AddKnownCardId(gameState, game, CardIds.NonCollectible.Neutral.MapToTheGoldenMonkeyToken); break; case CardIds.NonCollectible.Neutral.MapToTheGoldenMonkeyToken: AddKnownCardId(gameState, game, CardIds.NonCollectible.Neutral.GoldenMonkeyToken); break; default: if (playerEntity.Value != null && playerEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) == 1 && !gameState.PlayerUsedHeroPower || opponentEntity.Value != null && opponentEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) == 1 && !gameState.OpponentUsedHeroPower) { var card = Database.GetCardFromId(actionStartingCardId); if (card.Type == "Hero Power") { if (playerEntity.Value != null && playerEntity.Value.GetTag(GAME_TAG.CURRENT_PLAYER) == 1) { gameState.GameHandler.HandlePlayerHeroPower(actionStartingCardId, gameState.GetTurnNumber()); gameState.PlayerUsedHeroPower = true; } else if (opponentEntity.Value != null) { gameState.GameHandler.HandleOpponentHeroPower(actionStartingCardId, gameState.GetTurnNumber()); gameState.OpponentUsedHeroPower = true; } } } break; } } } } else if (logLine.Contains("BlockType=JOUST")) { gameState.JoustReveals = 2; } }
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; } } }