private int[,] BuildTimeMap()
        {
            if (PathToNextPositionLength == 0)
            {
                return Tail.Length > 1 ? BuildOutsideTimeMap() : BuildInsideTimeMap();
            }

            if (Tail.Length == 0 || Territory.Contains(Position.MoveLogic(Direction.Value))) // Возможно, когда ход закончится следующая клетка будет уже не территорией игрока, но мы выбираем худший для нас вариант
            {
                return BuildInsideTimeMap();
            }

            return BuildOutsideTimeMap();
        }
        private unsafe int[,] BuildOutsideTimeMap()
        {
            var timeMap = Game.GetNewMap<int>();
            Utils.FastCopyArray(Game.NoEnemiesDangerousMap, timeMap, GameParams.MapSize.Width*GameParams.MapSize.Height);
            var distanceMap = stackalloc int[GameParams.MapSize.Width*GameParams.MapSize.Height];
            var visited = stackalloc bool[GameParams.MapSize.Width*GameParams.MapSize.Height];
            var timeMapAfterHome = stackalloc int[GameParams.MapSize.Width*GameParams.MapSize.Height];
            var distanceMapAfterHome = stackalloc int[GameParams.MapSize.Width*GameParams.MapSize.Height];
            var visitedAfterHome = stackalloc bool[GameParams.MapSize.Width*GameParams.MapSize.Height];

            Point startPoint;
            int currentTime;
            int currentDistance;

            if (PathToNextPositionLength > 0)
            {
                startPoint = Position.MoveLogic(Direction.Value);
                currentTime = (GameParams.CellSize - PathToNextPositionLength)/GetSpeed(0);
                currentDistance = 1;
            }
            else
            {
                startPoint = Position;
                currentTime = 0;
                currentDistance = 0;
            }

            int startPointCoord = startPoint.X + startPoint.Y*GameParams.MapSize.Width;
            timeMap[startPoint.X, startPoint.Y] = currentTime;
            distanceMap[startPointCoord] = currentDistance;
            visited[startPointCoord] = true;

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

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

                int currentCoord = currentPoint.X + currentPoint.Y*GameParams.MapSize.Width;

                if (!afterHome)
                {
                    currentTime = timeMap[currentPoint.X, currentPoint.Y];
                    currentDistance = distanceMap[currentCoord];
                    foreach (var direction in EnumValues.GetAll<Direction>())
                    {
                        var neighbor = currentPoint.MoveLogic(direction);
                        int neighborCoord = neighbor.X + neighbor.Y*GameParams.MapSize.Width;
                        if (!GameParams.MapSize.ContainsPoint(neighbor) || Tail.AsPointsSet().Contains(neighbor))
                        {
                            continue;
                        }

                        if (Territory.Contains(neighbor) && !Territory.Contains(currentPoint) && !visitedAfterHome[neighborCoord])
                        {
                            queue.Enqueue((neighbor, true, direction));
                            distanceMapAfterHome[neighborCoord] = currentDistance + 1;
                            timeMapAfterHome[neighborCoord] = currentTime + GameParams.CellSize/GetSpeed(currentDistance);
                            visitHome = true;
                        }

                        if (visited[neighborCoord])
                        {
                            continue;
                        }

                        distanceMap[neighborCoord] = currentDistance + 1;
                        timeMap[neighbor.X, neighbor.Y] = currentTime + GameParams.CellSize/GetSpeed(currentDistance);
                        visited[neighborCoord] = true;
                        queue.Enqueue((neighbor, false, null));
                    }
                }
                else
                {
                    currentTime = timeMapAfterHome[currentCoord];
                    currentDistance = distanceMapAfterHome[currentCoord];
                    foreach (var direction in EnumValues.GetAll<Direction>())
                    {
                        var neighbor = currentPoint.MoveLogic(direction);
                        int neighborCoord = neighbor.X + neighbor.Y*GameParams.MapSize.Width;
                        if (!GameParams.MapSize.ContainsPoint(neighbor) || visitedAfterHome[neighborCoord] || visitHomeDirection == direction.GetOpposite())
                        {
                            continue;
                        }

                        distanceMapAfterHome[neighborCoord] = currentDistance + 1;
                        timeMapAfterHome[neighborCoord] = currentTime + GameParams.CellSize/GetSpeed(currentDistance);
                        visitedAfterHome[neighborCoord] = true;
                        queue.Enqueue((neighbor, true, null));
                    }
                }
            }

            if (!visitHome)
            {
                return timeMap;
            }

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

            return timeMap;
        }