Ejemplo n.º 1
0
        private static void _selectIfNotSelected(Sandbox env, AMove move)
        {
            if (move.Action != ActionType.ClearAndSelect)
            {
                throw new Exception("Invalid arguments for _selectIfNotSelected");
            }
            var selHash = Utility.UnitsHash(env.MyVehicles.Where(x =>
                                                                 move.Rect.ContainsPoint(x) &&
                                                                 (move.VehicleType == null || move.VehicleType == x.Type) &&
                                                                 (move.Group == 0 || x.HasGroup(move.Group))));

            var curHash = Utility.UnitsHash(env.MyVehicles.Where(x => x.IsSelected));

            if (curHash != selHash)
            {
                MoveQueue.Add(move);
            }
        }
Ejemplo n.º 2
0
        public static void Update2(Sandbox prevEnv, Sandbox curEnv)
        {
            if (G.IsFogOfWarEnabled)
            {
                foreach (var veh in OppUncheckedVehicles.Values.ToArray())
                {
                    if (_isVehicleVisible(curEnv, veh))
                    {
                        OppCheckedVehicles.Add(veh.Id, veh);
                        OppUncheckedVehicles.Remove(veh.Id);
                    }
                }

                foreach (var disappearedId in _disappearedIds)
                {
                    if (curEnv.VehicleById.ContainsKey(disappearedId))
                    {
                        throw new Exception("Something wrong");
                    }

                    var veh = prevEnv.VehicleById[disappearedId];
                    if (_isVehicleVisible(curEnv, veh))
                    {
                        // убит
                    }
                    else
                    {
                        OppUncheckedVehicles[veh.Id] = veh;
                    }
                }

                if (MyStrategy.World.TickIndex == 0)
                {
                    _fillStartingPosition(curEnv.MyVehicles);
                }
            }

            if (MyStrategy.World.TickIndex > 0)
            {
                _facilitiesProduction(prevEnv, curEnv);
            }
        }
Ejemplo n.º 3
0
        private static AVehicle _doFacilityProd(Sandbox env, AFacility facility)
        {
            var vehicleType = facility.VehicleType.Value;
            var isMy        = facility.IsMy;

            var pt = new ACircularUnit();

            pt.Radius = G.VehicleRadius;

            for (var j = 0; j < 11; j++)
            {
                for (var i = 0; i < 11; i++)
                {
                    if (facility.IsMy)
                    {
                        pt.X = facility.X + i * 6 + G.VehicleRadius;
                        pt.Y = facility.Y + j * 6 + G.VehicleRadius;
                    }
                    else
                    {
                        pt.X = facility.X2 - i * 6 - G.VehicleRadius;
                        pt.Y = facility.Y2 - j * 6 - G.VehicleRadius;
                    }

                    var nearby = env.GetFirstIntersector(pt, Utility.IsAerial(vehicleType));
                    if (nearby == null && !facility.IsMy)
                    {
                        nearby = OppUncheckedVehicles.Values
                                 .Where(x => Utility.IsAerial(x.Type) == Utility.IsAerial(vehicleType))
                                 .ArgMin(x => x.GetDistanceTo2(pt));
                    }

                    if (nearby == null || !nearby.IntersectsWith(pt) || nearby.Id == _nextFreeId && Geom.PointsEquals(nearby, pt))
                    {
                        return(new AVehicle(pt, _nextFreeId++, vehicleType, isMy));
                    }
                }
            }
            return(null);
        }
Ejemplo n.º 4
0
        static double GetSumMaxAlmostAttacks(Sandbox env, IEnumerable <AVehicle> myVehicles)
        {
            Logger.CumulativeOperationStart("Danger0");
            var result = myVehicles.Sum(m =>
            {
                var additionalRadius   = m.ActualSpeed;
                const int radiusFactor = 5;
                return(env.GetOpponentNeighbours(m.X, m.Y, G.MaxAttackRange + additionalRadius * radiusFactor).DefaultIfEmpty(null)
                       .Max(opp =>
                {
                    if (opp == null)
                    {
                        return 0;
                    }
                    var dmg = opp.GetAttackDamage(m, additionalRadius * radiusFactor);
                    if (dmg == 0)
                    {
                        return
                        -(m.GetAttackDamage(opp, additionalRadius) +
                          m.GetAttackDamage(opp, additionalRadius * radiusFactor) / 2.0);
                    }
                    return (opp.GetAttackDamage(m, additionalRadius) +
                            opp.GetAttackDamage(m, additionalRadius * 2) / 2.0 +
                            opp.GetAttackDamage(m, additionalRadius * 3) / 4.0 +
                            opp.GetAttackDamage(m, additionalRadius * 4) / 8.0 +
                            dmg / 16.0
                            ) *
                    (G.AttackDamage[(int)m.Type, (int)opp.Type] > 0
                                   ? Geom.Sqr(1.0 * opp.Durability / G.MaxDurability)
                                   : 1) *
                    (m.Type == opp.Type ? 0.6 : 1) *
                    (G.IsAerialButerDetected && opp.Type == VehicleType.Fighter ? 3 : 1);
                }));
            });

            Logger.CumulativeOperationEnd("Danger0");
            return(result);
        }
Ejemplo n.º 5
0
        private double _nuclearGetDamage(AVehicle veh, Sandbox env, double lowerBound, List <AVehicle> targets, out ANuclear nuclearResult)
        {
            var vr  = veh.ActualVisionRange * 0.9;
            var cen = Utility.Average(targets);

            cen = veh + (cen - veh).Normalized() * Math.Min(vr, veh.GetDistanceTo(cen));
            var nuclear = new ANuclear(cen.X, cen.Y, true, veh.Id, G.TacticalNuclearStrikeDelay);

            nuclearResult = nuclear;

            var totalOpponentDamage = targets.Sum(x => x.GetNuclearDamage(nuclear));

            if (totalOpponentDamage <= lowerBound)
            {
                return(totalOpponentDamage);
            }

            var totalDamage = totalOpponentDamage -
                              env.GetMyNeighbours(nuclear.X, nuclear.Y, nuclear.Radius)
                              .Sum(x => x.GetNuclearDamage(nuclear));

            return(totalDamage);
        }
Ejemplo n.º 6
0
        Tuple <AMove[], MyGroup, DangerResult> MainLoopStrategy(bool opt)
        {
            VisualSegments.Clear();
            var visualVectorsStart = new List <Point>();
            var visualVectorsDir   = new List <Point>();
            var visualVectorsScore = new List <double>();

            _isSlowMode = _isSlowMode && Environment.OppVehicles.Count == 0;
            var baseTicksCount = Const.ActionsBruteforceDepth;

            if (Environment.Nuclears.Length > 0)
            {
                baseTicksCount *= 2;
            }

            var          selMoves  = new[] { new AMove() };
            MyGroup      selGroup  = null;
            DangerResult selDanger = null;

            var targetFacilities = GetDanger(Environment, Environment, GroupsManager.MyGroups, MyUngroupedClusters).TargetFacility;

            for (var s = 0; s < GroupsManager.MyGroups.Count + MyUngroupedClusters.Count; s++)
            {
                var availableActions = MoveObserver.AvailableActions;
                if (Opp.RemainingNuclearStrikeCooldownTicks < 60 && Environment.Nuclears.Length == 0)
                {
                    availableActions -= 2;
                }

                MyGroup         group;
                List <AVehicle> newGroupVehicles = null;
                if (s < GroupsManager.MyGroups.Count)
                {
                    group = GroupsManager.MyGroups[s];
                }
                else
                {
                    newGroupVehicles = MyUngroupedClusters[s - GroupsManager.MyGroups.Count];
                    if (newGroupVehicles.Count < NewGroupMinSize)
                    {
                        continue;
                    }
                    if (availableActions < 3) // required: clear, move, assign
                    {
                        continue;
                    }
                    group = new MyGroup(GroupsManager.NextGroupId, newGroupVehicles[0].Type);
                }

                if (opt && !(
                        Environment.Nuclears.Length > 0 ||
                        Environment.Facilities.Length <= 4 ||
                        World.TickIndex < 2500 ||
                        MoveObserver.MaxAvailableActions <= 12 ||
                        _doMainLastGroup != null && _doMainLastGroup.Group == group.Group ||                                                                   // ходил предыдущий раз
                        (newGroupVehicles == null && group.Group % 2 == _doMainsCount % 2 || newGroupVehicles != null && group.Group % 3 == _doMainsCount % 3) // через раз/два
                        ))
                {
                    continue;
                }

                if (_isSlowMode && World.TickIndex < 300 && group.VehicleType == VehicleType.Helicopter)
                {
                    continue;
                }

                Logger.CumulativeOperationStart("First env actions");

                var startEnv   = Environment.Clone();
                var ticksCount = baseTicksCount;

                if (newGroupVehicles != null)
                {
                    foreach (var newVeh in newGroupVehicles)
                    {
                        startEnv.AddVehicleGroup(startEnv.VehicleById[newVeh.Id], group.Group);
                    }
                }

                var selectedIds     = Utility.UnitsHash(startEnv.MyVehicles.Where(x => x.IsSelected));
                var needToSelectIds = Utility.UnitsHash(startEnv.GetVehicles(true, group));

                List <AMove> selectionMoves = new List <AMove>();

                if (selectedIds != needToSelectIds)
                {
                    if (availableActions < 2) // required: select, move
                    {
                        Logger.CumulativeOperationEnd("First env actions");
                        continue;
                    }

                    if (newGroupVehicles == null)
                    {
                        selectionMoves.Add(AMovePresets.ClearAndSelectGroup(group.Group));
                    }
                    else
                    {
                        var selectionMove = AMovePresets.ClearAndSelectType(group.VehicleType, Utility.BoundingRect(newGroupVehicles));
                        startEnv.ApplyMove(selectionMove); // ниже выполнится лишний раз, но не страшно
                        selectionMoves.Add(selectionMove);

                        foreach (var mg in GroupsManager.MyGroups)
                        {
                            if (mg.VehicleType == group.VehicleType && startEnv.MyVehicles.Where(x => x.IsSelected).Any(x => x.IsGroup(mg)))
                            {
                                selectionMoves.Add(new AMove {
                                    Action = ActionType.Deselect, Group = mg.Group
                                });
                            }
                        }
                    }

                    if (availableActions < selectionMoves.Count + 1) // required: select, move, deselect all
                    {
                        Logger.CumulativeOperationEnd("First env actions");
                        continue;
                    }

                    foreach (var mv in selectionMoves)
                    {
                        startEnv.ApplyMove(mv);
                        availableActions--;
                    }
                }
                availableActions--;

                Logger.CumulativeOperationEnd("First env actions");

                // availableActions теперь - это сколько действий останется после выполнения текущего тика
                // должно остаться хотябы 2, или 0, если обладатель ядерки selected
                var myNuclear = startEnv.Nuclears.FirstOrDefault(n => n.IsMy);
                if (myNuclear != null && availableActions < 2 - (startEnv.VehicleById.ContainsKey(myNuclear.VehicleId) && startEnv.VehicleById[myNuclear.VehicleId].IsSelected ? 2 : 0))
                {
                    continue;
                }

                var typeRect = Utility.BoundingRect(startEnv.GetVehicles(true, group));

                Sandbox partialEnv = null;
                var     sumMaxAlmostAttacksCache = -1.0;
                if (Environment.Nuclears.Length == 0)
                {
                    Logger.CumulativeOperationStart("Partial env actions");

                    partialEnv = new Sandbox(
                        startEnv.Vehicles.Where(x => !x.IsSelected),
                        new ANuclear[] { },
                        startEnv.Facilities,
                        clone: true
                        );
                    partialEnv.CheckCollisionsWithOpponent = false;

                    var grps = GroupsManager.MyGroups.Select(g => partialEnv.GetVehicles(true, g).ToArray()).ToArray();

                    try
                    {
                        for (var i = 0; i < ticksCount; i++)
                        {
                            for (var j = 0; j < grps.Length; j++)
                            {
                                var pgr = grps[j];
                                if (pgr.Length > 0)
                                {
                                    partialEnv.DoMoveApprox(pgr, pgr[0].Action != AVehicle.MoveType.Scale);
                                }
                            }
                            partialEnv.DoFacilities();
                            partialEnv.DoNuclears();
                        }
                        partialEnv.DoFight();

                        sumMaxAlmostAttacksCache = GetSumMaxAlmostAttacks(partialEnv, partialEnv.MyVehicles);
                    }
                    catch (QuadTree <AVehicle> .PointAlreadyExistsException e)
                    {
                        Logger.Log(e.Message);
                        continue;
                    }
                    finally
                    {
                        Logger.CumulativeOperationEnd("Partial env actions");
                    }
                }

                Logger.CumulativeOperationStart("Pre last env actions");

                Sandbox         preLastEnv             = null;
                AVehicle[]      nearInteractors        = null;
                List <AVehicle> currentVehicles        = null;
                AVehicle[]      preLastEnvVehiclesCopy = null;

                if (partialEnv != null)
                {
                    currentVehicles = startEnv.GetVehicles(true, group);
                    var currentVehiclesCenter = Utility.BoundingRect(currentVehicles).Center;
                    nearInteractors = partialEnv.Vehicles
                                      .Where(x =>
                                             !x.IsMy && x.GetDistanceTo2(currentVehiclesCenter) < Geom.Sqr(2 * G.TacticalNuclearStrikeRadius) ||
                                             x.IsMy && x.IsAerial == Utility.IsAerial(group.VehicleType) && x.GetDistanceTo2(currentVehiclesCenter) < Geom.Sqr(G.TacticalNuclearStrikeRadius))
                                      .ToArray();

                    preLastEnv = new Sandbox(
                        partialEnv.Vehicles.Concat(currentVehicles),
                        new ANuclear[] { },
                        new AFacility[] { },
                        clone: true
                        );
                    preLastEnvVehiclesCopy = preLastEnv.Vehicles.Select(x => new AVehicle(x)).ToArray();
                }

                Logger.CumulativeOperationEnd("Pre last env actions");

                Func <AMove, double> checkAction = move =>
                {
                    Logger.CumulativeOperationStart("Building nearby environment");
                    Sandbox env;

                    if (partialEnv == null)
                    {
                        env = startEnv.Clone();
                    }
                    else
                    {
                        env = new Sandbox(nearInteractors.Concat(currentVehicles),
                                          startEnv.Nuclears, partialEnv.Facilities, clone: true);
                    }

                    env.CheckCollisionsWithOpponent = false;
                    env.UseFightOptimization        = false;

                    if (partialEnv != null)
                    {
                        foreach (var veh in env.Vehicles)
                        {
                            if (veh.IsGroup(group))
                            {
                                continue;
                            }

                            veh.ForgotTarget();            // чтобы не шли повторно
                            veh.CanChargeFacility = false; // чтобы не захватывали повторно
                            // TODO: лечение

                            if (veh.RemainingAttackCooldownTicks > 0) // у тех, кто стрелял давно, откатываем кд
                            {
                                veh.RemainingAttackCooldownTicks += ticksCount;
                            }
                            // TODO: если кд только восстановилось
                        }
                    }
                    Logger.CumulativeOperationEnd("Building nearby environment");

                    Logger.CumulativeOperationStart("End of simulation");
                    env.ApplyMove(move);
                    try
                    {
                        env.DoTicksApprox(ticksCount,
                                          moveApprox: move.Action == ActionType.Move || move.Action == ActionType.Rotate,
                                          fightApprox: true);
                    }
                    catch (QuadTree <AVehicle> .PointAlreadyExistsException e)
                    {
                        Logger.Log(e.Message);
                        return(double.PositiveInfinity);
                    }
                    finally
                    {
                        Logger.CumulativeOperationEnd("End of simulation");
                    }

                    Logger.CumulativeOperationStart("Building last environment");
                    var cache = sumMaxAlmostAttacksCache;
                    if (partialEnv != null)
                    {
                        var tmp = env;
                        env = preLastEnv;

                        for (var i = 0; i < env.Vehicles.Length; i++)
                        {
                            var veh = env.Vehicles[i];
                            if (tmp.VehicleById.ContainsKey(veh.Id))
                            {
                                env.UpdateVehicle(veh, tmp.VehicleById[veh.Id]);
                            }
                            else
                            {
                                env.UpdateVehicle(veh, preLastEnvVehiclesCopy[i]);
                            }
                        }

                        env.Nuclears   = tmp.Nuclears;
                        env.Facilities = tmp.Facilities;
                        cache         += GetSumMaxAlmostAttacks(env, env.GetVehicles(true, group));
                    }

                    var myGroups   = GroupsManager.MyGroups.AsEnumerable();
                    var myUngroups = MyUngroupedClusters.AsEnumerable();
                    if (newGroupVehicles != null)
                    {
                        myGroups   = myGroups.ConcatSingle(group);
                        myUngroups = myUngroups.Where(cl => !cl.Equals(newGroupVehicles));
                    }

                    if (env.Vehicles.Length != Environment.Vehicles.Length)
                    {
                        throw new Exception("Final sandbox size mismatch");
                    }
                    Logger.CumulativeOperationEnd("Building last environment");


                    var danger = GetDanger(Environment, env, myGroups.ToList(), myUngroups.ToList(), cache);

                    if (move.Action == ActionType.Move)
                    {
                        visualVectorsStart.Add(typeRect.Center);
                        visualVectorsDir.Add(new Point(move.X, move.Y).Normalized());
                        visualVectorsScore.Add(danger.Score);
                    }

                    if (selDanger == null || danger.Score < selDanger.Score)
                    {
                        selDanger = danger;
                        selMoves  = selectionMoves.Concat(new[]
                        {
                            move,
                            newGroupVehicles == null
                                ? null
                                : AMovePresets.AssignGroup(group.Group)
                        })
                                    .Where(x => x != null)
                                    .ToArray();
                        selGroup = group;
                    }
                    return(danger.Score);
                };

                var typeRectCenter = typeRect.Center;
                var simpleMode     = Environment.Nuclears.Length == 0 && (
                    Environment.OppVehicles.Count == 0 ||
                    Environment.OppVehicles.Min(x => x.GetDistanceTo2(typeRectCenter)) > Geom.Sqr(120));

                var moveMaxSpeed = _isSlowMode && Utility.IsAerial(group.VehicleType) ? G.MaxSpeed[(int)group.VehicleType] * 0.6 : 0;

                Func <int, AMove> idxToMove = idx => AMovePresets.Move(
                    Point.ByAngle(2 * Math.PI / 12 * idx)
                    * startEnv.MyVehicles.Where(x => x.IsSelected).Max(x => x.ActualSpeed)
                    * ticksCount * 40,
                    group.Group == GroupsManager.StartingTanksGroupId && Const.MixArrvsWithGrounds
                        ? Math.Min(G.MaxSpeed[(int)VehicleType.Tank], G.MaxSpeed[(int)VehicleType.Arrv])
                        : group.Group == GroupsManager.StartingIfvsGroupId && Const.MixArrvsWithGrounds
                            ? Math.Min(G.MaxSpeed[(int)VehicleType.Ifv], G.MaxSpeed[(int)VehicleType.Arrv])
                            : moveMaxSpeed
                    );


                double[] dangers;
                if (simpleMode)
                {
                    // проверка на каждые 3 часа
                    dangers = Enumerable.Range(0, 4).Select(i => checkAction(idxToMove(i * 3))).ToArray();
                }
                else
                {
                    // проверка на каждые 2 часа
                    dangers = Enumerable.Range(0, 6).Select(i => checkAction(idxToMove(i * 2))).ToArray();

                    // проверка на середины лучших промежутков
                    var dangers2 = dangers.Select((x, i) => new Tuple <double, int>(x, i)).OrderBy(x => x.Item1).Select(x => x.Item2).Take(2).ToArray();
                    foreach (var i in dangers2.Select(i => i * 2 + 1).Concat(dangers2.Select(i => i * 2 - 1)).Distinct())
                    {
                        checkAction(idxToMove(i));
                    }
                }

                foreach (var move in
                         Environment.Nuclears
                         .Where(n =>
                                n.GetDistanceTo(Utility.Average(startEnv.MyVehicles.Where(x => x.IsSelected))) <
                                G.TacticalNuclearStrikeRadius * 2)
                         .SelectMany(nuclear => new[]
                {
                    AMovePresets.Scale(nuclear, 1.5),
                    AMovePresets.Scale(nuclear, 3.0),
                    Environment.VehicleById.ContainsKey(nuclear.VehicleId) ? AMovePresets.Scale((Environment.VehicleById[nuclear.VehicleId] + nuclear) / 2, 2.0) : null,
                }))
                {
                    if (move != null)
                    {
                        checkAction(move);
                    }
                }

                checkAction(AMovePresets.Scale(typeRect.Center, 0.1));
                if (_doMainLastUnscale.ContainsKey(group.Group))
                {
                    var prevScaleMove = _doMainLastUnscale[group.Group].Item2;
                    checkAction(AMovePresets.Scale(prevScaleMove.Point, 1 / prevScaleMove.Factor));
                }
                checkAction(AMovePresets.Rotate(typeRect.Center, Math.PI / 4));
                checkAction(AMovePresets.Rotate(typeRect.Center, -Math.PI / 4));

                List <Point> positiveInteractors = new List <Point>(), negativeInteractors = new List <Point>();
                foreach (var cluster in OppClusters)
                {
                    foreach (var oppType in Const.AllTypes)
                    {
                        if (cluster.CountByType[(int)oppType] > 0)
                        {
                            var avg = Utility.Average(cluster.VehicleType(oppType));
                            if (G.AttackDamage[(int)group.VehicleType, (int)oppType] > 0)
                            {
                                positiveInteractors.Add(avg);
                            }
                            else if (G.AttackDamage[(int)oppType, (int)group.VehicleType] > 0)
                            {
                                negativeInteractors.Add(avg);
                            }
                        }
                    }
                }

                foreach (var move in
                         positiveInteractors.OrderBy(cen => cen.GetDistanceTo2(typeRect.Center))
                         .Take(2)
                         .Select(cen => AMovePresets.MoveTo(typeRect.Center, cen, moveMaxSpeed)))
                {
                    checkAction(move);
                }

                foreach (var move in
                         negativeInteractors.OrderBy(cen => cen.GetDistanceTo2(typeRect.Center))
                         .Take(1)
                         .Select(cen => AMovePresets.Move((typeRect.Center - cen).Take(150), moveMaxSpeed)))
                {
                    checkAction(move);
                }

                if (targetFacilities.ContainsKey(group.Group))
                {
                    checkAction(AMovePresets.MoveTo(typeRect.Center, targetFacilities[group.Group], moveMaxSpeed));
                }

                // проверка действия "ничего не делать"
                if (selectionMoves.Count == 0)
                {
                    checkAction(new AMove());
                }

                // полет к ближайшему Arrv
                if (group.VehicleType == VehicleType.Helicopter || group.VehicleType == VehicleType.Fighter)
                {
                    var arrvGroupsCenters = GroupsManager.MyGroups
                                            .Where(g => g.VehicleType == VehicleType.Arrv)
                                            .Select(g => Utility.BoundingRect(Environment.GetVehicles(true, g)).Center)
                                            .ToArray();
                    if (arrvGroupsCenters.Length > 0)
                    {
                        checkAction(AMovePresets.MoveTo(typeRect.Center,
                                                        arrvGroupsCenters.ArgMin(p => p.GetDistanceTo2(typeRect.Center)), moveMaxSpeed));
                    }
                }
            }

#if DEBUG
            //if (selDanger != null)
            //{
            //    var maxScore = visualVectorsScore.Max();
            //    var minScore = visualVectorsScore.Min();
            //    if (maxScore > minScore)
            //    {
            //        for (var i = 0; i < visualVectorsStart.Count; i++)
            //        {
            //            VisualSegments.Add(new object[]
            //            {
            //                new List<Point>
            //                {
            //                    visualVectorsStart[i],
            //                    visualVectorsStart[i] + visualVectorsDir[i]*((visualVectorsScore[i]-minScore)/(minScore-maxScore)*40)
            //                },
            //                new System.Drawing.Pen(System.Drawing.Color.Green),
            //                5
            //            });
            //        }
            //    }
            //}
#endif

            return(new Tuple <AMove[], MyGroup, DangerResult>(selMoves, selGroup, selDanger));
        }
Ejemplo n.º 7
0
        public static void Initialize()
        {
            var facilities = World.Facilities
                             .Select(x => new AFacility(x))
                             .OrderBy(x => x.Id)
                             .ToArray();

            if (TerrainType == null)
            {
                TerrainType = World.TerrainByCellXY;
                WeatherType = World.WeatherByCellXY;
                FacilityIdx = new int[TerrainType.Length][];
                for (var i = 0; i < TerrainType.Length; i++)
                {
                    FacilityIdx[i] = new int[TerrainType[i].Length];
                    for (var j = 0; j < TerrainType[i].Length; j++)
                    {
                        FacilityIdx[i][j] = -1;
                        for (var k = 0; k < facilities.Length; k++)
                        {
                            if (facilities[k].ContainsPoint(new Point((i + 0.5) * G.CellSize, (j + 0.5) * G.CellSize)))
                            {
                                FacilityIdx[i][j] = k;
                            }
                        }
                    }
                }
            }

            var nuclears = World.Players
                           .Where(player => player.NextNuclearStrikeVehicleId != -1)
                           .Select(player => new ANuclear(
                                       player.NextNuclearStrikeX,
                                       player.NextNuclearStrikeY,
                                       player.IsMe,
                                       player.NextNuclearStrikeVehicleId,
                                       player.NextNuclearStrikeTickIndex - World.TickIndex)
                                   )
                           .ToArray();

            Logger.CumulativeOperationStart("VO Update");
            VehiclesObserver.Update();
            Logger.CumulativeOperationEnd("VO Update");

            MoveObserver.Init();
            var prevEnv = Environment;

            Environment = new Sandbox(VehiclesObserver.VehicleById.Values, nuclears, facilities)
            {
                TickIndex = World.TickIndex
            };

            Logger.CumulativeOperationStart("VO Update2");
            VehiclesObserver.Update2(prevEnv, Environment);
            Logger.CumulativeOperationEnd("VO Update2");

            OppClusters = Clustering.GetClustersSimple(
                Environment.OppVehicles.Concat(VehiclesObserver.OppUncheckedVehicles.Values).ToArray(),
                Const.ClusteringMargin
                );

            if (!G.IsAerialButerDetected && World.TickIndex < 1500 && OppClusters.Count < 20)
            {
                foreach (var cl1 in OppClusters)
                {
                    if (cl1.CountByType[(int)VehicleType.Fighter] > 30)
                    {
                        foreach (var cl2 in OppClusters)
                        {
                            if (cl2.CountByType[(int)VehicleType.Helicopter] > 30)
                            {
                                var inter = cl1.BoundingRect.IntersectionWith(cl2.BoundingRect);
                                if (inter != null && inter.Area >= cl1.BoundingRect.Area * 0.7)
                                {
                                    G.IsAerialButerDetected = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            NewGroupMinSize = Math.Min(33, (int)(Environment.MyVehicles.Count * 44 / 500.0));

            var newVehicles = Environment.MyVehicles.Where(x => x.Groups == 0).ToArray();

            var ungroupedEnv = new Sandbox(
                newVehicles,
                new ANuclear[] { },
                new AFacility[] { },
                clone: true
                );

            MyUngroupedClusters = G.IsFacilitiesEnabled
                ? Clustering.GetClustersSimple(ungroupedEnv.MyVehicles.ToArray(), Const.ClusteringMargin * 2)
                : new List <VehiclesCluster>();
        }
Ejemplo n.º 8
0
        private Tuple <double, AMove> _nuclearFindMove(Sandbox env, double selTotalDamage, bool checkOnly)
        {
            AMove selMove = null;

            for (var s = 0; s < GroupsManager.MyGroups.Count + MyUngroupedClusters.Count; s++)
            {
                var vehicles = s < GroupsManager.MyGroups.Count
                    ? env.GetVehicles(true, GroupsManager.MyGroups[s])
                    : MyUngroupedClusters[s - GroupsManager.MyGroups.Count];
                var myAvg = Utility.Average(vehicles);

                var vrg = G.VisionRange[(int)VehicleType.Fighter] + G.MaxTacticalNuclearStrikeDamage;

                var oppGroups = OppClusters
                                .Where(cl =>
                                       cl.Avg.GetDistanceTo(myAvg) < vrg &&
                                       cl.Any(x => env.VehicleById.ContainsKey(x.Id)))// пропускать полностью фантомные группы
                                .OrderBy(cl => cl.Avg.GetDistanceTo(myAvg))
                                .Take(3)
                                .ToArray();

                foreach (var veh in vehicles)
                {
                    if (!veh.IsSelected && MoveObserver.AvailableActions < 3)
                    {
                        continue;
                    }
                    if (veh.IsSelected && MoveObserver.AvailableActions < 2)
                    {
                        continue;
                    }

                    var vr = veh.ActualVisionRange * 0.9;

                    foreach (
                        var oppGroup in
                        new[] { env.GetOpponentNeighbours(veh.X, veh.Y, vr + G.TacticalNuclearStrikeRadius) }.Concat(oppGroups))
                    {
                        ANuclear nuclear;
                        var      totalDamage = _nuclearGetDamage(veh, env, selTotalDamage, oppGroup, out nuclear);

                        if (totalDamage <= selTotalDamage)
                        {
                            continue;
                        }

                        var vehNextMove = new AVehicle(veh);
                        for (var t = 0; t < 3; t++)
                        {
                            vehNextMove.Move();
                        }
                        if (vehNextMove.GetDistanceTo2(nuclear) + Const.Eps >= Geom.Sqr(vehNextMove.ActualVisionRange))
                        {
                            continue;
                        }

                        const int n = 10;
                        if (vehicles.Count > n)
                        {
                            var myDist2        = veh.GetDistanceTo2(nuclear);
                            var myNearestCount = vehicles.Count(x => x.GetDistanceTo2(nuclear) <= myDist2);
                            if (myNearestCount < n)
                            {
                                continue;
                            }
                        }

                        selTotalDamage = totalDamage;
                        selMove        = new AMove
                        {
                            Action    = ActionType.TacticalNuclearStrike,
                            VehicleId = veh.Id,
                            Point     = nuclear,
                        };

                        if (checkOnly)
                        {
                            return(new Tuple <double, AMove>(selTotalDamage, selMove));
                        }
                    }
                }
            }

            if (selMove == null)
            {
                return(null);
            }

            return(new Tuple <double, AMove>(selTotalDamage, selMove));
        }
Ejemplo n.º 9
0
        public Sandbox Clone()
        {
            var clone = new Sandbox
            {
                CheckCollisionsWithOpponent = CheckCollisionsWithOpponent,
                UseFightOptimization        = UseFightOptimization,
                TickIndex = TickIndex,

                Nuclears   = Nuclears.Select(x => new ANuclear(x)).ToArray(),
                Facilities = Facilities.Select(x => new AFacility(x)).ToArray(),
                Vehicles   = new AVehicle[Vehicles.Length],
            };
            var ptr = 0;


            for (var i = 0; i < _myVehiclesByGroup.Count; i++)
            {
                clone._myVehiclesByGroup.Add(new List <AVehicle>(_myVehiclesByGroup[i].Count));
            }

            for (var isMy = 0; isMy < 2; isMy++)
            {
                clone._vehiclesByOwner[isMy].Capacity = _vehiclesByOwner[isMy].Count;
                for (var j = 0; j < 5; j++)
                {
                    clone._vehiclesByOwnerAndType[isMy][j].Capacity = _vehiclesByOwnerAndType[isMy][j].Count;
                }

                for (var isAerial = 0; isAerial < 2; isAerial++)
                {
                    IEnumerable <AVehicle> vehiclesClones;
                    clone._trees[isMy, isAerial] = _trees[isMy, isAerial];
                    if (clone._trees[isMy, isAerial] == null)
                    {
                        vehiclesClones = _vehiclesByOwner[isMy].Where(x => x.IsAerial == (isAerial == 1)).Select(_cloneVehicle);
                    }
                    else
                    {
                        var treeNodes = new List <AVehicle>();
                        clone._trees[isMy, isAerial] = clone._trees[isMy, isAerial].Clone(ref treeNodes);
                        vehiclesClones = treeNodes;
                    }
                    foreach (var veh in vehiclesClones)
                    {
                        clone.Vehicles[ptr++] = veh;

                        clone._vehiclesByOwner[isMy].Add(veh);
                        clone._vehiclesByOwnerAndType[isMy][(int)veh.Type].Add(veh);
                        clone.VehicleById[veh.Id] = veh;
                        if (veh.IsMy)
                        {
                            foreach (var g in veh.GroupsList)
                            {
                                clone._myVehiclesByGroup[g - 1].Add(veh);
                            }
                        }
                    }
                }
            }
            return(clone);
        }
Ejemplo n.º 10
0
        public static DangerResult GetDanger(Sandbox startEnv, Sandbox env, List <MyGroup> myGroups, List <VehiclesCluster> myUngroups, double sumMaxAlmostAttacksCache = -1)
        {
            ExpB = Math.Log(ExpY1 / ExpY2) / (ExpX2 - ExpX1);
            ExpA = ExpY1 / Math.Exp(-ExpB * ExpX1);

            Logger.CumulativeOperationStart("GetDanger");

            var result = new DangerResult();

            if (sumMaxAlmostAttacksCache <= -1)
            {
                result.SumMaxAlmostAttacks = GetSumMaxAlmostAttacks(env, env.MyVehicles);
            }
            else
            {
                result.SumMaxAlmostAttacks = sumMaxAlmostAttacksCache;
            }

            Logger.CumulativeOperationStart("Danger1");

            var myDurabilityBefore  = startEnv.MyVehicles.Sum(x => x.FullDurability);
            var oppDurabilityBefore = startEnv.OppVehicles.Sum(x => x.FullDurability);

            var myDurabilityAfter  = env.MyVehicles.Sum(x => x.FullDurability);
            var oppDurabilityAfter = env.OppVehicles.Sum(x => x.FullDurability);

            result.MyDurabilityDiff  = myDurabilityBefore - myDurabilityAfter;
            result.OppDurabilityDiff = oppDurabilityBefore - oppDurabilityAfter;

            result.MyDeadsCount  = env.MyVehicles.Count(x => !x.IsAlive);
            result.OppDeadsCount = env.OppVehicles.Count(x => !x.IsAlive);

            result.FacilitiesPointsDiff = startEnv.Facilities.Sum(x => x.CapturePoints) - env.Facilities.Sum(x => x.CapturePoints);

            // nuclears
            foreach (var nuclear in env.Nuclears)
            {
                foreach (var target in env.GetAllNeighbours(nuclear.X, nuclear.Y, nuclear.Radius))
                {
                    result.NuclearsPotentialDamage += Utility.TrueFactor(target.IsMy) * target.GetNuclearDamage(nuclear);
                }
            }

            // groups intersections
            var groupsIsAerial = myGroups.Select(g => Utility.IsAerial(g.VehicleType))
                                 .Concat(myUngroups.Select(cl => cl[0].IsAerial))
                                 .ToArray();
            var groupsRects = myGroups.Select(g => Utility.BoundingRect(env.GetVehicles(true, g)))
                              .Concat(myUngroups.Select(cl => cl.BoundingRect))
                              .ToArray();

            for (var j = 0; j < groupsRects.Length; j++)
            {
                var rect = groupsRects[j];
                if (rect.X < G.VehicleRadius || rect.Y < G.VehicleRadius || rect.X + G.VehicleRadius > G.MapSize || rect.Y + G.VehicleRadius > G.MapSize)
                {
                    result.RectanglesIntersects1++;
                    continue;
                }

                for (var i = 0; i < j; i++)
                {
                    if (groupsIsAerial[i] != groupsIsAerial[j])
                    {
                        continue;
                    }
                    var rect1 = groupsRects[i].Clone();
                    var rect2 = groupsRects[j].Clone();

                    rect1.ExtendRadius(G.VehicleRadius * 1.5);
                    rect2.ExtendRadius(G.VehicleRadius * 1.5);

                    if (rect1.IntersectsWith(rect2))
                    {
                        result.RectanglesIntersects1++;
                        continue;
                    }

                    rect1.ExtendRadius(G.VehicleRadius * 1.5);
                    rect2.ExtendRadius(G.VehicleRadius * 1.5);
                    if (rect1.IntersectsWith(rect2))
                    {
                        result.RectanglesIntersects2++;
                    }
                }
            }


            Logger.CumulativeOperationEnd("Danger1");

            var clusters = OppClusters; // NOTE: юниты врага считаются неподвижными, поэтому берем инстансы из основного Environment

            Logger.CumulativeOperationStart("Danger2");
            var groundGroupsCenters = new List <Point>();
            var groundGroups        = new List <List <AVehicle> >();
            var groundGroupsIdxes   = new List <int>();
            var groundGroupsId      = new List <MyGroup>();

            for (var s = 0; s < myGroups.Count + myUngroups.Count; s++)
            {
                VehicleType     type;
                MyGroup         gr = null;
                List <AVehicle> myGroup;
                if (s < myGroups.Count)
                {
                    gr      = myGroups[s];
                    type    = gr.VehicleType;
                    myGroup = env.GetVehicles(true, gr);
                }
                else
                {
                    myGroup = myUngroups[s - myGroups.Count];
                    type    = myGroup[0].Type;
                }
                var myGroupCenter = Utility.Average(myGroup);

                var list = new List <DangerResult.ScoreDistancePair>();

                var myRatio = 1.0 * myGroup.Count / env.MyVehicles.Count;

                foreach (var cl in clusters)
                {
                    for (var oppType = 0; oppType < 5; oppType++)
                    {
                        if (cl.CountByType[oppType] == 0)
                        {
                            continue;
                        }

                        var myAttack  = G.AttackDamage[(int)type, oppType];
                        var oppAttack = G.AttackDamage[oppType, (int)type];

                        var avg  = Utility.Average(cl.VehicleType((VehicleType)oppType));
                        var dist = avg.GetDistanceTo(myGroupCenter);

                        var score = myAttack - oppAttack * 0.49;
                        if (type == VehicleType.Helicopter && oppType == (int)VehicleType.Fighter)
                        {
                            score *= 2.5;
                        }
                        else if (type == VehicleType.Helicopter && oppType == (int)VehicleType.Arrv)
                        {
                            score *= 0.8;
                        }

                        var maxDurability   = cl.CountByType[oppType] * G.MaxDurability;
                        var durabilityCoeff = (maxDurability - cl.DurabilitySumByType[oppType]) / G.MaxDurability;
                        if (score < 0)
                        {
                            durabilityCoeff *= -1;
                        }
                        score = score * (cl.CountByType[oppType] + durabilityCoeff) * myRatio;

                        var e = -(myAttack == 0 && dist > 100 || myAttack <oppAttack && dist> (type == VehicleType.Helicopter ? 350 : 140)
                            ? 0
                            : DangerExp(dist));

                        list.Add(new DangerResult.ScoreDistancePair(score, e));
                    }
                }

                foreach (var helpGroup in myGroups)
                {
                    if (type == VehicleType.Helicopter && helpGroup.VehicleType == VehicleType.Ifv)
                    {
                        var fightersCount = env.GetVehicles(false, VehicleType.Fighter).Count;
                        if (fightersCount == 0)
                        {
                            continue;
                        }

                        var helpGroupVehicles       = env.GetVehicles(true, helpGroup);
                        var helpGroupVehiclesCenter = Utility.BoundingRect(helpGroupVehicles).Center;

                        var myAttack  = G.AttackDamage[(int)type, (int)VehicleType.Fighter];
                        var oppAttack = G.AttackDamage[(int)VehicleType.Fighter, (int)type];

                        var score = (myAttack - oppAttack * 0.49) * 2.5;
                        score = score * fightersCount * myRatio;
                        var          dist          = myGroupCenter.GetDistanceTo(helpGroupVehiclesCenter);
                        var          distToFighter = Math.Sqrt(env.GetVehicles(false, VehicleType.Fighter).Min(x => x.GetDistanceTo2(myGroupCenter)));
                        const double n             = 400;
                        var          coef          = Math.Max(0, (n - distToFighter) / n);

                        list.Add(new DangerResult.ScoreDistancePair(coef * score, DangerExp(dist)));
                    }

                    if ((type == VehicleType.Helicopter || type == VehicleType.Fighter) &&
                        helpGroup.VehicleType == VehicleType.Arrv)
                    {
                        var helpGroupVehicles       = env.GetVehicles(true, helpGroup);
                        var helpGroupVehiclesCenter = Utility.BoundingRect(helpGroupVehicles).Center;

                        var score = -(myGroup.Count * G.MaxDurability - myGroup.Sum(x => x.Durability)) * myRatio;
                        var dist  = myGroupCenter.GetDistanceTo(helpGroupVehiclesCenter);

                        list.Add(new DangerResult.ScoreDistancePair(score, DangerExp(dist)));
                    }
                }

                result.MoveToInfo.Add(new Tuple <MyGroup, int, List <DangerResult.ScoreDistancePair> >(gr, s, list));

                // scale groups
                var boundingRect = Utility.BoundingRect(myGroup);
                boundingRect.ExtendRadius(G.VehicleRadius);
                result.RectanglesAreas.Add(new Tuple <double, int>(boundingRect.Area, myGroup.Count));

                if (!Utility.IsAerial(type) && s < myGroups.Count)
                {
                    groundGroups.Add(myGroup);
                    groundGroupsCenters.Add(myGroupCenter);
                    groundGroupsId.Add(gr);
                    groundGroupsIdxes.Add(s);
                }
            }

            var targetFacilities = env.Facilities.Where(x => !x.IsMy).ToArray();

            if (groundGroups.Count > 0 && targetFacilities.Length > 0)
            {
                var mat = new double[groundGroups.Count][];
                for (var i = 0; i < groundGroups.Count; i++)
                {
                    mat[i] = new double[targetFacilities.Length];
                    for (var j = 0; j < targetFacilities.Length; j++)
                    {
                        mat[i][j] = groundGroupsCenters[i].GetDistanceTo(targetFacilities[j].Center);
                    }
                }
                var asg = HungarianAssignment.Minimize(mat, 2 * G.MapSize);
                for (var i = 0; i < groundGroups.Count; i++)
                {
                    var myGroup = groundGroups[i];
                    var cen     = groundGroupsCenters[i];
                    var myRatio = 1.0 * myGroup.Count / env.MyVehicles.Count;

                    var flist = new List <DangerResult.ScoreDistancePair>();

                    if (asg[i] == -1)
                    {
                        continue;
                    }
                    var facility = targetFacilities[asg[i]];

                    result.TargetFacility[groundGroupsId[i].Group] = facility.Center;

                    var dist  = cen.GetDistanceTo(facility.Center);
                    var score = -myRatio * (groundGroupsId[i].VehicleType == VehicleType.Arrv ? 4 : 1);
                    flist.Add(new DangerResult.ScoreDistancePair(score, DangerExp(dist)));

                    result.MoveToFacilitiesInfo.Add(new Tuple <MyGroup, int, List <DangerResult.ScoreDistancePair> >(groundGroupsId[i], groundGroupsIdxes[i], flist));
                }
            }

            Logger.CumulativeOperationEnd("Danger2");

            Logger.CumulativeOperationEnd("GetDanger");

            return(result);
        }