コード例 #1
0
        public bool _ethalonCanCastMagicMissile(ACircularUnit opp, bool checkCooldown)
        {
            var distTo = GetDistanceTo(opp);

            if (distTo > CastRange + opp.Radius + MyStrategy.Game.MagicMissileRadius)
            {
                return(false);
            }

            var angleTo    = GetAngleTo(opp);
            var deltaAngle = Math.Atan2(opp.Radius, distTo);
            var angles     = new[] { angleTo, angleTo + deltaAngle, angleTo - deltaAngle };

            foreach (var angle in angles)
            {
                if (Math.Abs(angle) > MyStrategy.Game.StaffSector / 2)
                {
                    continue;
                }

                var proj = new AProjectile(this, angle, ProjectileType.MagicMissile);
                if (CheckProjectileCantDodge(proj, opp as ACombatUnit))
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #2
0
        static Cell FindNearestCell(ACircularUnit my)
        {
            double ds = Const.MapSize / GridSize;

            var    I = (int)(my.X / ds + Const.Eps);
            var    J = (int)(my.Y / ds + Const.Eps);
            int    seldI = int.MaxValue, seldJ = int.MaxValue;
            double minDist   = int.MaxValue;
            var    obstacles = _obstacles
                               .Concat(BuildingsObserver.Buildings)
                               .Concat(TreesObserver.Trees)
                               .ToArray();

            for (var di = 0; di < 2; di++)
            {
                for (var dj = 0; dj < 2; dj++)
                {
                    var dst = WizardPath.GetSegmentWeight(_points[I + di, J + dj], my, true);
                    if (dst < minDist &&
                        obstacles.All(ob =>
                                      !Geom.SegmentCircleIntersects(my, _points[I + di, J + dj], ob, ob.Radius + my.Radius + MagicConst.RadiusAdditionalEpsilon))
                        )
                    {
                        minDist = dst;
                        seldI   = di;
                        seldJ   = dj;
                    }
                }
            }
            if (seldI == int.MaxValue)
            {
                return(null);
            }
            return(new Cell(I + seldI, J + seldJ));
        }
コード例 #3
0
ファイル: AMinion.cs プロジェクト: znsoft/AiCup
        public override void EthalonMove(ACircularUnit target)
        {
            var isFrozen = RemainingFrozen > 0;

            SkipTick();

            if (isFrozen)
            {
                return;
            }

            if (target == null)
            {
                X += Math.Cos(Angle) * MyStrategy.Game.MinionSpeed;
                Y += Math.Sin(Angle) * MyStrategy.Game.MinionSpeed;
            }
            else
            {
                var angleTo = GetAngleTo(target);
                if (GetDistanceTo2(target) >
                    Geom.Sqr(this is AOrc
                        ? MyStrategy.Game.OrcWoodcutterAttackRange + target.Radius
                        : MyStrategy.Game.FetishBlowdartAttackRange + target.Radius + MyStrategy.Game.DartRadius))
                {
                    X += Math.Cos(Angle + angleTo) * MyStrategy.Game.MinionSpeed;
                    Y += Math.Sin(Angle + angleTo) * MyStrategy.Game.MinionSpeed;
                }
                Angle += Utility.EnsureInterval(angleTo, MyStrategy.Game.MinionMaxTurnAngle);
            }
        }
コード例 #4
0
        public override bool EthalonCanHit(ACircularUnit target, bool checkCooldown = true)
        {
            if (CanStaffAttack(target, checkCooldown))
            {
                return(true);
            }

            return(EthalonCanCastMagicMissile(target, checkCooldown));
        }
コード例 #5
0
ファイル: Geometry.cs プロジェクト: znsoft/AiCup
        public double GetDistanceToCircle(ACircularUnit circle)
        {
            var distToCenter = GetDistanceTo(circle);

            if (distToCenter <= circle.Radius)
            {
                return(0);
            }
            return(distToCenter - circle.Radius);
        }
コード例 #6
0
        public bool CanStaffAttack(ACircularUnit unit, bool checkCooldown = true)
        {
            if (!CanUseStaff(checkCooldown))
            {
                return(false);
            }

            if (GetDistanceTo2(unit) > Geom.Sqr(MyStrategy.Game.StaffRange + unit.Radius))
            {
                return(false);
            }
            if (Math.Abs(GetAngleTo(unit)) > MyStrategy.Game.StaffSector / 2)
            {
                return(false);
            }
            return(true);
        }
コード例 #7
0
ファイル: AMinion.cs プロジェクト: znsoft/AiCup
        public override bool EthalonCanHit(ACircularUnit target, bool checkCooldown = true)
        {
            if (RemainingFrozen > 0)
            {
                return(false);
            }
            if (checkCooldown && RemainingActionCooldownTicks > 0)
            {
                return(false);
            }

            var angleTo = GetAngleTo(target);

            if (Math.Abs(angleTo) > MyStrategy.Game.OrcWoodcutterAttackSector / 2)
            {
                return(false);
            }
            return(GetDistanceTo2(target) <= Geom.Sqr(MyStrategy.Game.OrcWoodcutterAttackRange + target.Radius));
        }
コード例 #8
0
        public bool EthalonCanCastMagicMissile(ACircularUnit opp, bool checkCooldown = true, bool checkAngle = true)
        {
            if (!CanUseMagicMissile(checkCooldown))
            {
                return(false);
            }

            var tmp = Angle;

            if (!checkAngle)
            {
                Angle += GetAngleTo(opp); // поворачиваем, чтобы угол до цели был 0
            }
            var ret = _ethalonCanCastMagicMissile(opp, checkCooldown);

            if (!checkAngle)
            {
                Angle = tmp;
            }
            return(ret);
        }
コード例 #9
0
 public override void EthalonMove(ACircularUnit target)
 {
     MoveTo(target, target, w => !w.IntersectsWith(target));
 }
コード例 #10
0
 public override bool EthalonCanHit(ACircularUnit target, bool checkCooldown = true)
 {
     return((!checkCooldown || RemainingActionCooldownTicks == 0) &&
            GetDistanceTo2(target) <= Geom.Sqr(CastRange));
 }
コード例 #11
0
 public override void EthalonMove(ACircularUnit target)
 {
     SkipTick();
 }
コード例 #12
0
ファイル: FindTarget.cs プロジェクト: znsoft/AiCup
        MovingInfo _findStaffTarget(AWizard self)
        {
            var potentialColliders = Combats
                                     .Where(x => x.Id != self.Id && self.GetDistanceTo2(x) < Geom.Sqr(Game.StaffRange * 6))
                                     .ToArray();
            int minTicks = int.MaxValue;
            var move     = new FinalMove(new Move());

            var attacked = self.GetStaffAttacked(potentialColliders).Cast <ACombatUnit>().ToArray();

            ACircularUnit selTarget = attacked.FirstOrDefault(x => x.IsOpponent);

            if (selTarget != null) // если уже можно бить
            {
                move.Action = ActionType.Staff;
                return(new MovingInfo(selTarget, 0, move));
            }

            if (self.MmSkillLevel == 5)
            {
                // т.к. стрелять можно без задержки
                // возможно, нужно сделать исключение, если прокачан посох
                return(new MovingInfo(null, int.MaxValue, move));
            }

            Point selMoveTo = null;

            foreach (var opp in OpponentCombats)
            {
                var dist = self.GetDistanceTo(opp);
                if (dist > Game.StaffRange * 5 || !opp.IsAssailable)
                {
                    continue;
                }

                var range = opp.Radius + Game.StaffRange;
                foreach (var delta in new[] { -range, -range / 2, 0, range / 2, range })
                {
                    var angle  = Math.Atan2(delta, dist);
                    var moveTo = self + (opp - self).Normalized().RotateClockwise(angle) * self.VisionRange;

                    var nearstCombats = Combats
                                        .Where(x => x.GetDistanceTo(self) <= Math.Max(x.VisionRange, self.VisionRange) * 1.2)
                                        .Select(Utility.CloneCombat)
                                        .ToArray();

                    var targetsSelector = new TargetsSelector(nearstCombats)
                    {
                        EnableMinionsCache = true
                    };
                    var nearstOpponents = nearstCombats.Where(x => x.IsOpponent).ToArray();

                    var my  = nearstCombats.FirstOrDefault(x => x.Id == self.Id) as AWizard;
                    var his = nearstCombats.FirstOrDefault(x => x.Id == opp.Id);

                    var allowRush = opp is AFetish || opp is AWizard;
                    var canHitNow = opp.EthalonCanHit(self, checkCooldown: !allowRush);

                    var ticks        = 0;
                    var ok           = true;
                    var buildingsHit = false;

                    while (ticks < (allowRush ? 65 : 35) && my.GetDistanceTo2(his) > Geom.Sqr(Game.StaffRange + his.Radius))
                    {
                        foreach (var x in nearstOpponents) // свои как-бы стоят на месте
                        {
                            var tar = targetsSelector.Select(x);
                            buildingsHit = buildingsHit ||
                                           (x is ABuilding && tar != null && tar.Id == my.Id && x.EthalonCanHit(my));
                            x.EthalonMove(tar ?? my);
                        }

                        if (!my.MoveTo(moveTo, his, w => !CheckIntersectionsAndTress(w, potentialColliders)))
                        {
                            ok = false;
                            break;
                        }
                        ticks++;
                    }

                    if (ok && !(opp is AOrc))
                    {
                        while (Math.Abs(my.GetAngleTo(his)) > Game.StaffSector / 2)
                        {
                            my.MoveTo(null, his);
                            foreach (var x in nearstOpponents)
                            {
                                var tar = targetsSelector.Select(x);
                                buildingsHit = buildingsHit ||
                                               (x is ABuilding && tar != null && tar.Id == my.Id && x.EthalonCanHit(my));
                                x.EthalonMove(tar ?? my);
                            }
                            ticks++;
                        }
                    }

                    Func <ACombatUnit, bool> check = x =>
                    {
                        if ((opp is AWizard) && (opp as AWizard).IsBesieded && !(x is ABuilding))
                        {
                            return(true);
                        }

                        if (canHitNow && x.Id == opp.Id) // он и так доставал
                        {
                            return(true);
                        }

                        if (!x.EthalonCanHit(my) && (!(x is ABuilding) || !buildingsHit))
                        {
                            return(true);
                        }

                        if (his.Id == x.Id && my.StaffDamage >= his.Life)
                        {
                            return(true);
                        }

                        var target = targetsSelector.Select(x);
                        if (target != null && target.Id != my.Id)
                        {
                            return(true);
                        }

                        return(false);
                    };

                    if (opp is AWizard)
                    {
                        ticks -= 5;
                        if ((opp as AWizard).IsBesieded)
                        {
                            ticks -= 10;
                        }
                    }

                    if (ok && ticks < minTicks)
                    {
                        if (my.CanStaffAttack(his))
                        {
                            if (nearstOpponents.All(check))
                            {
                                // успею-ли я вернуться обратно
                                while (my.GetDistanceTo(self) > my.MaxForwardSpeed)//TODO:HACK
                                {
                                    my.MoveTo(self, null);
                                    foreach (var x in nearstOpponents)
                                    {
                                        var tar = targetsSelector.Select(x);

                                        buildingsHit = buildingsHit ||
                                                       (x is ABuilding && tar != null && tar.Id == my.Id && x.EthalonCanHit(my));

                                        if (tar != null)
                                        {
                                            x.EthalonMove(tar);
                                        }
                                        else
                                        {
                                            x.SkipTick();
                                        }
                                    }
                                }
                                if (nearstOpponents.All(check))
                                {
                                    selTarget = opp;
                                    selMoveTo = moveTo;
                                    minTicks  = ticks;
                                }
                            }
                        }
                    }
                }
            }
            if (selTarget != null)
            {
                bool angleOk = Math.Abs(self.GetAngleTo(selTarget)) <= Game.StaffSector / 2,
                     distOk  = self.GetDistanceTo2(selTarget) <= Geom.Sqr(Game.StaffRange + selTarget.Radius);

                if (!distOk)
                {
                    move.MoveTo(selMoveTo, selTarget);
                }
                else if (!angleOk)
                {
                    move.MoveTo(null, selTarget);
                }
            }
            return(new MovingInfo(selTarget, Math.Max(0, minTicks), move));
        }
コード例 #13
0
 public virtual bool EthalonCanHit(ACircularUnit target, bool checkCooldown = true)
 {
     throw new NotImplementedException();
 }
コード例 #14
0
 public virtual void EthalonMove(ACircularUnit target)
 {
     throw new NotImplementedException();
 }
コード例 #15
0
ファイル: ACircularUnit.cs プロジェクト: znsoft/AiCup
 public virtual bool IntersectsWith(ACircularUnit unit)
 {
     // если касаются, то false
     return(GetDistanceTo2(unit) < Geom.Sqr(Radius + unit.Radius));
 }
コード例 #16
0
ファイル: ACircularUnit.cs プロジェクト: znsoft/AiCup
 public ACircularUnit(ACircularUnit unit) : base(unit)
 {
     Radius = unit.Radius;
 }