public void NearMap_GoOut_ReturnsValidFastCoord(int x, int y, int orientation)
        {
            var coord     = new Coord(x, y);
            var fastCoord = FastCoord.Create(coord);
            var neighbor  = FastCoord.Neighbor(fastCoord, orientation);

            neighbor.Should().Be(-1);
        }
        public void NearMap_GoIn_ReturnsValidFastCoord(int x, int y, int orientation)
        {
            var coord     = new Coord(x, y);
            var fastCoord = FastCoord.Create(coord);
            var neighbor  = FastCoord.Neighbor(fastCoord, orientation);
            var actual    = FastCoord.ToCoord(neighbor);

            actual.Should().Be(coord.Neighbor(orientation));
        }
 public void InsideMap_ReturnsValidFastCoord(int orientation)
 {
     for (int x = 0; x < Constants.MAP_WIDTH; x++)
     {
         for (int y = 0; y < Constants.MAP_HEIGHT; y++)
         {
             var coord     = new Coord(x, y);
             var fastCoord = FastCoord.Create(coord);
             var neighbor  = FastCoord.Neighbor(fastCoord, orientation);
             var actual    = FastCoord.ToCoord(neighbor);
             actual.Should().Be(coord.Neighbor(orientation));
         }
     }
 }
        private void BuildCannonballsForecast(TurnState turnState)
        {
            for (var i = 0; i < turnState.cannonballs.Count; i++)
            {
                if (turnState.cannonballs[i].turns - 1 >= 0 && turnState.cannonballs[i].turns - 1 < Settings.NAVIGATION_PATH_DEPTH)
                {
                    GetTurnForecast(turnState.cannonballs[i].turns - 1).cannonballCoordsMap[turnState.cannonballs[i].fcoord] = true;
                }
            }

            if (Settings.CANNONBALLS_FORECAST_TRAVEL_TIME_LIMIT > 0)
            {
                foreach (var enemyShip in turnState.enemyShips)
                {
                    if (!enemiesCanFire.Contains(enemyShip.id))
                    {
                        continue;
                    }
                    var targets = Enumerable.Range(0, 6).Select(o => enemyShip.fbow).ToArray();
                    for (var dist = 1; dist <= 10; dist++)
                    {
                        var travelTime = (int)(1 + Math.Round(dist / 3.0));
                        if (travelTime > Settings.CANNONBALLS_FORECAST_TRAVEL_TIME_LIMIT)
                        {
                            break;
                        }
                        if (travelTime >= Settings.NAVIGATION_PATH_DEPTH)
                        {
                            break;
                        }
                        for (var orientation = 0; orientation < 6; orientation++)
                        {
                            targets[orientation] = FastCoord.Neighbor(targets[orientation], orientation);
                        }
                        for (var orientation = 0; orientation < 6; orientation++)
                        {
                            if (FastCoord.IsInsideMap(targets[orientation]))
                            {
                                GetTurnForecast(travelTime).cannonballCoordsMap[targets[orientation]] = true;
                            }
                        }
                    }
                }
            }
        }
 private void BuildMineForecast(int mineCoord)
 {
     if (!FastCoord.IsInsideMap(mineCoord))
     {
         return;
     }
     for (var depth = 0; depth < Settings.NAVIGATION_PATH_DEPTH; depth++)
     {
         var turnForecast = GetTurnForecast(depth);
         turnForecast.mineDamageCoordMap[mineCoord] += Constants.MINE_DAMAGE;
         if (turnForecast.cannonballCoordsMap[mineCoord])
         {
             for (int orientation = 0; orientation < 6; orientation++)
             {
                 var neighbor = FastCoord.Neighbor(mineCoord, orientation);
                 turnForecast.nearMineDamageCoordMap[neighbor] += Constants.NEAR_MINE_DAMAGE;
             }
         }
     }
 }
        private static void Split(int position, ShipMoveCommand command, out int coord, out int bow, out int stern, out int orientation, out int speed, out int ncoord, out int nbow, out int nstern, out int norientation)
        {
            coord        = FastShipPosition.Coord(position);
            orientation  = FastShipPosition.Orientation(position);
            speed        = FastShipPosition.Speed(position);
            bow          = FastCoord.Neighbor(coord, orientation);
            stern        = FastCoord.Neighbor(coord, (orientation + 3) % 6);
            ncoord       = coord;
            nbow         = bow;
            nstern       = stern;
            norientation = orientation;
            switch (command)
            {
            case ShipMoveCommand.Faster:
                if (speed < Constants.MAX_SHIP_SPEED)
                {
                    speed++;
                }
                break;

            case ShipMoveCommand.Slower:
                if (speed > 0)
                {
                    speed--;
                }
                break;

            case ShipMoveCommand.Port:
                norientation = (orientation + 1) % 6;
                break;

            case ShipMoveCommand.Starboard:
                norientation = (orientation + 5) % 6;
                break;
            }
        }
        private static bool GoForward(int phaseSpeed, ref int coord, ref int bow, ref int stern, ref int orientation, ref int speed, ref int ncoord, ref int nbow, ref int nstern)
        {
            ncoord = coord;
            nbow   = bow;
            nstern = stern;

            if (phaseSpeed > speed)
            {
                return(true);
            }

            var newCoord = bow;

            if (FastCoord.IsInsideMap(newCoord))
            {
                ncoord = newCoord;
                nbow   = FastCoord.Neighbor(ncoord, orientation);
                nstern = FastCoord.Neighbor(ncoord, (orientation + 3) % 6);
                return(true);
            }

            speed = 0;
            return(false);
        }
        public static CollisionType Move(int myPosition, ShipMoveCommand myCommand, int otherPosition, ShipMoveCommand otherCommand, out uint myMovement, out uint otherMovement)
        {
            var result = CollisionType.None;

            int myCoord, myBow, myStern, myOrientation, mySpeed, nmyCoord, nmyBow, nmyStern, nmyOrientation;

            Split(myPosition, myCommand, out myCoord, out myBow, out myStern, out myOrientation, out mySpeed, out nmyCoord, out nmyBow, out nmyStern, out nmyOrientation);

            int otherCoord, otherBow, otherStern, otherOrientation, otherSpeed, notherCoord, notherBow, notherStern, notherOrientation;

            Split(otherPosition, otherCommand, out otherCoord, out otherBow, out otherStern, out otherOrientation, out otherSpeed, out notherCoord, out notherBow, out notherStern, out notherOrientation);

            // move ships

            for (int i = 1; i <= Constants.MAX_SHIP_SPEED; i++)
            {
                if (!GoForward(i, ref myCoord, ref myBow, ref myStern, ref myOrientation, ref mySpeed, ref nmyCoord, ref nmyBow, ref nmyStern))
                {
                    result |= CollisionType.MyWall;
                }
                if (!GoForward(i, ref otherCoord, ref otherBow, ref otherStern, ref otherOrientation, ref otherSpeed, ref notherCoord, ref notherBow, ref notherStern))
                {
                    result |= CollisionType.OtherWall;
                }

                var myCollides    = mySpeed > 0 && (nmyBow == notherBow || nmyBow == notherCoord || nmyBow == notherStern);
                var otherCollides = otherSpeed > 0 && (notherBow == nmyBow || notherBow == nmyCoord || notherBow == nmyStern);

                if (myCollides)
                {
                    nmyCoord = myCoord;
                    nmyBow   = myBow;
                    nmyStern = myStern;
                    mySpeed  = 0;
                    result  |= CollisionType.MyMove;
                }
                if (otherCollides)
                {
                    notherCoord = otherCoord;
                    notherBow   = otherBow;
                    notherStern = otherStern;
                    otherSpeed  = 0;
                    result     |= CollisionType.OtherMove;
                }

                myCoord = nmyCoord;
                myBow   = nmyBow;
                myStern = nmyStern;

                otherCoord = notherCoord;
                otherBow   = notherBow;
                otherStern = notherStern;
            }

            var myMovedPosition    = FastShipPosition.Create(myCoord, myOrientation, mySpeed);
            var otherMovedPosition = FastShipPosition.Create(otherCoord, otherOrientation, otherSpeed);

            // rotate ships
            nmyBow   = FastCoord.Neighbor(myCoord, nmyOrientation);
            nmyStern = FastCoord.Neighbor(myCoord, (nmyOrientation + 3) % 6);

            notherBow   = FastCoord.Neighbor(otherCoord, notherOrientation);
            notherStern = FastCoord.Neighbor(otherCoord, (notherOrientation + 3) % 6);

            var rotationCollides =
                nmyBow == notherBow || nmyBow == notherCoord || nmyBow == notherStern ||
                nmyCoord == notherBow || nmyCoord == notherCoord || nmyCoord == notherStern ||
                nmyStern == notherBow || nmyStern == notherCoord || nmyStern == notherStern;

            if (rotationCollides)
            {
                if (myCommand == ShipMoveCommand.Port || myCommand == ShipMoveCommand.Starboard)
                {
                    result |= CollisionType.MyRotation;
                }
                if (otherCommand == ShipMoveCommand.Port || otherCommand == ShipMoveCommand.Starboard)
                {
                    result |= CollisionType.OtherRotation;
                }
            }
            else
            {
                myBow         = nmyBow;
                myStern       = nmyStern;
                myOrientation = nmyOrientation;

                otherBow         = notherBow;
                otherStern       = notherStern;
                otherOrientation = notherOrientation;
            }

            var myFinalPosition = FastShipPosition.Create(myCoord, myOrientation, mySpeed);

            myMovement = FastShipPosition.Move(myMovedPosition, myFinalPosition);

            var otherFinalPosition = FastShipPosition.Create(otherCoord, otherOrientation, otherSpeed);

            otherMovement = FastShipPosition.Move(otherMovedPosition, otherFinalPosition);

            return(result);
        }
        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);
        }