Exemple #1
0
        private bool IsSuddenDeathRestart(TriadDeckInstanceScreen deck)
        {
            // sudden death: all red cards visible, not matching npc deck at all
            int numMismatchedCards = 0;
            int numVisibleCards    = 0;
            int hiddenCardId       = TriadCardDB.Get().hiddenCard.Id;

            for (int Idx = 0; Idx < deck.cards.Length; Idx++)
            {
                int npcCardIdx = deck.deck.GetCardIndex(deck.cards[Idx]);
                if (npcCardIdx < 0)
                {
                    numMismatchedCards++;
                }

                if (deck.cards[Idx] != null && deck.cards[Idx].Id != hiddenCardId)
                {
                    numVisibleCards++;
                }
            }

            bool bHasOpenAndMismatched = (numVisibleCards >= 4 && numMismatchedCards > 1);
            bool bHasOpenAndShouldnt   = (numVisibleCards >= 4 && !bHasOpenRule);

            Logger.WriteLine("IsSuddenDeathRestart? numMismatchedCards:" + numMismatchedCards + ", numVisibleCards:" + numVisibleCards);
            return(bHasOpenAndMismatched || bHasOpenAndShouldnt);
        }
Exemple #2
0
 public TriadGameScreenMemory()
 {
     gameSession        = new TriadGameSession();
     gameState          = new TriadGameData();
     deckBlue           = new TriadDeckInstanceScreen();
     deckRed            = new TriadDeckInstanceScreen();
     blueDeckHistory    = new List <TriadCard[]>();
     bHasSwapRule       = false;
     swappedBlueCardIdx = -1;
     lastScanNpc        = null;
 }
Exemple #3
0
        private void UpdateRedDeckDetails(TriadDeckInstanceScreen deck)
        {
            string NumPlacedPrefix = "All placed: ";
            string VarPlacedPrefix = "Var placed: ";

            if (deck == null || deck.deck == null)
            {
                for (int Idx = 0; Idx < redDeckKnownCards.Length; Idx++)
                {
                    redDeckKnownCards[Idx].Visible   = false;
                    redDeckUnknownCards[Idx].Visible = false;
                    deckCtrlRed.SetTransparent(Idx, false);
                }

                labelNumPlaced.Text     = NumPlacedPrefix + "0";
                labelUnknownPlaced.Text = VarPlacedPrefix + "0";
            }
            else
            {
                int firstKnownIdx   = deck.cards.Length;
                int firstUnknownIdx = deck.cards.Length + deck.deck.knownCards.Count;
                for (int Idx = 0; Idx < redDeckKnownCards.Length; Idx++)
                {
                    bool bIsValidKnownCard = Idx < deck.deck.knownCards.Count;
                    redDeckKnownCards[Idx].Visible = bIsValidKnownCard;
                    if (bIsValidKnownCard)
                    {
                        bool bIsUsed = deck.IsPlaced(firstKnownIdx + Idx);
                        redDeckKnownCards[Idx].bIsTransparent = bIsUsed;
                        TriadCard showCard = (deck.swappedCardIdx == (firstKnownIdx + Idx)) ? deck.swappedCard : deck.deck.knownCards[Idx];
                        redDeckKnownCards[Idx].SetCard(new TriadCardInstance(showCard, ETriadCardOwner.Red));
                    }

                    bool bIsValidUnknownCard = Idx < deck.deck.unknownCardPool.Count;
                    redDeckUnknownCards[Idx].Visible = bIsValidUnknownCard;
                    if (bIsValidUnknownCard)
                    {
                        bool bIsUsed = deck.IsPlaced(firstUnknownIdx + Idx);
                        redDeckUnknownCards[Idx].bIsTransparent = bIsUsed;
                        TriadCard showCard = (deck.swappedCardIdx == (firstUnknownIdx + Idx)) ? deck.swappedCard : deck.deck.unknownCardPool[Idx];
                        redDeckUnknownCards[Idx].SetCard(new TriadCardInstance(showCard, ETriadCardOwner.Red));
                    }
                }

                for (int Idx = 0; Idx < deck.cards.Length; Idx++)
                {
                    bool bIsUsed = deck.IsPlaced(Idx);
                    deckCtrlRed.SetTransparent(Idx, bIsUsed);
                }

                labelNumPlaced.Text     = NumPlacedPrefix + deck.numPlaced;
                labelUnknownPlaced.Text = VarPlacedPrefix + deck.numUnknownPlaced;
            }
        }
Exemple #4
0
        private bool IsDeckMatching(TriadDeckInstanceScreen deckInstance, TriadCard[] cards)
        {
            bool bIsMatching = false;

            if ((deckInstance != null) && (cards != null) && (deckInstance.cards.Length >= cards.Length))
            {
                bIsMatching = true;
                for (int Idx = 0; Idx < cards.Length; Idx++)
                {
                    bIsMatching = bIsMatching && (cards[Idx] == deckInstance.cards[Idx]);
                }
            }

            return(bIsMatching);
        }
Exemple #5
0
        public TriadDeckInstanceScreen(TriadDeckInstanceScreen copyFrom)
        {
            cards = new TriadCard[copyFrom.cards.Length];
            for (int Idx = 0; Idx < copyFrom.cards.Length; Idx++)
            {
                cards[Idx] = copyFrom.cards[Idx];
            }

            deck              = copyFrom.deck;
            numUnknownPlaced  = copyFrom.numUnknownPlaced;
            numPlaced         = copyFrom.numPlaced;
            availableCardMask = copyFrom.availableCardMask;
            unknownPoolMask   = copyFrom.unknownPoolMask;
            swappedCardIdx    = copyFrom.swappedCardIdx;
            swappedCard       = copyFrom.swappedCard;
        }
Exemple #6
0
        private bool FindSwappedCardVisible(TriadCard[] screenCards, TriadCardInstance[] board, TriadDeckInstanceScreen otherDeck, out int swappedCardIdx, out int swappedOtherIdx, out TriadCard swappedCard)
        {
            swappedCardIdx  = -1;
            swappedOtherIdx = -1;
            swappedCard     = null;

            int numDiffs  = 0;
            int numOnHand = 0;

            int hiddenCardId = TriadCardDB.Get().hiddenCard.Id;

            for (int Idx = 0; Idx < otherDeck.cards.Length; Idx++)
            {
                if (otherDeck.cards[Idx] != null && otherDeck.cards[Idx].Id != hiddenCardId)
                {
                    // find in source deck, not in instance
                    int cardIdx = otherDeck.deck.GetCardIndex(otherDeck.cards[Idx]);
                    if (cardIdx < 0)
                    {
                        swappedOtherIdx = Idx;
                        swappedCard     = otherDeck.cards[Idx];
                        for (int ScreenIdx = 0; ScreenIdx < screenCards.Length; ScreenIdx++)
                        {
                            cardIdx = otherDeck.deck.GetCardIndex(screenCards[ScreenIdx]);
                            if (cardIdx >= 0)
                            {
                                swappedCardIdx = ScreenIdx;
                                numDiffs++;
                            }
                        }
                    }
                }

                numOnHand += (otherDeck.cards[Idx] != null) ? 1 : 0;
            }

            bool bBoardMode = false;

            if (numOnHand < screenCards.Length)
            {
                for (int Idx = 0; Idx < board.Length; Idx++)
                {
                    if (board[Idx] != null && board[Idx].owner == ETriadCardOwner.Red)
                    {
                        // find in source deck, not in instance
                        int cardIdx = otherDeck.deck.GetCardIndex(board[Idx].card);
                        if (cardIdx < 0)
                        {
                            swappedCard     = board[Idx].card;
                            swappedOtherIdx = 100;                  // something way outside, it's not going to be used directly as card was already placed

                            for (int ScreenIdx = 0; ScreenIdx < screenCards.Length; ScreenIdx++)
                            {
                                cardIdx = otherDeck.deck.GetCardIndex(screenCards[ScreenIdx]);
                                if (cardIdx >= 0)
                                {
                                    swappedCardIdx = ScreenIdx;
                                    bBoardMode     = true;
                                    numDiffs++;
                                }
                            }
                        }
                    }
                }
            }

            bool bHasSwapped = (numDiffs == 1);

            Logger.WriteLine("FindSwappedCardVisible: blue[" + swappedCardIdx + "]:" + (swappedCardIdx >= 0 ? screenCards[swappedCardIdx].Name : "??") +
                             " <=> red[" + swappedOtherIdx + "]:" + (swappedCard != null ? swappedCard.Name : "??") +
                             ", boardMode:" + bBoardMode + ", diffs:" + numDiffs + " => " + (bHasSwapped ? "SWAP" : "ignore"));

            return(bHasSwapped);
        }
Exemple #7
0
        private bool FindSwappedCard(TriadCard[] screenCards, TriadCard[] expectedCards, TriadDeckInstanceScreen otherDeck, out int swappedCardIdx, out int swappedOtherIdx, out TriadCard swappedCard)
        {
            swappedCardIdx  = -1;
            swappedOtherIdx = -1;
            swappedCard     = null;
            TriadCard swappedBlueCard = null;

            int numDiffs          = 0;
            int numPotentialSwaps = 0;

            for (int Idx = 0; Idx < screenCards.Length; Idx++)
            {
                if ((screenCards[Idx] != expectedCards[Idx]) && (screenCards[Idx] != null))
                {
                    numDiffs++;
                    swappedCardIdx  = Idx;
                    swappedOtherIdx = otherDeck.GetCardIndex(screenCards[Idx]);
                    swappedBlueCard = screenCards[Idx];
                    swappedCard     = expectedCards[Idx];
                    Logger.WriteLine("FindSwappedCard[" + Idx + "]: screen:" + screenCards[Idx].Name + ", expected:" + expectedCards[Idx].Name + ", redIdxScreen:" + swappedOtherIdx);

                    if (swappedOtherIdx >= 0)
                    {
                        numPotentialSwaps++;
                    }
                }
            }

            bool bHasSwapped = (numDiffs == 1) && (numPotentialSwaps == 1);

            Logger.WriteLine("FindSwappedCard: blue[" + swappedCardIdx + "]:" + (swappedBlueCard != null ? swappedBlueCard.Name : "??") +
                             " <=> red[" + swappedOtherIdx + "]:" + (swappedCard != null ? swappedCard.Name : "??") +
                             ", diffs:" + numDiffs + ", potentialSwaps:" + numPotentialSwaps +
                             " => " + (bHasSwapped ? "SWAP" : "ignore"));

            return(bHasSwapped);
        }
Exemple #8
0
        private void UpdateAvailableRedCards(TriadDeckInstanceScreen redDeck,
                                             TriadCard[] screenCardsRed, TriadCard[] screenCardsBlue, TriadCard[] screenBoard,
                                             TriadCard[] prevCardsBlue, TriadCardInstance[] prevBoard, bool bContinuePrevState)
        {
            bool bDebugMode      = false;
            int  hiddenCardId    = TriadCardDB.Get().hiddenCard.Id;
            int  numVisibleCards = deckRed.cards.Length;

            redDeck.numPlaced = 0;
            if (!bContinuePrevState)
            {
                redDeck.numUnknownPlaced = 0;
            }

            int maxUnknownToUse     = redDeck.cards.Length - redDeck.deck.knownCards.Count;
            int firstUnknownPoolIdx = redDeck.cards.Length + redDeck.deck.knownCards.Count;

            if (redDeck.deck.unknownCardPool.Count > 0)
            {
                redDeck.unknownPoolMask = ((1 << redDeck.deck.unknownCardPool.Count) - 1) << firstUnknownPoolIdx;

                for (int Idx = 0; Idx < screenCardsRed.Length; Idx++)
                {
                    if ((screenCardsRed[Idx] != null) && (screenCardsRed[Idx].Id != hiddenCardId) && redDeck.deck.unknownCardPool.Contains(screenCardsRed[Idx]))
                    {
                        redDeck.unknownPoolMask |= (1 << Idx);
                    }
                }
            }

            int allDeckAvailableMask = ((1 << (redDeck.deck.knownCards.Count + redDeck.deck.unknownCardPool.Count)) - 1) << numVisibleCards;

            bool bCanCompareWithPrevData = (screenCardsRed.Length == redDeck.cards.Length) && (screenCardsBlue.Length == prevCardsBlue.Length) && (screenBoard.Length == prevBoard.Length);

            if (bCanCompareWithPrevData && !bContinuePrevState)
            {
                // special case: 1st turn

                int numCardsOnBoard = 0;
                for (int Idx = 0; Idx < screenBoard.Length; Idx++)
                {
                    if (screenBoard[Idx] != null)
                    {
                        numCardsOnBoard++;
                    }
                }

                if (numCardsOnBoard <= 1)
                {
                    bCanCompareWithPrevData = true;
                    prevBoard                 = new TriadCardInstance[screenBoard.Length];
                    prevCardsBlue             = new TriadCard[numVisibleCards];
                    deckRed.cards             = new TriadCard[numVisibleCards];
                    deckRed.availableCardMask = allDeckAvailableMask;
                    deckRed.numPlaced         = 0;
                    deckRed.numUnknownPlaced  = 0;
                }
                else
                {
                    bCanCompareWithPrevData = false;
                }
            }

            if (bDebugMode)
            {
                Logger.WriteLine("Red deck update, diff mode check... " +
                                 "bContinuePrevState:" + bContinuePrevState +
                                 ", cards(screen:" + screenCardsRed.Length + ", prev:" + deckRed.cards.Length + ")=" + ((screenCardsRed.Length == deckRed.cards.Length) ? "ok" : "nope") +
                                 ", other(screen:" + screenCardsBlue.Length + ", prev:" + prevCardsBlue.Length + ")=" + ((screenCardsBlue.Length == prevCardsBlue.Length) ? "ok" : "nope") +
                                 ", board(screen:" + screenBoard.Length + ", prev:" + prevBoard.Length + ")=" + ((screenBoard.Length == prevBoard.Length) ? "ok" : "nope"));
            }

            if (bCanCompareWithPrevData)
            {
                // create diffs, hopefully prev state comes from last turn and is just 2 cards away
                List <int>       usedCardsIndices = new List <int>();
                List <TriadCard> usedCardsOther   = new List <TriadCard>();

                int numKnownOnHand   = 0;
                int numUnknownOnHand = 0;
                int numHidden        = 0;
                int numOnHand        = 0;
                for (int Idx = 0; Idx < deckRed.cards.Length; Idx++)
                {
                    if (screenCardsRed[Idx] == null)
                    {
                        TriadCard prevCard = deckRed.cards[Idx];
                        if ((prevCard != null) && (prevCard.Id != hiddenCardId))
                        {
                            if (bDebugMode)
                            {
                                Logger.WriteLine("  card[" + Idx + "]:" + prevCard.Name + " => mark as used, disappeared from prev state");
                            }
                            usedCardsIndices.Add(Idx);
                        }

                        deckRed.availableCardMask &= ~(1 << Idx);
                        deckRed.numPlaced++;
                    }
                    else
                    {
                        if (screenCardsRed[Idx].Id != hiddenCardId)
                        {
                            bool bIsUnknown = (deckRed.unknownPoolMask & (1 << Idx)) != 0;
                            numUnknownOnHand += bIsUnknown ? 1 : 0;
                            numKnownOnHand   += bIsUnknown ? 0 : 1;
                            numOnHand++;
                            deckRed.availableCardMask |= (1 << Idx);

                            int knownCardIdx   = deckRed.deck.knownCards.IndexOf(screenCardsRed[Idx]);
                            int unknownCardIdx = deckRed.deck.unknownCardPool.IndexOf(screenCardsRed[Idx]);
                            if (knownCardIdx >= 0)
                            {
                                deckRed.availableCardMask &= ~(1 << (knownCardIdx + deckRed.cards.Length));
                            }
                            else if (unknownCardIdx >= 0)
                            {
                                deckRed.availableCardMask &= ~(1 << (unknownCardIdx + deckRed.cards.Length + deckRed.deck.knownCards.Count));
                            }

                            if (bDebugMode)
                            {
                                TriadCard cardOb = screenCardsRed[Idx];
                                Logger.WriteLine(" card[" + Idx + "]:" + (cardOb != null ? cardOb.Name : "??") +
                                                 " => numUnknown:" + numUnknownOnHand + ", numKnown:" + numKnownOnHand + ", numHidden:" + numHidden);
                            }
                        }
                        else
                        {
                            numHidden++;
                        }
                    }
                }

                for (int Idx = 0; Idx < prevCardsBlue.Length; Idx++)
                {
                    if ((prevCardsBlue[Idx] != null) && (screenCardsBlue[Idx] == null))
                    {
                        usedCardsOther.Add(prevCardsBlue[Idx]);
                        if (bDebugMode)
                        {
                            Logger.WriteLine("  blue[" + Idx + "]:" + prevCardsBlue[Idx].Name + " => mark as used");
                        }
                    }
                }

                for (int Idx = 0; Idx < prevBoard.Length; Idx++)
                {
                    TriadCard testCard = screenBoard[Idx];
                    if ((prevBoard[Idx] == null || prevBoard[Idx].card == null) && (testCard != null))
                    {
                        int testCardIdx = deckRed.GetCardIndex(testCard);
                        if (!usedCardsOther.Contains(testCard) && (testCardIdx >= 0))
                        {
                            usedCardsIndices.Add(testCardIdx);
                            if (bDebugMode)
                            {
                                Logger.WriteLine("  card[" + testCardIdx + "]:" + testCard.Name + " => mark as used, appeared on board[" + Idx + "], not used by blue");
                            }
                        }
                    }
                }

                Array.Copy(screenCardsRed, deckRed.cards, 5);

                for (int Idx = 0; Idx < usedCardsIndices.Count; Idx++)
                {
                    int cardMask = 1 << usedCardsIndices[Idx];
                    deckRed.availableCardMask &= ~cardMask;

                    bool bIsUnknownPool = (deckRed.unknownPoolMask & cardMask) != 0;
                    if (bIsUnknownPool)
                    {
                        deckRed.numUnknownPlaced++;
                    }

                    if (bDebugMode)
                    {
                        TriadCard cardOb = deckRed.GetCard(usedCardsIndices[Idx]);
                        Logger.WriteLine(" card[" + usedCardsIndices[Idx] + "]:" + (cardOb != null ? cardOb.Name : "??") + " => used");
                    }
                }

                if ((numHidden == 0) && ((numOnHand + deckRed.numPlaced) == numVisibleCards))
                {
                    deckRed.availableCardMask &= (1 << numVisibleCards) - 1;
                    if (bDebugMode)
                    {
                        Logger.WriteLine("   all cards are on hand and visible");
                    }
                }
                else if ((deckRed.numUnknownPlaced + numUnknownOnHand) >= maxUnknownToUse ||
                         ((numKnownOnHand >= (numVisibleCards - maxUnknownToUse)) && (numHidden == 0)))
                {
                    deckRed.availableCardMask &= (1 << (numVisibleCards + deckRed.deck.knownCards.Count)) - 1;

                    if (bDebugMode)
                    {
                        Logger.WriteLine("   removing all unknown cards, numUnknownPlaced:" + deckRed.numUnknownPlaced +
                                         ", numUnknownOnHand:" + numUnknownOnHand + ", numKnownOnHand:" + numKnownOnHand +
                                         ", numHidden:" + numHidden + ", maxUnknownToUse:" + maxUnknownToUse);
                    }
                }
            }
            else
            {
                // TriadDeckInstanceScreen is mostly stateless (created from scratch on screen capture)
                // this makes guessing which cards were placed hard, especially when there's no good
                // history data to compare with.
                // Ignore board data here, cards could be placed by blue and are still available for red deck

                deckRed.UpdateAvailableCards(screenCardsRed);
                deckRed.availableCardMask = allDeckAvailableMask;
            }

            if (bDebugMode)
            {
                redDeck.LogAvailableCards("Red deck");
            }
        }
Exemple #9
0
        public override TriadDeckInstance CreateCopy()
        {
            TriadDeckInstanceScreen deckCopy = new TriadDeckInstanceScreen(this);

            return(deckCopy);
        }