1

I am attempting to place rooms on an ASCII screen, and then use Prim's algorithm to "fill" the space between rooms with maze, but without actually breaking into the rooms. I have been tinkering for a few hours, and I can't figure out a way to stop my algorithm from breaking into my rooms.

Can anyone help me? I'm pretty lost. I'm practicing map generation techniques, and this is my 5th one I'm on. No, I don't want to do it another way, I simply want to do it this way - but right.

Below is both a photo of my current output with rooms, my current output without rooms, and a link to the relevant source code (AKA the Prim's algorithm section). Thanks again if you can actually help me!

Note: All the opposite method does is figure out which cell the "parent" cell is, and determine direction based off of that. So if parent cell's x value is 7, and the child's x value is 6, then it know that's the new child.

start = new Point(x,y, null);
map[start.x][start.y] = Tile.STAIRS_DOWN;

for(int nx = -1; nx <= 1; nx++){
    for(int ny = -1; ny <= 1; ny++){
        if((nx == 0 && ny == 0) || (nx != 0 && ny != 0)){
            continue;
        }
        try{
            if(map[start.x + nx][start.y + ny] == Tile.FLOOR){
                continue;
            }
            frontier.add(new Point(start.x+nx, start.y + ny, start));
        }
        catch(Exception e){
            continue;
        }
    }
}

Point last = null;
while(!frontier.isEmpty()){
    Point cu = frontier.remove(RandomGen.rand(0, frontier.size() - 1));
    Point op = cu.opposite();
    try{
        if((map[cu.x][cu.y] == Tile.WALL) && (map[op.x][op.y] == Tile.WALL)){
            for (int bx = -1; bx <= 1; bx++)
                for (int by = -1; by <= 1; by++) {
                    boolean failed = false;
                    if (bx == 0 && by == 0 || bx != 0 && by != 0)
                        continue;
                    try {
                        if(map[op.x + bx][op.y + by] == Tile.FLOOR){
                            break;
                        }
                        last = op;
                        if(!failed){
                        map[cu.x][cu.y] = Tile.FLOOR;
                        map[op.x][op.y] = Tile.FLOOR;
                        frontier.add(new Point(op.x + bx, op.y + by, op));
                        }
                    }
                    catch(Exception e){
                        continue;
                    }
                }
        }
    }
    catch(Exception e){}
}

Without Rooms

With Rooms

K. Kennedy
  • 21
  • 6
  • Prim's algorithm (I assume you're using it with random weights) finds a tree in a graph. To avoid getting edges you don't want, you must arrange for them to be missing from the original graph. I.e. you should include only edges that don't break into rooms. Then Prim can't possibly give you an edge you don't want. – Gene Mar 17 '17 at 04:53
  • @Gene since it's a tile map and I have to traverse 2 tiles forward each time, it seems really hard to not break into the rooms. Is there a way I can change that? – K. Kennedy Mar 17 '17 at 12:39
  • You're making the common beginner's mistake of trying to map a problem onto a data structure rather than finding the right data structure for a problem. Stop thinking about rooms and moves. Prim's is about graphs. Think about a graph of nodes and edges that covers a grid with "legal" edges (i.e. ones that don't penetrate rooms) that correspond to acceptable moves. Draw a few to get the details in your head. Now that you understand the graphs, design a data structure that represents them efficiently. That might not be (probably isn't) a 2d array of enum values. _Now_ run Prim's. – Gene Mar 17 '17 at 13:23
  • @Gene I'll try that and get back to you! I'm a student and I haven't studied graph theory yet, so I'm sort of...muddling through on my own. I'm doing this because I want to practice graph theory, so if I'm doing it backwards, then that's bad. Thanks. – K. Kennedy Mar 17 '17 at 13:29
  • @Gene Okay, I haven't actually implemented it yet, but I'm pretty sure I figured out the solution to my problem using the method you described. I think the problem with my code is that I'm adding the tile NEXT to my points to the frontier, when I should be adding the tile +1 away, because there is supposed to be a solid wall between. Basically, my frontier call is wrong. – K. Kennedy Mar 17 '17 at 15:30

1 Answers1

0

Solved: I needed to check my forward facing corners for open spaces. So if I'm going "east" then I need to check Northeast and Southeast tiles as well, or else I will potentially burrow into the rooms.

K. Kennedy
  • 21
  • 6