예제 #1
0
        void AlternativeMove(Points pts)
        {
            var car = new ACar(self);

            var backBruteRes = _doAndSelectBrute(BackBrutes, pts);

            if (backBruteRes.Item1 != -1)
            {
                BackBrutes[backBruteRes.Item1].SelectThis();
                var mv = backBruteRes.Item2[backBruteRes.Item1];
                if (mv.Count > 0)
                {
                    mv[0].Apply(move, new ACar(self));
                    ComputedPath[self.Id] = GetCarPath(self, mv);
#if DEBUG
                    Visualizer.DrawWays(self, backBruteRes.Item2, backBruteRes.Item1);
#endif
                    return;
                }
            }

            // change points
            pts = GetAlternativeWaySegments(self);
            var turnCenter = pts[1];

            var tmp = new ACar(self);
            var aa  = tmp + tmp.Speed;
            if (Math.Abs(tmp.GetAngleTo(aa)) > Math.PI / 2)
            {
                move.EnginePower = 1;
                move.WheelTurn  *= -1;
                return;
            }


            move.EnginePower = 1.0;

            if (car.GetDistanceTo(turnCenter) < 1.6 * Const.TileSize)
            {
                move.EnginePower = 0.8;
            }

            if (car.GetDistanceTo(turnCenter) < 1.0 * Const.TileSize)
            {
                if (GetSpeed(self) > 11)
                {
                    move.IsBrake = true;
                }
            }
            move.WheelTurn = car.GetAngleTo(turnCenter);

            if (BAD_TESTING_STRATEGY)
            {
                if (turnCenter.GetDistanceTo(self) >= 7 * Const.TileSize &&
                    Math.Abs(car.GetAngleTo(turnCenter)) < Math.PI / 6)
                {
                    move.IsUseNitro = true;
                }
            }
        }
예제 #2
0
        public Moves Do(ACar car, Points pts)
        {
            // Проверка что данный путь был выбран
            if (_selectThisTick + 1 != MyStrategy.world.Tick)
            {
                _lastSuccessStack = null;
            }

            Self = car.Clone();

            if (_lastCall == LastSuccess)
            {
                LastSuccess = _lastCall;
            }

            for (var t = 0; t < MyStrategy.world.Tick - _lastCall && _lastSuccessStack != null && _lastSuccessStack.Count > 0; t++)
            {
                _lastSuccessStack[0].Times--;
                _lastSuccessStack.Normalize();
            }
            if (_lastSuccessStack != null && (_lastSuccessStack.Count == 0 || _useDist2 && _lastSuccessStack.ComputeTime() < 30))
            {
                _lastSuccessStack = null;
            }

            _lastCall = MyStrategy.world.Tick;

            /*
             * Количество бонусов на расстоянии 0.5t
             * Если изменилось - пересчитывать сильно
             */
            var bonusesCount05 = MyStrategy.Bonuses
                                 .Count(bonus => Self.GetDistanceTo(bonus) < Const.TileSize / 2);

            /*
             * Количество бонусов на расстоянии 2t
             * Если изменилось - чуть нужно пересчитать
             */
            var bonusesCount2 = MyStrategy.Bonuses
                                .Count(
                bonus =>
                Self.GetDistanceTo(bonus) < Const.TileSize * 2 &&
                MyStrategy.CellDistance(Self, bonus) <= 2);

            // Если был success на прошлом тике, то продолжаем. Или каждые _interval тиков.
            if (Const.Game.InitialFreezeDurationTicks < MyStrategy.world.Tick &&
                bonusesCount05 == _bonusesCount05 &&
                LastSuccess < MyStrategy.world.Tick - 1 &&
                (MyStrategy.world.Tick - (LastSuccess + 1)) % _interval != 0)
            {
                _validateLastSuccessStack();
                return(_lastSuccessStack);
            }

            /*
             * Смотрим на шины, которые на расстоянии не более 6 тайлов
             */
            var prevProj = _projCandidates;

            _projCandidates = MyStrategy.Tires
                              .Where(
                proj =>
                Self.GetDistanceTo(proj[0]) <= Const.TileSize * 6 &&
                MyStrategy.CellDistance(Self, proj[0]) <= 6)
                              .ToArray();

            var extended = MyStrategy.ExtendWaySegments(pts, 50);

            _bruteWayPoints = extended.GetRange(0, Math.Min(_waypointsCount, extended.Count)).ToArray();
            if (LastStageMove.IsUseNitro && _turnsCount(_bruteWayPoints) > 1)
            {
                return(null);
            }
#if DEBUG
            var bruteWayPoints = new Points();
            bruteWayPoints.AddRange(_bruteWayPoints);
            Visualizer.SegmentsDrawQueue.Add(new object[] { Brushes.Brown, bruteWayPoints, 0.0 });
#endif
            _needDist  = Const.TileSize * 0.5 - 3;
            _needDist2 = Const.TileSize - 3;
            _turnTo    = _bruteWayPoints[_bruteWayPoints.Length - 1];
            _turnTo2   = _bruteWayPoints[Math.Min(_bruteWayPoints.Length - 1, (int)(_bruteWayPoints.Length * 0.83))];
#if DEBUG
            Visualizer.CircleFillQueue.Add(new Tuple <Brush, ACircularUnit>(Brushes.OrangeRed, new ACircularUnit {
                X = _turnTo.X, Y = _turnTo.Y, Radius = 20
            }));
            Visualizer.CircleFillQueue.Add(new Tuple <Brush, ACircularUnit>(Brushes.Orange, new ACircularUnit {
                X = _turnTo2.X, Y = _turnTo2.Y, Radius = 20
            }));
#endif

            _patterns = Patterns.Select(pt => new PathPattern
            {
                From = pt.From,
                To   = pt.To,
                Step = pt.Step,
                Move = pt.Move.Clone()
            }).ToArray();
            foreach (var p in _patterns)
            {
                if (p.Move.WheelTurn is TurnPattern)
                {
                    var turnPattern = p.Move.WheelTurn as TurnPattern;
                    if (turnPattern.Pattern == TurnPatternType.ToNext)
                    {
                        p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? -1 : 1;
                    }
                    else if (turnPattern.Pattern == TurnPatternType.FromNext)
                    {
                        p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? 1 : -1;
                    }
                }
            }

            _movesStack     = new Moves();
            _bestMovesStack = new Moves();
            _bestTime       = MyStrategy.Infinity;
            _bestImportance = 0;

            /*
             * Смотрим на бонусы, которые на расстоянии не более 4t
             * TODO: уменьшить приоритет бонусов, которые может быть возьмет другой (в.т.ч тиммейт)
             */
            _bonusCandidates = MyStrategy.Bonuses
                               .Where(
                bonus =>
                MyStrategy.world.Tick > 270 &&         // Не смотреть на бонусы при старте!!!
                Self.GetDistanceTo(bonus) <= Const.TileSize * 4 &&
                MyStrategy.CellDistance(Self, bonus) <= 4
                )
                               .ToArray();


            /*
             * Смотрим на лужи, которые на расстоянии не более 5 тайлов
             */
            var prevSlicks = _slickCandidates;
            _slickCandidates = MyStrategy.OilSlicks
                               .Where(
                slick =>
                Self.GetDistanceTo(slick) <= Const.TileSize * 5 &&
                MyStrategy.CellDistance(Self, slick) <= 5
                )
                               .ToArray();

            /*
             * Пытаться объехать тех, которые
             * - Крашнулись
             * - Убиты
             * - Двигатель меньше чем на 0.5 мощности
             * - Двигаются по встречной
             *
             * - Если у меня нитро, или будет нитро
             *
             * - Своих
             */
            var prevCars = _carCandidates;
            _carCandidates = MyStrategy.Others
                             .Where(opp => opp[0].GetDistanceTo(Self) < Const.TileSize * 9)
                             .Where(
                opp =>
                opp[0].Original.IsTeammate ||
                MyStrategy.IsCrashed(opp[0].Original) ||
                !DurabilityObserver.IsActive(opp[0].Original) ||
                opp[0].EnginePower < 0.5 ||
                Self.RemainingNitroTicks > 0 ||
                Math.Abs(Geom.GetAngleBetween(Self.Speed, opp[0].Speed)) > Math.PI / 2
                )
                             .Where(opp => MyStrategy.CellDistance(Self, opp[0]) <= 9) // 9 - потому что он может ехать по встречке
                             .ToArray();


            if (_cache != null)
            {
                for (var k = 0; k < _patterns.Length; k++)
                {
                    var range = (prevSlicks == null || prevCars == null || prevProj == null ||
                                 _bonusesCount2 != bonusesCount2 ||
                                 prevSlicks.Length != _slickCandidates.Length ||
                                 prevCars.Length != _carCandidates.Length ||
                                 prevProj.Length != _projCandidates.Length)
                        ? (k == 0 ? 6 : 4)
                        : (k == 0 ? 6 : 2);

                    if (_bonusesCount05 != bonusesCount05 || Special && k == 0)
                    {
                        range = 10;
                    }

                    _patterns[k].From = Math.Max(0, _cache[k].Times - range);
                    _patterns[k].To   = Math.Min(_patterns[k].To * 9 / 7, _cache[k].Times + range);
                    _patterns[k].Step = 2;
                }
            }

            _bonusesCount05 = bonusesCount05;
            _bonusesCount2  = bonusesCount2;

            var wayPointRequired = false;
            for (var i = _bruteWayPoints.Length - 1; i >= 0; i--)
            {
                if (_bruteWayPoints[i].GetDistanceTo2(_turnTo) < _needDist * _needDist)
                {
                    for (var j = 0; j < i; j++)
                    {
                        wayPointRequired |=
                            MyStrategy.GetNextWayPoint(Self.Original).Equals(MyStrategy.GetCell(_bruteWayPoints[j]));
                    }
                    break;
                }
            }

            _doRecursive(Self, 0, new PassedInfo {
                WayPoint = !wayPointRequired
            });
            _cache = null;
            if (_bestTime == MyStrategy.Infinity)
            {
                return(_lastSuccessStack);
            }

            if (_bestMovesStack.ComputeTime() != _bestTime)
            {
                throw new Exception("ComputeTime != BestTime");
            }

            LastSuccess = MyStrategy.world.Tick;
            _cache      = _bestMovesStack.Clone();

            if (_maxTicksInfo == null)
            {
                _maxTicksInfo = new int[_bestMovesStack.Count];
            }
            for (var i = 0; i < _maxTicksInfo.Length; i++)
            {
                _maxTicksInfo[i] = Math.Max(_maxTicksInfo[i], _bestMovesStack[i].Times);
            }

            _bestMovesStack.Normalize();
            _lastSuccessStack = _bestMovesStack.Clone();
            return(_bestMovesStack);
        }
예제 #3
0
        public Moves Do(ACar car, Points pts)
        {
            // Проверка что данный путь был выбран
            if (_selectThisTick + 1 != MyStrategy.world.Tick)
                _lastSuccessStack = null;

            Self = car.Clone();

            if (_lastCall == LastSuccess)
                LastSuccess = _lastCall;

            for (var t = 0; t < MyStrategy.world.Tick - _lastCall && _lastSuccessStack != null && _lastSuccessStack.Count > 0; t++)
            {
                _lastSuccessStack[0].Times--;
                _lastSuccessStack.Normalize();
            }
            if (_lastSuccessStack != null && (_lastSuccessStack.Count == 0 || _useDist2 && _lastSuccessStack.ComputeTime() < 30))
                _lastSuccessStack = null;

            _lastCall = MyStrategy.world.Tick;

            /*
             * Количество бонусов на расстоянии 0.5t
             * Если изменилось - пересчитывать сильно
             */
            var bonusesCount05 = MyStrategy.Bonuses
                .Count(bonus => Self.GetDistanceTo(bonus) < Const.TileSize / 2);

            /*
             * Количество бонусов на расстоянии 2t
             * Если изменилось - чуть нужно пересчитать
             */
            var bonusesCount2 = MyStrategy.Bonuses
                .Count(
                    bonus =>
                        Self.GetDistanceTo(bonus) < Const.TileSize*2 &&
                        MyStrategy.CellDistance(Self, bonus) <= 2);

            // Если был success на прошлом тике, то продолжаем. Или каждые _interval тиков.
            if (Const.Game.InitialFreezeDurationTicks < MyStrategy.world.Tick &&
                bonusesCount05 == _bonusesCount05 &&
                LastSuccess < MyStrategy.world.Tick - 1 &&
                (MyStrategy.world.Tick - (LastSuccess + 1))%_interval != 0)
            {
                _validateLastSuccessStack();
                return _lastSuccessStack;
            }

            /*
             * Смотрим на шины, которые на расстоянии не более 6 тайлов
             */
            var prevProj = _projCandidates;
            _projCandidates = MyStrategy.Tires
                .Where(
                    proj =>
                        Self.GetDistanceTo(proj[0]) <= Const.TileSize * 6 &&
                        MyStrategy.CellDistance(Self, proj[0]) <= 6)
                .ToArray();

            var extended = MyStrategy.ExtendWaySegments(pts, 50);
            _bruteWayPoints = extended.GetRange(0, Math.Min(_waypointsCount, extended.Count)).ToArray();
            if (LastStageMove.IsUseNitro && _turnsCount(_bruteWayPoints) > 1)
                return null;
            #if DEBUG
            var bruteWayPoints = new Points();
            bruteWayPoints.AddRange(_bruteWayPoints);
            Visualizer.SegmentsDrawQueue.Add(new object[]{ Brushes.Brown, bruteWayPoints, 0.0 });
            #endif
            _needDist = Const.TileSize*0.5 - 3;
            _needDist2 = Const.TileSize - 3;
            _turnTo = _bruteWayPoints[_bruteWayPoints.Length - 1];
            _turnTo2 = _bruteWayPoints[Math.Min(_bruteWayPoints.Length - 1, (int)(_bruteWayPoints.Length * 0.83))];
            #if DEBUG
            Visualizer.CircleFillQueue.Add(new Tuple<Brush, ACircularUnit>(Brushes.OrangeRed, new ACircularUnit { X = _turnTo.X, Y = _turnTo.Y, Radius = 20}));
            Visualizer.CircleFillQueue.Add(new Tuple<Brush, ACircularUnit>(Brushes.Orange, new ACircularUnit { X = _turnTo2.X, Y = _turnTo2.Y, Radius = 20 }));
            #endif

            _patterns = Patterns.Select(pt => new PathPattern
            {
                From = pt.From,
                To = pt.To,
                Step = pt.Step,
                Move = pt.Move.Clone()
            }).ToArray();
            foreach (var p in _patterns)
            {
                if (p.Move.WheelTurn is TurnPattern)
                {
                    var turnPattern = p.Move.WheelTurn as TurnPattern;
                    if (turnPattern.Pattern == TurnPatternType.ToNext)
                        p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? -1 : 1;
                    else if (turnPattern.Pattern == TurnPatternType.FromNext)
                        p.Move.WheelTurn = Self.GetAngleTo(_turnTo) < 0 ? 1 : -1;
                }
            }

            _movesStack = new Moves();
            _bestMovesStack = new Moves();
            _bestTime = MyStrategy.Infinity;
            _bestImportance = 0;

            /*
             * Смотрим на бонусы, которые на расстоянии не более 4t
             * TODO: уменьшить приоритет бонусов, которые может быть возьмет другой (в.т.ч тиммейт)
             */
            _bonusCandidates = MyStrategy.Bonuses
                .Where(
                    bonus =>
                        MyStrategy.world.Tick > 270 && // Не смотреть на бонусы при старте!!!
                        Self.GetDistanceTo(bonus) <= Const.TileSize * 4 &&
                        MyStrategy.CellDistance(Self, bonus) <= 4
                )
                .ToArray();

            /*
             * Смотрим на лужи, которые на расстоянии не более 5 тайлов
             */
            var prevSlicks = _slickCandidates;
            _slickCandidates = MyStrategy.OilSlicks
                .Where(
                    slick =>
                        Self.GetDistanceTo(slick) <= Const.TileSize*5 &&
                        MyStrategy.CellDistance(Self, slick) <= 5
                )
                .ToArray();

            /*
             * Пытаться объехать тех, которые
             * - Крашнулись
             * - Убиты
             * - Двигатель меньше чем на 0.5 мощности
             * - Двигаются по встречной
             *
             * - Если у меня нитро, или будет нитро
             *
             * - Своих
             */
            var prevCars = _carCandidates;
            _carCandidates = MyStrategy.Others
                .Where(opp => opp[0].GetDistanceTo(Self) < Const.TileSize*9)
                .Where(
                    opp =>
                        opp[0].Original.IsTeammate ||
                        MyStrategy.IsCrashed(opp[0].Original) ||
                        !DurabilityObserver.IsActive(opp[0].Original) ||
                        opp[0].EnginePower < 0.5 ||
                        Self.RemainingNitroTicks > 0 ||
                        Math.Abs(Geom.GetAngleBetween(Self.Speed, opp[0].Speed)) > Math.PI / 2
                )
                .Where(opp => MyStrategy.CellDistance(Self, opp[0]) <= 9) // 9 - потому что он может ехать по встречке
                .ToArray();

            if (_cache != null)
            {
                for (var k = 0; k < _patterns.Length; k++)
                {
                    var range = (prevSlicks == null || prevCars == null || prevProj == null
                        || _bonusesCount2 != bonusesCount2
                        || prevSlicks.Length != _slickCandidates.Length
                        || prevCars.Length != _carCandidates.Length
                        || prevProj.Length != _projCandidates.Length)
                        ? (k == 0 ? 6 : 4)
                        : (k == 0 ? 6 : 2);

                    if (_bonusesCount05 != bonusesCount05 || Special && k == 0)
                        range = 10;

                    _patterns[k].From = Math.Max(0, _cache[k].Times - range);
                    _patterns[k].To = Math.Min(_patterns[k].To * 9 / 7, _cache[k].Times + range);
                    _patterns[k].Step = 2;
                }
            }

            _bonusesCount05 = bonusesCount05;
            _bonusesCount2 = bonusesCount2;

            var wayPointRequired = false;
            for(var i = _bruteWayPoints.Length - 1; i >= 0; i--)
            {
                if (_bruteWayPoints[i].GetDistanceTo2(_turnTo) < _needDist*_needDist)
                {
                    for (var j = 0; j < i; j++)
                        wayPointRequired |=
                            MyStrategy.GetNextWayPoint(Self.Original).Equals(MyStrategy.GetCell(_bruteWayPoints[j]));
                    break;
                }
            }

            _doRecursive(Self, 0, new PassedInfo { WayPoint = !wayPointRequired });
            _cache = null;
            if (_bestTime == MyStrategy.Infinity)
                return _lastSuccessStack;

            if (_bestMovesStack.ComputeTime() != _bestTime)
                throw new Exception("ComputeTime != BestTime");

            LastSuccess = MyStrategy.world.Tick;
            _cache = _bestMovesStack.Clone();

            if (_maxTicksInfo == null)
                _maxTicksInfo = new int[_bestMovesStack.Count];
            for (var i = 0; i < _maxTicksInfo.Length; i++)
                _maxTicksInfo[i] = Math.Max(_maxTicksInfo[i], _bestMovesStack[i].Times);

            _bestMovesStack.Normalize();
            _lastSuccessStack = _bestMovesStack.Clone();
            return _bestMovesStack;
        }
예제 #4
0
        void AlternativeMove(Points pts)
        {
            var car = new ACar(self);

            var backBruteRes = _doAndSelectBrute(BackBrutes, pts);

            if (backBruteRes.Item1 != -1)
            {
                BackBrutes[backBruteRes.Item1].SelectThis();
                var mv = backBruteRes.Item2[backBruteRes.Item1];
                if (mv.Count > 0)
                {
                    mv[0].Apply(move, new ACar(self));
                    ComputedPath[self.Id] = GetCarPath(self, mv);
            #if DEBUG
                    Visualizer.DrawWays(self, backBruteRes.Item2, backBruteRes.Item1);
            #endif
                    return;
                }
            }

            // change points
            pts = GetAlternativeWaySegments(self);
            var turnCenter = pts[1];

            var tmp = new ACar(self);
            var aa = tmp + tmp.Speed;
            if (Math.Abs(tmp.GetAngleTo(aa)) > Math.PI / 2)
            {
                move.EnginePower = 1;
                move.WheelTurn *= -1;
                return;
            }

            move.EnginePower = 1.0;

            if (car.GetDistanceTo(turnCenter) < 1.6 * Const.TileSize)
            {
                move.EnginePower = 0.8;
            }

            if (car.GetDistanceTo(turnCenter) < 1.0 * Const.TileSize)
            {
                if (GetSpeed(self) > 11)
                    move.IsBrake = true;
            }
            move.WheelTurn = car.GetAngleTo(turnCenter);

            if (BAD_TESTING_STRATEGY)
            {
                if (turnCenter.GetDistanceTo(self) >= 7*Const.TileSize &&
                    Math.Abs(car.GetAngleTo(turnCenter)) < Math.PI/6)
                {
                    move.IsUseNitro = true;
                }
            }
        }