prims_generator.hxx
Go to the documentation of this file.
1 /*===========================================================================================================
2  *
3  * HUC - Hurna Core
4  *
5  * Copyright (c) Michael Jeulin-Lagarrigue
6  *
7  * Licensed under the MIT License, you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * https://github.com/Hurna/Hurna-Core/blob/master/LICENSE
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License is
13  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and limitations under the License.
15  *
16  * The above copyright notice and this permission notice shall be included in all copies or
17  * substantial portions of the Software.
18  *
19  *=========================================================================================================*/
20 #ifndef MODULE_MAZE_PRIMSG_HXX
21 #define MODULE_MAZE_PRIMSG_HXX
22 
23 #include <DataStructures/grid.hxx>
24 
25 // STD
26 #include <random>
27 #include <stack>
28 
29 namespace huc
30 {
31  namespace maze
32  {
53  {
54  public:
56  { uint64_t rootDistance; };
57 
59  typedef Maze::Cell Cell;
60  typedef Maze::Point Point;
61 
62  std::unique_ptr<Maze> operator()(const uint32_t width, const uint32_t height,
63  const Point& startPoint = Point(0,0), const uint32_t seed = 0)
64  {
65  if (width < 1 || height < 1 || startPoint.x >= width || startPoint.y >= height)
66  return nullptr;
67 
68  auto maze(std::unique_ptr<Maze>(new Maze(width, height)));
69  std::mt19937 mt(seed); // Random generator - Mersenne Twister algorithm
70  std::set<std::shared_ptr<Cell>> pathSet; // Keep track of possible paths to expand
71 
72  // While there is cell within the set:
73  (*maze)[startPoint.x][startPoint.y]->info.rootDistance = 0;
74  pathSet.insert((*maze)[startPoint.x][startPoint.y]);
75  while (!pathSet.empty())
76  {
77  auto cellIt = pathSet.begin();
78  std::advance(cellIt, mt() % pathSet.size());
79  (*cellIt)->info.isVisited = true;
80 
81  // Randomly connect it to a cell that is already part of the mze
82  auto neighbours = GetNeighbours(*maze, *(*cellIt).get(), true);
83  if (!neighbours.empty())
84  {
85  auto randIdx = mt() % neighbours.size();
86  (*cellIt)->info.rootDistance = neighbours[randIdx]->info.rootDistance + 1;
87  maze->Connect(*cellIt, neighbours[randIdx]);
88  }
89 
90  // Add available neighbours and remove current cell
91  neighbours = GetNeighbours(*maze, *(*cellIt).get(), false);
92  pathSet.insert(neighbours.begin(), neighbours.end());
93  pathSet.erase(cellIt);
94  }
95 
96  return maze;
97  }
98 
106  static std::vector<std::shared_ptr<Cell>>
107  GetNeighbours(const Maze& maze, const Cell& cell, const bool visited)
108  {
109  std::vector<std::shared_ptr<Cell>> neighbour;
110 
111  const auto x = cell.x;
112  const auto y = cell.y;
113 
114  // Push left if available
115  if (static_cast<int>(x - 1) >= 0 &&
116  ((visited) ? maze[x-1][y]->info.isVisited : !maze[x-1][y]->info.isVisited))
117  neighbour.push_back(maze[x-1][y]);
118  // Push bottom if available
119  if (static_cast<int>(y - 1) >= 0 &&
120  ((visited) ? maze[x][y-1]->info.isVisited : !maze[x][y-1]->info.isVisited))
121  neighbour.push_back(maze[x][y-1]);
122  // Push top if available
123  if (x + 1 < maze.Width() &&
124  ((visited) ? maze[x+1][y]->info.isVisited : !maze[x+1][y]->info.isVisited))
125  neighbour.push_back(maze[x+1][y]);
126  // Push right if available
127  if (y + 1 < maze.Height() &&
128  ((visited) ? maze[x][y+1]->info.isVisited : !maze[x][y+1]->info.isVisited))
129  neighbour.push_back(maze[x][y+1]);
130 
131  return neighbour;
132  }
133  };
134  }
135 }
136 
137 #endif // MODULE_MAZE_PRIMSG_HXX
std::unique_ptr< Maze > operator()(const uint32_t width, const uint32_t height, const Point &startPoint=Point(0, 0), const uint32_t seed=0)
uint32_t Width() const
Definition: grid.hxx:192
const uint32_t y
Definition: grid.hxx:70
uint32_t Height() const
Definition: grid.hxx:193
Point struct is a convenient struct use to represent a 2D point for a grid (index position)...
Definition: grid.hxx:56
const uint32_t x
Definition: grid.hxx:69
static std::vector< std::shared_ptr< Cell > > GetNeighbours(const Maze &maze, const Cell &cell, const bool visited)