/// <summary>
        /// Creates the neighbor cache.
        /// </summary>
        /// <returns></returns>
        private Position[, ][] CreateNeighborCache()
        {
            Position[, ][] positions = new Position[Width, Height][];

            for (int y = 0; y < Height; ++y)
            {
                for (int x = 0; x < Width; ++x)
                {
                    Position currentPosition = new Position(x, y);
                    positions[x, y] = NeighborHelper.GetNeighborPositions(currentPosition, Width, Height);
                }
            }

            return(positions);
        }
        /// <summary>
        /// Creates the neighbor cache. The result contains the neighbors for every livable position.
        /// </summary>
        /// <returns>The neighbors for every livable position.</returns>
        private Position[, ][] CreateNeighborCache()
        {
            var edgeMapping = CreateEdgeMapping();

            Position[, ][] positions = new Position[Width, Height][]; // TODO: Don't waste space! new Position[2 * (_width * _depth + _width * _height + _height * _depth)][];

            for (int y = 0; y < Height; ++y)
            {
                for (int x = 0; x < Width; ++x)
                {
                    if (IsLifePossible(x, y))
                    {
                        // by adding a height of two and and moving the Y position one to the bottom, we can simulate an empty row above and below the cuboid field.
                        // by adding a width of two and and moving the X position one to the right, we can simulate an empty column to the left and right of the cuboid field.
                        Position virtualPosition = new Position(x + 1, y + 1);
                        IEnumerable <Position> virtualNeighborPositions = NeighborHelper.GetNeighborPositions(virtualPosition, Width + 2, Height + 2);

                        List <Position> realNeighborPositions = new List <Position>();
                        foreach (var virtualNeighborPosition in virtualNeighborPositions)
                        {
                            if (edgeMapping.Contains(virtualNeighborPosition))
                            {
                                realNeighborPositions.AddRange(edgeMapping[virtualNeighborPosition].Where(p => p.X != virtualPosition.X || p.Y != virtualPosition.Y).Select(vp => new Position(vp.X - 1, vp.Y - 1)));
                            }
                            else if (virtualNeighborPosition.X != 0 && virtualNeighborPosition.X != ((2 * CuboidDepth) + (2 * CuboidWidth)) + 1 && virtualNeighborPosition.Y != 0 && virtualNeighborPosition.Y != ((2 * CuboidDepth) + CuboidHeight) + 1)
                            {
                                realNeighborPositions.Add(new Position(virtualNeighborPosition.X - 1, virtualNeighborPosition.Y - 1));
                            }
                        }

                        positions[x, y] = realNeighborPositions.Distinct().ToArray();
                    }
                }
            }

            return(positions);
        }