public Playfield getPlayfield(string path) { string[] lines = new string[0] { }; try { lines = System.IO.File.ReadAllLines(path); Logger.Debug("read test.txt {Length} lines", lines.Length); } catch { Logger.Error("Read failed."); return(null); } Playfield p = new Playfield(); foreach (string s in lines) { string[] tmp = s.Split(' '); int len = tmp.Length; if (len < 1) { continue; } BoardObj bo; switch (tmp[0]) { case "Data": getBattleData(tmp, p); continue; case "Hand": p.ownHandCards.Add(getHCfromHeader(tmp)); continue; case "AOE": bo = getBOfromHeader(tmp, p.ownerIndex); //predefined data if (bo.own) { p.ownAreaEffects.Add(bo); } else { p.enemyAreaEffects.Add(bo); } continue; case "BUILDING": bo = getBOfromHeader(tmp, p.ownerIndex); //predefined data int tower = 0; switch (bo.Name) { case CardDB.cardName.princesstower: tower = bo.Line; if (bo.own) { if (tower == 1) { p.ownPrincessTower1 = bo; } else { p.ownPrincessTower2 = bo; } } else { if (tower == 1) { p.enemyPrincessTower1 = bo; } else { p.enemyPrincessTower2 = bo; } } break; case CardDB.cardName.kingtower: tower = 10 + bo.Line; if (bo.own) { if (p.ownerIndex == bo.ownerIndex) { p.ownKingsTower = bo; } } else { p.enemyKingsTower = bo; } break; case CardDB.cardName.kingtowermiddle: tower = 100; break; } if (tower == 0) { if (bo.own) { p.ownBuildings.Add(bo); } else { p.enemyBuildings.Add(bo); } } continue; case "MOB": bo = getBOfromHeader(tmp, p.ownerIndex); //predefined data if (bo.own) { p.ownMinions.Add(bo); } else { p.enemyMinions.Add(bo); } continue; } } p.home = p.ownKingsTower.Position.Y < 15250 ? true : false; p.initTowers(); int i = 0; foreach (BoardObj t in p.ownTowers) { if (t.Tower < 10) { i += t.Line; } } int kingsLine = 0; switch (i) { case 0: kingsLine = 3; break; case 1: kingsLine = 2; break; case 2: kingsLine = 1; break; } foreach (BoardObj t in p.ownTowers) { if (t.Tower > 9) { t.Line = kingsLine; } } Logger.Debug("getPlayfield:OK"); return(p); //Set default settings for behaviour //Apply settings from this Logg //set Simulation stuff //save data }
public sealed override CastRequest GetNextCast() { Logger.Debug(""); if (statNumSuccessfulEntrances > 0) { statTimeOutsideRoutine = DateTime.Now - statTimerRoutine; } statTimerRoutine = DateTime.Now; List <BoardObj> ownMinions = new List <BoardObj>(); List <BoardObj> enemyMinions = new List <BoardObj>(); List <BoardObj> ownAreaEffects = new List <BoardObj>(); List <BoardObj> enemyAreaEffects = new List <BoardObj>(); List <BoardObj> ownBuildings = new List <BoardObj>(); List <BoardObj> enemyBuildings = new List <BoardObj>(); BoardObj ownKingsTower = new BoardObj(); BoardObj ownPrincessTower1 = new BoardObj(); BoardObj ownPrincessTower2 = new BoardObj(); BoardObj enemyKingsTower = new BoardObj(); BoardObj enemyPrincessTower1 = new BoardObj(); BoardObj enemyPrincessTower2 = new BoardObj(); List <Handcard> ownHandCards = new List <Handcard>(); Handcard prevHandCard = new Handcard(); Logger.Debug("#####Stats##### Inint BO {0}", (statTimerRoutine - DateTime.Now).TotalSeconds); var battle = ClashEngine.Instance.Battle; if (battle == null || !battle.IsValid) { return(null); } var om = ClashEngine.Instance.ObjectManager; if (om == null) { return(null); } var lp = ClashEngine.Instance.LocalPlayer; if (lp == null || !lp.IsValid) { return(null); } var spellButtons = ClashEngine.Instance.AvailableSpellButtons; if (spellButtons == null) { return(null); } var spells = ClashEngine.Instance.AvailableSpells; if (spells == null) { return(null); } if (ownKingsTowerPos.Y == -1) { List <Tuple <int, int> > towersIndY = new List <Tuple <int, int> >(); bool needFriendlyIndex = false; var chars = om.OfType <Clash.Engine.NativeObjects.Logic.GameObjects.Character>(); foreach (var @char in chars) { if ([email protected]) { continue; } var data = @char.LogicGameObjectData; if (data == null || !data.IsValid) { continue; } var name = data.Name; if ((MemPtr)name == MemPtr.Zero) { continue; } switch (CardDB.Instance.cardNamestringToEnum(name.Value.ToString(), "0")) { case CardDB.cardName.kingtower: int OwnerIndex = (int)@char.OwnerIndex; int charY = @char.StartPosition.Y; towersIndY.Add(new Tuple <int, int>(OwnerIndex, charY)); if (OwnerIndex == lp.OwnerIndex) { ownKingsTowerPos.Y = charY; } break; case CardDB.cardName.kingtowermiddle: ownKingsTowerPos.X = @char.StartPosition.X; needFriendlyIndex = true; break; } } if (needFriendlyIndex) { foreach (var t in towersIndY) { if (ownKingsTowerPos.Y == t.Item2 && lp.OwnerIndex != t.Item1) { friendlyOwnerIndex = t.Item1; } } } } Logger.Debug("#####Stats##### Inint BO+engine {0}", (statTimerRoutine - DateTime.Now).TotalSeconds); using (new PerformanceTimer("GetNextCast entrance")) { Handcard Mirror = null; Dictionary <string, int> AvailableSpells = new Dictionary <string, int>(); foreach (var spell in spells) { if (spell == null || !spell.IsValid) { continue; } var name = spell.Name; if ((MemPtr)name == MemPtr.Zero) { continue; } AvailableSpells.Add(name.Value.ToString(), 0); } foreach (var spellBtn in spellButtons) { if (spellBtn == null || !spellBtn.IsValid) { continue; } if (spellBtn.SpellDeckSpell == null || !spellBtn.SpellDeckSpell.IsValid) { continue; } if (spellBtn.SpellDeckSpell.Spell == null || !spellBtn.SpellDeckSpell.Spell.IsValid) { continue; } var name = spellBtn.SpellDeckSpell.Spell.Name; if ((MemPtr)name == MemPtr.Zero) { continue; } if (!AvailableSpells.ContainsKey(name.Value.ToString())) { continue; } int lvl = spellBtn.SpellDeckSpell.LevelIndex; Handcard hc = new Handcard(name.Value.ToString(), lvl); if (hc.card.name == CardDB.cardName.unknown) { CardDB.Instance.collectNewCards(spellBtn); } hc.manacost = spellBtn.SpellDeckSpell.Spell.ManaCost; if (hc.card.name == CardDB.cardName.mirror) { Mirror = hc; } //if (hc.card.needUpdate) CardDB.Instance.cardsAdjustment(spell); ownHandCards.Add(hc); } if (ownHandCards.Count == 4) { if (prevHandCards.Count != 4) { prevHandCards = new List <Handcard>(ownHandCards); } else { for (int i = 0; i < 4; i++) { if (ownHandCards[i].card.name == prevHandCards[i].card.name) { continue; } if (ownHandCards[i].card.name == CardDB.cardName.unknown) { continue; } prevHandCard = prevHandCards[i]; if (Mirror != null) { Mirror.transformTo(prevHandCard); Mirror.mirror = true; } break; } } } var qSpells = ClashEngine.Instance.QueuedSpells; if (qSpells != null) { if (qSpells.Count() == 0) { if (CastRequestDB.Count != 0) { CastRequestDB.Clear(); } } else { if (CastRequest != null && !CastRequestDB.ContainsKey(CastRequest.SpellName)) { CastRequestDB.Add(CastRequest.SpellName, CastRequest); } if (CastRequestDBtmp.Count != 0) { CastRequestDBtmp.Clear(); } foreach (var qs in qSpells) { if (qs == null || !qs.IsValid) { continue; } string name = qs.Name.Value.ToString(); if (!CastRequestDBtmp.ContainsKey(name)) { CastRequestDBtmp.Add(name, 0); } if (CastRequestDB.ContainsKey(name)) { //add to pf //TODO: real lvl BoardObj bo = new BoardObj(CardDB.Instance.cardNamestringToEnum(name, "21"), 6); bo.Position = new VectorAI(CastRequestDB[name].Position); bo.ownerIndex = (int)lp.OwnerIndex; bo.frozen = true; bo.GId = getNextGId(); switch (bo.type) { case boardObjType.MOB: int nums = bo.card.SummonNumber; if (nums == 0) { nums = 1; } else { if (bo.card.SpawnCharacter != "") { bo = new BoardObj(CardDB.Instance.cardNamestringToEnum(bo.card.SpawnCharacter, "22"), 6); bo.Position = new VectorAI(CastRequestDB[name].Position); bo.ownerIndex = (int)lp.OwnerIndex; bo.frozen = true; bo.GId = getNextGId(); } } for (int i = 0; i < nums; i++) { ownMinions.Add(bo); if (nums > 1) { bo = new BoardObj(bo); bo.GId = getNextGId(); } } break; case boardObjType.BUILDING: ownBuildings.Add(bo); break; case boardObjType.AOE: break; } } } foreach (var kvp in CastRequestDB.ToArray()) { if (!CastRequestDBtmp.ContainsKey(kvp.Key)) { CastRequestDB.Remove(kvp.Key); } } } } //var projs = om.OfType<Clash.Engine.NativeObjects.Logic.GameObjects.Projectile>(); //foreach (var proj in projs) //{ // if (proj != null && proj.IsValid) // { // //TODO: get static data for all objects // //Here we get dynamic data only // CardDB.Instance.collectNewCards(proj); // } //} var aoes = om.OfType <Clash.Engine.NativeObjects.Logic.GameObjects.AreaEffectObject>(); foreach (var aoe in aoes) { if (!aoe.IsValid) { continue; } var data = aoe.LogicGameObjectData; if (data == null || !data.IsValid) { continue; } var name = data.Name; if ((MemPtr)name == MemPtr.Zero) { continue; } BoardObj bo = new BoardObj(CardDB.Instance.cardNamestringToEnum(name.Value.ToString(), "1")); //if (bo.card.needUpdate) CardDB.Instance.cardsAdjustment(aoe); if (bo.card.name == CardDB.cardName.unknown) { CardDB.Instance.collectNewCards(aoe); } bo.GId = aoe.GlobalId; bo.Position = new VectorAI(aoe.StartPosition); bo.Line = bo.Position.X > 8700 ? 2 : 1; //bo.level = TODO real value //bo.Atk = TODO real value bo.LifeTime = aoe.HealthComponent.RemainingTime; //bo.extraData = data.Field10.ToString();//!!TEST bo.ownerIndex = (int)aoe.OwnerIndex; bool own = bo.ownerIndex == lp.OwnerIndex ? true : (bo.ownerIndex == friendlyOwnerIndex ? true : false); bo.own = own; if (own) { ownAreaEffects.Add(bo); } else { enemyAreaEffects.Add(bo); } } var chars = om.OfType <Clash.Engine.NativeObjects.Logic.GameObjects.Character>(); foreach (var @char in chars) { if ([email protected]) { continue; } var data = @char.LogicGameObjectData; if (data == null || !data.IsValid) { continue; } var name = data.Name; if ((MemPtr)name == MemPtr.Zero) { continue; } BoardObj bo = new BoardObj(CardDB.Instance.cardNamestringToEnum(name.Value.ToString(), "2"), (int)@char.TowerLevel); bo.ownerIndex = (int)@char.OwnerIndex; bool own = bo.ownerIndex == lp.OwnerIndex ? true : (bo.ownerIndex == friendlyOwnerIndex ? true : false); bo.own = own; if (bo.card.name == CardDB.cardName.unknown) { CardDB.Instance.collectNewCards(@char); } else if (bo.ownerIndex == lp.OwnerIndex && bo.card.needUpdate) { CardDB.Instance.cardsAdjustment(@char); } bo.GId = @char.GlobalId; bo.Position = new VectorAI(@char.StartPosition); bo.Line = bo.Position.X > 8700 ? 2 : 1; bo.level = 1 + (int)@char.TowerLevel; //this.frozen = TODO //this.startFrozen = TODO bo.HP = @char.HealthComponent.CurrentHealth; bo.Shield = @char.HealthComponent.CurrentShieldHealth; bo.LifeTime = @char.HealthComponent.LifeTime - @char.HealthComponent.RemainingTime; //TODO: - find real value for battle stage int tower = 0; switch (bo.Name) { case CardDB.cardName.princesstower: CardDB.Instance.setPrincessTowerMaxHP(bo); tower = bo.Line; if (bo.own) { if (tower == 1) { ownPrincessTower1 = bo; } else { ownPrincessTower2 = bo; } } else { if (tower == 1) { enemyPrincessTower1 = bo; } else { enemyPrincessTower2 = bo; } } break; case CardDB.cardName.kingtower: CardDB.Instance.setKingsTowerMaxHP(bo); tower = 10 + bo.Line; if (bo.own) { if (ownKingsTower.HP == 0) { ownKingsTower = bo; } else if (bo.HP < ownKingsTower.HP) { ownKingsTower = bo; } if (ownKingsTowerPos.X != -1) { ownKingsTower.Position.X = ownKingsTowerPos.X; } ownKingsTower.ownerIndex = (int)lp.OwnerIndex; } else { if (enemyKingsTower.HP == 0) { enemyKingsTower = bo; } else if (bo.HP < enemyKingsTower.HP) { enemyKingsTower = bo; } if (ownKingsTowerPos.X != -1) { enemyKingsTower.Position.X = ownKingsTowerPos.X; } } break; case CardDB.cardName.kingtowermiddle: tower = 100; break; default: bo.Atk = (int)(bo.card.Atk * lvlToCoef[bo.level]); //TODO: need value from core if (own) { switch (bo.type) { case boardObjType.MOB: ownMinions.Add(bo); break; case boardObjType.BUILDING: ownBuildings.Add(bo); break; } } else { switch (bo.type) { case boardObjType.MOB: enemyMinions.Add(bo); break; case boardObjType.BUILDING: enemyBuildings.Add(bo); break; } } break; } } } Playfield p; Logger.Debug("#####Stats##### before Initialize playfield {0}", (statTimerRoutine - DateTime.Now).TotalSeconds); using (new PerformanceTimer("Initialize playfield.")) { Logger.Debug("################################Routine v.0.8.6 Behavior:{Name:l} v.{Version:l}", Name, Version); p = new Playfield { BattleTime = battle.BattleTime, suddenDeath = battle.BattleTime.TotalSeconds > 180, ownerIndex = (int)lp.OwnerIndex, ownMana = (int)(lp.Mana - lp.ReservedMana), ownHandCards = ownHandCards, ownAreaEffects = ownAreaEffects, ownMinions = ownMinions, ownBuildings = ownBuildings, ownKingsTower = ownKingsTower, ownPrincessTower1 = ownPrincessTower1, ownPrincessTower2 = ownPrincessTower2, enemyAreaEffects = enemyAreaEffects, enemyMinions = enemyMinions, enemyBuildings = enemyBuildings, enemyKingsTower = enemyKingsTower, enemyPrincessTower1 = enemyPrincessTower1, enemyPrincessTower2 = enemyPrincessTower2, prevCard = prevHandCard, //nextCard = //TODO: Add next card }; p.home = p.ownKingsTower.Position.Y < 15250 ? true : false; if (p.ownPrincessTower1.Position == null) { p.ownPrincessTower1.Position = p.getDeployPosition(deployDirectionAbsolute.ownPrincessTowerLine1); } if (p.ownPrincessTower2.Position == null) { p.ownPrincessTower2.Position = p.getDeployPosition(deployDirectionAbsolute.ownPrincessTowerLine2); } if (p.enemyPrincessTower1.Position == null) { p.enemyPrincessTower1.Position = p.getDeployPosition(deployDirectionAbsolute.enemyPrincessTowerLine1); } if (p.enemyPrincessTower2.Position == null) { p.enemyPrincessTower2.Position = p.getDeployPosition(deployDirectionAbsolute.enemyPrincessTowerLine2); } p.initTowers(); p.print(); battleLogs.Add(p); } Logger.Debug("#####Stats##### after Initialize playfield {0}", (statTimerRoutine - DateTime.Now).TotalSeconds); statTimeInitPlayfield = DateTime.Now - statTimerRoutine; statTimerRoutine = DateTime.Now; Cast bc; using (new PerformanceTimer("GetBestCast")) { //DateTime statBehaviorCalcStart = DateTime.Now; bc = this.GetBestCast(p); CastRequest = null; if (bc != null && bc.Position != null) { if (p.ownMana + 1 >= bc.hc.manacost) { CastRequest = new CastRequest(bc.SpellName, bc.Position.ToVector2f(true)); } Logger.Debug("CastRequest {SpellName:l} {Position:l}", bc.SpellName, CastRequest == null ? bc.Position?.ToString() : CastRequest.Position.ToString()); } else { Logger.Debug("Waiting for cast, maybe next tick..."); } statTimeInsideBehavior = DateTime.Now - statTimerRoutine; //stat info statSumTimeOutsideRoutine += statTimeOutsideRoutine; statSumTimeInitPlayfield += statTimeInitPlayfield; statSumTimeInsideBehavior += statTimeInsideBehavior; statNumSuccessfulEntrances++; int objsCount = ownAreaEffects.Count + enemyAreaEffects.Count + ownMinions.Count + enemyMinions.Count + ownBuildings.Count + enemyBuildings.Count; //without HandCards if (objsCount == 0) { objsCount = 2; } Logger.Debug("Hint: ne:NumberEntrances CT:CalculationTime aCT:AverageCalculationTimePer1Game tpo:TimePer1Object ToR:TimeOutsideRoutine"); Logger.Debug("#####Stats### ne:{NumberEntrances} Behavior(CT/aCT/tpo):{BehaviorCalcTime}/{averageBCT}/{timePer1Object} Playfield(CT/aCT/tpo):{PlayfieldCreationTime}/{averagePCT}/{timePer1Object} outsideRoutine(ToR/aToR/tpo):{timeOutsideRoutine}/{averageToR}/{timePer1Object}", statNumSuccessfulEntrances, statTimeInsideBehavior.TotalSeconds, (statSumTimeInsideBehavior / statNumSuccessfulEntrances).TotalSeconds, (statTimeInsideBehavior / objsCount).TotalSeconds, statTimeInitPlayfield.TotalSeconds, (statSumTimeInitPlayfield / statNumSuccessfulEntrances).TotalSeconds, (statTimeInitPlayfield / objsCount).TotalSeconds, statTimeOutsideRoutine.TotalSeconds, (statSumTimeOutsideRoutine / (statNumSuccessfulEntrances > 1 ? statNumSuccessfulEntrances - 1 : 1)).TotalSeconds, (statTimeOutsideRoutine / objsCount).TotalSeconds); statTimerRoutine = DateTime.Now; return(CastRequest); } }
public sealed override CastRequest GetNextCast() { List <BoardObj> ownMinions = new List <BoardObj>(); List <BoardObj> enemyMinions = new List <BoardObj>(); List <BoardObj> ownAreaEffects = new List <BoardObj>(); List <BoardObj> enemyAreaEffects = new List <BoardObj>(); List <BoardObj> ownBuildings = new List <BoardObj>(); List <BoardObj> enemyBuildings = new List <BoardObj>(); BoardObj ownKingsTower = new BoardObj(); BoardObj ownPrincessTower1 = new BoardObj(); BoardObj ownPrincessTower2 = new BoardObj(); BoardObj enemyKingsTower = new BoardObj(); BoardObj enemyPrincessTower1 = new BoardObj(); BoardObj enemyPrincessTower2 = new BoardObj(); List <Handcard> ownHandCards = new List <Handcard>(); var battle = ClashEngine.Instance.Battle; if (battle == null || !battle.IsValid) { return(null); } var om = ClashEngine.Instance.ObjectManager; if (om == null) { return(null); } var lp = ClashEngine.Instance.LocalPlayer; if (lp == null || !lp.IsValid) { return(null); } var spells = ClashEngine.Instance.AvailableSpells; if (spells == null) { return(null); } StringBuilder sb = new StringBuilder(); using (new PerformanceTimer("GetNextCast entrance")) { foreach (var spell in spells) { if (spell != null && spell.IsValid) { int lvl = 1; Handcard hc = new Handcard(spell.Name.Value, lvl); //hc.lvl = ??? TODO hc.manacost = spell.ManaCost; //hc.position = ??? TODO //TODO:for all objects - if (new name) get actual params ownHandCards.Add(hc); } } var aoes = om.OfType <Clash.Engine.NativeObjects.Logic.GameObjects.AreaEffectObject>(); foreach (var aoe in aoes) { if (aoe != null && aoe.IsValid) { //TODO: get static data for all objects //Here we get dynamic data only BoardObj bo = new BoardObj(CardDB.Instance.cardNamestringToEnum(aoe.LogicGameObjectData.Name.Value)); bo.GId = aoe.GlobalId; bo.Position = new VectorAI(aoe.StartPosition); bo.Line = bo.Position.X > 8700 ? 1 : 2; //bo.level = TODO real value //bo.Atk = TODO real value bo.LifeTime = aoe.HealthComponent.RemainingTime; //TODO check this value bo.ownerIndex = (int)aoe.OwnerIndex; bool own = bo.ownerIndex == lp.OwnerIndex ? true : false; //TODO: replace it on Friendly (for 2x2 mode) bo.own = own; if (own) { ownAreaEffects.Add(bo); } else { enemyAreaEffects.Add(bo); } //hc.position = ??? TODO } } var chars = om.OfType <Clash.Engine.NativeObjects.Logic.GameObjects.Character>(); foreach (var @char in chars) { //sb.Clear(); //i++; //BoardObj bo = new BoardObj(); var data = @char.LogicGameObjectData; if (data != null && data.IsValid) { //TODO: get static data for all objects //Here we get dynamic data only BoardObj bo = new BoardObj(CardDB.Instance.cardNamestringToEnum(data.Name.Value)); bo.GId = @char.GlobalId; bo.Position = new VectorAI(@char.StartPosition); bo.Line = bo.Position.X > 8700 ? 1 : 2; //bo.level = TODO real value //bo.Atk = TODO real value //this.frozen = TODO //this.startFrozen = TODO bo.HP = @char.HealthComponent.CurrentHealth; //TODO: check it bo.Shield = @char.HealthComponent.CurrentShieldHealth; //TODO: check it bo.LifeTime = @char.HealthComponent.LifeTime - @char.HealthComponent.RemainingTime; //TODO: check it of data.LifeTime, - find real value for battle stage bo.ownerIndex = (int)@char.OwnerIndex; bool own = bo.ownerIndex == lp.OwnerIndex ? true : false; //TODO: replace it on Friendly (for 2x2 mode) int tower = 0; switch (bo.Name) { case CardDB.cardName.princesstower: tower = bo.Line; if (bo.own) { if (tower == 1) { ownPrincessTower1 = bo; } else { ownPrincessTower2 = bo; } } else { if (tower == 1) { enemyPrincessTower1 = bo; } else { enemyPrincessTower2 = bo; } } break; case CardDB.cardName.kingtower: tower = 10 + bo.Line; if (bo.own) { if (lp.OwnerIndex == bo.ownerIndex) { ownKingsTower = bo; } } else { enemyKingsTower = bo; } break; case CardDB.cardName.kingtowermiddle: tower = 100; break; } if (tower == 0) { if (bo.own) { ownBuildings.Add(bo); } else { enemyBuildings.Add(bo); } } bo.own = own; if (own) { switch (bo.type) { case boardObjType.MOB: ownMinions.Add(bo); break; case boardObjType.BUILDING: if (bo.Tower > 0) { if (bo.Tower > 9 && bo.ownerIndex == lp.OwnerIndex) { ownKingsTower = bo; } } else { ownBuildings.Add(bo); } break; } } else { switch (bo.type) { case boardObjType.MOB: enemyMinions.Add(bo); continue; case boardObjType.BUILDING: if (bo.Tower == 0) { if (bo.Tower > 9) { enemyKingsTower = bo; } } else { enemyBuildings.Add(bo); } break; } } } } } Playfield p; using (new PerformanceTimer("Initialize playfield.")) { p = new Playfield { BattleTime = ClashEngine.Instance.Battle.BattleTime, ownerIndex = (int)lp.OwnerIndex, ownMana = (int)lp.Mana, ownHandCards = ownHandCards, ownAreaEffects = ownAreaEffects, ownMinions = ownMinions, ownBuildings = ownBuildings, ownKingsTower = ownKingsTower, ownPrincessTower1 = ownPrincessTower1, ownPrincessTower2 = ownPrincessTower2, enemyAreaEffects = enemyAreaEffects, enemyMinions = enemyMinions, enemyBuildings = enemyBuildings, enemyKingsTower = enemyKingsTower, enemyPrincessTower1 = enemyPrincessTower1, enemyPrincessTower2 = enemyPrincessTower2, //TODO: Add next card //nextCard = }; p.home = p.ownKingsTower.Position.Y < 15250 ? true : false; p.initTowers(); int i = 0; foreach (BoardObj t in p.ownTowers) { if (t.Tower < 10) { i += t.Line; } } int kingsLine = 0; switch (i) { case 0: kingsLine = 3; break; case 1: kingsLine = 2; break; case 2: kingsLine = 1; break; } foreach (BoardObj t in p.ownTowers) { if (t.Tower > 9) { t.Line = kingsLine; } } p.print(); } Cast bc; using (new PerformanceTimer("GetBestCast")) { bc = this.GetBestCast(p); CastRequest retval = null; if (bc != null && bc.Position != null) { Logger.Information("Cast {bc}", bc.ToString()); retval = new CastRequest(bc.SpellName, bc.Position.ToVector2()); } else { Logger.Information("Waiting for cast, maybe next tick..."); } return(retval); } }