public int doallmoves(Playfield playf, bool isLethalCheck) { //Helpfunctions.Instance.logg("NXTTRN" + playf.mana); if (botBase == null) { botBase = Ai.Instance.botBase; } bool test = false; this.posmoves.Clear(); this.addToPosmoves(playf); bool havedonesomething = true; List <Playfield> temp = new List <Playfield>(); int deep = 0; //Helpfunctions.Instance.logg("NXTTRN" + playf.mana + " " + posmoves.Count); this.calculated = 0; while (havedonesomething) { if (this.printNormalstuff) { Helpfunctions.Instance.logg("ailoop"); } GC.Collect(); temp.Clear(); temp.AddRange(this.posmoves); havedonesomething = false; Playfield bestold = null; int bestoldval = -20000000; foreach (Playfield p in temp) { if (p.complete || p.ownHeroHp <= 0) { continue; } //take a card and play it List <CardDB.cardName> playedcards = new List <CardDB.cardName>(); foreach (Handmanager.Handcard hc in p.owncards) { if (this.calculated > this.totalboards) { continue; } CardDB.Card c = hc.card; //help.logg("try play crd" + c.name + " " + c.getManaCost(p) + " " + c.canplayCard(p)); if (playedcards.Contains(c.name)) { continue; // dont play the same card in one loop } playedcards.Add(c.name); if (c.choice) { if (doAllChoices(p, hc, isLethalCheck)) { havedonesomething = true; } } else { int bestplace = p.getBestPlace(c, isLethalCheck); if (hc.canplayCard(p)) { havedonesomething = true; List <targett> trgts = c.getTargetsForCard(p); if (isLethalCheck && (pen.DamageTargetDatabase.ContainsKey(c.name) || pen.DamageTargetSpecialDatabase.ContainsKey(c.name)))// only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } else { // no enemy hero -> enemy have taunts ->kill the taunts from left to right if (trgts.Count >= 1) { trg = trgts[0]; trgts.Clear(); trgts.Add(trg); } } } int cardplayPenality = 0; if (trgts.Count == 0) { if (usePenalityManager) { cardplayPenality = pen.getPlayCardPenality(c, -1, p, 0, isLethalCheck); if (cardplayPenality <= 499) { Playfield pf = new Playfield(p); havedonesomething = true; pf.playCard(hc, hc.position - 1, hc.entity, -1, -1, 0, bestplace, cardplayPenality); addToPosmoves(pf); } } else { Playfield pf = new Playfield(p); havedonesomething = true; pf.playCard(hc, hc.position - 1, hc.entity, -1, -1, 0, bestplace, cardplayPenality); addToPosmoves(pf); } } else { if (isLethalCheck)// only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } } foreach (targett trgt in trgts) { if (usePenalityManager) { cardplayPenality = pen.getPlayCardPenality(c, trgt.target, p, 0, isLethalCheck); if (cardplayPenality <= 499) { Playfield pf = new Playfield(p); havedonesomething = true; pf.playCard(hc, hc.position - 1, hc.entity, trgt.target, trgt.targetEntity, 0, bestplace, cardplayPenality); addToPosmoves(pf); } } else { Playfield pf = new Playfield(p); havedonesomething = true; pf.playCard(hc, hc.position - 1, hc.entity, trgt.target, trgt.targetEntity, 0, bestplace, cardplayPenality); addToPosmoves(pf); } } } } } } //attack with a minion List <Minion> playedMinions = new List <Minion>(8); foreach (Minion m in p.ownMinions) { if (this.calculated > this.totalboards) { continue; } 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 = pen.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 = pen.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(true); if (isLethalCheck)// only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } else { // no enemy hero -> enemy have taunts ->kill the taunts from left to right if (trgts.Count >= 1) { trg = trgts[0]; trgts.Clear(); trgts.Add(trg); } } } else { if (this.useCutingTargets) { trgts = this.cutAttackTargets(trgts, p, true); } } foreach (targett trgt in trgts) { int attackPenality = 0; if (usePenalityManager) { attackPenality = pen.getAttackWithMininonPenality(m, p, trgt.target, isLethalCheck); if (attackPenality <= 499) { Playfield pf = new Playfield(p); havedonesomething = true; pf.attackWithMinion(m, trgt.target, trgt.targetEntity, attackPenality); addToPosmoves(pf); } } else { Playfield pf = new Playfield(p); havedonesomething = true; pf.attackWithMinion(m, trgt.target, trgt.targetEntity, attackPenality); addToPosmoves(pf); } } if ((!m.stealth || isLethalCheck) && p.enemySecretCount == 0 && trgts.Count == 1 && trgts[0].target == 200) //only enemy hero is available als attack { break; } } } // attack with hero if (p.ownHeroReady) { if (this.calculated > this.totalboards) { continue; } List <targett> trgts = p.getAttackTargets(true); havedonesomething = true; if (isLethalCheck)// only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } else { // no enemy hero -> enemy have taunts ->kill the taunts from left to right if (trgts.Count >= 1) { trg = trgts[0]; trgts.Clear(); trgts.Add(trg); } } } else { if (this.useCutingTargets) { trgts = this.cutAttackTargets(trgts, p, true); } } foreach (targett trgt in trgts) { Playfield pf = new Playfield(p); int heroAttackPen = 0; if (usePenalityManager) { heroAttackPen = pen.getAttackWithHeroPenality(trgt.target, p, isLethalCheck); } pf.attackWithWeapon(trgt.target, trgt.targetEntity, heroAttackPen); addToPosmoves(pf); } } // use ability /// TODO check if ready after manaup if (p.ownAbilityReady && p.mana >= 2 && p.ownHeroAblility.canplayCard(p, 2)) { if (this.calculated > this.totalboards) { continue; } int abilityPenality = 0; havedonesomething = true; // if we have mage or priest, we have to target something#################################################### if (p.ownHeroName == HeroEnum.mage || p.ownHeroName == HeroEnum.priest) { List <targett> trgts = p.ownHeroAblility.getTargetsForCard(p); if (isLethalCheck && (p.ownHeroName == HeroEnum.mage || (p.ownHeroName == HeroEnum.priest && (p.ownHeroAblility.name != CardDB.cardName.lesserheal || (p.ownHeroAblility.name == CardDB.cardName.lesserheal && p.auchenaiseelenpriesterin))))) // only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } else { // no enemy hero -> enemy have taunts ->kill the taunts from left to right if (trgts.Count >= 1) { trg = trgts[0]; trgts.Clear(); trgts.Add(trg); } } } foreach (targett trgt in trgts) { if (usePenalityManager) { abilityPenality = pen.getPlayCardPenality(p.ownHeroAblility, trgt.target, p, 0, isLethalCheck); if (abilityPenality <= 499) { Playfield pf = new Playfield(p); havedonesomething = true; pf.activateAbility(p.ownHeroAblility, trgt.target, trgt.targetEntity, abilityPenality); addToPosmoves(pf); } } else { Playfield pf = new Playfield(p); havedonesomething = true; pf.activateAbility(p.ownHeroAblility, trgt.target, trgt.targetEntity, abilityPenality); addToPosmoves(pf); } } } else { // the other classes dont have to target#################################################### Playfield pf = new Playfield(p); if (usePenalityManager) { abilityPenality = pen.getPlayCardPenality(p.ownHeroAblility, -1, pf, 0, isLethalCheck); if (abilityPenality <= 499) { havedonesomething = true; pf.activateAbility(p.ownHeroAblility, -1, -1, abilityPenality); addToPosmoves(pf); } } else { havedonesomething = true; pf.activateAbility(p.ownHeroAblility, -1, -1, abilityPenality); addToPosmoves(pf); } } } if (isLethalCheck) { p.complete = true; } else { p.endTurn(this.simulateSecondTurn, this.playaround, false, this.playaroundprob, this.playaroundprob2); } //sort stupid stuff ouf if (botBase.getPlayfieldValue(p) > bestoldval) { bestoldval = botBase.getPlayfieldValue(p); bestold = p; } if (!test) { posmoves.Remove(p); } if (this.calculated > this.totalboards) { break; } } if (!test && bestoldval >= -10000 && bestold != null) { this.posmoves.Add(bestold); } //Helpfunctions.Instance.loggonoff(true); if (this.printNormalstuff) { int donec = 0; foreach (Playfield p in posmoves) { if (p.complete) { donec++; } } Helpfunctions.Instance.logg("deep " + deep + " len " + this.posmoves.Count + " dones " + donec); } if (!test) { cuttingposibilities(); } if (this.printNormalstuff) { Helpfunctions.Instance.logg("cut to len " + this.posmoves.Count); } //Helpfunctions.Instance.loggonoff(false); deep++; if (this.calculated > this.totalboards) { break; } if (deep >= this.maxdeep) { break; //remove this? } } foreach (Playfield p in posmoves)//temp { if (!p.complete) { if (isLethalCheck) { p.complete = true; } else { p.endTurn(this.simulateSecondTurn, this.playaround, false, this.playaroundprob, this.playaroundprob2); } } } // Helpfunctions.Instance.logg("find best "); if (posmoves.Count >= 1) { int bestval = int.MinValue; int bestanzactions = 1000; Playfield bestplay = posmoves[0]; //temp[0] foreach (Playfield p in posmoves) //temp { int val = botBase.getPlayfieldValue(p); if (bestval <= val) { if (bestval == val && bestanzactions < p.playactions.Count) { continue; } bestplay = p; bestval = val; bestanzactions = p.playactions.Count; } } this.bestmove = bestplay.getNextAction(); this.bestmoveValue = bestval; this.bestboard = new Playfield(bestplay); //Helpfunctions.Instance.logg("return"); return(bestval); } //Helpfunctions.Instance.logg("return"); this.bestmove = null; this.bestmoveValue = -100000; this.bestboard = playf; return(-10000); }
private void doallmoves(bool test, Bot botBase, bool isLethalCheck) { bool havedonesomething = true; List <Playfield> temp = new List <Playfield>(); int deep = 0; while (havedonesomething) { help.logg("ailoop"); GC.Collect(); temp.Clear(); temp.AddRange(this.posmoves); havedonesomething = false; Playfield bestold = null; int bestoldval = -20000000; foreach (Playfield p in temp) { if (p.complete) { continue; } //take a card and play it List <string> playedcards = new List <string>(); foreach (Handmanager.Handcard hc in p.owncards) { CardDB.Card c = hc.card; //help.logg("try play crd" + c.name + " " + c.getManaCost(p) + " " + c.canplayCard(p)); if (playedcards.Contains(c.name)) { continue; // dont play the same card in one loop } playedcards.Add(c.name); if (c.choice) { if (doAllChoices(p, hc, isLethalCheck)) { havedonesomething = true; } } else { int bestplace = p.getBestPlace(c); if (hc.canplayCard(p)) { havedonesomething = true; List <targett> trgts = c.getTargetsForCard(p); if (isLethalCheck && (penman.DamageTargetDatabase.ContainsKey(c.name) || penman.DamageTargetSpecialDatabase.ContainsKey(c.name)))// only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } else { // no enemy hero -> enemy have taunts ->kill the taunts from left to right if (trgts.Count >= 1) { trg = trgts[0]; trgts.Clear(); trgts.Add(trg); } } } int cardplayPenality = 0; if (trgts.Count == 0) { if (usePenalityManager) { cardplayPenality = penman.getPlayCardPenality(c, -1, p, 0, isLethalCheck); if (cardplayPenality <= 499) { Playfield pf = new Playfield(p); havedonesomething = true; pf.playCard(hc, hc.position - 1, hc.entity, -1, -1, 0, bestplace, cardplayPenality); this.posmoves.Add(pf); } } else { Playfield pf = new Playfield(p); havedonesomething = true; pf.playCard(hc, hc.position - 1, hc.entity, -1, -1, 0, bestplace, cardplayPenality); this.posmoves.Add(pf); } } else { if (isLethalCheck)// only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } } foreach (targett trgt in trgts) { if (usePenalityManager) { cardplayPenality = penman.getPlayCardPenality(c, trgt.target, p, 0, isLethalCheck); if (cardplayPenality <= 499) { Playfield pf = new Playfield(p); havedonesomething = true; pf.playCard(hc, hc.position - 1, hc.entity, trgt.target, trgt.targetEntity, 0, bestplace, cardplayPenality); this.posmoves.Add(pf); } } else { Playfield pf = new Playfield(p); havedonesomething = true; pf.playCard(hc, hc.position - 1, hc.entity, trgt.target, trgt.targetEntity, 0, bestplace, cardplayPenality); this.posmoves.Add(pf); } } } } } } //attack with a minion List <Minion> playedMinions = new List <Minion>(8); foreach (Minion m in p.ownMinions) { 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 = penman.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 = penman.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(); if (isLethalCheck)// only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } else { // no enemy hero -> enemy have taunts ->kill the taunts from left to right if (trgts.Count >= 1) { trg = trgts[0]; trgts.Clear(); trgts.Add(trg); } } } else { if (this.useCutingTargets) { trgts = this.cutAttackTargets(trgts, p); } } foreach (targett trgt in trgts) { int attackPenality = 0; if (usePenalityManager) { attackPenality = penman.getAttackWithMininonPenality(m, p, trgt.target, isLethalCheck); if (attackPenality <= 499) { Playfield pf = new Playfield(p); havedonesomething = true; pf.attackWithMinion(m, trgt.target, trgt.targetEntity, attackPenality); this.posmoves.Add(pf); } } else { Playfield pf = new Playfield(p); havedonesomething = true; pf.attackWithMinion(m, trgt.target, trgt.targetEntity, attackPenality); this.posmoves.Add(pf); } } if (trgts.Count == 1 && trgts[0].target == 200)//only enemy hero is available als attack { break; } } } // attack with hero if (p.ownHeroReady) { List <targett> trgts = p.getAttackTargets(); havedonesomething = true; if (isLethalCheck)// only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } else { // no enemy hero -> enemy have taunts ->kill the taunts from left to right if (trgts.Count >= 1) { trg = trgts[0]; trgts.Clear(); trgts.Add(trg); } } } else { if (this.useCutingTargets) { trgts = this.cutAttackTargets(trgts, p); } } foreach (targett trgt in trgts) { Playfield pf = new Playfield(p); int heroAttackPen = 0; if (usePenalityManager) { heroAttackPen = penman.getAttackWithHeroPenality(trgt.target, p); } pf.attackWithWeapon(trgt.target, trgt.targetEntity, heroAttackPen); this.posmoves.Add(pf); } } // use ability /// TODO check if ready after manaup if (p.ownAbilityReady && p.mana >= 2 && p.ownHeroAblility.canplayCard(p, 2)) { int abilityPenality = 0; havedonesomething = true; // if we have mage or priest, we have to target something#################################################### if (this.hp.heroname == "mage" || this.hp.heroname == "priest") { List <targett> trgts = p.ownHeroAblility.getTargetsForCard(p); if (isLethalCheck && (this.hp.heroname == "mage" || (this.hp.heroname == "priest" && p.ownHeroAblility.name != "lesserheal")))// only target enemy hero during Lethal check! { targett trg = trgts.Find(x => x.target == 200); if (trg != null) { trgts.Clear(); trgts.Add(trg); } else { // no enemy hero -> enemy have taunts ->kill the taunts from left to right if (trgts.Count >= 1) { trg = trgts[0]; trgts.Clear(); trgts.Add(trg); } } } foreach (targett trgt in trgts) { if (usePenalityManager) { abilityPenality = penman.getPlayCardPenality(p.ownHeroAblility, trgt.target, p, 0, isLethalCheck); if (abilityPenality <= 499) { Playfield pf = new Playfield(p); havedonesomething = true; pf.activateAbility(p.ownHeroAblility, trgt.target, trgt.targetEntity, abilityPenality); this.posmoves.Add(pf); } } else { Playfield pf = new Playfield(p); havedonesomething = true; pf.activateAbility(p.ownHeroAblility, trgt.target, trgt.targetEntity, abilityPenality); this.posmoves.Add(pf); } } } else { // the other classes dont have to target#################################################### Playfield pf = new Playfield(p); if (usePenalityManager) { abilityPenality = penman.getPlayCardPenality(p.ownHeroAblility, -1, pf, 0, isLethalCheck); if (abilityPenality <= 499) { havedonesomething = true; pf.activateAbility(p.ownHeroAblility, -1, -1, abilityPenality); this.posmoves.Add(pf); } } else { havedonesomething = true; pf.activateAbility(p.ownHeroAblility, -1, -1, abilityPenality); this.posmoves.Add(pf); } } } p.endTurn(); //sort stupid stuff ouf if (botBase.getPlayfieldValue(p) > bestoldval) { bestoldval = botBase.getPlayfieldValue(p); bestold = p; } if (!test) { posmoves.Remove(p); } } if (!test && bestoldval >= -10000 && bestold != null) { this.posmoves.Add(bestold); } help.loggonoff(true); int donec = 0; foreach (Playfield p in posmoves) { if (p.complete) { donec++; } } help.logg("deep " + deep + " len " + this.posmoves.Count + " dones " + donec); if (!test) { cuttingposibilities(botBase); } help.logg("cut to len " + this.posmoves.Count); help.loggonoff(false); deep++; if (deep >= this.maxdeep) { break; //remove this? } } int bestval = int.MinValue; int bestanzactions = 1000; Playfield bestplay = temp[0]; foreach (Playfield p in temp) { int val = botBase.getPlayfieldValue(p); if (bestval <= val) { if (bestval == val && bestanzactions < p.playactions.Count) { continue; } bestplay = p; bestval = val; bestanzactions = p.playactions.Count; } } help.loggonoff(true); help.logg("-------------------------------------"); help.logg("bestPlayvalue " + bestval); bestplay.printActions(); this.bestmove = bestplay.getNextAction(); this.bestmoveValue = bestval; this.bestboard = new Playfield(bestplay); /*if (bestmove != null && bestmove.cardplay && bestmove.handcard.card.type == CardDB.cardtype.MOB) * { * Playfield pf = new Playfield(); * help.logg("bestplaces:"); * pf.getBestPlacePrint(bestmove.card); * }*/ if (bestmove != null) // save the guessed move, so we doesnt need to recalc! { this.nextMoveGuess = new Playfield(); if (bestmove.cardplay) { //pf.playCard(c, hc.position - 1, hc.entity, trgt.target, trgt.targetEntity, 0, bestplace, cardplayPenality); Handmanager.Handcard hc = this.nextMoveGuess.owncards.Find(x => x.entity == bestmove.cardEntitiy); if (bestmove.owntarget >= 0 && bestmove.enemytarget >= 0 && bestmove.enemytarget <= 9 && bestmove.owntarget < bestmove.enemytarget) { this.nextMoveGuess.playCard(bestmove.handcard, hc.position - 1, hc.entity, bestmove.enemytarget - 1, bestmove.enemyEntitiy, bestmove.druidchoice, bestmove.owntarget, 0); } else { this.nextMoveGuess.playCard(bestmove.handcard, hc.position - 1, hc.entity, bestmove.enemytarget, bestmove.enemyEntitiy, bestmove.druidchoice, bestmove.owntarget, 0); } //this.nextMoveGuess.playCard(bestmove.card, hc.position - 1, hc.entity, bestmove.enemytarget, bestmove.enemyEntitiy, bestmove.druidchoice, bestmove.owntarget, 0); } if (bestmove.minionplay) { //.attackWithMinion(m, trgt.target, trgt.targetEntity, attackPenality); Minion m = this.nextMoveGuess.ownMinions.Find(x => x.entitiyID == bestmove.ownEntitiy); this.nextMoveGuess.attackWithMinion(m, bestmove.enemytarget, bestmove.enemyEntitiy, 0); } if (bestmove.heroattack) { this.nextMoveGuess.attackWithWeapon(bestmove.enemytarget, bestmove.enemyEntitiy, 0); } if (bestmove.useability) { //.activateAbility(p.ownHeroAblility, trgt.target, trgt.targetEntity, abilityPenality); this.nextMoveGuess.activateAbility(this.nextMoveGuess.ownHeroAblility, bestmove.enemytarget, bestmove.enemyEntitiy, 0); } this.bestboard.playactions.RemoveAt(0); } else { nextMoveGuess.mana = -1; } }