2
\$\begingroup\$

One of the steps for cell-based dungeon generation is deciding the amount and location of exits for each room. My current set up consists of the following:

  1. Define my exits. There are 15 types of room exits:

    • Left (L), Right (R), Top (T), Bottom (B).
    • Every non-redundant combinatoric of two directions (LT, TR, RB, BL, LR, TB)
    • The same for three directions (LTR, TRB, RBL, BLT)
    • All directions (LRTB)
  2. Create a list exitsList that contains the type of exit of that index, i.e. exitsList[0] = L means that our first room has a single exit: one to the left.

After creating my basic level layout and having my exit generation ready, it's time to go back to each room and assign its exits, and this is the part I'm having my doubts about.

Currently, my method for assigning rooms is to make a case check looping through each cell. Something such as:

for (each room){
    switch (exitsList[this_room]) {
        case L:
            place_exit_L;
            break;
        case LT:
            place_exit_L;
            place_exit_T;
            break;
        case TR:
        .
        .
        .
        case LTRB:
            place_exit_L;
            place_exit_T;
            place_exit_R;
            place_exit_B;
            break;
        default:
            return_error;
            break;
    }
}

While this can work, it seems very inelegant, and more importantly obnoxious to read by a human. I was able to refactor cases that shared the same type of exit by omitting breaks, for example:

case LTR:
    place_exit_R;
case LT
    place_exit_T;
case L
    place_exit_L;
    break;

But this seems rather arbitrary. I suspect there's a more efficient way to do this, or at least one that won't become a pain to read by other people if the number of exits somehow increases.

\$\endgroup\$
4
\$\begingroup\$

Use four attributes instead of one for expressing the types of exits for a room.

for (each room){
    if (room.has_left_exit){
        place_exit_L;
    }
    if (room.has_top_exit){
        place_exit_T;
    }
    ...
}
\$\endgroup\$
5
\$\begingroup\$

Building on the answer from @congusbonus, if you are committed to using a single variable in an array as you have shown, you can define each combination in such a way that encodes each direction as a single bit in a bitmask:

int T = 1;
int L = 2;
int B = 4;
int R = 8:

int TL = T | L;
...

for (each room){
    int exits = exitsList[this_room];
    if (exits & L == L){
        place_exit_L;
    }
    if (exits & T == T){
        place_exit_T;
    }
    if (exits & B == B){
        place_exit_B;
    }
    if (exits & R == R){
        place_exit_R;
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.