Example #1
0
        public bool PlaceCard(TriadGameData gameData, TriadCard card, ETriadCardOwner owner, int boardPos)
        {
            TriadDeckInstance useDeck = (owner == ETriadCardOwner.Blue) ? gameData.deckBlue : gameData.deckRed;
            int cardIdx = useDeck.GetCardIndex(card);

            return(PlaceCard(gameData, cardIdx, useDeck, owner, boardPos));
        }
Example #2
0
        public bool SolverPlayRandomTurn(TriadGameData gameData, Random random)
        {
#if DEBUG
            Stopwatch timer = new Stopwatch();
            timer.Start();
#endif // DEBUG
            const int boardPosMax = TriadGameData.boardSize * TriadGameData.boardSize;
            int       boardPos    = -1;
            if (gameData.numCardsPlaced < boardPosMax)
            {
                int testPos = random.Next(boardPosMax);
                for (int passIdx = 0; passIdx < boardPosMax; passIdx++)
                {
                    testPos = (testPos + 1) % boardPosMax;
                    if (gameData.board[testPos] == null)
                    {
                        boardPos = testPos;
                        break;
                    }
                }
            }
#if DEBUG
            perfStats.PlayRandomTurnSelectSpot += timer.ElapsedTicks;
            timer.Restart();
#endif // DEBUG

            int cardIdx = -1;
            TriadDeckInstance useDeck = (gameData.state == ETriadGameState.InProgressBlue) ? gameData.deckBlue : gameData.deckRed;
            if (useDeck.availableCardMask > 0)
            {
                int testIdx = random.Next(TriadDeckInstance.maxAvailableCards);
                for (int passIdx = 0; passIdx < TriadDeckInstance.maxAvailableCards; passIdx++)
                {
                    testIdx = (testIdx + 1) % TriadDeckInstance.maxAvailableCards;
                    if ((useDeck.availableCardMask & (1 << testIdx)) != 0)
                    {
                        cardIdx = testIdx;
                        break;
                    }
                }
            }
#if DEBUG
            perfStats.PlayRandomTurnSelectCard += timer.ElapsedTicks;
            timer.Restart();
#endif // DEBUG

            bool bResult = false;
            if (cardIdx >= 0)
            {
                bResult = PlaceCard(gameData, cardIdx, useDeck, (gameData.state == ETriadGameState.InProgressBlue) ? ETriadCardOwner.Blue : ETriadCardOwner.Red, boardPos);
            }

#if DEBUG
            perfStats.PlayRandomTurnPlaceCard += timer.ElapsedTicks;
            timer.Stop();
#endif // DEBUG
            return(bResult);
        }
Example #3
0
        public bool SolverPlayRandomTurn(TriadGameData gameData, Random random)
        {
            const int boardPosMax = TriadGameData.boardSize * TriadGameData.boardSize;
            int       boardPos    = -1;

            if (gameData.numCardsPlaced < boardPosMax)
            {
                int testPos = random.Next(boardPosMax);
                for (int passIdx = 0; passIdx < boardPosMax; passIdx++)
                {
                    testPos = (testPos + 1) % boardPosMax;
                    if (gameData.board[testPos] == null)
                    {
                        boardPos = testPos;
                        break;
                    }
                }
            }

            int cardIdx = -1;
            TriadDeckInstance useDeck = (gameData.state == ETriadGameState.InProgressBlue) ? gameData.deckBlue : gameData.deckRed;

            if (useDeck.availableCardMask > 0)
            {
                int testIdx = random.Next(TriadDeckInstance.maxAvailableCards);
                for (int passIdx = 0; passIdx < TriadDeckInstance.maxAvailableCards; passIdx++)
                {
                    testIdx = (testIdx + 1) % TriadDeckInstance.maxAvailableCards;
                    if ((useDeck.availableCardMask & (1 << testIdx)) != 0)
                    {
                        cardIdx = testIdx;
                        break;
                    }
                }
            }

            bool bResult = false;

            if (cardIdx >= 0)
            {
                bResult = PlaceCard(gameData, cardIdx, useDeck, (gameData.state == ETriadGameState.InProgressBlue) ? ETriadCardOwner.Blue : ETriadCardOwner.Red, boardPos);
            }

            return(bResult);
        }
Example #4
0
        public TriadGameData(TriadGameData copyFrom)
        {
            board = new TriadCardInstance[copyFrom.board.Length];
            for (int Idx = 0; Idx < board.Length; Idx++)
            {
                board[Idx] = (copyFrom.board[Idx] == null) ? null : new TriadCardInstance(copyFrom.board[Idx]);
            }

            typeMods = new int[copyFrom.typeMods.Length];
            for (int Idx = 0; Idx < typeMods.Length; Idx++)
            {
                typeMods[Idx] = copyFrom.typeMods[Idx];
            }

            deckBlue        = copyFrom.deckBlue.CreateCopy();
            deckRed         = copyFrom.deckRed.CreateCopy();
            state           = copyFrom.state;
            numCardsPlaced  = copyFrom.numCardsPlaced;
            numRestarts     = copyFrom.numRestarts;
            resolvedSpecial = copyFrom.resolvedSpecial;
            // bDebugRules not copied, only first step needs it
        }
Example #5
0
        public bool SolverFindBestMove(TriadGameData gameData, out int boardPos, out TriadCard card, out TriadGameResultChance probabilities)
        {
            bool bResult = false;

            card            = null;
            boardPos        = -1;
            currentProgress = 0;

            string namePrefix = string.IsNullOrEmpty(solverName) ? "" : ("[" + solverName + "] ");

            // prepare available board data
            int availBoardMask = 0;
            int numAvailBoard  = 0;

            for (int Idx = 0; Idx < gameData.board.Length; Idx++)
            {
                if (gameData.board[Idx] == null)
                {
                    availBoardMask |= (1 << Idx);
                    numAvailBoard++;
                }
            }

            // prepare available cards data
            TriadDeckInstance useDeck   = (gameData.state == ETriadGameState.InProgressBlue) ? gameData.deckBlue : gameData.deckRed;
            ETriadCardOwner   turnOwner = (gameData.state == ETriadGameState.InProgressBlue) ? ETriadCardOwner.Blue : ETriadCardOwner.Red;
            int availCardsMask          = 0;

            if (gameData.state == ETriadGameState.InProgressBlue && gameData.forcedCardIdx >= 0)
            {
                availCardsMask = 1 << gameData.forcedCardIdx;
            }
            else
            {
                availCardsMask = useDeck.availableCardMask;
            }

            if ((modFeatures & TriadGameModifier.EFeature.FilterNext) != 0)
            {
                foreach (TriadGameModifier mod in modifiers)
                {
                    mod.OnFilterNextCards(gameData, ref availCardsMask);
                }
            }

            int numAvailCards = 0;

            for (int Idx = 0; Idx < TriadDeckInstance.maxAvailableCards; Idx++)
            {
                numAvailCards += ((availCardsMask & (1 << Idx)) != 0) ? 1 : 0;
            }

            // check all combinations
            if ((numAvailCards > 0) && (numAvailBoard > 0))
            {
                int numCombinations            = numAvailCards * numAvailBoard;
                TriadGameResultChance bestProb = new TriadGameResultChance(-1.0f, 0);

                int cardProgressCounter = 0;
                for (int cardIdx = 0; cardIdx < TriadDeckInstance.maxAvailableCards; cardIdx++)
                {
                    bool bCardNotAvailable = (availCardsMask & (1 << cardIdx)) == 0;
                    if (bCardNotAvailable)
                    {
                        continue;
                    }

                    currentProgress = 100 * cardProgressCounter / numAvailCards;
                    cardProgressCounter++;

                    for (int boardIdx = 0; boardIdx < gameData.board.Length; boardIdx++)
                    {
                        bool bBoardNotAvailable = (availBoardMask & (1 << boardIdx)) == 0;
                        if (bBoardNotAvailable)
                        {
                            continue;
                        }

                        TriadGameData gameDataCopy = new TriadGameData(gameData);
                        bool          bPlaced      = PlaceCard(gameDataCopy, cardIdx, useDeck, turnOwner, boardIdx);
                        if (bPlaced)
                        {
                            TriadGameResultChance gameProb = SolverFindWinningProbability(gameDataCopy);
                            if (gameProb.IsBetterThan(bestProb))
                            {
                                bestProb = gameProb;
                                card     = useDeck.GetCard(cardIdx);
                                boardPos = boardIdx;
                                bResult  = true;
                            }
                        }
                    }
                }

                probabilities = bestProb;
                Logger.WriteLine(namePrefix + "Solver win:" + bestProb.winChance.ToString("P2") + " (draw:" + bestProb.drawChance.ToString("P2") +
                                 "), blue[" + gameData.deckBlue + "], red[" + gameData.deckRed + "], turn:" + turnOwner + ", availBoard:" + numAvailBoard +
                                 " (" + availBoardMask.ToString("x") + ") availCards:" + numAvailCards + " (" + (useDeck == gameData.deckBlue ? "B" : "R") + ":" + availCardsMask.ToString("x") + ")");
            }
            else
            {
                probabilities = new TriadGameResultChance(0, 0);
                Logger.WriteLine(namePrefix + "Can't find move! availSpots:" + numAvailBoard + " (" + availBoardMask.ToString("x") +
                                 ") availCards:" + numAvailCards + " (" + (useDeck == gameData.deckBlue ? "B" : "R") + ":" + availCardsMask.ToString("x") + ")");
            }

            return(bResult);
        }
Example #6
0
        public bool PlaceCard(TriadGameData gameData, int cardIdx, TriadDeckInstance cardDeck, ETriadCardOwner owner, int boardPos)
        {
            bool bResult = false;

            bool bIsAllowedOwner =
                ((owner == ETriadCardOwner.Blue) && (gameData.state == ETriadGameState.InProgressBlue)) ||
                ((owner == ETriadCardOwner.Red) && (gameData.state == ETriadGameState.InProgressRed));

            TriadCard card = cardDeck.GetCard(cardIdx);

            if (bIsAllowedOwner && (boardPos >= 0) && (gameData.board[boardPos] == null) && (card != null))
            {
                gameData.board[boardPos] = new TriadCardInstance(card, owner);
                gameData.numCardsPlaced++;

                if (owner == ETriadCardOwner.Blue)
                {
                    gameData.deckBlue.OnCardPlacedFast(cardIdx);
                    gameData.state = ETriadGameState.InProgressRed;
                }
                else
                {
                    gameData.deckRed.OnCardPlacedFast(cardIdx);
                    gameData.state = ETriadGameState.InProgressBlue;
                }
                bResult = true;

                bool bAllowCombo = false;
                if ((modFeatures & TriadGameModifier.EFeature.CardPlaced) != 0)
                {
                    foreach (TriadGameModifier mod in modifiers)
                    {
                        mod.OnCardPlaced(gameData, boardPos);
                        bAllowCombo = bAllowCombo || mod.AllowsCombo();
                    }
                }

                List <int> comboList    = new List <int>();
                int        comboCounter = 0;
                CheckCaptures(gameData, boardPos, comboList, comboCounter);

                while (bAllowCombo && comboList.Count > 0)
                {
                    if (gameData.bDebugRules)
                    {
                        Logger.WriteLine(">> combo step: {0}", string.Join(",", comboList));
                    }

                    List <int> nextCombo = new List <int>();
                    comboCounter++;
                    foreach (int pos in comboList)
                    {
                        CheckCaptures(gameData, pos, nextCombo, comboCounter);
                    }

                    comboList = nextCombo;
                }

                if ((modFeatures & TriadGameModifier.EFeature.PostCapture) != 0)
                {
                    foreach (TriadGameModifier mod in modifiers)
                    {
                        mod.OnPostCaptures(gameData, boardPos);
                    }
                }

                if (gameData.numCardsPlaced == gameData.board.Length)
                {
                    OnAllCardsPlaced(gameData);
                }
            }

            return(bResult);
        }
Example #7
0
        public bool PlaceCard(TriadGameData gameData, int cardIdx, TriadDeckInstance cardDeck, ETriadCardOwner owner, int boardPos)
        {
            bool bResult = false;

            bool bIsAllowedOwner =
                ((owner == ETriadCardOwner.Blue) && (gameData.state == ETriadGameState.InProgressBlue)) ||
                ((owner == ETriadCardOwner.Red) && (gameData.state == ETriadGameState.InProgressRed));

            TriadCard card = cardDeck.GetCard(cardIdx);

            if (bIsAllowedOwner && (boardPos >= 0) && (gameData.board[boardPos] == null) && (card != null))
            {
#if DEBUG
                Stopwatch timer = new Stopwatch();
                timer.Start();
#endif // DEBUG

                gameData.board[boardPos] = new TriadCardInstance(card, owner);
                gameData.numCardsPlaced++;

                if (owner == ETriadCardOwner.Blue)
                {
                    gameData.deckBlue.OnCardPlacedFast(cardIdx);
                    gameData.state = ETriadGameState.InProgressRed;
                }
                else
                {
                    gameData.deckRed.OnCardPlacedFast(cardIdx);
                    gameData.state = ETriadGameState.InProgressBlue;
                }
#if DEBUG
                perfStats.PlaceCardOnPlaced += timer.ElapsedTicks;
                timer.Restart();
#endif // DEBUG
                bResult = true;

                bool bAllowCombo = false;
                if ((modFeatures & TriadGameModifier.EFeature.CardPlaced) != 0)
                {
                    foreach (TriadGameModifier mod in modifiers)
                    {
                        mod.OnCardPlaced(gameData, boardPos);
                        bAllowCombo = bAllowCombo || mod.AllowsCombo();
                    }
                }
#if DEBUG
                perfStats.PlaceCardOnPlacedMods += timer.ElapsedTicks;
                timer.Restart();
#endif // DEBUG

                List <int> comboList    = new List <int>();
                int        comboCounter = 0;
                CheckCaptures(gameData, boardPos, comboList, comboCounter);
#if DEBUG
                perfStats.PlaceCardCaptures += timer.ElapsedTicks;
                timer.Restart();
#endif // DEBUG

                while (bAllowCombo && comboList.Count > 0)
                {
                    List <int> nextCombo = new List <int>();
                    comboCounter++;
                    foreach (int pos in comboList)
                    {
                        CheckCaptures(gameData, pos, nextCombo, comboCounter);
                    }

                    comboList = nextCombo;
                }
#if DEBUG
                perfStats.PlaceCardCapturesCombo += timer.ElapsedTicks;
                timer.Restart();
#endif // DEBUG

                if ((modFeatures & TriadGameModifier.EFeature.PostCapture) != 0)
                {
                    foreach (TriadGameModifier mod in modifiers)
                    {
                        mod.OnPostCaptures(gameData, boardPos);
                    }
                }
#if DEBUG
                perfStats.PlaceCardPostCaptures += timer.ElapsedTicks;
                timer.Restart();
#endif // DEBUG

                if (gameData.numCardsPlaced == gameData.board.Length)
                {
                    OnAllCardsPlaced(gameData);
                }
#if DEBUG
                timer.Stop();
                perfStats.PlaceCardAllPlaced += timer.ElapsedTicks;
#endif // DEBUG
            }

            return(bResult);
        }