public float DoAllMoves(Playfield playf) { print = playf.print; isLethalCheck = playf.isLethalCheck; enoughCalculations = false; botBase = Ai.Instance.botBase; posmoves.Clear(); twoturnfields.Clear(); addToPosmoves(playf); bool havedonesomething = true; List <Playfield> temp = new List <Playfield>(); int deep = 0; calculated = 0; Playfield bestold = null; bestoldval = -20000000; while (havedonesomething) { if (printNormalstuff) { LogHelper.WriteCombatLog($"ailoop{deep}"); } GC.Collect(); temp.Clear(); temp.AddRange(posmoves); posmoves.Clear(); havedonesomething = false; threadnumberGlobal = 0; if (print) { startEnemyTurnSimThread(temp, 0, temp.Count); } else { Parallel.ForEach(Partitioner.Create(0, temp.Count), range => { startEnemyTurnSimThread(temp, range.Item1, range.Item2); }); } foreach (Playfield p in temp) { if (totalboards > 0) { calculated += p.nextPlayfields.Count; } if (calculated <= totalboards) { posmoves.AddRange(p.nextPlayfields); p.nextPlayfields.Clear(); } //get the best Playfield float pVal = botBase.getPlayfieldValue(p); if (pVal > bestoldval) { bestoldval = pVal; bestold = p; bestoldDuplicates.Clear(); } else if (Math.Abs(pVal - bestoldval) < 0.001f) { bestoldDuplicates.Add(p); } } if (isLethalCheck && bestoldval >= 10000) { posmoves.Clear(); } if (posmoves.Count > 0) { havedonesomething = true; } if (printNormalstuff) { int donec = 0; foreach (Playfield p in posmoves) { if (p.complete) { donec++; } } LogHelper.WriteCombatLog("deep " + deep + " len " + posmoves.Count + " dones " + donec); } cuttingposibilities(isLethalCheck);//will update posmoves if (printNormalstuff) { LogHelper.WriteCombatLog("cut to len " + posmoves.Count); } int itemPlayfieldIndex = 0; foreach (var itemPlayfield in posmoves) { itemPlayfieldIndex++; var actionsCount = itemPlayfield.playactions.Count; LogHelper.WriteTestCombatLog($"{nameof(itemPlayfield)}{itemPlayfieldIndex} with {actionsCount} actions"); itemPlayfield.printActions(); } deep++; temp.Clear(); if (calculated > totalboards) { enoughCalculations = true; } if (deep >= maxdeep) { enoughCalculations = true; } } if (dirtyTwoTurnSim > 0 && !twoturnfields.Contains(bestold)) { twoturnfields.Add(bestold); } posmoves.Clear(); posmoves.Add(bestold); posmoves.AddRange(bestoldDuplicates); // search the best play........................................................... //do dirtytwoturnsim first :D if (!isLethalCheck && bestoldval < 10000) { doDirtyTwoTurnsim(); } if (posmoves.Count >= 1) { posmoves.Sort((a, b) => botBase.getPlayfieldValue(b).CompareTo(botBase.getPlayfieldValue(a))); Playfield bestplay = posmoves[0]; float bestval = botBase.getPlayfieldValue(bestplay); int pcount = posmoves.Count; for (int i = 1; i < pcount; i++) { float val = botBase.getPlayfieldValue(posmoves[i]); if (bestval > val) { break; } if (posmoves[i].cardsPlayedThisTurn > bestplay.cardsPlayedThisTurn) { continue; } if (posmoves[i].cardsPlayedThisTurn == bestplay.cardsPlayedThisTurn) { if (bestplay.optionsPlayedThisTurn > posmoves[i].optionsPlayedThisTurn) { continue; } if (bestplay.optionsPlayedThisTurn == posmoves[i].optionsPlayedThisTurn && bestplay.enemyHero.HealthPoints <= posmoves[i].enemyHero.HealthPoints) { continue; } } bestplay = posmoves[i]; bestval = val; } bestmove = bestplay.getNextAction(); bestmoveValue = bestval; bestboard = new Playfield(bestplay); bestboard.guessingHeroHP = bestplay.guessingHeroHP; bestboard.value = bestplay.value; bestboard.hashcode = bestplay.hashcode; bestoldDuplicates.Clear(); return(bestval); } bestmove = null; bestmoveValue = -100000; bestboard = playf; return(-10000); }