1

So here's my base map:

enter image description here

(It won't necessarily be 5x5, just using this as an example.)

It's kinda boring the way it is with all the rooms connected. I want it to be more of a randomly generated labyrinth, where every room is accessible like so:

enter image description here

I've tried setting the hallways randomly:

foreach(Room r)
{
    r.northWall = randomBoolean();
    r.southWall = randomBoolean();
    r.eastWall = randomBoolean();
    r.westWall = randomBoolean();
}

But that almost always ends up with rooms that you're unable to go to, like this:

enter image description here

And often some rooms have no hallways at all. I tried saying each room must have a minimum of 2 hallways, but it still doesn't fix the problem that sometimes there an inaccessible areas.

How should I go about doing this? I'm not too worried about the speed, as long as it's not ridiculously slow (Some levels will have 100+ rooms).

Entity
  • 601
  • 7
  • 13
  • 3
    This is vague. Any generation of environments should be guided by the question of What are you intending to do with the environment you've generated? You could onnect each room to randomInt(1,4) other rooms in random directions until doing a flood fill hits all squares. Everything is guaranteed to be connected but depending on your use case, it might not be a very interesting map... – Anko Dec 09 '13 at 22:27
  • Wouldn't it make more sense to generate a mazethen place rooms at random points in the maze? There's loads of stuff on how you might do that around here. – War Dec 09 '13 at 22:25

3 Answers3

6

One option you could try is using a maze generation algorithm: http://en.wikipedia.org/wiki/Maze_generation_algorithm

Personally I like using a recursive backtracker method.

Start: all doorways closed and all nodes unvisited, pick one node to start with
step 1: visit current node and look at nearby unvisited nodes and randomly move to one of them (open the door) and repeat step 1
step 2: if no nearby nodes are unvisited, go back to the previous node and repeat step 1
step 3: if you return to the start node, your maze is complete
UnderscoreZero
  • 1,042
  • 6
  • 10
2

Spelunky's algorithm is descibed here:

http://tinysubversions.com/spelunkyGen/

The basic approach is to ensure connectivity between rooms in a path until a suitable distance is hit. Every other room can be totally random, or an algorithm can be applied to ensure there's a path from every room to the "main path" from start to end.

To generate the main path, and algorithm similar to Spelunky's makes a lot of sense. Limit the options of which paths you are allowed to generate to ensure a legal path.

Once you have a full main path, you can then fill in the side rooms and ensure connectivity. If you assign the main path rooms a unique "group" ID of 1, you can then assign each new room you create its own group ID (+1 to last group ID) if it has no hallways to existing rooms. If the new room does have a hallway to an existing room, use the ID of that existing room. If at the end of the process you have any rooms with IDs other than 1, they form a cluster of inaccessible rooms. You can then randomly pick any room in that cluster that borders another cluster and connect them, then assign all the rooms of one group with the other's (always picking the lower/older ID of the two). Repeat until every room has an ID of 1. This ensures that all rooms are connected while keeping the assurance that the main path is still connected, creating dead-ends. If you want to allow loops or such then you can increase the number of hallways you create when isolated groups are detected.

This is just one way to do it. There are many, many more.

Sean Middleditch
  • 41,807
  • 4
  • 89
  • 132
0

This problem reduces to finding a spanning subgraph of your room grid, so any spanning subgraph algorithm will work. This is a well-solved problem, and there are many super-fast algorithms to choose from.

In particular, you could find a spanning tree (using any of these algorithms, for example), and then add a few extra connections if you want loops as in your example above.

DMGregory
  • 134,153
  • 22
  • 242
  • 357