Beispiel #1
0
        public static bool HasConflicts(AUnit a, AUnit b)
        {
            if (a is AMinion && (a as AMinion).IsNeutral && !(a as AMinion).IsAggressiveNeutral)
            {
                return(false);
            }
            if (b is AMinion && (b as AMinion).IsNeutral && !(b as AMinion).IsAggressiveNeutral)
            {
                return(false);
            }

            return(a.Faction != b.Faction);
        }
Beispiel #2
0
        MovingInfo _findCastTarget2(AWizard self, Point moveTo, ProjectileType projectileType)
        {
            var move = new FinalMove(new Move());

            if (projectileType == ProjectileType.MagicMissile)
            {
                AUnit  mmSelTarget      = null;
                Point  mmSelFirstMoveTo = null;
                var    mmMinTicks       = int.MaxValue;
                double mmMinPriority    = int.MaxValue;

                foreach (var opp in OpponentCombats)
                {
                    if (self.GetDistanceTo2(opp) > Geom.Sqr(self.CastRange + opp.Radius + 40) || !opp.IsAssailable)
                    {
                        continue;
                    }

                    var nearest = Combats
                                  .Where(x => self.GetDistanceTo2(x) < Geom.Sqr(Math.Max(x.VisionRange, self.VisionRange) * 1.3))
                                  .Select(Utility.CloneCombat)
                                  .ToArray();

                    var targetsSelector = new TargetsSelector(nearest)
                    {
                        EnableMinionsCache = true
                    };

                    var nearstOpponents = nearest
                                          .Where(x => x.IsOpponent)
                                          .ToArray();

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

                    var ticks = 0;
                    var my    = nearest.FirstOrDefault(x => x.Id == self.Id) as AWizard;
                    var his   = nearest.FirstOrDefault(x => x.Id == opp.Id);
                    if (my == null || his == null)
                    {
                        continue;
                    }

                    Point firstMoveTo  = null;
                    var   buildingsHit = false;
                    while (!my.EthalonCanCastMagicMissile(his, checkCooldown: false))
                    {
                        if (ticks > 40)
                        {
                            break;
                        }

                        var m = moveTo;
                        var stopIfCannotMove = true;
                        if (m == null && my.EthalonCanCastMagicMissile(his, checkCooldown: false, checkAngle: false))
                        {
                            stopIfCannotMove = false;
                            m = my + (my - his);
                            var tmp = new AWizard(my);
                            tmp.MoveTo(m, his, w => !CheckIntersectionsAndTress(w, nearest));

                            if (EstimateDanger(my, false) <= EstimateDanger(tmp, false))
                            {
                                m = null;
                            }
                        }
                        if (m == null)
                        {
                            m = his;
                        }

                        if (ticks == 0)
                        {
                            firstMoveTo = m;
                        }

                        if (!my.MoveTo(m, his, w => !CheckIntersectionsAndTress(w, nearest)) && Utility.PointsEqual(m, his) && stopIfCannotMove)
                        {
                            break;
                        }

                        foreach (var x in nearest)
                        {
                            if (x.Id == my.Id)
                            {
                                continue;
                            }
                            var tar = targetsSelector.Select(x);
                            buildingsHit = buildingsHit ||
                                           (x.IsOpponent && x is ABuilding && tar != null && tar.Id == my.Id && x.EthalonCanHit(my));

                            if (x.IsOpponent)
                            {
                                x.EthalonMove(tar ?? my);
                            }
                            else if (tar != null)
                            {
                                x.EthalonMove(tar);
                            }
                            else
                            {
                                x.SkipTick();
                            }
                        }
                        ticks++;
                    }

                    if (his is AWizard && (his as AWizard).IsBesieded)
                    {
                        ticks -= 15; // чтобы дать больше приоритета визарду
                    }
                    var priority = GetCombatPriority(self, his);
                    if (ticks < mmMinTicks || ticks == mmMinTicks && priority < mmMinPriority)
                    {
                        if (my.EthalonCanCastMagicMissile(his))
                        {
                            if (nearstOpponents.All(x =>
                            {
                                if (canHitNow && x.Id == opp.Id) // он и так доставал
                                {
                                    return(true);
                                }

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

                                if (his.Id == x.Id && CanRush(my, x))
                                {
                                    return(true);
                                }

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

                                return(false);
                            })
                                )
                            {
                                mmMinTicks       = ticks;
                                mmMinPriority    = priority;
                                mmSelTarget      = opp;
                                mmSelFirstMoveTo = firstMoveTo;
                            }
                        }
                    }
                }


                if (mmSelTarget != null)
                {
                    mmMinTicks = Math.Max(0, mmMinTicks);
                    move.MoveTo(moveTo ?? mmSelFirstMoveTo, mmSelTarget);
                    return(new MovingInfo(mmSelTarget, mmMinTicks, move)
                    {
                        TargetId = mmSelTarget.Id
                    });
                }
            }


            const int walkLimit = 9;

            if (projectileType == ProjectileType.Fireball && self.FireballSkillLevel == 5 && Math.Max(self.RemainingActionCooldownTicks, self.RemainingFireballCooldownTicks) <= walkLimit)
            {
                var   fbMaxDamage = 0.0;
                Point fbSelTarget = null;
                var   fbMinTicks  = int.MaxValue;

                foreach (var ang in Utility.Range(-Game.StaffSector, Game.StaffSector, 10))
                {
                    var nearest = Combats
                                  .Where(x => self.GetDistanceTo2(x) < Geom.Sqr(Math.Max(x.VisionRange, self.VisionRange) * 1.3))
                                  .Select(Utility.CloneCombat)
                                  .ToArray();

                    var targetsSelector = new TargetsSelector(nearest)
                    {
                        EnableMinionsCache = true
                    };

                    var ticks = 0;
                    var my    = nearest.FirstOrDefault(x => x.Id == self.Id) as AWizard;
                    var dir   = my + Point.ByAngle(my.Angle + ang) * 1000;

                    while (ticks <= walkLimit)
                    {
                        if (my.CanUseFireball())
                        {
                            var proj = new AProjectile(my, 0, ProjectileType.Fireball);
                            var path = proj.Emulate(nearest, 0.0);

                            var damage =
                                path.Where(x => _isFireballGoodSeg(my, x))
                                .Select(x => x.OpponentDamage)
                                .DefaultIfEmpty(0)
                                .Max();
                            if (damage > fbMaxDamage)
                            {
                                fbMaxDamage = damage;
                                fbSelTarget = dir;
                                fbMinTicks  = ticks;
                            }
                        }

                        foreach (var x in nearest)
                        {
                            if (x.Id == my.Id)
                            {
                                continue;
                            }

                            if (x is AMinion)
                            {
                                x.EthalonMove(targetsSelector.Select(x));
                            }
                            else
                            {
                                x.SkipTick();
                            }
                        }

                        if (!my.MoveTo(dir, dir, w => !CheckIntersectionsAndTress(w, nearest)))
                        {
                            break;
                        }

                        if (nearest.Any(x => x.IsOpponent && x is ABuilding && x.EthalonCanHit(my) && targetsSelector.Select(x) == my))
                        {
                            break;
                        }
                        ticks++;
                    }
                }


                if (fbSelTarget != null)
                {
                    move.MoveTo(fbSelTarget, fbSelTarget);
                    return(new MovingInfo(fbSelTarget, fbMinTicks, move)
                    {
                        Damage = fbMaxDamage
                    });
                }
            }

            return(new MovingInfo(null, int.MaxValue, move));
        }
Beispiel #3
0
        private void _move(Wizard self, World world, Game game, Move move)
        {
            World     = world;
            Game      = game;
            Self      = self;
            FinalMove = new FinalMove(move);

            Const.Initialize();
            MagicConst.TreeObstacleWeight = Const.IsFinal ? 25 : 35;

            Wizards = world.Wizards
                      .Select(x => new AWizard(x))
                      .ToArray();

            foreach (var wizard in Wizards)
            {
                foreach (var other in Wizards)
                {
                    if (wizard.Faction != other.Faction)
                    {
                        continue;
                    }
                    if (wizard.GetDistanceTo2(other) > Geom.Sqr(Game.AuraSkillRange))
                    {
                        continue;
                    }

                    for (var i = 0; i < 5; i++)
                    {
                        wizard.AurasFactorsArr[i] = Math.Max(wizard.AurasFactorsArr[i], other.SkillsLearnedArr[i] / 2);
                    }
                }
                var orig   = World.Wizards.FirstOrDefault(w => w.Id == wizard.Id);
                var player = World.Players.FirstOrDefault(p => orig != null && p.Id == orig.OwnerPlayerId);
                if (player != null && player.IsStrategyCrashed)
                {
                    wizard.RemainingFrozen = 100500;
                }
            }

            OpponentWizards = Wizards
                              .Where(x => x.IsOpponent)
                              .ToArray();

            MyWizards = Wizards
                        .Where(x => x.IsTeammate)
                        .ToArray();

            Minions = world.Minions
                      .Select(x => x.Type == MinionType.OrcWoodcutter ? (AMinion) new AOrc(x) : new AFetish(x))
                      .ToArray();

            NeutralMinions = Minions
                             .Where(x => x.Faction == Faction.Neutral)
                             .ToArray();

            Combats =
                Minions.Cast <ACombatUnit>()
                .Concat(Wizards)
                .Concat(BuildingsObserver.Buildings)//TODO перед BuildingsObserver.Update????
                .ToArray();

            MyCombats = Combats
                        .Where(x => x.IsTeammate)
                        .ToArray();

            NeutralMinionsObserver.Update();
            OpponentMinions = Minions
                              .Where(x => x.IsOpponent)
                              .ToArray();

            OpponentCombats = Combats
                              .Where(x => x.IsOpponent)
                              .ToArray();

            RoadsHelper.Initialize();
            BuildingsObserver.Update();

            OpponentBuildings = BuildingsObserver.Buildings
                                .Where(x => x.IsOpponent)
                                .ToArray();

            TreesObserver.Update();
            ProjectilesObserver.Update();
            BonusesObserver.Update();
            MessagesObserver.Update();

            InitializeProjectiles();
            InitializeDijkstra();

            ASelf = Wizards.FirstOrDefault(x => x.Id == Self.Id);
            if (ASelf == null)
            {
                throw new Exception("Self not found in wizards list");
            }

            InitializeDangerEstimation();
            SupportObserver.Update();

            if (Self.IsMaster && World.TickIndex == 0)
            {
                MasterSendMessages();
            }
            if (Self.IsMaster)
            {
                MasterCheckRearrange();
            }

            var nearestBonus         = BonusesObserver.Bonuses.ArgMin(b => b.GetDistanceTo(ASelf));
            var opponentsAroundBonus = OpponentWizards.Where(w => nearestBonus.GetDistanceTo(w) < ASelf.VisionRange * 1.5).ToArray();
            var teammatesAroundBonus = MyWizards.Where(w => ASelf.GetDistanceTo(w) < ASelf.VisionRange * 1.5).ToArray();



            WizardPath path        = null;
            AUnit      pathTarget  = null;
            var        goAway      = GoAwayDetect();
            var        bonusMoving = goAway ? new MovingInfo(null, int.MaxValue, null) : GoToBonus();
            var        target      = FindTarget(new AWizard(ASelf), bonusMoving.Target);

            if (target == null && bonusMoving.Target == null && !goAway)
            {
                var nearest = OpponentCombats
                              .Where(
                    x =>
                    Utility.IsBase(x) || RoadsHelper.GetLane(x) == MessagesObserver.GetLane() ||
                    RoadsHelper.GetLaneEx(ASelf) == ALaneType.Middle &&
                    RoadsHelper.GetLaneEx(x) == ALaneType.Middle && CanRush(ASelf, x))
                              .Where(x => x.IsAssailable && x.Faction != Faction.Neutral)
                              .OrderBy(
                    x =>
                    x.GetDistanceTo(self) +
                    (x is AWizard ? -40 : (x is ABuilding && !((ABuilding)x).IsBesieded) ? 1500 : 0))
                              .ToArray();

                foreach (var n in nearest)
                {
                    path = GoAgainst(n);
                    if (path != null)
                    {
                        pathTarget = n;
                        break;
                    }
                }
                if (nearest.Length > 0 && path == null)
                {
                    GoDirect(nearest[0], FinalMove);
                }
            }

            TimerStart();
            if (!TryDodgeProjectile())
            {
                if (target == null)
                {
                    TryPreDodgeProjectile();
                }

                if (goAway)
                {
                    GoAway();
                }
                else if (target == null || target.Type == TargetType.Teammate ||
                         (FinalMove.Action == ActionType.Staff ||
                          FinalMove.Action == ActionType.MagicMissile ||
                          FinalMove.Action == ActionType.Fireball ||
                          FinalMove.Action == ActionType.FrostBolt) && target.Type == TargetType.Opponent)
                {
                    if (bonusMoving.Target != null)
                    {
                        NextBonusWaypoint = bonusMoving.Target;
                        FinalMove.Turn    = bonusMoving.Move.Turn;
                        if (bonusMoving.Move.Action != ActionType.None && bonusMoving.Move.Action != null)
                        {
                            FinalMove.Action          = bonusMoving.Move.Action;
                            FinalMove.MinCastDistance = bonusMoving.Move.MinCastDistance;
                            FinalMove.MaxCastDistance = bonusMoving.Move.MaxCastDistance;
                            FinalMove.CastAngle       = bonusMoving.Move.CastAngle;
                        }

                        NextBonusWaypoint = ASelf + (NextBonusWaypoint - ASelf).Normalized() * (Self.Radius + 30);

                        if (nearestBonus.GetDistanceTo(ASelf) < ASelf.VisionRange * 1.5 &&
                            nearestBonus.GetDistanceTo(ASelf) > 100 &&
                            opponentsAroundBonus.Length <= 1 &&
                            ASelf.Life + 10 >= (opponentsAroundBonus.FirstOrDefault() ?? ASelf).Life &&
                            OpponentMinions.Count(x => x.GetDistanceTo(ASelf) < Game.FetishBlowdartAttackRange) == 0
                            )
                        {
                            FinalMove.MoveTo(NextBonusWaypoint, null);
                        }
                        else
                        {
                            TryGoByGradient(x => EstimateDanger(x), null, FinalMove);
                        }
                    }
                    else
                    {
                        var all = Combats.Select(Utility.CloneCombat).ToArray();
                        var my  = all.FirstOrDefault(x => x.Id == ASelf.Id) as AWizard;

                        my?.Move(FinalMove.Speed, FinalMove.StrafeSpeed);
                        var ts = new TargetsSelector(all);

                        var skipBuildings = path == null ||
                                            path.GetLength() < 300 ||
                                            path.GetLength() < 600 && OpponentBuildings.Any(x =>
                        {
                            var tar = ts.Select(x);
                            return(tar != null && tar.Id == ASelf.Id);
                        });


                        if (TryGoByGradient(x => EstimateDanger(x), x => HasAnyTarget(x, skipBuildings), FinalMove))
                        {
                            var cutTreeMovingInfo = FindTreeTarget(ASelf);
                            if (cutTreeMovingInfo.Target != null)
                            {
                                FinalMove.Turn = cutTreeMovingInfo.Move.Turn;
                                if (cutTreeMovingInfo.Move.Action != null && FinalMove.Action == null)
                                {
                                    FinalMove.Action = cutTreeMovingInfo.Move.Action;
                                }
                                // не будет мешать TryPreDodgeProjectile?
                            }
                        }
                    }
                }

                PostDodgeProjectile();
            }
            TimerEndLog("Go", 1);

            if (ASelf.CanLearnSkill)
            {
                move.SkillToLearn = MessagesObserver.GetSkill();
            }
        }
Beispiel #4
0
 public AUnit(AUnit unit) : base(unit)
 {
     Id      = unit.Id;
     Angle   = unit.Angle;
     Faction = unit.Faction;
 }