//MAIN //TODO: //Fields Has_0Drop, Has_1Drop //DECK INFO //Race fields: Beast, murloc etc public List <Card.Cards> HandleMulligan(List <Card.Cards> choices, Card.CClass opponentClass, Card.CClass ownClass) { _comboDic = new Dictionary <string, int>(); //Load deck try { _myDeck = Bot.CurrentDeck().Cards.Select(card => (Card.Cards)Enum.Parse(typeof(Card.Cards), card)).ToList(); } catch { _myDeck = new List <Card.Cards>(); } if (BlnDebugMode) { _myDeck = new List <Card.Cards>() { Cards.ShieldSlam, Cards.ShieldSlam, Card.Cards.BOT_299, //Omega Assembly Card.Cards.BOT_299, //Omega Assembly Card.Cards.BOT_042, //Weapons Project Card.Cards.BOT_042, //Weapons Project Cards.Warpath, Cards.Warpath, Cards.CorneredSentry, Cards.CorneredSentry, Cards.DeadMansHand, Cards.DrywhiskerArmorer, Cards.DrywhiskerArmorer, Cards.Execute, Cards.Execute, Cards.AcolyteofPain, Cards.AcolyteofPain, Cards.BloodRazor, Cards.BloodRazor, Cards.HarrisonJones, Cards.Brawl, Cards.Brawl, Card.Cards.BOT_270, //Giggling Inventor Card.Cards.BOT_270, //Giggling Inventor Card.Cards.BOT_238, //Dr. Boom, Mad Genius Cards.GrommashHellscream, Cards.GeosculptorYip, Cards.ScourgelordGarrosh, Cards.TheLichKing, Card.Cards.BOT_069 //The Boomship } } ; DeckInfo currentDeckInfo = new DeckInfo(_myDeck); //ARCHETYPE DETECTOR var archetypes = new List <Archetype>(); archetypes.AddRange(Bot.GetArchetypes().Where(archetype => archetype.ArchetypeName().Contains("SMK_"))); Archetype friend = ArchetypeDetector.DetectArchetype(_myDeck, archetypes, 70); if (BlnDebugMode) { string s = ""; foreach (var card in _myDeck) { s += CardTemplate.LoadFromId(card).Name + ", "; } Bot.Log(s); } //Choosing ini file if (!(Bot.CurrentMode() == Bot.Mode.Arena || Bot.CurrentMode() == Bot.Mode.ArenaAuto)) { AddLog(SDivider); if (friend != null) { AddLog("Archetype = " + friend.ArchetypeName()); var fName = Directory.GetCurrentDirectory() + @"\MulliganProfiles\Files\" + friend.ArchetypeName() + ".ini"; if (File.Exists(fName)) { _iniTierList = new IniManager(fName); } } else { AddLog("Archetype = NONE"); } } IniManager currentFile = _iniTierList; string tempString = MulliganInfo(); if (tempString != null) { AddLog(tempString); } else { AddLog(SDivider); AddLog("ERROR!!!"); AddLog("MULLIGAN IS INSTALLED WRONG"); AddLog("PLEASE, FOLLOW THE INSTRUCTIONS AT THE TOPIC:"); AddLog("https://smartbot.ws/index.php?/topic/9020-SMK/&"); AddLog("Doesn't matter if this is arena mulligan or not."); AddLog(SDivider); LogDebug(); PrintLog(); return(_keep); } //Setting mode combo preferences #region Mode preferences int tempCount = -1917; int.TryParse( currentFile.GetString("combo", "count", "-1917"), out tempCount); if (tempCount != -1917) { //Bot.Log("Custom curve: "); for (var i = 0; i < tempCount; i++) { string tempArgs = currentFile.GetString("combo", string.Format("combo_{0}", i), null); if (tempArgs == null) { continue; } string[] args = tempArgs.Split('*'); if (!_comboDic.ContainsKey(args[0])) { //Bot.Log(String.Format("{0} - {1}", args[0], args[1])); _comboDic.Add(args[0], int.Parse(args[1])); } } } if (_comboDic.Count == 0) { if (Bot.CurrentMode() == Bot.Mode.ArenaAuto || Bot.CurrentMode() == Bot.Mode.Arena) //ARENA { _comboDic = new Dictionary <string, int>() { //coin { "12200", 35 }, { "12110", 35 }, { "12100", 20 }, { "11111", 40 }, { "11110", 30 }, { "11102", 35 }, { "11101", 25 }, { "11100", 20 }, { "11021", 35 }, { "11020", 25 }, { "11010", 15 }, { "10211", 35 }, { "10210", 25 }, { "10110", 10 }, { "10010", 0 }, { "10020", 0 }, { "10030", -45 }, { "10040", -60 }, //no coin { "01110", 30 }, { "01100", 20 }, { "01010", 15 }, { "02010", 0 }, { "00110", 0 }, { "00030", -45 }, { "00020", -30 }, { "00010", 0 }, }; } else //Ranked/Unranked/Practice { _comboDic = new Dictionary <string, int>() { //coin { "12200", 30 }, { "12100", 0 }, { "11111", 40 }, { "11110", 30 }, { "11102", 35 }, { "11101", 25 }, { "11100", 20 }, { "11021", 35 }, { "11020", 25 }, { "11010", 15 }, { "10211", 35 }, { "10210", 25 }, { "10030", -45 }, { "10040", -60 }, //no coin { "01110", 30 }, { "01100", 20 }, { "01010", 15 }, { "02100", -10 }, }; } } #endregion //Define our globals _choices = choices; _opponentClass = opponentClass; //New class choices //var mChoices = new List<Mcard> //{ // new Mcard(choices[0]), // new Mcard(choices[1]), // new Mcard(choices[2]), //}; //if (choices.Count > 3) mChoices.Add(new Mcard(choices[3])); AddLog("Match info: "); AddLog("Class: " + ownClass); AddLog("Opponent: " + _opponentClass); bool coin = _choices.Count >= 4; //Defines the coin if (coin) { Keep(null, Card.Cards.GAME_005); } AddLog("Coin: " + coin); AddLog(SDivider); AddLog("Offered:"); foreach (var card in _choices) { AddLog("> " + CardTemplate.LoadFromId(card).Name + " (" + card + ")"); } AddLog(SDivider); //LOAD ID int[] iCardPts = new int[_choices.Count]; int[] iCardCombo = new int[_choices.Count]; int[,] iCardInteractionPts = new int[_choices.Count, _choices.Count]; for (var i = 0; i < choices.Count; i++) { var card = choices[i]; int.TryParse(_iniTierList.GetString(string.Format("card_{0}", card), "class_ANY", "-50"), out iCardPts[i]); int temp; int.TryParse( _iniTierList.GetString(string.Format("card_{0}", card), string.Format("class_{0}", ownClass), "-1917"), out temp); iCardPts[i] = (temp == -1917) ? iCardPts[i] : temp; int.TryParse( _iniTierList.GetString(string.Format("card_{0}", card), "combo", "0"), out iCardCombo[i]); int.TryParse( _iniTierList.GetString(string.Format("card_{0}", card), string.Format("opp_{0}", _opponentClass), "0"), out temp); iCardPts[i] += temp; if (coin) { int.TryParse(_iniTierList.GetString(string.Format("card_{0}", card), "coin", "0"), out temp); iCardPts[i] += temp; } for (var j = 0; j < choices.Count; j++) { if (j == i) { continue; } var card2 = choices[j]; int.TryParse( _iniTierList.GetString(string.Format("card_{0}", card), string.Format("pCard_{0}", card2), "0"), out iCardInteractionPts[i, j]); } int.TryParse( _iniTierList.GetString(string.Format("card_{0}", card), string.Format("opp_{0}", _opponentClass), "0"), out temp); } int[,,,] combinationPts = new int[2, 2, 2, 2]; double[,,,] combinationPtsPerCrd = new double[2, 2, 2, 2]; bool[,,,] combinationCmb = new bool[2, 2, 2, 2]; int[,,,,] combinationInt = new int[2, 2, 2, 2, 4]; int[,,,,] combinationCst = new int[2, 2, 2, 2, 6]; string bestComboVal = "0000"; int bestComboPts = 0; double bestComboPtsPerCard = 0; int bestCardCount = 0; do { int[] i = new int[4]; for (i[0] = 0; i[0] < 2; i[0]++) { for (i[1] = 0; i[1] < 2; i[1]++) { for (i[2] = 0; i[2] < 2; i[2]++) { for (i[3] = 0; (i[3] < 2 && coin || i[3] < 1 && !coin); i[3]++) { //List<Card.Cards> currentChoices = new List<Card.Cards>(); //for (var it = 0; it < choices.Count; it++) //{ // if (i[it] == 1) // { // currentChoices.Add(choices[it]); // } //} for (var it = 0; it < choices.Count; it++) { //var card = choices[it]; if (i[it] == 0) { continue; } combinationPts[i[0], i[1], i[2], i[3]] += iCardPts[it]; combinationInt[i[0], i[1], i[2], i[3], it] += iCardPts[it]; for (var jt = 0; jt < choices.Count; jt++) { if ((jt == it) || (i[jt] == 0)) { continue; } combinationInt[i[0], i[1], i[2], i[3], jt] += iCardInteractionPts[it, jt]; combinationPts[i[0], i[1], i[2], i[3]] += iCardInteractionPts[it, jt]; } } for (var it = 0; it < choices.Count; it++) { var card = choices[it]; var cardTmp = CardTemplate.LoadFromId(card); if (i[it] == 0) { continue; } int tmp = cardTmp.Cost; /* TODO: FIXME: dirty hack */ if (card == Cards.NerubianProphet) { tmp = 3; } if (card == Cards.CorridorCreeper) { tmp = 3; } if (card == Cards.MoguFleshshaper) { tmp = 4; } combinationCst[i[0], i[1], i[2], i[3], Math.Min(5, tmp)]++; } //TODO: MB BETTER TO REWORK COMBO FORMAT var curCombo = string.Format ( "{0}{1}{2}{3}{4}", coin ? 1 : 0, combinationCst[i[0], i[1], i[2], i[3], 1], combinationCst[i[0], i[1], i[2], i[3], 2], combinationCst[i[0], i[1], i[2], i[3], 3], combinationCst[i[0], i[1], i[2], i[3], 4] ); if (_comboDic.ContainsKey(curCombo) && combinationCst[i[0], i[1], i[2], i[3], 5] == 0) { combinationPts[i[0], i[1], i[2], i[3]] += _comboDic[curCombo]; combinationCmb[i[0], i[1], i[2], i[3]] = true; for (int j = 0; j < 4; j++) { if (i[j] == 1) { combinationPts[i[0], i[1], i[2], i[3]] += iCardCombo[j]; } } } //Extra cards value reduce if (!combinationCmb[i[0], i[1], i[2], i[3]]) { combinationPts[i[0], i[1], i[2], i[3]] -= combinationCst[i[0], i[1], i[2], i[3], 5] * 150; combinationPts[i[0], i[1], i[2], i[3]] -= combinationCst[i[0], i[1], i[2], i[3], 4] * 100; combinationPts[i[0], i[1], i[2], i[3]] -= combinationCst[i[0], i[1], i[2], i[3], 3] * 75; if (!coin && combinationCst[i[0], i[1], i[2], i[3], 2] > 1) { combinationPts[i[0], i[1], i[2], i[3]] -= (combinationCst[i[0], i[1], i[2], i[3], 2] - 1) * 55; } else if (coin && combinationCst[i[0], i[1], i[2], i[3], 2] > 2) { combinationPts[i[0], i[1], i[2], i[3]] -= (combinationCst[i[0], i[1], i[2], i[3], 2] - 2) * 55; } if (!coin && combinationCst[i[0], i[1], i[2], i[3], 1] > 2) { combinationPts[i[0], i[1], i[2], i[3]] -= (combinationCst[i[0], i[1], i[2], i[3], 1] - 2) * 30; } else if (coin && combinationCst[i[0], i[1], i[2], i[3], 1] > 2) { combinationPts[i[0], i[1], i[2], i[3]] -= (combinationCst[i[0], i[1], i[2], i[3], 2] - 1) * 20; } } if (combinationCst[i[0], i[1], i[2], i[3], 0] > 1) { combinationPts[i[0], i[1], i[2], i[3]] -= (combinationCst[i[0], i[1], i[2], i[3], 0] - 1) * 20; } /* TODO: FIXME: dirty hack */ if ((i[0] == 1 && choices[0] == Cards.CorridorCreeper) || (i[1] == 1 && choices[1] == Cards.CorridorCreeper) || (i[2] == 1 && choices[2] == Cards.CorridorCreeper) || (i[3] == 1 && choices[3] == Cards.CorridorCreeper)) { for (var it = 0; it < choices.Count; it++) { if (i[it] == 0) { continue; } combinationPts[i[0], i[1], i[2], i[3]] += GetTokenCount(choices[it]) * 10; } } //weapon penalty var weaponCount = choices.Where((t, it) => i[it] == 1 && CardTemplate.LoadFromId(t).Type == Card.CType.WEAPON).Count(); if (weaponCount > 1) { combinationPts[i[0], i[1], i[2], i[3]] -= (weaponCount - 1) * 30; } var cardCount = i[0] + i[1] + i[2] + i[3]; if (i[0] + i[1] + i[2] + i[3] != 0) { combinationPtsPerCrd[i[0], i[1], i[2], i[3]] = (double)combinationPts[i[0], i[1], i[2], i[3]] / cardCount; } if (BlnUserDebugMode) { AddLog(string.Format("Combination: {0}{1}{2}{3} -- Points: {4,5} -- Pts/Card: {5:###.##}", i[0], i[1], i[2], i[3], combinationPts[i[0], i[1], i[2], i[3]], combinationPtsPerCrd[i[0], i[1], i[2], i[3]])); } if (combinationPts[i[0], i[1], i[2], i[3]] >= cardCount * 100 && (bestComboPts <combinationPts[i[0], i[1], i[2], i[3]] || bestComboPts == combinationPts[i[0], i[1], i[2], i[3]] && cardCount> bestCardCount)) { bestCardCount = cardCount; bestComboPts = combinationPts[i[0], i[1], i[2], i[3]]; bestComboPtsPerCard = combinationPtsPerCrd[i[0], i[1], i[2], i[3]]; bestComboVal = string.Format("{0}{1}{2}{3}", i[0], i[1], i[2], i[3]); } } } } } } while (false); AddLog(string.Format("Best Combination: {0} -- Points: {1} -- Pts/Card: {2:###.##}", bestComboVal, bestComboPts, bestComboPtsPerCard)); AddLog(SDivider); AddLog("Finally keeping:"); List <Card.Cards> lccKeeping = new List <Card.Cards>(); for (var i = _choices.Count - 1; i >= 0; i--) { if (bestComboVal[i] == '1') { lccKeeping.Add(_choices[i]); } } foreach (var card in lccKeeping) { Keep(null, card); } if (lccKeeping.Count == 0) { AddLog("Nothing"); } AddLog(SDivider); if (BlnUserDebugMode) { LogDebug(); } //Ending PrintLog(); return(_keep); } }