public int[,] Initial()
        {
            var homePoints = new List <(Point Point, Direction SourceDirection, int PathLength)>();

            var map = Game.GetNewMap <int>();

            Utils.FastCopyArray(Game.NoEnemiesDangerousMap, map, GameParams.MapSize.Width * GameParams.MapSize.Height);

            var visited = Game.GetNewMap <bool>();

            map[_position.X, _position.Y]     = 0;
            visited[_position.X, _position.Y] = true;

            var queue = new Queue <Point>(GameParams.MapSize.Width * GameParams.MapSize.Height);

            queue.Enqueue(_position);

            while (queue.Count > 0)
            {
                var currentPoint  = queue.Dequeue();
                int currentLength = map[currentPoint.X, currentPoint.Y];
                foreach (var direction in EnumValues.GetAll <Direction>())
                {
                    var neighbor = currentPoint.MoveLogic(direction);
                    if (!GameParams.MapSize.ContainsPoint(neighbor) || _tail.AsPointsSet().Contains(neighbor))
                    {
                        continue;
                    }

                    if (_territory.Contains(neighbor) && !_territory.Contains(currentPoint))
                    {
                        homePoints.Add((neighbor, direction, currentLength + 1));
                    }

                    if (visited[neighbor.X, neighbor.Y])
                    {
                        continue;
                    }

                    map[neighbor.X, neighbor.Y]     = currentLength + 1;
                    visited[neighbor.X, neighbor.Y] = true;
                    queue.Enqueue(neighbor);
                }
            }

            if (homePoints.Count == 0)
            {
                return(map);
            }

            for (int y = 0; y < GameParams.MapSize.Height; y++)
            {
                for (int x = 0; x < GameParams.MapSize.Width; x++)
                {
                    map[x, y] = Math.Min(map[x, y], homePoints.Min(p => p.Point.GetDistanceTo(new Point(x, y), p.SourceDirection)));
                }
            }

            return(map);
        }
        public int[,] DoubleSides()
        {
            var map = Game.GetNewMap <int>();

            Utils.FastCopyArray(Game.NoEnemiesDangerousMap, map, GameParams.MapSize.Width * GameParams.MapSize.Height);
            var visited = Game.GetNewMap <bool>();

            var mapAfterHome     = Game.GetNewMap <int>();
            var visitedAfterHome = Game.GetNewMap <bool>();

            map[_position.X, _position.Y]     = 0;
            visited[_position.X, _position.Y] = true;

            var queue = new Queue <(Point Point, bool AfterHome, Direction?VisitHomeDirection)>(GameParams.MapSize.Width * GameParams.MapSize.Height);

            queue.Enqueue((_position, false, null));

            bool visitHome = false;

            while (queue.Count > 0)
            {
                (var currentPoint, bool afterHome, var visitHomeDirection) = queue.Dequeue();

                if (!afterHome)
                {
                    int currentLength = map[currentPoint.X, currentPoint.Y];
                    foreach (var direction in EnumValues.GetAll <Direction>())
                    {
                        var neighbor = currentPoint.MoveLogic(direction);
                        if (!GameParams.MapSize.ContainsPoint(neighbor) || _tail.AsPointsSet().Contains(neighbor))
                        {
                            continue;
                        }

                        if (_territory.Contains(neighbor) && !_territory.Contains(currentPoint) && !visitedAfterHome[neighbor.X, neighbor.Y])
                        {
                            queue.Enqueue((neighbor, true, direction));
                            mapAfterHome[neighbor.X, neighbor.Y] = currentLength + 1;
                            visitHome = true;
                        }

                        if (visited[neighbor.X, neighbor.Y])
                        {
                            continue;
                        }

                        map[neighbor.X, neighbor.Y]     = currentLength + 1;
                        visited[neighbor.X, neighbor.Y] = true;
                        queue.Enqueue((neighbor, false, null));
                    }
                }
                else
                {
                    int currentLength = mapAfterHome[currentPoint.X, currentPoint.Y];
                    foreach (var direction in EnumValues.GetAll <Direction>())
                    {
                        var neighbor = currentPoint.MoveLogic(direction);
                        if (!GameParams.MapSize.ContainsPoint(neighbor) || visitedAfterHome[neighbor.X, neighbor.Y] || visitHomeDirection == direction.GetOpposite())
                        {
                            continue;
                        }

                        mapAfterHome[neighbor.X, neighbor.Y]     = currentLength + 1;
                        visitedAfterHome[neighbor.X, neighbor.Y] = true;
                        queue.Enqueue((neighbor, true, null));
                    }
                }
            }

            if (!visitHome)
            {
                return(map);
            }

            for (int y = 0; y < GameParams.MapSize.Height; y++)
            {
                for (int x = 0; x < GameParams.MapSize.Width; x++)
                {
                    map[x, y] = Math.Min(map[x, y], mapAfterHome[x, y]);
                }
            }

            return(map);
        }