コード例 #1
0
        /// <summary>
        /// Пока примитивная логика, не стартуем если враги есть рядом
        /// </summary>
        /// <param name="facility"></param>
        /// <param name="createdUnassignedUnits"></param>
        /// <returns></returns>
        private static bool CanStartProduction(FacilityEx facility, MyLivingUnit[] createdUnassignedUnits)
        {
            var isProductionTickExceed = GlobalHelper.Game.TickCount - GlobalHelper.World.TickIndex <
                                         ConfigurationHelper.StopProductionWhenTicksToEndGameRemaining;

            //var testStopProduction = (GlobalHelper.World.TickIndex / 1000) % 2 == 1;

            //Остановим производство, если слишком много юнитов
            //Для варианта с туманом, если их больше n
            //Для варианта без тумана, если количество превышает кол-во врага в n раз
            var isUnitsTooMuch = (GlobalHelper.Mode == GameMode.FacFow
                                     ? UnitHelper.UnitsAlly.Length > 750
                                     : UnitHelper.UnitsAlly.Length - UnitHelper.UnitsEnemy.Length > 300) &&
                                 GlobalHelper.World.TickIndex > 10000;

            var clusters = MyStrategy.LazyClusters.Value;

            var facilityX = facility.Left + GlobalHelper.Game.FacilityWidth / 2;
            var facilityY = facility.Top + GlobalHelper.Game.FacilityHeight / 2;

            var isEnemyNear = clusters.Any(cluster =>
            {
                var clusterUnitsX = cluster.Sum(x => x.X) / cluster.Count;
                var clusterUnitsY = cluster.Sum(x => x.Y) / cluster.Count;

                var isInRange =
                    GeometryHelper.GetDistancePower2To(facilityX, facilityY, clusterUnitsX, clusterUnitsY)
                    <= ConfigurationHelper.EnemyNearOurFacilityWarningLostRangePow2;

                return(isInRange);
            });

            var result = !isProductionTickExceed && !isUnitsTooMuch && !isEnemyNear;

            return(result);
        }
コード例 #2
0
        public static HasTargetToNuclearAttackResult HasTargetToNuclearAttack(MyLivingUnit[] selectedUnits)
        {
            var allEnemiesCanBeAttacked = new Dictionary <long, List <MyLivingUnit> >();

            foreach (var selectedUnit in selectedUnits)
            {
                var enemyUnitsInRange = UnitHelper.UnitsEnemy
                                        .Where(x =>
                {
                    var visionRange = GetVisionRangeByWeather(selectedUnit);
                    return(GeometryHelper.PointIsWithinCircle(selectedUnit.X, selectedUnit.Y, visionRange, x.X, x.Y));
                }).ToArray();

                foreach (var enemyUnitInRange in enemyUnitsInRange)
                {
                    var enemyId = enemyUnitInRange.Id;

                    if (!allEnemiesCanBeAttacked.ContainsKey(enemyId))
                    {
                        allEnemiesCanBeAttacked[enemyId] = new List <MyLivingUnit>();
                    }

                    allEnemiesCanBeAttacked[enemyId].Add(selectedUnit);
                }
            }

            if (allEnemiesCanBeAttacked.Count == 0)
            {
                return(new HasTargetToNuclearAttackResult()
                {
                    Success = false
                });
            }

            var enemiesCanBeAttacked = allEnemiesCanBeAttacked.Select(x => UnitHelper.Units[x.Key]).ToList();
            var nsRange     = GlobalHelper.Game.TacticalNuclearStrikeRadius;
            var maxNsDamage = GlobalHelper.Game.MaxTacticalNuclearStrikeDamage;

            var enemiesWithDamage = new List <Tuple <MyLivingUnit, double> >(allEnemiesCanBeAttacked.Count);

            var minEnemiesToAttack = GetMinEnemiesToAttackNuclearStrike();

            foreach (var enemyCanBeAttacked in enemiesCanBeAttacked)
            {
                var allEnemiesFromEnemyRange = UnitHelper.UnitsEnemy
                                               .Where(x => GeometryHelper.PointIsWithinCircle(enemyCanBeAttacked.X, enemyCanBeAttacked.Y,
                                                                                              nsRange, x.X, x.Y)).ToArray();

                if (allEnemiesFromEnemyRange.Length < minEnemiesToAttack)
                {
                    continue;
                }

                double totalDamage = 0;

                foreach (var enemyFromEnemyRange in allEnemiesFromEnemyRange)
                {
                    var distance = PotentialFieldsHelper.GetDistanceTo(enemyCanBeAttacked.X, enemyCanBeAttacked.Y,
                                                                       enemyFromEnemyRange.X, enemyFromEnemyRange.Y);

                    //Урон - это расстояние от эпиценра * урон
                    var damage = ((nsRange - distance) / nsRange) * maxNsDamage;

                    var speedDamageCoef = GetDamageCoefficientByVehicleTypeSpeed(enemyFromEnemyRange.Type);

                    damage *= speedDamageCoef;

                    if (damage > enemyFromEnemyRange.Durability)
                    {
                        totalDamage += maxNsDamage;
                    }
                    else
                    {
                        totalDamage += damage;
                    }
                }

                var allAlliesFromEnemyRange = UnitHelper.UnitsAlly
                                              .Where(x => GeometryHelper.PointIsWithinCircle(enemyCanBeAttacked.X, enemyCanBeAttacked.Y,
                                                                                             nsRange, x.X, x.Y)).ToArray();

                foreach (var allyFromEnemyRange in allAlliesFromEnemyRange)
                {
                    var distance = PotentialFieldsHelper.GetDistanceTo(enemyCanBeAttacked.X, enemyCanBeAttacked.Y,
                                                                       allyFromEnemyRange.X, allyFromEnemyRange.Y);

                    //Урон - это расстояние от эпиценра * урон
                    var damage = ((nsRange - distance) / nsRange) * maxNsDamage;

                    if (damage > allyFromEnemyRange.Durability)
                    {
                        totalDamage -= 100;
                    }
                    else
                    {
                        totalDamage -= damage;
                    }
                }

                enemiesWithDamage.Add(new Tuple <MyLivingUnit, double>(enemyCanBeAttacked, totalDamage));
            }

            if (enemiesWithDamage.Count == 0)
            {
                return(new HasTargetToNuclearAttackResult()
                {
                    Success = false
                });
            }

            var maxTotalDamage = enemiesWithDamage.Select(x => x.Item2).Max();

            //Выгода по урону не в пользу нас, не планируем удар
            if (maxTotalDamage < 0)
            {
                return(new HasTargetToNuclearAttackResult()
                {
                    Success = false
                });
            }

            var enemyUnitWithMaxDamage = enemiesWithDamage.First(x => Math.Abs(x.Item2 - maxTotalDamage) < 0.00000001).Item1;

#if DEBUG
            RewindClient.RewindClient.Instance.Circle(enemyUnitWithMaxDamage.X, enemyUnitWithMaxDamage.Y, enemyUnitWithMaxDamage.Radius * 3, Color.Red);
#endif

            var alliesCanAttackEnemyWithMaxDamage = allEnemiesCanBeAttacked[enemyUnitWithMaxDamage.Id];
            var alliesWithRange = alliesCanAttackEnemyWithMaxDamage.Select(x => new
            {
                Ally  = x,
                Range = GeometryHelper.GetDistancePower2To(x.X, x.Y, enemyUnitWithMaxDamage.X,
                                                           enemyUnitWithMaxDamage.Y)
            }).ToList();

            var maxRange = alliesWithRange.Select(x => x.Range).Max();
            var ally     = alliesWithRange.First(x => Math.Abs(x.Range - maxRange) < 0.00000001).Ally;

#if DEBUG
            RewindClient.RewindClient.Instance.Circle(ally.X, ally.Y, ally.Radius * 3, Color.Purple);

            var vr = GetVisionRangeByWeather(ally);
            RewindClient.RewindClient.Instance.Circle(ally.X, ally.Y, vr, Color.FromArgb(100, 255, 0, 200));
#endif

            return(new HasTargetToNuclearAttackResult()
            {
                Success = true,
                SelectedUnitRes = ally,
                EnemyRes = enemyUnitWithMaxDamage
            });
        }
コード例 #3
0
        public static void UpdateFacilitiesStates()
        {
            var facilityWidth  = GlobalHelper.Game.FacilityWidth;
            var facilityHeight = GlobalHelper.Game.FacilityHeight;

            var worldFacilities = GlobalHelper.World.Facilities;

            foreach (var worldFacility in worldFacilities)
            {
                if (!FacilityHelper.Facilities.ContainsKey(worldFacility.Id))
                {
                    FacilityHelper.Facilities.Add(worldFacility.Id, new FacilityEx());
                }

                var side = Side.Neutral;
                if (worldFacility.OwnerPlayerId == GlobalHelper.Me.Id)
                {
                    side = Side.Our;
                }
                else if (worldFacility.OwnerPlayerId == GlobalHelper.Enemy.Id)
                {
                    side = Side.Enemy;
                }

                var facility = FacilityHelper.Facilities[worldFacility.Id];

                var gotMineThisTick  = facility.Side != Side.Our && side == Side.Our;
                var lostMineThisTick = facility.Side == Side.Our && side != Side.Our;

                facility.Id = worldFacility.Id;
                //facility.OwnerPlayerId = worldFacility.OwnerPlayerId;
                facility.VehicleType        = worldFacility.VehicleType;
                facility.ProductionProgress = worldFacility.ProductionProgress;
                facility.Type             = worldFacility.Type;
                facility.CapturePoints    = worldFacility.CapturePoints;
                facility.Left             = worldFacility.Left;
                facility.Top              = worldFacility.Top;
                facility.Side             = side;
                facility.GotMineThisTick  = gotMineThisTick;
                facility.LostMineThisTick = lostMineThisTick;

                if (facility.Type == FacilityType.VehicleFactory)
                {
                    var createdUnassignedUnits = facility.GetCreatedUnassignedUnits();
                    var needStopProduction     = NeedStopProduction(facility, createdUnassignedUnits);
                    var canStartProduction     = CanStartProduction(facility, createdUnassignedUnits);

                    //Если захватили здание
                    if (gotMineThisTick)
                    {
                        //И можно стартовать производствао
                        if (canStartProduction)
                        {
                            facility.ProductionInProgress = true;
                            QueueHelper.Queue.Enqueue(new StartProduction(facility));
                        }
                        else
                        {
                            facility.ProductionInProgress = false;
                        }
                    }
                    //Если производство было остановлено и можно запускать заного
                    else if (!facility.ProductionInProgress && canStartProduction && facility.Side == Side.Our)
                    {
                        facility.ProductionInProgress = true;
                        QueueHelper.Queue.Enqueue(new StartProduction(facility));
                    }
                    else
                    {
                        var needCreateGroupFromProducingUnits =
                            lostMineThisTick ||
                            (facility.ProductionCount > 0 && createdUnassignedUnits.Length >= facility.ProductionCount);

                        if (needCreateGroupFromProducingUnits)
                        {
                            if (!facility.FacilityGroupCreating)
                            {
                                facility.FacilityGroupCreating = true;
                                QueueHelper.Queue.Enqueue(new SelectUnits(facility.Left, facility.Top,
                                                                          facility.Left + facilityWidth, facility.Top + facilityHeight,
                                                                          facility.LastAssignedVehicleType));

                                var vehicleType = facility.LastAssignedVehicleType ?? VehicleType.Tank;

                                QueueHelper.Queue.Enqueue(new AddSelecteUnitsToNewGroupTask(vehicleType));

                                if (needStopProduction)
                                {
                                    facility.ProductionInProgress = false;
                                    QueueHelper.Queue.Enqueue(new StopProduction(facility));
                                }
                                else if (canStartProduction)
                                {
                                    facility.ProductionInProgress = true;
                                    QueueHelper.Queue.Enqueue(new StartProduction(facility));
                                }
                            }
                        }
                        else if (needStopProduction && facility.Side == Side.Our && facility.ProductionInProgress)
                        {
                            if (createdUnassignedUnits.Length > 0)
                            {
                                QueueHelper.Queue.Enqueue(new SelectUnits(facility.Left, facility.Top,
                                                                          facility.Left + facilityWidth, facility.Top + facilityHeight,
                                                                          facility.LastAssignedVehicleType));

                                var vehicleType = facility.LastAssignedVehicleType ?? VehicleType.Tank;

                                QueueHelper.Queue.Enqueue(new AddSelecteUnitsToNewGroupTask(vehicleType));
                            }

                            facility.ProductionInProgress = false;
                            QueueHelper.Queue.Enqueue(new StopProduction(facility));
                        }
                    }
                }
            }

            if (GlobalHelper.Mode == GameMode.FacFow)
            {
                foreach (var myGroup in GroupHelper.Groups)
                {
                    var groupUnits = UnitHelper.UnitsAlly.Where(x => x.Groups.Contains(myGroup.Id)).ToArray();
                    var xCenter    = groupUnits.Sum(x => x.X) / groupUnits.Length;
                    var yCenter    = groupUnits.Sum(x => x.Y) / groupUnits.Length;

                    foreach (var facility in FacilityHelper.Facilities.Values)
                    {
                        if (facility.Side == Side.Our)
                        {
                            facility.LastVisitedTick = GlobalHelper.World.TickIndex;
                        }
                        else
                        {
                            var fx = facility.Left + GlobalHelper.Game.FacilityWidth / 2;
                            var fy = facility.Top + GlobalHelper.Game.FacilityHeight / 2;

                            var currentDistance     = GeometryHelper.GetDistancePower2To(xCenter, yCenter, fx, fy);
                            var recheckDistancePow2 = ConfigurationHelper.RecheckFacilityDistansePow2;

                            if (currentDistance <= recheckDistancePow2)
                            {
                                facility.LastVisitedTick = GlobalHelper.World.TickIndex;
                            }
                        }
                    }
                }
            }
        }
コード例 #4
0
        private static bool NeedStopProduction(FacilityEx facility, MyLivingUnit[] createdUnassignedUnits)
        {
            var isProductionTickExceed = GlobalHelper.Game.TickCount - GlobalHelper.World.TickIndex <
                                         ConfigurationHelper.StopProductionWhenTicksToEndGameRemaining;

            //var testStopProduction = (GlobalHelper.World.TickIndex / 1000) % 2 == 1;

            //Остановим производство, если слишком много юнитов
            //Для варианта с туманом, если их больше n
            //Для варианта без тумана, если количество превышает кол-во врага в n раз
            var isUnitsTooMuch = (GlobalHelper.Mode == GameMode.FacFow
                                     ? UnitHelper.UnitsAlly.Length > 750
                                     : UnitHelper.UnitsAlly.Length - UnitHelper.UnitsEnemy.Length > 300) &&
                                 GlobalHelper.World.TickIndex > 10000;

            var clusters = MyStrategy.LazyClusters.Value;
            //var res = BattleHelper.CalculatePower(enemies, currentSelectedGroup.VehicleType, basePower);
            var isEnemyCanBeatProducingGroupTooClose = false;

            if (facility.Side == Side.Our && clusters.Count > 0 && createdUnassignedUnits.Length > 0)
            {
                var vehicleType = createdUnassignedUnits[0].Type;

                var basePower = PotentialFieldsHelper.EnemyPowerToDodge;

                var facilityUnitsX = createdUnassignedUnits.Sum(x => x.X) / createdUnassignedUnits.Length;
                var facilityUnitsY = createdUnassignedUnits.Sum(x => x.Y) / createdUnassignedUnits.Length;

                isEnemyCanBeatProducingGroupTooClose = clusters.Any(cluster =>
                {
                    var clusterUnitsX = cluster.Sum(x => x.X) / cluster.Count;
                    var clusterUnitsY = cluster.Sum(x => x.Y) / cluster.Count;

                    var isInRange =
                        GeometryHelper.GetDistancePower2To(facilityUnitsX, facilityUnitsY, clusterUnitsX, clusterUnitsY)
                        <= ConfigurationHelper.EnemyNearOurFacilityWarningRangePow2;

                    if (!isInRange)
                    {
                        return(false);
                    }

                    var res = BattleHelper.CalculatePower(cluster, vehicleType, PotentialFieldsHelper.EnemyPowerToDodge);

                    var enemyPower       = res.EnemyPower;
                    var canAttackSomeone = res.CanAttackSomeone;

                    var existGroupPower =
                        createdUnassignedUnits.Sum(y => BattleHelper.GetPowerHealthMulitplier(y.Type, y.Durability)) *
                        basePower;

                    bool needStayOnFacility;

                    //Если строящаяся группа сильнее или чуть чуть слабее, то не уходим
                    if (existGroupPower * 1.2 > enemyPower)
                    {
                        needStayOnFacility = true;
                        //needStayOnFacility = canAttackSomeone;
                    }
                    else
                    {
                        //Если у врага нулевая сила, никуда не уходим
                        needStayOnFacility = (Math.Abs(enemyPower) < PotentialFieldsHelper.Epsilon);
                    }

                    return(!needStayOnFacility);
                });
            }

            var result = isProductionTickExceed || isUnitsTooMuch || isEnemyCanBeatProducingGroupTooClose /*|| testStopProduction*/;

            if (result)
            {
                var a = 0;
            }

            return(result);
        }
コード例 #5
0
        public static void AppendEnemyPower(List <List <DbScanHelper.Point> > clusters, bool applyNuclearStrikePower)
        {
            var basePower = EnemyPowerToDodge;

            var currentSelectedGroup = GroupHelper.CurrentGroup;

            //Хак по задержке вертов при старте, тянемся к ифвам
            if (currentSelectedGroup.VehicleType == VehicleType.Helicopter && GlobalHelper.World.TickIndex < 800)
            {
                var ifvGroup = GroupHelper.Groups.FirstOrDefault(x => x.VehicleType == VehicleType.Ifv);
                if (ifvGroup != null)
                {
                    var ifvUnits = UnitHelper.UnitsAlly.Where(x => x.Groups.Contains(ifvGroup.Id)).ToArray();
                    var ifvX     = ifvUnits.Sum(x => x.X) / ifvUnits.Length;
                    var ifvY     = ifvUnits.Sum(x => x.Y) / ifvUnits.Length;

                    var eCellX = (int)ifvX / PpSize;
                    var eCellY = (int)ifvY / PpSize;

                    ApplyPower(PotentialFields, eCellX, eCellY, RangePowerMask49, -(float)ifvUnits.Length * basePower / 2);

                    return;
                }
            }

            var selectedUnits = UnitHelper.UnitsAlly.Where(x => x.Groups.Contains(GroupHelper.CurrentGroup.Id)).ToArray();
            var myGroupPower  = selectedUnits
                                .Sum(x => BattleHelper.GetPowerHealthMulitplier(currentSelectedGroup.VehicleType, x.Durability))
                                * basePower;

            var minEnemiesToAttack = NuclearStrikeHelper.GetMinEnemiesToAttackNuclearStrike();

            foreach (var enemies in clusters)
            {
                var ex     = enemies.Sum(x => x.X) / enemies.Count;
                var ey     = enemies.Sum(x => x.Y) / enemies.Count;
                var eCellX = (int)ex / PpSize;
                var eCellY = (int)ey / PpSize;

                var res = BattleHelper.CalculatePower(enemies, currentSelectedGroup.VehicleType, basePower);

                var enemyPower       = res.EnemyPower;
                var canAttackSomeone = res.CanAttackSomeone;

                //Если готовы нанести ядерный удар
                if (applyNuclearStrikePower)
                {
                    //И врагов в кластере достаточно для удара, сделаем врагов притягиваемыми
                    if (enemies.Count >= minEnemiesToAttack)
                    {
                        ApplyPower(PotentialFields, eCellX, eCellY, RangePowerMask49, -enemyPower);
                    }
                }
                else
                {
                    if (canAttackSomeone)
                    {
                        var pwr = enemyPower - myGroupPower;
                        if (pwr >= 0)
                        {
                            //Если атакуют вертов, попробуем укрыться за Ifv
                            if (currentSelectedGroup.VehicleType == VehicleType.Helicopter &&
                                enemies.Any(x => x.Type == VehicleType.Fighter) &&
                                pwr > 0)
                            {
                                var sx = selectedUnits.Sum(x => x.X) / selectedUnits.Length;
                                var sy = selectedUnits.Sum(x => x.Y) / selectedUnits.Length;

                                var distanceLow = GeometryHelper.GetDistancePower2To(sx, sy, ex, ey) < (300 * 300);

                                if (distanceLow)
                                {
                                    var ifvGroup = GroupHelper.Groups.FirstOrDefault(x => x.VehicleType == VehicleType.Ifv);
                                    if (ifvGroup != null)
                                    {
                                        var ifvUnits = UnitHelper.UnitsAlly.Where(x => x.Groups.Contains(ifvGroup.Id)).ToArray();
                                        var ifvX     = ifvUnits.Sum(x => x.X) / ifvUnits.Length;
                                        var ifvY     = ifvUnits.Sum(x => x.Y) / ifvUnits.Length;

                                        var ifvCellX = (int)ifvX / PpSize;
                                        var ifvCellY = (int)ifvY / PpSize;

                                        ApplyPower(PotentialFields, ifvCellX, ifvCellY, RangePowerMask49, -(float)ifvUnits.Length * basePower);
                                    }
                                }
                            }

                            ApplyPower(PotentialFields, eCellX, eCellY, RangePowerMask7, pwr);
                        }
                        else
                        {
                            ApplyPower(PotentialFields, eCellX, eCellY, RangePowerMask49, pwr);
                        }
                    }
                    else
                    {
                        ApplyPower(PotentialFields, eCellX, eCellY, RangePowerMask7, enemyPower);
                    }
                }
            }
        }