Example #1
0
            public override string ToString()
            {
                string rarityStr = "*";

                for (ETriadCardRarity Idx = ETriadCardRarity.Common; Idx < Card.Rarity; Idx++)
                {
                    rarityStr += " *";
                }

                return(Card.Name + " (" + rarityStr + ")");
            }
Example #2
0
 public TriadCard(int id, string name, string iconPath, ETriadCardRarity rarity, ETriadCardType type, int numUp, int numDown, int numLeft, int numRight, int sortKey)
 {
     Id       = id;
     Name     = name;
     IconPath = iconPath;
     Rarity   = rarity;
     Type     = type;
     Sides    = new int[4] {
         numUp, numLeft, numDown, numRight
     };
     SameNumberId = -1;
     SortKey      = sortKey;
 }
Example #3
0
        private bool TryParseCardRarity(string desc, out ETriadCardRarity foundRarity)
        {
            if (!string.IsNullOrEmpty(desc))
            {
                foreach (ETriadCardRarity testRarity in Enum.GetValues(typeof(ETriadCardRarity)))
                {
                    if (testRarity.ToString().Equals(desc, StringComparison.InvariantCultureIgnoreCase))
                    {
                        foundRarity = testRarity;
                        return(true);
                    }
                }
            }

            foundRarity = ETriadCardRarity.Common;
            return(false);
        }
Example #4
0
        public TriadCard(int id, string iconPath, ETriadCardRarity rarity, ETriadCardType type, int numUp, int numDown, int numLeft, int numRight, int sortOrder, int group)
        {
            Id       = id;
            Name     = LocalizationDB.Get().FindOrAddLocString(ELocStringType.CardName, id);
            IconPath = iconPath;
            Rarity   = rarity;
            Type     = type;
            Sides    = new int[4] {
                numUp, numLeft, numDown, numRight
            };
            SameNumberId = -1;
            SortOrder    = sortOrder;
            Group        = group;

            if (group != 0 && SortOrder < 1000)
            {
                SortOrder += 1000;
            }
        }
Example #5
0
        public TriadCard(int id, string name, string iconPath, ETriadCardRarity rarity, ETriadCardType type, int numUp, int numDown, int numLeft, int numRight, int sortOrder, int group)
        {
            Id       = id;
            Name     = name;
            IconPath = iconPath;
            Rarity   = rarity;
            Type     = type;
            Sides    = new int[4] {
                numUp, numLeft, numDown, numRight
            };
            SameNumberId = -1;
            SortOrder    = sortOrder;
            Group        = group;

            if (group != 0 && SortOrder < 1000)
            {
                SortOrder += 1000;
            }
        }
Example #6
0
        private void UpdatePossibleDeckCount(int numRare, int numCommon, List <TriadCard> lockedCards, bool bIsOrderImportant)
        {
            int numLocked = 0;

            foreach (TriadCard card in lockedCards)
            {
                if (card != null)
                {
                    numLocked++;
                }
            }

            if (numLocked > 0)
            {
                ETriadCardRarity rareThreshold = GetRareThreshold(PlayerSettingsDB.Get().ownedCards);
                ECardSlotState[] cardSlots     = BuildCardSlots(lockedCards, numRare, numCommon, rareThreshold, bIsOrderImportant);
                UpdatePossibleDeckCount(numRare, numCommon, cardSlots, bIsOrderImportant);
            }
            else
            {
                // num possible decks: numRare * (num 4 element combinations from numCommon set)
                // num 4 elem: numCommon! / (4! * (numCommon - 4)!)

                numPossibleDecks = numRare;
                for (int Idx = 0; Idx < 4; Idx++)
                {
                    numPossibleDecks *= (numCommon - Idx);
                }

                int Fact4 = (4 * 3 * 2 * 1);
                if (!bIsOrderImportant || !bAllowPermutationChecks)
                {
                    numPossibleDecks /= Fact4;
                }
            }
        }
Example #7
0
        private ECardSlotState[] BuildCardSlots(List <TriadCard> lockedCards, int numRare, int numCommon, ETriadCardRarity rareThreshold, bool bIsOrderImportant)
        {
            ECardSlotState[] slots = new ECardSlotState[lockedCards.Count];

            // assign locked slots
            int numAssignedRare = 0;

            for (int Idx = 0; Idx < lockedCards.Count; Idx++)
            {
                if (lockedCards[Idx] != null)
                {
                    if (lockedCards[Idx].Rarity >= rareThreshold)
                    {
                        slots[Idx] = ECardSlotState.LockedRare;
                        numAssignedRare++;
                    }
                    else
                    {
                        slots[Idx] = ECardSlotState.LockedCommon;
                    }
                }
                else
                {
                    slots[Idx] = ECardSlotState.Common;
                }
            }

            // assign rare slot (1st available or 2nd for order rule)
            if (numAssignedRare == 0 && numRare > 0)
            {
                int FirstFreeIdx  = 0;
                int SecondFreeIdx = 0;
                for (int Idx = 0; Idx < slots.Length; Idx++)
                {
                    if (slots[Idx] == ECardSlotState.Common)
                    {
                        if (FirstFreeIdx <= 0)
                        {
                            FirstFreeIdx = Idx;
                        }
                        else if (SecondFreeIdx <= 0)
                        {
                            SecondFreeIdx = Idx;
                        }
                    }
                }

                int UseRareIdx = (bIsOrderImportant && SecondFreeIdx <= 3) ? SecondFreeIdx : FirstFreeIdx;
                slots[UseRareIdx] = ECardSlotState.Rare;
            }

            return(slots);
        }
Example #8
0
        private void FindDecksScored(TriadGameModifier[] regionMods, List <TriadCard> lockedCards)
        {
            PlayerSettingsDB playerDB = PlayerSettingsDB.Get();
            //TriadCardDB playerDB = TriadCardDB.Get();

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            TriadGameSession solver = new TriadGameSession();

            solver.modifiers.AddRange(npc.Rules);
            solver.modifiers.AddRange(regionMods);
            solver.UpdateSpecialRules();

            bool bIsOrderImportant = false;

            foreach (TriadGameModifier mod in solver.modifiers)
            {
                bIsOrderImportant = bIsOrderImportant || mod.IsDeckOrderImportant();
            }

            List <TriadCard> rareList   = new List <TriadCard>();
            List <TriadCard> commonList = new List <TriadCard>();

            FindCardsToUse(playerDB.ownedCards, solver.modifiers, rareList, commonList);

            ETriadCardRarity rareThreshold = GetRareThreshold(playerDB.ownedCards);

            ECardSlotState[] cardSlots = BuildCardSlots(lockedCards, rareList.Count, commonList.Count, rareThreshold, bIsOrderImportant);

            object    lockOb    = new object();
            int       bestScore = 0;
            TriadDeck bestDeck  = new TriadDeck(PlayerSettingsDB.Get().starterCards);

            List <TriadCard>[] slotLists = new List <TriadCard> [cardSlots.Length];
            int numLocked    = 0;
            int numRareSlots = 0;

            for (int Idx = 0; Idx < slotLists.Length; Idx++)
            {
                switch (cardSlots[Idx])
                {
                case ECardSlotState.Common:
                    slotLists[Idx] = commonList;
                    break;

                case ECardSlotState.Rare:
                    slotLists[Idx] = rareList;
                    numRareSlots++;
                    break;

                default:
                    slotLists[Idx] = new List <TriadCard>()
                    {
                        lockedCards[Idx]
                    };
                    numLocked++;
                    break;
                }
            }

            if (numLocked > 0)
            {
                // slower when ran for all 5 slots
                UpdatePossibleDeckCount(rareList.Count, commonList.Count, cardSlots, bIsOrderImportant);

                //for (int IdxS0 = 0; IdxS0 < slotLists[0].Count; IdxS0++)
                Parallel.For(0, slotLists[0].Count, IdxS0 =>
                {
                    if (!bAbort)
                    {
                        //for (int IdxS1 = 0; IdxS1 < slotLists[1].Count; IdxS1++)
                        Parallel.For(0, slotLists[1].Count, IdxS1 =>
                        {
                            if (!bAbort)
                            {
                                //for (int IdxS2 = 0; IdxS2 < slotLists[2].Count; IdxS2++)
                                Parallel.For(0, slotLists[2].Count, IdxS2 =>
                                {
                                    if (!bAbort)
                                    {
                                        //for (int IdxS3 = 0; IdxS3 < slotLists[3].Count; IdxS3++)
                                        Parallel.For(0, slotLists[3].Count, IdxS3 =>
                                        {
                                            if (!bAbort)
                                            {
                                                //for (int IdxS4 = 0; IdxS4 < slotLists[4].Count; IdxS4++)
                                                Parallel.For(0, slotLists[4].Count, IdxS4 =>
                                                {
                                                    if (!bAbort)
                                                    {
                                                        TriadCard[] testDeckCards = new TriadCard[] { slotLists[0][IdxS0], slotLists[1][IdxS1], slotLists[2][IdxS2], slotLists[3][IdxS3], slotLists[4][IdxS4] };
                                                        if (testDeckCards[0] != testDeckCards[1] &&
                                                            testDeckCards[0] != testDeckCards[2] &&
                                                            testDeckCards[0] != testDeckCards[3] &&
                                                            testDeckCards[0] != testDeckCards[4] &&
                                                            testDeckCards[1] != testDeckCards[2] &&
                                                            testDeckCards[1] != testDeckCards[3] &&
                                                            testDeckCards[1] != testDeckCards[4] &&
                                                            testDeckCards[2] != testDeckCards[3] &&
                                                            testDeckCards[2] != testDeckCards[4] &&
                                                            testDeckCards[3] != testDeckCards[4])
                                                        {
                                                            Random randomGen = GetRandomStream(IdxS0, IdxS1, IdxS2, IdxS3, IdxS4);
                                                            // TODO: custom permutation lookup
                                                            {
                                                                TriadDeck testDeck = new TriadDeck(testDeckCards);
                                                                int testScore      = GetDeckScore(solver, testDeck, randomGen, 1);
                                                                if (testScore > bestScore)
                                                                {
                                                                    lock (lockOb)
                                                                    {
                                                                        bestScore = testScore;
                                                                        bestDeck  = testDeck;
                                                                        OnFoundDeck.Invoke(testDeck);
                                                                    }
                                                                }
                                                            }
                                                        }

                                                        lock (lockOb)
                                                        {
                                                            numTestedDecks++;
                                                        }
                                                    }
                                                });
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }
                });
            }
            else
            {
                // faster loops when nothing is locked
                // A: single rare slot, most common case
                if (numRareSlots == 1)
                {
                    UpdatePossibleDeckCount(rareList.Count, commonList.Count, lockedCards, bIsOrderImportant);

                    Parallel.For(0, rareList.Count, IdxR0 =>
                    {
                        if (!bAbort)
                        {
                            Parallel.For(0, commonList.Count, IdxC1 =>
                            {
                                if (!bAbort)
                                {
                                    for (int IdxC2 = IdxC1 + 1; IdxC2 < commonList.Count; IdxC2++)
                                    {
                                        for (int IdxC3 = IdxC2 + 1; IdxC3 < commonList.Count; IdxC3++)
                                        {
                                            for (int IdxC4 = IdxC3 + 1; IdxC4 < commonList.Count; IdxC4++)
                                            {
                                                TriadCard[] testDeckCards = new TriadCard[] { rareList[IdxR0], commonList[IdxC1], commonList[IdxC2], commonList[IdxC3], commonList[IdxC4] };
                                                Random randomGen          = GetRandomStream(IdxR0, IdxC1, IdxC2, IdxC3, IdxC4);

                                                if (bIsOrderImportant)
                                                {
                                                    if (bAllowPermutationChecks)
                                                    {
                                                        for (int IdxP = 0; IdxP < permutationList.Length; IdxP++)
                                                        {
                                                            int[] UseOrder            = permutationList[IdxP];
                                                            TriadCard[] permDeckCards = new TriadCard[] { testDeckCards[UseOrder[0]], testDeckCards[UseOrder[1]], testDeckCards[UseOrder[2]], testDeckCards[UseOrder[3]], testDeckCards[UseOrder[4]] };
                                                            TriadDeck permDeck        = new TriadDeck(permDeckCards);
                                                            int testScore             = GetDeckScore(solver, permDeck, randomGen, 10);
                                                            if (testScore > bestScore)
                                                            {
                                                                lock (lockOb)
                                                                {
                                                                    bestScore = testScore;
                                                                    bestDeck  = permDeck;
                                                                    OnFoundDeck.Invoke(permDeck);
                                                                }
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        testDeckCards = new TriadCard[] { commonList[IdxC1], rareList[IdxR0], commonList[IdxC2], commonList[IdxC3], commonList[IdxC4] };
                                                    }
                                                }

                                                {
                                                    TriadDeck testDeck = new TriadDeck(testDeckCards);
                                                    int testScore      = GetDeckScore(solver, testDeck, randomGen, 1);
                                                    if (testScore > bestScore)
                                                    {
                                                        lock (lockOb)
                                                        {
                                                            bestScore = testScore;
                                                            bestDeck  = testDeck;
                                                            OnFoundDeck.Invoke(testDeck);
                                                        }
                                                    }
                                                }

                                                lock (lockOb)
                                                {
                                                    numTestedDecks++;
                                                    if (bAbort)
                                                    {
                                                        IdxC2 = commonList.Count;
                                                        IdxC3 = commonList.Count;
                                                        IdxC4 = commonList.Count;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            });
                        }
                    });
                }
                else if (numRareSlots == 0)
                {
                    // remove part of common list for faster procesing, normally it would use 1 rare slot (smaller pool)
                    // randomly for all thta matters...
                    int    maxCommonToUse = commonList.Count * 80 / 100;
                    Random pruneRng       = new Random();

                    while (commonList.Count > maxCommonToUse)
                    {
                        int idxToRemove = pruneRng.Next(0, commonList.Count);
                        commonList.RemoveAt(idxToRemove);
                    }

                    // call simpler version of max possible combinations, 1 list in use
                    UpdatePossibleDeckCount(maxCommonToUse, bIsOrderImportant);
                    OnUpdateMaxSearchDecks?.Invoke(numPossibleDecks.ToString());

                    Parallel.For(0, commonList.Count, IdxC1 =>
                    {
                        if (!bAbort)
                        {
                            for (int IdxC2 = IdxC1 + 1; IdxC2 < commonList.Count; IdxC2++)
                            {
                                for (int IdxC3 = IdxC2 + 1; IdxC3 < commonList.Count; IdxC3++)
                                {
                                    for (int IdxC4 = IdxC3 + 1; IdxC4 < commonList.Count; IdxC4++)
                                    {
                                        for (int IdxC5 = IdxC4 + 1; IdxC5 < commonList.Count; IdxC5++)
                                        {
                                            TriadCard[] testDeckCards = new TriadCard[] { commonList[IdxC1], commonList[IdxC2], commonList[IdxC3], commonList[IdxC4], commonList[IdxC5] };
                                            Random randomGen          = GetRandomStream(IdxC1, IdxC2, IdxC3, IdxC4, IdxC5);

                                            if (bIsOrderImportant && bAllowPermutationChecks)
                                            {
                                                for (int IdxP = 0; IdxP < permutationList.Length; IdxP++)
                                                {
                                                    int[] UseOrder            = permutationList[IdxP];
                                                    TriadCard[] permDeckCards = new TriadCard[] { testDeckCards[UseOrder[0]], testDeckCards[UseOrder[1]], testDeckCards[UseOrder[2]], testDeckCards[UseOrder[3]], testDeckCards[UseOrder[4]] };
                                                    TriadDeck permDeck        = new TriadDeck(permDeckCards);
                                                    int testScore             = GetDeckScore(solver, permDeck, randomGen, 10);
                                                    if (testScore > bestScore)
                                                    {
                                                        lock (lockOb)
                                                        {
                                                            bestScore = testScore;
                                                            bestDeck  = permDeck;
                                                            OnFoundDeck.Invoke(permDeck);
                                                        }
                                                    }
                                                }
                                            }

                                            {
                                                TriadDeck testDeck = new TriadDeck(testDeckCards);
                                                int testScore      = GetDeckScore(solver, testDeck, randomGen, 1);
                                                if (testScore > bestScore)
                                                {
                                                    lock (lockOb)
                                                    {
                                                        bestScore = testScore;
                                                        bestDeck  = testDeck;
                                                        OnFoundDeck.Invoke(testDeck);
                                                    }
                                                }
                                            }

                                            lock (lockOb)
                                            {
                                                numTestedDecks++;
                                                if (bAbort)
                                                {
                                                    IdxC2 = commonList.Count;
                                                    IdxC3 = commonList.Count;
                                                    IdxC4 = commonList.Count;
                                                    IdxC5 = commonList.Count;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    });
                }
                else
                {
                    Logger.WriteLine("Unexpected slot setup: " + string.Join(", ", cardSlots) + ", bailing out");
                }
            }

            stopwatch.Stop();
            Logger.WriteLine("Building list of decks: " + stopwatch.ElapsedMilliseconds + "ms, num:" + numPossibleDecks);
            optimizedDeck = bestDeck;
        }
Example #9
0
        private void FindDecks(TriadGameModifier[] regionMods)
        {
            PlayerSettingsDB playerDB = PlayerSettingsDB.Get();
            //TriadCardDB playerDB = TriadCardDB.Get();

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            ETriadCardRarity RarityLimitThr =
                (playerDB.ownedCards.Count < 30) ? ETriadCardRarity.Uncommon :
                (playerDB.ownedCards.Count < 60) ? ETriadCardRarity.Rare :
                ETriadCardRarity.Epic;

            TriadGameSession solver = new TriadGameSession();

            solver.modifiers.AddRange(npc.Rules);
            solver.modifiers.AddRange(regionMods);
            solver.UpdateSpecialRules();

            bool bIsOrderImportant = false;

            foreach (TriadGameModifier mod in solver.modifiers)
            {
                bIsOrderImportant = bIsOrderImportant || mod.IsDeckOrderImportant();
            }

            object    lockOb    = new object();
            int       bestScore = 0;
            TriadDeck bestDeck  = new TriadDeck(PlayerSettingsDB.Get().starterCards);

            Parallel.For(1, playerDB.ownedCards.Count, Idx1 =>
            {
                Parallel.For(Idx1 + 1, playerDB.ownedCards.Count, Idx2 =>
                {
                    int rareCounterLv2 =
                        ((playerDB.ownedCards[Idx1].Rarity >= RarityLimitThr) ? 1 : 0) +
                        ((playerDB.ownedCards[Idx2].Rarity >= RarityLimitThr) ? 1 : 0);
                    if (rareCounterLv2 <= 1)
                    {
                        Parallel.For(Idx2 + 1, playerDB.ownedCards.Count, Idx3 =>
                        {
                            int rareCounterLv3 =
                                ((playerDB.ownedCards[Idx1].Rarity >= RarityLimitThr) ? 1 : 0) +
                                ((playerDB.ownedCards[Idx2].Rarity >= RarityLimitThr) ? 1 : 0) +
                                ((playerDB.ownedCards[Idx3].Rarity >= RarityLimitThr) ? 1 : 0);

                            if (rareCounterLv3 <= 1)
                            {
                                Parallel.For(Idx3 + 1, playerDB.ownedCards.Count, Idx4 =>
                                {
                                    int rareCounterLv4 =
                                        ((playerDB.ownedCards[Idx1].Rarity >= RarityLimitThr) ? 1 : 0) +
                                        ((playerDB.ownedCards[Idx2].Rarity >= RarityLimitThr) ? 1 : 0) +
                                        ((playerDB.ownedCards[Idx3].Rarity >= RarityLimitThr) ? 1 : 0) +
                                        ((playerDB.ownedCards[Idx4].Rarity >= RarityLimitThr) ? 1 : 0);
                                    if (rareCounterLv4 <= 1)
                                    {
                                        for (int Idx5 = Idx4 + 1; Idx5 < playerDB.ownedCards.Count; Idx5++)
                                        {
                                            int rareCounterLv5 = rareCounterLv4 +
                                                                 ((playerDB.ownedCards[Idx5].Rarity >= RarityLimitThr) ? 1 : 0);
                                            if (rareCounterLv5 <= 1)
                                            {
                                                TriadCard[] testDeckCards = new TriadCard[] { playerDB.ownedCards[Idx1], playerDB.ownedCards[Idx2], playerDB.ownedCards[Idx3], playerDB.ownedCards[Idx4], playerDB.ownedCards[Idx5] };
                                                Random randomGen          = GetRandomStream(Idx1, Idx2, Idx3, Idx4, Idx5);

                                                if (bIsOrderImportant)
                                                {
                                                    if (bAllowPermutationChecks)
                                                    {
                                                        for (int IdxP = 0; IdxP < permutationList.Length; IdxP++)
                                                        {
                                                            int[] UseOrder     = permutationList[IdxP];
                                                            TriadDeck permDeck = new TriadDeck(new TriadCard[] { testDeckCards[UseOrder[0]], testDeckCards[UseOrder[1]], testDeckCards[UseOrder[2]], testDeckCards[UseOrder[3]], testDeckCards[UseOrder[4]] });

                                                            int testScore = GetDeckScore(solver, permDeck, randomGen, 10);
                                                            if (testScore > bestScore)
                                                            {
                                                                lock (lockOb)
                                                                {
                                                                    bestScore = testScore;
                                                                    bestDeck  = permDeck;
                                                                }
                                                            }
                                                        }
                                                    }
                                                    else
                                                    {
                                                        int fixedRareSlot = 2;
                                                        for (int TestSlotIdx = 0; TestSlotIdx < testDeckCards.Length; TestSlotIdx++)
                                                        {
                                                            if (testDeckCards[TestSlotIdx].Rarity > testDeckCards[fixedRareSlot].Rarity)
                                                            {
                                                                TriadCard swapOb             = testDeckCards[TestSlotIdx];
                                                                testDeckCards[TestSlotIdx]   = testDeckCards[fixedRareSlot];
                                                                testDeckCards[fixedRareSlot] = swapOb;
                                                            }
                                                        }
                                                    }
                                                }

                                                {
                                                    TriadDeck testDeck = new TriadDeck(testDeckCards);
                                                    int testScore      = GetDeckScore(solver, testDeck, randomGen, 1);
                                                    if (testScore > bestScore)
                                                    {
                                                        lock (lockOb)
                                                        {
                                                            bestScore = testScore;
                                                            bestDeck  = testDeck;
                                                        }
                                                    }
                                                }
                                            }

                                            numTestedDecks++;
                                        }
                                    }
                                    else
                                    {
                                        numTestedDecks += playerDB.ownedCards.Count - Idx4;
                                    }
                                });
                            }
                            else
                            {
                                numTestedDecks += (playerDB.ownedCards.Count - Idx3) * (playerDB.ownedCards.Count - Idx3 - 1);
                            }
                        });
                    }
                    else
                    {
                        numTestedDecks += (playerDB.ownedCards.Count - Idx2) * (playerDB.ownedCards.Count - Idx2 - 1) * (playerDB.ownedCards.Count - Idx2 - 2);
                    }
                });
            });

            stopwatch.Stop();
            Logger.WriteLine("Building list of decks: " + stopwatch.ElapsedMilliseconds + "ms, num:" + numPossibleDecks);
            optimizedDeck = bestDeck;
        }
Example #10
0
        private void FindCardsToUse(List <TriadCard> allCards, List <TriadGameModifier> modifiers, List <TriadCard> rareList, List <TriadCard> commonList)
        {
            ETriadCardRarity     limitedRarity    = GetRareThreshold(allCards);
            List <CardScoreData> rareScoredList   = new List <CardScoreData>();
            List <CardScoreData> commonScoredList = new List <CardScoreData>();

            foreach (TriadCard card in allCards)
            {
                if (card == null || !card.IsValid())
                {
                    continue;
                }

                // try to guess how good card will perform
                // - avg of sides
                // - std of sides
                // - rarity (should be reflected by sides already)
                // - corners with same number
                // - max corner number

                int   numberSum        = card.Sides[0] + card.Sides[1] + card.Sides[2] + card.Sides[3];
                float numberAvg        = numberSum / 4.0f;
                float numberMeanSqDiff =
                    ((card.Sides[0] - numberAvg) * (card.Sides[0] - numberAvg)) +
                    ((card.Sides[1] - numberAvg) * (card.Sides[1] - numberAvg)) +
                    ((card.Sides[2] - numberAvg) * (card.Sides[2] - numberAvg)) +
                    ((card.Sides[3] - numberAvg) * (card.Sides[3] - numberAvg));
                float numberStd = (float)Math.Sqrt(numberMeanSqDiff / 4);

                int cornerNum  = 0;
                int numCorners = 0;
                if (card.Sides[0] == card.Sides[1])
                {
                    numCorners++; cornerNum = Math.Max(cornerNum, card.Sides[0]);
                }
                if (card.Sides[1] == card.Sides[2])
                {
                    numCorners++; cornerNum = Math.Max(cornerNum, card.Sides[1]);
                }
                if (card.Sides[2] == card.Sides[3])
                {
                    numCorners++; cornerNum = Math.Max(cornerNum, card.Sides[2]);
                }
                if (card.Sides[3] == card.Sides[0])
                {
                    numCorners++; cornerNum = Math.Max(cornerNum, card.Sides[3]);
                }

                float cardScore =
                    (numberAvg * scoreAvgSides) +
                    (numberStd * scoreStdSides) +
                    (numCorners * scoreSameCorners) +
                    (cornerNum * scoreMaxCorner) +
                    ((int)card.Rarity * scoreRarity);

                foreach (TriadGameModifier mod in modifiers)
                {
                    mod.OnScoreCard(card, ref cardScore);
                }

                if (card.Rarity >= limitedRarity)
                {
                    rareScoredList.Add(new CardScoreData(card, cardScore));
                }
                else
                {
                    commonScoredList.Add(new CardScoreData(card, cardScore));
                }
            }

            // special case: don't include any rare slots with reverse rule if there's enough cards in common list
            bool shouldRemoveRares = false;

            foreach (TriadGameModifier mod in modifiers)
            {
                if (mod.GetType() == typeof(TriadGameModifierReverse))
                {
                    shouldRemoveRares = (commonScoredList.Count >= 5);
                    break;
                }
            }

            commonScoredList.Sort();
            rareScoredList.Sort();

            int maxCommonToCopy = Math.Min(shouldRemoveRares ? (numCommonToBuild + numRareToBuild) : numCommonToBuild, commonScoredList.Count);

            for (int Idx = 0; Idx < maxCommonToCopy; Idx++)
            {
                commonList.Add(commonScoredList[Idx].card);
            }

            int maxRareToCopy = Math.Min(shouldRemoveRares ? 0 : numRareToBuild, rareScoredList.Count);

            for (int Idx = 0; Idx < maxRareToCopy; Idx++)
            {
                rareList.Add(rareScoredList[Idx].card);
            }
        }
Example #11
0
        public bool Load()
        {
            List <TriadCard> loadedCards = new List <TriadCard>();
            int maxLoadedId = 0;

            try
            {
                XmlDocument xdoc       = new XmlDocument();
                Stream      dataStream = AssetManager.Get().GetAsset(DBPath);
                xdoc.Load(dataStream);

                foreach (XmlNode cardNode in xdoc.DocumentElement.ChildNodes)
                {
                    XmlElement cardElem = (XmlElement)cardNode;
                    if (cardElem != null && cardElem.Name == "card")
                    {
                        try
                        {
                            ETriadCardRarity cardRarity = ETriadCardRarity.Common;
                            ETriadCardType   cardType   = ETriadCardType.None;
                            bool             bHasRarity = TryParseCardRarity(cardElem.GetAttribute("rarity"), out cardRarity);
                            bool             bHasType   = TryParseCardType(cardElem.GetAttribute("type"), out cardType);

                            if (bHasType && bHasRarity)
                            {
                                TriadCard newCard = new TriadCard(
                                    int.Parse(cardElem.GetAttribute("id")),
                                    WebUtility.HtmlDecode(cardElem.GetAttribute("name")),
                                    cardElem.GetAttribute("icon"),
                                    cardRarity,
                                    cardType,
                                    ParseCardSideNum(cardElem.GetAttribute("up")),
                                    ParseCardSideNum(cardElem.GetAttribute("dn")),
                                    ParseCardSideNum(cardElem.GetAttribute("lt")),
                                    ParseCardSideNum(cardElem.GetAttribute("rt")),
                                    int.Parse(cardElem.GetAttribute("sort")));

                                if (newCard.IsValid())
                                {
                                    loadedCards.Add(newCard);
                                    maxLoadedId = Math.Max(maxLoadedId, newCard.Id);
                                }
                                else
                                {
                                    Logger.WriteLine("Loading failed! ob[" + newCard + "], xml:" + cardElem.OuterXml);
                                }
                            }
                            else
                            {
                                Logger.WriteLine("Loading failed! xml:" + cardElem.OuterXml);
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.WriteLine("Loading failed! Exception:" + ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLine("Loading failed! Exception:" + ex);
            }

            if (loadedCards.Count > 0)
            {
                while (cards.Count < (maxLoadedId + 1))
                {
                    cards.Add(null);
                }

                foreach (TriadCard card in loadedCards)
                {
                    cards[card.Id] = card;
                }
            }

            sameNumberMap.Clear();
            int sameNumberId = 0;

            for (int Idx1 = 0; Idx1 < cards.Count; Idx1++)
            {
                TriadCard card1 = cards[Idx1];
                if (card1 != null && card1.SameNumberId < 0)
                {
                    bool bHasSameNumberCards = false;
                    for (int Idx2 = (Idx1 + 1); Idx2 < cards.Count; Idx2++)
                    {
                        TriadCard card2 = cards[Idx2];
                        if (card2 != null && card2.SameNumberId < 0)
                        {
                            bool bHasSameNumbers =
                                (card1.Sides[0] == card2.Sides[0]) &&
                                (card1.Sides[1] == card2.Sides[1]) &&
                                (card1.Sides[2] == card2.Sides[2]) &&
                                (card1.Sides[3] == card2.Sides[3]);

                            bHasSameNumberCards = bHasSameNumberCards || bHasSameNumbers;
                            if (bHasSameNumbers)
                            {
                                if (!sameNumberMap.ContainsKey(sameNumberId))
                                {
                                    sameNumberMap.Add(sameNumberId, new List <TriadCard>());
                                    sameNumberMap[sameNumberId].Add(card1);
                                    card1.SameNumberId = sameNumberId;
                                }

                                sameNumberMap[sameNumberId].Add(card2);
                                card2.SameNumberId = sameNumberId;
                            }
                        }
                    }

                    if (bHasSameNumberCards)
                    {
                        sameNumberId++;
                    }
                }
            }

            Logger.WriteLine("Loaded cards: " + loadedCards.Count + ", same sides: " + sameNumberMap.Count);
            return(loadedCards.Count > 0);
        }
        public TriadDeckOptimizer()
        {
            numGamesToPlay               = 2000;
            numPriorityToBuild           = 10;
            numCommonToBuild             = 20;
            numCommonPctToDropPerPriSlot = 10;

            maxSlotsPerRarity = new Dictionary <ETriadCardRarity, int>();
            maxSlotsPerRarity.Add(ETriadCardRarity.Legendary, 1);
            maxSlotsPerRarity.Add(ETriadCardRarity.Epic, 2);
            commonRarity = ETriadCardRarity.Rare;

            debugMode = false;
            bAbort    = false;
#if DEBUG
            debugMode = true;
#endif // DEBUG

            scoreAvgSides    = 1.0f;
            scoreStdSides    = 0.0f;
            scoreMaxSides    = 0.1f;
            scoreSameCorners = 0.0f;
            scoreMaxCorner   = 0.0f;
            scoreRarity      = 1.0f;

            // generate lookup for permutations used when deck order is important
            // num entries = 5! = 120
            permutationList = new int[120][];
            int ListIdx = 0;
            for (int IdxP0 = 0; IdxP0 < 5; IdxP0++)
            {
                for (int IdxP1 = 0; IdxP1 < 5; IdxP1++)
                {
                    if (IdxP1 == IdxP0)
                    {
                        continue;
                    }
                    for (int IdxP2 = 0; IdxP2 < 5; IdxP2++)
                    {
                        if (IdxP2 == IdxP0 || IdxP2 == IdxP1)
                        {
                            continue;
                        }
                        for (int IdxP3 = 0; IdxP3 < 5; IdxP3++)
                        {
                            if (IdxP3 == IdxP0 || IdxP3 == IdxP1 || IdxP3 == IdxP2)
                            {
                                continue;
                            }
                            for (int IdxP4 = 0; IdxP4 < 5; IdxP4++)
                            {
                                if (IdxP4 == IdxP0 || IdxP4 == IdxP1 || IdxP4 == IdxP2 || IdxP4 == IdxP3)
                                {
                                    continue;
                                }

                                permutationList[ListIdx] = new int[5] {
                                    IdxP0, IdxP1, IdxP2, IdxP3, IdxP4
                                };
                                ListIdx++;
                            }
                        }
                    }
                }
            }

            // temporary, set initial rule set
            OnLanguageChanged();
        }
        private bool FindCardPool(List <TriadCard> allCards, List <TriadGameModifier> modifiers, List <TriadCard> lockedCards)
        {
            currentPool = new CardPool();

            int maxRarityNum = Enum.GetValues(typeof(ETriadCardRarity)).Length;
            int priRarityNum = (int)commonRarity + 1;

            int[] mapAvailRarity = new int[maxRarityNum];

            // special case: don't include any rare slots with reverse rule if there's enough cards in common list
            bool hasReverseMod   = false;
            bool hasAscensionMod = false;

            foreach (TriadGameModifier mod in modifiers)
            {
                if (mod.GetType() == typeof(TriadGameModifierReverse))
                {
                    hasReverseMod = true;
                }
                else if (mod.GetType() == typeof(TriadGameModifierAscention))
                {
                    hasAscensionMod = true;
                }
            }

            // find number of priority lists based on unique rarity limits
            List <ETriadCardRarity> priRarityThr = new List <ETriadCardRarity>();

            for (int idxR = priRarityNum; idxR < maxRarityNum; idxR++)
            {
                ETriadCardRarity testRarity = (ETriadCardRarity)idxR;
                if (!hasReverseMod && maxSlotsPerRarity.ContainsKey(testRarity) && maxSlotsPerRarity[testRarity] > 0)
                {
                    mapAvailRarity[idxR]      = maxSlotsPerRarity[testRarity];
                    mapAvailRarity[idxR - 1] -= maxSlotsPerRarity[testRarity];

                    priRarityThr.Add(testRarity);
                }
            }

            if (debugMode)
            {
                Logger.WriteLine("FindCardPool> priRarityThr:{0}, maxAvail:[{1},{2},{3},{4},{5}], reverse:{6}, ascention:{7}", priRarityThr.Count,
                                 mapAvailRarity[0], mapAvailRarity[1], mapAvailRarity[2], mapAvailRarity[3], mapAvailRarity[4],
                                 hasReverseMod, hasAscensionMod);
            }

            // check rarity of locked cards, eliminate pri list when threshold is matched
            // when multiple pri rarities are locked, start eliminating from pool above
            // e.g. 2x 4 star locked => 4 star out, 5 star out
            currentPool.deckSlotTypes = new int[lockedCards.Count];
            int numLockedCards = 0;

            for (int idx = 0; idx < lockedCards.Count; idx++)
            {
                TriadCard card = lockedCards[idx];
                if (card != null)
                {
                    if (card.Rarity > commonRarity)
                    {
                        for (int testR = (int)card.Rarity; testR <= maxRarityNum; testR++)
                        {
                            if (mapAvailRarity[testR] > 0)
                            {
                                mapAvailRarity[testR]--;
                                break;
                            }
                        }
                    }

                    currentPool.deckSlotTypes[idx] = DeckSlotLocked;
                    numLockedCards++;
                }
                else
                {
                    currentPool.deckSlotTypes[idx] = DeckSlotCommon;
                }
            }

            if (debugMode)
            {
                Logger.WriteLine(">> adjusted for locking, numLocked:{0}, maxAvail:[{1},{2},{3},{4},{5}]", numLockedCards, mapAvailRarity[0], mapAvailRarity[1], mapAvailRarity[2], mapAvailRarity[3], mapAvailRarity[4]);
            }
            if (numLockedCards == lockedCards.Count)
            {
                return(false);
            }

            List <CardScoreData>         commonScoredList = new List <CardScoreData>();
            List <List <CardScoreData> > priScoredList    = new List <List <CardScoreData> >();

            for (int idxP = 0; idxP < priRarityThr.Count; idxP++)
            {
                priScoredList.Add(new List <CardScoreData>());
            }

            // reverse priority thresholds, idx:0 becomes strongest card
            priRarityThr.Reverse();

            // assign each owned card to scored lists
            foreach (TriadCard card in allCards)
            {
                if (card == null || !card.IsValid())
                {
                    continue;
                }

                // try to guess how good card will perform
                // - avg of sides
                // - std of sides
                // - max of sides
                // - rarity (should be reflected by sides already)
                // - corners with same number
                // - max corner number

                int   numberMax        = Math.Max(Math.Max(card.Sides[0], card.Sides[1]), Math.Max(card.Sides[2], card.Sides[3]));
                int   numberSum        = card.Sides[0] + card.Sides[1] + card.Sides[2] + card.Sides[3];
                float numberAvg        = numberSum / 4.0f;
                float numberMeanSqDiff =
                    ((card.Sides[0] - numberAvg) * (card.Sides[0] - numberAvg)) +
                    ((card.Sides[1] - numberAvg) * (card.Sides[1] - numberAvg)) +
                    ((card.Sides[2] - numberAvg) * (card.Sides[2] - numberAvg)) +
                    ((card.Sides[3] - numberAvg) * (card.Sides[3] - numberAvg));
                float numberStd = (float)Math.Sqrt(numberMeanSqDiff / 4);

                int cornerNum  = 0;
                int numCorners = 0;
                if (card.Sides[0] == card.Sides[1])
                {
                    numCorners++; cornerNum = Math.Max(cornerNum, card.Sides[0]);
                }
                if (card.Sides[1] == card.Sides[2])
                {
                    numCorners++; cornerNum = Math.Max(cornerNum, card.Sides[1]);
                }
                if (card.Sides[2] == card.Sides[3])
                {
                    numCorners++; cornerNum = Math.Max(cornerNum, card.Sides[2]);
                }
                if (card.Sides[3] == card.Sides[0])
                {
                    numCorners++; cornerNum = Math.Max(cornerNum, card.Sides[3]);
                }

                CardScoreData scoredCard = new CardScoreData()
                {
                    card = card
                };
                scoredCard.score =
                    (numberAvg * scoreAvgSides) +
                    (numberStd * scoreStdSides) +
                    (numberMax * scoreMaxSides) +
                    (numCorners * scoreSameCorners) +
                    (cornerNum * scoreMaxCorner) +
                    ((int)card.Rarity * scoreRarity);

                foreach (TriadGameModifier mod in modifiers)
                {
                    mod.OnScoreCard(card, ref scoredCard.score);
                }

                for (int idxP = 0; idxP < priRarityThr.Count; idxP++)
                {
                    if (card.Rarity <= priRarityThr[idxP])
                    {
                        priScoredList[idxP].Add(scoredCard);
                    }
                }

                if (card.Rarity <= commonRarity)
                {
                    commonScoredList.Add(scoredCard);
                }
            }

            if (debugMode)
            {
                Logger.WriteLine(">> card lists sorted, common:{0}", commonScoredList.Count);
            }
            bool isPoolValid = (commonScoredList.Count > 0);

            if (isPoolValid)
            {
                int numPriLists = 0;
                int deckSlotIdx = isOrderImportant ? 1 : 0;

                for (int idx = 0; idx < priScoredList.Count; idx++)
                {
                    int numAvail = mapAvailRarity[(int)priRarityThr[idx]];
                    if (debugMode)
                    {
                        Logger.WriteLine("  pri list[{0}]:{1}, rarity:{2}, avail:{3}", idx, priScoredList[idx].Count, priRarityThr[idx], numAvail);
                    }
                    if ((numAvail > 0) && (priScoredList[idx].Count > 0))
                    {
                        // initial deckSlotIdx should be already past only available spot (e.g. all slots but [0] are locked), make sure to wrap around
                        // find fist available Common slot to overwrite with priority list, repeat numAvail times
                        for (int idxAvail = 0; idxAvail < numAvail; idxAvail++)
                        {
                            for (int idxD = 0; idxD < currentPool.deckSlotTypes.Length; idxD++)
                            {
                                if (currentPool.deckSlotTypes[deckSlotIdx] == DeckSlotCommon)
                                {
                                    break;
                                }

                                deckSlotIdx++;
                            }

                            currentPool.deckSlotTypes[deckSlotIdx] = numPriLists;
                        }

                        numPriLists++;
                    }
                    else
                    {
                        priScoredList[idx].Clear();
                    }
                }

                // ascension modifier special case: same type across all pools is best
                // aply after priority lists were trimmed
                if (hasAscensionMod)
                {
                    ApplyAscentionFilter(commonScoredList, priScoredList);
                }

                if (numPriLists > 0)
                {
                    currentPool.priorityLists = new TriadCard[numPriLists][];
                    if (debugMode)
                    {
                        Logger.WriteLine(">> num priority lists:{0}", numPriLists);
                    }

                    int idxP = 0;
                    for (int idxL = 0; idxL < priScoredList.Count; idxL++)
                    {
                        int maxPriorityToUse = Math.Min(numPriorityToBuild, priScoredList[idxL].Count);
                        if (maxPriorityToUse > 0)
                        {
                            currentPool.priorityLists[idxP] = new TriadCard[maxPriorityToUse];
                            priScoredList[idxL].Sort();

                            for (int idxC = 0; idxC < maxPriorityToUse; idxC++)
                            {
                                currentPool.priorityLists[idxP][idxC] = priScoredList[idxL][idxC].card;
                            }

                            idxP++;
                        }
                    }
                }

                // adjust pool of common cards based on avail common slots
                // - all common: use requested size
                // - scale down 20% per every priority list slot
                int numPriSlots = 0;
                for (int idx = 0; idx < currentPool.deckSlotTypes.Length; idx++)
                {
                    numPriSlots += (currentPool.deckSlotTypes[idx] >= 0) ? 1 : 0;
                }

                int maxCommonToUse = Math.Min(numCommonToBuild - (numCommonToBuild * numPriSlots * numCommonPctToDropPerPriSlot / 100), commonScoredList.Count);
                if (debugMode)
                {
                    Logger.WriteLine(">> adjusting common pool based on priSlots:{0} and drop:{1}% => {2}", numPriSlots, numCommonPctToDropPerPriSlot, maxCommonToUse);
                }

                currentPool.commonList = new TriadCard[maxCommonToUse];
                commonScoredList.Sort();

                for (int idx = 0; idx < currentPool.commonList.Length; idx++)
                {
                    currentPool.commonList[idx] = commonScoredList[idx].card;
                }
            }

            if (debugMode)
            {
                Logger.WriteLine(">> deck slot types:[{0}, {1}, {2}, {3}, {4}]", currentPool.deckSlotTypes[0], currentPool.deckSlotTypes[1], currentPool.deckSlotTypes[2], currentPool.deckSlotTypes[3], currentPool.deckSlotTypes[4]);
            }
            return(isPoolValid);
        }
Example #14
0
        private void FindDecksScored(TriadGameModifier[] regionMods, List <TriadCard> lockedCards)
        {
            PlayerSettingsDB playerDB = PlayerSettingsDB.Get();
            //TriadCardDB playerDB = TriadCardDB.Get();

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            TriadGameSession solver = new TriadGameSession();

            solver.modifiers.AddRange(npc.Rules);
            solver.modifiers.AddRange(regionMods);
            solver.UpdateSpecialRules();

            bool bIsOrderImportant = false;

            foreach (TriadGameModifier mod in solver.modifiers)
            {
                bIsOrderImportant = bIsOrderImportant || mod.IsDeckOrderImportant();
            }

            List <TriadCard> rareList   = new List <TriadCard>();
            List <TriadCard> commonList = new List <TriadCard>();

            FindCardsToUse(playerDB.ownedCards, solver.modifiers, rareList, commonList);

            ETriadCardRarity rareThreshold = GetRareThreshold(playerDB.ownedCards);

            ECardSlotState[] cardSlots = BuildCardSlots(lockedCards, rareList.Count, commonList.Count, rareThreshold, bIsOrderImportant);

            object    lockOb    = new object();
            int       bestScore = 0;
            TriadDeck bestDeck  = new TriadDeck(PlayerSettingsDB.Get().starterCards);

            List <TriadCard>[] slotLists = new List <TriadCard> [cardSlots.Length];
            int numLocked = 0;

            for (int Idx = 0; Idx < slotLists.Length; Idx++)
            {
                switch (cardSlots[Idx])
                {
                case ECardSlotState.Common: slotLists[Idx] = commonList; break;

                case ECardSlotState.Rare: slotLists[Idx] = rareList; break;

                default:
                    slotLists[Idx] = new List <TriadCard>()
                    {
                        lockedCards[Idx]
                    };
                    numLocked++;
                    break;
                }
            }

            if (numLocked > 0)
            {
                // slower when ran for all 5 slots
                UpdatePossibleDeckCount(rareList.Count, commonList.Count, cardSlots, bIsOrderImportant);

                //for (int IdxS0 = 0; IdxS0 < slotLists[0].Count; IdxS0++)
                Parallel.For(0, slotLists[0].Count, IdxS0 =>
                {
                    if (!bAbort)
                    {
                        //for (int IdxS1 = 0; IdxS1 < slotLists[1].Count; IdxS1++)
                        Parallel.For(0, slotLists[1].Count, IdxS1 =>
                        {
                            if (!bAbort)
                            {
                                //for (int IdxS2 = 0; IdxS2 < slotLists[2].Count; IdxS2++)
                                Parallel.For(0, slotLists[2].Count, IdxS2 =>
                                {
                                    if (!bAbort)
                                    {
                                        //for (int IdxS3 = 0; IdxS3 < slotLists[3].Count; IdxS3++)
                                        Parallel.For(0, slotLists[3].Count, IdxS3 =>
                                        {
                                            if (!bAbort)
                                            {
                                                //for (int IdxS4 = 0; IdxS4 < slotLists[4].Count; IdxS4++)
                                                Parallel.For(0, slotLists[4].Count, IdxS4 =>
                                                {
                                                    if (!bAbort)
                                                    {
                                                        TriadCard[] testDeckCards = new TriadCard[] { slotLists[0][IdxS0], slotLists[1][IdxS1], slotLists[2][IdxS2], slotLists[3][IdxS3], slotLists[4][IdxS4] };
                                                        if (testDeckCards[0] != testDeckCards[1] &&
                                                            testDeckCards[0] != testDeckCards[2] &&
                                                            testDeckCards[0] != testDeckCards[3] &&
                                                            testDeckCards[0] != testDeckCards[4] &&
                                                            testDeckCards[1] != testDeckCards[2] &&
                                                            testDeckCards[1] != testDeckCards[3] &&
                                                            testDeckCards[1] != testDeckCards[4] &&
                                                            testDeckCards[2] != testDeckCards[3] &&
                                                            testDeckCards[2] != testDeckCards[4] &&
                                                            testDeckCards[3] != testDeckCards[4])
                                                        {
                                                            Random randomGen = GetRandomStream(IdxS0, IdxS1, IdxS2, IdxS3, IdxS4);
                                                            // TODO: custom permutation lookup
                                                            {
                                                                TriadDeck testDeck = new TriadDeck(testDeckCards);
                                                                int testScore      = GetDeckScore(solver, testDeck, randomGen, 1);
                                                                if (testScore > bestScore)
                                                                {
                                                                    lock (lockOb)
                                                                    {
                                                                        bestScore = testScore;
                                                                        bestDeck  = testDeck;
                                                                        OnFoundDeck.Invoke(testDeck);
                                                                    }
                                                                }
                                                            }
                                                        }

                                                        lock (lockOb)
                                                        {
                                                            numTestedDecks++;
                                                        }
                                                    }
                                                });
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }
                });
            }
            else
            {
                // faster loops when nothing is locked
                UpdatePossibleDeckCount(rareList.Count, commonList.Count, lockedCards, bIsOrderImportant);

                Parallel.For(0, rareList.Count, IdxR0 =>
                {
                    if (!bAbort)
                    {
                        Parallel.For(0, commonList.Count, IdxC1 =>
                        {
                            if (!bAbort)
                            {
                                for (int IdxC2 = IdxC1 + 1; IdxC2 < commonList.Count; IdxC2++)
                                {
                                    for (int IdxC3 = IdxC2 + 1; IdxC3 < commonList.Count; IdxC3++)
                                    {
                                        for (int IdxC4 = IdxC3 + 1; IdxC4 < commonList.Count; IdxC4++)
                                        {
                                            TriadCard[] testDeckCards = new TriadCard[] { rareList[IdxR0], commonList[IdxC1], commonList[IdxC2], commonList[IdxC3], commonList[IdxC4] };
                                            Random randomGen          = GetRandomStream(IdxR0, IdxC1, IdxC2, IdxC3, IdxC4);

                                            if (bIsOrderImportant)
                                            {
                                                if (bAllowPermutationChecks)
                                                {
                                                    for (int IdxP = 0; IdxP < permutationList.Length; IdxP++)
                                                    {
                                                        int[] UseOrder            = permutationList[IdxP];
                                                        TriadCard[] permDeckCards = new TriadCard[] { testDeckCards[UseOrder[0]], testDeckCards[UseOrder[1]], testDeckCards[UseOrder[2]], testDeckCards[UseOrder[3]], testDeckCards[UseOrder[4]] };
                                                        TriadDeck permDeck        = new TriadDeck(permDeckCards);
                                                        int testScore             = GetDeckScore(solver, permDeck, randomGen, 10);
                                                        if (testScore > bestScore)
                                                        {
                                                            lock (lockOb)
                                                            {
                                                                bestScore = testScore;
                                                                bestDeck  = permDeck;
                                                                OnFoundDeck.Invoke(permDeck);
                                                            }
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    testDeckCards = new TriadCard[] { commonList[IdxC1], rareList[IdxR0], commonList[IdxC2], commonList[IdxC3], commonList[IdxC4] };
                                                }
                                            }

                                            {
                                                TriadDeck testDeck = new TriadDeck(testDeckCards);
                                                int testScore      = GetDeckScore(solver, testDeck, randomGen, 1);
                                                if (testScore > bestScore)
                                                {
                                                    lock (lockOb)
                                                    {
                                                        bestScore = testScore;
                                                        bestDeck  = testDeck;
                                                        OnFoundDeck.Invoke(testDeck);
                                                    }
                                                }
                                            }

                                            lock (lockOb)
                                            {
                                                numTestedDecks++;
                                                if (bAbort)
                                                {
                                                    IdxC2 = commonList.Count;
                                                    IdxC3 = commonList.Count;
                                                    IdxC4 = commonList.Count;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        });
                    }
                });
            }

            stopwatch.Stop();
            Logger.WriteLine("Building list of decks: " + stopwatch.ElapsedMilliseconds + "ms, num:" + numPossibleDecks);
            optimizedDeck = bestDeck;
        }
Example #15
0
        public bool Load()
        {
            try
            {
                XmlDocument xdoc       = new XmlDocument();
                Stream      dataStream = AssetManager.Get().GetAsset(DBPath);
                xdoc.Load(dataStream);

                foreach (XmlNode cardNode in xdoc.DocumentElement.ChildNodes)
                {
                    XmlElement cardElem = (XmlElement)cardNode;
                    if (cardElem != null && cardElem.Name == "card")
                    {
                        try
                        {
                            ETriadCardRarity cardRarity = (ETriadCardRarity)int.Parse(cardElem.GetAttribute("rarity"));
                            ETriadCardType   cardType   = (ETriadCardType)int.Parse(cardElem.GetAttribute("type"));
                            int sortOrder = int.Parse(cardElem.GetAttribute("sort"));
                            int cardGroup = int.Parse(cardElem.GetAttribute("group"));

                            TriadCard newCard = new TriadCard(
                                int.Parse(cardElem.GetAttribute("id")),
                                cardElem.GetAttribute("icon"),
                                cardRarity,
                                cardType,
                                ParseCardSideNum(cardElem.GetAttribute("up")),
                                ParseCardSideNum(cardElem.GetAttribute("dn")),
                                ParseCardSideNum(cardElem.GetAttribute("lt")),
                                ParseCardSideNum(cardElem.GetAttribute("rt")),
                                sortOrder,
                                cardGroup);

                            while (cards.Count <= newCard.Id)
                            {
                                cards.Add(null);
                            }

                            cards[newCard.Id] = newCard;
                        }
                        catch (Exception ex)
                        {
                            Logger.WriteLine("Loading failed! Exception:" + ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLine("Loading failed! Exception:" + ex);
            }

            sameNumberMap.Clear();
            int sameNumberId = 0;

            for (int Idx1 = 0; Idx1 < cards.Count; Idx1++)
            {
                TriadCard card1 = cards[Idx1];
                if (card1 != null && card1.SameNumberId < 0)
                {
                    bool bHasSameNumberCards = false;
                    for (int Idx2 = (Idx1 + 1); Idx2 < cards.Count; Idx2++)
                    {
                        TriadCard card2 = cards[Idx2];
                        if (card2 != null && card2.SameNumberId < 0)
                        {
                            bool bHasSameNumbers =
                                (card1.Sides[0] == card2.Sides[0]) &&
                                (card1.Sides[1] == card2.Sides[1]) &&
                                (card1.Sides[2] == card2.Sides[2]) &&
                                (card1.Sides[3] == card2.Sides[3]);

                            bHasSameNumberCards = bHasSameNumberCards || bHasSameNumbers;
                            if (bHasSameNumbers)
                            {
                                if (!sameNumberMap.ContainsKey(sameNumberId))
                                {
                                    sameNumberMap.Add(sameNumberId, new List <TriadCard>());
                                    sameNumberMap[sameNumberId].Add(card1);
                                    card1.SameNumberId = sameNumberId;
                                }

                                sameNumberMap[sameNumberId].Add(card2);
                                card2.SameNumberId = sameNumberId;
                            }
                        }
                    }

                    if (bHasSameNumberCards)
                    {
                        sameNumberId++;
                    }
                }
            }

            Logger.WriteLine("Loaded cards: " + cards.Count + ", same sides: " + sameNumberMap.Count);
            return(cards.Count > 0);
        }