Exemplo n.º 1
0
        public static void RunTest(string configPath, bool debugMode)
        {
            string testName = System.IO.Path.GetFileNameWithoutExtension(configPath);

            string configText = System.IO.File.ReadAllText(configPath);

            JsonParser.ObjectValue rootOb = JsonParser.ParseJson(configText);
            if (rootOb["type"] != "Screen")
            {
                return;
            }

            ScannerTriad.VerifyConfig configData = new ScannerTriad.VerifyConfig();
            configData.Load(rootOb);

            // setup npc & modifiers
            TriadNpc testNpc = TriadNpcDB.Get().Find(configData.npc);

            if (testNpc == null)
            {
                string exceptionMsg = string.Format("Test {0} failed! Can't find npc: {1}", testName, configData.npc);
                throw new Exception(exceptionMsg);
            }

            ScannerTriad.GameState screenGame = new ScannerTriad.GameState();
            if (mapValidationRules == null)
            {
                mapValidationRules = new Dictionary <string, TriadGameModifier>();
                foreach (TriadGameModifier mod in ImageHashDB.Get().modObjects)
                {
                    mapValidationRules.Add(mod.GetCodeName(), mod);
                }
            }

            foreach (string modName in configData.rules)
            {
                screenGame.mods.Add(mapValidationRules[modName]);
            }

            Func <ScannerTriad.VerifyCard, TriadCard> ConvertToTriadCard = configCard =>
            {
                if (configCard.state == ScannerTriad.ECardState.None)
                {
                    return(null);
                }
                if (configCard.state == ScannerTriad.ECardState.Hidden)
                {
                    return(TriadCardDB.Get().hiddenCard);
                }

                TriadCard matchingCard = !string.IsNullOrEmpty(configCard.name) ?
                                         TriadCardDB.Get().Find(configCard.name) :
                                         TriadCardDB.Get().Find(configCard.sides[0], configCard.sides[1], configCard.sides[2], configCard.sides[3]);

                if (matchingCard == null)
                {
                    string exceptionMsg = string.Format("Test {0} failed! Can't match validation card: '{1}' [{2},{3},{4},{5}]", testName,
                                                        configCard.name, configCard.sides[0], configCard.sides[1], configCard.sides[2], configCard.sides[3]);
                    throw new Exception(exceptionMsg);
                }

                return(matchingCard);
            };

            bool needsLockedBlue = false;

            for (int idx = 0; idx < 5; idx++)
            {
                screenGame.blueDeck[idx] = ConvertToTriadCard(configData.deckBlue[idx]);
                screenGame.redDeck[idx]  = ConvertToTriadCard(configData.deckRed[idx]);

                if (configData.deckBlue[idx].state == ScannerTriad.ECardState.Locked)
                {
                    needsLockedBlue = true;
                }
            }

            if (needsLockedBlue)
            {
                for (int idx = 0; idx < 5; idx++)
                {
                    if (configData.deckBlue[idx].state == ScannerTriad.ECardState.Visible)
                    {
                        screenGame.forcedBlueCard = screenGame.blueDeck[idx];
                        break;
                    }
                }
            }

            for (int idx = 0; idx < 9; idx++)
            {
                screenGame.board[idx]      = ConvertToTriadCard(configData.board[idx]);
                screenGame.boardOwner[idx] =
                    configData.board[idx].state == ScannerTriad.ECardState.PlacedBlue ? ETriadCardOwner.Blue :
                    configData.board[idx].state == ScannerTriad.ECardState.PlacedRed ? ETriadCardOwner.Red :
                    ETriadCardOwner.Unknown;
            }

            TriadGameScreenMemory screenMemory = new TriadGameScreenMemory {
                logScan = false
            };

            screenMemory.OnNewScan(screenGame, testNpc);
            screenMemory.gameSession.SolverFindBestMove(screenMemory.gameState, out int solverBoardPos, out TriadCard solverTriadCard, out TriadGameResultChance bestChance);

            if (bestChance.expectedResult == ETriadGameState.BlueLost && bestChance.winChance <= 0.0f && bestChance.drawChance <= 0.0f)
            {
                string exceptionMsg = string.Format("Test {0} failed! Can't find move!", testName);
                throw new Exception(exceptionMsg);
            }
        }
Exemplo n.º 2
0
        public EUpdateFlags OnNewScan(ScannerTriad.GameState screenGame, TriadNpc selectedNpc)
        {
            EUpdateFlags updateFlags = EUpdateFlags.None;

            if (screenGame == null)
            {
                return(updateFlags);
            }

            // check if game from screenshot can be continuation of cached one
            // is current state a continuation of last one?
            // ideally each blue turn is a capture until game resets = any card disappears from board
            // guess work for adding sense of persistence to screen decks
            bool bContinuesPrevState = (deckRed.deck == selectedNpc.Deck) && (lastScanNpc == selectedNpc);

            if (bContinuesPrevState)
            {
                for (int Idx = 0; Idx < gameState.board.Length; Idx++)
                {
                    bool bWasNull = gameState.board[Idx] == null;
                    bool bIsNull  = screenGame.board[Idx] == null;

                    if (!bWasNull && bIsNull)
                    {
                        bContinuesPrevState = false;
                        if (logScan)
                        {
                            Logger.WriteLine("Can't continue previous state: board[" + Idx + "] disappeared ");
                        }
                    }
                }
            }
            else
            {
                if (logScan)
                {
                    Logger.WriteLine("Can't continue previous state: npc changed");
                }
            }

            bool bModsChanged = (gameSession.modifiers.Count != screenGame.mods.Count) || !gameSession.modifiers.All(screenGame.mods.Contains);

            if (bModsChanged)
            {
                bHasSwapRule    = false;
                bHasRestartRule = false;
                bHasOpenRule    = false;
                gameSession.modifiers.Clear();
                gameSession.modifiers.AddRange(screenGame.mods);
                gameSession.specialRules = ETriadGameSpecialMod.None;
                gameSession.modFeatures  = TriadGameModifier.EFeature.None;
                foreach (TriadGameModifier mod in gameSession.modifiers)
                {
                    gameSession.modFeatures |= mod.GetFeatures();

                    // swap rule is bad for screenshot based analysis, no good way of telling what is out of place
                    if (mod is TriadGameModifierSwap)
                    {
                        bHasSwapRule = true;
                    }
                    else if (mod is TriadGameModifierSuddenDeath)
                    {
                        bHasRestartRule = true;
                    }
                    else if (mod is TriadGameModifierAllOpen)
                    {
                        bHasOpenRule = true;
                    }
                }

                updateFlags        |= EUpdateFlags.Modifiers;
                bContinuesPrevState = false;
                if (logScan)
                {
                    Logger.WriteLine("Can't continue previous state: modifiers changed");
                }

                deckRed.SetSwappedCard(null, -1);
            }

            // wipe blue deck history when playing with new npc (or region modifiers have changed)
            bool bRemoveBlueHistory = bModsChanged || (lastScanNpc != selectedNpc);

            if (bRemoveBlueHistory)
            {
                blueDeckHistory.Clear();
                if (bHasSwapRule && logScan)
                {
                    Logger.WriteLine("Blue deck history cleared");
                }
            }

            bool bRedDeckChanged = (lastScanNpc != selectedNpc) || !IsDeckMatching(deckRed, screenGame.redDeck) || (deckRed.deck != selectedNpc.Deck);

            if (bRedDeckChanged)
            {
                updateFlags |= EUpdateFlags.RedDeck;
                deckRed.deck = selectedNpc.Deck;
                lastScanNpc  = selectedNpc;

                // needs to happen before any changed to board (gameState)
                UpdateAvailableRedCards(deckRed, screenGame.redDeck, screenGame.blueDeck,
                                        screenGame.board, deckBlue.cards, gameState.board, bContinuesPrevState);
            }

            bool bBlueDeckChanged = !IsDeckMatching(deckBlue, screenGame.blueDeck);

            if (bBlueDeckChanged)
            {
                updateFlags |= EUpdateFlags.BlueDeck;
                deckBlue.UpdateAvailableCards(screenGame.blueDeck);
            }

            gameState.state          = ETriadGameState.InProgressBlue;
            gameState.deckBlue       = deckBlue;
            gameState.deckRed        = deckRed;
            gameState.numCardsPlaced = 0;
            gameState.forcedCardIdx  = deckBlue.GetCardIndex(screenGame.forcedBlueCard);

            bool bBoardChanged = false;

            for (int Idx = 0; Idx < gameState.board.Length; Idx++)
            {
                bool bWasNull = gameState.board[Idx] == null;
                bool bIsNull  = screenGame.board[Idx] == null;

                if (bWasNull && !bIsNull)
                {
                    bBoardChanged        = true;
                    gameState.board[Idx] = new TriadCardInstance(screenGame.board[Idx], screenGame.boardOwner[Idx]);
                    if (logScan)
                    {
                        Logger.WriteLine("  board update: [" + Idx + "] " + gameState.board[Idx].owner + ": " + gameState.board[Idx].card.Name.GetCodeName());
                    }
                }
                else if (!bWasNull && bIsNull)
                {
                    bBoardChanged        = true;
                    gameState.board[Idx] = null;
                }
                else if (!bWasNull && !bIsNull)
                {
                    if (gameState.board[Idx].owner != screenGame.boardOwner[Idx] ||
                        gameState.board[Idx].card != screenGame.board[Idx])
                    {
                        bBoardChanged        = true;
                        gameState.board[Idx] = new TriadCardInstance(screenGame.board[Idx], screenGame.boardOwner[Idx]);
                    }
                }

                gameState.numCardsPlaced += (gameState.board[Idx] != null) ? 1 : 0;
            }

            if (bBoardChanged)
            {
                updateFlags |= EUpdateFlags.Board;

                foreach (TriadGameModifier mod in gameSession.modifiers)
                {
                    mod.OnScreenUpdate(gameState);
                }
            }

            // start of game, do additional checks when swap rule is active
            if (bHasSwapRule && gameState.numCardsPlaced <= 1)
            {
                updateFlags |= DetectSwapOnGameStart();
            }

            if (logScan)
            {
                Logger.WriteLine("OnNewScan> board:" + (bBoardChanged ? "changed" : "same") +
                                 ", blue:" + (bBlueDeckChanged ? "changed" : "same") +
                                 ", red:" + (bRedDeckChanged ? "changed" : "same") +
                                 ", mods:" + (bModsChanged ? "changed" : "same") +
                                 ", continuePrev:" + bContinuesPrevState +
                                 " => " + ((updateFlags != EUpdateFlags.None) ? ("UPDATE[" + updateFlags + "]") : "skip"));
            }

            return(updateFlags);
        }