public override IEnumerable <int> AttackRoutine()
        {
            // Set start battle time.
            startTime = DateTime.Now;

            int waveLimit   = UserSettings.WaveSize;
            int waveDelay   = (int)(UserSettings.WaveDelay * 1000);
            int heroesIndex = -1;

            // Set the core point of the base
            SmartFourFingersHelper.SetCore();

            if (!IsTargetsCalculated)
            {
                SmartFourFingersHelper.CalculateTargets();
            }


            // Points to draw lines in deploy extends area.
            var topLeft  = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MaxY);
            var topRight = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MaxY - 2);

            var rightTop    = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MinY + 2);
            var rightBottom = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MinY);

            // Move 8 tiles from bottom corner due to unitsbar.
            var bottomLeft  = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MinY + 8);
            var bottomRight = new PointFT((float)GameGrid.MinX + 8, (float)GameGrid.DeployExtents.MinY);

            var leftTop    = new PointFT((float)GameGrid.MinX + 2, (float)GameGrid.DeployExtents.MaxY);
            var leftBottom = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MaxY - 2);

            var linesPointsList = new List <PointFT>
            {
                topLeft, topRight,
                rightTop, rightBottom,
                bottomLeft, bottomRight,
                leftBottom, leftTop
            };

            // Main four lines of attack.
            var topRightLine    = new Tuple <PointFT, PointFT>(topRight, rightTop);
            var bottomRightLine = new Tuple <PointFT, PointFT>(bottomRight, rightBottom);
            var bottomLeftLine  = new Tuple <PointFT, PointFT>(bottomLeft, leftBottom);
            var topLeftLine     = new Tuple <PointFT, PointFT>(topLeft, leftTop);

            // List of the four attack lines in clocwise order
            AttackLines = new List <Tuple <PointFT, PointFT> >
            {
                topRightLine,
                bottomRightLine,
                bottomLeftLine,
                topLeftLine
            };



            var deployHeroesAt = GetCurrentSetting("Deploy Heroes At");

            var target = SmartFourFingersHelper.GetHeroesTarget(deployHeroesAt);

            // Search for target if not found for 3 more times
            if (target.X == 0f && target.Y == 0f)
            {
                for (var i = 1; i <= 3; i++)
                {
                    yield return(1000);

                    target = SmartFourFingersHelper.GetHeroesTarget(deployHeroesAt);
                    if (target.X != 0f || target.Y != 0f)
                    {
                        break;
                    }
                }
            }

            var nearestRedPointToTarget = GameGrid.RedPoints.OrderBy(p => p.DistanceSq(target)).FirstOrDefault();
            var nearestLinePoint        = linesPointsList.OrderBy(p => p.DistanceSq(nearestRedPointToTarget)).FirstOrDefault();

            heroesIndex = AttackLines.FindIndex(u => (u.Item1.X == nearestLinePoint.X && u.Item1.Y == nearestLinePoint.Y) || (u.Item2.X == nearestLinePoint.X && u.Item2.Y == nearestLinePoint.Y));

            var units  = Deploy.GetTroops();
            var heroes = units.Extract(x => x.IsHero);
            var cc     = units.ExtractOne(u => u.ElementType == DeployElementType.ClanTroops);
            var spells = units.Extract(u => u.ElementType == DeployElementType.Spell);

            units.OrderForDeploy();

            // Set first attack line
            // Start from the next line to user defined to end with user defined line
            var line  = AttackLines.NextOf(AttackLines[heroesIndex]);
            var index = AttackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y);

            var deploymentMode = GetCurrentSetting("Set Troops Deployment");

            if (deploymentMode == 2)
            {
                AddFakeTargets();
            }

            var targetsCount = TargetsAtLine[index];

            Log.Info($"{AttackName} {Version} starts");

            var deployCC = GetCurrentSetting("CC Deployment");

            if (deployCC == 0 && cc?.Count > 0)
            {
                Log.Info($"{AttackName} Deploy Clan Castle troops first");
                foreach (var t in Deploy.AlongLine(cc, line.Item1, line.Item2, 1, 1, 0, waveDelay))
                {
                    yield return(t);
                }
            }

            // Start troops deployment on four sides.
            for (var i = 4; i >= 1; i--)
            {
                Log.Info($"Targets at this side = {targetsCount} targets from total {TotalTargetsCount} targets");
                foreach (var unit in units)
                {
                    if (unit?.Count > 0)
                    {
                        var count   = deploymentMode == 0 ? unit.Count / i : (TotalTargetsCount > 0 ? unit.Count * targetsCount / TotalTargetsCount : 0);
                        var housing = unit.UnitData.HousingSpace;
                        var fingers = housing < 4 ? (count < 8 ? count : 4) : 1;

                        Log.Info($"{AttackName} Deploy {count}x {unit.PrettyName}");
                        foreach (var t in Deploy.AlongLine(unit, line.Item1, line.Item2, count, fingers, 0, waveDelay))
                        {
                            yield return(t);
                        }
                    }
                }

                if (i != 1)
                {
                    line  = AttackLines.NextOf(AttackLines[index]);
                    index = AttackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y);

                    TotalTargetsCount -= targetsCount;
                    targetsCount       = TargetsAtLine[index];
                }
            }

            if (deployCC == 1 && cc?.Count > 0)
            {
                Log.Info($"{AttackName} Deploy Clan Castle troops");
                foreach (var t in Deploy.AlongLine(cc, line.Item1, line.Item2, 1, 1, 0, waveDelay))
                {
                    yield return(t);
                }
            }

            if (heroes.Any())
            {
                Log.Info($"{AttackName} Deploy Heroes");
                foreach (var hero in heroes.Where(u => u.Count > 0))
                {
                    foreach (var t in Deploy.AlongLine(hero, line.Item1, line.Item2, 1, 1, 0, waveDelay))
                    {
                        yield return(t);
                    }
                }
                Deploy.WatchHeroes(heroes, 5000);
            }

            // Call FinalizeAttack and ForceZap at the same time
            var zapSpells = Deploy.GetTroops().Extract(u => u.ElementType == DeployElementType.Spell);

            if (spells.Extract(u => u.Id == DeployId.Lightning).Sum(u => u.Count) > 0 ||
                spells.Extract(u => u.Id == DeployId.Earthquake).Sum(u => u.Count) > 0)
            {
                var finalize = this.FinalizeAttack(units).GetEnumerator();
                var force    = ForceZap().GetEnumerator();

                var firstEnumMoreItems  = finalize.MoveNext();
                var secondEnumMoreItems = force.MoveNext();

                // Start both FinalizeAttack and ForceZap
                while (firstEnumMoreItems && secondEnumMoreItems)
                {
                    firstEnumMoreItems  = finalize.MoveNext();
                    secondEnumMoreItems = force.MoveNext();
                    yield return(200);
                }
                // Complete ForceZap if FinalizeAttack finished
                while (!firstEnumMoreItems && secondEnumMoreItems)
                {
                    secondEnumMoreItems = force.MoveNext();
                    yield return(200);
                }
                // Complete FinalizeAttack if ForceZap finished
                while (!secondEnumMoreItems && firstEnumMoreItems)
                {
                    firstEnumMoreItems = finalize.MoveNext();
                    yield return(200);
                }
            }
            else
            {
                yield break;
            }
        }
示例#2
0
        public override IEnumerable <int> AttackRoutine()
        {
            int waveLimit   = UserSettings.WaveSize;
            int waveDelay   = (int)(UserSettings.WaveDelay * 1000);
            int heroesIndex = -1;

            var core = new PointFT(-0.01f, 0.01f);

            // Points to draw lines in deploy extends area.
            var topLeft  = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MaxY);
            var topRight = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MaxY - 2);

            var rightTop    = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MinY + 2);
            var rightBottom = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MinY);

            // Move 8 tiles from bottom corner due to unitsbar.
            var bottomLeft  = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MinY + 8);
            var bottomRight = new PointFT((float)GameGrid.MinX + 8, (float)GameGrid.DeployExtents.MinY);

            var leftTop    = new PointFT((float)GameGrid.MinX + 2, (float)GameGrid.DeployExtents.MaxY);
            var leftBottom = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MaxY - 2);

            var linesPointsList = new List <PointFT>
            {
                topLeft, topRight,
                rightTop, rightBottom,
                bottomLeft, bottomRight,
                leftBottom, leftTop
            };

            // Main four lines of attack.
            var topRightLine    = new Tuple <PointFT, PointFT>(topRight, rightTop);
            var bottomRightLine = new Tuple <PointFT, PointFT>(bottomRight, rightBottom);
            var bottomLeftLine  = new Tuple <PointFT, PointFT>(bottomLeft, leftBottom);
            var topLeftLine     = new Tuple <PointFT, PointFT>(topLeft, leftTop);

            // List of the four attack lines in clocwise order
            var attackLines = new List <Tuple <PointFT, PointFT> >
            {
                topLeftLine,
                topRightLine,
                bottomRightLine,
                bottomLeftLine
            };

            var deployHeroesAt = GetCurrentSetting("Deploy Heroes At");


            var target = SmartFourFingersHelper.GetHeroesTarget(deployHeroesAt);

            var nearestRedPointToTarget = GameGrid.RedPoints.OrderBy(p => p.DistanceSq(target)).FirstOrDefault();
            var nearestLinePoint        = linesPointsList.OrderBy(p => p.DistanceSq(nearestRedPointToTarget)).FirstOrDefault();

            heroesIndex = attackLines.FindIndex(u => (u.Item1.X == nearestLinePoint.X && u.Item1.Y == nearestLinePoint.Y) || (u.Item2.X == nearestLinePoint.X && u.Item2.Y == nearestLinePoint.Y));

            var units  = Deploy.GetTroops();
            var heroes = units.Extract(x => x.IsHero);
            var cc     = units.ExtractOne(u => u.ElementType == DeployElementType.ClanTroops);
            var spells = units.Extract(u => u.ElementType == DeployElementType.Spell);

            units.OrderForDeploy();

            // Set first attack line
            // Start from the next line to user defined to end with user defined line
            var line  = attackLines.NextOf(attackLines[heroesIndex]);
            var index = attackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y);

            Log.Info($"{AttackName} {Version} starts");
            // Start troops deployment on four sides.
            for (var i = 4; i >= 1; i--)
            {
                foreach (var unit in units)
                {
                    if (unit?.Count > 0)
                    {
                        var count   = unit.Count / i;
                        var fingers = count % 4 <= 1 ? count : 4;
                        foreach (var t in Deploy.AlongLine(unit, line.Item1, line.Item2, count, fingers, 0, waveDelay))
                        {
                            yield return(t);
                        }
                    }
                }
                if (i != 1)
                {
                    line  = attackLines.NextOf(attackLines[index]);
                    index = attackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y);
                }
            }

            if (cc?.Count > 0)
            {
                Log.Info($"{AttackName} Deploy Clan Castle troops");
                foreach (var t in Deploy.AlongLine(cc, line.Item1, line.Item2, 1, 1, 0, waveDelay))
                {
                    yield return(t);
                }
            }

            if (heroes.Any())
            {
                Log.Info($"{AttackName} Deploy Heroes");
                foreach (var hero in heroes.Where(u => u.Count > 0))
                {
                    foreach (var t in Deploy.AlongLine(hero, line.Item1, line.Item2, 1, 1, 0, waveDelay))
                    {
                        yield return(t);
                    }
                }
                Deploy.WatchHeroes(heroes, 5000);
            }


            var minDEDrillLevel = GetCurrentSetting("Min Drill Level");

            // start smart zap
            if (GetCurrentSetting("Smart Zap Drills") == 1)
            {
                var waitBeforeSmartZap = GetCurrentSetting("Start Zap Drills After ?(sec)") * 1000;
                var minDEAmount        = GetCurrentSetting("Min Dark Elixir per Zap");


                yield return(waitBeforeSmartZap);

                foreach (var t in SmartZapping.SmartZap(minDEAmount, minDEDrillLevel, spells))
                {
                    yield return(t);
                }
            }

            // start Use EarthQuake spell on drills
            if (GetCurrentSetting("Use EarthQuake spell on drills") == 1)
            {
                foreach (var t in SmartZapping.UseEQOnDrills(minDEDrillLevel, spells))
                {
                    yield return(t);
                }
            }

            // end battle
            var endBattleTime = GetCurrentSetting("End Battle after zap ?(sec)");

            foreach (var t in SmartZapping.EndBattle(endBattleTime))
            {
                yield return(t);
            }
        }