public Bot() { //crawler stuff----------------- OnVictory = HandleWining; OnLost = HandleLosing; OnBattleStateUpdate = HandleOnBattleStateUpdate; OnMulliganStateUpdate = HandleBattleMulliganPhase; //----------------------------------------- starttime = DateTime.Now; Settings set = Settings.Instance; this.sf = Silverfish.Instance; behave = set.setSettings(); sf.setnewLoggFile(); CardDB cdb = CardDB.Instance; if (cdb.installedWrong) { Helpfunctions.Instance.ErrorLog("cant find CardDB"); return; } bool teststuff = false; // set to true, to run a testfile (requires test.txt file in folder where _cardDB.txt file is located) bool printstuff = false; // if true, the best board of the tested file is printet stepp by stepp Helpfunctions.Instance.ErrorLog("----------------------------"); Helpfunctions.Instance.ErrorLog("you are running uai V" + sf.versionnumber); Helpfunctions.Instance.ErrorLog("----------------------------"); if (Settings.Instance.useExternalProcess) Helpfunctions.Instance.ErrorLog("YOU USE SILVER.EXE FOR CALCULATION, MAKE SURE YOU STARTED IT!"); if (Settings.Instance.useExternalProcess) Helpfunctions.Instance.ErrorLog("SILVER.EXE IS LOCATED IN: " + Settings.Instance.path); if (teststuff)//run autotester for developpers { Ai.Instance.autoTester(printstuff); } writeSettings(); }
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 if (!p.attacked) { 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); } } } } } } // 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); } } } } //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); } } 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; }
public bool updateEverything(Behavior botbase) { this.botbehave = "rush"; if (botbase is BehaviorControl) this.botbehave = "control"; this.botbehave += " " + Ai.Instance.maxwide; if (Ai.Instance.secondTurnAmount>0) { if (Ai.Instance.nextMoveGuess.mana == -100) { Ai.Instance.updateTwoTurnSim(); } this.botbehave += " twoturnsim " + Ai.Instance.mainTurnSimulator.dirtyTwoTurnSim; } if (Ai.Instance.playaround) { this.botbehave += " playaround"; this.botbehave += " " + Ai.Instance.playaroundprob + " " + Ai.Instance.playaroundprob2; } HRPlayer ownPlayer = HRPlayer.GetLocalPlayer(); HRPlayer enemyPlayer = HRPlayer.GetEnemyPlayer(); ownPlayerController = ownPlayer.GetHero().GetControllerId();//ownPlayer.GetHero().GetControllerId() // create hero + minion data getHerostuff(); getMinions(); getHandcards(); getDecks(); // send ai the data: Hrtprozis.Instance.clearAll(); Handmanager.Instance.clearAll(); Hrtprozis.Instance.setOwnPlayer(ownPlayerController); Handmanager.Instance.setOwnPlayer(ownPlayerController); Hrtprozis.Instance.updatePlayer(this.ownMaxMana, this.currentMana, this.cardsPlayedThisTurn, this.numMinionsPlayedThisTurn, this.ueberladung, ownPlayer.GetHero().GetEntityId(), enemyPlayer.GetHero().GetEntityId()); Hrtprozis.Instance.updateSecretStuff(this.ownSecretList, this.enemySecretCount); Hrtprozis.Instance.updateOwnHero(this.ownHeroWeapon, this.heroWeaponAttack, this.heroWeaponDurability, this.heroname, this.heroAbility, this.ownAbilityisReady, this.ownHero); Hrtprozis.Instance.updateEnemyHero(this.enemyHeroWeapon, this.enemyWeaponAttack, this.enemyWeaponDurability, this.enemyHeroname, this.enemyMaxMana, this.enemyAbility, this.enemyHero); Hrtprozis.Instance.updateMinions(this.ownMinions, this.enemyMinions); Handmanager.Instance.setHandcards(this.handCards, this.anzcards, this.enemyAnzCards); Hrtprozis.Instance.updateFatigueStats(this.ownDecksize, this.ownHeroFatigue, this.enemyDecksize, this.enemyHeroFatigue); //learnmode :D Playfield p = new Playfield(); if (lastpf != null) { if (lastpf.isEqualf(p)) { return false; } lastpf = p; } else { lastpf = p; } // print data printstuff(); Hrtprozis.Instance.printHero(); Hrtprozis.Instance.printOwnMinions(); Hrtprozis.Instance.printEnemyMinions(); Handmanager.Instance.printcards(); Probabilitymaker.Instance.printTurnGraveYard(); // calculate stuff Helpfunctions.Instance.ErrorLog("calculating stuff... " + DateTime.Now.ToString("HH:mm:ss.ffff")); Ai.Instance.dosomethingclever(botbase); Helpfunctions.Instance.ErrorLog("calculating ended! " + DateTime.Now.ToString("HH:mm:ss.ffff")); return true; }
public void autoTester(Behavior bbase, bool printstuff) { help.logg("simulating board "); BoardTester bt = new BoardTester(); this.botBase = bbase; hp.printHero(); hp.printOwnMinions(); hp.printEnemyMinions(); hm.printcards(); //calculate the stuff posmoves.Clear(); posmoves.Add(new Playfield()); posmoves[0].sEnemTurn = this.simulateEnemyTurn; foreach (Playfield p in this.posmoves) { p.printBoard(); } help.logg("ownminionscount " + posmoves[0].ownMinions.Count); help.logg("owncardscount " + posmoves[0].owncards.Count); foreach (var item in this.posmoves[0].owncards) { help.logg("card " + item.card.name + " is playable :" + item.canplayCard(posmoves[0]) + " cost/mana: " + item.manacost + "/" + posmoves[0].mana); } help.logg("ability " + posmoves[0].ownHeroAblility.card.name + " is playable :" + posmoves[0].ownHeroAblility.card.canplayCard(posmoves[0], 2) + " cost/mana: " + posmoves[0].ownHeroAblility.card.getManaCost(posmoves[0], 2) + "/" + posmoves[0].mana); // lethalcheck + normal DateTime strt = DateTime.Now; doallmoves(false, true); help.logg("calculated " + (DateTime.Now - strt).TotalSeconds); if (bestmoveValue < 10000) { posmoves.Clear(); posmoves.Add(new Playfield()); posmoves[0].sEnemTurn = this.simulateEnemyTurn; strt = DateTime.Now; doallmoves(false, false); help.logg("calculated " + (DateTime.Now - strt).TotalSeconds); } this.mainTurnSimulator.printPosmoves(); help.logg("bestfield"); bestboard.printBoard(); if (printstuff) simmulateWholeTurn(); }
public bool updateEverything(Behavior botbase, bool runExtern = false, bool passiveWait = false) { this.updateBehaveString(botbase); HRPlayer ownPlayer = HRPlayer.GetLocalPlayer(); HRPlayer enemyPlayer = HRPlayer.GetEnemyPlayer(); ownPlayerController = ownPlayer.GetHero().GetControllerId();//ownPlayer.GetHero().GetControllerId() // create hero + minion data getHerostuff(); getMinions(); getHandcards(); getDecks(); // send ai the data: Hrtprozis.Instance.clearAll(); Handmanager.Instance.clearAll(); Hrtprozis.Instance.setOwnPlayer(ownPlayerController); Handmanager.Instance.setOwnPlayer(ownPlayerController); this.numOptionPlayedThisTurn = 0; this.numOptionPlayedThisTurn += this.cardsPlayedThisTurn + this.ownHero.numAttacksThisTurn; foreach (Minion m in this.ownMinions) { if (m.Hp >= 1) this.numOptionPlayedThisTurn += m.numAttacksThisTurn; } Hrtprozis.Instance.updatePlayer(this.ownMaxMana, this.currentMana, this.cardsPlayedThisTurn, this.numMinionsPlayedThisTurn, this.numOptionPlayedThisTurn, this.ueberladung, ownPlayer.GetHero().GetEntityId(), enemyPlayer.GetHero().GetEntityId(), this.numberMinionsDiedThisTurn, this.ownCurrentOverload, this.enemyOverload); Hrtprozis.Instance.setPlayereffects(this.ownDragonConsort, this.enemyDragonConsort, this.ownLoathebs, this.enemyLoathebs, this.ownMillhouse, this.enemyMillhouse, this.ownKirintor, this.ownPrepa); Hrtprozis.Instance.updateSecretStuff(this.ownSecretList, this.enemySecretCount); Hrtprozis.Instance.updateOwnHero(this.ownHeroWeapon, this.heroWeaponAttack, this.heroWeaponDurability, this.heroname, this.heroAbility, this.ownAbilityisReady, this.ownHero); Hrtprozis.Instance.updateEnemyHero(this.enemyHeroWeapon, this.enemyWeaponAttack, this.enemyWeaponDurability, this.enemyHeroname, this.enemyMaxMana, this.enemyAbility, this.enemyHero); Hrtprozis.Instance.updateMinions(this.ownMinions, this.enemyMinions); Handmanager.Instance.setHandcards(this.handCards, this.anzcards, this.enemyAnzCards); Hrtprozis.Instance.updateFatigueStats(this.ownDecksize, this.ownHeroFatigue, this.enemyDecksize, this.enemyHeroFatigue); Probabilitymaker.Instance.getEnemySecretGuesses(this.enemySecretList, Hrtprozis.Instance.heroNametoEnum(this.enemyHeroname)); //learnmode :D Playfield p = new Playfield(); if (lastpf != null) { if (lastpf.isEqualf(p)) { return false; } //board changed we update secrets! //if(Ai.Instance.nextMoveGuess!=null) Probabilitymaker.Instance.updateSecretList(Ai.Instance.nextMoveGuess.enemySecretList); Probabilitymaker.Instance.updateSecretList(p, lastpf); lastpf = p; } else { lastpf = p; } p = new Playfield();//secrets have updated :D // calculate stuff Helpfunctions.Instance.ErrorLog("calculating stuff... " + DateTime.Now.ToString("HH:mm:ss.ffff")); if (runExtern) { Helpfunctions.Instance.logg("recalc-check###########"); //p.printBoard(); //Ai.Instance.nextMoveGuess.printBoard(); if (p.isEqual(Ai.Instance.nextMoveGuess, true)) { printstuff(false); Ai.Instance.doNextCalcedMove(); } else { printstuff(true); readActionFile(passiveWait); } } else { printstuff(false); Ai.Instance.dosomethingclever(botbase); } Helpfunctions.Instance.ErrorLog("calculating ended! " + DateTime.Now.ToString("HH:mm:ss.ffff")); return true; }
public float 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.twoturnfields.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; float bestoldval = -20000000; foreach (Playfield p in temp) { if (p.complete || p.ownHero.Hp <= 0) { continue; } //gernerate actions and play them! List<Action> actions = movegen.getMoveList(p, isLethalCheck, usePenalityManager, useCutingTargets); foreach (Action a in actions) { //if (deep == 0 && a.actionType == actionEnum.playcard) Helpfunctions.Instance.ErrorLog("play " + a.card.card.name); havedonesomething = true; Playfield pf = new Playfield(p); pf.doAction(a); addToPosmoves(pf); } // end the turn of the current board (only if its not a lethalcheck) 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); } } } // search the best play........................................................... //do dirtytwoturnsim first :D if (!isLethalCheck) doDirtyTwoTurnsim(); if (!isLethalCheck) this.dirtyTwoTurnSim /= 2; // Helpfunctions.Instance.logg("find best "); if (posmoves.Count >= 1) { float bestval = int.MinValue; int bestanzactions = 1000; Playfield bestplay = posmoves[0];//temp[0] foreach (Playfield p in posmoves)//temp { float 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; }
public bool updateEverything(Behavior botbase, bool runExtern = false, bool passiveWait = false) { this.updateBehaveString(botbase); ownPlayerController = TritonHs.OurHero.ControllerId; // create hero + minion data getHerostuff(); //small fix for not knowing when to mulligan: if (ownMaxMana == 1 && currentMana == 1 && numMinionsPlayedThisTurn == 0 && cardsPlayedThisTurn == 0) { setnewLoggFile(); getHerostuff(); } getMinions(); getHandcards(); getDecks(); // send ai the data: Hrtprozis.Instance.clearAll(); Handmanager.Instance.clearAll(); Hrtprozis.Instance.setOwnPlayer(ownPlayerController); Handmanager.Instance.setOwnPlayer(ownPlayerController); this.numOptionPlayedThisTurn = 0; this.numOptionPlayedThisTurn += this.cardsPlayedThisTurn + this.ownHero.numAttacksThisTurn; foreach (Minion m in this.ownMinions) { if (m.Hp >= 1) this.numOptionPlayedThisTurn += m.numAttacksThisTurn; } Hrtprozis.Instance.updatePlayer(this.ownMaxMana, this.currentMana, this.cardsPlayedThisTurn, this.numMinionsPlayedThisTurn, this.numOptionPlayedThisTurn, this.ueberladung, ownHero.entitiyID, enemyHero.entitiyID, this.numberMinionsDiedThisTurn, this.ownCurrentOverload, this.enemyOverload, this.heroPowerUsesThisTurn, this.lockandload); Hrtprozis.Instance.setPlayereffects(this.ownDragonConsort, this.enemyDragonConsort, this.ownLoathebs, this.enemyLoathebs, this.ownMillhouse, this.enemyMillhouse, this.ownKirintor, this.ownPrepa, this.ownsabo, this.enemysabo, this.ownFenciCoaches); Hrtprozis.Instance.updateSecretStuff(this.ownSecretList, this.enemySecretCount); Hrtprozis.Instance.updateOwnHero(this.ownHeroWeapon, this.heroWeaponAttack, this.heroWeaponDurability, this.heroname, this.heroAbility, this.ownAbilityisReady, this.ownHero, this.ownHeroPowerUsesThisGame); Hrtprozis.Instance.updateEnemyHero(this.enemyHeroWeapon, this.enemyWeaponAttack, this.enemyWeaponDurability, this.enemyHeroname, this.enemyMaxMana, this.enemyAbility, this.enemyHero, this.enemyHeroPowerUsesThisGame); Hrtprozis.Instance.updateMinions(this.ownMinions, this.enemyMinions); Handmanager.Instance.setHandcards(this.handCards, this.anzcards, this.enemyAnzCards); Hrtprozis.Instance.updateFatigueStats(this.ownDecksize, this.ownHeroFatigue, this.enemyDecksize, this.enemyHeroFatigue); Probabilitymaker.Instance.getEnemySecretGuesses(this.enemySecretList, Hrtprozis.Instance.heroNametoEnum(this.enemyHeroname)); //learnmode :D Playfield p = new Playfield(); if (lastpf != null) { if (lastpf.isEqualf(p)) { return false; } //board changed we update secrets! //if(Ai.Instance.nextMoveGuess!=null) Probabilitymaker.Instance.updateSecretList(Ai.Instance.nextMoveGuess.enemySecretList); Probabilitymaker.Instance.updateSecretList(p, lastpf); lastpf = p; } else { lastpf = p; } p = new Playfield(); //secrets have updated :D // calculate stuff Helpfunctions.Instance.ErrorLog("calculating stuff... " + DateTime.Now.ToString("HH:mm:ss.ffff")); if (runExtern) { Helpfunctions.Instance.logg("recalc-check###########"); if (p.isEqual(Ai.Instance.nextMoveGuess, true)) { printstuff(p, false); Ai.Instance.doNextCalcedMove(); } else { printstuff(p, true); readActionFile(passiveWait); } } else { // Drew: This prevents the freeze during AI updates, but no API functions may be called // during this time! using (TritonHs.Memory.ReleaseFrame(true)) { printstuff(p, false); //Helpfunctions.Instance.logg("middle calculations: " + DateTime.Now.ToString("HH:mm:ss.ffff")); Ai.Instance.dosomethingclever(botbase); } } Helpfunctions.Instance.ErrorLog("calculating ended! " + DateTime.Now.ToString("HH:mm:ss.ffff")); return true; }
public Behavior behave = new BehaviorControl();//change this to new BehaviorRush() for rush mode //Behavior behave = new BehaviorRush(); public DefaultRoutine() { // Global rules. Never keep a 4+ minion, unless it's Bolvar Fordragon (paladin). _mulliganRules.Add(new Tuple<string, string>("True", "card.Entity.Cost >= 4 and card.Entity.Id != \"GVG_063\"")); // Never keep Tracking. _mulliganRules.Add(new Tuple<string, string>("mulliganData.UserClass == TAG_CLASS.HUNTER", "card.Entity.Id == \"DS1_184\"")); // Example rule for self. //_mulliganRules.Add(new Tuple<string, string>("mulliganData.UserClass == TAG_CLASS.MAGE", "card.Cost >= 5")); // Example rule for opponents. //_mulliganRules.Add(new Tuple<string, string>("mulliganData.OpponentClass == TAG_CLASS.MAGE", "card.Cost >= 3")); // Example rule for matchups. //_mulliganRules.Add(new Tuple<string, string>("mulliganData.userClass == TAG_CLASS.HUNTER && mulliganData.OpponentClass == TAG_CLASS.DRUID", "card.Cost >= 2")); bool concede = false; HREngine.Bots.Settings set = HREngine.Bots.Settings.Instance; Silverfish sfff = Silverfish.Instance; behave = set.setSettings(); /* // play with these settings################################### int enfacehp = 15; // hp of enemy when your hero is allowed to attack the enemy face with his weapon int mxwde = 3000; // numer of boards which are taken to the next deep-lvl int twotsamount = 0; // number of boards where the next turn is simulated bool enemySecondTurnSim = false; // if he simulates the next players-turn, he also simulates the enemys respons bool playaround = false; // play around some enemys aoe-spells // these two parameters(probs) are value between 0 and 100 (0 <= Your_Value <= 100) //!!! Correct description: int playaroundprob = 50; // probability where the enemy NOT plays the aoe-spell: 100 - enemy never plays aoe-spell, 0 - always uses int playaroundprob2 = 80; // probability where the enemy plays the aoe-spell, and your minions will survive: 100 - always survive, 0 - never(survival depends on their real HP) int amountBoardsInEnemyTurnSim = 40; int amountBoardsInEnemyTurnSimSecondStepp = 200; int amountBoardsInEnemySecondTurnSim = 20; int nextturnsimDeep = 10; int nextturnsimMaxWidth = 20; int nexttunsimMaxBoards = 160; int ImprovedCalculations = 1; // 0 - disabled(for old PCs), 1 - enabled bool secrets = true; // playing arround enemys secrets int alpha = 50; // weight of the second turn in calculation (0<= alpha <= 100) HREngine.Bots.Settings.Instance.simulatePlacement = false; //rudiment!!! set this true, and ai will simulate all placements, whether you have a alpha/flametongue/argus //########################################################### */ if (HREngine.Bots.Settings.Instance.useExternalProcess) Helpfunctions.Instance.ErrorLog("YOU USE SILVER.EXE FOR CALCULATION, MAKE SURE YOU STARTED IT!"); if (HREngine.Bots.Settings.Instance.useExternalProcess) Helpfunctions.Instance.ErrorLog("SILVER.EXE IS LOCATED IN: " + HREngine.Bots.Settings.Instance.path); try{ if (HREngine.Bots.Settings.Instance.useExternalProcess) { System.Diagnostics.Process[] pname = System.Diagnostics.Process.GetProcessesByName("Silver"); string directory = HREngine.Bots.Settings.Instance.path + "Silver.exe"; directory = Path.GetFullPath(directory); Helpfunctions.Instance.ErrorLog("searching silver.exe in " + directory); bool hasToOpen = true; if (pname.Length >= 1) { for (int i = 0; i < pname.Length; i++) { string fullPath = pname[i].Modules[0].FileName; if (fullPath == directory) hasToOpen = false; } } if (hasToOpen) { System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(directory); startInfo.WorkingDirectory = HREngine.Bots.Settings.Instance.path; System.Diagnostics.Process.Start(startInfo); } System.Threading.Thread.Sleep(500); } } catch (Exception e) { Helpfunctions.Instance.ErrorLog("SILVER.EXE IS MISSING, bot will not work"); Helpfunctions.Instance.ErrorLog(e.ToString()); return; } CardDB cdb = CardDB.Instance; if (cdb.installedWrong) { Helpfunctions.Instance.ErrorLog("cant find CardDB"); return; } Silverfish.Instance.setnewLoggFile(); /*Helpfunctions.Instance.ErrorLog("set enemy-face-hp to: " + enfacehp); ComboBreaker.Instance.attackFaceHP = enfacehp; Ai.Instance.setMaxWide(mxwde); Helpfunctions.Instance.ErrorLog("set maxwide to: " + mxwde); Ai.Instance.setTwoTurnSimulation(false, twotsamount); Helpfunctions.Instance.ErrorLog("calculate the second turn of the " + twotsamount + " best boards"); if (twotsamount >= 1) { //Ai.Instance.nextTurnSimulator.setEnemyTurnsim(enemySecondTurnSim); HREngine.Bots.Settings.Instance.simEnemySecondTurn = enemySecondTurnSim; if (enemySecondTurnSim) Helpfunctions.Instance.ErrorLog("simulates the enemy turn on your second turn"); } if (secrets) { HREngine.Bots.Settings.Instance.useSecretsPlayArround = secrets; Helpfunctions.Instance.ErrorLog("playing arround secrets is " + secrets); } if (playaround) { HREngine.Bots.Settings.Instance.playarround = playaround; HREngine.Bots.Settings.Instance.playaroundprob = playaroundprob; HREngine.Bots.Settings.Instance.playaroundprob2 = playaroundprob2; Ai.Instance.setPlayAround(); Helpfunctions.Instance.ErrorLog("activated playaround"); } HREngine.Bots.Settings.Instance.setWeights(alpha); HREngine.Bots.Settings.Instance.enemyTurnMaxWide = amountBoardsInEnemyTurnSim; HREngine.Bots.Settings.Instance.enemySecondTurnMaxWide = amountBoardsInEnemySecondTurnSim; HREngine.Bots.Settings.Instance.nextTurnDeep = nextturnsimDeep; HREngine.Bots.Settings.Instance.nextTurnMaxWide = nextturnsimMaxWidth; HREngine.Bots.Settings.Instance.nextTurnTotalBoards = nexttunsimMaxBoards; //HREngine.Bots.Settings.Instance.ImprovedCalculations = ImprovedCalculations; */ bool teststuff = false; // set to true, to run a testfile (requires test.txt file in filder where _cardDB.txt file is located) bool printstuff = false; // if true, the best board of the tested file is printet stepp by stepp Helpfunctions.Instance.ErrorLog("----------------------------"); Helpfunctions.Instance.ErrorLog("you are running uai V" + Silverfish.Instance.versionnumber); Helpfunctions.Instance.ErrorLog("----------------------------"); if (teststuff) { Ai.Instance.autoTester(printstuff); } }
public void simulateEnemysTurn(Playfield rootfield, bool simulateTwoTurns, bool playaround, bool print, int pprob, int pprob2) { if (botBase == null) { botBase = Ai.Instance.botBase; } bool havedonesomething = true; posmoves.Clear(); if (print) { Helpfunctions.Instance.ErrorLog("board at enemyturn start-----------------------------"); rootfield.value = botBase.getPlayfieldValue(rootfield); rootfield.printBoard(); } posmoves.Add(new Playfield(rootfield)); //posmoves[0].prepareNextTurn(false); List <Playfield> temp = new List <Playfield>(); int deep = 0; int enemMana = rootfield.enemyMaxMana; //get rid of cursed! ? if (posmoves[0].anzEnemyCursed >= 1) { int curseds = posmoves[0].anzEnemyCursed; for (int ii = curseds; ii > 0; ii--) { if (enemMana >= 2) { enemMana -= 2; posmoves[0].anzEnemyCursed--; } } } if (print) { Console.WriteLine("enemMana " + enemMana); } //playing aoe-effects if activated (and we didnt play loatheb) if (playaround && rootfield.anzOwnLoatheb == 0) { float oldval = botBase.getPlayfieldValueEnemy(posmoves[0]); posmoves[0].value = int.MinValue; enemMana = posmoves[0].EnemyCardPlaying(rootfield.enemyHeroName, enemMana, rootfield.enemyAnzCards, pprob, pprob2); float newval = botBase.getPlayfieldValueEnemy(posmoves[0]); posmoves[0].value = int.MinValue; posmoves[0].enemyAnzCards--; posmoves[0].triggerCardsChanged(false); posmoves[0].mana = enemMana; if (oldval < newval) { posmoves.Clear(); posmoves.Add(new Playfield(rootfield)); } } //play ability! if (posmoves[0].enemyAbilityReady && enemMana >= 2 && posmoves[0].enemyHeroAblility.card.canplayCard(posmoves[0], 0) && rootfield.anzOwnSaboteur == 0) { int abilityPenality = 0; havedonesomething = true; // if we have mage or priest or hunter, we have to target something#################################################### if (penmanager.TargetAbilitysDatabase.ContainsKey(posmoves[0].enemyHeroAblility.card.cardIDenum)) { List <Minion> trgts = posmoves[0].enemyHeroAblility.card.getTargetsForCard(posmoves[0], false, false); foreach (Minion trgt in trgts) { //if (trgt.isHero) continue;//do play his ability in basics Action a = new Action(actionEnum.useHeroPower, posmoves[0].enemyHeroAblility, null, 0, trgt, abilityPenality, 0); Playfield pf = new Playfield(posmoves[0]); pf.doAction(a); posmoves.Add(pf); } } else { bool hasinspire = false; foreach (Minion minie in rootfield.enemyMinions) { if (minie.handcard.card.Inspire) { hasinspire = true; } } // the other classes dont have to target#################################################### if ((rootfield.enemyHeroName == HeroEnum.thief && rootfield.enemyWeaponDurability == 0) || rootfield.enemyHeroName != HeroEnum.thief || hasinspire) { Action a = new Action(actionEnum.useHeroPower, posmoves[0].enemyHeroAblility, null, 0, null, abilityPenality, 0); Playfield pf = new Playfield(posmoves[0]); pf.doAction(a); posmoves.Add(pf); } } } //kill to strong minions with low hp /*if (enemMana >= 4) * { * foreach (Playfield pf in posmoves) * { * Minion lowest = null; * foreach (Minion m in pf.ownMinions) * { * if (m.Angr >= 4 && m.Hp <= 2 && m.Hp>=1) * { * pf.minionGetDamageOrHeal(m, 100); * if (lowest == null || lowest.Angr <= m.Angr) * { * // lowest = m; * } * } * } * pf.doDmgTriggers(); * if (lowest != null) * { * pf.minionGetDamageOrHeal(lowest, lowest.Hp); * pf.doDmgTriggers(); * } * } * }*/ foreach (Minion m in posmoves[0].enemyMinions) { if (m.Angr == 0) { continue; } m.numAttacksThisTurn = 0; m.playedThisTurn = false; m.updateReadyness(); } //might be more than just one foreach (Playfield pipi in posmoves) { doSomeBasicEnemyAi(pipi); } int boardcount = 0; //movegen... int i = 0; int count = 0; Playfield p = null; Playfield bestold = null; while (havedonesomething) { temp.Clear(); temp.AddRange(posmoves); havedonesomething = false; float bestoldval = int.MaxValue; //foreach (Playfield p in temp) count = temp.Count; for (i = 0; i < count; i++) { p = temp[i]; if (p.complete) { continue; } List <Action> actions = movegen.getEnemyMoveList(p, false, true, true, 1);// 1 for not using ability moves foreach (Action a in actions) { havedonesomething = true; Playfield pf = new Playfield(p); pf.doAction(a); posmoves.Add(pf); /*if (print) * { * a.print(); * }*/ boardcount++; } p.endEnemyTurn(); //p.guessingHeroHP = rootfield.guessingHeroHP; if (botBase.getPlayfieldValueEnemy(p) < bestoldval) // want the best enemy-play-> worst for us { bestoldval = botBase.getPlayfieldValueEnemy(p); bestold = p; } posmoves.Remove(p); if (boardcount >= maxwide) { break; } } if (bestoldval <= 10000 && bestold != null) { posmoves.Add(bestold); } cuttingPosibilitiesET(); deep++; if (boardcount >= maxwide) { break; } } //foreach (Playfield p in posmoves) count = posmoves.Count; for (i = 0; i < count; i++) { if (!posmoves[i].complete) { posmoves[i].endEnemyTurn(); } } float bestval = int.MaxValue; Playfield bestplay = rootfield;// posmoves[0]; //foreach (Playfield p in posmoves) count = posmoves.Count; for (i = 0; i < count; i++) { p = posmoves[i]; //p.guessingHeroHP = rootfield.guessingHeroHP; float val = botBase.getPlayfieldValueEnemy(p); if (bestval > val)// we search the worst value { bestplay = p; bestval = val; } /*if (print) * { * Helpfunctions.Instance.ErrorLog(""+val); * p.printBoard(); * }*/ } if (print) { Helpfunctions.Instance.ErrorLog("best enemy board----------------------------------"); bestplay.printBoard(); } rootfield.value = bestplay.value; if (simulateTwoTurns && bestplay.ownHero.Hp > 0 && bestplay.value > -1000) { bestplay.prepareNextTurn(true); rootfield.value = Settings.Instance.firstweight * bestval + Settings.Instance.secondweight * Ai.Instance.nextTurnSimulator[this.thread].doallmoves(bestplay, false, print); } }
public float doallmoves(Playfield playf, bool print = false) { //todo only one time! bool isLethalCheck = playf.isLethalCheck; int totalboards = Settings.Instance.nextTurnTotalBoards; int maxwide = Settings.Instance.nextTurnMaxWide; int maxdeep = Settings.Instance.nextTurnDeep; bool playaround = Settings.Instance.playaround; int playaroundprob = Settings.Instance.playaroundprob; int playaroundprob2 = Settings.Instance.playaroundprob2; botBase = Ai.Instance.botBase; this.posmoves.Clear(); this.posmoves.Add(new Playfield(playf)); bool havedonesomething = true; List <Playfield> temp = new List <Playfield>(); int deep = 0; this.calculated = 0; Playfield bestold = null; float bestoldval = -20000000; while (havedonesomething) { //GC.Collect(); temp.Clear(); temp.AddRange(this.posmoves); havedonesomething = false; foreach (Playfield p in temp) { if (p.complete || p.ownHero.HealthPoints <= 0) { continue; } List <Action> actions = movegen.GetMoveList(p, usePenalityManager, useCutingTargets, true); foreach (Action a in actions) { havedonesomething = true; Playfield pf = new Playfield(p); pf.doAction(a); if (pf.ownHero.HealthPoints > 0) { this.posmoves.Add(pf); } if (totalboards > 0) { this.calculated++; } } p.endTurn(); if (!isLethalCheck) { this.startEnemyTurnSim(p, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2); } //sort stupid stuff ouf if (botBase.getPlayfieldValue(p) > bestoldval) { bestoldval = botBase.getPlayfieldValue(p); bestold = p; } posmoves.Remove(p); if (this.calculated > totalboards) { break; } } cuttingposibilities(maxwide); deep++; if (this.calculated > totalboards) { break; } if (deep >= maxdeep) { break; } } posmoves.Add(bestold); foreach (Playfield p in posmoves) { if (!p.complete) { p.endTurn(); if (!isLethalCheck) { this.startEnemyTurnSim(p, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2); } } } // find best 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 (bestplay.playactions.Count <= posmoves[i].playactions.Count) { continue; //priority to the minimum acts } bestplay = posmoves[i]; bestval = val; } this.bestmove = bestplay.getNextAction(); this.bestmoveValue = bestval; this.bestboard = new Playfield(bestplay); return(bestval); } this.bestmove = null; this.bestmoveValue = -100000; this.bestboard = playf; return(-10000); }
public bool getHoldList(MulliganData mulliganData, Behavior behave) { cards.Clear(); readRules(behave.BehaviorName()); if (!mulliganRulesLoaded) { return(false); } if (!(mulliganData.Cards.Count == 3 || mulliganData.Cards.Count == 4)) { Helpfunctions.Instance.ErrorLog("[Mulligan] Mulligan is not used, since it got number of cards: " + cards.Count.ToString()); return(false); } Log.InfoFormat("[开局留牌] 应用这个 {0} 规则:", behave.BehaviorName()); for (var i = 0; i < mulliganData.Cards.Count; i++) { cards.Add(new CardIDEntity(mulliganData.Cards[i].Entity.Id, i)); } HeroEnum ownHeroClass = Hrtprozis.Instance.heroTAG_CLASSstringToEnum(mulliganData.UserClass.ToString()); HeroEnum enemyHeroClass = Hrtprozis.Instance.heroTAG_CLASSstringToEnum(mulliganData.OpponentClass.ToString()); int manaRule = 4; string MullRuleKey = getMullRuleKey(CardDB.cardIDEnum.None, ownHeroClass, enemyHeroClass, 1); if (MulliganRules.ContainsKey(MullRuleKey)) { string[] temp = MulliganRules[MullRuleKey].Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); manaRule = Convert.ToInt32(temp[2]); } else { MullRuleKey = getMullRuleKey(CardDB.cardIDEnum.None, ownHeroClass, HeroEnum.None, 1); if (MulliganRules.ContainsKey(MullRuleKey)) { string[] temp = MulliganRules[MullRuleKey].Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); manaRule = Convert.ToInt32(temp[2]); } } CardIDEntity Coin = new CardIDEntity("GAME_005", -888); if (cards.Count == 4) { cards.Add(Coin); //we have a coin } foreach (CardIDEntity CardIDEntityC in cards) { CardDB.Card c = CardDB.Instance.getCardDataFromID(CardIDEntityC.id); if (CardIDEntityC.hold == 0 && CardIDEntityC.holdByRule == 0) { if (c.cost < manaRule) { CardIDEntityC.holdByManarule = 2; CardIDEntityC.holdReason = joinSomeTxt("保留这些卡牌因为法力值消耗:", c.cost.ToString(), " 小于预定值:", manaRule.ToString()); } else { CardIDEntityC.holdByManarule = -2; CardIDEntityC.holdReason = joinSomeTxt("弃掉这些卡牌因为法力值消耗:", c.cost.ToString(), " 没有小于预定值:", manaRule.ToString()); } } int allowedQuantitySimple = 0; int allowedQuantityExtra = 0; bool hasRuleClassSimple = false; bool hasRule = false; string MullRuleKeySimple = getMullRuleKey(c.cardIDenum, ownHeroClass, enemyHeroClass, 0); //Simple key for Class enemy if (MulliganRules.ContainsKey(MullRuleKeySimple)) { hasRule = true; hasRuleClassSimple = true; } else { MullRuleKeySimple = getMullRuleKey(c.cardIDenum, ownHeroClass, HeroEnum.None, 0); //Simple key for ALL enemy if (MulliganRules.ContainsKey(MullRuleKeySimple)) { hasRule = true; } } if (hasRule) { string[] val = MulliganRules[MullRuleKeySimple].Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); allowedQuantitySimple = ((val[1] == "2") ? 2 : 1) * ((val[0] == "Hold") ? 1 : -1); } hasRule = false; string MullRuleKeyExtra = getMullRuleKey(c.cardIDenum, ownHeroClass, enemyHeroClass, 1); //Extra key for Class enemy if (MulliganRules.ContainsKey(MullRuleKeyExtra)) { hasRule = true; } else if (!hasRuleClassSimple) { MullRuleKeyExtra = getMullRuleKey(c.cardIDenum, ownHeroClass, HeroEnum.None, 1); //Extra key for ALL enemy if (MulliganRules.ContainsKey(MullRuleKeyExtra)) { hasRule = true; } } if (hasRule) { string[] val = MulliganRules[MullRuleKeyExtra].Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); allowedQuantityExtra = ((val[1] == "2") ? 2 : 1) * ((val[0] == "Hold") ? 1 : -1); } //superimpose Class rules to All rules bool useHold = false; bool useDiscard = false; bool useHoldRule = false; bool useDiscardRule = false; if (allowedQuantitySimple != 0 && allowedQuantitySimple != allowedQuantityExtra) { if (allowedQuantitySimple > 0) { useHold = true; } else { useDiscard = true; } } if (allowedQuantityExtra != 0) { if (allowedQuantityExtra < 0) { useDiscardRule = true; } else { useHoldRule = true; } } //apply the rules string[] MullRuleValueExtra = new string[3]; if (allowedQuantityExtra != 0) { MullRuleValueExtra = MulliganRules[MullRuleKeyExtra].Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); } if (useDiscardRule) { if (MullRuleValueExtra[2] != "/") { string[] addedCards = MullRuleValueExtra[2].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries); MulliganRulesManual.Clear(); foreach (string s in addedCards) { MulliganRulesManual.Add(CardDB.Instance.cardIdstringToEnum(s), ""); } foreach (CardIDEntity tmp in cards) { if (CardIDEntityC.entitiy == tmp.entitiy) { continue; } if (MulliganRulesManual.ContainsKey(tmp.id)) { CardIDEntityC.holdByRule = -2; CardIDEntityC.holdReason = joinSomeTxt("符合规则而弃掉: ", getClearRule(MullRuleKeyExtra)); break; } } } } else if (useDiscard) { CardIDEntityC.hold = -2; CardIDEntityC.holdReason = joinSomeTxt("符合规则而弃掉: ", getClearRule(MullRuleKeySimple)); } if (useHoldRule) { if (CardIDEntityC.holdByRule == 0) { string[] addedCards = MullRuleValueExtra[2].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries); MulliganRulesManual.Clear(); foreach (string s in addedCards) { MulliganRulesManual.Add(CardDB.Instance.cardIdstringToEnum(s), ""); } bool foundFreeCard = false; for (int i = 0; i < cards.Count; i++) { if (CardIDEntityC.entitiy == cards[i].entitiy) { continue; } if (MulliganRulesManual.ContainsKey(cards[i].id)) { CardIDEntityC.holdByRule = 2; CardIDEntityC.holdReason = joinSomeTxt("符合规则而保留: ", getClearRule(MullRuleKeyExtra)); if (cards[i].holdByRule < 0) { for (int j = i; j < cards.Count; j++) { if (CardIDEntityC.entitiy == cards[j].entitiy) { continue; } if (MulliganRulesManual.ContainsKey(cards[j].id)) { if (cards[j].holdByRule < 0) { continue; } foundFreeCard = true; cards[j].holdByRule = 2; cards[j].holdReason = joinSomeTxt("符合规则而保留: ", getClearRule(MullRuleKeyExtra)); break; } } if (!foundFreeCard) { foundFreeCard = true; cards[i].holdByRule = 2; cards[i].holdReason = joinSomeTxt("符合规则而保留: ", getClearRule(MullRuleKeyExtra)); break; } } else { foundFreeCard = true; cards[i].holdByRule = 2; cards[i].holdReason = joinSomeTxt("符合规则而保留: ", getClearRule(MullRuleKeyExtra)); } if (allowedQuantityExtra == 1) { foreach (CardIDEntity tmp in cards) { if (tmp.entitiy == CardIDEntityC.entitiy) { continue; } if (tmp.id == CardIDEntityC.id) { tmp.holdByRule = -2; tmp.holdReason = joinSomeTxt("符合规则而弃掉: ", getClearRule(MullRuleKeyExtra)); } } } } } } } if (useHold && CardIDEntityC.holdByRule != -2) { if (CardIDEntityC.hold == 0) { CardIDEntityC.hold = 2; CardIDEntityC.holdReason = joinSomeTxt("符合规则而保留: ", getClearRule(MullRuleKeySimple)); if (allowedQuantitySimple == 1) { CardIDEntityC.hold = 1; foreach (CardIDEntity tmp in cards) { if (tmp.entitiy == CardIDEntityC.entitiy) { continue; } if (tmp.id == CardIDEntityC.id) { tmp.hold = -2; tmp.holdReason = joinSomeTxt("discard Second card by rule: ", getClearRule(MullRuleKeySimple)); } } } } } } if (cards.Count == 5) { cards.Remove(Coin); } foreach (CardIDEntity c in cards) { if (c.holdByRule == 0) { if (c.hold == 0) { c.holdByRule = c.holdByManarule; } else { c.holdByRule = c.hold; } } } for (var i = 0; i < mulliganData.Cards.Count; i++) { mulliganData.Mulligans[i] = (cards[i].holdByRule > 0) ? false : true; Log.InfoFormat("[开局留牌] {0} {1}.", mulliganData.Cards[i].Entity.Name, cards[i].holdReason); } return(true); }
public float doallmoves(Playfield playf, bool isLethalCheck) { movegen.isLethalCheck = isLethalCheck; print = playf.print; this.isLethalCheck = isLethalCheck; enoughCalculations = false; botBase = Ai.Instance.botBase; this.posmoves.Clear(); this.twoturnfields.Clear(); this.addToPosmoves(playf); bool havedonesomething = true; List <Playfield> temp = new List <Playfield>(); int deep = 0; this.calculated = 0; Playfield bestold = null; bestoldval = -20000000; while (havedonesomething) { if (this.printNormalstuff) { Helpfunctions.Instance.logg("ailoop"); } GC.Collect(); temp.Clear(); temp.AddRange(this.posmoves); this.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 (this.totalboards > 0) { this.calculated += p.nextPlayfields.Count; } if (this.calculated <= this.totalboards) { this.posmoves.AddRange(p.nextPlayfields); p.nextPlayfields.Clear(); } //get the best Playfield float pVal = botBase.getPlayfieldValue(p); if (pVal > bestoldval) { bestoldval = pVal; bestold = p; } else if (pVal == bestoldval) { bestoldDuplicates.Add(p); } } if (isLethalCheck && bestoldval >= 10000) { this.posmoves.Clear(); } if (this.posmoves.Count > 0) { havedonesomething = 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); } cuttingposibilities(isLethalCheck); if (this.printNormalstuff) { Helpfunctions.Instance.logg("cut to len " + this.posmoves.Count); } deep++; temp.Clear(); if (this.calculated > this.totalboards) { enoughCalculations = true; } if (deep >= this.maxdeep) { enoughCalculations = true; } } if (this.dirtyTwoTurnSim > 0 && !twoturnfields.Contains(bestold)) { twoturnfields.Add(bestold); } this.posmoves.Clear(); this.posmoves.Add(bestold); this.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; } else if (posmoves[i].cardsPlayedThisTurn == bestplay.cardsPlayedThisTurn) { if (bestplay.optionsPlayedThisTurn > posmoves[i].optionsPlayedThisTurn) { continue; } else if (bestplay.optionsPlayedThisTurn == posmoves[i].optionsPlayedThisTurn && bestplay.enemyHero.Hp <= posmoves[i].enemyHero.Hp) { continue; } } bestplay = posmoves[i]; bestval = val; } this.bestmove = bestplay.getNextAction(); this.bestmoveValue = bestval; this.bestboard = new Playfield(bestplay); this.bestboard.guessingHeroHP = bestplay.guessingHeroHP; this.bestboard.value = bestplay.value; this.bestboard.hashcode = bestplay.hashcode; bestoldDuplicates.Clear(); return(bestval); } this.bestmove = null; this.bestmoveValue = -100000; this.bestboard = playf; return(-10000); }
public bool updateEverything(Behavior botbase, bool quequeActions, bool runExtern = false, bool passiveWait = false, bool nodruidchoice=true) { quequeActions = false; Helpfunctions.Instance.ErrorLog("updateEverything"); this.updateBehaveString(botbase); ownPlayerController = TritonHs.OurHero.ControllerId; // create hero + minion data getHerostuff(); //small fix for not knowing when to mulligan: if (ownMaxMana == 1 && currentMana == 1 && numMinionsPlayedThisTurn == 0 && cardsPlayedThisTurn == 0) { setnewLoggFile(); getHerostuff(); } getMinions(); getHandcards(nodruidchoice); getDecks(); correctSpellpower(); // send ai the data: Hrtprozis.Instance.clearAll(); Handmanager.Instance.clearAll(); Hrtprozis.Instance.setOwnPlayer(ownPlayerController); Handmanager.Instance.setOwnPlayer(ownPlayerController); this.numOptionPlayedThisTurn = 0; this.numOptionPlayedThisTurn += this.cardsPlayedThisTurn + this.ownHero.numAttacksThisTurn; foreach (Minion m in this.ownMinions) { if (m.Hp >= 1) this.numOptionPlayedThisTurn += m.numAttacksThisTurn; } Hrtprozis.Instance.updatePlayer(this.ownMaxMana, this.currentMana, this.cardsPlayedThisTurn, this.numMinionsPlayedThisTurn, this.numOptionPlayedThisTurn, this.ueberladung, ownHero.entitiyID, enemyHero.entitiyID, this.numberMinionsDiedThisTurn, this.ownCurrentOverload, this.enemyOverload, this.heroPowerUsesThisTurn,this.lockandload); Hrtprozis.Instance.setPlayereffects(this.ownDragonConsort, this.enemyDragonConsort, this.ownLoathebs, this.enemyLoathebs, this.ownMillhouse, this.enemyMillhouse, this.ownKirintor, this.ownPrepa, this.ownsabo, this.enemysabo, this.ownFenciCoaches, this.enemyCursedCardsInHand); Hrtprozis.Instance.updateSecretStuff(this.ownSecretList, this.enemySecretCount); Hrtprozis.Instance.updateOwnHero(this.ownHeroWeapon, this.heroWeaponAttack, this.heroWeaponDurability, this.heroname, this.heroAbility, this.ownAbilityisReady, this.ownHero, this.ownHeroPowerUsesThisGame); Hrtprozis.Instance.updateEnemyHero(this.enemyHeroWeapon, this.enemyWeaponAttack, this.enemyWeaponDurability, this.enemyHeroname, this.enemyMaxMana, this.enemyAbility, this.enemyHero, this.enemyHeroPowerUsesThisGame); Hrtprozis.Instance.updateMinions(this.ownMinions, this.enemyMinions); Handmanager.Instance.setHandcards(this.handCards, this.anzcards, this.enemyAnzCards, this.choiceCards); Hrtprozis.Instance.updateFatigueStats(this.ownDecksize, this.ownHeroFatigue, this.enemyDecksize, this.enemyHeroFatigue); Probabilitymaker.Instance.getEnemySecretGuesses(this.enemySecretList, Hrtprozis.Instance.heroNametoEnum(this.enemyHeroname)); //learnmode :D Playfield p = new Playfield(); if (lastpf != null) { if (lastpf.isEqualf(p)) { return false; } //board changed we update secrets! //if(Ai.Instance.nextMoveGuess!=null) Probabilitymaker.Instance.updateSecretList(Ai.Instance.nextMoveGuess.enemySecretList); Probabilitymaker.Instance.updateSecretList(p, lastpf); } lastpf = p; p = new Playfield();//secrets have updated :D // calculate stuff /*foreach (Handmanager.Handcard hc in p.owncards) { Helpfunctions.Instance.ErrorLog("hc playfield" + hc.manacost + " " + hc.getManaCost(p)); }*/ /*if (quequeActions) { // Detect errors in HearthRanger execution of our last set of actions and try to fix it so we don't // have to re-calculate the entire turn. Bot currentBot = (Bot)rangerbot; if (currentBot.numActionsSent > currentBot.numExecsReceived && !p.isEqualf(Ai.Instance.nextMoveGuess)) { Helpfunctions.Instance.ErrorLog("HR action queue did not complete!"); Helpfunctions.Instance.logg("board state out-of-sync due to action queue!"); if (Ai.Instance.restoreBestMoves(p, currentBot.queuedMoveGuesses)) { Helpfunctions.Instance.logg("rolled back state to replay queued actions."); Helpfunctions.Instance.ErrorLog("#queue-rollback#"); } } }*/ Helpfunctions.Instance.ErrorLog("calculating stuff... " + DateTime.Now.ToString("HH:mm:ss.ffff")); if (runExtern) { Helpfunctions.Instance.logg("recalc-check###########"); //p.printBoard(); //Ai.Instance.nextMoveGuess.printBoard(); if (p.isEqual(Ai.Instance.nextMoveGuess, true)) { printstuff(p, false); Ai.Instance.doNextCalcedMove(); } else { printstuff(p, true); readActionFile(passiveWait); } } else { using (TritonHs.Memory.ReleaseFrame(true)) { printstuff(p, false); Ai.Instance.dosomethingclever(botbase); } } Helpfunctions.Instance.ErrorLog("calculating ended! " + DateTime.Now.ToString("HH:mm:ss.ffff")); return true; }
private void updateBehaveString(Behavior botbase) { this.botbehave = "rush"; if (botbase is BehaviorControl) this.botbehave = "control"; this.botbehave += " " + Ai.Instance.maxwide; if (Ai.Instance.secondTurnAmount > 0) { if (Ai.Instance.nextMoveGuess.mana == -100) { Ai.Instance.updateTwoTurnSim(); } this.botbehave += " twoturnsim " + Ai.Instance.mainTurnSimulator.dirtyTwoTurnSim; } if (Ai.Instance.playaround) { this.botbehave += " playaround"; this.botbehave += " " + Ai.Instance.playaroundprob + " " + Ai.Instance.playaroundprob2; } if (Ai.Instance.nextTurnSimulator.doEnemySecondTurn) { this.botbehave += " simEnemy2Turn"; } }
//private void startEnemyTurnSim(Playfield p, bool simulateTwoTurns, bool print, bool playaround, int playaroundprob, int playaroundprob2) //{ // if (p.ownHero.Hp >= 1 && p.enemyHero.Hp>=1) // { // //simulateEnemysTurn(simulateTwoTurns, playaround, print, pprob, pprob2); // p.prepareNextTurn(p.isOwnTurn); // //Helpfunctions.Instance.ErrorLog("tc " + p.turnCounter); // Ai.Instance.enemySecondTurnSim[this.thread].simulateEnemysTurn(p, simulateTwoTurns, playaround, print, playaroundprob, playaroundprob2); // /* // if (p.turnCounter >= 2) // Ai.Instance.enemySecondTurnSim.simulateEnemysTurn(p, simulateTwoTurns, playaround, print, playaroundprob, playaroundprob2); // else // Ai.Instance.enemyTurnSim.simulateEnemysTurn(p, simulateTwoTurns, playaround, print, playaroundprob, playaroundprob2); // */ // } // p.complete = true; //} public float doallmoves(Playfield playf, bool isLethalCheck, bool print = false) { //todo only one time! this.doEnemySecondTurn = Settings.Instance.simEnemySecondTurn; int totalboards = Settings.Instance.nextTurnTotalBoards; int maxwide = Settings.Instance.nextTurnMaxWide; int maxdeep = Settings.Instance.nextTurnDeep; bool playaround = Settings.Instance.playarround; int playaroundprob = Settings.Instance.playaroundprob; int playaroundprob2 = Settings.Instance.playaroundprob2; //Helpfunctions.Instance.logg("NXTTRN" + playf.mana); if (botBase == null) { botBase = Ai.Instance.botBase; } bool test = false; this.posmoves.Clear(); this.addToPosmoves(playf, totalboards); bool havedonesomething = true; List <Playfield> temp = new List <Playfield>(); int deep = 0; //Helpfunctions.Instance.logg("NXTTRN" + playf.mana + " " + posmoves.Count); this.calculated = 0; Playfield bestold = null; while (havedonesomething) { //if (this.printNormalstuff) Helpfunctions.Instance.logg("ailoop"); //GC.Collect(); temp.Clear(); temp.AddRange(this.posmoves); havedonesomething = false; float bestoldval = -20000000; foreach (Playfield p in temp) { if (p.complete || p.ownHero.Hp <= 0) { continue; } List <Action> actions = movegen.getMoveList(p, isLethalCheck, usePenalityManager, useCutingTargets); foreach (Action a in actions) { havedonesomething = true; Playfield pf = new Playfield(p); pf.doAction(a); addToPosmoves(pf, totalboards); } if (isLethalCheck) { p.complete = true; } else { p.sEnemTurn = this.doEnemySecondTurn; p.endTurn(this.simulateSecondTurn, playaround, false, playaroundprob, playaroundprob2); //this.startEnemyTurnSim(p, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2); } //sort stupid stuff ouf if (botBase.getPlayfieldValue(p) > bestoldval) { bestoldval = botBase.getPlayfieldValue(p); bestold = p; } if (!test) { posmoves.Remove(p); } if (this.calculated > 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(maxwide); } //if (this.printNormalstuff) Helpfunctions.Instance.logg("cut to len " + this.posmoves.Count); //Helpfunctions.Instance.loggonoff(false); deep++; if (this.calculated > totalboards) { break; } if (deep >= maxdeep) { break; //remove this? } } foreach (Playfield p in posmoves)//temp { if (!p.complete) { if (isLethalCheck) { p.complete = true; } else { p.sEnemTurn = this.doEnemySecondTurn; p.endTurn(this.simulateSecondTurn, playaround, false, playaroundprob, playaroundprob2); //this.startEnemyTurnSim(p, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2); } } } // Helpfunctions.Instance.logg("find best "); if (posmoves.Count >= 1) { float bestval = int.MinValue; int bestanzactions = 1000; Playfield bestplay = posmoves[0]; //temp[0] foreach (Playfield p in posmoves) //temp { float val = botBase.getPlayfieldValue(p); if (bestval <= val) { if (bestval == val && bestanzactions < p.playactions.Count) { continue; } bestplay = p; bestval = val; bestanzactions = p.playactions.Count; } } this.bestboard = new Playfield(bestplay); if (print) { Helpfunctions.Instance.ErrorLog("best board after your second turn (value included enemy second turn)----------"); bestplay.printBoard(); bestplay.value = int.MinValue; //bestplay.sEnemTurn = this.doEnemySecondTurn; //Ai.Instance.enemySecondTurnSim[this.thread].simulateEnemysTurn(bestplay, false, playaround, false, playaroundprob, playaroundprob2); //Ai.Instance.enemySecondTurnSim.simulateEnemysTurn(bestplay, false, false, true, 100, 100); //dont play arround in enemys second turn } 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); }
/// <summary> The routine start callback. Do any initialization here. </summary> public void Start() { GameEventManager.NewGame += GameEventManagerOnNewGame; GameEventManager.GameOver += GameEventManagerOnGameOver; GameEventManager.QuestUpdate += GameEventManagerOnQuestUpdate; GameEventManager.ArenaRewards += GameEventManagerOnArenaRewards; foreach (var tuple in _mulliganRules) { Exception ex; if ( !VerifyCondition(tuple.Item1, new List<string> {"mulliganData"}, out ex)) { Log.ErrorFormat("[Start] There is an error with a mulligan execution condition [{1}]: {0}.", ex, tuple.Item1); BotManager.Stop(); } if ( !VerifyCondition(tuple.Item2, new List<string> {"mulliganData", "card"}, out ex)) { Log.ErrorFormat("[Start] There is an error with a mulligan card condition [{1}]: {0}.", ex, tuple.Item2); BotManager.Stop(); } } //set behaviour if (DefaultRoutineSettings.Instance.BotBehaviour == TAG_MODE.CONTROL) { behave = new BehaviorControl(); } if (DefaultRoutineSettings.Instance.BotBehaviour == TAG_MODE.RUSH) { behave = new BehaviorRush(); } if (DefaultRoutineSettings.Instance.BotBehaviour == TAG_MODE.FACE) { behave = new BehaviorFace(); } if (DefaultRoutineSettings.Instance.BotBehaviour == TAG_MODE.TEST) { behave = new BehaviorMana(); } //Helpfunctions.Instance.ErrorLog("start"); }
public float 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.twoturnfields.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; Helpfunctions.Instance.logg("Calculating... ");// while (havedonesomething) { //if (this.printNormalstuff)Helpfunctions.Instance.logg("ailoop"); GC.Collect(); temp.Clear(); temp.AddRange(this.posmoves); havedonesomething = false; Playfield bestold = null; float bestoldval = -20000000; foreach (Playfield p in temp) { if (p.complete || p.ownHero.Hp <= 0) { continue; } //gernerate actions and play them! List <Action> actions = movegen.getMoveList(p, isLethalCheck, usePenalityManager, useCutingTargets); foreach (Action a in actions) { //if (deep == 0 && a.actionType == actionEnum.attackWithMinion) Helpfunctions.Instance.ErrorLog("play " + a.own.entitiyID + " -> " + a.target.entitiyID); havedonesomething = true; Playfield pf = new Playfield(p); pf.doAction(a); /*if (deep == 1) * { * Helpfunctions.Instance.ErrorLog("do action..."); * a.print(false); * pf.printBoard(); * }*/ addToPosmoves(pf); } // end the turn of the current board (only if its not a lethalcheck) if (isLethalCheck) { p.complete = true; } else { //end turn of enemy p.endTurn(this.simulateSecondTurn, this.playaround, false, this.playaroundprob, this.playaroundprob2); //simulate the enemys response this.startEnemyTurnSim(p, this.simulateSecondTurn, false); } //sort stupid stuff ouf float newPlayfieldValue = botBase.getPlayfieldValue(p); if (newPlayfieldValue > bestoldval) { bestoldval = newPlayfieldValue; 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); this.startEnemyTurnSim(p, this.simulateSecondTurn, false); } } } // search the best play........................................................... //do dirtytwoturnsim first :D if (!isLethalCheck) { doDirtyTwoTurnsim(); } if (!isLethalCheck) { this.dirtyTwoTurnSim /= 2; } // Helpfunctions.Instance.logg("find best "); if (posmoves.Count >= 1) { float bestval = int.MinValue; int bestanzactions = 1000; Playfield bestplay = posmoves[0]; //temp[0] foreach (Playfield p in posmoves) //temp { float 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); }
public Bot() { behave = this.getBotBehave(); OnVictory = HandleWining; OnLost = HandleLosing; OnBattleStateUpdate = HandleOnBattleStateUpdate; OnMulliganStateUpdate = HandleBattleMulliganPhase; starttime = DateTime.Now; bool concede = false; bool writeToSingleFile = false; try { this.learnmode = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.wwuaid") == "true") ? true : false; if (this.learnmode) { Helpfunctions.Instance.ErrorLog("Learn mode is ON"); } } catch { Helpfunctions.Instance.ErrorLog("a wild error occurrs! cant read the settings..."); } try { concede = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.autoconcede") == "true") ? true : false; writeToSingleFile = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.singleLog") == "true") ? true : false; } catch { Helpfunctions.Instance.ErrorLog("a wild error occurrs! cant read the settings..."); } try { this.concedeLvl = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.concedelvl"))); if (this.concedeLvl >= 20) this.concedeLvl = 20; if (concede) { Helpfunctions.Instance.ErrorLog("concede till rank " + concedeLvl); } } catch { Helpfunctions.Instance.ErrorLog("cant read your concede-Lvl"); } try { this.stopAfterWins = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.stopwin"))); if (this.stopAfterWins <= 0) this.stopAfterWins = 10000; Helpfunctions.Instance.ErrorLog("stop after " + stopAfterWins + " wins"); } catch { Helpfunctions.Instance.ErrorLog("cant read stop after # of wins"); } try { this.enemyConcede = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.enemyconcede") == "true") ? true : false; if (this.enemyConcede) Helpfunctions.Instance.ErrorLog("concede whether enemy has lethal"); } catch { Helpfunctions.Instance.ErrorLog("cant read enemy concede"); } this.sf = new Silverfish(writeToSingleFile); CardDB cdb = CardDB.Instance; if (cdb.installedWrong) return; Mulligan.Instance.setAutoConcede(concede); sf.setnewLoggFile(); try { int enfacehp = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.enemyfacehp"))); Helpfunctions.Instance.ErrorLog("set enemy-face-hp to: " + enfacehp); ComboBreaker.Instance.attackFaceHP = enfacehp; } catch { Helpfunctions.Instance.ErrorLog("error in reading enemy-face-hp"); } try { int mxwde = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.maxwide"))); Ai.Instance.setMaxWide(mxwde); if (mxwde != 3000) { Ai.Instance.setMaxWide(mxwde); Helpfunctions.Instance.ErrorLog("set maxwide to: " + mxwde); } } catch { Helpfunctions.Instance.ErrorLog("error in reading Maxwide from settings, please recheck the entry"); } try { bool twots = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.simulateTwoTurns") == "true") ? true : false; Ai.Instance.setTwoTurnSimulation(twots); if (twots) { Ai.Instance.setTwoTurnSimulation(twots); Helpfunctions.Instance.ErrorLog("activated two turn simulation"); } } catch { Helpfunctions.Instance.ErrorLog("error in reading two-turn-simulation from settings"); } try { bool playaround = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.playAround") == "true") ? true : false; int playaroundprob = Convert.ToInt32(HRSettings.Get.ReadSetting("silverfish.xml", "uai.playAroundProb")); if (playaroundprob > 100) playaroundprob = 100; if (playaroundprob < 0) playaroundprob = 0; int playaroundprob2 = Convert.ToInt32(HRSettings.Get.ReadSetting("silverfish.xml", "uai.playAroundProb2")); if (playaroundprob2 < playaroundprob) playaroundprob2 = playaroundprob; if (playaroundprob2 > 100) playaroundprob2 = 100; if (playaroundprob2 < 0) playaroundprob2 = 0; if (playaround) { Ai.Instance.setPlayAround(playaround,playaroundprob, playaroundprob2); Helpfunctions.Instance.ErrorLog("activated playaround"); } } catch { Helpfunctions.Instance.ErrorLog("error in reading play around settings"); } Helpfunctions.Instance.ErrorLog("write to single log file is: " + writeToSingleFile); bool teststuff = false; bool printstuff = false; try { printstuff = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.longteststuff") == "true") ? true : false; teststuff = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.teststuff") == "true") ? true : false; } catch { Helpfunctions.Instance.ErrorLog("something went wrong with simulating stuff!"); } Helpfunctions.Instance.ErrorLog("----------------------------"); Helpfunctions.Instance.ErrorLog("you are running uai V"+sf.versionnumber); Helpfunctions.Instance.ErrorLog("----------------------------"); if (teststuff) { Ai.Instance.autoTester(behave, printstuff); } writeSettings(); }
public Bot() { behave = this.getBotBehave(); OnVictory = HandleWining; OnLost = HandleLosing; OnBattleStateUpdate = HandleOnBattleStateUpdate; OnMulliganStateUpdate = HandleBattleMulliganPhase; starttime = DateTime.Now; bool concede = false; bool writeToSingleFile = false; try { this.learnmode = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.wwuaid") == "true") ? true : false; if (this.learnmode) { Helpfunctions.Instance.ErrorLog("Learn mode is ON"); } } catch { Helpfunctions.Instance.ErrorLog("a wild error occurrs! cant read the settings..."); } try { concede = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.autoconcede") == "true") ? true : false; writeToSingleFile = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.singleLog") == "true") ? true : false; } catch { Helpfunctions.Instance.ErrorLog("a wild error occurrs! cant read the settings..."); } try { this.concedeLvl = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.concedelvl"))); if (this.concedeLvl >= 20) this.concedeLvl = 20; if (concede) { Helpfunctions.Instance.ErrorLog("concede till rank " + concedeLvl); } } catch { Helpfunctions.Instance.ErrorLog("cant read your concede-Lvl"); } /*try { this.stopAfterWins = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.stopwin"))); if (this.stopAfterWins <= 0) this.stopAfterWins = 10000; Helpfunctions.Instance.ErrorLog("stop after " + stopAfterWins + " wins"); } catch { Helpfunctions.Instance.ErrorLog("cant read stop after # of wins"); }*/ try { this.enemyConcede = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.enemyconcede") == "true") ? true : false; if (this.enemyConcede) Helpfunctions.Instance.ErrorLog("concede whether enemy has lethal"); } catch { Helpfunctions.Instance.ErrorLog("cant read enemy concede"); } this.sf = new Silverfish(writeToSingleFile); CardDB cdb = CardDB.Instance; if (cdb.installedWrong) return; Mulligan.Instance.setAutoConcede(concede); sf.setnewLoggFile(); try { int enfacehp = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.enemyfacehp"))); Helpfunctions.Instance.ErrorLog("set enemy-face-hp to: " + enfacehp); ComboBreaker.Instance.attackFaceHP = enfacehp; } catch { Helpfunctions.Instance.ErrorLog("error in reading enemy-face-hp"); } try { int mxwde = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.maxwide"))); if (mxwde != 3000) { Ai.Instance.setMaxWide(mxwde); Helpfunctions.Instance.ErrorLog("set maxwide to: " + mxwde); } } catch { Helpfunctions.Instance.ErrorLog("error in reading Maxwide from settings, please recheck the entry"); } int twotsamount =0; try { //bool twots = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.simulateTwoTurns") == "true") ? true : false; twotsamount = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.simulateTwoTurnCounter"))); if (twotsamount < 0) twotsamount = 0; Ai.Instance.setTwoTurnSimulation(false, twotsamount); Helpfunctions.Instance.ErrorLog("calculate the second turn of the " + twotsamount + " best boards"); } catch { Helpfunctions.Instance.ErrorLog("error in reading two-turn-simulation from settings"); } if (twotsamount >= 1) { try { bool enemySecondTurnSim = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.simulateEnemyOnSecondTurn") == "true") ? true : false; Ai.Instance.nextTurnSimulator.setEnemyTurnsim(enemySecondTurnSim); if(enemySecondTurnSim) Helpfunctions.Instance.ErrorLog("simulates the enemy turn on your second turn"); } catch { Helpfunctions.Instance.ErrorLog("error in reading enemys-two-turn-simulation from settings"); } } try { bool playaround = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.playAround") == "true") ? true : false; int playaroundprob = Convert.ToInt32(HRSettings.Get.ReadSetting("silverfish.xml", "uai.playAroundProb")); if (playaroundprob > 100) playaroundprob = 100; if (playaroundprob < 0) playaroundprob = 0; int playaroundprob2 = Convert.ToInt32(HRSettings.Get.ReadSetting("silverfish.xml", "uai.playAroundProb2")); if (playaroundprob2 < playaroundprob) playaroundprob2 = playaroundprob; if (playaroundprob2 > 100) playaroundprob2 = 100; if (playaroundprob2 < 0) playaroundprob2 = 0; if (playaround) { Ai.Instance.setPlayAround(playaround, playaroundprob, playaroundprob2); Helpfunctions.Instance.ErrorLog("activated playaround"); } } catch { Helpfunctions.Instance.ErrorLog("error in reading play around settings"); } Helpfunctions.Instance.ErrorLog("write to single log file is: " + writeToSingleFile); bool teststuff = false; bool printstuff = false; try { printstuff = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.longteststuff") == "true") ? true : false; teststuff = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.teststuff") == "true") ? true : false; } catch { Helpfunctions.Instance.ErrorLog("something went wrong with simulating stuff!"); } Helpfunctions.Instance.ErrorLog("----------------------------"); Helpfunctions.Instance.ErrorLog("you are running uai V" + sf.versionnumber); Helpfunctions.Instance.ErrorLog("----------------------------"); try { this.useExternalProcess = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.extern") == "true") ? true : false; } catch { Helpfunctions.Instance.ErrorLog("rand read the external-process setting!"); } if (this.useExternalProcess) Helpfunctions.Instance.ErrorLog("YOU USE SILVER.EXE FOR CALCULATION, MAKE SURE YOU STARTED IT!"); if (this.useExternalProcess) Helpfunctions.Instance.ErrorLog("SILVER.EXE IS LOCATED IN: " + Settings.Instance.path); if (teststuff) { Ai.Instance.autoTester(printstuff); } writeSettings(); }
public bool updateEverything(Behavior botbase) { this.botbehave = "rush"; if (botbase is BehaviorControl) this.botbehave = "control"; if (Ai.Instance.secondturnsim) this.botbehave += " twoturnsim"; if (Ai.Instance.playaround) this.botbehave += " playaround"; HRPlayer ownPlayer = HRPlayer.GetLocalPlayer(); HRPlayer enemyPlayer = HRPlayer.GetEnemyPlayer(); ownPlayerController = ownPlayer.GetHero().GetControllerId();//ownPlayer.GetHero().GetControllerId() // create hero + minion data getHerostuff(); getMinions(); getHandcards(); getDecks(); // send ai the data: Hrtprozis.Instance.clearAll(); Handmanager.Instance.clearAll(); Hrtprozis.Instance.setOwnPlayer(ownPlayerController); Handmanager.Instance.setOwnPlayer(ownPlayerController); Hrtprozis.Instance.updatePlayer(this.ownMaxMana, this.currentMana, this.cardsPlayedThisTurn, this.numMinionsPlayedThisTurn, this.ueberladung, ownPlayer.GetHero().GetEntityId(), enemyPlayer.GetHero().GetEntityId()); Hrtprozis.Instance.updateSecretStuff(this.ownSecretList, this.enemySecretCount); Hrtprozis.Instance.updateOwnHero(this.ownHeroWeapon, this.heroWeaponAttack, this.heroWeaponDurability, this.heroImmuneToDamageWhileAttacking, this.heroAtk, this.heroHp, this.heroDefence, this.heroname, this.ownheroisread, this.herofrozen, this.heroAbility, this.ownAbilityisReady, this.heroNumAttacksThisTurn, this.heroHasWindfury, this.heroImmune); Hrtprozis.Instance.updateEnemyHero(this.enemyHeroWeapon, this.enemyWeaponAttack, this.enemyWeaponDurability, this.enemyAtk, this.enemyHp, this.enemyDefence, this.enemyHeroname, this.enemyfrozen, this.enemyAbility, this.enemyHeroImmune, this.enemyMaxMana); Hrtprozis.Instance.updateMinions(this.ownMinions, this.enemyMinions); Handmanager.Instance.setHandcards(this.handCards, this.anzcards, this.enemyAnzCards); Hrtprozis.Instance.updateFatigueStats(this.ownDecksize, this.ownHeroFatigue, this.enemyDecksize, this.enemyHeroFatigue); Playfield p = new Playfield(); if (lastpf != null) { if (lastpf.isEqualf(p)) { return false; } lastpf = p; } else { lastpf = p; } // print data this.printstuff(); Hrtprozis.Instance.printHero(); Hrtprozis.Instance.printOwnMinions(); Hrtprozis.Instance.printEnemyMinions(); Handmanager.Instance.printcards(); // calculate stuff Helpfunctions.Instance.ErrorLog("calculating stuff... " + DateTime.Now.ToString("HH:mm:ss.ffff")); Ai.Instance.dosomethingclever(botbase); Helpfunctions.Instance.ErrorLog("calculating ended! " + DateTime.Now.ToString("HH:mm:ss.ffff")); return true; }
public Bot() { behave = this.getBotBehave(); OnVictory = HandleWining; OnLost = HandleLosing; OnBattleStateUpdate = HandleOnBattleStateUpdate; OnMulliganStateUpdate = HandleBattleMulliganPhase; starttime = DateTime.Now; bool concede = false; bool writeToSingleFile = false; try { this.learnmode = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.wwuaid") == "true") ? true : false; if (this.learnmode) { Helpfunctions.Instance.ErrorLog("Learn mode is ON"); } } catch { Helpfunctions.Instance.ErrorLog("a wild error occurrs! cant read the settings..."); } try { concede = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.autoconcede") == "true") ? true : false; writeToSingleFile = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.singleLog") == "true") ? true : false; } catch { Helpfunctions.Instance.ErrorLog("a wild error occurrs! cant read the settings..."); } try { this.concedeLvl = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.concedelvl"))); if (this.concedeLvl >= 20) { this.concedeLvl = 20; } if (concede) { Helpfunctions.Instance.ErrorLog("concede till rank " + concedeLvl); } } catch { Helpfunctions.Instance.ErrorLog("cant read your concede-Lvl"); } try { this.stopAfterWins = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.stopwin"))); if (this.stopAfterWins <= 0) { this.stopAfterWins = 10000; } Helpfunctions.Instance.ErrorLog("stop after " + stopAfterWins + " wins"); } catch { Helpfunctions.Instance.ErrorLog("cant read stop after # of wins"); } try { this.enemyConcede = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.enemyconcede") == "true") ? true : false; if (this.enemyConcede) { Helpfunctions.Instance.ErrorLog("concede whether enemy has lethal"); } } catch { Helpfunctions.Instance.ErrorLog("cant read enemy concede"); } this.sf = new Silverfish(writeToSingleFile); CardDB cdb = CardDB.Instance; if (cdb.installedWrong) { return; } Mulligan.Instance.setAutoConcede(concede); sf.setnewLoggFile(); try { int enfacehp = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.enemyfacehp"))); Helpfunctions.Instance.ErrorLog("set enemy-face-hp to: " + enfacehp); ComboBreaker.Instance.attackFaceHP = enfacehp; } catch { Helpfunctions.Instance.ErrorLog("error in reading enemy-face-hp"); } try { int mxwde = Convert.ToInt32((HRSettings.Get.ReadSetting("silverfish.xml", "uai.maxwide"))); Ai.Instance.setMaxWide(mxwde); if (mxwde != 3000) { Ai.Instance.setMaxWide(mxwde); Helpfunctions.Instance.ErrorLog("set maxwide to: " + mxwde); } } catch { Helpfunctions.Instance.ErrorLog("error in reading Maxwide from settings, please recheck the entry"); } try { bool twots = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.simulateTwoTurns") == "true") ? true : false; Ai.Instance.setTwoTurnSimulation(twots); if (twots) { Ai.Instance.setTwoTurnSimulation(twots); Helpfunctions.Instance.ErrorLog("activated two turn simulation"); } } catch { Helpfunctions.Instance.ErrorLog("error in reading two-turn-simulation from settings"); } try { bool playaround = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.playAround") == "true") ? true : false; int playaroundprob = Convert.ToInt32(HRSettings.Get.ReadSetting("silverfish.xml", "uai.playAroundProb")); if (playaroundprob > 100) { playaroundprob = 100; } if (playaroundprob < 0) { playaroundprob = 0; } int playaroundprob2 = Convert.ToInt32(HRSettings.Get.ReadSetting("silverfish.xml", "uai.playAroundProb2")); if (playaroundprob2 < playaroundprob) { playaroundprob2 = playaroundprob; } if (playaroundprob2 > 100) { playaroundprob2 = 100; } if (playaroundprob2 < 0) { playaroundprob2 = 0; } if (playaround) { Ai.Instance.setPlayAround(playaround, playaroundprob, playaroundprob2); Helpfunctions.Instance.ErrorLog("activated playaround"); } } catch { Helpfunctions.Instance.ErrorLog("error in reading play around settings"); } Helpfunctions.Instance.ErrorLog("write to single log file is: " + writeToSingleFile); bool teststuff = false; bool printstuff = false; try { printstuff = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.longteststuff") == "true") ? true : false; teststuff = (HRSettings.Get.ReadSetting("silverfish.xml", "uai.teststuff") == "true") ? true : false; } catch { Helpfunctions.Instance.ErrorLog("something went wrong with simulating stuff!"); } Helpfunctions.Instance.ErrorLog("----------------------------"); Helpfunctions.Instance.ErrorLog("you are running uai V" + sf.versionnumber); Helpfunctions.Instance.ErrorLog("----------------------------"); if (teststuff) { Ai.Instance.autoTester(behave, printstuff); } writeSettings(); }
public float doallmoves(Playfield playf, bool isLethalCheck, bool print = false) { //todo only one time! this.doEnemySecondTurn = sf.Settings.simEnemySecondTurn; int totalboards = sf.Settings.nextTurnTotalBoards; int maxwide = sf.Settings.nextTurnMaxWide; int maxdeep = sf.Settings.nextTurnDeep; bool playaround = sf.Settings.playarround; int playaroundprob = sf.Settings.playaroundprob; int playaroundprob2 = sf.Settings.playaroundprob2; //Helpfunctions.Instance.logg("NXTTRN" + playf.mana); if (botBase == null) botBase = sf.Ai.botBase; bool test = false; this.posmoves.Clear(); this.addToPosmoves(playf, totalboards); 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; float bestoldval = -20000000; foreach (Playfield p in temp) { if (p.complete || p.ownHero.Hp <= 0) { continue; } List<Action> actions = sf.Movegenerator.getMoveList(p, isLethalCheck, usePenalityManager, useCutingTargets); foreach (Action a in actions) { havedonesomething = true; Playfield pf = new Playfield(p); pf.doAction(a); addToPosmoves(pf, totalboards); } if (isLethalCheck) { p.complete = true; } else { p.sEnemTurn = this.doEnemySecondTurn; p.endTurn(this.simulateSecondTurn, playaround, false, playaroundprob, playaroundprob2); this.startEnemyTurnSim(p, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2); } //sort stupid stuff ouf if (botBase.getPlayfieldValue(p) > bestoldval) { bestoldval = botBase.getPlayfieldValue(p); bestold = p; } if (!test) { posmoves.Remove(p); } if (this.calculated > 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(maxwide); } //if (this.printNormalstuff) Helpfunctions.Instance.logg("cut to len " + this.posmoves.Count); //Helpfunctions.Instance.loggonoff(false); deep++; if (this.calculated > totalboards) break; if (deep >= maxdeep) break;//remove this? } foreach (Playfield p in posmoves)//temp { if (!p.complete) { if (isLethalCheck) { p.complete = true; } else { p.sEnemTurn = this.doEnemySecondTurn; p.endTurn(this.simulateSecondTurn, playaround, false, playaroundprob, playaroundprob2); this.startEnemyTurnSim(p, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2); } } } // Helpfunctions.Instance.logg("find best "); if (posmoves.Count >= 1) { float bestval = int.MinValue; int bestanzactions = 1000; Playfield bestplay = posmoves[0];//temp[0] foreach (Playfield p in posmoves)//temp { float val = botBase.getPlayfieldValue(p); if (bestval <= val) { if (bestval == val && bestanzactions < p.playactions.Count) continue; bestplay = p; bestval = val; bestanzactions = p.playactions.Count; } } this.bestboard = new Playfield(bestplay); if (print) { sf.Helpfunctions.ErrorLog("best board after your second turn (value included enemy second turn)----------"); bestplay.printBoard(); bestplay.value = int.MinValue; bestplay.sEnemTurn = this.doEnemySecondTurn; sf.Ai.enemySecondTurnSim[this.thread].simulateEnemysTurn(bestplay, false, playaround, false, playaroundprob, playaroundprob2); //sf.Ai.enemySecondTurnSim.simulateEnemysTurn(bestplay, false, false, true, 100, 100); //dont play arround in enemys second turn } 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; }
public Behavior readSettings() //takes same path as carddb { string[] lines = new string[] { }; string path = this.path; string cleanpath = "Silverfish" + System.IO.Path.DirectorySeparatorChar; string datapath = path + "Data" + System.IO.Path.DirectorySeparatorChar; string cleandatapath = cleanpath + "Data" + System.IO.Path.DirectorySeparatorChar; string classpath = datapath + ownClass + System.IO.Path.DirectorySeparatorChar; string cleanclasspath = cleandatapath + ownClass + System.IO.Path.DirectorySeparatorChar; string deckpath = classpath + deckName + System.IO.Path.DirectorySeparatorChar; string cleandeckpath = cleanclasspath + deckName + System.IO.Path.DirectorySeparatorChar; string enemyfilestring = "settings-" + enemyClass + ".txt"; const string filestring = "settings.txt"; bool enemysettings = false; // if we have a deckName then we have a real ownClass too, not the default "druid" if (deckName != "" && System.IO.File.Exists(deckpath + enemyfilestring)) { enemysettings = true; path = deckpath; cleanPath = cleandeckpath + enemyfilestring; } else if (deckName != "" && System.IO.File.Exists(deckpath + filestring)) { path = deckpath; cleanPath = cleandeckpath + filestring; } else if (deckName != "" && System.IO.File.Exists(classpath + enemyfilestring)) { enemysettings = true; path = classpath; cleanPath = cleanclasspath + enemyfilestring; } else if (deckName != "" && System.IO.File.Exists(classpath + filestring)) { path = classpath; cleanPath = cleanclasspath + filestring; } else if (deckName != "" && System.IO.File.Exists(datapath + enemyfilestring)) { enemysettings = true; path = datapath; cleanPath = cleandatapath + enemyfilestring; } else if (deckName != "" && System.IO.File.Exists(datapath + filestring)) { path = datapath; cleanPath = cleandatapath + filestring; } else if (System.IO.File.Exists(path + enemyfilestring)) { enemysettings = true; cleanPath = cleanpath + enemyfilestring; } else if (System.IO.File.Exists(path + filestring)) { cleanPath = cleanpath + filestring; } else { Helpfunctions.Instance.logg("[Settings] cant find base settings.txt, using default settings"); return(setDefaultSettings()); } Helpfunctions.Instance.ErrorLog("[Settings] read " + cleanPath); const string readerror = " read error. Continuing without user-defined rules."; if (enemysettings) { try { lines = System.IO.File.ReadAllLines(path + enemyfilestring); } catch { Helpfunctions.Instance.ErrorLog(enemyfilestring + readerror); return(setDefaultSettings()); } } else { try { lines = System.IO.File.ReadAllLines(path + filestring); } catch { Helpfunctions.Instance.logg(filestring + readerror); return(setDefaultSettings()); } } foreach (string ss in lines) { string s = ss.Replace(" ", ""); if (s.Contains(";")) { s = s.Split(';')[0]; } if (s.Contains("#")) { s = s.Split('#')[0]; } if (s.Contains("//")) { s = s.Split(new string[] { "//" }, StringSplitOptions.RemoveEmptyEntries)[0]; } if (s.Contains(",")) { s = s.Split(',')[0]; } if (s == "" || s == " ") { continue; } s = s.ToLower(); const string ignoring = "[Settings] ignoring the setting "; string searchword = "maxwide="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.maxwide = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "twotsamount="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.twotsamount = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "simenemysecondturn="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.simEnemySecondTurn = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "enfacehp="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.enfacehp = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "playarround="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.playarround = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "playaroundprob="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.playaroundprob = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "playaroundprob2="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.playaroundprob2 = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "enemyturnmaxwide="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.enemyTurnMaxWide = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "enemyturnmaxwidesecondtime="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.enemyTurnMaxWideSecondTime = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "enemysecondturnmaxwide="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.enemySecondTurnMaxWide = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "nextturndeep="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.nextTurnDeep = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "nextturnmaxwide="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.nextTurnMaxWide = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "nextturntotalboards="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.nextTurnTotalBoards = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "usesecretsplayarround="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.useSecretsPlayArround = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "alpha="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.alpha = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "simulateplacement="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.simulatePlacement = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "useexternalprocess="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.useExternalProcess = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "passivewaiting="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.passiveWaiting = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "behave="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); if (a.StartsWith("control")) { behave = new BehaviorControl(); } if (a.StartsWith("rush")) { behave = new BehaviorRush(); } if (a.StartsWith("mana")) { behave = new BehaviorMana(); } if (a.StartsWith("face")) { behave = new BehaviorFace(); } if (a.StartsWith("aggrowarlock")) { behave = new BehaviorAggroWarlock(); } if (a.StartsWith("aggroshaman")) { behave = new BehaviorAggroshaman(); } } searchword = "concedeonbadboard="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.enemyConcede = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "concedeonboardvalue="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.enemyConcedeValue = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "speed="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.speedy = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "usenetwork="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.useNetwork = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "netaddress="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.netAddress = a; } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "tcpport="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.tcpPort = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } //always enabled now so ignore user setting /* * searchword = "logbuffer="; * if (s.StartsWith(searchword)) * { * string a = s.Replace(searchword, ""); * try * { * this.logBuffer = Convert.ToInt32(a); * } * catch * { * Helpfunctions.Instance.ErrorLog(ignoring + searchword); * } * } */ searchword = "secretstandard ="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.SecretStandard = Convert.ToBoolean(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } searchword = "enemyherovaluemultiply="; if (s.StartsWith(searchword)) { string a = s.Replace(searchword, ""); try { this.enemyherovaluemultiply = Convert.ToInt32(a); } catch { Helpfunctions.Instance.ErrorLog(ignoring + searchword); } } } //foreach ended---------- applySettings(); return(behave); }
private void updateBehaveString(Behavior botbase) { this.botbehave = "rush"; if (botbase is BehaviorControl) this.botbehave = "control"; if (botbase is BehaviorMana) this.botbehave = "mana"; this.botbehave += " " + Ai.Instance.maxwide; this.botbehave += " face " + ComboBreaker.Instance.attackFaceHP; if (Settings.Instance.secondTurnAmount > 0) { if (Ai.Instance.nextMoveGuess.mana == -100) { Ai.Instance.updateTwoTurnSim(); } this.botbehave += " twoturnsim " + Settings.Instance.secondTurnAmount + " ntss " + Settings.Instance.nextTurnDeep + " " + Settings.Instance.nextTurnMaxWide + " " + Settings.Instance.nextTurnTotalBoards; } if (Settings.Instance.playarround) { this.botbehave += " playaround"; this.botbehave += " " + Settings.Instance.playaroundprob + " " + Settings.Instance.playaroundprob2; } this.botbehave += " ets " + Settings.Instance.enemyTurnMaxWide; if (Settings.Instance.simEnemySecondTurn) { this.botbehave += " ets2 " + Settings.Instance.enemyTurnMaxWideSecondTime; this.botbehave += " ents " + Settings.Instance.enemySecondTurnMaxWide; } if (Settings.Instance.useSecretsPlayArround) { this.botbehave += " secret"; } if (Settings.Instance.secondweight != 0.5f) { this.botbehave += " weight " + (int)(Settings.Instance.secondweight*100f); } if (Settings.Instance.simulatePlacement) { this.botbehave += " plcmnt"; } }
public float doallmoves(Playfield playf, bool isLethalCheck) { HRSim.Helpfunctions.Instance.startTimer(); List<Action> actions = null; if (botBase == null) botBase = sf.Ai.botBase; bool test = false; this.posmoves.Clear(); this.twoturnfields.Clear(); this.addToPosmoves(playf); bool havedonesomething = true; List<Playfield> temp = new List<Playfield>(); int deep = 0; //sf.helpfunctions.logg("NXTTRN" + playf.mana + " " + posmoves.Count); this.calculated = 0; //debug //int loopNumber = 0; while (havedonesomething) { //loopNumber++; if (this.printNormalstuff) sf.Helpfunctions.logg("ailoop"); GC.Collect(); temp.Clear(); temp.AddRange(this.posmoves); havedonesomething = false; Playfield bestold = null; float bestoldval = -20000000; foreach (Playfield p in temp) { if (p.complete || p.ownHero.Hp <= 0) { continue; } //gernerate actions and play them! actions = sf.Movegenerator.getMoveList(p, isLethalCheck, usePenalityManager, useCutingTargets); Playfield ppTest = new Playfield(sf); //if (loopNumber == 1) //{ // if (!p.isEqual(ppTest, false)) // { // int debug = 1; // } // foreach (Action a in actions) // { // if (a.actionType == actionEnum.playcard) // { // if (a.card.entity == 1020) { // int debug1 = 1; // } // bool isCardValid = false; // foreach (Handmanager.Handcard hh in p.owncards) // { // if (hh.entity == a.card.entity) // { // isCardValid = true; // break; // } // } // if (!isCardValid) // { // int debug = 1; // } // } // } //} //sf.helpfunctions.ErrorLog(" "); //sf.helpfunctions.ErrorLog(actions.Count + " Playfield: " + p.hashcode.ToString()); foreach (Action a in actions) { /* string aList = ""; if (a.actionType != null) { try { aList = aList + "type:" + a.actionType.ToString(); } catch { aList = aList + "type:---"; } } if (a.card != null) { try { aList = aList + " Cname:" + a.card.card.name.ToString(); } catch { aList = aList + " Cname:---"; } } if (a.own != null) { try { aList = aList + " oname:" + a.own.name.ToString(); } catch { aList = aList + " oname:---"; } } if (a.place != null) { try { aList = aList + " place:" + a.place.ToString(); } catch { aList = aList + " place:---"; } } if (a.penalty != null) { try { aList = aList + " penalty:" + a.penalty.ToString(); } catch { aList = aList + " penalty:---"; } } sf.helpfunctions.ErrorLog(aList);*/ //if (deep == 0 && a.actionType == actionEnum.attackWithMinion) sf.helpfunctions.ErrorLog("play " + a.own.entitiyID + " -> " + a.target.entitiyID); havedonesomething = true; Playfield pf = new Playfield(p); pf.doAction(a); addToPosmoves(pf); //HRSim.Helpfunctions.Instance.logTime("action itr"); } //sf.helpfunctions.ErrorLog("deep " + deep + " len " + this.posmoves.Count); // end the turn of the current board (only if its not a lethalcheck) if (isLethalCheck) { p.complete = true; } else { //end turn of enemy p.endTurn(this.simulateSecondTurn, this.playaround, false, this.playaroundprob, this.playaroundprob2); //simulate the enemys response this.startEnemyTurnSim(p, this.simulateSecondTurn, false); } //sort stupid stuff ouf if (botBase.getPlayfieldValue(p) > bestoldval) { bestoldval = botBase.getPlayfieldValue(p); bestold = p; } if (!test) { posmoves.Remove(p); } //HRSim.Helpfunctions.Instance.logTime("tempp itr"); if (this.calculated > this.totalboards) break; } if (!test && bestoldval >= -10000 && bestold != null) { this.posmoves.Add(bestold); } //sf.helpfunctions.loggonoff(true); if (this.printNormalstuff) { int donec = 0; foreach (Playfield p in posmoves) { if (p.complete) donec++; } sf.Helpfunctions.logg("deep " + deep + " len " + this.posmoves.Count + " dones " + donec); } if (!test) { cuttingposibilities(); } if (this.printNormalstuff) { sf.Helpfunctions.logg("cut to len " + this.posmoves.Count); } //sf.helpfunctions.loggonoff(false); deep++; if (this.calculated > this.totalboards) break; if (deep >= this.maxdeep) break;//remove this? //HRSim.Helpfunctions.Instance.logTime("sth itr"); } //HRSim.Helpfunctions.Instance.logTime("done sth"); 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); this.startEnemyTurnSim(p, this.simulateSecondTurn, false); } } } // search the best play........................................................... //do dirtytwoturnsim first :D if (!isLethalCheck) doDirtyTwoTurnsim(); if (!isLethalCheck) this.dirtyTwoTurnSim /= 2; // sf.helpfunctions.logg("find best "); ////HRSim.Helpfunctions.Instance.logTime("2 turn sim"); if (posmoves.Count >= 1) { float bestval = int.MinValue; int bestanzactions = 1000; Playfield bestplay = posmoves[0];//temp[0] foreach (Playfield p in posmoves)//temp { float val = botBase.getPlayfieldValue(p); sf.helpfunctions.logg("move val:" + val); if (bestval <= val) { if (bestval == val && bestanzactions < p.playactions.Count) continue; bestplay = p; bestval = val; bestanzactions = p.playactions.Count; } //HRSim.Helpfunctions.Instance.logTime("search best play itr"); } //HRSim.Helpfunctions.Instance.logTime("search best play 1: " + posmoves.Count); this.bestmove = bestplay.getNextAction(); this.bestmoveValue = bestval; this.bestboard = new Playfield(bestplay); //HRSim.Helpfunctions.Instance.logTime("search best play 2"); return bestval; } //sf.helpfunctions.logg("return"); this.bestmove = null; this.bestmoveValue = -100000; this.bestboard = playf; return -10000; }
public void dosomethingclever(Behavior bbase) { //return; //turncheck //help.moveMouse(950,750); //help.Screenshot(); this.botBase = bbase; hp.updatePositions(); posmoves.Clear(); posmoves.Add(new Playfield()); posmoves[0].sEnemTurn = Settings.Instance.simulateEnemysTurn; /* foreach (var item in this.posmoves[0].owncards) { help.logg("card " + item.handcard.card.name + " is playable :" + item.handcard.card.canplayCard(posmoves[0]) + " cost/mana: " + item.handcard.card.cost + "/" + posmoves[0].mana); } */ //help.logg("is hero ready?" + posmoves[0].ownHeroReady); help.loggonoff(false); //do we need to recalc? help.logg("recalc-check###########"); if (this.dontRecalc && posmoves[0].isEqual(this.nextMoveGuess, true)) { doNextCalcedMove(); } else { help.logg("Leathal-check###########"); bestmoveValue = -1000000; DateTime strt = DateTime.Now; if (useLethalCheck) { strt = DateTime.Now; doallmoves(false, true); help.logg("calculated " + (DateTime.Now - strt).TotalSeconds); } if (bestmoveValue < 10000) { posmoves.Clear(); posmoves.Add(new Playfield()); posmoves[0].sEnemTurn = Settings.Instance.simulateEnemysTurn; help.logg("no lethal, do something random######"); strt = DateTime.Now; doallmoves(false, false); help.logg("calculated " + (DateTime.Now - strt).TotalSeconds); } } //help.logging(true); }
public bool getHoldList(MulliganData mulliganData, Behavior behave) { this.cards.Clear(); this.readRules(behave.BehaviorName()); if (!this.mulliganRulesLoaded) { return(false); } if (!(mulliganData.Cards.Count == 3 || mulliganData.Cards.Count == 4)) { Helpfunctions.Instance.ErrorLog( $"[Mulligan] Mulligan is not used, since it got number of cards: {this.cards.Count}"); return(false); } Log.InfoFormat("[开局留牌] 应用这个 {0} 规则:", behave.BehaviorName()); for (var i = 0; i < mulliganData.Cards.Count; i++) { this.cards.Add(new CardIDEntity(mulliganData.Cards[i].Entity.Id, i)); } var ownHeroClass = mulliganData.UserClass.Convert(); var enemyHeroClass = mulliganData.OpponentClass.Convert(); var manaRule = 4; var MullRuleKey = this.getMullRuleKey(SimCard.None, ownHeroClass, enemyHeroClass, 1); if (this.MulliganRules.ContainsKey(MullRuleKey)) { var temp = this.MulliganRules[MullRuleKey].Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries); manaRule = Convert.ToInt32(temp[2]); } else { MullRuleKey = this.getMullRuleKey(SimCard.None, ownHeroClass, CardClass.INVALID, 1); if (this.MulliganRules.ContainsKey(MullRuleKey)) { var temp = this.MulliganRules[MullRuleKey].Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries); manaRule = Convert.ToInt32(temp[2]); } } var Coin = new CardIDEntity("GAME_005", -888); if (this.cards.Count == 4) { this.cards.Add(Coin); //we have a coin } foreach (var CardIDEntityC in this.cards) { var c = CardIDEntityC.id; if (CardIDEntityC.hold == 0 && CardIDEntityC.holdByRule == 0) { if (c.Cost < manaRule) { CardIDEntityC.holdByManarule = 2; CardIDEntityC.holdReason = this.joinSomeTxt("保留这些卡牌因为法力值消耗:", c.Cost.ToString(), " 小于预定值:", manaRule.ToString()); } else { CardIDEntityC.holdByManarule = -2; CardIDEntityC.holdReason = this.joinSomeTxt("弃掉这些卡牌因为法力值消耗:", c.Cost.ToString(), " 没有小于预定值:", manaRule.ToString()); } } var allowedQuantitySimple = 0; var allowedQuantityExtra = 0; var hasRuleClassSimple = false; var hasRule = false; var MullRuleKeySimple = this.getMullRuleKey(c, ownHeroClass, enemyHeroClass); //Simple key for Class enemy if (this.MulliganRules.ContainsKey(MullRuleKeySimple)) { hasRule = true; hasRuleClassSimple = true; } else { MullRuleKeySimple = this.getMullRuleKey(c, ownHeroClass); //Simple key for ALL enemy if (this.MulliganRules.ContainsKey(MullRuleKeySimple)) { hasRule = true; } } if (hasRule) { var val = this.MulliganRules[MullRuleKeySimple].Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries); allowedQuantitySimple = (val[1] == "2" ? 2 : 1) * (val[0] == "Hold" ? 1 : -1); } hasRule = false; var MullRuleKeyExtra = this.getMullRuleKey(c, ownHeroClass, enemyHeroClass, 1); //Extra key for Class enemy if (this.MulliganRules.ContainsKey(MullRuleKeyExtra)) { hasRule = true; } else if (!hasRuleClassSimple) { MullRuleKeyExtra = this.getMullRuleKey(c, ownHeroClass, CardClass.INVALID, 1); //Extra key for ALL enemy if (this.MulliganRules.ContainsKey(MullRuleKeyExtra)) { hasRule = true; } } if (hasRule) { var val = this.MulliganRules[MullRuleKeyExtra].Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries); allowedQuantityExtra = (val[1] == "2" ? 2 : 1) * (val[0] == "Hold" ? 1 : -1); } //superimpose Class rules to All rules var useHold = false; var useDiscard = false; var useHoldRule = false; var useDiscardRule = false; if (allowedQuantitySimple != 0 && allowedQuantitySimple != allowedQuantityExtra) { if (allowedQuantitySimple > 0) { useHold = true; } else { useDiscard = true; } } if (allowedQuantityExtra != 0) { if (allowedQuantityExtra < 0) { useDiscardRule = true; } else { useHoldRule = true; } } //apply the rules var MullRuleValueExtra = new string[3]; if (allowedQuantityExtra != 0) { MullRuleValueExtra = this.MulliganRules[MullRuleKeyExtra].Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries); } if (useDiscardRule) { if (MullRuleValueExtra[2] != "/") { var addedCards = MullRuleValueExtra[2].Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries); this.MulliganRulesManual.Clear(); foreach (var s in addedCards) { this.MulliganRulesManual.Add(s, ""); } foreach (var tmp in this.cards) { if (CardIDEntityC.entitiy == tmp.entitiy) { continue; } if (this.MulliganRulesManual.ContainsKey(tmp.id)) { CardIDEntityC.holdByRule = -2; CardIDEntityC.holdReason = this.joinSomeTxt("符合规则而弃掉: ", this.getClearRule(MullRuleKeyExtra)); break; } } } } else if (useDiscard) { CardIDEntityC.hold = -2; CardIDEntityC.holdReason = this.joinSomeTxt("符合规则而弃掉: ", this.getClearRule(MullRuleKeySimple)); } if (useHoldRule) { if (CardIDEntityC.holdByRule == 0) { var addedCards = MullRuleValueExtra[2].Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries); this.MulliganRulesManual.Clear(); foreach (var s in addedCards) { this.MulliganRulesManual.Add(s, ""); } var foundFreeCard = false; for (var i = 0; i < this.cards.Count; i++) { if (CardIDEntityC.entitiy == this.cards[i].entitiy) { continue; } if (this.MulliganRulesManual.ContainsKey(this.cards[i].id)) { CardIDEntityC.holdByRule = 2; CardIDEntityC.holdReason = this.joinSomeTxt("符合规则而保留: ", this.getClearRule(MullRuleKeyExtra)); if (this.cards[i].holdByRule < 0) { for (var j = i; j < this.cards.Count; j++) { if (CardIDEntityC.entitiy == this.cards[j].entitiy) { continue; } if (this.MulliganRulesManual.ContainsKey(this.cards[j].id)) { if (this.cards[j].holdByRule < 0) { continue; } foundFreeCard = true; this.cards[j].holdByRule = 2; this.cards[j].holdReason = this.joinSomeTxt("符合规则而保留: ", this.getClearRule(MullRuleKeyExtra)); break; } } if (!foundFreeCard) { foundFreeCard = true; this.cards[i].holdByRule = 2; this.cards[i].holdReason = this.joinSomeTxt("符合规则而保留: ", this.getClearRule(MullRuleKeyExtra)); break; } } else { foundFreeCard = true; this.cards[i].holdByRule = 2; this.cards[i].holdReason = this.joinSomeTxt("符合规则而保留: ", this.getClearRule(MullRuleKeyExtra)); } if (allowedQuantityExtra == 1) { foreach (var tmp in this.cards) { if (tmp.entitiy == CardIDEntityC.entitiy) { continue; } if (tmp.id == CardIDEntityC.id) { tmp.holdByRule = -2; tmp.holdReason = this.joinSomeTxt("符合规则而弃掉: ", this.getClearRule(MullRuleKeyExtra)); } } } } } } } if (useHold && CardIDEntityC.holdByRule != -2) { if (CardIDEntityC.hold == 0) { CardIDEntityC.hold = 2; CardIDEntityC.holdReason = this.joinSomeTxt("符合规则而保留: ", this.getClearRule(MullRuleKeySimple)); if (allowedQuantitySimple == 1) { CardIDEntityC.hold = 1; foreach (var tmp in this.cards) { if (tmp.entitiy == CardIDEntityC.entitiy) { continue; } if (tmp.id == CardIDEntityC.id) { tmp.hold = -2; tmp.holdReason = this.joinSomeTxt("discard Second card by rule: ", this.getClearRule(MullRuleKeySimple)); } } } } } } if (this.cards.Count == 5) { this.cards.Remove(Coin); } foreach (var c in this.cards) { if (c.holdByRule == 0) { if (c.hold == 0) { c.holdByRule = c.holdByManarule; } else { c.holdByRule = c.hold; } } } for (var i = 0; i < mulliganData.Cards.Count; i++) { mulliganData.Mulligans[i] = this.cards[i].holdByRule > 0 ? false : true; Log.InfoFormat("[开局留牌] {0} {1}.", mulliganData.Cards[i].Entity.Name, this.cards[i].holdReason); } return(true); }