private void FindDecksScored(TriadGameModifier[] regionMods, List <TriadCard> lockedCards)
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            if (currentPool.commonList == null && currentPool.priorityLists == null)
            {
                stopwatch.Stop();
                Logger.WriteLine("Skip deck building, everything was locked");

                optimizedDeck = new TriadDeck(lockedCards);
                return;
            }

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

            // no more flexible slot count after this point => loop land
            const int numSlots = 5;

            TriadCard[][] slotLists = new TriadCard[numSlots][];
            for (int idx = 0; idx < numSlots; idx++)
            {
                slotLists[idx] =
                    (currentPool.deckSlotTypes[idx] == DeckSlotCommon) ? currentPool.commonList :
                    (currentPool.deckSlotTypes[idx] >= 0) ? currentPool.priorityLists[currentPool.deckSlotTypes[idx]] :
                    new TriadCard[1] {
                    lockedCards[idx]
                };
            }

            Func <int, int, int, int, int, int> FindLoopStart = (SlotIdx, IdxS0, IdxS1, IdxS2, IdxS3) =>
            {
                if (bAbort)
                {
                    return(slotLists[SlotIdx].Length);
                }
                if (currentPool.deckSlotTypes[SlotIdx] != DeckSlotCommon)
                {
                    return(0);
                }

                if (SlotIdx >= 4 && currentPool.deckSlotTypes[3] == DeckSlotCommon)
                {
                    return(IdxS3 + 1);
                }
                if (SlotIdx >= 3 && currentPool.deckSlotTypes[2] == DeckSlotCommon)
                {
                    return(IdxS2 + 1);
                }
                if (SlotIdx >= 2 && currentPool.deckSlotTypes[1] == DeckSlotCommon)
                {
                    return(IdxS1 + 1);
                }
                if (SlotIdx >= 1 && currentPool.deckSlotTypes[0] == DeckSlotCommon)
                {
                    return(IdxS0 + 1);
                }

                return(0);
            };

            Parallel.For(0, slotLists[0].Length, IdxS0 =>
                         //for (int IdxS0 = 0; IdxS0 < slotLists[0].Length; IdxS0++)
            {
                int startS1 = FindLoopStart(1, IdxS0, -1, -1, -1);
                Parallel.For(startS1, slotLists[1].Length, IdxS1 =>
                             //for (int IdxS1 = startS1; IdxS1 < slotLists[1].Length; IdxS1++)
                {
                    int startS2 = FindLoopStart(2, IdxS0, IdxS1, -1, -1);
                    Parallel.For(startS2, slotLists[2].Length, IdxS2 =>
                                 //for (int IdxS2 = startS2; IdxS2 < slotLists[2].Length; IdxS2++)
                    {
                        int startS3 = FindLoopStart(3, IdxS0, IdxS1, IdxS2, -1);
                        for (int IdxS3 = startS3; IdxS3 < slotLists[3].Length; IdxS3++)
                        {
                            int startS4 = FindLoopStart(4, IdxS0, IdxS1, IdxS2, IdxS3);
                            for (int IdxS4 = startS4; IdxS4 < slotLists[4].Length; IdxS4++)
                            {
                                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(currentSolver, testDeck, randomGen, 1);
                                        if (testScore > bestScore)
                                        {
                                            lock (lockOb)
                                            {
                                                bestScore = testScore;
                                                bestDeck  = testDeck;
                                                OnFoundDeck.Invoke(testDeck);
                                            }
                                        }
                                    }
                                }

                                lock (lockOb)
                                {
                                    numTestedDecks++;
                                }
                            }
                        }
                    });
                });
            });

            stopwatch.Stop();
            Logger.WriteLine("Building list of decks: " + stopwatch.ElapsedMilliseconds + "ms, num:" + numPossibleDecks);
            optimizedDeck = bestDeck;
        }
Exemple #2
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;
        }
        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;
        }