예제 #1
0
        public StrategicDecision RunAway_FreeWay(TurnState turnState, Ship ship, StrategicDecision prevDecision)
        {
            var finalCoords = new List <int>();

            foreach (var enemyShip in turnState.enemyShips)
            {
                var move = FastShipPosition.Move(enemyShip.fposition, ShipMoveCommand.Faster);
                move = FastShipPosition.Move(FastShipPosition.GetFinalPosition(move), ShipMoveCommand.Faster);
                move = FastShipPosition.Move(FastShipPosition.GetFinalPosition(move), ShipMoveCommand.Faster);
                var finalCoord = FastShipPosition.Coord(FastShipPosition.GetFinalPosition(move));
                finalCoords.Add(finalCoord);
            }

            var candidates = runTargets.OrderByDescending(t => (int)finalCoords.Average(fc => FastCoord.Distance(t, fc) * FastCoord.Distance(t, fc))).Take(3).ToArray();

            var runTarget = candidates.OrderBy(
                t =>
            {
                var cost = 0;
                foreach (var enemyShip in turnState.enemyShips)
                {
                    cost += WayEvaluator.CalcCost(ship.fcoord, t, enemyShip.fcoord);
                }
                return(cost);
            }).First();

            return(new StrategicDecision {
                role = StrategicRole.RunAway, targetCoord = runTarget
            });
        }
        public CollectableBarrel FindNearestBarrelToCollect(TurnState turnState, Ship ship, HashSet <int> used = null)
        {
            var barrelsHitTurns = new Dictionary <int, int>();

            foreach (var barrel in turnState.barrels)
            {
                foreach (var cannonball in turnState.cannonballs)
                {
                    if (cannonball.fcoord == barrel.fcoord)
                    {
                        int prevTurns;
                        if (!barrelsHitTurns.TryGetValue(barrel.id, out prevTurns) || prevTurns > cannonball.turns)
                        {
                            barrelsHitTurns[barrel.id] = cannonball.turns;
                        }
                    }
                }
            }

            var    nextShipPosition1 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship.fposition, ShipMoveCommand.Faster));
            var    nextShipPosition2 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship.fposition, ShipMoveCommand.Wait));
            var    bestDist          = int.MaxValue;
            Barrel bestBarrel        = null;

            foreach (var barrel in turnState.barrels)
            {
                if (used == null || !used.Contains(barrel.id))
                {
                    var dist = FastShipPosition.DistanceTo(nextShipPosition1, barrel.fcoord);
                    if (dist < bestDist)
                    {
                        var enemyTravelTime = dist / 2 + 1;
                        int hitTurns;
                        if (barrelsHitTurns.TryGetValue(barrel.id, out hitTurns) && hitTurns <= enemyTravelTime)
                        {
                            continue;
                        }
                        bestBarrel = barrel;
                        bestDist   = dist;
                    }
                    dist = FastShipPosition.DistanceTo(nextShipPosition2, barrel.fcoord);
                    if (dist < bestDist)
                    {
                        var enemyTravelTime = dist / 2 + 1;
                        int hitTurns;
                        if (barrelsHitTurns.TryGetValue(barrel.id, out hitTurns) && hitTurns <= enemyTravelTime)
                        {
                            continue;
                        }
                        bestBarrel = barrel;
                        bestDist   = dist;
                    }
                }
            }
            return(bestBarrel == null ? null : new CollectableBarrel {
                barrel = bestBarrel, dist = bestDist
            });
        }
        public void ApplyPath(Ship ship, List <PathItem> path)
        {
            var index     = ship.index;
            var movedShip = ship.fposition;

            for (var i = 0; i < path.Count; i++)
            {
                var pathItem = path[i];
                GetTurnForecast(i).myShipsSourcePositions[index] = pathItem.sourcePosition;
                GetTurnForecast(i).myShipsPositions[index]       = pathItem.targetPosition;
                GetTurnForecast(i).myShipsMoveCommands[index]    = pathItem.command;
                movedShip = pathItem.targetPosition;
            }
            for (var i = path.Count; i < Settings.NAVIGATION_PATH_DEPTH; i++)
            {
                movedShip = FastShipPosition.GetFinalPosition(FastShipPosition.Move(movedShip, ShipMoveCommand.Wait));
                GetTurnForecast(i).myShipsPositions[index] = movedShip;
            }
        }
        public StrategicDecision MakeStrategicDecision(TurnState turnState, StrategicDecision prevDecision, Ship ship, Ship enemyShip)
        {
            var barrels = CollectableBarrels(turnState, enemyShip);

            var nextShipPosition1 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship.fposition, ShipMoveCommand.Faster));
            var nextShipPosition2 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship.fposition, ShipMoveCommand.Wait));

            var target = barrels.FirstOrDefault(
                b => FastShipPosition.DistanceTo(nextShipPosition1, b.barrel.fcoord) < b.dist - 1 ||
                FastShipPosition.DistanceTo(nextShipPosition2, b.barrel.fcoord) < b.dist - 1);

            if (target == null)
            {
                return(strateg.RunAway(turnState, ship, prevDecision));
            }

            var barrelToFire = barrels.TakeWhile(b => b != target).LastOrDefault();

            return(strateg.Collect(target.barrel).FireTo(barrelToFire?.barrel.fcoord));
        }
        private void BuildMyShipsForecast(TurnState turnState)
        {
            var prevPositions = new int[turnState.myShips.Count];

            for (var i = 0; i < turnState.myShips.Count; i++)
            {
                prevPositions[i] = turnState.myShips[i].fposition;
            }
            for (int depth = 0; depth < Settings.NAVIGATION_PATH_DEPTH; depth++)
            {
                turnForecasts[depth].myShipsSourcePositions = prevPositions;
                var commands = new ShipMoveCommand[prevPositions.Length];
                turnForecasts[depth].myShipsMoveCommands = commands;
                var nextPositions = new int[prevPositions.Length];
                for (var i = 0; i < prevPositions.Length; i++)
                {
                    var position = prevPositions[i];
                    var movement = FastShipPosition.Move(position, ShipMoveCommand.Wait);
                    nextPositions[i] = FastShipPosition.GetFinalPosition(movement);
                }
                prevPositions = turnForecasts[depth].myShipsPositions = nextPositions;
            }
        }
        private void BuildEnemyShipsForecast(TurnState turnState)
        {
            var prevPositions = new int[turnState.enemyShips.Count];

            for (var i = 0; i < turnState.enemyShips.Count; i++)
            {
                prevPositions[i] = turnState.enemyShips[i].fposition;
            }

            for (var depth = 0; depth < Settings.NAVIGATION_PATH_DEPTH; depth++)
            {
                var nextMovedPositions = new int[prevPositions.Length];
                var nextFinalPositions = new int[prevPositions.Length];
                for (var i = 0; i < prevPositions.Length; i++)
                {
                    var position = prevPositions[i];
                    var movement = FastShipPosition.Move(position, ShipMoveCommand.Wait);
                    nextMovedPositions[i] = FastShipPosition.GetMovedPosition(movement);
                    nextFinalPositions[i] = FastShipPosition.GetFinalPosition(movement);
                }
                turnForecasts[depth].enemyShipsMovedPositions = nextMovedPositions;
                prevPositions = turnForecasts[depth].enemyShipsFinalPositions = nextFinalPositions;
            }
        }
예제 #7
0
        public void CollectEnemyBarrels(TurnState turnState, Ship enemyShip1, Ship enemyShip2)
        {
            var barrels1 = strateg.strategy1vs1.CollectableBarrels(turnState, enemyShip1);
            var barrels2 = strateg.strategy1vs1.CollectableBarrels(turnState, enemyShip2);

            var ship1 = turnState.myShips[0];
            var ship2 = turnState.myShips[1];

            var nextShip1Position1 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship1.fposition, ShipMoveCommand.Faster));
            var nextShip1Position2 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship1.fposition, ShipMoveCommand.Wait));

            var nextShip2Position1 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship2.fposition, ShipMoveCommand.Faster));
            var nextShip2Position2 = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship2.fposition, ShipMoveCommand.Wait));

            var target1 = barrels1.FirstOrDefault(
                b => FastShipPosition.DistanceTo(nextShip1Position1, b.barrel.fcoord) < b.dist - 1 ||
                FastShipPosition.DistanceTo(nextShip1Position2, b.barrel.fcoord) < b.dist - 1);

            var target2 = barrels2.FirstOrDefault(
                b => FastShipPosition.DistanceTo(nextShip2Position1, b.barrel.fcoord) < b.dist - 1 ||
                FastShipPosition.DistanceTo(nextShip2Position2, b.barrel.fcoord) < b.dist - 1);

            while (true)
            {
                if (target1 == null)
                {
                    StrategicDecision decision;
                    strateg.decisions.TryGetValue(ship1.id, out decision);
                    strateg.decisions[ship1.id] = strateg.RunAway(turnState, ship1, decision);
                }

                if (target2 == null)
                {
                    StrategicDecision decision;
                    strateg.decisions.TryGetValue(ship2.id, out decision);
                    strateg.decisions[ship2.id] = strateg.RunAway(turnState, ship2, decision);
                }

                if (target1 == null && target2 == null)
                {
                    return;
                }

                if (target1 != null && target2 == null)
                {
                    var barrelToFire = barrels1.TakeWhile(b => b != target1).LastOrDefault();
                    strateg.decisions[ship1.id] = strateg.Collect(target1.barrel).FireTo(barrelToFire?.barrel.fcoord);
                    return;
                }

                if (target2 != null && target1 == null)
                {
                    var barrelToFire = barrels2.TakeWhile(b => b != target2).LastOrDefault();
                    strateg.decisions[ship2.id] = strateg.Collect(target2.barrel).FireTo(barrelToFire?.barrel.fcoord);
                    return;
                }

                if (target1.barrel != target2.barrel)
                {
                    var barrelToFire1 = barrels1.TakeWhile(b => b.barrel != target1.barrel && b.barrel != target2.barrel).LastOrDefault();
                    strateg.decisions[ship1.id] = strateg.Collect(target1.barrel).FireTo(barrelToFire1?.barrel.fcoord);

                    var barrelToFire2 = barrels2.TakeWhile(b => b.barrel != target1.barrel && b.barrel != target2.barrel && b.barrel != barrelToFire1?.barrel).LastOrDefault();
                    strateg.decisions[ship2.id] = strateg.Collect(target2.barrel).FireTo(barrelToFire2?.barrel.fcoord);
                    return;
                }

                var dist1 = Math.Min(FastShipPosition.DistanceTo(nextShip1Position1, target1.barrel.fcoord),
                                     FastShipPosition.DistanceTo(nextShip1Position2, target1.barrel.fcoord));
                var dist2 = Math.Min(FastShipPosition.DistanceTo(nextShip2Position1, target1.barrel.fcoord),
                                     FastShipPosition.DistanceTo(nextShip2Position2, target1.barrel.fcoord));
                if (dist1 < dist2)
                {
                    target2 = barrels2.FirstOrDefault(
                        b => b.barrel != target1.barrel && (FastShipPosition.DistanceTo(nextShip2Position1, b.barrel.fcoord) < b.dist - 1 ||
                                                            FastShipPosition.DistanceTo(nextShip2Position2, b.barrel.fcoord) < b.dist - 1));
                }
                else
                {
                    target1 = barrels1.FirstOrDefault(
                        b => b.barrel != target2.barrel && (FastShipPosition.DistanceTo(nextShip1Position1, b.barrel.fcoord) < b.dist - 1 ||
                                                            FastShipPosition.DistanceTo(nextShip1Position2, b.barrel.fcoord) < b.dist - 1));
                }
            }
        }
예제 #8
0
        private void RunOrSuicide(TurnState turnState)
        {
            if (turnState.myShips.Max(s => s.rum) > turnState.enemyShips.Max(s => s.rum) || turnState.myShips.Min(s => s.rum) > 50)
            {
                foreach (var ship in turnState.myShips)
                {
                    StrategicDecision prevDecision;
                    strateg.decisions.TryGetValue(ship.id, out prevDecision);
                    strateg.decisions[ship.id] = strateg.RunAway(turnState, ship, prevDecision);
                }
                return;
            }

            if (turnState.myShips.Count == 1)
            {
                var ship = turnState.myShips[0];
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(ship.id, out prevDecision);
                strateg.decisions[ship.id] = strateg.RunAway(turnState, ship, prevDecision);
                return;
            }

            var ship1 = turnState.myShips[0];
            var ship2 = turnState.myShips[1];

            if (ship1.rum > ship2.rum)
            {
                var tmp = ship1;
                ship1 = ship2;
                ship2 = tmp;
            }
            if (FastCoord.Distance(ship1.fbow, ship2.fbow) <= 4)
            {
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(ship1.id, out prevDecision);
                if (prevDecision?.role == StrategicRole.Fire || prevDecision?.role == StrategicRole.Explicit)
                {
                    strateg.decisions[ship1.id] = new StrategicDecision {
                        role = StrategicRole.Explicit, explicitCommand = ShipMoveCommand.Slower
                    };
                    strateg.decisions[ship2.id] = new StrategicDecision {
                        role = StrategicRole.Approach, targetCoord = prevDecision.fireToCoord
                    };
                }
                else
                {
                    var nextShip1Position = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship1.fposition, ShipMoveCommand.Wait));
                    nextShip1Position           = FastShipPosition.GetFinalPosition(FastShipPosition.Move(nextShip1Position, ShipMoveCommand.Slower));
                    strateg.decisions[ship1.id] = new StrategicDecision {
                        role = StrategicRole.Fire, fireToCoord = FastShipPosition.Coord(nextShip1Position)
                    };
                    strateg.decisions[ship2.id] = new StrategicDecision {
                        role = StrategicRole.Approach, targetCoord = FastShipPosition.Coord(nextShip1Position)
                    };
                }
            }
            else
            {
                var x = (FastCoord.GetX(ship1.fcoord) + FastCoord.GetX(ship2.fcoord)) / 2;
                var y = (FastCoord.GetY(ship1.fcoord) + FastCoord.GetY(ship2.fcoord)) / 2;
                if (x < 5)
                {
                    x = 5;
                }
                if (x > Constants.MAP_WIDTH - 6)
                {
                    x = Constants.MAP_WIDTH - 6;
                }
                if (y < 5)
                {
                    y = 5;
                }
                if (y > Constants.MAP_HEIGHT - 6)
                {
                    x = Constants.MAP_HEIGHT - 6;
                }

                strateg.decisions[ship1.id] = new StrategicDecision {
                    role = StrategicRole.Approach, targetCoord = FastCoord.Create(x, y)
                };
                strateg.decisions[ship2.id] = new StrategicDecision {
                    role = StrategicRole.Approach, targetCoord = FastCoord.Create(x, y)
                };
            }
        }
        private CollisionType GetCollisionType(int my, ShipMoveCommand myc, int other, ShipMoveCommand oc)
        {
            uint myMovement;
            uint otherMovement;
            var  collisionType = CollisionChecker.Move(my, myc, other, oc, out myMovement, out otherMovement);

            Console.Out.WriteLine(FastShipPosition.ToShipPosition(FastShipPosition.GetMovedPosition(myMovement)) + " - " + FastShipPosition.ToShipPosition(FastShipPosition.GetFinalPosition(myMovement)));
            Console.Out.WriteLine(FastShipPosition.ToShipPosition(FastShipPosition.GetMovedPosition(otherMovement)) + " - " + FastShipPosition.ToShipPosition(FastShipPosition.GetFinalPosition(otherMovement)));
            return(collisionType);
        }
        public void MakeStrategicDecisions(TurnState turnState)
        {
            if (turnState.barrels.Any())
            {
                strateg.MakeStandardStrategicDecisions(turnState);
                return;
            }

            if (turnState.myShips.Max(s => s.rum) > turnState.enemyShips.Max(s => s.rum) || turnState.myShips.Min(s => s.rum) > 50)
            {
                foreach (var ship in turnState.myShips)
                {
                    StrategicDecision prevDecision;
                    strateg.decisions.TryGetValue(ship.id, out prevDecision);
                    strateg.decisions[ship.id] = strateg.RunAway(turnState, ship, prevDecision);
                }
                return;
            }

            if (turnState.myShips.Count == 1)
            {
                var ship = turnState.myShips[0];
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(ship.id, out prevDecision);
                strateg.decisions[ship.id] = strateg.RunAway(turnState, ship, prevDecision);
                return;
            }

            var maxRum = turnState.myShips.Max(s => s.rum);
            var minRum = turnState.myShips.Min(s => s.rum);
            var ship1  = turnState.myShips.First(s => s.rum == minRum);
            var ship2  = turnState.myShips.Last(s => s.rum == maxRum);
            var last   = turnState.myShips.FirstOrDefault(s => s != ship1 && s != ship2);

            if (last != null)
            {
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(last.id, out prevDecision);
                strateg.decisions[last.id] = strateg.RunAway(turnState, last, prevDecision);
            }

            if (FastCoord.Distance(ship1.fbow, ship2.fbow) <= 4)
            {
                StrategicDecision prevDecision;
                strateg.decisions.TryGetValue(ship1.id, out prevDecision);
                if (prevDecision?.role == StrategicRole.Fire || prevDecision?.role == StrategicRole.Explicit)
                {
                    strateg.decisions[ship1.id] = new StrategicDecision {
                        role = StrategicRole.Explicit, explicitCommand = ShipMoveCommand.Slower
                    };
                    strateg.decisions[ship2.id] = new StrategicDecision {
                        role = StrategicRole.Approach, targetCoord = prevDecision.fireToCoord
                    };
                }
                else
                {
                    var nextShip1Position = FastShipPosition.GetFinalPosition(FastShipPosition.Move(ship1.fposition, ShipMoveCommand.Wait));
                    nextShip1Position           = FastShipPosition.GetFinalPosition(FastShipPosition.Move(nextShip1Position, ShipMoveCommand.Slower));
                    strateg.decisions[ship1.id] = new StrategicDecision {
                        role = StrategicRole.Fire, fireToCoord = FastShipPosition.Coord(nextShip1Position)
                    };
                    strateg.decisions[ship2.id] = new StrategicDecision {
                        role = StrategicRole.Approach, targetCoord = FastShipPosition.Coord(nextShip1Position)
                    };
                }
            }
            else
            {
                var x = (FastCoord.GetX(ship1.fcoord) + FastCoord.GetX(ship2.fcoord)) / 2;
                var y = (FastCoord.GetY(ship1.fcoord) + FastCoord.GetY(ship2.fcoord)) / 2;
                if (x < 5)
                {
                    x = 5;
                }
                if (x > Constants.MAP_WIDTH - 6)
                {
                    x = Constants.MAP_WIDTH - 6;
                }
                if (y < 5)
                {
                    y = 5;
                }
                if (y > Constants.MAP_HEIGHT - 6)
                {
                    x = Constants.MAP_HEIGHT - 6;
                }

                strateg.decisions[ship1.id] = new StrategicDecision {
                    role = StrategicRole.Approach, targetCoord = FastCoord.Create(x, y)
                };
                strateg.decisions[ship2.id] = new StrategicDecision {
                    role = StrategicRole.Approach, targetCoord = FastCoord.Create(x, y)
                };
            }
        }
        private static void Main22(string[] args)
        {
            FastCoord.Init();

            var coordsX = new List <Coord>();

            for (int x = -1; x < Constants.MAP_WIDTH + 1; x++)
            {
                for (int y = -1; y < Constants.MAP_HEIGHT + 1; y++)
                {
                    var coord = new Coord(x, y);
                    coordsX.Add(coord);
                }
            }

            var indexes = Enumerable.Range(0, coordsX.Count).ToArray();
            var seed    = new Random().Next();

            Console.Out.WriteLine($"Seed: {seed}");
            var random = new Random(seed);

            for (int i = 0; i < indexes.Length; i++)
            {
                var r   = random.Next(i, indexes.Length);
                var tmp = indexes[r];
                indexes[r] = indexes[i];
                indexes[i] = tmp;
            }

            var coords     = indexes.Select(i => coordsX[i]).ToArray();
            var fastCoords = indexes.Select(i => FastCoord.Create(coords[i])).ToArray();

            var ships     = coords.Select(c => new ShipPosition(c, random.Next(6), random.Next(3))).ToArray();
            var fastShips = ships.Select(FastShipPosition.Create).ToArray();

            var stopwatch = Stopwatch.StartNew();

            Console.Out.WriteLine("IsInsideMap");
            stopwatch.Restart();
            int ind = 0;

            for (int i = 0; i < 10000000; i++)
            {
                coords[ind++].IsInsideMap();
                if (ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                FastCoord.IsInsideMap(fastCoords[ind++]);
                if (ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            Console.Out.WriteLine("DistanceTo");
            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                coords[ind++].DistanceTo(coords[0]);
                if (ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                FastCoord.Distance(fastCoords[ind++], fastCoords[0]);
                if (ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            Console.Out.WriteLine("Neighbor");
            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                coords[ind].Neighbor(0);
                coords[ind].Neighbor(1);
                coords[ind].Neighbor(2);
                coords[ind].Neighbor(3);
                coords[ind].Neighbor(4);
                coords[ind].Neighbor(5);
                if (++ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                FastCoord.Neighbor(fastCoords[ind], 0);
                FastCoord.Neighbor(fastCoords[ind], 1);
                FastCoord.Neighbor(fastCoords[ind], 2);
                FastCoord.Neighbor(fastCoords[ind], 3);
                FastCoord.Neighbor(fastCoords[ind], 4);
                FastCoord.Neighbor(fastCoords[ind], 5);
                if (++ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            Console.Out.WriteLine("ShipDistanceTo");
            var shipPosition = new ShipPosition(coords[0], 0, 0);

            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                shipPosition.DistanceTo(coords[ind]);
                if (++ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            var fastShipPosition = FastShipPosition.Create(shipPosition);

            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                FastShipPosition.DistanceTo(fastShipPosition, fastCoords[ind++]);
                if (ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            Console.Out.WriteLine("Collides");
            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                shipPosition.Collides(coords[ind++]);
                if (ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                FastShipPosition.Collides(fastShipPosition, fastCoords[ind++]);
                if (ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            Console.Out.WriteLine("CollidesShip");
            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                shipPosition.CollidesShip(ships[ind++]);
                if (ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 10000000; i++)
            {
                FastShipPosition.CollidesShip(fastShipPosition, fastShips[ind++]);
                if (ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            Console.Out.WriteLine("Move");
            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 1_000_000; i++)
            {
                foreach (var moveCommand in ShipMoveCommands.all)
                {
                    ships[ind].Apply(moveCommand);
                }
                if (++ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 1_000_000; i++)
            {
                foreach (var moveCommand in ShipMoveCommands.all)
                {
                    var moved = FastShipPosition.Move(fastShips[ind], moveCommand);
                    FastShipPosition.GetMovedPosition(moved);
                    FastShipPosition.GetFinalPosition(moved);
                }
                if (++ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);

            stopwatch.Restart();
            ind = 0;
            for (int i = 0; i < 1_000_000; i++)
            {
                foreach (var moveCommand in ShipMoveCommands.all)
                {
                    uint myMovement;
                    uint otherMovement;
                    CollisionChecker.Move(fastShips[ind], moveCommand, fastShips[(ind + 1) % indexes.Length], moveCommand, out myMovement, out otherMovement);
                    FastShipPosition.GetMovedPosition(myMovement);
                    FastShipPosition.GetFinalPosition(myMovement);
                }
                if (++ind >= indexes.Length)
                {
                    ind = 0;
                }
            }
            stopwatch.Stop();
            Console.Out.WriteLine(stopwatch.ElapsedMilliseconds);
        }
        public List <PathItem> FindPath(TurnState turnState, int ftarget, NavigationMethod navigationMethod)
        {
            var ship = turnState.FindMyShip(shipId);

            //if (FastShipPosition.Collides(ship.fposition, ftarget))
            //	return new List<PathItem>();

            var queue = new Queue <ShipPathChainItem>();

            queue.Enqueue(ShipPathChainItem.Start(ship.fposition, ftarget));

            var used = new Dictionary <ShipMovementState, ShipPathChainItem>();

            while (queue.Any())
            {
                var current = queue.Dequeue();
                if (current.depth != Settings.NAVIGATION_PATH_DEPTH)
                {
                    var turnForecast = gameState.forecaster.GetTurnForecast(current.depth);
                    foreach (var moveCommand in ShipMoveCommands.all)
                    {
                        var newShipMovement  = FastShipPosition.Move(current.fposition, moveCommand);
                        var newMovedPos      = FastShipPosition.GetMovedPosition(newShipMovement);
                        var newPos           = FastShipPosition.GetFinalPosition(newShipMovement);
                        var newMovementState = new ShipMovementState(newPos, current.depth + 1);
                        if (!used.ContainsKey(newMovementState))
                        {
                            var onMyShip = false;
                            foreach (var otherShip in turnState.myShips)
                            {
                                if (otherShip == ship)
                                {
                                    continue;
                                }
                                var  otherPosition = turnForecast.myShipsSourcePositions[otherShip.index];
                                uint myMovement;
                                uint otherMovement;
                                var  collisionType = CollisionChecker.Move(current.fposition, moveCommand, otherPosition, turnForecast.myShipsMoveCommands[otherShip.index], out myMovement, out otherMovement);
                                if ((collisionType & (CollisionType.MyMove | CollisionType.MyRotation)) != CollisionType.None)
                                {
                                    newShipMovement  = myMovement;
                                    newMovedPos      = FastShipPosition.GetMovedPosition(newShipMovement);
                                    newPos           = FastShipPosition.GetFinalPosition(newShipMovement);
                                    newMovementState = new ShipMovementState(newPos, current.depth + 1);
                                    onMyShip         = used.ContainsKey(newMovementState);
                                    break;
                                }
                            }

                            if (onMyShip)
                            {
                                continue;
                            }

                            var onEnemyShip = false;
                            if (current.depth == 0)
                            {
                                foreach (var enemyShip in turnState.enemyShips)
                                {
                                    var enemyPosition = enemyShip.fposition;
                                    foreach (var enemyMoveCommand in ShipMoveCommands.all)
                                    {
                                        uint myMovement;
                                        uint enemyMovement;
                                        var  collisionType = CollisionChecker.Move(current.fposition, moveCommand, enemyPosition, enemyMoveCommand, out myMovement, out enemyMovement);
                                        if ((collisionType & (CollisionType.MyMove | CollisionType.MyRotation)) != CollisionType.None)
                                        {
                                            newShipMovement  = myMovement;
                                            newMovedPos      = FastShipPosition.GetMovedPosition(newShipMovement);
                                            newPos           = FastShipPosition.GetFinalPosition(newShipMovement);
                                            newMovementState = new ShipMovementState(newPos, current.depth + 1);
                                            onEnemyShip      = used.ContainsKey(newMovementState);
                                            break;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                var prevEnemyFinalPositions = gameState.forecaster.GetTurnForecast(Math.Min(current.depth - 1, Settings.NAVIGATOR_ENEMY_POSITION_DEPTH)).enemyShipsFinalPositions;
                                foreach (var enemyPosition in prevEnemyFinalPositions)
                                {
                                    uint myMovement;
                                    uint enemyMovement;
                                    var  collisionType = CollisionChecker.Move(current.fposition, moveCommand, enemyPosition, ShipMoveCommand.Wait, out myMovement, out enemyMovement);
                                    if ((collisionType & (CollisionType.MyMove | CollisionType.MyRotation)) != CollisionType.None)
                                    {
                                        newShipMovement  = myMovement;
                                        newMovedPos      = FastShipPosition.GetMovedPosition(newShipMovement);
                                        newPos           = FastShipPosition.GetFinalPosition(newShipMovement);
                                        newMovementState = new ShipMovementState(newPos, current.depth + 1);
                                        onEnemyShip      = used.ContainsKey(newMovementState);
                                        break;
                                    }
                                }

                                //onEnemyShip = gameState.forecaster.GetTurnForecast(Math.Min(current.depth, Settings.NAVIGATOR_ENEMY_POSITION_DEPTH)).enemyShipsFinalPositions
                                //	.Any(m => FastShipPosition.CollidesShip(newPos, m) || FastShipPosition.CollidesShip(newMovedPos, m));
                            }

                            if (onEnemyShip)
                            {
                                //used.Add(newMovementState, null);
                                continue;
                            }

                            var damage = turnForecast.mineDamageCoordMap[FastShipPosition.Coord(newPos)]
                                         + turnForecast.mineDamageCoordMap[FastShipPosition.Bow(newPos)]
                                         + turnForecast.mineDamageCoordMap[FastShipPosition.Stern(newPos)]
                                         + turnForecast.nearMineDamageCoordMap[FastShipPosition.Bow(newPos)]
                                         + turnForecast.nearMineDamageCoordMap[FastShipPosition.Stern(newPos)];

                            if (newMovedPos != newPos)
                            {
                                damage += turnForecast.mineDamageCoordMap[FastShipPosition.Bow(newMovedPos)]
                                          + turnForecast.mineDamageCoordMap[FastShipPosition.Stern(newMovedPos)]
                                          + turnForecast.nearMineDamageCoordMap[FastShipPosition.Bow(newMovedPos)]
                                          + turnForecast.nearMineDamageCoordMap[FastShipPosition.Stern(newMovedPos)];
                            }

                            var cannonedBowOrStern = turnForecast.cannonballCoordsMap[FastShipPosition.Bow(newPos)] || turnForecast.cannonballCoordsMap[FastShipPosition.Stern(newPos)];
                            if (cannonedBowOrStern)
                            {
                                damage += Constants.LOW_DAMAGE;
                            }

                            var cannonedCenter = turnForecast.cannonballCoordsMap[FastShipPosition.Coord(newPos)];
                            if (cannonedCenter)
                            {
                                damage += Constants.HIGH_DAMAGE;
                            }

                            if (Settings.NEAR_ENEMYSHIP_VIRTUAL_DAMAGE > 0)
                            {
                                var nearEnemyShip = turnState.enemyShips.Any(m => FastShipPosition.DistanceTo(newPos, m.fcoord) < Settings.NEAR_ENEMY_SHIP_MIN_DIST);
                                if (nearEnemyShip)
                                {
                                    damage += Settings.NEAR_ENEMYSHIP_VIRTUAL_DAMAGE;
                                }
                            }

                            var next = current.Next(newPos, moveCommand, ftarget, damage);
                            queue.Enqueue(next);
                            used.Add(newMovementState, next);
                        }
                    }
                }
            }

            ShipPathChainItem bestChainItem = null;

            foreach (var chainItem in used.Values.Where(v => v != null))
            {
                if (chainItem.prev != null)
                {
                    if (bestChainItem == null)
                    {
                        bestChainItem = chainItem;
                    }
                    else
                    {
                        switch (navigationMethod)
                        {
                        case NavigationMethod.Approach:
                            bestChainItem = SelectBestPath_Approach(chainItem, bestChainItem, ship);
                            break;

                        case NavigationMethod.Collect:
                            bestChainItem = SelectBestPath_Collect(chainItem, bestChainItem, ship);
                            break;

                        default:
                            bestChainItem = SelectBestPath(chainItem, bestChainItem, ship);
                            break;
                        }
                    }
                }
            }

            if (bestChainItem == null)
            {
                return(new List <PathItem>());
            }

            var chainDump = new List <ShipPathChainItem>();
            var chain     = new List <PathItem>();

            while (bestChainItem.prev != null)
            {
                chain.Add(new PathItem {
                    command = bestChainItem.command, targetPosition = bestChainItem.fposition, sourcePosition = bestChainItem.prev.fposition
                });
                chainDump.Add(bestChainItem);
                bestChainItem = bestChainItem.prev;
            }
            chainDump.Reverse();
            if (Settings.DUMP_BEST_PATH)
            {
                Console.Error.WriteLine($"Best path for ship {shipId}");
                foreach (var item in chainDump)
                {
                    Console.Error.WriteLine($"{item.command} - {FastShipPosition.ToShipPosition(item.fposition)} - dmg:{item.damage}");
                }
            }
            chain.Reverse();
            return(chain);
        }