예제 #1
0
        /// <summary>
        /// ZapQuake routine for destroying AirDefenses
        /// </summary>
        /// <param name="targets">AirDefense targets to destroy</param>
        /// <param name="earthQuakeSpells">Extracted Earthquake deployelement</param>
        /// <param name="lightningSpells">Extracted Lightning deployelement</param>
        /// <param name="waitUntilSpellAnimationIsOver">Bool if we should wait until the spell effect animation is completely gone</param>
        /// <returns></returns>
        IEnumerable <int> ZapQuakeAirDefenses(List <AirDefense> targets, DeployElement earthQuakeSpells, DeployElement lightningSpells, bool waitUntilSpellAnimationIsOver = true)
        {
            // Find targets until we have no more targets available
            for (var i = 0; i < targets.Count; i++)
            {
                Log.Info($"[LavaLoon] Going to destroy Air Defense {i + 1}");

                // Drop one earthquake spell and two lightningspells each Air Defense
                Log.Info($"[LavaLoon] Deploying Earthquake and Lightning spells for AirDefense {i + 1}");
                foreach (var t in Deploy.AtPoint(earthQuakeSpells, targets[i].Location.GetCenter()))
                {
                    yield return(t);
                }

                foreach (var t in Deploy.AtPoint(lightningSpells, targets[i].Location.GetCenter(), 2))
                {
                    yield return(t);
                }
            }
            // This should be prevent a CheckForDestroyed rescan while the animation is still going on (For example: http://i.imgur.com/SDPU5EG.jpg )
            if (waitUntilSpellAnimationIsOver)
            {
                Log.Debug("[LavaLoon] Waiting for 10 seconds until the zapquake animation is completely gone");
                yield return(10 * 1000);
            }
        }
        public static IEnumerable <int> DeployBalloons()
        {
            yield return(dragonAttack ? 2000 : (babyLoon ? 500 : 0));

            if (balloon?.Count > 0)
            {
                if (!dragonAttack || balloon.Count > 10)
                {
                    foreach (var t in Deploy.AlongLine(balloon, AllInOnePushDeploy.AttackLine.Item1, AllInOnePushDeploy.AttackLine.Item2, balloon.Count, 2))
                    {
                        yield return(t);
                    }
                }
                else
                {
                    var count = balloon.Count / 2;
                    foreach (var t in Deploy.AtPoint(balloon, AllInOnePushDeploy.FirstFunnellingPoint, count))
                    {
                        yield return(t);
                    }

                    foreach (var t in Deploy.AtPoint(balloon, AllInOnePushDeploy.SecondFunnellingPoint, count))
                    {
                        yield return(t);
                    }
                }
            }
        }
예제 #3
0
        public override IEnumerable <int> AttackRoutine()
        {
            Log.Info("[16 Fingers] Attack start");

            // Get all the units available
            Log.Debug("Scanning troops");

            var unitDeployElements = Deploy.GetTroops();

            // remove spells
            unitDeployElements.Extract(DeployElementType.Spell);

            var heroesAndClanCastle = unitDeployElements.Extract(u => u.IsHero || u.Id == DeployId.ClanCastle);

            var unitGroups = new Dictionary <string, DeployElement[]>
            {
                { "tank units", unitDeployElements.Extract(AttackType.Tank).ToArray() },
                { "attack units", unitDeployElements.Extract(AttackType.Damage).ToArray() },
                { "heal units", unitDeployElements.Extract(AttackType.Heal).ToArray() },
                { "wallbreak units", unitDeployElements.Extract(AttackType.Wallbreak).ToArray() },
            };

            PointFT left   = new PointFT(PointFT.MinRedZoneX, PointFT.MaxRedZoneY);
            PointFT top    = new PointFT(PointFT.MaxRedZoneX, PointFT.MaxRedZoneY);
            PointFT right  = new PointFT(PointFT.MaxRedZoneX, PointFT.MinRedZoneY);
            PointFT bottom = new PointFT(PointFT.MinRedZoneX, PointFT.MinRedZoneY);

            Tuple <PointFT, PointFT>[] lines =
            {
                new Tuple <PointFT, PointFT>(left,  top),
                new Tuple <PointFT, PointFT>(right, top),
                new Tuple <PointFT, PointFT>(left,  bottom),
                new Tuple <PointFT, PointFT>(right, bottom),
            };

            foreach (var unitGroup in unitGroups)
            {
                Logger.Info("[16 Fingers] Deploying " + unitGroup.Key);
                foreach (var y in Deploy.AlongLines(unitGroup.Value, lines, 4))
                {
                    yield return(y);
                }
            }

            Logger.Info("[16 Fingers] Deploying heroes");
            var heroPoint = new Container <PointFT> {
                Item = new PointFT((lines[0].Item1.X + lines[0].Item2.X) / 2, (lines[0].Item1.Y + lines[0].Item2.Y) / 2)
            };

            foreach (var delay in Deploy.AtPoint(heroesAndClanCastle.Where(d => d?.Count > 0).ToArray(), heroPoint, 1, 0, (int)(UserSettings.WaveDelay * 1000)))
            {
                yield return(delay);
            }

            // Remove clan castle before watching heroes
            heroesAndClanCastle.ExtractOne(x => x.ElementType == DeployElementType.ClanTroops);
            Deploy.WatchHeroes(heroesAndClanCastle);

            Logger.Info("[16 Fingers] Deploy done");
        }
        public static IEnumerable <int> AirFunnelling()
        {
            if (dragon?.Count > 0)
            {
                foreach (var t in Deploy.AtPoint(dragon, AllInOnePushDeploy.AttackLine.Item1))
                {
                    yield return(t);
                }

                foreach (var t in Deploy.AtPoint(dragon, AllInOnePushDeploy.AttackLine.Item2))
                {
                    yield return(t);
                }
                if (!lavaloonion)
                {
                    yield return(new Random().Next(8000, 9000));
                }
            }
            else if (babyDragon?.Count > 0)
            {
                foreach (var t in Deploy.AtPoint(babyDragon, AllInOnePushDeploy.AttackLine.Item1))
                {
                    yield return(t);
                }

                foreach (var t in Deploy.AtPoint(babyDragon, AllInOnePushDeploy.AttackLine.Item2))
                {
                    yield return(t);
                }
                if (!lavaloonion)
                {
                    yield return(new Random().Next(5000, 6500));
                }
            }
        }
        public static IEnumerable <int> DeployWB()
        {
            if (wallbreaker?.Count > 0)
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] droping wallBreakers");

                foreach (var t in Deploy.AtPoint(wallbreaker, AllInOnePushDeploy.Origin, 1))
                {
                    yield return(t);
                }

                yield return(800);

                while (wallbreaker?.Count > 0)
                {
                    var count = wallbreaker.Count;
                    foreach (var t in Deploy.AtPoint(wallbreaker, AllInOnePushDeploy.Origin, 3))
                    {
                        yield return(t);
                    }

                    yield return(400);

                    // prevent infinite loop if deploy point is on red
                    if (wallbreaker.Count != count)
                    {
                        continue;
                    }

                    Log.Warning($"[{AllInOnePushDeploy.AttackName}] Couldn't deploy {wallbreaker.PrettyName}");
                    break;
                }
            }
        }
        // Air deploy methods

        public static IEnumerable <int> ZapAirDefense()
        {
            // Todo: use 3 lighting if th7.

            var airDefenses      = AirDefense.Find(CacheBehavior.ForceScan);
            var targetAirDefense = airDefenses
                                   .OrderBy(a => a.Location.GetCenter().DistanceSq(AllInOnePushDeploy.Origin))
                                   .ElementAtOrDefault(2) ?? airDefenses
                                   .OrderBy(a => a.Location.GetCenter().DistanceSq(AllInOnePushDeploy.Origin))
                                   .ElementAtOrDefault(1) ?? airDefenses
                                   .FirstOrDefault();

            var zapPoint = targetAirDefense.Location.GetCenter();


            if (eq?.Sum(u => u.Count) > 0)
            {
                foreach (var unit in eq)
                {
                    foreach (var t in Deploy.AtPoint(unit, zapPoint))
                    {
                        yield return(t);
                    }
                    break;
                }
            }

            foreach (var t in Deploy.AtPoint(lightingSpell, zapPoint, 2))
            {
                yield return(t);
            }

            yield return(new Random().Next(1200, 2500));
        }
예제 #7
0
        /// <summary>
        /// Drop EQ spells on drills to get DE beacuse max EQ will gain 320 DE from max drill
        /// </summary>
        /// <param name="drillLevel">minmum drill level</param>
        /// <param name="spells">available spells in unitsbar</param>
        /// <returns>Drop EQ spells on drills</returns>
        public static IEnumerable <int> UseEQOnDrills(int drillLevel, List <DeployElement> spells)
        {
            var EQSpell = spells.Extract(u => u.Id == DeployId.Earthquake);
            var EQCount = EQSpell.Sum(u => u.Count);

            if (EQCount > 0)
            {
                Log.Info($"{SmartFourFingersDeploy.AttackName} start use EQ on drills");
                GetDrills(drillLevel);

                if (availableDrills.Any())
                {
                    foreach (var d in availableDrills)
                    {
                        var eq = EQSpell.FirstOrDefault()?.Count > 0 ? EQSpell.FirstOrDefault() : EQSpell.LastOrDefault();
                        if (eq.Count > 0)
                        {
                            foreach (var t in Deploy.AtPoint(eq, d.Location.GetCenter()))
                            {
                                yield return(t);
                            }
                        }
                    }
                }
                else
                {
                    Log.Warning($"{SmartFourFingersDeploy.AttackName} no Drills found to use EQ on !!");
                }
            }
            else
            {
                Log.Warning($"{SmartFourFingersDeploy.AttackName} no EarthQuake spells found to use on drills");
            }
        }
        public static IEnumerable <int> DeployGiants()
        {
            var jumpSpellCount = jumpSpell?.Sum(u => u.Count);

            if ((useJump && jumpSpellCount >= 2) || (!useJump && jumpSpellCount >= 1))
            {
                foreach (var unit in jumpSpell)
                {
                    foreach (var t in Deploy.AtPoint(unit, AllInOnePushDeploy.FirstJumpPoint))
                    {
                        yield return(t);
                    }
                }
            }

            if (giant?.Count > 0)
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy Giants ...");
                foreach (var t in Deploy.AlongLine(giant, AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint, 8, 4))
                {
                    yield return(t);
                }

                var waves = wizard?.Count >= 8 ? 2 : 1;
                foreach (var f in DeployWizard(waves))
                {
                    yield return(f);
                }

                foreach (var f in DeployWB())
                {
                    yield return(f);
                }

                foreach (var t in Deploy.AtPoint(giant, AllInOnePushDeploy.Origin, giant.Count))
                {
                    yield return(t);
                }
            }

            if (clanCastle?.Count > 0 && AllInOnePushDeploy.ClanCastleSettings == 2)
            {
                foreach (var t in Deploy.AtPoint(clanCastle, AllInOnePushDeploy.Origin))
                {
                    yield return(t);
                }
            }

            //if one golem deploy after funnlling
            if (golem?.Count > 0)
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy Golem ...");
                foreach (var t in Deploy.AlongLine(golem, AllInOnePushDeploy.AttackLine.Item1, AllInOnePushDeploy.AttackLine.Item2, golem.Count, golem.Count))
                {
                    yield return(t);
                }
            }
        }
예제 #9
0
        public override IEnumerable <int> AttackRoutine()
        {
            // Bottom right side
            var rightBottom = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MinY);
            var bottomRight = new PointFT((float)GameGrid.MinX + 8, (float)GameGrid.DeployExtents.MinY);

            var center = new PointFT(bottomRight.X + 0.5f * (rightBottom.X - bottomRight.X),
                                     bottomRight.Y + 0.5f * (rightBottom.Y - bottomRight.Y));

            // Screenshot for 3 points for the deployment line
            using (var bmp = Screenshot.Capture())
            {
                using (var g = Graphics.FromImage(bmp))
                {
                    Visualize.RectangleT(bmp, new RectangleT((int)rightBottom.X, (int)rightBottom.Y, 1, 1), new Pen(Color.Blue));
                    Visualize.RectangleT(bmp, new RectangleT((int)bottomRight.X, (int)bottomRight.Y, 1, 1), new Pen(Color.Blue));

                    Visualize.RectangleT(bmp, new RectangleT((int)center.X, (int)center.Y, 1, 1), new Pen(Color.White));
                }
                var d = DateTime.UtcNow;
                Screenshot.Save(bmp, "Bottom Right {d.Year}-{d.Month}-{d.Day} {d.Hour}-{d.Minute}-{d.Second}-{d.Millisecond}");
            }

            // Deploy troops
            var units = Deploy.GetTroops();

            units.OrderForDeploy();
            for (var i = 3; i >= 1; i--)
            {
                switch (i)
                {
                case 3:
                    point = rightBottom;
                    break;

                case 2:
                    point = bottomRight;
                    break;

                case 1:
                    point = center;
                    break;
                }

                foreach (var unit in units)
                {
                    if (unit?.Count > 0)
                    {
                        foreach (var t in Deploy.AtPoint(unit, point, unit.Count / i))
                        {
                            yield return(t);
                        }
                    }
                }
            }
        }
 public static IEnumerable <int> DeploySpell(List <DeployElement> spell, PointFT point)
 {
     if (spell.Sum(u => u.Count) > 0)
     {
         var unit = spell.FirstOrDefault().Count > 0 ? spell.FirstOrDefault() : spell.LastOrDefault();
         foreach (var t in Deploy.AtPoint(unit, point))
         {
             yield return(t);
         }
     }
 }
        private static void DropFreeze(object sender, EventArgs e)
        {
            var inferno = (InfernoTower)sender;

            foreach (var t in Deploy.AtPoint(DeploymentMethods.freezeSpell, inferno.Location.GetCenter()))
            {
                Thread.Sleep(t);
            }

            inferno.StopWatching();
        }
        IEnumerable <int> DeployDragons()
        {
            var dragons = deployElements.FirstOrDefault(u => u.Id == DeployId.Dragon);

            if (dragons?.Count > 2)
            {
                Log.Info($"{Tag} Deploying two Dragons to Create a funnel to direct main force at Dark Elixer Storage...");
                //Deploy two dragons - one at each funel point.
                foreach (var t in Deploy.AtPoint(dragons, deFunnelPoints[0], 1))
                {
                    yield return(t);
                }

                yield return(Rand.Int(500, 1500));

                foreach (var t in Deploy.AtPoint(dragons, deFunnelPoints[1], 1))
                {
                    yield return(t);
                }

                yield return(Rand.Int(1000, 1500)); // pause for a little while... - Long enought for dragons to begin to create the funnel.
            }
            else
            {
                Log.Error($"{Tag} Two Dragons to create the funnel do not exist. {dragons?.Count ?? 0} exists...");
            }

            if (dragons?.Count > 0)
            {
                //Deploy our main force of dragons all on one spot...
                Log.Info($"{Tag} Deploying Main Force of Dragons...");
                foreach (var t in Deploy.AtPoint(dragons, mainTarget.DeployGrunts, dragons.Count))
                {
                    yield return(t);
                }
            }
            else
            {
                Log.Error($"{Tag} When Trying to deploy Main Force of Dragons - None Exist!");
            }

            if (dragons?.Count > 0)
            {
                Log.Error($"{Tag} Main Force of Dragons Not Fully Deployed! Trying to drop them on the Edge of the map...");
                //Find the edge, by adding an arbitrary large distance to the point, and the function will return a safe point always on the map.
                var mapEdge = HumanLikeAlgorithms.Origin.PointOnLineAwayFromEnd(mainTarget.DeployGrunts, 30);

                foreach (var t in Deploy.AtPoint(dragons, mapEdge, dragons.Count))
                {
                    yield return(t);
                }
            }
        }
        public static IEnumerable <int> DeployJump()
        {
            if (useJump && jumpSpell.Sum(u => u.Count) > 0)
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy jump next to Townhall");

                var unit = jumpSpell.FirstOrDefault().Count > 0 ? jumpSpell.FirstOrDefault() : jumpSpell.LastOrDefault();
                foreach (var t in Deploy.AtPoint(unit, AllInOnePushDeploy.SecondJumpPoint))
                {
                    yield return(t);
                }
            }
        }
        public static IEnumerable <int> DeployLava()
        {
            if (lava?.Count >= 2)
            {
                var count = lava.Count / 2;

                foreach (var t in Deploy.AtPoints(lava, new PointFT[] { AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint }, count, 0, 200, 5))
                {
                    yield return(t);
                }

                if (lava?.Count > 0)
                {
                    foreach (var t in Deploy.AtPoint(lava, AllInOnePushDeploy.SecondFunnellingPoint, lava.Count))
                    {
                        yield return(t);
                    }
                }

                if (clanCastle?.Count > 0 && AllInOnePushDeploy.ClanCastleSettings > 0)
                {
                    foreach (var t in Deploy.AtPoint(clanCastle, AllInOnePushDeploy.FirstFunnellingPoint))
                    {
                        yield return(t);
                    }
                }
            }
            else if (lava?.Count == 1)
            {
                if (clanCastle?.Count > 0 && AllInOnePushDeploy.ClanCastleSettings > 0)
                {
                    foreach (var t in Deploy.AtPoint(clanCastle, AllInOnePushDeploy.FirstFunnellingPoint))
                    {
                        yield return(t);
                    }

                    foreach (var t in Deploy.AtPoint(lava, AllInOnePushDeploy.SecondFunnellingPoint))
                    {
                        yield return(t);
                    }
                }
                else
                {
                    foreach (var t in Deploy.AtPoint(lava, AllInOnePushDeploy.Origin))
                    {
                        yield return(t);
                    }
                }
            }
        }
        IEnumerable <int> DeployKing()
        {
            var king = deployElements.FirstOrDefault(u => u.IsHero && u.Id == DeployId.King);

            if (UserSettings.UseKing && king != null)
            {
                //Deploy the king
                Log.Info($"{Tag} Deploying King...");
                foreach (var t in Deploy.AtPoint(king, mainTarget.DeployGrunts))
                {
                    yield return(t);
                }

                watchHeroes = true;
            }
        }
예제 #16
0
        IEnumerable <int> DeployWarden()
        {
            var warden = deployElements.FirstOrDefault(u => u.IsHero && u.Id == DeployId.Warden);

            if (UserSettings.UseWarden && warden != null)
            {
                Log.Info($"{Tag} Deploying Warden...");
                foreach (var t in Deploy.AtPoint(warden, darkElixirStorage.DeployRanged))
                {
                    yield return(t);
                }
                yield return(Rand.Int(500, 1000)); //Wait

                watchHeroes = true;
            }
        }
        IEnumerable <int> DeployQueen()
        {
            var queen = deployElements.FirstOrDefault(u => u.IsHero && u.Id == DeployId.Queen);

            if (UserSettings.UseQueen && queen != null)
            {
                Log.Info($"{Tag} Deploying Queen...");
                foreach (var t in Deploy.AtPoint(queen, mainTarget.DeployGrunts))
                {
                    yield return(t);
                }
                yield return(Rand.Int(500, 1000)); //Wait

                watchHeroes = true;
            }
        }
 public static IEnumerable <int> DeployJump()
 {
     if (useJump && jumpSpell.Sum(u => u.Count) > 0)
     {
         Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy jump next to Townhall");
         foreach (var unit in jumpSpell)
         {
             unit.Select();
             foreach (var t in Deploy.AtPoint(unit, AllInOnePushDeploy.SecondJumpPoint))
             {
                 yield return(t);
             }
             break;
         }
     }
 }
        IEnumerable <int> DeployHealers()
        {
            var healers = deployElements.FirstOrDefault(u => u.Id == DeployId.Healer);

            if (healers?.Count > 0)
            {
                Log.Info($"{Tag} Deploying Healers near Heros...");
                foreach (var t in Deploy.AtPoint(healers, mainTarget.DeployGrunts, healers.Count))
                {
                    yield return(t);
                }
            }
            else
            {
                Log.Info($"{Tag} No Healers found to Deploy...");
            }
        }
        IEnumerable <int> DeployClanCastle()
        {
            var clanCastle = deployElements.FirstOrDefault(u => u.ElementType == DeployElementType.ClanTroops);

            if (clanCastle?.Count > 0 && UserSettings.UseClanTroops)
            {
                Log.Info($"{Tag} Deploying Clan Castle Behind Heros...");
                foreach (var t in Deploy.AtPoint(clanCastle, mainTarget.DeployGrunts, clanCastle.Count))
                {
                    yield return(t);
                }
            }
            else
            {
                Log.Info($"{Tag} No Clan Castle Troops found to Deploy...");
            }
        }
        IEnumerable <int> DeployWallBreakers()
        {
            var wallBreakers = deployElements.FirstOrDefault(u => u.Id == DeployId.WallBreaker);

            if (wallBreakers?.Count > 0)
            {
                Log.Info($"{Tag} Deploying {wallBreakers.Count} {wallBreakers.PrettyName}...");
                foreach (var t in Deploy.AtPoint(wallBreakers, mainTarget.DeployGrunts, wallBreakers.Count))
                {
                    yield return(t);
                }
            }
            else
            {
                Log.Info($"{Tag} No WallBreakers found to Deploy...");
            }
        }
        public static IEnumerable <int> DeployUnusedTroops()
        {
            // Check unit bar for unused troops
            Log.Warning($"{AllInOnePushDeploy.AttackName} search for unused troops !!");
            var unusedTroops = Deploy.GetTroops();
            var spell        = unusedTroops.Extract(DeployElementType.Spell);

            if (unusedTroops.Sum(u => u.Count) > 0)
            {
                unusedTroops.OrderForDeploy();
                foreach (var u in unusedTroops)
                {
                    if (u?.Count > 0)
                    {
                        Log.Warning($"we found {u.Count}x {u.PrettyName}");
                    }
                }

                Log.Info($"[{AllInOnePushDeploy.AttackName}] deploy unused troops");
                foreach (var unit in unusedTroops)
                {
                    if (unit?.Count > 0)
                    {
                        if (unit.IsRanged)
                        {
                            foreach (var t in Deploy.AlongLine(unit, AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint, unit.Count, 4))
                            {
                                yield return(t);
                            }
                        }
                        else
                        {
                            foreach (var t in Deploy.AtPoint(unit, AllInOnePushDeploy.Origin, unit.Count))
                            {
                                yield return(t);
                            }
                        }
                    }
                }
            }
            else
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] all Troops have been deployed");
            }
        }
        IEnumerable <int> DeployLavaHounds()
        {
            var lavaHounds = deployElements.FirstOrDefault(u => u.Id == DeployId.LavaHound);

            //Deploy Lava Hounds - TODO Make the Drop position better for these guys...
            if (lavaHounds?.Count > 0)
            {
                Log.Info($"{Tag} Deploying Lava Hounds...");
                foreach (var t in Deploy.AtPoint(lavaHounds, mainTarget.DeployGrunts, lavaHounds.Count))
                {
                    yield return(t);
                }
            }
            else
            {
                Log.Info($"{Tag} No LavaHounds found to Deploy...");
            }
        }
        IEnumerable <int> DeployRageSpell()
        {
            var rageSpells = deployElements.FirstOrDefault(u => u.ElementType == DeployElementType.Spell && u.Id == DeployId.Rage);

            if (rageSpells?.Count > 0)
            {
                //Point on line between Center of DE Storage, and The Deploy Point of the Dragons... Such that the spell edge is near the DE Storage.
                var rageDropPoint = mainTarget.Center.PointOnLineAwayFromStart(mainTarget.DeployGrunts, 6f);
                Log.Info($"{Tag} Deploying ONE Rage Spell Close to DE Storage....");
                foreach (var t in Deploy.AtPoint(rageSpells, rageDropPoint, 1))
                {
                    yield return(t);
                }
            }
            else
            {
                Log.Info($"{Tag} No Rage Spells found to Deploy...");
            }
        }
        /// <summary>
        /// ZapQuakes (2 lightningspells + 1 Earthquake) one Target (AirDefense)
        /// </summary>
        /// <param name="target">Target to Zapquake</param>
        /// <param name="earthQuakeSpell">Earthquake deployelement</param>
        /// <param name="lightningSpell">Lightningspell deployelement</param>
        /// <returns></returns>
        IEnumerable <int> ZapQuakeTarget(PointFT target, DeployElement earthQuakeSpell, DeployElement lightningSpell)
        {
            if (earthQuakeSpell?.Count < 1 || lightningSpell?.Count < 2)
            {
                Log.Debug("[BabyLoon] Not enough spells for ZapQuake available");
                yield break;
            }

            // Drop one earthquake spell and two lightningspells onto target
            Log.Info($"[BabyLoon] Deploying Earthquake and Lightning spells");
            foreach (var t in Deploy.AtPoint(earthQuakeSpell, target))
            {
                yield return(t);
            }

            foreach (var t in Deploy.AtPoint(lightningSpell, target, 2))
            {
                yield return(t);
            }
        }
        IEnumerable <int> DeployLeftoverTroops()
        {
            var dragons      = deployElements.FirstOrDefault(u => u.Id == DeployId.Dragon);
            var balloons     = deployElements.FirstOrDefault(u => u.Id == DeployId.Balloon);
            var hogs         = deployElements.FirstOrDefault(u => u.Id == DeployId.HogRider);
            var lavaHounds   = deployElements.FirstOrDefault(u => u.Id == DeployId.LavaHound);
            var minions      = deployElements.FirstOrDefault(u => u.Id == DeployId.Minion);
            var wallBreakers = deployElements.FirstOrDefault(u => u.Id == DeployId.WallBreaker);
            var healers      = deployElements.FirstOrDefault(u => u.Id == DeployId.Healer);

            //Do a last check for ANY units that we have left... at this point if they haven't been deployed, Its probably an error.
            //Try and dump anything that is left on the edge of the map so the next time Troops are built, it doesnt hang the bot.
            var leftoverTroops = new List <DeployElement>();

            leftoverTroops.RecountAndAddIfAny(dragons);
            leftoverTroops.RecountAndAddIfAny(balloons);
            leftoverTroops.RecountAndAddIfAny(hogs);
            leftoverTroops.RecountAndAddIfAny(lavaHounds);
            leftoverTroops.RecountAndAddIfAny(minions);
            leftoverTroops.RecountAndAddIfAny(wallBreakers);
            leftoverTroops.RecountAndAddIfAny(healers);

            if (leftoverTroops.Count > 0)
            {
                //Spot in the middle of the y axis, and the Min Edge of the X axis... (Should ALWAYS be able to dump here)
                var dumpSpot = new PointFT(GameGrid.MinX - .5f, 0f);

                foreach (var troop in leftoverTroops)
                {
                    Log.Error($"{Tag} Deploying {troop.Count} left over {troop.PrettyName}s to edge of map, to get rid of troops.  This should not happen, but does sometimes when troops are not properly deployed in earlier phases of the algorithm.");
                    foreach (var t in Deploy.AtPoint(troop, dumpSpot, troop.Count))
                    {
                        yield return(t);
                    }
                }
            }
            else
            {
                Log.Info($"{Tag} All Troops Successfully Deployed...");
            }
        }
        public static IEnumerable <int> DeployHeroes()
        {
            foreach (var s in DeployJump())
            {
                yield return(s);
            }

            Log.Info($"[{AllInOnePushDeploy.AttackName}] droping heroes");
            if (heroes.Any())
            {
                foreach (var hero in heroes.Where(u => u.Count > 0))
                {
                    foreach (var t in Deploy.AtPoint(hero, AllInOnePushDeploy.Origin))
                    {
                        yield return(t);
                    }
                }
                watchHeroes = true;
            }

            if (queen?.Count > 0)
            {
                foreach (var t in Deploy.AtPoint(queen, AllInOnePushDeploy.Origin))
                {
                    yield return(t);
                }
                watchQueen = true;
            }
            if (warden?.Count > 0)
            {
                foreach (var t in Deploy.AtPoint(warden, AllInOnePushDeploy.Origin))
                {
                    yield return(t);
                }
                isWarden = true;
            }
            else
            {
                isWarden = false;
            }
        }
        public static IEnumerable <int> DropEQ()
        {
            var EQCount = eq?.Sum(u => u.Count);

            if (EQCount >= 4)
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] Use earthquakes spells to open walls near target.");;
                foreach (var unit in eq)
                {
                    foreach (var t in Deploy.AtPoint(unit, AllInOnePushDeploy.EqPoint, unit.Count, 50))
                    {
                        yield return(t);
                    }
                }
                yield return(new Random().Next(2000, 4000));
            }
            else
            {
                useJump = true;
            }
        }
        public static IEnumerable <int> DeployWizard(int waves = 1)
        {
            if (wizard?.Count > 0)
            {
                var count = wizard.Count / waves;

                if (bowlerFunnelCount > 0)
                {
                    foreach (var t in Deploy.AtPoint(wizard, AllInOnePushDeploy.Origin, count))
                    {
                        yield return(t);
                    }
                }
                else
                {
                    foreach (var t in Deploy.AlongLine(wizard, AllInOnePushDeploy.FirstFunnellingPoint, AllInOnePushDeploy.SecondFunnellingPoint, count, 4))
                    {
                        yield return(t);
                    }
                }
            }
        }
        public override IEnumerable <int> AttackRoutine()
        {
            Log.Debug("[Snipe Deploy] Getting the best townhall deploy point.");
            var snipePoint = new Container <PointFT> {
                Item = GetTownHallDeployPoint()
            };

            Log.Debug($"[Snipe Deploy] Deploy point is ({snipePoint.Item})");

            var troops = Deploy.GetTroops();

            var hero = troops.GetQueen() ?? troops.GetKing() ?? troops.GetWarden();

            if (hero != null)
            {
                Log.Info("[Snipe Deploy] Deploying the " + hero.PrettyName + " to snipe.");
                foreach (var t in Deploy.AtPoint(hero, snipePoint))
                {
                    yield return(t);
                }

                hero.Recount();

                if (hero.Count > 0)
                {
                    var th = TownHall.Find();

                    using (var bmp = Screenshot.Capture(true))
                    {
                        Visualize.RectangleT(bmp, th.Location);
                        Visualize.RectangleT(bmp, new RectangleT((int)snipePoint.Item.X, (int)snipePoint.Item.Y, 1, 1));
                        var d = DateTime.UtcNow;
                        Screenshot.Save(bmp, $"Snipe Deploy_{d.Year}-{d.Month}-{d.Day}_{d.Hour}-{d.Minute}-{d.Second}");
                    }
                }

                yield return(5000);

                Deploy.WatchHeroes(new List <DeployElement> {
                    hero
                });

                var countdown = new Countdown(15.0);

                if (hero.Count < 1)
                {
                    while (countdown.IsRunning)
                    {
                        if (Attack.SurrenderIfWeHaveAStar())
                        {
                            yield break;
                        }
                        else
                        {
                            yield return(200);
                        }
                    }
                }
                else
                {
                    Log.Info("[Snipe Deploy] Hero failed to deploy; trying to use troops");
                }
            }

            var snipeTroops =
                troops.GetByAttackType(AttackType.Damage)
                .GetByType(DeployElementType.NormalUnit)
                .Where(u => u.UnitData?.TargetType == TargetType.Loot || u.UnitData?.TargetType == TargetType.None)
                .ToArray();

            if (snipeTroops.Length > 0)
            {
                Log.Info("[Snipe Deploy] Deploying troops to snipe.");

                var countdown = new Countdown(15.0, true);
                var pt        = new Container <PointFT> {
                    Item = GetTownHallDeployPoint()
                };
                while (true)
                {
                    if (countdown.IsFinished)
                    {
                        foreach (var t in Deploy.AtPoint(snipeTroops, snipePoint))
                        {
                            yield return(t);
                        }

                        snipeTroops.Recount();

                        if (snipeTroops.All(u => u.Count < 1))
                        {
                            yield break;
                        }

                        countdown.Restart();
                    }

                    if (Attack.SurrenderIfWeHaveAStar())
                    {
                        yield break;
                    }
                }
            }
        }