Dungeon with rooms algorithm for Javascript ultimate begginer guide!

Victor Catalin Torac
5 min readSep 8, 2016

--

this picture is for illustration purposes only :)

Hello and welcome, in this tutorial i will guide you in the creation of an random dungeon generator with Javascript. Recently as an assignment for Free Code Camp i had to create an dungeon with random rooms and the first thing i noticed when i was doing my research is that all the writen tutorials out there are for medium to advanced programers.

Well, i wanted to create an tutorial for novice programers, like me, who are just beggining to grasp to beauty and the complexity of programing.The code i will use here is an extract from Peter Daily ‘s pen Roguelike Dungeon Crawler, that was kind enough to explain to me how everithing works.

In this tutorial we will be using ES6 destructuring a lot, so be sure to get familiar with the syntax before proceding.

The Begining

THE ALGORITHM and me!

The first thing we do is create an simple function for creating an 2d array of ‘empty’ cells, with a random opacity value (for styling).

Here is an empty CODEPEN template that has everithing preseted, split you’re screen and we can begin to code right away.

All the functions that we will create will have the same scope → createDungeon(), no nesting . Check the finished version if encounter any problems.

We now create our first room with coordinates.

Now we place our room inside the grid and make use of the id property we just created in the first room for visualization.

Our grid now should look like this

For convenience move the placeCells() inside the helper function segment right at the beginning of our createDungeon().

Here comes the tricky part. Using the first room as a seed, recursivley we then add rooms to the grid. Our function will take 4 parameters: the grid array, an array that will store all the rooms that we will create at each iteration and finaly 2 integers named counter and maxRooms.

//recursive function
const growMap = (grid, seedRooms, counter = 1, maxRooms = c.MAX_ROOMS) => {}

And when we will use it will look like this:

 growMap(grid, firstRoom);

but since our recursive takes an array as second parameter we use ES6 and say

//[firstRoom] creates an array with firstRoom as it's first value
growMap(grid, [firstRoom]);

What we want is a function that adds random rooms starting from the first seed that just passed.

Our createRoomsFromSeed will take an grid array, an object(room), and an default value for range.

const createRoomsFromSeed = (grid, {x, y, width, height}, range = c.ROOM_SIZE_RANGE) => {}

One way we could do that is to take the 4 cardinal directions(N,E,S,W) and place one room on each (edge +1 space) of the room(object) given to it, then using a forEach() we check if each room can be placed inside our grid, if so, placeCells() and then,

return the new grid and the array with the rooms just placed.

Why we need the array? because we will need the last room of the array for generating other rooms in the 4 directions.

const createRoomsFromSeed = (grid, {x, y, width, height}, range = c.ROOM_SIZE_RANGE) => {
const placedRooms = [];
roomValues = [{northRoom}, {southRoom}, {eastRoom}, {westRoom}]
roomValues.forEach(room => {
if (isValidRoomPlacement(grid, room)) {

grid = placeCells(grid, room);
placedRooms.push(room);
}
};//end forEach
return {grid, placedRooms};
}

Visual representation of the recursive iteration:

In the first iteration we generate 2 rooms and return them as an array.

In the second iteration we take the last room of the array and we generate 3 rooms, 2 of wich aren’t valid because one overlaps the origin room and the other is addiacent with the room on the right of the origin room.

In the third iteration we take the last room of the array that we return and we generate 2 rooms, one is good and the other is addiacent to one of the first rooms.

Inside it will make use of an function to check if isValidRoomPlacement(). Let’s define that function and put it in the helper function section.

const createDungeon = () => {
// HELPER FUNCTIONS FOR CREATING THE MAP
const isValidRoomPlacement...
const placeCells...
}

Now we just need a way of creating the 4 rooms and the function is ready to be used in our recursive.

Data visualization of the recursive iteration:

when subtracting -1 is because we dont want the new room to start from edge of the initial room.

In the first iteration using the first room x and y properties we generate 2 rooms and return them as an array.

In the second iteration we take the last room of the array(the south room) and make use of it’s x and y properties for generating new values for the 4 cardinal rooms.In the finished pen i have added some console logs that will print the values of the rooms created so just do the math and everithing will be clear.

Here is the complete function:

We create an id property for each room so that we can easily understand from where they were originated

The last thing we miss is writing our recursive.

Since it’s an recursive function we begin writing the break condition, and by doing so we must think of what will happen in the last and second-to-last iterations.

Look at the code below and everithing will be clear.We are putting 2 conditions:

  1. we have placed already number of rooms desired
  2. the seedRooms array is empty because in the second-to-last iteration we have tryed to place the rooms in all directions but that was not possible, so we are returning an empty array.
if (counter + seedRooms.length > maxRooms || seedRooms.length == 0) {
return grid;
}

And now the body of the function:

And we are finished now. I am adding an finished Codepen with all the code for reference.

Congratulations and thank you for you’re time.If you want to learn more on how to use it i have writen an tutorial on how to make an Random Dungeon Crawler using this algorithm.

If you enjoyed this article share it or leave it a like, the author greatly apreciates it :)

The End

--

--