Roguelike Game in C++17
Dungeon Generation
The player can move around, and there are few rooms. But at this time nothing connects the rooms, so player cannot go from one room to another. Additionally, room generation is very static, it's the same everytime; and that's boring.
Goals
So let's fix both these issues.
- Simple rooms generator
- Connect all the generated rooms
For this round, neither of these two goals will use a complex algorithm. Idea is to get it to be random enough that it feels different. But is simple to implement and understand.
Brief detour into Refactoing lands
As is always the case, one can never be satisfied with how things are. So things must change. For this cycle, we want to do two things:
- Change
game_map
structure so that it has list of rooms. - Ensure that player always starts in one of these rooms.
All the changes in this refactor are in service of these two items.
I've added room
structure, and game_map
structure has an array of these rooms
.
Additionally, I am changing the tile
structure, such that it now has two data
members and two function members; and everything that use tile
was updated to use
new members. And lastly, renamed map_size
to dimension
, since game_map
has
dimension, and room
has dimension. They can use the same type.
The way we ensure that player always starts in one of the rooms, we get 1st room
from game_map
and put the player in centre of that room.
Simple rooms generator
We start by adding two member functions to room
, center
and intersects
, first
just returns centre of the room, while second tells you if this room intersects
another room.
Most of the changes for this section, will be modifying game_map.cpp
file. We will
also be using vcpkg
to get a library to help with iterating over arrays. The library
in question is called CppIterTools
, there are many librarys for C++ that do similar
things as this library. e.g. NanoRanges
, Easy Iterator
, Range-V3
, etc. You could
achieve the same with any of them. You can download the library using following command.
vcpkg install cppitertools
And because it's a header only library, we don't have to change anything in CMakeLists to
make use of it. vcpkg
automagic!!!.
We start by changing generate_map
function, first we change how tiles array is populated.
Previously, we populated the tiles
member with default wall type of ground
, now we make
it a wall
. Using the CppIterTools
the code is much more readable, and simpler to write.
The idea is each room we make will change the tile type from being wall
to ground
.
Continuing on, our rooms array will be generated by make_rooms
function. This function
will take in size of our map, as well as tiles on the map.
Now I could have written make_rooms
function in many different ways. However, I've choosen
to compartmentalize each sub-process used to make rooms into their own lambda
function.
So there are two lambda functions within make_rooms
function. change_tiles
which will
given a room
structure change the tiles
array to ground type for that part of the map
array. make_random_room
simply generates a randomly sized room, keep it constrained
with in map size and room size. Randomization is generated using C++'s <random>
header.
Then taking make_random_room
lambda functions, make a random room, check if it intersects with any
other room already in the array, if it intersects we reject that random room and generate a new one.
If the room does not intersect then we add it to the list of rooms. The intersection test against
rooms array is done using C++'s find_if
algorithm function.
After I have list of rooms, I loop through them and call change_tiles
to make sure room is visually
and structurally represented. And we return to our generate_map
function.
There are also few file local variables defined to constrain the size of rooms, and how many rooms we want per map generation.
And that's our "Simple Rooms Generator". There are many better algorithms out there. This one is very much dependent on just simple random number generator. No smarts required/applied.

Connecting all the rooms
Having a billion rooms you can't get to is not fun. A game must be fun. So, next up, connect_rooms
function. Similar to make_rooms
, we have few lambda functions that do the various sub tasks involved
in connecting two rooms.
Similar to make_rooms
's change_tiles
lambda, here we have make_hallway
lambda, which changes 1
tile
to tunnel
type, if tile is not already ground
. I know naming is inconsistent. Might fix that in future.
For rest of the this article assume hallway and tunnel are used interchangably.
Next we have two lambda that do same effective job, one makes vertical tunnels/hallways other makes horizontal tunnels/hallways. All the connections between rooms will have a 90 degree turn, if required.
Lastly we loop through all the rooms, and pass to previously mentioned lambdas, there is a random number generator here, to determine which room is primary. Notice we change the flip value between horizontal and vertical hallway calls. This is to ensure, that we don't start both tunnels at primary room.
Having done all this, we now have a series of rooms, we can walk around in. We can control how many rooms there are on a map, how big or small they can be. Amount of code is not all that much. Just organizing it makes a lot of difference.

Links
╣ GitHub Repo ╠═══
╣ Home ╠═══
╣ Prev: The entity and the map ╠═══
╣ Next: Player's field of view ╠═══