Mazegen is a maze generation library based on Bob Nystrom's approach, decribed here https://journal.stuffwithstuff.com/2014/12/21/rooms-and-mazes/
It has zero dependecies, but uses stl heavily, so it is supposed to be used in C++ applications.
The example/
directory includes an ASCII-graphics example application. To build it set -DBUILD_EXAMPLE=ON
when running cmake.
More complex demo project with SFML and ImGui can be found here https://github.com/aleksandrbazhin/mazegen_sfml_example It's recommended to use it to understand the parameters of the generation.
The algorithm:
- Throws rooms randomly.
- Grows the maze by random walk, wiggling with a
wiggle chance
, from every point. Unlike the original it has user-definedconstraints
which are first to be used as growth starting points. - Connects rooms to all of the adjacent hall regions by the doors once.
- If the room is connected to an already connected region, the door is removed with
1.0f - extra connection chance
. Unlike the original, there is no flood fill to test for connectivity, instead union-find is used for maze regions. - Deadends are removed with
1.0f - deadend chance
. Ifdeadend chance
is 0, the maze just connects all the constraints and the rooms without any blind halls. - Deadends adjacent to the rooms are connected with
reconnect deadends chance
. This step is not in the original, but leads to a more natural looking maze - who would build a hall close to the room and not build a door?
This is an odd number based maze - the height, width, room_min_size, room_max_size, and all the constrained points' coords should always be odd. The limitation comes from the walls being as thick as the halls.
Maximum room placement attempts number is 1 000 000. Height and width are not constrained, but I wouldn't try something much bigger than 10000 by 10000. Such a maze takes around 10s to build on my machine, but the time will grow non-lineraly due to random walk during maze building.
At minimum you have to create a generator and call generate.
auto gen = mazegen::Generator();
gen.generate(width, height);
gen.generate()
runs a generation algorithm storing all results in the std containers.
To iterate over the resulting maze use gen.maze_width()
and gen.get_height()
. By calling gen.region_at(x, y)
you can get a maze region id at that point. If there is a wall or x
or y
is out of maze boundaries, mazegen::NOTHING_ID
will be returned. To determine if the id belongs to a hall, room or door use mazegen::is_hall(id)
, mazegen::is_room(id)
, and mazegen::is_door(id)
.
You can set a randomization seed for the generator. Seed is unsigned int
as used by std <random>
.
auto gen = mazegen::Generator();
gen.set_seed(1000);
gen.generate(width, height);
gen.get_seed()
returns the seed used for the last generation.
Most likely you would want to setup generation parameters, it is done by providing mazegen::Config
to the generate
method. The 4th parameter is constrained points of type mazegen::PointSet
. Those points are always in a room or a hall. If the can be in a room is determined by constrain halls only
boolean value.
mazegen::Config cfg;
cfg.ROOM_BASE_NUMBER = 25;
cfg.ROOM_SIZE_MIN = 5;
cfg.ROOM_SIZE_MAX = 7;
cfg.EXTRA_CONNECTION_CHANCE = 0.0;
cfg.WIGGLE_CHANCE = 0.5;
cfg.DEADEND_CHANCE = 0.5;
cfg.RECONNECT_DEADENDS_CHANCE = 0.5;
cfg.CONSTRAIN_HALL_ONLY = true;
mazegen::PointSet constraints {{1, 1}, {width - 2, height - 2}};
auto gen = mazegen::Generator();
gen.generate(width, height, cfg, constraints);
mazegen::Generator
sanitizes the config and constrains' values before using them.
gen.get_config()
returns a fixed mazegen::Config
which was actually used for the generation.
gen.get_warnings()
return a std::string
with all the warnings generated during sanitizing, separarted by \n
.
Vectors of hall regions, rooms, and doors are returned by the following methods of mazegen::Generator
:
const std::vector<Room>& get_rooms();
const std::vector<Hall>& get_halls();
const std::vector<Door>& get_doors();
- Improve warnings reporting
- Room constraints (Needed to embed hand-generated rooms).
- Return crossroad graph.
- Pathfinding using crossroad graph.
- Godot plugin.