예제 #1
0
        private static void UpdateEnemyFormations()
        {
            // будем пересоздавать вражеские формации не каждый тик, а то посядем по быстродействию.
            if (Global.World.TickIndex % 10 == 0)
            {
                var allEnemyTiles = new HashSet <Tile>();
                var formations    = new List <List <Tile> >();

                foreach (var tile in Global.DetailMap.Tiles)
                {
                    if (tile.Enemies.Count != 0 && !allEnemyTiles.Contains(tile))
                    {
                        var formationTiles = new List <Tile>();
                        AddToEnemyFormations(allEnemyTiles, formationTiles, tile);
                        formations.Add(formationTiles);
                    }
                }

                Global.EnemyFormations.Clear();
                foreach (var formation in formations)
                {
                    FormationFactory.CreateEnemyFormation(formation);
                }
            }
            foreach (var formation in Global.EnemyFormations)
            {
                formation.Update(Global.World.VehicleUpdates);
            }
        }
예제 #2
0
        public static void CreateProducedFormation()
        {
            foreach (var facility in Global.MyFacilities)
            {
                if (facility.Type == FacilityType.VehicleFactory)
                {
                    var createdVehicles = Global.MyVehicles.Values
                                          .Where(v => v.Groups.Length == 0 && v.IsInside(facility.Rect) && v.IsStanding)
                                          .ToList();

                    if (createdVehicles.Count > 50 || facility.NearGroundEnemyCount > 10 && createdVehicles.Count > 20)
                    {
                        var createdRect = new Rect(createdVehicles.Min(v => v.X),
                                                   createdVehicles.Min(v => v.Y),
                                                   createdVehicles.Max(v => v.X),
                                                   createdVehicles.Max(v => v.Y));
                        var allVehiclesInsideCount = Global.MyVehicles.Values.Count(v => v.IsInside(createdRect));
                        if (createdVehicles.Count == allVehiclesInsideCount)
                        {
                            var result = FormationFactory.CreateMyFormation(createdRect.Left, createdRect.Top,
                                                                            createdRect.Right, createdRect.Bottom);
                            result.Formation.ShiftTo(0, -50);
                            Global.ActionQueue.Add(new ActionSequence(result.ActionList.ToArray()));
                        }
                    }
                }
            }
        }
예제 #3
0
        public static void CreateProducedFormation()
        {
            foreach (var facility in Global.MyFacilities)
            {
                if (facility.Type == FacilityType.VehicleFactory)
                {
                    List <VehicleWrapper> createdVehicles = facility.CreatedVehicles;

                    if (createdVehicles.Count > 40 || facility.NearGroundEnemyCount > 10 && createdVehicles.Count > 20)
                    {
                        Rect createdRect            = facility.CreatedVehiclesRect;
                        var  allVehiclesInsideCount = Global.MyVehicles.Values.Count(v => v.IsInside(createdRect));
                        if (createdVehicles.Count == allVehiclesInsideCount)
                        {
                            var stopProduction = facility.StopProduction();
                            var result         = FormationFactory.CreateMyFormation(createdRect.Left, createdRect.Top,
                                                                                    createdRect.Right, createdRect.Bottom);
                            result.ActionList.Insert(0, stopProduction);

                            foreach (var action in result.ActionList)
                            {
                                action.Priority = ActionPriority.High;
                            }
                            Global.ActionQueue.Add(new ActionSequence(result.ActionList.ToArray()));
                        }
                    }
                }
            }
        }
예제 #4
0
        public static void SplitFormation(MyFormation formation, int runFromCenter = 0)
        {
            var child = FormationFactory.CreateMyFormation(
                () => formation.Rect.Left,
                () => formation.Rect.Top,
                () => formation.MassCenter.X,
                () => formation.MassCenter.Y);

            formation.Children.Add(child.Formation);
            var sequence = new ActionSequence(child.ActionList.ToArray());

            if (runFromCenter > 0)
            {
                sequence.Add(child.Formation.ShiftTo(-runFromCenter, -runFromCenter));
            }

            child = FormationFactory.CreateMyFormation(
                () => formation.MassCenter.X,
                () => formation.Rect.Top,
                () => formation.Rect.Right,
                () => formation.MassCenter.Y);
            sequence.AddRange(child.ActionList);
            formation.Children.Add(child.Formation);
            if (runFromCenter > 0)
            {
                sequence.Add(child.Formation.ShiftTo(runFromCenter, -runFromCenter));
            }

            child = FormationFactory.CreateMyFormation(
                () => formation.Rect.Left,
                () => formation.MassCenter.Y,
                () => formation.MassCenter.X,
                () => formation.Rect.Bottom);
            sequence.AddRange(child.ActionList);
            formation.Children.Add(child.Formation);
            if (runFromCenter > 0)
            {
                sequence.Add(child.Formation.ShiftTo(-runFromCenter, runFromCenter));
            }
            child = FormationFactory.CreateMyFormation(
                () => formation.MassCenter.X,
                () => formation.MassCenter.Y,
                () => formation.Rect.Right,
                () => formation.Rect.Bottom);
            sequence.AddRange(child.ActionList);
            formation.Children.Add(child.Formation);
            if (runFromCenter > 0)
            {
                sequence.Add(child.Formation.ShiftTo(runFromCenter, runFromCenter));
            }
            Global.ActionQueue.Add(sequence);
        }
예제 #5
0
        private static void CreateAndScale(VehicleType vehicleType)
        {
            var factor = 0.5;
            var result = FormationFactory.CreateMyFormation(vehicleType);

            var scaleAction = result.Formation.ScaleCenter(factor);

            scaleAction.StartCondition = () =>
            {
                return(result.ActionList.Last(a => a.ActionType == ActionType.Assign).Status ==
                       ActionStatus.Finished);
            };
            result.ActionList.Add(scaleAction);

            Global.ActionQueue.Add(new ActionSequence(result.ActionList.ToArray()));
        }
예제 #6
0
        public static MyFormation CreateAirFormation()
        {
            const double eps              = 10D;
            const double deltaShift       = 5.1D;
            const double commonCoordinate = 350D;
            const double nearCoordinate   = 60D;
            const double farCoordinate    = 200D;
            const double factor           = 1.7D;
            const double vehicleSize      = 4D;


            var fighters    = Global.MyFighters;
            var helicopters = Global.MyHelicopters;

            Global.IgnoreCollisionGroupIndexes.Add(fighters.GroupIndex);
            Global.IgnoreCollisionGroupIndexes.Add(helicopters.GroupIndex);

            var isVertical = Math.Abs(fighters.Rect.Left - helicopters.Rect.Left) < eps;

            MyFormation f1;
            MyFormation f2;
            double      f1MoveX;
            double      f1MoveY;
            double      f2MoveX;
            double      f2MoveY;
            double      shiftX;
            double      shiftY;
            double      compactX;
            double      compactY;
            double      angle;

            if (isVertical)
            {
                f1MoveX  = commonCoordinate + deltaShift;
                f1MoveY  = nearCoordinate;
                f2MoveX  = commonCoordinate;
                f2MoveY  = farCoordinate;
                shiftX   = 0;
                shiftY   = (farCoordinate - nearCoordinate) / 2;
                compactX = 0;
                compactY = 3 * vehicleSize;
                angle    = -Math.PI / 4;
            }

            else
            {
                f1MoveX  = nearCoordinate;
                f1MoveY  = commonCoordinate + deltaShift;
                f2MoveX  = farCoordinate;
                f2MoveY  = commonCoordinate;
                shiftX   = (farCoordinate - nearCoordinate) / 2;
                shiftY   = 0;
                compactX = 3 * vehicleSize;
                compactY = 0;
                angle    = Math.PI / 4;
            }
            if (isVertical && fighters.Rect.Top < helicopters.Rect.Top ||
                !isVertical && fighters.Rect.Left < helicopters.Rect.Left)
            {
                f1 = fighters;
                f2 = helicopters;
            }
            else
            {
                f1 = helicopters;
                f2 = fighters;
            }
            // двигаем первую формацию налево или вниз, а потом - масштабируем ее
            var sMove1 = new ActionSequence(
                f1.MoveLeftTopTo(f1MoveX, f1MoveY),
                f1.ScaleLeftTop(factor)
                );

            Global.ActionQueue.Add(sMove1);

            // двигаем вторую формацию налево или вниз, а потом - масштабируем ее
            var sMove2 = new ActionSequence(
                f2.MoveLeftTopTo(f2MoveX, f2MoveY),
                f2.ScaleLeftTop(factor)
                );

            Global.ActionQueue.Add(sMove2);

            // после того, как обе формации отмасштабированы, первая формация движеться наствречу второй
            var aPenetrate1 = f1.ShiftTo(shiftX, shiftY);

            aPenetrate1.StartCondition = () => sMove1.IsFinished && sMove2.IsFinished;
            var sPenetrate1 = new ActionSequence(aPenetrate1);

            Global.ActionQueue.Add(sPenetrate1);

            // а вторая - навстречу первой до полного проникновения
            var aPenetrate2 = f2.ShiftTo(-shiftX, -shiftY);

            aPenetrate2.StartCondition = () => sMove1.IsFinished && sMove2.IsFinished;
            var sPenetrate2 = new ActionSequence(aPenetrate2);

            Global.ActionQueue.Add(sPenetrate2);

            // сплющиваем сбоку бутерброд
            var res = FormationFactory.CreateMyFormation(
                () => Math.Min(f1.Rect.Left, f2.Rect.Left),
                () => Math.Min(f1.Rect.Top, f2.Rect.Top),
                () => Math.Max(f1.Rect.Right, f2.Rect.Right) - compactX,
                () => Math.Max(f1.Rect.Bottom, f2.Rect.Bottom) - compactY);

            Global.IgnoreCollisionGroupIndexes.Add(res.GroupIndex);

            var sShift = new ActionSequence(res.ActionList.ToArray());

            sShift.First().StartCondition = () => sPenetrate2.IsFinished && sPenetrate1.IsFinished;

            sShift.Add(res.Formation.ShiftTo(shiftX, shiftY));
            Global.ActionQueue.Add(sShift);

            //   компактизируем
            res = FormationFactory.CreateMyFormation(
                () => Math.Min(f1.Rect.Left, f2.Rect.Left),
                () => Math.Min(f1.Rect.Top, f2.Rect.Top),
                () => Math.Max(f1.Rect.Right, f2.Rect.Right),
                () => Math.Max(f1.Rect.Bottom, f2.Rect.Bottom));

            var sCompact = new ActionSequence(res.ActionList.ToArray());

            sCompact.First().StartCondition = () => sShift.IsFinished;
            sCompact.Add(res.Formation.ScaleCenter(1.2));
            sCompact.Add(res.Formation.RotateCenter(angle));
            sCompact.Add(res.Formation.ScaleCenter(0.5));
            sCompact.Add(res.Formation.ShiftTo(10, 10));
            Global.ActionQueue.Add(sCompact);

            return(res.Formation);
        }
예제 #7
0
        public static bool Attack(MyFormation formation)
        {
            var enemyFightersCount = Global.EnemyFighters.Count();

            if (formation == Global.MyHelicopters && enemyFightersCount > 30)
            {
                var enemyFighters = FormationFactory.CreateEnemyFormation(Global.EnemyFighters);
                if ((enemyFighters.Rect.RightBottom - enemyFighters.Rect.LeftTop).Length() < 300)
                {
                    MyFormation foundAllyGround = null;
                    if (Global.MyIfvs.Alive && Global.MyIfvs.Vehicles.Count > 30)
                    {
                        foundAllyGround = Global.MyIfvs;
                    }
                    else if (Global.MyArrvs.Alive && Global.MyArrvs.Vehicles.Count > 30)
                    {
                        foundAllyGround = Global.MyArrvs;
                    }
                    if (foundAllyGround != null)
                    {
                        var actionMove = formation.MoveCenterTo(Global.MyIfvs.Center);
                        AbortAndAddToExecutingSequence(formation, actionMove);
                        return(true);
                    }
                }
            }
            if (formation == Global.MyFighters)
            {
                if (enemyFightersCount > 10)
                {
                    var enemy       = FormationFactory.CreateEnemyFormation(Global.EnemyFighters);
                    var enemyLength = (enemy.Rect.RightBottom - enemy.Rect.LeftTop).Length();
                    if (enemyLength < 200)
                    {
                        MakeAttackOrder(formation, enemy, true);
                        return(true);
                    }
                }
                if (Global.EnemyHelicopters.Count() > 10)
                {
                    var enemy       = FormationFactory.CreateEnemyFormation(Global.EnemyHelicopters);
                    var enemyLength = (enemy.Rect.RightBottom - enemy.Rect.LeftTop).Length();
                    if (enemyLength < 300)
                    {
                        MakeAttackOrder(formation, enemy, true);
                        return(true);
                    }
                }
//                if (Global.MyArrvs.Alive && Global.MyArrvs.Vehicles.Count > 30)
//                {
//                    var actionMove = formation.MoveCenterTo(Global.MyArrvs.Center);
//                    AbortAndAddToExecutingSequence(formation, actionMove);
//                    return true;
//                }
            }

            var oneShotDanger = new Dictionary <EnemyFormation, double>();

            foreach (var enemy in Global.EnemyFormations)
            {
                var dangerForEnemy = formation.DangerFor(enemy);
                var dangerForMe    = enemy.DangerFor(formation);
                oneShotDanger.Add(enemy, dangerForEnemy - dangerForMe);
            }

            // todo: давать правильную команду
            // выбирать также по расстоянию
            EnemyFormation target     = null;
            var            targetPair = oneShotDanger.OrderByDescending(kv => kv.Value).First();

            if (targetPair.Value > 0)
            {
                target = targetPair.Key;
            }

            if (target != null)
            {
                var targetFacility = Global.World.Facilities
                                     .Where(f => f.SelectedAsTargetForGroup == formation.GroupIndex).ToList();
                if (targetFacility.Any())
                {
                    foreach (var facility in targetFacility)
                    {
                        facility.SelectedAsTargetForGroup = null;
                    }
                    OccupyFacilities(formation);
                    return(true);
                }
                MakeAttackOrder(formation, target, false);
                return(true);
            }
            return(false);
        }
예제 #8
0
        public static void Anticollision()
        {
            if (Global.JoinFormation1 != null && Global.JoinFormation1.Alive && Global.JoinFormation1.Count > 0 &&
                Global.JoinFormation2 != null && Global.JoinFormation2.Alive && Global.JoinFormation2.Count > 0)
            {
                var result = FormationFactory.CreateMyFormation(Global.JoinFormation1, Global.JoinFormation2);

                Global.JoinFormation1 = null;
                Global.JoinFormation2 = null;

                Global.ActionQueue.Add(new ActionSequence(result.ActionList.ToArray()));
                return;
            }
            var processedKeys = new List <int>();

            foreach (var key1 in Global.MyFormations.Keys)
            {
                var f1 = Global.MyFormations[key1];
                if (f1.Alive && !Global.IgnoreCollisionGroupIndexes.Contains(key1))
                {
                    foreach (var facility in Global.MyFacilities.Where(f =>
                                                                       f.Type == FacilityType.VehicleFactory && f.VehicleType.HasValue))
                    {
                        var facRect = facility.CreatedVehiclesRect;

                        if (f1.IsAllAeral && facility.CreatedVehicles.All(v => v.IsAerial) ||
                            f1.IsAllGround && facility.CreatedVehicles.All(v => !v.IsAerial))
                        {
                            var distBetweenCenters = f1.Rect.Center.SqrDistance(facRect.Center);
                            if (distBetweenCenters < (f1.Rect.SqrDiameter + facRect.SqrDiameter) / 2)
                            {
                                if (!processedKeys.Contains(key1))
                                {
                                    processedKeys.Add(key1);
                                    var delta           = f1.Center - facRect.Center;
                                    var normalizedSpeed = f1.AvgSpeed.Normalized();
                                    var rotated         = new Point(normalizedSpeed.Y, -normalizedSpeed.X);
                                    delta = delta.Normalized();

                                    CompactAndContinue(f1, 50 * (delta + rotated / 2));
                                }
                            }
                        }
                    }

                    foreach (var key2 in Global.MyFormations.Keys.Where(k => k != key1))
                    {
                        var f2 = Global.MyFormations[key2];
                        if (f2.Alive &&
                            !Global.IgnoreCollisionGroupIndexes.Contains(key2) &&
                            (f1.IsMixed || f2.IsMixed || f1.IsAllAeral == f2.IsAllAeral))
                        {
                            var distBetweenCenters = f1.Rect.Center.SqrDistance(f2.Rect.Center);
                            if (distBetweenCenters < (f1.Rect.SqrDiameter + f2.Rect.SqrDiameter) / 2)
                            {
                                var delta = f1.Center - f2.Center;

                                if (Global.MyFormations.Count > 15 &&
                                    f1.Count < 50 &&
                                    f2.Count < 50 &&
                                    !processedKeys.Contains(key1) &&
                                    !processedKeys.Contains(key2))
                                {
                                    processedKeys.Add(key1);
                                    processedKeys.Add(key2);
                                    Global.JoinFormation1 = f1;
                                    Global.JoinFormation2 = f2;
                                    return;
                                }
                                else
                                {
                                    if (!processedKeys.Contains(key1))
                                    {
                                        processedKeys.Add(key1);
                                        var delta1 = 20 * (delta.Normalized() + f1.AvgSpeed.Normalized() / 2);

                                        CompactAndContinue(f1, delta1);
                                    }
                                    if (!processedKeys.Contains(key2))
                                    {
                                        processedKeys.Add(key2);
                                        var delta2 = 20 * (delta.Normalized() + f2.AvgSpeed.Normalized() / 2);
                                        CompactAndContinue(f2, -1 * delta2);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #9
0
        private static bool AirAttack(MyFormation formation)
        {
            if (formation != Global.MyHelicopters && formation != Global.MyFighters)
            {
                return(false);
            }
            if (Global.MyArrvs.Alive && Global.MyArrvs.Vehicles.Count > 10)
            {
                var durabilityPercent = formation.Durability / (formation.MaxDurability + 1);
                if (durabilityPercent < 0.7 || (durabilityPercent < 0.9 && formation.Center.Distance(Global.MyArrvs.Center) < 100))
                {
                    if (MoveToAlly(formation, Global.MyArrvs))
                    {
                        return(true);
                    }
                }
            }
            var enemyFightersCount = Global.EnemyFighters.Count();

            if (formation == Global.MyHelicopters)
            {
                if (enemyFightersCount > 30)
                {
                    var enemyFighters = FormationFactory.CreateEnemyFormation(Global.EnemyFighters);

                    var isMyArrvsCanProtect  = Global.MyArrvs.Alive && Global.MyArrvs.Vehicles.Count > 30;
                    var distanceToProtection = isMyArrvsCanProtect
                        ? Global.MyArrvs.Rect.Center.Distance(formation.Center)
                        : 0;

                    if ((enemyFighters.Rect.RightBottom - enemyFighters.Rect.LeftTop).Length() < 300 &&
                        enemyFighters.Rect.Center.Distance(formation.Center) < distanceToProtection)
                    {
                        MyFormation foundAllyGround = null;
                        if (Global.MyIfvs.Alive && Global.MyIfvs.Vehicles.Count > 30)
                        {
                            foundAllyGround = Global.MyIfvs;
                        }
                        else if (isMyArrvsCanProtect)
                        {
                            foundAllyGround = Global.MyArrvs;
                        }
                        if (foundAllyGround != null)
                        {
                            var actionMove = formation.MoveCenterTo(foundAllyGround.Center);
                            AbortAndAddToExecutingSequence(formation, actionMove);
                            return(true);
                        }
                    }
                }
                if (Global.EnemyVehicles.Count == 0)
                {
                    var actionMove = formation.MoveCenterTo(Global.World.Width / 3 - 100, Global.World.Height / 3);
                    AbortAndAddToExecutingSequence(formation, actionMove);
                    return(true);
                }
            }
            if (formation == Global.MyFighters)
            {
                if (enemyFightersCount > 10)
                {
                    var rect = new Rect(Global.EnemyFighters.Min(f => f.X),
                                        Global.EnemyFighters.Min(f => f.Y),
                                        Global.EnemyFighters.Max(f => f.X),
                                        Global.EnemyFighters.Max(f => f.Y));
                    var allEnemiesNearFighters = Global.EnemyVehicles.Values.Where(v => v.IsInside(rect));
                    var enemy = FormationFactory.CreateEnemyFormation(allEnemiesNearFighters);


                    var enemyLength = (enemy.Rect.RightBottom - enemy.Rect.LeftTop).Length();
                    if (enemyLength < 200)
                    {
                        if (AttackOrRunAway(formation, enemy))
                        {
                            return(true);
                        }
                    }
                }
                if (Global.EnemyHelicopters.Count() > 10)
                {
                    var rect = new Rect(Global.EnemyHelicopters.Min(f => f.X),
                                        Global.EnemyHelicopters.Min(f => f.Y),
                                        Global.EnemyHelicopters.Max(f => f.X),
                                        Global.EnemyHelicopters.Max(f => f.Y));
                    var allEnemiesNearHeli = Global.EnemyVehicles.Values.Where(v => v.IsInside(rect));
                    var enemy = FormationFactory.CreateEnemyFormation(allEnemiesNearHeli);

                    var enemyLength = (enemy.Rect.RightBottom - enemy.Rect.LeftTop).Length();
                    if (enemyLength < 300)
                    {
                        if (AttackOrRunAway(formation, enemy))
                        {
                            return(true);
                        }
                    }
                }
                if (Global.EnemyVehicles.Count == 0)
                {
                    var actionMove = formation.MoveCenterTo(Global.World.Width / 2 + 100, Global.World.Height / 2);
                    AbortAndAddToExecutingSequence(formation, actionMove);
                    return(true);
                }
            }
            return(false);
        }