public void Initialize(TriadNpc npc, TriadGameModifier[] regionMods, List <TriadCard> lockedCards) { this.npc = npc; numPossibleDecks = 1; numTestedDecks = 0; numMsElapsed = 0; PlayerSettingsDB playerDB = PlayerSettingsDB.Get(); currentSolver = new TriadGameSession(); currentSolver.modifiers.AddRange(npc.Rules); currentSolver.modifiers.AddRange(regionMods); currentSolver.UpdateSpecialRules(); isOrderImportant = false; foreach (TriadGameModifier mod in currentSolver.modifiers) { isOrderImportant = isOrderImportant || mod.IsDeckOrderImportant(); } bool foundCards = FindCardPool(playerDB.ownedCards, currentSolver.modifiers, lockedCards); if (foundCards) { UpdatePossibleDeckCount(); } }
private void contextMenuStripPickCard_Opened(object sender, EventArgs e) { toolStripComboBoxPick.BeginUpdate(); PlayerSettingsDB playerDB = PlayerSettingsDB.Get(); TriadCardDB cardsDB = TriadCardDB.Get(); int numExpected = toolStripMenuOnlyOwned.Checked ? playerDB.ownedCards.Count : cardsDB.cards.Count; if (numExpected != toolStripComboBoxPick.Items.Count) { toolStripComboBoxPick.Items.Clear(); foreach (TriadCard card in cardsDB.cards) { if (card != null && (!toolStripMenuOnlyOwned.Checked || playerDB.ownedCards.Contains(card))) { toolStripComboBoxPick.Items.Add(new DeckCardPicker(card)); } } } for (int Idx = 0; Idx < toolStripComboBoxPick.Items.Count; Idx++) { DeckCardPicker cardOb = (DeckCardPicker)toolStripComboBoxPick.Items[Idx]; if (cardOb.Card == cardClickOwner.GetCard()) { toolStripComboBoxPick.SelectedIndex = Idx; break; } } toolStripComboBoxPick.EndUpdate(); toolStripComboBoxPick.Focus(); }
public void PrepareStats(TriadNpc npc, TriadGameModifier[] regionMods, List <TriadCard> lockedCards, out string numOwnedStr, out string numPossibleStr) { bool bIsOrderImportant = false; foreach (TriadGameModifier mod in npc.Rules) { bIsOrderImportant = bIsOrderImportant || mod.IsDeckOrderImportant(); } foreach (TriadGameModifier mod in regionMods) { bIsOrderImportant = bIsOrderImportant || mod.IsDeckOrderImportant(); } //TriadCardDB playerDB = TriadCardDB.Get(); PlayerSettingsDB playerDB = PlayerSettingsDB.Get(); int numOwned = playerDB.ownedCards.Count; numOwnedStr = numOwned.ToString(); if (bUseScoredBuilder) { UpdatePossibleDeckCount(numRareToBuild, numCommonToBuild, lockedCards, bIsOrderImportant); } else { UpdatePossibleDeckCount(numOwned, bIsOrderImportant); } numPossibleStr = numPossibleDecks.ToString("N0"); }
public void InitializeAssets(ImageList cardImageList) { cardImages = cardImageList; for (int Idx = 0; Idx < boardControls.Length; Idx++) { boardControls[Idx].cardIcons = cardImages; } for (int Idx = 0; Idx < redDeckKnownCards.Length; Idx++) { redDeckKnownCards[Idx].cardIcons = cardImages; redDeckUnknownCards[Idx].cardIcons = cardImages; } deckCtrlBlue.cardIcons = cardImages; deckCtrlRed.cardIcons = cardImages; deckCtrlBlue.allowRearrange = false; deckCtrlRed.allowRearrange = false; deckCtrlBlue.enableHitTest = false; deckCtrlRed.enableHitTest = false; deckCtrlBlue.drawMode = ECardDrawMode.ImageOnly; deckCtrlRed.drawMode = ECardDrawMode.ImageOnly; deckCtrlBlue.clickAction = EDeckCtrlAction.None; deckCtrlRed.clickAction = EDeckCtrlAction.None; deckCtrlBlue.deckOwner = ETriadCardOwner.Blue; deckCtrlRed.deckOwner = ETriadCardOwner.Red; checkBoxAutoScan.Checked = PlayerSettingsDB.Get().useAutoScan; }
public ETriadDeckState GetDeckState() { PlayerSettingsDB playerDB = PlayerSettingsDB.Get(); int[] rarityCounters = new int[5]; for (int DeckIdx = 0; DeckIdx < knownCards.Count; DeckIdx++) { TriadCard deckCard = knownCards[DeckIdx]; bool bIsOwned = playerDB.ownedCards.Contains(deckCard); if (!bIsOwned) { return(ETriadDeckState.MissingCards); } for (int TestIdx = 0; TestIdx < knownCards.Count; TestIdx++) { if ((TestIdx != DeckIdx) && knownCards[TestIdx].Equals(deckCard)) { return(ETriadDeckState.HasDuplicates); } } rarityCounters[(int)deckCard.Rarity]++; } int numRare5 = rarityCounters[(int)ETriadCardRarity.Legendary]; int numRare45 = rarityCounters[(int)ETriadCardRarity.Epic] + numRare5; // temporary, can be removed once all game clients are on 5.5+ version // step up your releases SE :P bool isUsingRulesVer54 = LocalizationDB.Languages[LocalizationDB.UserLanguageIdx] == "cn" || LocalizationDB.Languages[LocalizationDB.UserLanguageIdx] == "ko"; if (isUsingRulesVer54) { if (numRare45 > 1) { // reuse "single 5 star" error, don't have better description anymore return(ETriadDeckState.TooMany5Star); } } else { if (numRare5 > 1) { return(ETriadDeckState.TooMany5Star); } else if (numRare45 > 2) { return(ETriadDeckState.TooMany4Star); } } return(ETriadDeckState.Valid); }
private void buttonAdd_Click(object sender, EventArgs e) { DialogResult = DialogResult.Yes; deck.Name = textBox1.Text; PlayerSettingsDB.Get().UpdateFavDeck(slotIdx, deck); Close(); }
public ETriadDeckState GetDeckState() { PlayerSettingsDB playerDB = PlayerSettingsDB.Get(); int[] rarityCounters = new int[5]; for (int DeckIdx = 0; DeckIdx < knownCards.Count; DeckIdx++) { TriadCard deckCard = knownCards[DeckIdx]; bool bIsOwned = playerDB.ownedCards.Contains(deckCard); if (!bIsOwned) { return(ETriadDeckState.MissingCards); } for (int TestIdx = 0; TestIdx < knownCards.Count; TestIdx++) { if ((TestIdx != DeckIdx) && knownCards[TestIdx].Equals(deckCard)) { return(ETriadDeckState.HasDuplicates); } } rarityCounters[(int)deckCard.Rarity]++; } int numRare45 = rarityCounters[(int)ETriadCardRarity.Epic] + rarityCounters[(int)ETriadCardRarity.Legendary]; int numRare345 = rarityCounters[(int)ETriadCardRarity.Rare] + numRare45; int numRare2345 = rarityCounters[(int)ETriadCardRarity.Uncommon] + numRare345; if (playerDB.ownedCards.Count < 30) { if (numRare2345 > 1) { return(ETriadDeckState.TooManyRaresUncomon); } } else if (playerDB.ownedCards.Count < 60) { if (numRare345 > 1) { return(ETriadDeckState.TooManyRaresRare); } } else { if (numRare45 > 1) { return(ETriadDeckState.TooManyRaresEpic); } } return(ETriadDeckState.Valid); }
private void buttonRemove_Click(object sender, EventArgs e) { DialogResult ret = MessageBox.Show("Favorite deck will be removed, do you want to continue?", Text, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (ret == DialogResult.Yes) { DialogResult = DialogResult.No; PlayerSettingsDB.Get().UpdateFavDeck(slotIdx, null); Close(); } }
private void buttonOk_Click(object sender, EventArgs e) { DialogResult = DialogResult.Cancel; if (comboBox1.SelectedItem != null) { TriadCard card = comboBox1.SelectedItem as TriadCard; // check modified numbers for (int idx = 0; idx < 4; idx++) { if (card.Sides[idx] != cardState.sideNumber[idx]) { ImageHashData digitPattern = new ImageHashData() { type = EImageHashType.CardNumber, previewBounds = cardState.sideInfo[idx].scanBox, previewContextBounds = cardState.scanBox, isKnown = true }; digitPattern.CalculateHash(cardState.sideInfo[idx].hashValues); digitPattern.ownerOb = card.Sides[idx]; PlayerSettingsDB.Get().RemoveKnownHash(digitPattern); if (card.Sides[idx] != cardState.sideInfo[idx].matchNum) { PlayerSettingsDB.Get().AddKnownHash(digitPattern); cardState.sideInfo[idx].hasOverride = true; } cardState.sideNumber[idx] = card.Sides[idx]; cardState.card = card; cardState.failedMatching = false; DialogResult = DialogResult.OK; } } // check multicard hash if (comboBox1.Items.Count > 1 && cardState.cardImageHash != null && cardState.card != card) { cardState.cardImageHash.ownerOb = card; PlayerSettingsDB.Get().RemoveKnownHash(cardState.cardImageHash); PlayerSettingsDB.Get().AddKnownHash(cardState.cardImageHash); cardState.card = card; DialogResult = DialogResult.OK; } } Close(); }
private void toolStripMenuOnlyOwned_CheckedChanged(object sender, EventArgs e) { toolStripComboBoxPick.Items.Clear(); PlayerSettingsDB playerDB = PlayerSettingsDB.Get(); TriadCardDB cardsDB = TriadCardDB.Get(); foreach (TriadCard card in cardsDB.cards) { if (card != null && (!toolStripMenuOnlyOwned.Checked || playerDB.ownedCards.Contains(card))) { toolStripComboBoxPick.Items.Add(new DeckCardPicker(card)); } } }
public bool MergeWithContent(string jsonString) { PlayerSettingsDB mergeDB = new PlayerSettingsDB(); bool bLoaded = mergeDB.LoadFromJson(jsonString); bool bHadUniqueSettings = false; if (bLoaded) { bool bUpdatedOwnedCards = false; foreach (TriadCard card in mergeDB.ownedCards) { if (!ownedCards.Contains(card)) { ownedCards.Add(card); bUpdatedOwnedCards = true; } } bHadUniqueSettings = bHadUniqueSettings || (ownedCards.Count > mergeDB.ownedCards.Count); bool bUpdatedNpcs = false; foreach (TriadNpc npc in mergeDB.completedNpcs) { if (!completedNpcs.Contains(npc)) { completedNpcs.Add(npc); bUpdatedNpcs = true; } } bHadUniqueSettings = bHadUniqueSettings || (completedNpcs.Count > mergeDB.completedNpcs.Count); bool bUpdatedDecks = false; foreach (KeyValuePair <TriadNpc, TriadDeck> kvp in mergeDB.lastDeck) { if (!lastDeck.ContainsKey(kvp.Key)) { lastDeck.Add(kvp.Key, kvp.Value); } // replace existing? skip for now... } bHadUniqueSettings = bHadUniqueSettings || (lastDeck.Count > mergeDB.lastDeck.Count); OnUpdated.Invoke(bUpdatedOwnedCards, bUpdatedNpcs, bUpdatedDecks); } return(bHadUniqueSettings); }
private Rectangle GetGameWindowBounds(HandleRef windowHandle) { Rectangle result = GetGameWindowBoundsRaw(windowHandle); Screen activeScreen = Screen.FromHandle(windowHandle.Handle); if (result.Width > 0 && PlayerSettingsDB.Get().useFullScreenCapture) { result = Screen.GetBounds(result); activeScreen = Screen.FromRectangle(result); } if (activeScreen != cachedScreen) { cachedScreen = activeScreen; DEVMODE dm = new DEVMODE(); dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE)); EnumDisplaySettings(cachedScreen.DeviceName, -1, ref dm); if (dm.dmPelsWidth == cachedScreen.Bounds.Width) { cachedScreenScaling = 1.0f; } else { cachedScreenScaling = (float)cachedScreen.Bounds.Width / (float)dm.dmPelsWidth; } if (Logger.IsSuperVerbose()) { Logger.WriteLine("GetGameWindowBounds, caching screen data: bounds:{0}, pelsWidth:{1} => scale:{2}", cachedScreen.Bounds, dm.dmPelsWidth, cachedScreenScaling); } } if (cachedScreenScaling != 1.0f) { result.X = cachedScreen.Bounds.X + (int)((result.X - cachedScreen.Bounds.X) / cachedScreenScaling); result.Y = cachedScreen.Bounds.Y + (int)((result.Y - cachedScreen.Bounds.Y) / cachedScreenScaling); result.Width = (int)(result.Width / cachedScreenScaling); result.Height = (int)(result.Height / cachedScreenScaling); } return(result); }
private void buttonOk_Click(object sender, EventArgs e) { HashOwnerItem hashComboItem = (HashOwnerItem)comboBoxOwner.SelectedItem; if (hashComboItem != null) { if (hashData.ownerOb == null || (labelHashOrg.Text != hashComboItem.SourceObject.ToString())) { PlayerSettingsDB.Get().RemoveKnownHash(hashData); hashData.ownerOb = hashComboItem.SourceObject; hashData.matchDistance = 0; hashData.isAuto = false; PlayerSettingsDB.Get().AddKnownHash(hashData); } } DialogResult = DialogResult.OK; Close(); }
public void InitDeck(int slotIdx, TriadDeck copyFrom, ImageList cardImages, ImageList cardTypes, ImageList cardRarity) { this.slotIdx = slotIdx; PlayerSettingsDB playerDB = PlayerSettingsDB.Get(); if (slotIdx < playerDB.favDecks.Count) { deck = playerDB.favDecks[slotIdx]; buttonAdd.Text = "Update"; } else { deck = new TriadDeckNamed(copyFrom); deck.Name = "Fav #" + (slotIdx + 1).ToString(); } deckCtrl1.SetImageLists(cardImages, cardTypes, cardRarity); deckCtrl1.SetDeck(deck); textBox1.Text = deck.Name; }
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; } } }
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 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; }
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; }
private void checkBoxFullScreenScan_CheckedChanged(object sender, EventArgs e) { PlayerSettingsDB.Get().useFullScreenCapture = checkBoxFullScreenScan.Checked; UpdateScreenState(screenReader); OnUpdateState.Invoke(); }
public static object FindMatchingHash(FastBitmapHash hashData, EImageHashType hashType, out int bestDistance, bool bDebugMode = false) { string debugDesc = bDebugMode ? hashData.Hash + " >> " : ""; int debugDescParts = 0; object bestMatchOb = null; bestDistance = -1; bool bIsLocked = PlayerSettingsDB.Get().IsLockedHash(hashData.Hash); foreach (ImageHashData hashInfo in PlayerSettingsDB.Get().customHashes) { if (hashInfo.Type == hashType) { bool bIsMatching = hashInfo.IsHashMatching(hashData.Hash, out int testDistance); if (bDebugMode) { debugDesc += ((hashType == EImageHashType.Card) ? ((TriadCard)hashInfo.Owner).ToShortString() : hashInfo.Owner.ToString()) + ":" + testDistance + ", "; debugDescParts++; } if (bIsLocked && testDistance != 0) { continue; } if (bIsMatching && (bestDistance < 0 || bestDistance > testDistance)) { bestDistance = testDistance; bestMatchOb = hashInfo.Owner; } } } if (bestDistance < 0) { foreach (ImageHashData hashInfo in ImageHashDB.Get().hashes) { if (hashInfo.Type == hashType) { bool bIsMatching = hashInfo.IsHashMatching(hashData.Hash, out int testDistance); if (bDebugMode) { debugDesc += ((hashType == EImageHashType.Card) ? ((TriadCard)hashInfo.Owner).ToShortString() : hashInfo.Owner.ToString()) + ":" + testDistance + ", "; debugDescParts++; } if (bIsLocked && testDistance != 0) { continue; } if (bIsMatching && (bestDistance < 0 || bestDistance > testDistance)) { bestDistance = testDistance; bestMatchOb = hashInfo.Owner; } } } } if (bDebugMode) { if (debugDescParts > 0) { debugDesc = debugDesc.Remove(debugDesc.Length - 2, 2); } debugDesc += " >> "; debugDesc += (bestMatchOb == null) ? "unknown" : ((hashType == EImageHashType.Card) ? ((TriadCard)bestMatchOb).ToShortString() : bestMatchOb.ToString()); Logger.WriteLine(debugDesc); } return(bestMatchOb); }
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; }