- Find a random location in the map and create a rectangular room.
- Search random locations until you find a wall
- Check that a new room will fit in the designated area
- Dig the new room
- Repeat steps 2 to 4 until maximum number of rooms reached or no viable spaces can be found
The issues seems to be somewhere in the middle 3 steps. As I have no idea where the problem come from I will provide complete listing of the scripts I use.
Spoiler
// scr_map_gen(width, height, seed, max number of rooms)
//
// This script will generate a dungeon map.
//
// args: width - The width in cells
// height - The height in cells
// seed - The seed for the rng
// rooms - The maximum number of rooms to create
//
// returns: map - A 2D array containing references
// to the type of terrain in each
// cell.
/////////////////////////////////////////////////////
// room array
room_type[0] = 'square';
room_type[1] = 'corridor';
room_type[2] = 'octogon';
room_type[3] = 'corridor';
room_type[4] = 'arena';
room_type[5] = 'cave';
room_type[6] = 'pool';
room_type[7] = 'lavapit';
room_type[8] = 'temple';
// Terrain types
// W - Standard Wall
// . - Standard Floor
// D - Door
// C - Cave Wall
// , - Cave Floor
// S - Shrine
// P - Pool
// L - Lava
width = argument[0];
height = argument[1];
seed = argument[2];
rooms = argument[3];
// Set the seed for the map
random_set_seed(seed);
// Create the initial map
for(i = 0; i < width; i += 1)
{
for(j = 0; j < height; j += 1)
{
global.map[i,j] = '#';
}
}
// Create the first room
selected = false;
while(!selected)
{
// Locate the first room
pos_x = irandom_range(1,width);
pos_y = irandom_range(1,height);
// Choose the size
w = irandom_range(4,7);
h = irandom_range(4,7);
clear = true;
// Check the room can be built here
for(i = pos_x - 1; i <= pos_x + w; i += 1)
{
for(j = pos_y - 1; j <= pos_y + h; j += 1)
{
if(i > width - 1 ||
j > height - 1)
{
clear = false
}
else if(global.map[i,j] != '#')
{
clear = false;
}
if(!clear) break;
}
if(!clear) break;
}
if(!clear)
selected = false;
else
selected = true;
}
// Build the room
for(i = pos_x - 1; i <= pos_x + w; i += 1)
{
global.map[i,pos_y - 1] = 'W';
global.map[i,pos_y + h] = 'W';
}
for(j = pos_y; j <= pos_y + h; j += 1)
{
global.map[pos_x - 1,j] = 'W';
global.map[pos_x + w,j] = 'W';
}
for(i = pos_x; i < pos_x + w; i += 1)
{
for(j = pos_y; j < pos_y + h; j += 1)
{
global.map[i,j] = '.';
}
}
// Loop through room generation
done = false;
room_count = 1;
while(!done)
{
tries = 0;
found_room = false
// Choose type of room
type = room_type[irandom(8)];
// Find a wall
while(!found_room)
{
tries += 1;
door_x = irandom_range(1,width - 1);
door_y = irandom_range(1,height - 1);
if(global.map[door_x,door_y] == 'W')
{
dir = -1;
// Find the direction
for(i = 0; i < 4; i += 1)
{
switch(i)
{
case 0:
if(global.map[door_x,door_y-1] == '#')
dir = 0;
break;
case 1:
if(global.map[door_x-1,door_y] == '#')
dir = 1;
break;
case 2:
if(global.map[door_x,door_y+1] == '#')
dir = 2;
break;
case 3:
if(global.map[door_x+1,door_y] == '#')
dir = 3;
break;
}
if(dir > -1)
break;
}
if( dir > -1)
{
//determine the room size based on it's type
switch(type)
{
case 'square':
w = irandom_range(4,7);
h = irandom_range(4,7);
break;
case 'corridor':
hv = irandom(1);
switch(hv)
{
case 0:
w = irandom_range(4,7);
h = 1;
case 1:
w = 1;
h = irandom_range(4,7);
}
break;
case 'octogon':
w = irandom_range(5, 10);
h = w;
break;
case 'arena':
w = irandom_range(5, 10);
h = irandom_range(5, 10);
break;
case 'cave':
w = irandom_range(4,12);
h = irandom_range(4,12);
break;
case 'pool':
w = irandom_range(3, 7);
h = irandom_range(3, 7);
break;
case 'lavapit':
w = irandom_range(3, 7);
h = irandom_range(3, 7);
break;
case 'temple':
w = 5;
h = 5;
break;
default:
return false;
}
// Check the room will fit
found_room = scr_check_room(type, door_x, door_y, dir, w, h);
if(found_room)
{
// Get the top left
switch(dir)
{
case 0:
dx = (w + 2)/2;
cx = door_x - dx;
cy = door_y - (h + 2);
break;
case 1:
dy = (h + 2)/2;
cy = door_y - dy;
cx = door_x;
break;
case 2:
dx = (w + 2)/2;
cx = door_x - dx;
cy = door_y;
break;
case 3:
dy = (h + 2)/2;
cy = door_y - dy;
cx = door_x - (w + 2);
break;
}
//scr_dig_room(type, w, h, cx, cy, door_x, door_y);
tries = 0;
}
}
}
if(tries >= 10000)
{
done = true;
break;
}
}
room_count += 1;
if(room_count == rooms)
done = true;
}
Spoiler
// scr_dig_room(type, width, height, locationx, locationy, doorx, doory)
//
// N.B. the width and height do not take into account the walls
//
// returns the map
///////////////////////////////////////////////////////////////
type = argument[0];
width = argument[1];
height = argument[2];
px = argument[3];
py = argument[4];
doorx = argument[5];
doory = argument[6];
// room array
room_type[0] = 'square';
room_type[1] = 'corridor';
room_type[2] = 'octogon';
room_type[3] = 'corridor';
room_type[4] = 'arena';
room_type[5] = 'cave';
room_type[6] = 'pool';
room_type[7] = 'lavapit';
room_type[8] = 'temple';
// Terrain types
// W - Standard Wall
// . - Standard Floor
// D - Door
// C - Cave Wall
// , - Cave Floor
// S - Shrine
// P - Pool
// L - Lava
// Switch to the correct room type
switch(type)
{
case 'square':
case 'corridor':
case 'arena':
case 'cave':
case 'pool':
case 'lavapit':
case 'temple':
for(i = px - 1; i <= px + width; i += 1)
{
if(global.map[i,py-1] != 'D')
global.map[i,py-1] = 'W';
if(global.map[i,py + height] != 'D')
global.map[i,py + height] = 'W';
}
for(j = py; j < py + height; j += 1)
{
if(global.map[px-1,j] != 'D')
global.map[px-1,j] = 'W';
if(global.map[px + width,j] != 'D')
global.map[px + width,j] = 'W';
}
for(i = px; i < px + width; i += 1)
{
for(j = py; j < py + height; j += 1)
{
global.map[i,j] = '.';
}
}
break;
case 'octogon':
qwidth = width div 3;
for(i = px + qwidth; i <= px + (width - qwidth) + 1; i += 1)
{
if(global.map[i, py] != 'D')
{
global.map[i, py] = 'W';
}
if(global.map[i, py + height + 1] != 'D')
{
global.map[i, py + height + 1] = 'W';
}
}
for(i = py + qwidth; i <= py + (height - qwidth) + 1; i += 1)
{
if(global.map[px, i] != 'D')
{
global.map[px, i] = 'W';
}
if(global.map[px + width + 1, i] != 'D')
{
global.map[px + width + 1, i] = 'W';
}
}
mirror = px + width;
for(i = px + 1; i <= px + (width/2); i += 1)
{
for(j = py + 1; j <= py + height; j += 1)
{
if(j <= py + qwidth || j >= py + height - qwidth)
{
if(gloabl.map[i,j] != 'D') gloabl.map[i,j] = 'W';
if(gloabl.map[mirror, j] != 'D') gloabl.map[mirror,j] = 'W';
}
else
{
if(gloabl.map[i,j] != 'D') gloabl.map[i,j] = '.';
if(gloabl.map[mirror, j] != 'D') gloabl.map[mirror,j] = '.';
}
}
mirror -= 1;
}
break;
}
// place the door
gloabl.map[doorx,doory] = 'D';
Spoiler
// scr_check_room(room type, x location, y location, direction, width, height)
//
// Checks whether the given room can fit in the grid
// at the given location.
//
// args: room type - type of the room
// x location - x location of the door to the room
// y location - y location of the door to the room
// direction - direction in which we will dig the room
// width - width of the room
// height - height of the room
//
// return: found - whether or not the room can fit
//
////////////////////////////////////////////////////////////////////
type = argument[0];
door_x = argument[1];
door_y = argument[2];
dir = argument[3];
w = argument[4];
h = argument[5];
// room array
room_type[0] = 'square';
room_type[1] = 'corridor';
room_type[2] = 'octogon';
room_type[3] = 'corridor';
room_type[4] = 'arena';
room_type[5] = 'cave';
room_type[6] = 'pool';
room_type[7] = 'lavapit';
room_type[8] = 'temple';
wall_w = w + 2;
wall_h = h + 2;
// check the area in the given direction
switch(dir)
{
case 0:
dx = wall_w/2;
cx = door_x - dx;
cy = door_y - wall_h;
if(cx < 0 || cy < 0) return false;;
for(i = 0; i < wall_w; i += 1)
{
for(j = 0; j < wall_h; j += 1)
{
if(global.map[cx + i, cy + j] != '#' ||
global.map[cx + i, cy + j] != 'W' ||
global.map[cx + i, cy + j] != 'C' ||
global.map[cx + i, cy + j] != 'D')
{
return false;
}
}
}
break;
case 1:
dy = wall_h/2;
cy = door_y - dy;
cx = door_x;
if(cx < 0 || cy < 0) return false;;
for(i = 0; i < wall_w; i += 1)
{
for(j = 0; j < wall_h; j += 1)
{
if(global.map[cx + i, cy + j] != '#' ||
global.map[cx + i, cy + j] != 'W' ||
global.map[cx + i, cy + j] != 'C' ||
global.map[cx + i, cy + j] != 'D')
{
return false;
}
}
}
break;
case 2:
dx = wall_w/2;
cx = door_x + dx;
cy = door_y;
if(cx < 0 || cy < 0) return false;;
for(i = 0; i < wall_w; i += 1)
{
for(j = 0; j < wall_h; j += 1)
{
if(global.map[cx + i, cy + j] != '#' ||
global.map[cx + i, cy + j] != 'W' ||
global.map[cx + i, cy + j] != 'C' ||
global.map[cx + i, cy + j] != 'D')
{
return false;
}
}
}
break;
case 3:
dy = wall_h/2;
cy = door_y + dy;
cx = door_x - wall_w;
if(cx < 0 || cy < 0) return false;;
for(i = 0; i < wall_w; i += 1)
{
for(j = 0; j < wall_h; j += 1)
{
if(global.map[cx + i, cy + j] != '#' ||
global.map[cx + i, cy + j] != 'W' ||
global.map[cx + i, cy + j] != 'C' ||
global.map[cx + i, cy + j] != 'D')
{
return false;
}
}
}
break;
default:
return false;
}
scr_dig_room(type, w, h, cx, cy, door_x, door_y);
return true;
The remainder of the program simply writes the result to a text file just so I can see if it works. The issue is that all that happens is the first room is created. Following on from that there is nothing.
Thanks to anyone who can help. I apologise if the solution turns out to be really simple I recently overhauled all of this code because I discovered that GML does handle arrays like most programming languages and they cannot be passed as arguments or returned from functions.
Edited by this_is_phil, 12 July 2012 - 03:09 PM.












