public void simulateEnemysTurn(bool simulateTwoTurns) { int maxwide = 20; this.enemyAbilityReady = true; this.enemyHeroNumAttackThisTurn = 0; this.enemyHeroWindfury = false; if (this.enemyWeaponName == "doomhammer") this.enemyHeroWindfury = true; this.enemyheroImmuneWhileAttacking = false; if (this.enemyWeaponName == "gladiatorslongbow") this.enemyheroImmuneWhileAttacking = true; if (!this.enemyHeroFrozen && this.enemyWeaponDurability > 0) this.enemyHeroReady = true; this.enemyheroAngr = this.enemyWeaponAttack; bool havedonesomething = true; List<Playfield> posmoves = new List<Playfield>(); posmoves.Add(new Playfield(this)); List<Playfield> temp = new List<Playfield>(); int deep = 0; while (havedonesomething) { temp.Clear(); temp.AddRange(posmoves); havedonesomething = false; Playfield bestold = null; int bestoldval = 20000000; foreach (Playfield p in temp) { if (p.complete) { continue; } List<Minion> playedMinions = new List<Minion>(8); foreach (Minion m in p.enemyMinions) { if (m.Ready && m.Angr >= 1 && !m.frozen) { //BEGIN:cut (double/similar) attacking minions out##################################### // DONT LET SIMMILAR MINIONS ATTACK IN ONE TURN (example 3 unlesh the hounds-hounds doesnt need to simulated hole) List<Minion> tempoo = new List<Minion>(playedMinions); bool dontattacked = true; bool isSpecial = PenalityManager.Instance.specialMinions.ContainsKey(m.name); foreach (Minion mnn in tempoo) { // special minions are allowed to attack in silended and unsilenced state! //help.logg(mnn.silenced + " " + m.silenced + " " + mnn.name + " " + m.name + " " + penman.specialMinions.ContainsKey(m.name)); bool otherisSpecial = PenalityManager.Instance.specialMinions.ContainsKey(mnn.name); if ((!isSpecial || (isSpecial && m.silenced)) && (!otherisSpecial || (otherisSpecial && mnn.silenced))) // both are not special, if they are the same, dont add { if (mnn.Angr == m.Angr && mnn.Hp == m.Hp && mnn.divineshild == m.divineshild && mnn.taunt == m.taunt && mnn.poisonous == m.poisonous) dontattacked = false; continue; } if (isSpecial == otherisSpecial && !m.silenced && !mnn.silenced) // same are special { if (m.name != mnn.name) // different name -> take it { continue; } // same name -> test whether they are equal if (mnn.Angr == m.Angr && mnn.Hp == m.Hp && mnn.divineshild == m.divineshild && mnn.taunt == m.taunt && mnn.poisonous == m.poisonous) dontattacked = false; continue; } } if (dontattacked) { playedMinions.Add(m); } else { //help.logg(m.name + " doesnt need to attack!"); continue; } //END: cut (double/similar) attacking minions out##################################### //help.logg(m.name + " is going to attack!"); List<targett> trgts = p.getAttackTargets(false); if (true)//(this.useCutingTargets) { trgts = Ai.Instance.cutAttackTargets(trgts, p, false); } foreach (targett trgt in trgts) { Playfield pf = new Playfield(p); havedonesomething = true; pf.ENEMYattackWithMinion(m, trgt.target, trgt.targetEntity); posmoves.Add(pf); } if (trgts.Count == 1 && trgts[0].target == 100)//only enemy hero is available als attack { break; } } } // attacked with minions done // attack with hero if (p.enemyHeroReady) { List<targett> trgts = p.getAttackTargets(false); havedonesomething = true; if (true)//(this.useCutingTargets) { trgts = Ai.Instance.cutAttackTargets(trgts, p, false); } foreach (targett trgt in trgts) { Playfield pf = new Playfield(p); pf.ENEMYattackWithWeapon(trgt.target, trgt.targetEntity, 0); posmoves.Add(pf); } } // use ability /// TODO check if ready after manaup if (p.enemyAbilityReady && p.enemyHeroAblility.canplayCard(p, 0)) { int abilityPenality = 0; havedonesomething = true; // if we have mage or priest, we have to target something#################################################### if (p.enemyHeroName == HeroEnum.mage || p.enemyHeroName == HeroEnum.priest) { List<targett> trgts = p.enemyHeroAblility.getTargetsForCard(p); foreach (targett trgt in trgts) { Playfield pf = new Playfield(p); havedonesomething = true; pf.ENEMYactivateAbility(p.enemyHeroAblility, trgt.target, trgt.targetEntity); posmoves.Add(pf); } } else { // the other classes dont have to target#################################################### Playfield pf = new Playfield(p); havedonesomething = true; pf.ENEMYactivateAbility(p.enemyHeroAblility, -1, -1); posmoves.Add(pf); } } p.endEnemyTurn(); if (Ai.Instance.botBase.getPlayfieldValue(p) < bestoldval) // want the best enemy-play-> worst for us { bestoldval = Ai.Instance.botBase.getPlayfieldValue(p); bestold = p; } posmoves.Remove(p); if (posmoves.Count >= maxwide) break; } if ( bestoldval <= 10000 && bestold != null) { posmoves.Add(bestold); } deep++; if (posmoves.Count >= maxwide) break; } foreach (Playfield p in posmoves) { if (!p.complete) p.endEnemyTurn(); } int bestval = int.MaxValue; Playfield bestplay = posmoves[0]; foreach (Playfield p in posmoves) { int val = Ai.Instance.botBase.getPlayfieldValue(p); if (bestval > val)// we search the worst value { bestplay = p; bestval = val; } } this.value = bestplay.value; if (simulateTwoTurns) { bestplay.prepareNextTurn(); MiniSimulator ms = new MiniSimulator(); this.value = (int)(0.5 * bestval + 0.5 * ms.doallmoves(bestplay)); } }