# Generating 'Specially' shaped rooms for a Dungeon

I've made a fairly simple dungeon generator but now I want to expand on it so that I can procedurally generate a dungeon with irregular shaped rooms. I don't just want any old crazy shapes popping up though, I want to be able to have room types that follow a certain pattern but ultimately have random sizes. I just don't have a clue how to generate rooms that aren't just square.

I have an idea of how to merge squares together to make rooms comprised of other rooms, but I'm more interested in how to get hexagon and octagon shaped rooms, or doughnut-like rooms. My code for generating square rooms is:

    public static char[,] GetSquareRoom(int width, int height)
{
char[,] roomLayout_Square;

roomLayout_Square = new char[width, height];

for (int x = 0; x < roomLayout_Square.GetLength(0); x++)
for (int y = 0; y < roomLayout_Square.GetLength(1); y++)
if (x == 0 || y == 0 || x == width - 1 || y == height - 1)
roomLayout_Square[x, y] = '#';
else
roomLayout_Square[x, y] = '.';

return roomLayout_Square;
}


I would like to create more functions like this that will accept a few variables so I can create specific variations of these room-types, so I can input specific number and randomly generated values alike.

:)

• Yet again I thought I'd share a vaguely related link: Irregular Shaped Rooms (from roguebasin). If anything, it may help as inspiration. – Roflo Oct 22 '15 at 14:58
• @Roflo - I was actually looking at this yesterday, a very neat way of generating completely irregular rooms. A few of these might actually look good in a procedurally generated dungeon, no? Or perhaps the method can be altered to create somewhat less irregular shapes? Your knowledge of vaguely related links is endless, thank you :) – ImperialCoder Oct 23 '15 at 10:35

You can create a room that is in the shape of a regular convex polygon with arbitrary sides, size and rotation.
Steps:

1. Draw walls by picking pairs of points around a circle and linearly interpolating between them. The number of pairs should equal the number of sides of the shape. You will need to use trig for this.
2. Create a floor by filling the shape using some sort of fill algorithm.

You can then create a doughnut shaped room by subtracting a smaller generated room from the center of a larger generated room. You should keep the walls of the smaller generated room though.

Since I found this interesting I went ahead and tried implementing it myself. I would recommend not looking at my code until you have tried to write it yourself though.

public static char[,] RegConvexPolyRoom(int sides, double radius, double rotation)
{
// convert the rotation degrees to radians.
rotation *= Math.PI / 180.0;

// make an array size that is sure to fit the room.
int roomSize = (int) Math.Ceiling(radius*2) + 1;

char[,] room = new char[roomSize, roomSize];

// first we must create the walls of the room.
double rchange = (Math.PI * 2.0) / sides;
for (double r = 0; r < Math.PI * 2; r += rchange)
{
// define first point.

// define second point (rotated 1 iteration further).
double p2_x = radius + Math.Cos(r + rotation + rchange) * radius;
double p2_y = radius + Math.Sin(r + rotation + rchange) * radius;

// get distance between the two points.
double len = Math.Sqrt(Math.Pow(p2_x - p1_x, 2) + Math.Pow(p2_y - p1_y, 2));

// linearly interpolate between the two points and place walls between them.
for (double i = 0; i < 1; i += 1.0 / len)
{
int place_x = (int) Math.Round((1 - i) * p1_x + i * p2_x);
int place_y = (int) Math.Round((1 - i) * p1_y + i * p2_y);

room[place_y, place_x] = '#';
}
}

// now we have to fill the room with a floor.
// this is done using something similar to a scanline algorithm.
for (int scan = 0; scan < roomSize; scan++)
{
int left_x = -1;
int right_x = -1;
bool spaceDetected = false;

for (int i = 0; i < roomSize; i++)
{
if (room[scan, i] == '#')
{
if (!spaceDetected)
left_x = i;
else
{
right_x = i;
break;
}
}
else if (left_x != -1)
spaceDetected = true;
}

if (right_x != -1)
{
for (int i = left_x + 1; i < right_x; i++)
{
room[scan, i] = '.';
}
}
}

return room;
}


Here is a hexagonal room generated with the above method:

     ##############
#.............#
#..............#
#...............#
#................#
#.................#
#...................#
##...................#
#.....................#
#.......................#
#.......................#
#.......................#
#.....................#
#...................##
#..................#
#.................#
#...............##
#...............#
#..............#
#.............#
##############

• Thanks for the answer. The ring room implementation seems really interesting though, can arrays be altered like that? I thought to do that with the square rooms I have generated, i.e.: create large square room, then small square room, and then subtract the small room from the large one's centre but I have no idea how to do this when working with arrays. – ImperialCoder Oct 22 '15 at 12:37
• Nevermind, managed to create a nice 'hole room' function that takes room width and height, and hole width and height, but all the time allowing at least a 2-cell path width round the hole. A couple of horrible if statements though. Thanks! – ImperialCoder Oct 22 '15 at 13:45