private void TurnChange(IHsGameState gameState, IGame game) { if(!gameState.SetupDone || game.PlayerEntity == null) return; var activePlayer = game.PlayerEntity.HasTag(CURRENT_PLAYER) ? ActivePlayer.Player : ActivePlayer.Opponent; gameState.GameHandler.TurnStart(activePlayer, gameState.GetTurnNumber()); if(activePlayer == ActivePlayer.Player) gameState.PlayerUsedHeroPower = false; else gameState.OpponentUsedHeroPower = false; }
private void ZoneChangeFromOther(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { if (!game.Entities.TryGetValue(id, out var entity)) { return; } var currentBlockCardId = gameState.CurrentBlock?.CardId ?? ""; if (entity.Info.OriginalZone == DECK && value != (int)DECK) { //This entity was moved from DECK to SETASIDE to HAND, e.g. by Tracking entity.Info.Discarded = false; ZoneChangeFromDeck(gameState, id, game, value, prevValue, controller, cardId); return; } entity.Info.Created = true; switch ((Zone)value) { case PLAY: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerCreateInPlay(entity, cardId, gameState.GetTurnNumber()); } if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentCreateInPlay(entity, cardId, gameState.GetTurnNumber()); } break; case DECK: if (controller == game.Player.Id) { if (gameState.JoustReveals > 0) { break; } gameState.GameHandler.HandlePlayerGetToDeck(entity, cardId, gameState.GetTurnNumber()); } if (controller == game.Opponent.Id) { if (gameState.JoustReveals > 0) { break; } gameState.GameHandler.HandleOpponentGetToDeck(entity, gameState.GetTurnNumber()); } break; case HAND: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerGet(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentGet(entity, gameState.GetTurnNumber(), id); } break; case Zone.SECRET: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerSecretPlayed(entity, cardId, gameState.GetTurnNumber(), (Zone)prevValue, currentBlockCardId); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentSecretPlayed(entity, cardId, -1, gameState.GetTurnNumber(), (Zone)prevValue, id); } break; case SETASIDE: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerCreateInSetAside(entity, gameState.GetTurnNumber()); } if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentCreateInSetAside(entity, gameState.GetTurnNumber()); if (gameState.CurrentBlock?.CardId == Collectible.Neutral.GrandArchivist && gameState.CurrentBlock.EntityDiscardedByArchivist != null) { gameState.CurrentBlock.EntityDiscardedByArchivist.CardId = entity.Info.LatestCardId; } } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
public void Handle(string logLine, IHsGameState gameState, IGame game) { var creationTag = false; if (GameEntityRegex.IsMatch(logLine)) { var match = GameEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id) { Name = "GameEntity" }); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } return; } if (PlayerEntityRegex.IsMatch(logLine)) { var match = PlayerEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id)); } if (gameState.WasInProgress) { game.Entities[id].Name = game.GetStoredPlayerName(id); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } return; } if (TagChangeRegex.IsMatch(logLine)) { var match = TagChangeRegex.Match(logLine); var rawEntity = match.Groups["entity"].Value.Replace("UNKNOWN ENTITY ", ""); if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = 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 int 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) { var players = game.Entities.Where(x => x.Value.HasTag(GameTag.PLAYER_ID)).Take(2).ToList(); var unnamedPlayers = players.Where(x => string.IsNullOrEmpty(x.Value.Name)).ToList(); var unknownHumanPlayer = players.FirstOrDefault(x => x.Value.Name == "UNKNOWN HUMAN PLAYER"); if (unnamedPlayers.Count == 0 && unknownHumanPlayer.Value != null) { Log.Info("Updating UNKNOWN HUMAN PLAYER"); entity = unknownHumanPlayer; } //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) { Name = rawEntity }; _tmpEntities.Add(tmpEntity); } Enum.TryParse(match.Groups["tag"].Value, out GameTag tag); var value = GameTagHelper.ParseTag(tag, match.Groups["value"].Value); if (unnamedPlayers.Count == 1) { entity = unnamedPlayers.Single(); } else if (unnamedPlayers.Count == 2 && tag == GameTag.CURRENT_PLAYER && value == 0) { entity = game.Entities.FirstOrDefault(x => x.Value?.HasTag(GameTag.CURRENT_PLAYER) ?? false); } if (entity.Value != null) { entity.Value.Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { _tagChangeHandler.TagChange(gameState, t.Key, entity.Key, t.Value, game); } _tmpEntities.Remove(tmpEntity); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } if (_tmpEntities.Contains(tmpEntity)) { tmpEntity.SetTag(tag, value); var player = game.Player.Name == tmpEntity.Name ? game.Player : (game.Opponent.Name == tmpEntity.Name ? game.Opponent : null); if (player != null) { var playerEntity = game.Entities.FirstOrDefault(x => x.Value.GetTag(GameTag.PLAYER_ID) == player.Id).Value; if (playerEntity != null) { playerEntity.Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { _tagChangeHandler.TagChange(gameState, t.Key, playerEntity.Id, t.Value, game); } _tmpEntities.Remove(tmpEntity); } } } } else { _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } } } else if (CreationRegex.IsMatch(logLine)) { var match = CreationRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); var cardId = EnsureValidCardID(match.Groups["cardId"].Value); var zone = GameTagHelper.ParseEnum <Zone>(match.Groups["zone"].Value); var guessedCardId = false; if (!game.Entities.ContainsKey(id)) { if (string.IsNullOrEmpty(cardId) && zone != Zone.SETASIDE) { var blockId = gameState.CurrentBlock?.Id; if (blockId.HasValue && gameState.KnownCardIds.ContainsKey(blockId.Value)) { cardId = gameState.KnownCardIds[blockId.Value].FirstOrDefault(); if (!string.IsNullOrEmpty(cardId)) { Log.Info($"Found known cardId for entity {id}: {cardId}"); gameState.KnownCardIds[blockId.Value].Remove(cardId); guessedCardId = true; } } } var entity = new Entity(id) { CardId = cardId }; if (guessedCardId) { entity.Info.GuessedCardState = GuessedCardState.Guessed; } game.Entities.Add(id, entity); if (gameState.CurrentBlock != null && (entity.CardId?.ToUpper().Contains("HERO") ?? false)) { gameState.CurrentBlock.HasFullEntityHeroPackets = true; } } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } gameState.CurrentEntityHasCardId = !string.IsNullOrEmpty(cardId); gameState.CurrentEntityZone = zone; return; } else if (UpdatingEntityRegex.IsMatch(logLine)) { var match = UpdatingEntityRegex.Match(logLine); var cardId = EnsureValidCardID(match.Groups["cardId"].Value); var rawEntity = match.Groups["entity"].Value; var type = match.Groups["type"].Value; int entityId; if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = EntityRegex.Match(rawEntity); entityId = int.Parse(entity.Groups["id"].Value); } else if (!int.TryParse(rawEntity, out entityId)) { entityId = -1; } if (entityId != -1) { if (!game.Entities.ContainsKey(entityId)) { game.Entities.Add(entityId, new Entity(entityId)); } var entity = game.Entities[entityId]; if (string.IsNullOrEmpty(entity.CardId)) { entity.CardId = cardId; } entity.Info.LatestCardId = cardId; if (type == "SHOW_ENTITY") { if (entity.Info.GuessedCardState != GuessedCardState.None) { entity.Info.GuessedCardState = GuessedCardState.Revealed; } } if (type == "CHANGE_ENTITY") { if (!entity.Info.OriginalEntityWasCreated.HasValue) { entity.Info.OriginalEntityWasCreated = entity.Info.Created; } if (entity.GetTag(GameTag.TRANSFORMED_FROM_CARD) == 46706) { gameState.ChameleosReveal = new Tuple <int, string>(entityId, cardId); } } gameState.SetCurrentEntity(entityId); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } } if (gameState.JoustReveals > 0) { if (game.Entities.TryGetValue(entityId, out Entity 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()); } } } return; } else if (CreationTagRegex.IsMatch(logLine) && !logLine.Contains("HIDE_ENTITY")) { var match = CreationTagRegex.Match(logLine); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, gameState.CurrentEntityId, match.Groups["value"].Value, game, true); creationTag = true; } else if (logLine.Contains("HIDE_ENTITY")) { var match = HideEntityRegex.Match(logLine); if (match.Success) { var id = int.Parse(match.Groups["id"].Value); if (game.Entities.TryGetValue(id, out var entity)) { if (entity.Info.GuessedCardState == GuessedCardState.Revealed) { entity.Info.GuessedCardState = GuessedCardState.Guessed; } if (gameState.CurrentBlock?.CardId == Collectible.Neutral.KingTogwaggle || gameState.CurrentBlock?.CardId == NonCollectible.Neutral.KingTogwaggle_KingsRansomToken) { entity.Info.Hidden = true; } } } } if (logLine.Contains("End Spectator") && !game.IsInMenu) { gameState.GameHandler.HandleGameEnd(false); } else if (logLine.Contains("BLOCK_START")) { var match = BlockStartRegex.Match(logLine); var blockType = match.Success ? match.Groups["type"].Value : null; var cardId = match.Success ? match.Groups["Id"].Value : null; var target = GetTargetCardId(match); var correspondPlayer = match.Success ? int.Parse(match.Groups["player"].Value) : -1; gameState.BlockStart(blockType, cardId, target); if (match.Success && (blockType == "TRIGGER" || blockType == "POWER")) { var playerEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Player.Id); var opponentEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Opponent.Id); var actionStartingCardId = match.Groups["cardId"].Value.Trim(); var actionStartingEntityId = int.Parse(match.Groups["id"].Value); Entity actionStartingEntity = null; if (string.IsNullOrEmpty(actionStartingCardId)) { if (game.Entities.TryGetValue(actionStartingEntityId, out actionStartingEntity)) { actionStartingCardId = actionStartingEntity.CardId; } } if (string.IsNullOrEmpty(actionStartingCardId)) { return; } if (actionStartingCardId == Collectible.Shaman.Shudderwock) { var effectCardId = match.Groups["effectCardId"].Value; if (!string.IsNullOrEmpty(effectCardId)) { actionStartingCardId = effectCardId; } } if (actionStartingCardId == NonCollectible.Rogue.ValeeratheHollow_ShadowReflectionToken) { actionStartingCardId = cardId; } if (blockType == "TRIGGER" && actionStartingCardId == Collectible.Neutral.AugmentedElekk) { if (gameState.CurrentBlock.Parent != null) { actionStartingCardId = gameState.CurrentBlock.Parent.CardId; blockType = gameState.CurrentBlock.Parent.Type; target = gameState.CurrentBlock.Parent.Target; } } if (blockType == "TRIGGER") { switch (actionStartingCardId) { // Todo: Add Demon Hunter case Collectible.Rogue.TradePrinceGallywix: if (!game.Entities.TryGetValue(gameState.LastCardPlayed, out var lastPlayed)) { break; } AddKnownCardId(gameState, lastPlayed.CardId); AddKnownCardId(gameState, NonCollectible.Neutral.TradePrinceGallywix_GallywixsCoinToken); break; case Collectible.Shaman.WhiteEyes: AddKnownCardId(gameState, NonCollectible.Shaman.WhiteEyes_TheStormGuardianToken); break; case Collectible.Hunter.RaptorHatchling: AddKnownCardId(gameState, NonCollectible.Hunter.RaptorHatchling_RaptorPatriarchToken); break; case Collectible.Warrior.DirehornHatchling: AddKnownCardId(gameState, NonCollectible.Warrior.DirehornHatchling_DirehornMatriarchToken); break; case Collectible.Mage.FrozenClone: AddKnownCardId(gameState, target, 2); break; case Collectible.Shaman.Moorabi: case Collectible.Rogue.SonyaShadowdancer: AddKnownCardId(gameState, target); break; case Collectible.Neutral.HoardingDragon: AddKnownCardId(gameState, NonCollectible.Neutral.TheCoinCore, 2); break; case Collectible.Priest.GildedGargoyle: AddKnownCardId(gameState, NonCollectible.Neutral.TheCoinCore); break; case Collectible.Druid.AstralTiger: AddKnownCardId(gameState, Collectible.Druid.AstralTiger); break; case Collectible.Rogue.Kingsbane: AddKnownCardId(gameState, Collectible.Rogue.Kingsbane); break; case Collectible.Neutral.WeaselTunneler: AddKnownCardId(gameState, Collectible.Neutral.WeaselTunneler); break; case Collectible.Neutral.SparkDrill: AddKnownCardId(gameState, NonCollectible.Neutral.SparkDrill_SparkToken, 2); break; case NonCollectible.Neutral.HakkartheSoulflayer_CorruptedBloodToken: AddKnownCardId(gameState, NonCollectible.Neutral.HakkartheSoulflayer_CorruptedBloodToken, 2); break; //TODO: Gral, the Shark? case Collectible.Paladin.ImmortalPrelate: AddKnownCardId(gameState, Collectible.Paladin.ImmortalPrelate); break; case Collectible.Warrior.Wrenchcalibur: AddKnownCardId(gameState, NonCollectible.Neutral.SeaforiumBomber_BombToken); break; case Collectible.Priest.SpiritOfTheDead: if (correspondPlayer == game.Player.Id) { AddKnownCardId(gameState, game.Player.LastDiedMinionCardId); } else if (correspondPlayer == game.Opponent.Id) { AddKnownCardId(gameState, game.Opponent.LastDiedMinionCardId); } break; case Collectible.Druid.SecureTheDeck: AddKnownCardId(gameState, Collectible.Druid.ClawLegacy, 3); break; case Collectible.Rogue.Waxadred: AddKnownCardId(gameState, NonCollectible.Rogue.Waxadred_WaxadredsCandleToken); break; case Collectible.Neutral.BadLuckAlbatross: AddKnownCardId(gameState, NonCollectible.Neutral.BadLuckAlbatross_AlbatrossToken, 2); break; case Collectible.Priest.ReliquaryOfSouls: AddKnownCardId(gameState, NonCollectible.Priest.ReliquaryofSouls_ReliquaryPrimeToken); break; case Collectible.Mage.AstromancerSolarian: AddKnownCardId(gameState, NonCollectible.Mage.AstromancerSolarian_SolarianPrimeToken); break; case Collectible.Warlock.KanrethadEbonlocke: AddKnownCardId(gameState, NonCollectible.Warlock.KanrethadEbonlocke_KanrethadPrimeToken); break; case Collectible.Paladin.MurgurMurgurgle: AddKnownCardId(gameState, NonCollectible.Paladin.MurgurMurgurgle_MurgurglePrimeToken); break; case Collectible.Rogue.Akama: AddKnownCardId(gameState, NonCollectible.Rogue.Akama_AkamaPrimeToken); break; case Collectible.Druid.ArchsporeMsshifn: AddKnownCardId(gameState, NonCollectible.Druid.ArchsporeMsshifn_MsshifnPrimeToken); break; case Collectible.Shaman.LadyVashj: AddKnownCardId(gameState, NonCollectible.Shaman.LadyVashj_VashjPrimeToken); break; case Collectible.Hunter.ZixorApexPredator: AddKnownCardId(gameState, NonCollectible.Hunter.ZixorApexPredator_ZixorPrimeToken); break; case Collectible.Warrior.KargathBladefist: AddKnownCardId(gameState, NonCollectible.Warrior.KargathBladefist_KargathPrimeToken); break; case Collectible.Neutral.SneakyDelinquent: AddKnownCardId(gameState, NonCollectible.Neutral.SneakyDelinquent_SpectralDelinquentToken); break; case Collectible.Neutral.FishyFlyer: AddKnownCardId(gameState, NonCollectible.Neutral.FishyFlyer_SpectralFlyerToken); break; case Collectible.Neutral.SmugSenior: AddKnownCardId(gameState, NonCollectible.Neutral.SmugSenior_SpectralSeniorToken); break; case Collectible.Rogue.Plagiarize: if (actionStartingEntity != null) { var player = actionStartingEntity.IsControlledBy(game.Player.Id) ? game.Opponent : game.Player; foreach (var card in player.CardsPlayedThisTurn) { AddKnownCardId(gameState, card); } } break; case Collectible.Neutral.KeymasterAlabaster: // The player controlled side of this is handled by TagChangeActions.OnCardCopy if (actionStartingEntity != null && actionStartingEntity.IsControlledBy(game.Opponent.Id) && game.Player.LastDrawnCardId != null) { AddKnownCardId(gameState, game.Player.LastDrawnCardId); } break; case Collectible.Neutral.EducatedElekk: if (actionStartingEntity != null) { if (actionStartingEntity.IsInGraveyard) { foreach (var card in actionStartingEntity.Info.StoredCardIds) { AddKnownCardId(gameState, card); } } else if (game.Entities.TryGetValue(gameState.LastCardPlayed, out var lastPlayedEntity) && lastPlayedEntity.CardId != null) { actionStartingEntity.Info.StoredCardIds.Add(lastPlayedEntity.CardId); } } break; case Collectible.Shaman.DiligentNotetaker: if (game.Entities.TryGetValue(gameState.LastCardPlayed, out var lastPlayedEntity1) && lastPlayedEntity1.CardId != null) { AddKnownCardId(gameState, lastPlayedEntity1.CardId); } break; case Collectible.Neutral.CthunTheShattered: // The pieces are created in random order. So we can not assign predicted ids to entities the way we usually do. if (actionStartingEntity != null) { var player = actionStartingEntity.IsControlledBy(game.Player.Id) ? game.Player : game.Opponent; player.PredictUniqueCardInDeck(NonCollectible.Neutral.CThuntheShattered_EyeOfCthunToken, true); player.PredictUniqueCardInDeck(NonCollectible.Neutral.CThuntheShattered_BodyOfCthunToken, true); player.PredictUniqueCardInDeck(NonCollectible.Neutral.CThuntheShattered_MawOfCthunToken, true); player.PredictUniqueCardInDeck(NonCollectible.Neutral.CThuntheShattered_HeartOfCthunToken, true); } break; } } else //POWER { switch (actionStartingCardId) { // Todo: Add Demon Hunter case Collectible.Rogue.GangUp: case Collectible.Hunter.DireFrenzy: case Collectible.Rogue.LabRecruiter: AddKnownCardId(gameState, target, 3); break; case Collectible.Rogue.BeneathTheGrounds: AddKnownCardId(gameState, NonCollectible.Rogue.BeneaththeGrounds_NerubianAmbushToken, 3); break; case Collectible.Warrior.IronJuggernaut: AddKnownCardId(gameState, NonCollectible.Warrior.IronJuggernaut_BurrowingMineToken); break; case Collectible.Druid.Recycle: case Collectible.Mage.ManicSoulcaster: case Collectible.Neutral.ZolaTheGorgon: case Collectible.Druid.Splintergraft: //case Collectible.Priest.HolyWater: -- TODO case Collectible.Neutral.BalefulBanker: case Collectible.Neutral.DollmasterDorian: case Collectible.Priest.Seance: AddKnownCardId(gameState, target); break; case Collectible.Druid.MarkOfTheSpikeshell: AddKnownCardId(gameState, target); break; case Collectible.Mage.ForgottenTorch: AddKnownCardId(gameState, NonCollectible.Mage.ForgottenTorch_RoaringTorchToken); break; case Collectible.Warlock.CurseOfRafaam: AddKnownCardId(gameState, NonCollectible.Warlock.CurseofRafaam_CursedToken); break; case Collectible.Neutral.AncientShade: AddKnownCardId(gameState, NonCollectible.Neutral.AncientShade_AncientCurseToken); break; case Collectible.Priest.ExcavatedEvil: AddKnownCardId(gameState, Collectible.Priest.ExcavatedEvil); break; case Collectible.Neutral.EliseStarseeker: AddKnownCardId(gameState, NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken); break; case NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken: AddKnownCardId(gameState, NonCollectible.Neutral.EliseStarseeker_GoldenMonkeyToken); break; case Collectible.Neutral.Doomcaller: AddKnownCardId(gameState, NonCollectible.Neutral.Cthun); break; case Collectible.Druid.JadeIdol: AddKnownCardId(gameState, Collectible.Druid.JadeIdol, 3); break; case NonCollectible.Hunter.TheMarshQueen_QueenCarnassaToken: AddKnownCardId(gameState, NonCollectible.Hunter.TheMarshQueen_CarnassasBroodToken, 15); break; case Collectible.Neutral.EliseTheTrailblazer: AddKnownCardId(gameState, NonCollectible.Neutral.ElisetheTrailblazer_UngoroPackToken); break; case Collectible.Mage.GhastlyConjurer: AddKnownCardId(gameState, Collectible.Mage.MirrorImageLegacy); break; case Collectible.Druid.ThorngrowthSentries: AddKnownCardId(gameState, NonCollectible.Druid.ThorngrowthSentries_ThornguardTurtleToken, 2); break; case Collectible.Mage.DeckOfWonders: AddKnownCardId(gameState, NonCollectible.Mage.DeckofWonders_ScrollOfWonderToken, 5); break; case Collectible.Neutral.TheDarkness: AddKnownCardId(gameState, NonCollectible.Neutral.TheDarkness_DarknessCandleToken, 3); break; case Collectible.Rogue.FaldoreiStrider: AddKnownCardId(gameState, NonCollectible.Rogue.FaldoreiStrider_SpiderAmbushEnchantment, 3); break; case Collectible.Neutral.KingTogwaggle: AddKnownCardId(gameState, NonCollectible.Neutral.KingTogwaggle_KingsRansomToken); break; case NonCollectible.Neutral.TheCandle: AddKnownCardId(gameState, NonCollectible.Neutral.TheCandle); break; case NonCollectible.Neutral.CoinPouchGILNEAS: AddKnownCardId(gameState, NonCollectible.Neutral.SackOfCoinsGILNEAS); break; case NonCollectible.Neutral.SackOfCoinsGILNEAS: AddKnownCardId(gameState, NonCollectible.Neutral.HeftySackOfCoinsGILNEAS); break; case NonCollectible.Neutral.CreepyCurioGILNEAS: AddKnownCardId(gameState, NonCollectible.Neutral.HauntedCurioGILNEAS); break; case NonCollectible.Neutral.HauntedCurioGILNEAS: AddKnownCardId(gameState, NonCollectible.Neutral.CursedCurioGILNEAS); break; case NonCollectible.Neutral.OldMilitiaHornGILNEAS: AddKnownCardId(gameState, NonCollectible.Neutral.MilitiaHornGILNEAS); break; case NonCollectible.Neutral.MilitiaHornGILNEAS: AddKnownCardId(gameState, NonCollectible.Neutral.VeteransMilitiaHornGILNEAS); break; case NonCollectible.Neutral.SurlyMobGILNEAS: AddKnownCardId(gameState, NonCollectible.Neutral.AngryMobGILNEAS); break; case NonCollectible.Neutral.AngryMobGILNEAS: AddKnownCardId(gameState, NonCollectible.Neutral.CrazedMobGILNEAS); break; case Collectible.Neutral.SparkEngine: AddKnownCardId(gameState, NonCollectible.Neutral.SparkDrill_SparkToken); break; case Collectible.Priest.ExtraArms: AddKnownCardId(gameState, NonCollectible.Priest.ExtraArms_MoreArmsToken); break; case Collectible.Neutral.SeaforiumBomber: case Collectible.Warrior.ClockworkGoblin: AddKnownCardId(gameState, NonCollectible.Neutral.SeaforiumBomber_BombToken); break; //case Collectible.Rogue.Wanted: -- TODO // AddKnownCardId(gameState, NonCollectible.Neutral.TheCoin); // break; //TODO: Hex Lord Malacrass //TODO: Krag'wa, the Frog case Collectible.Hunter.HalazziTheLynx: AddKnownCardId(gameState, NonCollectible.Hunter.Springpaw_LynxToken, 10); break; case Collectible.Neutral.BananaVendor: AddKnownCardId(gameState, NonCollectible.Neutral.BananaBuffoon_BananasToken, 4); break; case Collectible.Neutral.BananaBuffoon: AddKnownCardId(gameState, NonCollectible.Neutral.BananaBuffoon_BananasToken, 2); break; case Collectible.Neutral.BootyBayBookie: AddKnownCardId(gameState, NonCollectible.Neutral.TheCoinCore); break; case Collectible.Neutral.PortalKeeper: case Collectible.Neutral.PortalOverfiend: AddKnownCardId(gameState, NonCollectible.Neutral.PortalKeeper_FelhoundPortalToken); break; case Collectible.Rogue.TogwagglesScheme: AddKnownCardId(gameState, target); break; case Collectible.Paladin.SandwaspQueen: AddKnownCardId(gameState, NonCollectible.Paladin.SandwaspQueen_SandwaspToken, 2); break; case Collectible.Rogue.ShadowOfDeath: AddKnownCardId(gameState, NonCollectible.Rogue.ShadowofDeath_ShadowToken, 3); break; case Collectible.Warlock.Impbalming: AddKnownCardId(gameState, NonCollectible.Warlock.Impbalming_WorthlessImpToken, 3); break; case Collectible.Druid.YseraUnleashed: AddKnownCardId(gameState, NonCollectible.Druid.YseraUnleashed_DreamPortalToken, 7); break; case Collectible.Rogue.BloodsailFlybooter: AddKnownCardId(gameState, NonCollectible.Rogue.BloodsailFlybooter_SkyPirateToken, 2); break; case Collectible.Rogue.UmbralSkulker: AddKnownCardId(gameState, NonCollectible.Neutral.TheCoinCore, 3); break; case Collectible.Neutral.Sathrovarr: AddKnownCardId(gameState, target, 3); break; case Collectible.Neutral.DragonBreeder: AddKnownCardId(gameState, target); break; case Collectible.Warlock.SchoolSpirits: case Collectible.Warlock.SoulShear: case Collectible.Warlock.SpiritJailer: case Collectible.Demonhunter.Marrowslicer: AddKnownCardId(gameState, NonCollectible.Warlock.SchoolSpirits_SoulFragmentToken, 2); break; case Collectible.Mage.ConfectionCyclone: AddKnownCardId(gameState, NonCollectible.Mage.ConfectionCyclone_SugarElementalToken, 2); break; case Collectible.Druid.KiriChosenOfElune: AddKnownCardId(gameState, Collectible.Druid.LunarEclipse); AddKnownCardId(gameState, Collectible.Druid.SolarEclipse); break; case NonCollectible.Neutral.CThuntheShattered_EyeOfCthunToken: case NonCollectible.Neutral.CThuntheShattered_HeartOfCthunToken: case NonCollectible.Neutral.CThuntheShattered_BodyOfCthunToken: case NonCollectible.Neutral.CThuntheShattered_MawOfCthunToken: // A new copy of C'Thun is created in the last of these POWER blocks. // This currently leads to a duplicate copy of C'Thun showing up in the // opponents deck list, but it will have to do for now. AddKnownCardId(gameState, Collectible.Neutral.CthunTheShattered); break; case Collectible.Hunter.SunscaleRaptor: AddKnownCardId(gameState, Collectible.Hunter.SunscaleRaptor); break; case Collectible.Neutral.Mankrik: AddKnownCardId(gameState, NonCollectible.Neutral.Mankrik_OlgraMankriksWifeToken); break; case Collectible.Neutral.ShadowHunterVoljin: AddKnownCardId(gameState, target); break; default: if (playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.PlayerUsedHeroPower || opponentEntity.Value != null && opponentEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.OpponentUsedHeroPower) { var card = Database.GetCardFromId(actionStartingCardId); if (card.Type == "Hero Power") { if (playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.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; } else if (logLine.Contains("BlockType=REVEAL_CARD")) { gameState.JoustReveals = 1; } else if (gameState.GameTriggerCount == 0 && logLine.Contains("BLOCK_START BlockType=TRIGGER Entity=GameEntity")) { gameState.GameTriggerCount++; } } else if (logLine.Contains("CREATE_GAME")) { _tagChangeHandler.ClearQueuedActions(); } else if (logLine.Contains("BLOCK_END")) { if (gameState.GameTriggerCount < 10 && (game.GameEntity?.HasTag(GameTag.TURN) ?? false)) { gameState.GameTriggerCount += 10; _tagChangeHandler.InvokeQueuedActions(game); game.SetupDone = true; } if (gameState.CurrentBlock?.Type == "JOUST" || gameState.CurrentBlock?.Type == "REVEAL_CARD") { //make sure there are no more queued actions that might depend on JoustReveals _tagChangeHandler.InvokeQueuedActions(game); gameState.JoustReveals = 0; } if (gameState.CurrentBlock?.Type == "TRIGGER" && (gameState.CurrentBlock?.CardId == NonCollectible.Neutral.Chameleos_ShiftingEnchantment || gameState.CurrentBlock?.CardId == Collectible.Priest.Chameleos) && gameState.ChameleosReveal != null && game.Entities.TryGetValue(gameState.ChameleosReveal.Item1, out var chameleos) && chameleos.HasTag(GameTag.SHIFTING)) { gameState.GameHandler.HandleChameleosReveal(gameState.ChameleosReveal.Item2); } gameState.ChameleosReveal = null; if (gameState.CurrentBlock?.Type == "TRIGGER" && gameState.CurrentBlock?.CardId == NonCollectible.Neutral.Baconshop8playerenchantTavernBrawl && gameState.CurrentBlock?.HasFullEntityHeroPackets == true && gameState.Turn % 2 == 0) { game.SnapshotBattlegroundsBoardState(); if (game.CurrentGameStats != null) { BobsBuddyInvoker.GetInstance(game.CurrentGameStats.GameId, gameState.GetTurnNumber())? .StartCombat(); } } gameState.BlockEnd(); } if (game.IsInMenu) { return; } if (!creationTag && gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } if (!creationTag) { gameState.ResetCurrentEntity(); } }
private void ZoneChangeFromHand(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { if (!game.Entities.TryGetValue(id, out var entity)) { return; } switch ((Zone)value) { case PLAY: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerPlay(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentPlay(entity, cardId, entity.GetTag(ZONE_POSITION), gameState.GetTurnNumber()); } break; case REMOVEDFROMGAME: case SETASIDE: case GRAVEYARD: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerHandDiscard(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentHandDiscard(entity, cardId, entity.GetTag(ZONE_POSITION), gameState.GetTurnNumber()); } break; case Zone.SECRET: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerSecretPlayed(entity, cardId, gameState.GetTurnNumber(), (Zone)prevValue); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentSecretPlayed(entity, cardId, entity.GetTag(ZONE_POSITION), gameState.GetTurnNumber(), (Zone)prevValue, id); } break; case DECK: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerMulligan(entity, cardId); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentMulligan(entity, entity.GetTag(ZONE_POSITION)); } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
private void ZoneChangeFromSecret(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { switch ((Zone)value) { case Zone.SECRET: case GRAVEYARD: if (controller == game.Opponent.Id) { if (!game.Entities.TryGetValue(id, out var entity)) { return; } gameState.GameHandler.HandleOpponentSecretTrigger(entity, cardId, gameState.GetTurnNumber(), id); } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
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()); } } }
private void ZoneChangeFromSecret(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { switch((Zone)value) { case Zone.SECRET: case GRAVEYARD: if(controller == game.Player.Id) gameState.ProposeKeyPoint(SecretTriggered, id, ActivePlayer.Player); if(controller == game.Opponent.Id) { Entity entity; if(!game.Entities.TryGetValue(id, out entity)) return; gameState.GameHandler.HandleOpponentSecretTrigger(entity, cardId, gameState.GetTurnNumber(), id); gameState.ProposeKeyPoint(SecretTriggered, id, ActivePlayer.Opponent); } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
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) { 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.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; } }
private static void ZoneChangeFromDeck(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { 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) && gameState.SetupDone) { #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; } }
private static void ZoneChangeFromHand(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { 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; } }
private static void ZoneChangeFromPlay(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { 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; } }
private static void ZoneChangeFromSecret(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { 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; } }
private static void ZoneChangeFromOther(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { 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; } }
private static void CurrentPlayerChange(IHsGameState gameState, int id, IGame game, int value) { if(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; } }
private void ZoneChangeFromOther(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { var entity = game.Entities[id]; if (entity.Info.OriginalZone == DECK && value != (int)DECK) { //This entity was moved from DECK to SETASIDE to HAND, e.g. by Tracking entity.Info.Discarded = false; ZoneChangeFromDeck(gameState, id, game, value, prevValue, controller, cardId); return; } entity.Info.Created = true; switch ((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; case Zone.SECRET: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerSecretPlayed(game.Entities[id], cardId, gameState.GetTurnNumber(), (Zone)prevValue); gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Player); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentSecretPlayed(game.Entities[id], cardId, -1, gameState.GetTurnNumber(), (Zone)prevValue, id); gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Opponent); } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
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(GameEntityRegex.IsMatch(logLine)) { gameState.GameHandler.HandleGameStart(); gameState.GameEnded = false; gameState.AddToTurn = -1; var match = 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(PlayerEntityRegex.IsMatch(logLine)) { var match = 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(TagChangeRegex.IsMatch(logLine)) { var match = TagChangeRegex.Match(logLine); var rawEntity = match.Groups["entity"].Value.Replace("UNKNOWN ENTITY ", ""); int entityId; if(rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = 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) {Name = rawEntity}; _tmpEntities.Add(tmpEntity); } GAME_TAG tag; Enum.TryParse(match.Groups["tag"].Value, out tag); var value = LogReaderHelper.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(EntityNameRegex.IsMatch(logLine)) { match = 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(CreationRegex.IsMatch(logLine)) { var match = 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($"Found known cardId for entity {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(UpdatingEntityRegex.IsMatch(logLine)) { var match = UpdatingEntityRegex.Match(logLine); var cardId = match.Groups["cardId"].Value; var rawEntity = match.Groups["entity"].Value; int entityId; if(rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = 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(CreationTagRegex.IsMatch(logLine) && !logLine.Contains("HIDE_ENTITY")) { var match = 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(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 = 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) && targetEntity.IsMinion; gameState.GameHandler.HandlePlayerSpellPlayed(targetsMinion); } } if(string.IsNullOrEmpty(actionStartingCardId)) return; if(match.Groups["type"].Value == "TRIGGER") { switch(actionStartingCardId) { case Collectible.Rogue.TradePrinceGallywix: AddKnownCardId(gameState, game, game.Entities[gameState.LastCardPlayed].CardId); AddKnownCardId(gameState, game, NonCollectible.Neutral.GallywixsCoinToken); break; } } else //POWER { switch(actionStartingCardId) { case Collectible.Rogue.GangUp: AddTargetAsKnownCardId(gameState, game, match, 3); break; case Collectible.Rogue.BeneathTheGrounds: AddKnownCardId(gameState, game, NonCollectible.Rogue.AmbushToken, 3); break; case Collectible.Warrior.IronJuggernaut: AddKnownCardId(gameState, game, NonCollectible.Warrior.BurrowingMineToken); break; case Collectible.Druid.Recycle: AddTargetAsKnownCardId(gameState, game, match); break; case Collectible.Mage.ForgottenTorch: AddKnownCardId(gameState, game, NonCollectible.Mage.RoaringTorchToken); break; case Collectible.Warlock.CurseOfRafaam: AddKnownCardId(gameState, game, NonCollectible.Warlock.CursedToken); break; case Collectible.Neutral.AncientShade: AddKnownCardId(gameState, game, NonCollectible.Neutral.AncientCurseToken); break; case Collectible.Priest.ExcavatedEvil: AddKnownCardId(gameState, game, Collectible.Priest.ExcavatedEvil); break; case Collectible.Neutral.EliseStarseeker: AddKnownCardId(gameState, game, NonCollectible.Neutral.MapToTheGoldenMonkeyToken); break; case NonCollectible.Neutral.MapToTheGoldenMonkeyToken: AddKnownCardId(gameState, game, 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; } } }
private void ControllerChange(IHsGameState gameState, int id, IGame game, int prevValue, int value) { Entity entity; if(!game.Entities.TryGetValue(id, out entity)) return; if(prevValue <= 0) { entity.Info.OriginalController = value; return; } if(entity.HasTag(PLAYER_ID)) return; if(value == game.Player.Id) { if(entity.IsInZone(Zone.SECRET)) { gameState.GameHandler.HandleOpponentStolen(entity, entity.CardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(SecretStolen, id, ActivePlayer.Player); } else if(entity.IsInZone(PLAY)) gameState.GameHandler.HandleOpponentStolen(entity, entity.CardId, gameState.GetTurnNumber()); } else if(value == game.Opponent.Id) { if(entity.IsInZone(Zone.SECRET)) { gameState.GameHandler.HandlePlayerStolen(entity, entity.CardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(SecretStolen, id, ActivePlayer.Player); } else if(entity.IsInZone(PLAY)) gameState.GameHandler.HandlePlayerStolen(entity, entity.CardId, gameState.GetTurnNumber()); } }
public void Handle(string logLine, IHsGameState gameState, IGame game) { var setup = false; var creationTag = false; if (GameEntityRegex.IsMatch(logLine)) { var match = GameEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id) { Name = "GameEntity" }); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } return; } else if (PlayerEntityRegex.IsMatch(logLine)) { var match = PlayerEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id)); } if (gameState.WasInProgress) { game.Entities[id].Name = game.GetStoredPlayerName(id); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } return; } else if (TagChangeRegex.IsMatch(logLine)) { var match = TagChangeRegex.Match(logLine); var rawEntity = match.Groups["entity"].Value.Replace("UNKNOWN ENTITY ", ""); int entityId; if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = 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) { var players = game.Entities.Where(x => x.Value.HasTag(GameTag.PLAYER_ID)).Take(2).ToList(); var unnamedPlayers = players.Where(x => string.IsNullOrEmpty(x.Value.Name)).ToList(); var unknownHumanPlayer = players.FirstOrDefault(x => x.Value.Name == "UNKNOWN HUMAN PLAYER"); if (unnamedPlayers.Count == 0 && unknownHumanPlayer.Value != null) { Log.Info("Updating UNKNOWN HUMAN PLAYER"); entity = unknownHumanPlayer; SetPlayerName(game, entity.Value.GetTag(GameTag.PLAYER_ID), rawEntity); } //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) { Name = rawEntity }; _tmpEntities.Add(tmpEntity); } GameTag tag; Enum.TryParse(match.Groups["tag"].Value, out tag); var value = LogReaderHelper.ParseTag(tag, match.Groups["value"].Value); if (unnamedPlayers.Count == 1) { entity = unnamedPlayers.Single(); } else if (unnamedPlayers.Count == 2 && tag == GameTag.CURRENT_PLAYER && value == 0) { entity = game.Entities.FirstOrDefault(x => x.Value?.HasTag(GameTag.CURRENT_PLAYER) ?? false); } if (entity.Value != null) { entity.Value.Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { _tagChangeHandler.TagChange(gameState, t.Key, entity.Key, t.Value, game); } SetPlayerName(game, entity.Value.GetTag(GameTag.PLAYER_ID), tmpEntity.Name); _tmpEntities.Remove(tmpEntity); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } if (_tmpEntities.Contains(tmpEntity)) { tmpEntity.SetTag(tag, value); if (tmpEntity.HasTag(GameTag.ENTITY_ID)) { var id = tmpEntity.GetTag(GameTag.ENTITY_ID); if (game.Entities.ContainsKey(id)) { game.Entities[id].Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { _tagChangeHandler.TagChange(gameState, t.Key, id, t.Value, game); } _tmpEntities.Remove(tmpEntity); } else { Log.Warn("TMP ENTITY (" + rawEntity + ") NOW HAS A KEY, BUT GAME.ENTITIES DOES NOT CONTAIN THIS KEY"); } } } } else { _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } } if (EntityNameRegex.IsMatch(logLine)) { match = EntityNameRegex.Match(logLine); var name = match.Groups["name"].Value; var player = int.Parse(match.Groups["value"].Value); SetPlayerName(game, player, name); } } else if (CreationRegex.IsMatch(logLine)) { var match = 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)) { Log.Info($"Found known cardId for entity {id}: {cardId}"); gameState.KnownCardIds.Remove(id); } } game.Entities.Add(id, new Entity(id) { CardId = cardId }); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } gameState.CurrentEntityHasCardId = !string.IsNullOrEmpty(cardId); gameState.CurrentEntityZone = LogReaderHelper.ParseEnum <Zone>(match.Groups["zone"].Value); return; } else if (UpdatingEntityRegex.IsMatch(logLine)) { var match = UpdatingEntityRegex.Match(logLine); var cardId = match.Groups["cardId"].Value; var rawEntity = match.Groups["entity"].Value; int entityId; if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = EntityRegex.Match(rawEntity); entityId = int.Parse(entity.Groups["id"].Value); } else if (!int.TryParse(rawEntity, out entityId)) { entityId = -1; } if (entityId != -1) { if (!game.Entities.ContainsKey(entityId)) { game.Entities.Add(entityId, new Entity(entityId)); } game.Entities[entityId].CardId = cardId; gameState.SetCurrentEntity(entityId); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } } 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--; } return; } else if (CreationTagRegex.IsMatch(logLine) && !logLine.Contains("HIDE_ENTITY")) { var match = CreationTagRegex.Match(logLine); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, gameState.CurrentEntityId, match.Groups["value"].Value, game, true); setup = true; creationTag = true; } 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 (BlockStartRegex.IsMatch(logLine)) { var playerEntity = game.Entities.FirstOrDefault(e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Player.Id); var opponentEntity = game.Entities.FirstOrDefault(e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Opponent.Id); var match = BlockStartRegex.Match(logLine); var actionStartingCardId = match.Groups["cardId"].Value.Trim(); var actionStartingEntityId = int.Parse(match.Groups["id"].Value); if (string.IsNullOrEmpty(actionStartingCardId)) { Entity actionEntity; if (game.Entities.TryGetValue(actionStartingEntityId, out actionEntity)) { actionStartingCardId = actionEntity.CardId; } } if (string.IsNullOrEmpty(actionStartingCardId)) { return; } if (match.Groups["type"].Value == "TRIGGER") { switch (actionStartingCardId) { case Collectible.Rogue.TradePrinceGallywix: AddKnownCardId(gameState, game, game.Entities[gameState.LastCardPlayed].CardId); AddKnownCardId(gameState, game, NonCollectible.Neutral.TradePrinceGallywix_GallywixsCoinToken); break; } } else //POWER { switch (actionStartingCardId) { case Collectible.Rogue.GangUp: AddTargetAsKnownCardId(gameState, game, match, 3); break; case Collectible.Rogue.BeneathTheGrounds: AddKnownCardId(gameState, game, NonCollectible.Rogue.BeneaththeGrounds_AmbushToken, 3); break; case Collectible.Warrior.IronJuggernaut: AddKnownCardId(gameState, game, NonCollectible.Warrior.IronJuggernaut_BurrowingMineToken); break; case Collectible.Druid.Recycle: AddTargetAsKnownCardId(gameState, game, match); break; case Collectible.Mage.ForgottenTorch: AddKnownCardId(gameState, game, NonCollectible.Mage.ForgottenTorch_RoaringTorchToken); break; case Collectible.Warlock.CurseOfRafaam: AddKnownCardId(gameState, game, NonCollectible.Warlock.CurseofRafaam_CursedToken); break; case Collectible.Neutral.AncientShade: AddKnownCardId(gameState, game, NonCollectible.Neutral.AncientShade_AncientCurseToken); break; case Collectible.Priest.ExcavatedEvil: AddKnownCardId(gameState, game, Collectible.Priest.ExcavatedEvil); break; case Collectible.Neutral.EliseStarseeker: AddKnownCardId(gameState, game, NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken); break; case NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken: AddKnownCardId(gameState, game, NonCollectible.Neutral.EliseStarseeker_GoldenMonkeyToken); break; default: if (playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.PlayerUsedHeroPower || opponentEntity.Value != null && opponentEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.OpponentUsedHeroPower) { var card = Database.GetCardFromId(actionStartingCardId); if (card.Type == "Hero Power") { if (playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.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; } else if (logLine.Contains("CREATE_GAME")) { setup = true; _tagChangeHandler.ClearQueuedActions(); } if (game.IsInMenu) { return; } if (!creationTag && gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } if (!creationTag) { gameState.ResetCurrentEntity(); } if (!gameState.DeterminedPlayers && gameState.SetupDone) { if ((DateTime.Now - _lastDeterminePlayersWarning1).TotalSeconds > 5) { Log.Warn("Could not determine players by checking for opponent hand."); _lastDeterminePlayersWarning1 = DateTime.Now; } var playerCard = game.Entities.FirstOrDefault(x => x.Value.IsInHand && !string.IsNullOrEmpty(x.Value.CardId)).Value; if (playerCard != null) { _tagChangeHandler.DeterminePlayers(gameState, game, playerCard.GetTag(GameTag.CONTROLLER), false); } else if ((DateTime.Now - _lastDeterminePlayersWarning2).TotalSeconds > 5) { Log.Warn("Could not determine players by checking for player hand either... waiting for draws..."); _lastDeterminePlayersWarning2 = DateTime.Now; } } if (!setup) { gameState.SetupDone = true; } }
private void ZoneChangeFromHand(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { Entity entity; if(!game.Entities.TryGetValue(id, out entity)) return; switch((Zone)value) { case PLAY: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerPlay(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(Play, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentPlay(entity, cardId, entity.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(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(HandDiscard, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentHandDiscard(entity, cardId, entity.GetTag(ZONE_POSITION), gameState.GetTurnNumber()); gameState.ProposeKeyPoint(HandDiscard, id, ActivePlayer.Opponent); } break; case Zone.SECRET: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerSecretPlayed(entity, cardId, gameState.GetTurnNumber(), (Zone)prevValue); gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentSecretPlayed(entity, cardId, entity.GetTag(ZONE_POSITION), gameState.GetTurnNumber(), (Zone)prevValue, id); gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Opponent); } break; case DECK: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerMulligan(entity, cardId); gameState.ProposeKeyPoint(KeyPointType.Mulligan, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentMulligan(entity, entity.GetTag(ZONE_POSITION)); gameState.ProposeKeyPoint(KeyPointType.Mulligan, id, ActivePlayer.Opponent); } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
public void Handle(string logLine, IHsGameState gameState, IGame game) { if (GameEntityRegex.IsMatch(logLine)) { var match = GameEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id) { Name = "GameEntity" }); } gameState.CurrentEntityId = id; } else if (PlayerEntityRegex.IsMatch(logLine)) { var match = 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 (TagChangeRegex.IsMatch(logLine)) { var match = TagChangeRegex.Match(logLine); var rawEntity = match.Groups["entity"].Value.Replace("UNKNOWN ENTITY ", ""); int entityId; if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = 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) { Name = rawEntity }; _tmpEntities.Add(tmpEntity); } GAME_TAG tag; Enum.TryParse(match.Groups["tag"].Value, out tag); var value = LogReaderHelper.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 { Log.Warn("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 (EntityNameRegex.IsMatch(logLine)) { match = 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 (CreationRegex.IsMatch(logLine)) { var match = 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)) { Log.Info($"Found known cardId for entity {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 (UpdatingEntityRegex.IsMatch(logLine)) { var match = UpdatingEntityRegex.Match(logLine); var cardId = match.Groups["cardId"].Value; var rawEntity = match.Groups["entity"].Value; int entityId; if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = 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 (CreationTagRegex.IsMatch(logLine) && !logLine.Contains("HIDE_ENTITY")) { var match = 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 (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 = ActionStartRegex.Match(logLine); var actionStartingCardId = match.Groups["cardId"].Value.Trim(); var actionStartingEntityId = int.Parse(match.Groups["id"].Value); if (string.IsNullOrEmpty(actionStartingCardId)) { Entity actionEntity; if (game.Entities.TryGetValue(actionStartingEntityId, out actionEntity)) { actionStartingCardId = actionEntity.CardId; } } if (string.IsNullOrEmpty(actionStartingCardId)) { return; } if (match.Groups["type"].Value == "TRIGGER") { switch (actionStartingCardId) { case Collectible.Rogue.TradePrinceGallywix: AddKnownCardId(gameState, game, game.Entities[gameState.LastCardPlayed].CardId); AddKnownCardId(gameState, game, NonCollectible.Neutral.GallywixsCoinToken); break; } } else //POWER { switch (actionStartingCardId) { case Collectible.Rogue.GangUp: AddTargetAsKnownCardId(gameState, game, match, 3); break; case Collectible.Rogue.BeneathTheGrounds: AddKnownCardId(gameState, game, NonCollectible.Rogue.AmbushToken, 3); break; case Collectible.Warrior.IronJuggernaut: AddKnownCardId(gameState, game, NonCollectible.Warrior.BurrowingMineToken); break; case Collectible.Druid.Recycle: AddTargetAsKnownCardId(gameState, game, match); break; case Collectible.Mage.ForgottenTorch: AddKnownCardId(gameState, game, NonCollectible.Mage.RoaringTorchToken); break; case Collectible.Warlock.CurseOfRafaam: AddKnownCardId(gameState, game, NonCollectible.Warlock.CursedToken); break; case Collectible.Neutral.AncientShade: AddKnownCardId(gameState, game, NonCollectible.Neutral.AncientCurseToken); break; case Collectible.Priest.ExcavatedEvil: AddKnownCardId(gameState, game, Collectible.Priest.ExcavatedEvil); break; case Collectible.Neutral.EliseStarseeker: AddKnownCardId(gameState, game, NonCollectible.Neutral.MapToTheGoldenMonkeyToken); break; case NonCollectible.Neutral.MapToTheGoldenMonkeyToken: AddKnownCardId(gameState, game, 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 Handle(string logLine, IHsGameState gameState, IGame game) { var creationTag = false; if (GameEntityRegex.IsMatch(logLine)) { var match = GameEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id) { Name = "GameEntity" }); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } return; } if (PlayerEntityRegex.IsMatch(logLine)) { var match = PlayerEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id)); } if (gameState.WasInProgress) { game.Entities[id].Name = game.GetStoredPlayerName(id); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } return; } if (TagChangeRegex.IsMatch(logLine)) { var match = TagChangeRegex.Match(logLine); var rawEntity = match.Groups["entity"].Value.Replace("UNKNOWN ENTITY ", ""); if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = 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 int 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) { var players = game.Entities.Where(x => x.Value.HasTag(GameTag.PLAYER_ID)).Take(2).ToList(); var unnamedPlayers = players.Where(x => string.IsNullOrEmpty(x.Value.Name)).ToList(); var unknownHumanPlayer = players.FirstOrDefault(x => x.Value.Name == "UNKNOWN HUMAN PLAYER"); if (unnamedPlayers.Count == 0 && unknownHumanPlayer.Value != null) { Log.Info("Updating UNKNOWN HUMAN PLAYER"); entity = unknownHumanPlayer; } //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) { Name = rawEntity }; _tmpEntities.Add(tmpEntity); } Enum.TryParse(match.Groups["tag"].Value, out GameTag tag); var value = GameTagHelper.ParseTag(tag, match.Groups["value"].Value); if (unnamedPlayers.Count == 1) { entity = unnamedPlayers.Single(); } else if (unnamedPlayers.Count == 2 && tag == GameTag.CURRENT_PLAYER && value == 0) { entity = game.Entities.FirstOrDefault(x => x.Value?.HasTag(GameTag.CURRENT_PLAYER) ?? false); } if (entity.Value != null) { entity.Value.Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { _tagChangeHandler.TagChange(gameState, t.Key, entity.Key, t.Value, game); } _tmpEntities.Remove(tmpEntity); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } if (_tmpEntities.Contains(tmpEntity)) { tmpEntity.SetTag(tag, value); var player = game.Player.Name == tmpEntity.Name ? game.Player : (game.Opponent.Name == tmpEntity.Name ? game.Opponent : null); if (player != null) { var playerEntity = game.Entities.FirstOrDefault(x => x.Value.GetTag(GameTag.PLAYER_ID) == player.Id).Value; if (playerEntity != null) { playerEntity.Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { _tagChangeHandler.TagChange(gameState, t.Key, playerEntity.Id, t.Value, game); } _tmpEntities.Remove(tmpEntity); } } } } else { _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } } } else if (CreationRegex.IsMatch(logLine)) { var match = CreationRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); var cardId = match.Groups["cardId"].Value; var zone = GameTagHelper.ParseEnum <Zone>(match.Groups["zone"].Value); if (!game.Entities.ContainsKey(id)) { if (string.IsNullOrEmpty(cardId) && zone != Zone.SETASIDE) { var blockId = gameState.CurrentBlock?.Id; if (blockId.HasValue && gameState.KnownCardIds.ContainsKey(blockId.Value)) { cardId = gameState.KnownCardIds[blockId.Value].FirstOrDefault(); if (!string.IsNullOrEmpty(cardId)) { Log.Info($"Found known cardId for entity {id}: {cardId}"); gameState.KnownCardIds[blockId.Value].Remove(cardId); } } } game.Entities.Add(id, new Entity(id) { CardId = cardId }); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } gameState.CurrentEntityHasCardId = !string.IsNullOrEmpty(cardId); gameState.CurrentEntityZone = zone; return; } else if (UpdatingEntityRegex.IsMatch(logLine)) { var match = UpdatingEntityRegex.Match(logLine); var cardId = match.Groups["cardId"].Value; var rawEntity = match.Groups["entity"].Value; var type = match.Groups["type"].Value; int entityId; if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = EntityRegex.Match(rawEntity); entityId = int.Parse(entity.Groups["id"].Value); } else if (!int.TryParse(rawEntity, out entityId)) { entityId = -1; } if (entityId != -1) { if (!game.Entities.ContainsKey(entityId)) { game.Entities.Add(entityId, new Entity(entityId)); } if (type != "CHANGE_ENTITY" || string.IsNullOrEmpty(game.Entities[entityId].CardId)) { game.Entities[entityId].CardId = cardId; } gameState.SetCurrentEntity(entityId); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } } if (gameState.JoustReveals > 0) { if (game.Entities.TryGetValue(entityId, out Entity 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()); } } } return; } else if (CreationTagRegex.IsMatch(logLine) && !logLine.Contains("HIDE_ENTITY")) { var match = CreationTagRegex.Match(logLine); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, gameState.CurrentEntityId, match.Groups["value"].Value, game, true); creationTag = true; } else if (logLine.Contains("HIDE_ENTITY")) { if (gameState.CurrentBlock?.CardId == Collectible.Neutral.KingTogwaggle || gameState.CurrentBlock?.CardId == NonCollectible.Neutral.KingTogwaggle_KingsRansomToken) { var match = HideEntityRegex.Match(logLine); if (match.Success) { var id = int.Parse(match.Groups["id"].Value); if (game.Entities.TryGetValue(id, out var entity)) { entity.Info.Hidden = true; } } } } if (logLine.Contains("End Spectator") && !game.IsInMenu) { gameState.GameHandler.HandleGameEnd(); } else if (logLine.Contains("BLOCK_START")) { var match = BlockStartRegex.Match(logLine); var blockType = match.Success ? match.Groups["type"].Value : null; var cardId = match.Success ? match.Groups["Id"].Value : null; gameState.BlockStart(blockType, cardId); if (match.Success && (blockType == "TRIGGER" || blockType == "POWER")) { var playerEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Player.Id); var opponentEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Opponent.Id); 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 Entity actionEntity)) { actionStartingCardId = actionEntity.CardId; } } if (string.IsNullOrEmpty(actionStartingCardId)) { return; } if (blockType == "TRIGGER") { switch (actionStartingCardId) { case Collectible.Rogue.TradePrinceGallywix: AddKnownCardId(gameState, game.Entities[gameState.LastCardPlayed].CardId); AddKnownCardId(gameState, NonCollectible.Neutral.TradePrinceGallywix_GallywixsCoinToken); break; case Collectible.Shaman.WhiteEyes: AddKnownCardId(gameState, NonCollectible.Shaman.WhiteEyes_TheStormGuardianToken); break; case Collectible.Hunter.RaptorHatchling: AddKnownCardId(gameState, NonCollectible.Hunter.RaptorHatchling_RaptorPatriarchToken); break; case Collectible.Warrior.DirehornHatchling: AddKnownCardId(gameState, NonCollectible.Warrior.DirehornHatchling_DirehornMatriarchToken); break; case Collectible.Mage.FrozenClone: AddKnownCardId(gameState, GetTargetCardId(match), 2); break; case Collectible.Shaman.Moorabi: case Collectible.Rogue.SonyaShadowdancer: AddKnownCardId(gameState, GetTargetCardId(match)); break; case Collectible.Neutral.HoardingDragon: AddKnownCardId(gameState, NonCollectible.Neutral.TheCoin, 2); break; case Collectible.Priest.GildedGargoyle: AddKnownCardId(gameState, NonCollectible.Neutral.TheCoin); break; case Collectible.Druid.AstralTiger: AddKnownCardId(gameState, Collectible.Druid.AstralTiger); break; case Collectible.Rogue.Kingsbane: AddKnownCardId(gameState, Collectible.Rogue.Kingsbane); break; case Collectible.Neutral.WeaselTunneler: AddKnownCardId(gameState, Collectible.Neutral.WeaselTunneler); break; } } else //POWER { switch (actionStartingCardId) { case Collectible.Rogue.GangUp: case Collectible.Hunter.DireFrenzy: AddKnownCardId(gameState, GetTargetCardId(match), 3); break; case Collectible.Rogue.BeneathTheGrounds: AddKnownCardId(gameState, NonCollectible.Rogue.BeneaththeGrounds_NerubianAmbushToken, 3); break; case Collectible.Warrior.IronJuggernaut: AddKnownCardId(gameState, NonCollectible.Warrior.IronJuggernaut_BurrowingMineToken); break; case Collectible.Druid.Recycle: case Collectible.Mage.ManicSoulcaster: case Collectible.Neutral.ZolaTheGorgon: case Collectible.Druid.Splintergraft: //case Collectible.Priest.HolyWater: -- TODO case Collectible.Neutral.BalefulBanker: case Collectible.Neutral.DollmasterDorian: AddKnownCardId(gameState, GetTargetCardId(match)); break; case Collectible.Mage.ForgottenTorch: AddKnownCardId(gameState, NonCollectible.Mage.ForgottenTorch_RoaringTorchToken); break; case Collectible.Warlock.CurseOfRafaam: AddKnownCardId(gameState, NonCollectible.Warlock.CurseofRafaam_CursedToken); break; case Collectible.Neutral.AncientShade: AddKnownCardId(gameState, NonCollectible.Neutral.AncientShade_AncientCurseToken); break; case Collectible.Priest.ExcavatedEvil: AddKnownCardId(gameState, Collectible.Priest.ExcavatedEvil); break; case Collectible.Neutral.EliseStarseeker: AddKnownCardId(gameState, NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken); break; case NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken: AddKnownCardId(gameState, NonCollectible.Neutral.EliseStarseeker_GoldenMonkeyToken); break; case Collectible.Neutral.Doomcaller: AddKnownCardId(gameState, NonCollectible.Neutral.Cthun); break; case Collectible.Druid.JadeIdol: AddKnownCardId(gameState, Collectible.Druid.JadeIdol, 3); break; case NonCollectible.Hunter.TheMarshQueen_QueenCarnassaToken: AddKnownCardId(gameState, NonCollectible.Hunter.TheMarshQueen_CarnassasBroodToken, 15); break; case Collectible.Neutral.EliseTheTrailblazer: AddKnownCardId(gameState, NonCollectible.Neutral.ElisetheTrailblazer_UngoroPackToken); break; case Collectible.Mage.GhastlyConjurer: AddKnownCardId(gameState, Collectible.Mage.MirrorImage); break; case Collectible.Mage.DeckOfWonders: AddKnownCardId(gameState, NonCollectible.Mage.DeckofWonders_ScrollOfWonderToken, 5); break; case Collectible.Neutral.TheDarkness: AddKnownCardId(gameState, NonCollectible.Neutral.TheDarkness_DarknessCandleToken, 3); break; case Collectible.Rogue.FaldoreiStrider: AddKnownCardId(gameState, NonCollectible.Rogue.FaldoreiStrider_SpiderAmbushEnchantment, 3); break; case Collectible.Neutral.KingTogwaggle: AddKnownCardId(gameState, NonCollectible.Neutral.KingTogwaggle_KingsRansomToken); break; case NonCollectible.Neutral.TheCandle: AddKnownCardId(gameState, NonCollectible.Neutral.TheCandle); break; //case Collectible.Rogue.Wanted: -- TODO // AddKnownCardId(gameState, NonCollectible.Neutral.TheCoin); // break; default: if (playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.PlayerUsedHeroPower || opponentEntity.Value != null && opponentEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.OpponentUsedHeroPower) { var card = Database.GetCardFromId(actionStartingCardId); if (card.Type == "Hero Power") { if (playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.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; } else if (logLine.Contains("BlockType=REVEAL_CARD")) { gameState.JoustReveals = 1; } else if (gameState.GameTriggerCount == 0 && logLine.Contains("BLOCK_START BlockType=TRIGGER Entity=GameEntity")) { gameState.GameTriggerCount++; } } else if (logLine.Contains("CREATE_GAME")) { _tagChangeHandler.ClearQueuedActions(); } else if (logLine.Contains("BLOCK_END")) { if (gameState.GameTriggerCount < 10 && (game.GameEntity?.HasTag(GameTag.TURN) ?? false)) { gameState.GameTriggerCount += 10; _tagChangeHandler.InvokeQueuedActions(game); gameState.SetupDone = true; } if (gameState.CurrentBlock?.Type == "JOUST" || gameState.CurrentBlock?.Type == "REVEAL_CARD") { //make sure there are no more queued actions that might depend on JoustReveals _tagChangeHandler.InvokeQueuedActions(game); gameState.JoustReveals = 0; } gameState.BlockEnd(); } if (game.IsInMenu) { return; } if (!creationTag && gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } if (!creationTag) { gameState.ResetCurrentEntity(); } }
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); 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()); } } }
private void ZoneChangeFromPlay(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { if (!game.Entities.TryGetValue(id, out var entity)) { return; } switch ((Zone)value) { case HAND: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerBackToHand(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentPlayToHand(entity, cardId, gameState.GetTurnNumber(), id); } break; case DECK: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerPlayToDeck(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentPlayToDeck(entity, cardId, gameState.GetTurnNumber()); } break; case GRAVEYARD: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerPlayToGraveyard(entity, cardId, gameState.GetTurnNumber(), game.PlayerEntity?.IsCurrentPlayer ?? false); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentPlayToGraveyard(entity, cardId, gameState.GetTurnNumber(), game.PlayerEntity?.IsCurrentPlayer ?? false); } break; case REMOVEDFROMGAME: case SETASIDE: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerRemoveFromPlay(entity, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentRemoveFromPlay(entity, gameState.GetTurnNumber()); } break; case PLAY: break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
private void ZoneChangeFromDeck(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { 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) && gameState.SetupDone) { #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; } }
private void ZoneChangeFromDeck(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { if (!game.Entities.TryGetValue(id, out var entity)) { return; } switch ((Zone)value) { case HAND: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerDraw(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentDraw(entity, gameState.GetTurnNumber()); } break; case SETASIDE: case REMOVEDFROMGAME: if (!game.SetupDone) { entity.Info.Created = true; return; } if (controller == game.Player.Id) { if (gameState.JoustReveals > 0) { gameState.JoustReveals--; break; } gameState.GameHandler.HandlePlayerRemoveFromDeck(entity, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { if (gameState.JoustReveals > 0) { gameState.JoustReveals--; break; } if (gameState.CurrentBlock?.CardId == Collectible.Neutral.GrandArchivist) { gameState.CurrentBlock.EntityDiscardedByArchivist = entity; } gameState.GameHandler.HandleOpponentRemoveFromDeck(entity, gameState.GetTurnNumber()); } break; case GRAVEYARD: var parentId = gameState?.CurrentBlock?.CardId; if (parentId != null) { if (parentId == ClassicTrackingCardId) { entity.Info.Hidden = true; entity.SetTag(GameTag.ZONE, (int)Zone.DECK); } } if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerDeckDiscard(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentDeckDiscard(entity, cardId, gameState.GetTurnNumber()); } break; case PLAY: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerDeckToPlay(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentDeckToPlay(entity, cardId, gameState.GetTurnNumber()); } break; case Zone.SECRET: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerSecretPlayed(entity, cardId, gameState.GetTurnNumber(), (Zone)prevValue); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentSecretPlayed(entity, cardId, -1, gameState.GetTurnNumber(), (Zone)prevValue, id); } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
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 == 1) { gameState.GameHandler.HandlePlayerName(name); } else if (player == 2) { gameState.GameHandler.HandleOpponentName(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.ABILITY) { int targetEntityId = actionEntity.GetTag(GAME_TAG.CARD_TARGET); Entity targetEntity; bool targetsMinion = false; if (game.Entities.TryGetValue(targetEntityId, out targetEntity)) { targetsMinion = true; } gameState.GameHandler.HandlePlayerSpellPlayed(targetsMinion); } } 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.PowerTaskList.EntityRegex.IsMatch(target)) { var cardIdMatch = HsLogReaderConstants.PowerTaskList.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.PowerTaskList.EntityRegex.IsMatch(target)) { var cardIdMatch = HsLogReaderConstants.PowerTaskList.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; } }
private void ControllerChange(IHsGameState gameState, int id, IGame game, int prevValue, int value) { if (!game.Entities.TryGetValue(id, out var entity)) { return; } if (prevValue <= 0) { entity.Info.OriginalController = value; return; } if (entity.HasTag(PLAYER_ID)) { return; } if (value == game.Player.Id) { if (entity.IsInZone(Zone.SECRET)) { gameState.GameHandler.HandleOpponentStolen(entity, entity.Info.LatestCardId, gameState.GetTurnNumber()); } else if (entity.IsInZone(PLAY)) { gameState.GameHandler.HandleOpponentStolen(entity, entity.Info.LatestCardId, gameState.GetTurnNumber()); } } else if (value == game.Opponent.Id) { if (entity.IsInZone(Zone.SECRET)) { gameState.GameHandler.HandlePlayerStolen(entity, entity.Info.LatestCardId, gameState.GetTurnNumber()); } else if (entity.IsInZone(PLAY)) { gameState.GameHandler.HandlePlayerStolen(entity, entity.Info.LatestCardId, gameState.GetTurnNumber()); } } }
public void Handle(string logLine, IHsGameState gameState, IGame game) { var creationTag = false; if (GameEntityRegex.IsMatch(logLine)) { var match = GameEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id) { Name = "GameEntity" }); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } return; } if (PlayerEntityRegex.IsMatch(logLine)) { var match = PlayerEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if (!game.Entities.ContainsKey(id)) { game.Entities.Add(id, new Entity(id)); } if (gameState.WasInProgress) { game.Entities[id].Name = game.GetStoredPlayerName(id); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } return; } if (TagChangeRegex.IsMatch(logLine)) { var match = TagChangeRegex.Match(logLine); var rawEntity = match.Groups["entity"].Value.Replace("UNKNOWN ENTITY ", ""); if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = 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 int 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) { var players = game.Entities.Where(x => x.Value.HasTag(GameTag.PLAYER_ID)).Take(2).ToList(); var unnamedPlayers = players.Where(x => string.IsNullOrEmpty(x.Value.Name)).ToList(); var unknownHumanPlayer = players.FirstOrDefault(x => x.Value.Name == "UNKNOWN HUMAN PLAYER"); if (unnamedPlayers.Count == 0 && unknownHumanPlayer.Value != null) { Log.Info("Updating UNKNOWN HUMAN PLAYER"); entity = unknownHumanPlayer; } //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) { Name = rawEntity }; _tmpEntities.Add(tmpEntity); } Enum.TryParse(match.Groups["tag"].Value, out GameTag tag); var value = GameTagHelper.ParseTag(tag, match.Groups["value"].Value); if (unnamedPlayers.Count == 1) { entity = unnamedPlayers.Single(); } else if (unnamedPlayers.Count == 2 && tag == GameTag.CURRENT_PLAYER && value == 0) { entity = game.Entities.FirstOrDefault(x => x.Value?.HasTag(GameTag.CURRENT_PLAYER) ?? false); } if (entity.Value != null) { entity.Value.Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { _tagChangeHandler.TagChange(gameState, t.Key, entity.Key, t.Value, game); } _tmpEntities.Remove(tmpEntity); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } if (_tmpEntities.Contains(tmpEntity)) { tmpEntity.SetTag(tag, value); var player = game.Player.Name == tmpEntity.Name ? game.Player : (game.Opponent.Name == tmpEntity.Name ? game.Opponent : null); if (player != null) { var playerEntity = game.Entities.FirstOrDefault(x => x.Value.GetTag(GameTag.PLAYER_ID) == player.Id).Value; if (playerEntity != null) { playerEntity.Name = tmpEntity.Name; foreach (var t in tmpEntity.Tags) { _tagChangeHandler.TagChange(gameState, t.Key, playerEntity.Id, t.Value, game); } _tmpEntities.Remove(tmpEntity); } } } } else { _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } } } else if (CreationRegex.IsMatch(logLine)) { var match = CreationRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); var cardId = match.Groups["cardId"].Value; var zone = GameTagHelper.ParseEnum <Zone>(match.Groups["zone"].Value); var guessedCardId = false; if (!game.Entities.ContainsKey(id)) { if (string.IsNullOrEmpty(cardId) && zone != Zone.SETASIDE) { var blockId = gameState.CurrentBlock?.Id; if (blockId.HasValue && gameState.KnownCardIds.ContainsKey(blockId.Value)) { cardId = gameState.KnownCardIds[blockId.Value].FirstOrDefault(); if (!string.IsNullOrEmpty(cardId)) { Log.Info($"Found known cardId for entity {id}: {cardId}"); gameState.KnownCardIds[blockId.Value].Remove(cardId); guessedCardId = true; } } } var entity = new Entity(id) { CardId = cardId }; if (guessedCardId) { entity.Info.GuessedCardState = GuessedCardState.Guessed; } game.Entities.Add(id, entity); } gameState.SetCurrentEntity(id); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } gameState.CurrentEntityHasCardId = !string.IsNullOrEmpty(cardId); gameState.CurrentEntityZone = zone; return; } else if (UpdatingEntityRegex.IsMatch(logLine)) { var match = UpdatingEntityRegex.Match(logLine); var cardId = match.Groups["cardId"].Value; var rawEntity = match.Groups["entity"].Value; var type = match.Groups["type"].Value; int entityId; if (rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = EntityRegex.Match(rawEntity); entityId = int.Parse(entity.Groups["id"].Value); } else if (!int.TryParse(rawEntity, out entityId)) { entityId = -1; } if (entityId != -1) { if (!game.Entities.ContainsKey(entityId)) { game.Entities.Add(entityId, new Entity(entityId)); } var entity = game.Entities[entityId]; if (type != "CHANGE_ENTITY" || string.IsNullOrEmpty(entity.CardId)) { entity.CardId = cardId; if (entity.Info.GuessedCardState != GuessedCardState.None) { entity.Info.GuessedCardState = GuessedCardState.Revealed; } } if (type == "CHANGE_ENTITY") { if (!entity.Info.OriginalEntityWasCreated.HasValue) { entity.Info.OriginalEntityWasCreated = entity.Info.Created; } if (entity.GetTag(GameTag.TRANSFORMED_FROM_CARD) == 46706) { gameState.ChameleosReveal = new Tuple <int, string>(entityId, cardId); } } gameState.SetCurrentEntity(entityId); if (gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } } if (gameState.JoustReveals > 0) { if (game.Entities.TryGetValue(entityId, out Entity 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()); } } } return; } else if (CreationTagRegex.IsMatch(logLine) && !logLine.Contains("HIDE_ENTITY")) { var match = CreationTagRegex.Match(logLine); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, gameState.CurrentEntityId, match.Groups["value"].Value, game, true); creationTag = true; } else if (logLine.Contains("HIDE_ENTITY")) { var match = HideEntityRegex.Match(logLine); if (match.Success) { var id = int.Parse(match.Groups["id"].Value); if (game.Entities.TryGetValue(id, out var entity)) { if (entity.Info.GuessedCardState == GuessedCardState.Revealed) { entity.Info.GuessedCardState = GuessedCardState.Guessed; } if (gameState.CurrentBlock?.CardId == Collectible.Neutral.KingTogwaggle || gameState.CurrentBlock?.CardId == NonCollectible.Neutral.KingTogwaggle_KingsRansomToken) { entity.Info.Hidden = true; } } } } if (logLine.Contains("End Spectator") && !game.IsInMenu) { gameState.GameHandler.HandleGameEnd(); } else if (logLine.Contains("BLOCK_START")) { var match = BlockStartRegex.Match(logLine); var blockType = match.Success ? match.Groups["type"].Value : null; var cardId = match.Success ? match.Groups["Id"].Value : null; var target = GetTargetCardId(match); gameState.BlockStart(blockType, cardId, target); if (match.Success && (blockType == "TRIGGER" || blockType == "POWER")) { var playerEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Player.Id); var opponentEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Opponent.Id); 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 var actionEntity)) { actionStartingCardId = actionEntity.CardId; } } if (string.IsNullOrEmpty(actionStartingCardId)) { return; } if (actionStartingCardId == Collectible.Shaman.Shudderwock) { var effectCardId = match.Groups["effectCardId"].Value; if (!string.IsNullOrEmpty(effectCardId)) { actionStartingCardId = effectCardId; } } if (actionStartingCardId == NonCollectible.Rogue.ValeeratheHollow_ShadowReflectionToken) { actionStartingCardId = cardId; } if (blockType == "TRIGGER" && actionStartingCardId == Collectible.Neutral.AugmentedElekk) { if (gameState.CurrentBlock.Parent != null) { actionStartingCardId = gameState.CurrentBlock.Parent.CardId; blockType = gameState.CurrentBlock.Parent.Type; target = gameState.CurrentBlock.Parent.Target; } } if (blockType == "TRIGGER") { switch (actionStartingCardId) { case Collectible.Rogue.TradePrinceGallywix: if (!game.Entities.TryGetValue(gameState.LastCardPlayed, out var lastPlayed)) { break; } AddKnownCardId(gameState, lastPlayed.CardId); AddKnownCardId(gameState, NonCollectible.Neutral.TradePrinceGallywix_GallywixsCoinToken); break; case Collectible.Shaman.WhiteEyes: AddKnownCardId(gameState, NonCollectible.Shaman.WhiteEyes_TheStormGuardianToken); break; case Collectible.Hunter.RaptorHatchling: AddKnownCardId(gameState, NonCollectible.Hunter.RaptorHatchling_RaptorPatriarchToken); break; case Collectible.Warrior.DirehornHatchling: AddKnownCardId(gameState, NonCollectible.Warrior.DirehornHatchling_DirehornMatriarchToken); break; case Collectible.Mage.FrozenClone: AddKnownCardId(gameState, target, 2); break; case Collectible.Shaman.Moorabi: case Collectible.Rogue.SonyaShadowdancer: AddKnownCardId(gameState, target); break; case Collectible.Neutral.HoardingDragon: AddKnownCardId(gameState, NonCollectible.Neutral.TheCoin, 2); break; case Collectible.Priest.GildedGargoyle: AddKnownCardId(gameState, NonCollectible.Neutral.TheCoin); break; case Collectible.Druid.AstralTiger: AddKnownCardId(gameState, Collectible.Druid.AstralTiger); break; case Collectible.Rogue.Kingsbane: AddKnownCardId(gameState, Collectible.Rogue.Kingsbane); break; case Collectible.Neutral.WeaselTunneler: AddKnownCardId(gameState, Collectible.Neutral.WeaselTunneler); break; case Collectible.Neutral.SparkDrill: AddKnownCardId(gameState, NonCollectible.Neutral.SparkDrill_SparkToken, 2); break; case NonCollectible.Neutral.HakkartheSoulflayer_CorruptedBloodToken: AddKnownCardId(gameState, NonCollectible.Neutral.HakkartheSoulflayer_CorruptedBloodToken, 2); break; //TODO: Gral, the Shark? case Collectible.Paladin.ImmortalPrelate: AddKnownCardId(gameState, Collectible.Paladin.ImmortalPrelate); break; case Collectible.Warrior.Wrenchcalibur: AddKnownCardId(gameState, NonCollectible.Neutral.SeaforiumBomber_BombToken); break; } } else //POWER { switch (actionStartingCardId) { case Collectible.Rogue.GangUp: case Collectible.Hunter.DireFrenzy: case Collectible.Rogue.LabRecruiter: AddKnownCardId(gameState, target, 3); break; case Collectible.Rogue.BeneathTheGrounds: AddKnownCardId(gameState, NonCollectible.Rogue.BeneaththeGrounds_NerubianAmbushToken, 3); break; case Collectible.Warrior.IronJuggernaut: AddKnownCardId(gameState, NonCollectible.Warrior.IronJuggernaut_BurrowingMineToken); break; case Collectible.Druid.Recycle: case Collectible.Mage.ManicSoulcaster: case Collectible.Neutral.ZolaTheGorgon: case Collectible.Druid.Splintergraft: //case Collectible.Priest.HolyWater: -- TODO case Collectible.Neutral.BalefulBanker: case Collectible.Neutral.DollmasterDorian: case Collectible.Priest.Seance: AddKnownCardId(gameState, target); break; case Collectible.Mage.ForgottenTorch: AddKnownCardId(gameState, NonCollectible.Mage.ForgottenTorch_RoaringTorchToken); break; case Collectible.Warlock.CurseOfRafaam: AddKnownCardId(gameState, NonCollectible.Warlock.CurseofRafaam_CursedToken); break; case Collectible.Neutral.AncientShade: AddKnownCardId(gameState, NonCollectible.Neutral.AncientShade_AncientCurseToken); break; case Collectible.Priest.ExcavatedEvil: AddKnownCardId(gameState, Collectible.Priest.ExcavatedEvil); break; case Collectible.Neutral.EliseStarseeker: AddKnownCardId(gameState, NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken); break; case NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken: AddKnownCardId(gameState, NonCollectible.Neutral.EliseStarseeker_GoldenMonkeyToken); break; case Collectible.Neutral.Doomcaller: AddKnownCardId(gameState, NonCollectible.Neutral.Cthun); break; case Collectible.Druid.JadeIdol: AddKnownCardId(gameState, Collectible.Druid.JadeIdol, 3); break; case NonCollectible.Hunter.TheMarshQueen_QueenCarnassaToken: AddKnownCardId(gameState, NonCollectible.Hunter.TheMarshQueen_CarnassasBroodToken, 15); break; case Collectible.Neutral.EliseTheTrailblazer: AddKnownCardId(gameState, NonCollectible.Neutral.ElisetheTrailblazer_UngoroPackToken); break; case Collectible.Mage.GhastlyConjurer: AddKnownCardId(gameState, Collectible.Mage.MirrorImage); break; case Collectible.Mage.DeckOfWonders: AddKnownCardId(gameState, NonCollectible.Mage.DeckofWonders_ScrollOfWonderToken, 5); break; case Collectible.Neutral.TheDarkness: AddKnownCardId(gameState, NonCollectible.Neutral.TheDarkness_DarknessCandleToken, 3); break; case Collectible.Rogue.FaldoreiStrider: AddKnownCardId(gameState, NonCollectible.Rogue.FaldoreiStrider_SpiderAmbushEnchantment, 3); break; case Collectible.Neutral.KingTogwaggle: AddKnownCardId(gameState, NonCollectible.Neutral.KingTogwaggle_KingsRansomToken); break; case NonCollectible.Neutral.TheCandle: AddKnownCardId(gameState, NonCollectible.Neutral.TheCandle); break; case NonCollectible.Neutral.CoinPouch: AddKnownCardId(gameState, NonCollectible.Neutral.SackOfCoins); break; case NonCollectible.Neutral.SackOfCoins: AddKnownCardId(gameState, NonCollectible.Neutral.HeftySackOfCoins); break; case NonCollectible.Neutral.CreepyCurio: AddKnownCardId(gameState, NonCollectible.Neutral.HauntedCurio); break; case NonCollectible.Neutral.HauntedCurio: AddKnownCardId(gameState, NonCollectible.Neutral.CursedCurio); break; case NonCollectible.Neutral.OldMilitiaHorn: AddKnownCardId(gameState, NonCollectible.Neutral.MilitiaHorn); break; case NonCollectible.Neutral.MilitiaHorn: AddKnownCardId(gameState, NonCollectible.Neutral.VeteransMilitiaHorn); break; case NonCollectible.Neutral.SurlyMob: AddKnownCardId(gameState, NonCollectible.Neutral.AngryMob); break; case NonCollectible.Neutral.AngryMob: AddKnownCardId(gameState, NonCollectible.Neutral.CrazedMob); break; case Collectible.Neutral.SparkEngine: AddKnownCardId(gameState, NonCollectible.Neutral.SparkDrill_SparkToken); break; case Collectible.Priest.ExtraArms: AddKnownCardId(gameState, NonCollectible.Priest.ExtraArms_MoreArmsToken); break; case Collectible.Neutral.SeaforiumBomber: case Collectible.Warrior.ClockworkGoblin: AddKnownCardId(gameState, NonCollectible.Neutral.SeaforiumBomber_BombToken); break; //case Collectible.Rogue.Wanted: -- TODO // AddKnownCardId(gameState, NonCollectible.Neutral.TheCoin); // break; //TODO: Hex Lord Malacrass //TODO: Krag'wa, the Frog case Collectible.Hunter.HalazziTheLynx: AddKnownCardId(gameState, NonCollectible.Hunter.Springpaw_LynxToken, 10); break; case Collectible.Neutral.BananaBuffoon: AddKnownCardId(gameState, NonCollectible.Neutral.BananaBuffoon_BananasToken, 2); break; case Collectible.Neutral.BootyBayBookie: AddKnownCardId(gameState, NonCollectible.Neutral.TheCoin); break; case Collectible.Neutral.PortalKeeper: case Collectible.Neutral.PortalOverfiend: AddKnownCardId(gameState, NonCollectible.Neutral.PortalKeeper_FelhoundPortalToken); break; case Collectible.Rogue.TogwagglesScheme: AddKnownCardId(gameState, target); break; case Collectible.Paladin.SandwaspQueen: AddKnownCardId(gameState, NonCollectible.Paladin.SandwaspQueen_SandwaspToken, 2); break; case Collectible.Rogue.ShadowOfDeath: AddKnownCardId(gameState, NonCollectible.Rogue.ShadowofDeath_ShadowToken, 3); break; case Collectible.Warlock.Impbalming: AddKnownCardId(gameState, NonCollectible.Warlock.Impbalming_WorthlessImpToken, 3); break; default: if (playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.PlayerUsedHeroPower || opponentEntity.Value != null && opponentEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.OpponentUsedHeroPower) { var card = Database.GetCardFromId(actionStartingCardId); if (card.Type == "Hero Power") { if (playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.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; } else if (logLine.Contains("BlockType=REVEAL_CARD")) { gameState.JoustReveals = 1; } else if (gameState.GameTriggerCount == 0 && logLine.Contains("BLOCK_START BlockType=TRIGGER Entity=GameEntity")) { gameState.GameTriggerCount++; } } else if (logLine.Contains("CREATE_GAME")) { _tagChangeHandler.ClearQueuedActions(); } else if (logLine.Contains("BLOCK_END")) { if (gameState.GameTriggerCount < 10 && (game.GameEntity?.HasTag(GameTag.TURN) ?? false)) { gameState.GameTriggerCount += 10; _tagChangeHandler.InvokeQueuedActions(game); game.SetupDone = true; } if (gameState.CurrentBlock?.Type == "JOUST" || gameState.CurrentBlock?.Type == "REVEAL_CARD") { //make sure there are no more queued actions that might depend on JoustReveals _tagChangeHandler.InvokeQueuedActions(game); gameState.JoustReveals = 0; } if (gameState.CurrentBlock?.Type == "TRIGGER" && (gameState.CurrentBlock?.CardId == NonCollectible.Neutral.Chameleos_ShiftingEnchantment || gameState.CurrentBlock?.CardId == Collectible.Priest.Chameleos) && gameState.ChameleosReveal != null && game.Entities.TryGetValue(gameState.ChameleosReveal.Item1, out var chameleos) && chameleos.HasTag(GameTag.SHIFTING)) { gameState.GameHandler.HandleChameleosReveal(gameState.ChameleosReveal.Item2); } gameState.ChameleosReveal = null; gameState.BlockEnd(); } if (game.IsInMenu) { return; } if (!creationTag && gameState.DeterminedPlayers) { _tagChangeHandler.InvokeQueuedActions(game); } if (!creationTag) { gameState.ResetCurrentEntity(); } }
public void Handle(string logLine, IHsGameState gameState, IGame game) { var creationTag = false; if(GameEntityRegex.IsMatch(logLine)) { var match = GameEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if(!game.Entities.ContainsKey(id)) game.Entities.Add(id, new Entity(id) {Name = "GameEntity"}); gameState.SetCurrentEntity(id); if(gameState.DeterminedPlayers) _tagChangeHandler.InvokeQueuedActions(game); return; } else if(PlayerEntityRegex.IsMatch(logLine)) { var match = PlayerEntityRegex.Match(logLine); var id = int.Parse(match.Groups["id"].Value); if(!game.Entities.ContainsKey(id)) game.Entities.Add(id, new Entity(id)); if(gameState.WasInProgress) game.Entities[id].Name = game.GetStoredPlayerName(id); gameState.SetCurrentEntity(id); if(gameState.DeterminedPlayers) _tagChangeHandler.InvokeQueuedActions(game); return; } else if(TagChangeRegex.IsMatch(logLine)) { var match = TagChangeRegex.Match(logLine); var rawEntity = match.Groups["entity"].Value.Replace("UNKNOWN ENTITY ", ""); int entityId; if(rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = 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) { var players = game.Entities.Where(x => x.Value.HasTag(GameTag.PLAYER_ID)).Take(2).ToList(); var unnamedPlayers = players.Where(x => string.IsNullOrEmpty(x.Value.Name)).ToList(); var unknownHumanPlayer = players.FirstOrDefault(x => x.Value.Name == "UNKNOWN HUMAN PLAYER"); if(unnamedPlayers.Count == 0 && unknownHumanPlayer.Value != null) { Log.Info("Updating UNKNOWN HUMAN PLAYER"); entity = unknownHumanPlayer; } //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) {Name = rawEntity}; _tmpEntities.Add(tmpEntity); } GameTag tag; Enum.TryParse(match.Groups["tag"].Value, out tag); var value = LogReaderHelper.ParseTag(tag, match.Groups["value"].Value); if(unnamedPlayers.Count == 1) entity = unnamedPlayers.Single(); else if(unnamedPlayers.Count == 2 && tag == GameTag.CURRENT_PLAYER && value == 0) entity = game.Entities.FirstOrDefault(x => x.Value?.HasTag(GameTag.CURRENT_PLAYER) ?? false); if(entity.Value != null) { entity.Value.Name = tmpEntity.Name; foreach(var t in tmpEntity.Tags) _tagChangeHandler.TagChange(gameState, t.Key, entity.Key, t.Value, game); _tmpEntities.Remove(tmpEntity); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } if(_tmpEntities.Contains(tmpEntity)) { tmpEntity.SetTag(tag, value); var player = game.Player.Name == tmpEntity.Name ? game.Player : (game.Opponent.Name == tmpEntity.Name ? game.Opponent : null); if(player != null) { var playerEntity = game.Entities.FirstOrDefault(x => x.Value.GetTag(GameTag.PLAYER_ID) == player.Id).Value; if(playerEntity != null) { playerEntity.Name = tmpEntity.Name; foreach(var t in tmpEntity.Tags) _tagChangeHandler.TagChange(gameState, t.Key, playerEntity.Id, t.Value, game); _tmpEntities.Remove(tmpEntity); } } } } else _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, entity.Key, match.Groups["value"].Value, game); } } else if(CreationRegex.IsMatch(logLine)) { var match = 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)) { Log.Info($"Found known cardId for entity {id}: {cardId}"); gameState.KnownCardIds.Remove(id); } } game.Entities.Add(id, new Entity(id) {CardId = cardId}); } gameState.SetCurrentEntity(id); if(gameState.DeterminedPlayers) _tagChangeHandler.InvokeQueuedActions(game); gameState.CurrentEntityHasCardId = !string.IsNullOrEmpty(cardId); gameState.CurrentEntityZone = LogReaderHelper.ParseEnum<Zone>(match.Groups["zone"].Value); return; } else if(UpdatingEntityRegex.IsMatch(logLine)) { var match = UpdatingEntityRegex.Match(logLine); var cardId = match.Groups["cardId"].Value; var rawEntity = match.Groups["entity"].Value; int entityId; if(rawEntity.StartsWith("[") && EntityRegex.IsMatch(rawEntity)) { var entity = EntityRegex.Match(rawEntity); entityId = int.Parse(entity.Groups["id"].Value); } else if(!int.TryParse(rawEntity, out entityId)) entityId = -1; if(entityId != -1) { if(!game.Entities.ContainsKey(entityId)) game.Entities.Add(entityId, new Entity(entityId)); game.Entities[entityId].CardId = cardId; gameState.SetCurrentEntity(entityId); if(gameState.DeterminedPlayers) _tagChangeHandler.InvokeQueuedActions(game); } 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--; } return; } else if(CreationTagRegex.IsMatch(logLine) && !logLine.Contains("HIDE_ENTITY")) { var match = CreationTagRegex.Match(logLine); _tagChangeHandler.TagChange(gameState, match.Groups["tag"].Value, gameState.CurrentEntityId, match.Groups["value"].Value, game, true); creationTag = true; } if(logLine.Contains("End Spectator")) gameState.GameHandler.HandleGameEnd(); else if(BlockStartRegex.IsMatch(logLine)) { var playerEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Player.Id); var opponentEntity = game.Entities.FirstOrDefault( e => e.Value.HasTag(GameTag.PLAYER_ID) && e.Value.GetTag(GameTag.PLAYER_ID) == game.Opponent.Id); var match = BlockStartRegex.Match(logLine); var actionStartingCardId = match.Groups["cardId"].Value.Trim(); var actionStartingEntityId = int.Parse(match.Groups["id"].Value); if(string.IsNullOrEmpty(actionStartingCardId)) { Entity actionEntity; if(game.Entities.TryGetValue(actionStartingEntityId, out actionEntity)) actionStartingCardId = actionEntity.CardId; } if(string.IsNullOrEmpty(actionStartingCardId)) return; if(match.Groups["type"].Value == "TRIGGER") { switch(actionStartingCardId) { case Collectible.Rogue.TradePrinceGallywix: AddKnownCardId(gameState, game, game.Entities[gameState.LastCardPlayed].CardId); AddKnownCardId(gameState, game, NonCollectible.Neutral.TradePrinceGallywix_GallywixsCoinToken); break; } } else //POWER { switch(actionStartingCardId) { case Collectible.Rogue.GangUp: AddTargetAsKnownCardId(gameState, game, match, 3); break; case Collectible.Rogue.BeneathTheGrounds: AddKnownCardId(gameState, game, NonCollectible.Rogue.BeneaththeGrounds_AmbushToken, 3); break; case Collectible.Warrior.IronJuggernaut: AddKnownCardId(gameState, game, NonCollectible.Warrior.IronJuggernaut_BurrowingMineToken); break; case Collectible.Druid.Recycle: AddTargetAsKnownCardId(gameState, game, match); break; case Collectible.Mage.ForgottenTorch: AddKnownCardId(gameState, game, NonCollectible.Mage.ForgottenTorch_RoaringTorchToken); break; case Collectible.Warlock.CurseOfRafaam: AddKnownCardId(gameState, game, NonCollectible.Warlock.CurseofRafaam_CursedToken); break; case Collectible.Neutral.AncientShade: AddKnownCardId(gameState, game, NonCollectible.Neutral.AncientShade_AncientCurseToken); break; case Collectible.Priest.ExcavatedEvil: AddKnownCardId(gameState, game, Collectible.Priest.ExcavatedEvil); break; case Collectible.Neutral.EliseStarseeker: AddKnownCardId(gameState, game, NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken); break; case NonCollectible.Neutral.EliseStarseeker_MapToTheGoldenMonkeyToken: AddKnownCardId(gameState, game, NonCollectible.Neutral.EliseStarseeker_GoldenMonkeyToken); break; case Collectible.Neutral.Doomcaller: AddKnownCardId(gameState, game, NonCollectible.Neutral.Cthun); break; default: if(playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.PlayerUsedHeroPower || opponentEntity.Value != null && opponentEntity.Value.GetTag(GameTag.CURRENT_PLAYER) == 1 && !gameState.OpponentUsedHeroPower) { var card = Database.GetCardFromId(actionStartingCardId); if(card.Type == "Hero Power") { if(playerEntity.Value != null && playerEntity.Value.GetTag(GameTag.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; else if(logLine.Contains("CREATE_GAME")) _tagChangeHandler.ClearQueuedActions(); else if(gameState.GameTriggerCount == 0 && logLine.Contains("BLOCK_START BlockType=TRIGGER Entity=GameEntity")) gameState.GameTriggerCount++; else if(gameState.GameTriggerCount < 10 && logLine.Contains("BLOCK_END") && (game.GameEntity?.HasTag(GameTag.TURN) ?? false)) { gameState.GameTriggerCount += 10; _tagChangeHandler.InvokeQueuedActions(game); gameState.SetupDone = true; } if(game.IsInMenu) return; if(!creationTag && gameState.DeterminedPlayers) _tagChangeHandler.InvokeQueuedActions(game); if(!creationTag) gameState.ResetCurrentEntity(); }
private void ZoneChangeFromSecret(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { switch ((Zone)value) { case 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; } }
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 = 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 Logger.WriteLine($"Opponent Draw (EntityID={id}) already has a CardID. Removing. Blizzard Pls.", "TagChange"); #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: Logger.WriteLine($"WARNING - unhandled zone change (id={id}): {prevValue} -> {value}", "TagChange"); 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: Logger.WriteLine($"WARNING - unhandled zone change (id={id}): {prevValue} -> {value}", "TagChange"); 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: Logger.WriteLine($"WARNING - unhandled zone change (id={id}): {prevValue} -> {value}", "TagChange"); 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: Logger.WriteLine($"WARNING - unhandled zone change (id={id}): {prevValue} -> {value}", "TagChange"); 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: Logger.WriteLine($"WARNING - unhandled zone change (id={id}): {prevValue} -> {value}", "TagChange"); break; } break; default: Logger.WriteLine($"WARNING - unhandled zone change (id={id}): {prevValue} -> {value}", "TagChange"); 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 zone = game.Entities[id].GetTag(ZONE); if(zone == (int)HAND) { if(controller == game.Player.Id) { ReplayMaker.Generate(HandPos, id, ActivePlayer.Player, game); gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Player, HAND, gameState.GetTurnNumber()); } else if(controller == game.Opponent.Id) { ReplayMaker.Generate(HandPos, id, ActivePlayer.Opponent, game); gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Opponent, 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, PLAY, gameState.GetTurnNumber()); } else if(controller == game.Opponent.Id) { ReplayMaker.Generate(BoardPos, id, ActivePlayer.Opponent, game); gameState.GameHandler.HandleZonePositionUpdate(ActivePlayer.Opponent, 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 ZoneChangeFromPlay(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { switch ((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 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(), game.PlayerEntity?.IsCurrentPlayer ?? false); if (game.Entities[id].HasTag(HEALTH)) { gameState.ProposeKeyPoint(Death, id, ActivePlayer.Opponent); } } break; case REMOVEDFROMGAME: case SETASIDE: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerRemoveFromPlay(game.Entities[id], gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentRemoveFromPlay(game.Entities[id], gameState.GetTurnNumber()); } break; case PLAY: break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
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; } } }
private void ZoneChangeFromHand(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { switch ((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 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(KeyPointType.Mulligan, id, ActivePlayer.Player); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentMulligan(game.Entities[id], game.Entities[id].GetTag(ZONE_POSITION)); gameState.ProposeKeyPoint(KeyPointType.Mulligan, id, ActivePlayer.Opponent); } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
private void NumTurnsInPlayChange(IHsGameState gameState, int id, IGame game, int value) { if(value <= 0) return; Entity entity; if(!game.Entities.TryGetValue(id, out entity)) return; gameState.GameHandler.HandleTurnsInPlayChange(entity, gameState.GetTurnNumber()); }
private void ZoneChangeFromDeck(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { switch ((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) { 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 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; } }
private void ZoneChangeFromOther(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { Entity entity; if(!game.Entities.TryGetValue(id, out entity)) return; if(entity.Info.OriginalZone == DECK && value != (int)DECK) { //This entity was moved from DECK to SETASIDE to HAND, e.g. by Tracking entity.Info.Discarded = false; ZoneChangeFromDeck(gameState, id, game, value, prevValue, controller, cardId); return; } entity.Info.Created = true; switch((Zone)value) { case PLAY: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerCreateInPlay(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(Summon, id, ActivePlayer.Player); } if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentCreateInPlay(entity, 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(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(CreateToDeck, id, ActivePlayer.Player); } if(controller == game.Opponent.Id) { if(gameState.JoustReveals > 0) break; gameState.GameHandler.HandleOpponentGetToDeck(entity, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(CreateToDeck, id, ActivePlayer.Opponent); } break; case HAND: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerGet(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(Obtain, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentGet(entity, gameState.GetTurnNumber(), id); gameState.ProposeKeyPoint(Obtain, id, ActivePlayer.Opponent); } break; case Zone.SECRET: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerSecretPlayed(entity, cardId, gameState.GetTurnNumber(), (Zone)prevValue); gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentSecretPlayed(entity, cardId, -1, gameState.GetTurnNumber(), (Zone)prevValue, id); gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Opponent); } break; case SETASIDE: if(controller == game.Player.Id) gameState.GameHandler.HandlePlayerCreateInSetAside(entity, gameState.GetTurnNumber()); if(controller == game.Opponent.Id) gameState.GameHandler.HandleOpponentCreateInSetAside(entity, gameState.GetTurnNumber()); break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
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 = LogReaderHelper.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; } } }
private void ZoneChangeFromPlay(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { Entity entity; if(!game.Entities.TryGetValue(id, out entity)) return; switch((Zone)value) { case HAND: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerBackToHand(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(PlayToHand, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentPlayToHand(entity, cardId, gameState.GetTurnNumber(), id); gameState.ProposeKeyPoint(PlayToHand, id, ActivePlayer.Opponent); } break; case DECK: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerPlayToDeck(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(PlayToDeck, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentPlayToDeck(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(PlayToDeck, id, ActivePlayer.Opponent); } break; case GRAVEYARD: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerPlayToGraveyard(entity, cardId, gameState.GetTurnNumber()); if(entity.HasTag(HEALTH)) gameState.ProposeKeyPoint(Death, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentPlayToGraveyard(entity, cardId, gameState.GetTurnNumber(), game.PlayerEntity?.IsCurrentPlayer ?? false); if(entity.HasTag(HEALTH)) gameState.ProposeKeyPoint(Death, id, ActivePlayer.Opponent); } break; case REMOVEDFROMGAME: case SETASIDE: if(controller == game.Player.Id) gameState.GameHandler.HandlePlayerRemoveFromPlay(entity, gameState.GetTurnNumber()); else if(controller == game.Opponent.Id) gameState.GameHandler.HandleOpponentRemoveFromPlay(entity, gameState.GetTurnNumber()); break; case PLAY: break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
private void ZoneChangeFromDeck(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { if (!game.Entities.TryGetValue(id, out var entity)) { return; } switch ((Zone)value) { case HAND: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerDraw(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentDraw(entity, gameState.GetTurnNumber()); } break; case SETASIDE: case REMOVEDFROMGAME: if (!game.SetupDone) { entity.Info.Created = true; return; } if (controller == game.Player.Id) { if (gameState.JoustReveals > 0) { gameState.JoustReveals--; break; } gameState.GameHandler.HandlePlayerRemoveFromDeck(entity, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { if (gameState.JoustReveals > 0) { gameState.JoustReveals--; break; } gameState.GameHandler.HandleOpponentRemoveFromDeck(entity, gameState.GetTurnNumber()); } break; case GRAVEYARD: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerDeckDiscard(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentDeckDiscard(entity, cardId, gameState.GetTurnNumber()); } break; case PLAY: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerDeckToPlay(entity, cardId, gameState.GetTurnNumber()); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentDeckToPlay(entity, cardId, gameState.GetTurnNumber()); } break; case Zone.SECRET: if (controller == game.Player.Id) { gameState.GameHandler.HandlePlayerSecretPlayed(entity, cardId, gameState.GetTurnNumber(), (Zone)prevValue); } else if (controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentSecretPlayed(entity, cardId, -1, gameState.GetTurnNumber(), (Zone)prevValue, id); } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
private void ZoneChangeFromDeck(IHsGameState gameState, int id, IGame game, int value, int prevValue, int controller, string cardId) { Entity entity; if(!game.Entities.TryGetValue(id, out entity)) return; switch((Zone)value) { case HAND: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerDraw(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(Draw, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentDraw(entity, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(Draw, id, ActivePlayer.Opponent); } break; case SETASIDE: case REMOVEDFROMGAME: if(!gameState.SetupDone) { entity.Info.Created = true; return; } if(controller == game.Player.Id) { if(gameState.JoustReveals > 0) { gameState.JoustReveals--; break; } gameState.GameHandler.HandlePlayerRemoveFromDeck(entity, gameState.GetTurnNumber()); } else if(controller == game.Opponent.Id) { if(gameState.JoustReveals > 0) { gameState.JoustReveals--; break; } gameState.GameHandler.HandleOpponentRemoveFromDeck(entity, gameState.GetTurnNumber()); } break; case GRAVEYARD: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerDeckDiscard(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(DeckDiscard, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentDeckDiscard(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(DeckDiscard, id, ActivePlayer.Opponent); } break; case PLAY: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerDeckToPlay(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(DeckDiscard, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentDeckToPlay(entity, cardId, gameState.GetTurnNumber()); gameState.ProposeKeyPoint(DeckDiscard, id, ActivePlayer.Opponent); } break; case Zone.SECRET: if(controller == game.Player.Id) { gameState.GameHandler.HandlePlayerSecretPlayed(entity, cardId, gameState.GetTurnNumber(), (Zone)prevValue); gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Player); } else if(controller == game.Opponent.Id) { gameState.GameHandler.HandleOpponentSecretPlayed(entity, cardId, -1, gameState.GetTurnNumber(), (Zone)prevValue, id); gameState.ProposeKeyPoint(SecretPlayed, id, ActivePlayer.Player); } break; default: Log.Warn($"unhandled zone change (id={id}): {prevValue} -> {value}"); break; } }
private static void ControllerChange(IHsGameState gameState, int id, IGame game, int prevValue, int value, string cardId) { if(prevValue <= 0) return; 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()); } }