Example #1
0
        public override double ShouldAccept()
        {
            if (Opponent.MeetsRequirements(BaseRequirements.All))
            {
                if (!SmartAirDeployHelpers.AllAirDefensesFound(TownHall.Find() == null ? TownHallLimits.Limits.Length - 1 : TownHall.Find().Level))
                {
                    return(0);
                }

                return(1);
            }
            return(0);
        }
        PointFT[] CalculateRageDeployPoints(DeployElement rageSpell, PointFT[] potentialDeployPoints, List <VisualObject> visuals)
        {
            if (rageSpell == null)
            {
                return(null);
            }

            // PotentialdeployPoints[] is already ordered by angle ascending
            var minAnglePoint = potentialDeployPoints.First();
            var maxAnglePoint = potentialDeployPoints.Last();
            var line          = new Line(minAnglePoint, maxAnglePoint);

            visuals.Add(new LinesObject("RageSpellDeployPointLine", Color.FromArgb(200, Color.White), new[] { line }));

            // rageSpell.Count +1 because chopLine would start on the very first point of the line otherwise
            var spellDeployPoints = SmartAirDeployHelpers.ChopLine(line.Start, line.End, rageSpell.Count + 1);
            //visuals.Add(new PointsObject("BabyDragon DeployPoints", Color.FromArgb(250, Color.Tomato), spellDeployPoints, 3));
            var rageSpellDeployPoints = spellDeployPoints.Skip(1).Select(x => new PointFT((int)x.X, (int)x.Y)).ToArray();

            visuals.Add(new PointsObject("BabyDragon DeployPoints", Color.FromArgb(140, Color.Purple), rageSpellDeployPoints, 10));

            return(rageSpellDeployPoints);
        }
Example #3
0
        /// <summary>
        /// Finds AirDefenses which can and should be ZapQuaked.
        /// The length of the list is dependent on the available spells (2 lightnings, 1 earthquake = 1 AirDefense target)
        /// </summary>
        /// <param name="earthQuakeSpells">The available earthquake spells</param>
        /// <param name="lightningSpells">The available lightning spells</param>
        /// <returns>A list of AirDefenses which can and should be ZapQuaked</returns>
        List <AirDefense> FindAirDefenseTargets(DeployElement earthQuakeSpells, DeployElement lightningSpells, List <VisualObject> visuals)
        {
            var lightningsToDestroyAirDefenses = (int)Math.Floor((double)lightningSpells.Count / 2);
            var destroyableAirDefenses         = Math.Min(lightningsToDestroyAirDefenses, earthQuakeSpells.Count);

            Log.Info($"[LavaLoon] We've got {lightningSpells.Count} Lightning Spells and {earthQuakeSpells.Count}, which is enough to destroy {destroyableAirDefenses} AirDefenses.");


            var allAirDefenses = AirDefense.Find();

            try
            {
                var targetsToFindCount = Math.Min(destroyableAirDefenses, allAirDefenses.Count());
                if (targetsToFindCount == 0)
                {
                    Log.Error("[LavaLoon] FindAirDefenseTargets has been called even though it shouldn't have been called!");
                    return(null);
                }

                // If we need to find 2 or more AirDefense targets we want to find the closest AirDefenses
                if (targetsToFindCount > 1)
                {
                    var airDefensesOrderedByDeployPointDistance = allAirDefenses.OrderByDescending(x => SmartAirDeployHelpers.DistanceSqToClosestDeploypoint(x.Location.GetCenter()));
                    // furthestAirDefense = The airdefense which is the furthest away from deployzone
                    var furthestAirDefense   = airDefensesOrderedByDeployPointDistance.First();
                    var remainingAirDefenses = airDefensesOrderedByDeployPointDistance.Skip(1).ToList();
                    var orderedList          = OrderByDistance(furthestAirDefense, remainingAirDefenses).Take(targetsToFindCount).ToList();

                    // Add visuals
                    var orderedListCenters = orderedList.Select(x => x.Location.GetCenter());
                    visuals.Add(new PointsObject("AirDefenseTargets", Color.FromArgb(200, Color.CornflowerBlue), orderedListCenters));

                    return(orderedList);
                }
                var targetList = allAirDefenses.Take(1).ToList();

                // Add visuals
                var targetListCenters = targetList.Select(x => x.Location.GetCenter());
                visuals.Add(new PointsObject("AirDefenseTargets", Color.FromArgb(200, Color.CornflowerBlue), targetListCenters));

                return(targetList);
            }
            catch (Exception ex)
            {
                Log.Error("[LavaLoon] Exception occured during 'ZapQuakeAirDefenses'. More information can be found inside of the debug log.");
                Log.Debug("[LavaLoon] Exception details: " + ex);
                return(null);
            }
        }
Example #4
0
        /// <summary>
        /// Prepares some stuff (baseBorder, orth from AirDefenses, intersectionPoint) which helps to calculate the actual deploypoints.
        /// </summary>
        /// <param name="airDefenses">Found AirDefenses after possible ZapQuake</param>
        /// <param name="visuals">VisualObjects for drawing information (deploypoints, orth and so on) into bmp</param>
        /// <returns></returns>
        DeployCalculationInformation PrepareDeployCalculation(AirDefense[] airDefenses, List <VisualObject> visuals)
        {
            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;

            // border around the base
            var baseBorder = new List <RectangleT>();

            baseBorder.Add(new RectangleT((int)minRedPointX, (int)maxRedPointY, (int)(maxRedPointX - minRedPointX), (int)(minRedPointY - maxRedPointY)));

            // Add baseborder as visual
            visuals.Add(new RectangleObject("BaseBorder", Color.FromArgb(100, Color.Maroon), baseBorder, new Pen(Color.Maroon)));

            // Find nearest deploy points for two airdefenses
            var airDefensesOrderedByDeployPointDistance = airDefenses.OrderByDescending(x => SmartAirDeployHelpers.DistanceSqToClosestDeploypoint(x.Location.GetCenter()));
            var closestAirDefense    = airDefensesOrderedByDeployPointDistance.FirstOrDefault();
            var remainingAirDefenses = airDefensesOrderedByDeployPointDistance.Skip(1).ToList();
            var orderedList          = OrderByDistance(closestAirDefense, remainingAirDefenses).Take(2).ToList();

            PointF  intersectionPointF;
            PointFT intersectionPointFt;

            // 1. convert all corners into vectors
            var    left         = new PointFT(minRedPointX, maxRedPointY).ToScreenAbsolute();
            var    top          = new PointFT(maxRedPointX, maxRedPointY).ToScreenAbsolute();
            var    right        = new PointFT(maxRedPointX, minRedPointY).ToScreenAbsolute();
            var    bottom       = new PointFT(minRedPointX, minRedPointY).ToScreenAbsolute();
            Vector vLeftPoint   = new Vector(left.X, left.Y);
            Vector vTopPoint    = new Vector(top.X, top.Y);
            Vector vRightPoint  = new Vector(right.X, right.Y);
            Vector vBottomPoint = new Vector(bottom.X, bottom.Y);

            // 2. create the 4 combinations of the 4 points to get all 4 edges (topleft, topright, ...)
            var baseBorderSides = new List <Tuple <Vector, Vector> >();

            baseBorderSides.Add(Tuple.Create(vTopPoint, vLeftPoint));     // Topleft
            baseBorderSides.Add(Tuple.Create(vTopPoint, vRightPoint));    // Topright
            baseBorderSides.Add(Tuple.Create(vLeftPoint, vBottomPoint));  // BottomLeft
            baseBorderSides.Add(Tuple.Create(vRightPoint, vBottomPoint)); // BottomRight

            if (orderedList?.Count() == 2)
            {
                var start = orderedList.First().Location.GetCenter();
                var end   = orderedList.Last().Location.GetCenter();
                var airDefenseConnection = new Line(start, end);
                visuals.Add(new LinesObject("AirDefenseConnection", Color.FromArgb(180, Color.OrangeRed), new[] { airDefenseConnection }));


                Point screenStart = start.ToScreenAbsolute();
                Point screenEnd   = end.ToScreenAbsolute();

                Vector vStart = new Vector(screenStart.X, screenStart.Y);
                Vector vEnd   = new Vector(screenEnd.X, screenEnd.Y);

                Vector vStartEnd = vEnd - vStart;
                Vector vDir      = vStartEnd;
                vDir.Normalize();

                Vector vOrthDir = new Vector(vDir.Y, -vDir.X);

                Vector vOrthMidPoint = vStart + vStartEnd * 0.5;

                Point midPoint = new Point((int)vOrthMidPoint.X, (int)vOrthMidPoint.Y);

                // We have two lines (mid -> airDef1) and (mid -> airDef2)
                // We want to know what line points "away" from the townhall (center of the map)
                var    mapCenterAbsolute = new PointFT(0f, 0f).ToScreenAbsolute();
                Vector vMapCenter        = new Vector(mapCenterAbsolute.X, mapCenterAbsolute.Y);


                Vector dirTest1 = vOrthMidPoint + vOrthDir * +0.1;
                Vector dirTest2 = vOrthMidPoint + vOrthDir * -0.1;

                Vector dirAwayFromCenter = (vMapCenter - dirTest1).LengthSquared < (vMapCenter - dirTest2).LengthSquared
                    ? -vOrthDir
                    : vOrthDir;

                Vector vAirDefOrthLineEnd   = vOrthMidPoint + dirAwayFromCenter * 3000;
                Point  airDefLineEndCorrect = new Point((int)vAirDefOrthLineEnd.X, (int)vAirDefOrthLineEnd.Y);

                var orthLine = new Line(new PointF((float)vOrthMidPoint.X, (float)vOrthMidPoint.Y), new PointF(airDefLineEndCorrect.X, airDefLineEndCorrect.Y));
                visuals.Add(new LinesObject("AirDefenseOrth", new Pen(Color.OrangeRed, 3), new[] { orthLine }));

                // Now we want to find the intersection of our line, with the outer rectangle.
                // We know that our line starts inside the rect, and ends outside of it, that means there must be exactly one intersection point



                // 3. use those for the following intersection calculation:
                Vector vOrthLineStartPoint = vOrthMidPoint;
                Vector vOrthLineEndPoint   = vAirDefOrthLineEnd;
                Vector vOrth = vOrthLineStartPoint + vOrthLineEndPoint;

                // 4. test this line for intersections against all 4 sides, only (and exactly) one of them will have an intersection
                Vector vInterSectionPoint = default(Vector);
                foreach (var side in baseBorderSides)
                {
                    if (SmartAirDeployHelpers.LineSegementsIntersect(side.Item1, side.Item2, vOrthLineStartPoint, vOrthLineEndPoint, out vInterSectionPoint))
                    {
                        break;
                    }
                }
                intersectionPointF  = new PointF((float)vInterSectionPoint.X, (float)vInterSectionPoint.Y);
                intersectionPointFt = new PointFT((int)intersectionPointF.X, (int)intersectionPointF.Y);
            }
            else if (orderedList?.Count == 1)
            {
                // It's not necessary to build an orth between two AirDefenses in that case, so just find the closest deploy point to the only left AirDefense
                var start = orderedList.First().Location.GetCenter();
                var deployPointsOrderedByDistance = GameGrid.RedPoints.OrderBy(x => x.DistanceSq(start));
                intersectionPointFt = deployPointsOrderedByDistance.First();
                intersectionPointF  = intersectionPointFt.ToScreenAbsolute();
            }
            else
            {
                // No Airdefense left anymore? Then just use a random Redpoint
                intersectionPointFt = GameGrid.RedPoints.First();
                intersectionPointF  = intersectionPointFt.ToScreenAbsolute();
            }

            // 5. add that point to "visuals"
            visuals.Add(new PointsObject("IntersectionPoint", Color.FromArgb(200, Color.Cyan), new[] { intersectionPointF }));

            // 6. Chop baseborder line into points so we can determine proper deploypoints
            var baseBorderPoints = new List <PointFT>();

            foreach (var side in baseBorderSides)
            {
                baseBorderPoints.AddRange(SmartAirDeployHelpers.ChopLine(side.Item1, side.Item2));
            }


            // deployPoints = all Points within radius x
            var deployPoints = baseBorderPoints.Where(x => x.DistanceSq(intersectionPointFt) < 450).ToList();

            deployPoints = deployPoints.Select(x => x.TransformPositionAlongAxis(1)).ToList();
            deployPoints = deployPoints.Select(x => x.Constrain()).ToList();

            return(new DeployCalculationInformation(intersectionPointFt, intersectionPointF, deployPoints));
        }