Example #1
0
File: ACar.cs Project: znsoft/AiCup
        public ACar(Car original)
        {
            X = original.X;
            Y = original.Y;

            Speed                       = new Point(original.SpeedX, original.SpeedY);
            Angle                       = original.Angle;
            EnginePower                 = original.EnginePower;
            WheelTurn                   = original.WheelTurn;
            AngularSpeed                = original.AngularSpeed;
            Original                    = original;
            OutOfMap                    = false;
            RemainingNitroTicks         = original.RemainingNitroTicks;
            RemainingNitroCooldownTicks = original.RemainingNitroCooldownTicks;
            RemainingInactiveTicks      = DurabilityObserver.ReactivationTime(original) - MyStrategy.world.Tick;

            Width  = original.Width;
            Height = original.Height;

            if (original.Type == CarType.Buggy)
            {
                _carAccelerationUp   = Const.Game.BuggyEngineForwardPower / original.Mass;
                _carAccelerationDown = Const.Game.BuggyEngineRearPower / original.Mass;
            }
            else
            {
                _carAccelerationUp   = Const.Game.JeepEngineForwardPower / original.Mass;
                _carAccelerationDown = Const.Game.JeepEngineRearPower / original.Mass;
            }
        }
Example #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);
        }
Example #3
0
        public bool CheckUseProjectile()
        {
            if (world.Tick < Const.Game.InitialFreezeDurationTicks)
            {
                return(false);
            }
            if (self.ProjectileCount == 0)
            {
                return(false);
            }
            if (self.RemainingProjectileCooldownTicks > 0)
            {
                return(false);
            }

            var projectiles = AProjectile.GetProjectiles(new ACar(self));

            var shot      = new bool[projectiles.Length];
            var shotSpeed = 0.0;

            var checkTicks = MagicConst.OpponentsTicksPrediction * (self.Type == CarType.Buggy ? 0.5 : 0.4);

            for (var t = 1; t < checkTicks; t++)
            {
                for (var prId = 0; prId < projectiles.Length; prId++)
                {
                    var pr = projectiles[prId];
                    if (!pr.Exists)
                    {
                        continue;
                    }

                    pr.Move();

                    for (var i = 0; i < All.Length; i++)
                    {
                        if (t >= All[i].Length)
                        {
                            continue;
                        }

                        var car = All[i][t];

                        /*
                         * Чужие машинки считать меньшими по размеру
                         * Свои - большими
                         */
                        if (pr.Intersect(car, car.Original.IsTeammate ? 5 : -(pr.Type == ProjectileType.Tire ? 40 : 5)))
                        {
                            if (pr.Type == ProjectileType.Tire)
                            {
                                // если это я только что выпустил шину
                                if (car.Original.Id == self.Id && Math.Abs(pr.Speed.Length - Const.Game.TireInitialSpeed) < Eps)
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                // если это я выпустил шайбу
                                if (car.Original.Id == self.Id)
                                {
                                    continue;
                                }
                            }

                            if (car.Original.IsTeammate) // попал в своего
                            {
                                return(false);
                            }

                            if (DurabilityObserver.ReactivationTime(car.Original) + 2 < world.Tick + t || DurabilityObserver.IsActive(car.Original))
                            {
                                // если он не мертв
                                shot[prId] = true;
                                if (pr.Type == ProjectileType.Tire)
                                {
                                    shotSpeed = pr.Speed.Length;
                                }
                            }
                            pr.Exists = false;
                        }
                    }
                }
            }
            var shotCount = shot.Count(val => val);

            if (self.Type == CarType.Buggy)
            {
                return(shotCount >= 3 || shotCount == 2 && self.ProjectileCount > 2);
            }
            return(shotCount == 1 &&
                   (shotSpeed >= Const.Game.TireInitialSpeed - Eps ||
                    shotSpeed >= Const.Game.TireInitialSpeed / 2.5 && self.ProjectileCount > 2));
        }
Example #4
0
        public static void Draw()
        {
            if (_form.InvokeRequired)
            {
                _form.BeginInvoke(new DrawDelegate(Draw), new object[] { });
                return;
            }

            _renderTick++;
            if ((_renderTick - 1) % _myCarsCount != _myCarsCount - 1)
            {
                return;
            }

            var panel = _form.panel;

            _form.tickLabel.Text = MyStrategy.world.Tick + "";

            var drawArea = new Bitmap(panel.Size.Width, panel.Size.Height);

            panel.Image = drawArea;
            _graphics   = Graphics.FromImage(drawArea);

            if (_myCarsCount == 1)
            {
                _form.jeepRadioButton.Enabled  = false;
                _form.buggyRadioButton.Enabled = false;
                LookUp(new Point(MyStrategy.world.Cars.FirstOrDefault(x => x.IsTeammate)));
            }
            else
            {
                LookUp(
                    new Point(
                        MyStrategy.world.Cars.FirstOrDefault(
                            x =>
                            x.IsTeammate &&
                            (x.Type == CarType.Jeep && _form.jeepRadioButton.Checked ||
                             x.Type == CarType.Buggy && _form.buggyRadioButton.Checked))));
            }

            //var myNextWp = MyStrategy.GetNextWayPoint(self);
            //FillRect(Brushes.Aqua, myNextWp.J * Const.TileSize, myNextWp.I * Const.TileSize, Const.TileSize, Const.TileSize);

            // tiles
            foreach (var tile in MyStrategy.MyTiles)
            {
                var margin = Const.TileMargin;
                var tsize  = Const.TileSize;

                var dx = Const.TileSize * tile.J;
                var dy = Const.TileSize * tile.I;

                if (tile.Type == TileType.Unknown)
                {
                    FillRect(Brushes.DarkGray, dx, dy, tsize, tsize);
                }
                if (tile.Type == TileType.Empty)
                {
                    FillRect(Brushes.Black, dx, dy, tsize, tsize);
                }

                if (!tile.IsFreeLeft)
                {
                    FillRect(Brushes.Black, dx, dy, margin, tsize);
                }
                if (!tile.IsFreeTop)
                {
                    FillRect(Brushes.Black, dx, dy, tsize, margin);
                }
                if (!tile.IsFreeRight)
                {
                    FillRect(Brushes.Black, dx + tsize - margin, dy, margin, tsize);
                }
                if (!tile.IsFreeBottom)
                {
                    FillRect(Brushes.Black, dx, dy + tsize - margin, tsize, margin);
                }

                foreach (var part in tile.Parts)
                {
                    switch (part.Type)
                    {
                    case TilePartType.Circle:
                        FillCircle(Brushes.Black, part.Circle.X, part.Circle.Y, part.Circle.Radius);
                        break;

                    case TilePartType.Segment:
                        DrawLine(Brushes.DarkRed, part.Start.X, part.Start.Y, part.End.X, part.End.Y, 1);
                        break;

                    default:
                        throw new Exception("Unknown TilePartType");
                    }
                }
            }

            // Bonuses
            foreach (var bonus in MyStrategy.world.Bonuses)
            {
                var rect = new ABonus(bonus).GetRect();
                for (var i = 0; i < 4; i++)
                {
                    Brush brush;
                    if (bonus.Type == BonusType.PureScore)
                    {
                        brush = Brushes.OrangeRed;
                    }
                    else if (bonus.Type == BonusType.RepairKit)
                    {
                        brush = Brushes.LimeGreen;
                    }
                    else if (bonus.Type == BonusType.OilCanister)
                    {
                        brush = Brushes.DarkSlateGray;
                    }
                    else if (bonus.Type == BonusType.NitroBoost)
                    {
                        brush = Brushes.Blue;
                    }
                    else if (bonus.Type == BonusType.AmmoCrate)
                    {
                        brush = Brushes.DarkGoldenrod;
                    }
                    else
                    {
                        throw new Exception("Unknown BonusType");
                    }

                    DrawLine(brush, rect[i].X, rect[i].Y, rect[(i + 1) % 4].X, rect[(i + 1) % 4].Y, 2);
                }
            }

            // Cars
            foreach (var car in MyStrategy.world.Cars)
            {
                var isAvtive = DurabilityObserver.IsActive(car);
                var rect     = new ACar(car).GetRectEx(isAvtive ? 0 : 1);
                for (var i = 0; i < 4; i++)
                {
                    DrawLine(car.IsTeammate ? Brushes.Green : Brushes.Red,
                             rect[i].X, rect[i].Y, rect[(i + 1) % 4].X, rect[(i + 1) % 4].Y,
                             isAvtive ? 2 : 1);
                }
                var to = Point.ByAngle(car.Angle) * 100 + new Point(car);
                DrawLine(Brushes.Black, car.X, car.Y, to.X, to.Y, car.Type == CarType.Buggy ? 2 : 6);
                DrawText("~" + car.ProjectileCount, 50, Brushes.Black, car.X, car.Y);
            }

            // Oil
            foreach (var stick in MyStrategy.world.OilSlicks)
            {
                FillCircle(Brushes.Black, stick.X, stick.Y, stick.Radius);
            }

            // Nitro
            foreach (var car in MyStrategy.world.Cars)
            {
                if (car.RemainingNitroTicks > 0)
                {
                    FillCircle(Brushes.Blue, car.X, car.Y, 40);
                }
            }



            // Canisters
            foreach (var car in MyStrategy.world.Cars)
            {
                if (car.OilCanisterCount == 0)
                {
                    continue;
                }
                var canisterPen = car.RemainingOilCooldownTicks == 0 ? Pens.DarkSlateGray : Pens.Lavender;
                var slick       = new AOilSlick(new ACar(car));
                DrawCircle(canisterPen, slick.X, slick.Y, slick.Radius);
                if (car.RemainingOiledTicks > 0)
                {
                    FillCircle(Brushes.Black, car.X, car.Y, 30);
                }
            }


            // Projectiles
            foreach (var pr in MyStrategy.world.Projectiles)
            {
                FillCircle(Brushes.OrangeRed, pr.X, pr.Y, pr.Radius);
            }

            // Segments
            try
            {
                foreach (var _el in SegmentsDrawQueue)
                {
                    var el    = _el as object[];
                    var brush = el[0] as Brush;
                    var line  = el[1] as Points;
                    var width = Convert.ToDouble(el[2]);
                    for (var i = 1; i < line.Count; i++)
                    {
                        DrawLine(brush, line[i - 1].X, line[i - 1].Y, line[i].X, line[i].Y, (float)width);
                    }
                }
            }
            catch (Exception)
            {
            }

            // Circles
            foreach (var el in CircleFillQueue)
            {
                var brush  = el.Item1;
                var circle = el.Item2;
                FillCircle(brush, circle.X, circle.Y, circle.Radius);
            }

            CircleFillQueue.Clear();
            SegmentsDrawQueue.Clear();
        }
Example #5
0
        void Initialize()
        {
            if (!Const.Initialized)
            {
                Const.Initialized = true;

                Const.TileSize   = Const.Game.TrackTileSize;
                Const.TileMargin = Const.Game.TrackTileMargin;

                Const.CarDiagonalHalfLength   = Geom.Gypot(Const.Game.CarWidth, Const.Game.CarHeight) / 2;
                Const.BonusDiagonalHalfLength = Geom.Gypot(Const.Game.BonusSize / 2 - MagicConst.BonusSafeMargin, Const.Game.BonusSize / 2 - MagicConst.BonusSafeMargin);

                Const.MapWidth  = Const.TileSize * world.Width;
                Const.MapHeight = Const.TileSize * world.Height;
            }

            Teammate = world.Cars.FirstOrDefault(car => car.IsTeammate && car.Id != self.Id);

            ComputedPath.Remove(self.Id);
            if (Teammate != null)
            {
                TeammateCar = ComputedPath.ContainsKey(Teammate.Id) ? ComputedPath[Teammate.Id] : null;
            }

            if (Players == null) // check for first call
            {
                MyTiles = new ATile[world.Height, world.Width];
                for (var i = 0; i < world.Height; i++)
                {
                    for (var j = 0; j < world.Width; j++)
                    {
                        MyTiles[i, j] = new ATile(i, j, TileType.Unknown);
                    }
                }
            }

            // intialize tiles
            var t = world.TilesXY;

            for (var i = 0; i < world.Height; i++)
            {
                for (var j = 0; j < world.Width; j++)
                {
                    if (MyTiles[i, j].Type == TileType.Unknown && t[j][i] != TileType.Unknown)
                    {
                        MyTiles[i, j] = new ATile(i, j, t[j][i]);
                    }

                    MyTiles[i, j].Weight = 0;
                }
            }

            // intialize waypoints
            var wp = world.Waypoints;

            Waypoints = new Cell[wp.Length];
            for (var i = 0; i < Waypoints.Length; i++)
            {
                Waypoints[i] = new Cell(wp[i][1], wp[i][0]);
            }

            Players = new Dictionary <long, Player>();
            foreach (var player in world.Players)
            {
                Players[player.Id] = player;
            }

            foreach (var car in world.Cars)
            {
                DurabilityObserver.Watch(car);
            }

            var tires = world.Projectiles.Where(x => x.Type == ProjectileType.Tire).ToArray();

            Tires = new AProjectile[tires.Length][];
#if DEBUG
            var trajectories = Tires.Select(x => new Points()).ToArray();
#endif
            for (var i = 0; i < tires.Length; i++)
            {
                Tires[i]    = new AProjectile[MagicConst.ProjectilePredictionTicks];
                Tires[i][0] = new AProjectile(tires[i]);
                for (var j = 1; j < MagicConst.ProjectilePredictionTicks; j++)
                {
                    Tires[i][j] = Tires[i][j - 1].Clone();
                    Tires[i][j].Move();
#if DEBUG
                    trajectories[i].Add(new Point(Tires[i][j]));
#endif
                }
            }
#if DEBUG
            foreach (var tr in trajectories)
            {
                Visualizer.SegmentsDrawQueue.Add(new object[] { Brushes.Indigo, tr, 0.0 });
            }
#endif

            Bonuses   = world.Bonuses.Select(b => new ABonus(b)).ToArray();
            OilSlicks = world.OilSlicks.Select(s => new AOilSlick(s)).ToArray();

            EnumerateNeigbours(GetCell(self), to =>
            {
                var center = GetCenter(to);
                MyTiles[to.I, to.J].Weight += Math.Abs(self.GetAngleTo(center.X, center.Y));
            });

            foreach (var bonus in Bonuses)
            {
                var cell = GetCell(bonus);
                MyTiles[cell.I, cell.J].AddBonus(bonus);
            }
            foreach (var slick in OilSlicks)
            {
                var cell = GetCell(slick);
                MyTiles[cell.I, cell.J].AddSlick(slick);
            }

            Opponents = world.Cars.Where(car => !car.IsTeammate && !car.IsFinishedTrack).ToArray();
            PrepareOpponentsPath();
            if (OpponentsCars != null)
            {
                Others = OpponentsCars
                         .Concat(TeammateCar == null ? new ACar[][] { } : new[] { TeammateCar })
                         .ToArray();
            }

            ComputedPath.Clear();
            if (self.TeammateIndex == 1 && OpponentsCars != null)
            {
                foreach (var opp in OpponentsCars)
                {
                    ComputedPath[opp[0].Original.Id] = opp;
                }
            }
        }
Example #6
0
        private void _move()
        {
            var pts = GetWaySegments(self);

            if (world.Tick > Const.Game.InitialFreezeDurationTicks)
            {
                PositionsHistory.Add(new Point(self));
            }

            if (!DurabilityObserver.IsActive(self))
            {
                return;
            }

            if (CheckBackMove(pts[1]))
            {
                return;
            }

            InitBrutes();

            if (world.Tick < Const.Game.InitialFreezeDurationTicks)
            {
                var nextCell   = DijkstraNextCell(GetCell(self), GetNextWayPoint(self), new Cell[] {});
                var nextCenter = GetCenter(nextCell);
                move.EnginePower = self.GetAngleTo(nextCenter.X, nextCenter.Y) < Math.PI / 2 ? 1 : -1;
                return;
            }

            if (BAD_TESTING_STRATEGY)
            {
                AlternativeMove(pts);
                return;
            }

            // если еду назад, то запускать только первый перебор
            // если маленькая скорость, то 1-й и 2-й
            var bruteRes =
                _doAndSelectBrute(
                    self.EnginePower < 0
                        ? new[] { Brutes[0] }
                        : (GetSpeed(self) < 5 ? new[] { Brutes[0], Brutes[1] } : Brutes), pts);

            var sel            = bruteRes.Item1;
            var bestMoveStacks = bruteRes.Item2;

            if (sel != -1 && bestMoveStacks[sel].Count > 0)
            {
                Brutes[sel].SelectThis();
                bestMoveStacks[sel][0].Apply(move, new ACar(self));
                ComputedPath[self.Id] = GetCarPath(self, bestMoveStacks[sel]);
#if DEBUG
                Visualizer.DrawWays(self, bestMoveStacks, sel);
#endif
            }
            else
            {
                TimerStart();
                AlternativeMove(pts);
                TimerEndLog("AlternativeMove", 30);
            }
        }