Programmer / Web Developer

San Antonio, TX

January 1996

6 Mar 2019

Alright, please check out Part 1 if you haven't yet. Cool? Now we start moving on to an area where I am not 100% sure what I was thinking, but it works. It the previous article, we set up the dungeon and its parameters, so now it is time to actually build the thing one square at a time. I do this in a wonky way, probably quite suboptimal, but that is why there are two derps before I get to the code. I remember struggling with all of this quite a bit when I was originally writing it - some things just took a while to figure out.

```
for ($x = 1; $x <= 15; $x++) {
start_snake();
}
```

I called it start_snake because I imagined the code starting at a spot and snaking its way through the dungeon, creating squares as it went. Let's take a look at what that function does.```
function start_snake() {
global $cur_x, $cur_y, $max_x, $max_y, $map, $n, $s, $e, $w, $total_cells;
$door = find_next_cell();
if ($door) {
$map[$cur_x][$cur_y] = generate_new_cell($door);
$total_cells++;
}
}
```

Yeah, more globals. I am bad at this, I already told you this. I see now how to build this better without globals, by passing variables and such. Remember, most of this code was written 10ish years ago, when I was even more-er bad than now. But now we start going down the rabbit hole, as this function calls another one that we must go dig into.```
function find_next_cell() {
global $cur_x, $cur_y, $map, $n, $s, $e, $w;
$cur_cell = $map[$cur_x][$cur_y];
$found = 0; $door[8] = 0; $door[4] = 0; $door[2] = 0; $door[1] = 0;;
//FIND AN OPENING TO MOVE TO
if ($cur_cell >= $s) {
$door[8] = 1;
$cur_cell -= $s;
}
if ($cur_cell >= $e) {
$door[4] = 1;
$cur_cell -= $e;
}
if ($cur_cell >= $w) {
$door[2] = 1;
$cur_cell -= $w;
}
if ($cur_cell >= $n) {
$door[1] = 1;
}
```

So this is a little obtuse. I drag in more globals, and I know those directionals should be constants, then I figure out the numerical value of the current cell, which describes where the doors are in the cell. I set $found to 0, which is later set to a direction if I successfully fund the next cell. I also initialize some door array variables to 0, which means no door, but I check for those later. And by later I mean the very next thing I do. South is worth 8, so if the value of the cell is equal to or more than 8, then I know that the cell has a door to the South. If it does, I subtract 8 from the cell value and set the door[8] value to 1 to denote a door to the south. I repeat this for East (4), West (2), and North (1). Clear as mud? Moving on.```
//RANDOMLY CHOOSE A DIRECTION TO SEE IF THERE IS A DOOR THERE REPEAT UNTIL DOOR IS FOUND
$i = 0;
while (!$found) {
$rand1 = rand(0,3);
$rand = pow(2, $rand1);
if ($door[$rand] == 1) {
$found = $rand;
//FOUND IS THE DIRECTION OF THE DOOR
}
}
```

Now, while an appropriate door is not found, I loop through a random choice trying to find a door. Once I do find it, I set $found to it. I feel like there is amore elegant way to do all of this, especially with the $door[] array, but this is what I came up with.```
//MOVE CUR CELL TO THE DIRECTION OF THE DOOR
$new_y = $cur_y;
$new_x = $cur_x;
if ($found == $s) {
$new_y = $cur_y + 1;
} else if ($found == $n) {
$new_y = $cur_y - 1;
} else if ($found == $e) {
$new_x = $cur_x + 1;
} else if ($found == $w) {
$new_x = $cur_x - 1;
}
```

This bit is pretty simple. Depending on which direction the door is, I determine a new value for the cell the door is going to.```
//CHECK TO MAKE SURE THAT CELL DOESN'T ALREADY EXIST
if ($map[$new_x][$new_y] > 0) {
//CELL EXISTS, RECURSE AND DO IT OVER
return 0;
} else {
$cur_x = $new_x;
$cur_y = $new_y;
//NOW NEW CELL LOCATION IS $CUR_X $CUR_Y
//IT MUST HAVE A DOOR BACK TO THE PREVIOUS ROOM
if ($found == $s) { //PREVIOUS CELL HAS A DOOR SOUTH
return $n;
} else if ($found == $n) {
return $s;
} else if ($found == $w) {
return $e;
} else {
return $w;
}
}
```

I close out this process by first checking to see if the sqaure in that direction already has a cell created there. If it does, I return 0 which bubbles back up to the original start_snake loop and tries again. If the cell doesn't exist, I set the current coordinates as the new cell and return the value of the door back to the original cell, since each cell must have a door to the other. This value is returned into the $door variable back in the start_snake function which allows us to enter the if ($door) logic and get to the generate_new_cell function, which I will get into in the next article!Because I solved this problem in this way, it is hard to see another way because my mind keep going down this path. I think there is probably an easier way to do it, but this is what I have for now. Someday, maybe, after I write all about it and fully understand it, I'll try to optimize it. Mayeb when I rewrite the code in C# for the idle version of the Awesome Theory! Yeah, someday!Tags: Awesome Theory code dungeon generator functions globals random

Known Bugs

Tags list: top margin errors when only one item on a line