public override IEnumerable <int> AttackRoutine()
        {
            var allDeployElements = Deploy.GetTroops();

            List <Point> redPoints = new List <Point>();

            foreach (var s in AttackHelper.FindRedPoints(redPoints))
            {
                yield return(s);
            }

            var leftCorner = DeployHelper.DeployPointALeft;
            var topCorner  = DeployHelper.DeployPointATop;

            double tankPaddingFraction = 0.35;
            var    tankDeployA         = leftCorner.Lerp(topCorner, tankPaddingFraction);
            var    tankDeployB         = leftCorner.Lerp(topCorner, 1 - tankPaddingFraction);

            double wallBreakerFraction = 0.43;
            var    wallBreakDeployA    = leftCorner.Lerp(topCorner, wallBreakerFraction);
            var    wallBreakDeployB    = leftCorner.Lerp(topCorner, 1 - wallBreakerFraction);

            double damageFraction     = 0.15;
            var    damageDeployPointA = leftCorner.Lerp(topCorner, damageFraction);
            var    damageDeployPointB = leftCorner.Lerp(topCorner, 1 - damageFraction);

            // We want to drag our deploy points to the closest redline point
            // For that we get the vector from left to top, then we get its orthogonal vector (the one of both that points more towards the center)
            // then we can order the redline points. we want the one whos direction is closest to the orthogonal vector.
            var vecLeftTop = topCorner.Subtract(leftCorner).Normalize();
            var ortho      = GetOrthogonalDirection(tankDeployA, new Point((int)(vecLeftTop.Item1 * 30), (int)(vecLeftTop.Item2 * 30)), new PointF(0.5f, 0.5f).ToAbsolute());

            tankDeployA = GetBestRedlinePoint(redPoints, tankDeployA, ortho);
            tankDeployB = GetBestRedlinePoint(redPoints, tankDeployB, ortho);

            wallBreakDeployA = GetBestRedlinePoint(redPoints, wallBreakDeployA, ortho);
            wallBreakDeployB = GetBestRedlinePoint(redPoints, wallBreakDeployB, ortho);


            var attackLine = DeployHelper.GetPointsForLine(damageDeployPointA, damageDeployPointB, 30).ToArray();

            for (int i = 0; i < attackLine.Length; i++)
            {
                attackLine[i] = GetBestRedlinePoint(redPoints, attackLine[i], ortho);
            }
            attackLine = attackLine.Distinct().ToArray();


            var validUnits = allDeployElements.Where(u => u.UnitData != null).ToArray();
            var clanTroops = allDeployElements.FirstOrDefault(u => u.ElementType == DeployElementType.ClanTroops);
            //Func<DeployElement, bool> isAir = e => e.UnitData.UnitType == UnitType.Air;
            Func <DeployElement, bool> isBalloon = e => e.UnitData.NameSimple.Contains("balloon");
            Func <DeployElement, bool> isMinion  = e => e.UnitData.NameSimple.Contains("minion");

            var tankUnits        = validUnits.Where(u => u.UnitData.AttackType == AttackType.Tank).ToArray();
            var wallBreakerUnits = validUnits.Where(u => u.UnitData.AttackType == AttackType.Wallbreak).ToArray();
            var attackUnits      = validUnits.Where(u => u.UnitData.AttackType == AttackType.Damage && !isMinion(u)).ToArray();

            if (clanTroops != null && UserSettings.UseClanTroops)
            {
                attackUnits = attackUnits.Concat(new[] { clanTroops }).ToArray();
            }
            var healUnits    = validUnits.Where(u => u.UnitData.AttackType == AttackType.Heal).ToArray();
            var balloonUnits = validUnits.Where(isBalloon).ToArray();
            var minionUnits  = validUnits.Where(isMinion).ToArray();

            // Deploy tank units
            if (tankUnits.Any())
            {
                Logger.Debug($"{tankUnits.Length} tanking element{(tankUnits.Length > 1 ? "s" : "")} available to deploy.");
                foreach (var s in DeployUnits(tankUnits, new[] { tankDeployA, tankDeployB }, 20))
                {
                    yield return(s);
                }
                yield return(2000);
            }

            // Deploy wallbreakers
            if (tankUnits.Any())
            {
                Logger.Debug("Wallbreakers available to deploy.");
                foreach (var s in DeployUnits(wallBreakerUnits, new[] { wallBreakDeployA, wallBreakDeployB }, 40))
                {
                    yield return(s);
                }
                yield return(1000);
            }

            // Check whether we got an air troopset and decide to perform an air attack or not
            var balloonCount = balloonUnits.Sum(i => i.Count);

            if (balloonCount > 10)
            {
                // Ok, we have an air troopset, so we will deploy the air units first according to different deploy rules.
                attackUnits = attackUnits.Where(u => !isBalloon(u)).ToArray();

                int spotCount = (int)Math.Ceiling(balloonCount / 4.0);
                // We want to make x spots where balloons are deployed
                var airPoints = DeployHelper.GetPointsForLine(damageDeployPointA, damageDeployPointB, spotCount);
                for (int i = 0; i < airPoints.Count; i++)
                {
                    airPoints[i] = GetBestRedlinePoint(redPoints, airPoints[i], ortho);
                }
                airPoints = airPoints.Distinct().ToList();

                // Deploy those air units
                foreach (var s in DeployUnits(balloonUnits, airPoints.ToArray(), firstCycleYield: 1000))
                {
                    yield return(s);
                }
            }

            // Deploy atackers
            if (attackUnits.Any())
            {
                Logger.Debug($"{attackUnits.Length} attacking element{(attackUnits.Length > 1 ? "s" : "")} available to deploy.");
                foreach (var s in DeployUnits(attackUnits, attackLine, 0, 5, 2500))
                {
                    yield return(s);
                }
                yield return(500);
            }

            // Minions
            if (minionUnits.Any())
            {
                foreach (var s in DeployUnits(minionUnits, attackLine))
                {
                    yield return(s);
                }
            }

            // Deploy healers
            foreach (var s in DeployUnits(healUnits, attackLine))
            {
                yield return(s);
            }

            // Deploy heroes
            var heroes = allDeployElements
                         .Where(u => (UserSettings.UseKing && u.ElementType == DeployElementType.HeroKing) ||
                                (UserSettings.UseQueen && u.ElementType == DeployElementType.HeroQueen) ||
                                (UserSettings.UseWarden && u.ElementType == DeployElementType.HeroWarden))
                         .ToList();

            if (heroes.Count > 0)
            {
                foreach (var y in DeployHeroes(heroes, attackLine))
                {
                    yield return(y);
                }
            }
        }