/// <summary> /// Searching for target according to user input /// </summary> /// <param name="settingsTarget">Advanced Settings target select</param> /// <returns></returns> public static IEnumerable <int> SeTarget(int settingsTarget) { if (settingsTarget == 2) { // Eagle Artillerty search foreach (var f in SearchTarget(EagleArtillery.Find(CacheBehavior.ForceScan))) { yield return(f); } // If not found switch to thownhall if (targetIsSet == false) { foreach (var f in SearchTarget(TownHall.Find(CacheBehavior.ForceScan))) { yield return(f); } } } else if (settingsTarget == 0) { // Townhall search foreach (var f in SearchTarget(TownHall.Find(CacheBehavior.ForceScan))) { yield return(f); } // If not found switch to the core of the base if (targetIsSet == false) { AllInOnePushDeploy.Target = AllInOnePushDeploy.Core; targetIsSet = true; } } else if (settingsTarget == 1) { // Dark Elixir Storage search foreach (var f in SearchTarget(DarkElixirStorage.Find(CacheBehavior.ForceScan)?.FirstOrDefault())) { yield return(f); } // If not found switch to townhall if (targetIsSet == false) { foreach (var f in SearchTarget(TownHall.Find(CacheBehavior.ForceScan))) { yield return(f); } } } // If not found both switch to the core of the base if (targetIsSet == false) { AllInOnePushDeploy.Target = AllInOnePushDeploy.Core; } }
/// <summary> /// get where to deploy hereos according to user defined /// </summary> /// <param name="deployHeroesAt">user defined location 1 is TwonHall , 2 is Dark Elixir Storage</param> /// <returns></returns> public static PointFT GetHeroesTarget(int deployHeroesAt) { var target = new PointFT(0f, 0f); switch (deployHeroesAt) { case 1: target = (PointFT)TownHall.Find()?.Location.GetCenter(); break; case 2: target = (PointFT)DarkElixirStorage.Find()?.FirstOrDefault()?.Location.GetCenter(); break; } return(target); }
public static Target[] GenerateTargets(float minimumDistance, bool ignoreGold, bool ignoreElixir, CacheBehavior behavior = CacheBehavior.Default) { // Find all Collectors & storages just sitting around... List <Building> buildings = new List <Building>(); if (!ignoreGold) { //User has Gold min set to ZERO - which means Dont include Gold Targets buildings.AddRange(GoldMine.Find(behavior)); buildings.AddRange(GoldStorage.Find(behavior)); } if (!ignoreElixir) { //User has Elixir min set to ZERO - which means Dont include Elixir Targets buildings.AddRange(ElixirCollector.Find(behavior)); buildings.AddRange(ElixirStorage.Find(behavior)); } //We always includ DarkElixir - Because who doesnt love dark Elixir? buildings.AddRange(DarkElixirDrill.Find(behavior)); buildings.AddRange(DarkElixirStorage.Find(behavior)); List <Target> targetList = new List <Target>(); foreach (Building building in buildings) { Target current = new Target(); current.TargetBuilding = building; current.Center = building.Location.GetCenter(); current.NearestRedLine = GameGrid.RedPoints.OrderBy(p => p.DistanceSq(current.Center)).First(); current.CenterToRedline = current.Center.DistanceSq(current.NearestRedLine); Log.Debug($"[Berts Algorithms] DistanceSq from {current.Name} to red point: {current.CenterToRedline.ToString("F1")}"); if (current.CenterToRedline < minimumDistance) //Compare distance to Redline to the Minimum acceptable distance Passed in { current.DeployGrunts = current.Center.PointOnLineAwayFromEnd(current.NearestRedLine, _gruntDeployDistanceFromRedline); //Barbs & Goblins current.DeployRanged = current.Center.PointOnLineAwayFromEnd(current.NearestRedLine, _rangedDeployDistanceFromRedline); //Archers & Minions targetList.Add(current); } } Log.Debug($"[Berts Algorithms] Found {targetList.Count} deploy points"); return(targetList.ToArray()); }
/// <summary> /// get where to deploy hereos according to user defined /// </summary> /// <param name="deployHeroesAt">user defined location 1 is TwonHall , 2 is Dark Elixir Storage</param> /// <returns></returns> public static PointFT GetHeroesTarget(int deployHeroesAt) { var target = new PointFT(0f, 0f); switch (deployHeroesAt) { case 1: var th = TownHall.Find()?.Location.GetCenter(); target = th != null ? (PointFT)th : target; break; case 2: var de = DarkElixirStorage.Find()?.FirstOrDefault()?.Location.GetCenter(); target = de != null ? (PointFT)de : target; break; } return(target); }
public override double ShouldAccept() { if (Opponent.MeetsRequirements(BaseRequirements.All)) { Log.Debug("[Goblin Knife] searching for DE Storage ...."); var DE = DarkElixirStorage.Find()?.FirstOrDefault()?.Location.GetCenter(); if (DE == null) { Log.Debug("Couldn't found DE Storage .. we will skip this base"); Log.Error("Counld not locate DE Storage .. skipping this base"); return(0); } else { Log.Debug("[Goblin Knife] Found DE storage .. move to CreateDeployPoints Method"); return(1); } } return(0); }
public static Target TargetDarkElixirStorage(CacheBehavior behavior = CacheBehavior.Default) { var target = new Target(); var des = DarkElixirStorage.Find(behavior); target.ValidTarget = false; if (des.Length > 0) { target.ValidTarget = true; target.TargetBuilding = des[0]; target.Center = des[0].Location.GetCenter(); target.Edge = Origin.PointOnLineAwayFromEnd(target.Center, _DEStorageCenterToOuterEdgeDistance); target.NearestRedLine = GameGrid.RedPoints.OrderBy(p => p.DistanceSq(target.Edge)).First(); target.EdgeToRedline = target.Edge.DistanceSq(target.NearestRedLine); //Fill the DeployGrunts Property with where out main dragon force should go. target.DeployGrunts = Origin.PointOnLineAwayFromEnd(target.NearestRedLine, 0.2f); //TODO Move to Constants.. } return(target); }
public static Target[] GenerateTargets(string algorithmName, float minimumDistance, bool ignoreGold, bool ignoreElixir, string AttackId, out double avgFillstate, out double avgCollectorLvl, CacheBehavior behavior = CacheBehavior.Default, bool outputDebugImage = false, bool activeBase = false) { // Find all Collectors & storages just sitting around... List <Building> buildings = new List <Building>(); //Get a list of Gold Mines. List <GoldMine> goldMines = new List <GoldMine>(); goldMines.AddRange(GoldMine.Find(behavior)); //Get a list of Elixir Collectors. List <ElixirCollector> elixirCollectors = new List <ElixirCollector>(); elixirCollectors.AddRange(ElixirCollector.Find(behavior)); avgFillstate = 0; //Get the Average Fill State of all the Elixir Collectors - From this we can tell what percentage of the loot is in Collectors. if (elixirCollectors.Count > 1) { avgFillstate = elixirCollectors.Average(c => c.FillState); } //Log the Average Fill State of aLL elixir Collectors... Log.Debug($"[Berts Algorithms] - Fill State Average of ALL Elixir Collectors: {(avgFillstate * 10).ToString("F1")}"); if (!ignoreGold) { buildings.AddRange(goldMines); if (activeBase) { buildings.AddRange(GoldStorage.Find(behavior)); } } if (!ignoreElixir) { buildings.AddRange(elixirCollectors); if (activeBase) { buildings.AddRange(ElixirStorage.Find(behavior)); } } //Determine the Average Collector Level. avgCollectorLvl = 0; if (ignoreGold && !ignoreElixir) { if (elixirCollectors.Count(c => c.Level.HasValue) > 1) { avgCollectorLvl = elixirCollectors.Where(c => c.Level.HasValue).Average(c => (int)c.Level); } } else if (ignoreElixir && !ignoreGold) { if (goldMines.Count(c => c.Level.HasValue) > 1) { avgCollectorLvl = goldMines.Where(c => c.Level.HasValue).Average(c => (int)c.Level); } } else if (!ignoreElixir && !ignoreGold) { if (buildings.Count(c => c.Level.HasValue) > 1) { avgCollectorLvl = buildings.Where(c => c.Level.HasValue).Average(c => (int)c.Level); } } //We always includ DarkElixir - Because who doesnt love dark Elixir? buildings.AddRange(DarkElixirDrill.Find(behavior)); if (activeBase) { buildings.AddRange(DarkElixirStorage.Find(behavior)); } List <Target> targetList = new List <Target>(); foreach (Building building in buildings) { Target current = new Target(); current.TargetBuilding = building; current.Center = building.Location.GetCenter(); current.Edge = Origin.PointOnLineAwayFromEnd(current.Center, 1.0f); current.NearestRedLine = AllPoints.OrderBy(p => p.DistanceSq(current.Edge)).First(); current.CenterToRedline = current.Center.DistanceSq(current.NearestRedLine); if (current.CenterToRedline < minimumDistance) //Compare distance to Redline to the Minimum acceptable distance Passed in { Log.Debug($"[Berts Algorithms] Distance from {current.Name} to red point: {Math.Sqrt(current.CenterToRedline).ToString("F1")}, Min Distance: {Math.Sqrt(minimumDistance).ToString("F1")} - GO!"); current.DeployGrunts = current.Center.PointOnLineAwayFromEnd(current.NearestRedLine, _gruntDeployDistanceFromRedline); //Barbs & Goblins current.DeployRanged = current.Center.PointOnLineAwayFromEnd(current.NearestRedLine, _rangedDeployDistanceFromRedline); //Archers & Minions targetList.Add(current); } else { Log.Debug($"[Berts Algorithms] Distance from {current.Name} to red point: {Math.Sqrt(current.CenterToRedline).ToString("F1")}, Min Distance: {Math.Sqrt(minimumDistance).ToString("F1")} - TOO FAR!"); } } if (outputDebugImage) { OutputDebugImage(algorithmName, buildings, targetList, AttackId); } return(targetList.ToArray()); }
public override IEnumerable <int> AttackRoutine() { var DE = DarkElixirStorage.Find()?.FirstOrDefault()?.Location.GetCenter(); //set the target if (DE == null) { for (var i = 1; i <= 3; i++) { Log.Warning($"bot didn't found the DE Storage .. we will attemp search NO. {i + 1}"); yield return(1000); DE = DarkElixirStorage.Find()?.FirstOrDefault()?.Location.GetCenter(); if (DE != null) { Log.Warning($"DE Storage found after {i + 1} retries"); break; } } } if (DE != null) { _target = (PointFT)DE; } else { Log.Debug("[Goblin Knife] coundn't locate the target after aligning the base"); Log.Error("Couldn't find DE Storage we will return home"); Surrender(); yield break; } CreateDeployPoints(); Log.Info($"[Goblin Knife] V{Version} Deploy start"); //get troops var deployElements = Deploy.GetTroops(); var clanCastle = deployElements.ExtractOne(u => u.ElementType == DeployElementType.ClanTroops && UserSettings.UseClanTroops); var earthQuakeSpell = deployElements.Extract(u => u.Id == DeployId.Earthquake); var jumpSpell = deployElements.ExtractOne(DeployId.Jump); var giant = deployElements.ExtractOne(DeployId.Giant); var goblin = deployElements.ExtractOne(DeployId.Goblin); var wizard = deployElements.ExtractOne(DeployId.Wizard); var barbarian = deployElements.ExtractOne(DeployId.Barbarian); var archer = deployElements.ExtractOne(DeployId.Archer); var wallbreaker = deployElements.ExtractOne(DeployId.WallBreaker); var ragespell = deployElements.ExtractOne(DeployId.Rage); var healspell = deployElements.ExtractOne(DeployId.Heal); _freezeSpell = deployElements.ExtractOne(DeployId.Freeze); var heroes = deployElements .Extract(u => (UserSettings.UseKing && u.ElementType == DeployElementType.HeroKing) || (UserSettings.UseQueen && u.ElementType == DeployElementType.HeroQueen) || (UserSettings.UseWarden && u.ElementType == DeployElementType.HeroWarden)) .ToList(); //open near to dark elixer with 4 earthquakes if (earthQuakeSpell?.Sum(u => u.Count) >= 4) { foreach (var unit in earthQuakeSpell) { foreach (int t in Deploy.AtPoint(unit, _earthQuakePoint, unit.Count)) { yield return(t); } } } else { _useJump = true; } yield return(1000); if (giant?.Count > 0) { foreach (int t in Deploy.AlongLine(giant, _attackLine.Item1, _attackLine.Item2, 6, 6)) { yield return(t); } } yield return(1000); if (wizard?.Count > 0) { foreach (int t in Deploy.AlongLine(wizard, _attackLine.Item1, _attackLine.Item2, 8, 4)) { yield return(t); } } if (barbarian?.Count > 0) { while (barbarian.Count > 0) { int count = barbarian.Count; Log.Info($"[Goblin Knife] Deploying {barbarian.PrettyName}"); foreach (int t in Deploy.AlongLine(barbarian, _attackLine.Item1, _attackLine.Item2, count, 4)) { yield return(t); } // prevent infinite loop if deploy point is on red if (barbarian.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {barbarian.PrettyName}"); break; } } if (archer?.Count > 0) { int archerCount = (int)(archer.Count / 2); Log.Info($"[Goblin Knife] Deploying {archer.PrettyName} "); foreach (int t in Deploy.AlongLine(archer, _attackLine.Item1, _attackLine.Item2, archerCount, 4)) { yield return(t); } } yield return(3000); if (ragespell?.Count >= 2) { foreach (int t in Deploy.AtPoint(ragespell, _ragePoint)) { yield return(t); } } if (wallbreaker?.Count > 0) { Log.Info($"[Goblin Knife] send test {wallbreaker.PrettyName} to check for bombs"); foreach (int t in Deploy.AtPoint(wallbreaker, _orgin, 1)) { yield return(t); } } yield return(1000); while (wallbreaker?.Count > 0) { int count = wallbreaker.Count; Log.Info("[Goblin Knife] send wall breakers in groups"); foreach (int t in Deploy.AtPoint(wallbreaker, _orgin, 3)) { yield return(t); } // prevent infinite loop if deploy point is on red if (wallbreaker.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {wallbreaker.PrettyName}"); break; } while (giant?.Count > 0) { int count = giant.Count; Log.Info($"[Goblin Knife] Deploying {giant.PrettyName} x{count}"); foreach (int t in Deploy.AtPoint(giant, _orgin, count)) { yield return(t); } // prevent infinite loop if deploy point is on red if (giant.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {giant.PrettyName}"); break; } yield return(1000); while (wizard?.Count > 0) { int count = wizard.Count; Log.Info($"[Goblin Knife] Deploying {wizard}"); foreach (int t in Deploy.AlongLine(wizard, _attackLine.Item1, _attackLine.Item2, 4, 2)) { yield return(t); } // prevent infinite loop if deploy point is on red if (wizard.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {wizard.PrettyName}"); break; } if (archer?.Count > 0) { Log.Info($"[Goblin Knife] Deploying {archer.PrettyName} "); foreach (int t in Deploy.AlongLine(archer, _attackLine.Item1, _attackLine.Item2, archer.Count, 4)) { yield return(t); } } yield return(1500); if (_useJump == true && jumpSpell?.Count > 0) { foreach (int t in Deploy.AtPoint(jumpSpell, _jumpPoint)) { yield return(t); } } if (healspell?.Count > 0) { foreach (int t in Deploy.AtPoint(healspell, _healPoint)) { yield return(t); } } if (clanCastle?.Count > 0) { Log.Info($"[Goblin Knife] Deploying {clanCastle.PrettyName}"); foreach (int t in Deploy.AtPoint(clanCastle, _orgin)) { yield return(t); } } if (heroes.Any()) { _delay = 1000; foreach (DeployElement hero in heroes.Where(u => u.Count > 0)) { foreach (int t in Deploy.AtPoint(hero, _orgin)) { yield return(t); } } watchHeroes = true; } yield return(_delay); while (goblin?.Count > 0) { int testGoblins = (int)(goblin.Count / 3); Log.Info($"[Goblin Knife] Deploying {goblin.PrettyName} x{testGoblins}"); foreach (int t in Deploy.AtPoint(goblin, _orgin, testGoblins)) { yield return(t); } yield return(2000); int count = goblin.Count; Log.Info($"[Goblin Knife] Deploying {goblin.PrettyName} x{count}"); foreach (int t in Deploy.AtPoint(goblin, _orgin, count)) { yield return(t); } // prevent infinite loop if deploy point is on red if (goblin.Count != count) { continue; } Log.Warning($"[Goblin Knife] Couldn't deploy {goblin.PrettyName}"); break; } //use freeze if inferno is found if (_freezeSpell?.Count > 0) { var infernos = InfernoTower.Find(); // find and watch inferno towers if (infernos != null) { foreach (var inferno in infernos) { inferno.FirstActivated += DropFreeze; inferno.StartWatching(); } } } yield return(200); foreach (int t in Deploy.AtPoint(healspell, _target)) { yield return(t); } foreach (int t in Deploy.AtPoint(ragespell, _target)) { yield return(t); } if (watchHeroes == true) { Deploy.WatchHeroes(heroes, 7000); } }
private void CreateDeployPoints(bool qw) { var target = TownHall.Find()?.Location.GetCenter() ?? DarkElixirStorage.Find().FirstOrDefault()?.Location.GetCenter() ?? new PointFT(0, 0); // don't include corners in case build huts are there var maxRedPointX = GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Max(point => point.X) + 1 ?? GameGrid.RedZoneExtents.MaxX; var minRedPointX = GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Min(point => point.X) - 1 ?? GameGrid.RedZoneExtents.MinX; var maxRedPointY = GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Max(point => point.Y) + 1 ?? GameGrid.RedZoneExtents.MaxY; var minRedPointY = GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Min(point => point.Y) - 1 ?? GameGrid.RedZoneExtents.MinY; // build a box around the base var left = new PointFT(minRedPointX, maxRedPointY); var top = new PointFT(maxRedPointX, maxRedPointY); var right = new PointFT(maxRedPointX, minRedPointY); var bottom = new PointFT(minRedPointX, minRedPointY); // border around the base _border = new RectangleT((int)minRedPointX, (int)maxRedPointY, (int)(maxRedPointX - minRedPointX), (int)(minRedPointY - maxRedPointY)); // core is center of the box _core = _border.GetCenter(); var orginPoints = new[] { new PointFT(maxRedPointX, _core.Y), new PointFT(minRedPointX, _core.Y), new PointFT(_core.X, maxRedPointY), new PointFT(_core.X, minRedPointY) }; _orgin = new Container <PointFT> { Item = orginPoints.OrderBy(point => point.DistanceSq(target)).First() }; if (_orgin.Item.X > _core.X) { Log.Info("[Breakthrough] Attacking from the top right"); var redLinePoint = GameGrid.RedPoints .Where(point => point.Y > -10 && point.Y < 10)? .Max(point => point.X) ?? GameGrid.RedZoneExtents.MaxX; if (qw) { _qwPoint = right; _queenRagePoint = new PointFT(right.X - 5, right.Y + 5); _healerPoint = new PointFT(24f, -24f); _attackLine = new Tuple <PointFT, PointFT>(top, _orgin.Item.Midpoint(right)); } else { _attackLine = new Tuple <PointFT, PointFT>(top, right); _healerPoint = new PointFT(24f, _core.Y); } _healPoint = new PointFT(redLinePoint - 12f, _core.Y); _ragePoint = new PointFT(redLinePoint - 9f, _core.Y); } else if (_orgin.Item.X < _core.X) { Log.Info("[Breakthrough] Attacking from the bottom left"); var redLinePoint = GameGrid.RedPoints .Where(point => point.Y > -10 && point.Y < 10)? .Min(point => point.X) ?? GameGrid.RedZoneExtents.MinX; if (qw) { _qwPoint = left; _queenRagePoint = new PointFT(left.X + 5, left.Y - 5); _healerPoint = new PointFT(-24f, 24f); _attackLine = new Tuple <PointFT, PointFT>(bottom, _orgin.Item.Midpoint(left)); } else { _healerPoint = new PointFT(-24f, _core.Y); _attackLine = new Tuple <PointFT, PointFT>(bottom, left); } _healPoint = new PointFT(redLinePoint + 12, _core.Y); _ragePoint = new PointFT(redLinePoint + 9, _core.Y); } else if (_orgin.Item.Y > _core.Y) { Log.Info("[Breakthrough] Attacking from the top left"); var redLinePoint = GameGrid.RedPoints .Where(point => point.X > -10 && point.X < 10)? .Max(point => point.Y) ?? GameGrid.RedZoneExtents.MaxY; if (qw) { _qwPoint = left; _queenRagePoint = new PointFT(left.X + 5f, left.Y - 5f); _healerPoint = new PointFT(-24f, 24f); _attackLine = new Tuple <PointFT, PointFT>(top, _orgin.Item.Midpoint(left)); } else { _healerPoint = new PointFT(_core.X, 24f); _attackLine = new Tuple <PointFT, PointFT>(left, top); } _healPoint = new PointFT(_core.X, redLinePoint - 12f); _ragePoint = new PointFT(_core.X, redLinePoint - 9f); } else // (orgin.Y < core.Y) { Log.Info("[Breakthrough] Attacking from the bottom right"); var redLinePoint = GameGrid.RedPoints .Where(point => point.X > -10 && point.X < 10)? .Min(point => point.Y) ?? GameGrid.RedZoneExtents.MinY; if (qw) { _qwPoint = right; _queenRagePoint = new PointFT(right.X - 5, right.Y + 5); _healerPoint = new PointFT(24f, -24f); _attackLine = new Tuple <PointFT, PointFT>(bottom, _orgin.Item.Midpoint(right)); } else { _healerPoint = new PointFT(_core.X, -24f); _attackLine = new Tuple <PointFT, PointFT>(right, bottom); } _healPoint = new PointFT(_core.X, redLinePoint + 12); _ragePoint = new PointFT(_core.X, redLinePoint + 9); } }
public static Target[] GenerateTargets(float minimumDistance, bool ignoreGold, bool ignoreElixir, CacheBehavior behavior = CacheBehavior.Default, bool outputDebugImage = false) { // Find all Collectors & storages just sitting around... List <Building> buildings = new List <Building>(); if (!ignoreGold) { //User has Gold min set to ZERO - which means Dont include Gold Targets buildings.AddRange(GoldMine.Find(behavior)); buildings.AddRange(GoldStorage.Find(behavior)); } if (!ignoreElixir) { //User has Elixir min set to ZERO - which means Dont include Elixir Targets buildings.AddRange(ElixirCollector.Find(behavior)); buildings.AddRange(ElixirStorage.Find(behavior)); } //We always includ DarkElixir - Because who doesnt love dark Elixir? buildings.AddRange(DarkElixirDrill.Find(behavior)); buildings.AddRange(DarkElixirStorage.Find(behavior)); List <Target> targetList = new List <Target>(); foreach (Building building in buildings) { Target current = new Target(); current.TargetBuilding = building; current.Center = building.Location.GetCenter(); current.NearestRedLine = GameGrid.RedPoints.OrderBy(p => p.DistanceSq(current.Center)).First(); current.CenterToRedline = current.Center.DistanceSq(current.NearestRedLine); Log.Debug($"[Berts Algorithms] DistanceSq from {current.Name} to red point: {current.CenterToRedline.ToString("F1")}"); if (current.CenterToRedline < minimumDistance) //Compare distance to Redline to the Minimum acceptable distance Passed in { current.DeployGrunts = current.Center.PointOnLineAwayFromEnd(current.NearestRedLine, _gruntDeployDistanceFromRedline); //Barbs & Goblins current.DeployRanged = current.Center.PointOnLineAwayFromEnd(current.NearestRedLine, _rangedDeployDistanceFromRedline); //Archers & Minions targetList.Add(current); } } if (outputDebugImage) { var d = DateTime.UtcNow; var debugFileName = $"Human Barch {d.Year}-{d.Month}-{d.Day} {d.Hour}-{d.Minute}-{d.Second}-{d.Millisecond}"; //Get a screen Capture of all targets we found... using (Bitmap canvas = Screenshot.Capture()) { Screenshot.Save(canvas, $"{debugFileName}_1"); foreach (var building in buildings) { var color = Color.White; if (building.GetType() == typeof(ElixirCollector) || building.GetType() == typeof(ElixirStorage)) { color = Color.Violet; } if (building.GetType() == typeof(GoldMine) || building.GetType() == typeof(GoldStorage)) { color = Color.Gold; } if (building.GetType() == typeof(DarkElixirDrill) || building.GetType() == typeof(DarkElixirStorage)) { color = Color.Brown; } //Draw a target on each building. Visualize.Target(canvas, building.Location.GetCenter(), 40, color); } //Save the Image to the Debug Folder... Screenshot.Save(canvas, $"{debugFileName}_2"); } //Get a screen Capture of all targets we found... using (Bitmap canvas = Screenshot.Capture()) { foreach (var target in targetList) { var color = Color.White; if (target.TargetBuilding.GetType() == typeof(ElixirCollector) || target.TargetBuilding.GetType() == typeof(ElixirStorage)) { color = Color.Violet; } if (target.TargetBuilding.GetType() == typeof(GoldMine) || target.TargetBuilding.GetType() == typeof(GoldStorage)) { color = Color.Gold; } if (target.TargetBuilding.GetType() == typeof(DarkElixirDrill) || target.TargetBuilding.GetType() == typeof(DarkElixirStorage)) { color = Color.Brown; } //Draw a target on each building. Visualize.Target(canvas, target.TargetBuilding.Location.GetCenter(), 40, color); Visualize.Target(canvas, target.DeployGrunts, 20, color); Visualize.Target(canvas, target.DeployRanged, 20, color); } //Save the Image to the Debug Folder... Screenshot.Save(canvas, $"{debugFileName}_3"); } Log.Debug("[Berts Algorithms] Collector/Storage & Target Debug Images Saved!"); } Log.Debug($"[Berts Algorithms] Found {targetList.Count} deploy points"); return(targetList.ToArray()); }