Sidewinder maze instead of dfs
This commit is contained in:
parent
4fdd6f95e9
commit
6eaf0d9961
101
maze.c
101
maze.c
@ -34,6 +34,13 @@
|
||||
#define MAZEENDGAP (MAZESIZE / 5)
|
||||
#define HSCALE 1.5
|
||||
#define PAINTINGODDS 20
|
||||
// Some arbitrarily large number, up to you
|
||||
#define MAZEHRAND 100
|
||||
// The horizontal choice will be this out of MAZEHRAND.
|
||||
// So, if MAZEHRAND is 100, setting this to 80 will mean
|
||||
// an 8 / 10 chance to go horizontal
|
||||
#define MAZEHBIAS 60
|
||||
#define PRINTMAZE
|
||||
|
||||
// Maze grows in the positive direction
|
||||
#define MAZENORTH 1
|
||||
@ -157,69 +164,29 @@ void maze_generate(uint8_t *maze, int size, struct vec2i *start,
|
||||
for (int i = 0; i < mazesquare; i++) {
|
||||
maze[i] = MAZENORTH | MAZEEAST;
|
||||
}
|
||||
int *mazestack;
|
||||
mallocordie(mazestack, sizeof(int) * mazesquare);
|
||||
for (int i = 0; i < size * size; i++) {
|
||||
mazestack[i] = -1;
|
||||
}
|
||||
// Push current cell onto stack, mark as visited
|
||||
|
||||
start->x = rand() % size;
|
||||
start->y = rand() % size;
|
||||
int x = start->x;
|
||||
int y = start->y;
|
||||
int mazetop = 0;
|
||||
int maxmazetop = 0;
|
||||
STACKPUSH(mazestack, mazetop, x + y * size);
|
||||
maze[x + y * size] |= MAZEVISIT;
|
||||
uint8_t visitable[4];
|
||||
int visittop = 0;
|
||||
|
||||
// Now let's make a maze!
|
||||
while (mazetop) {
|
||||
// The end of the maze is the furthest into the stack we go. This should
|
||||
// somewhat maximize the complexity of start to finish?
|
||||
if (mazetop > maxmazetop) {
|
||||
// end->x = x;
|
||||
// end->y = y;
|
||||
maxmazetop = mazetop;
|
||||
}
|
||||
mazetop--;
|
||||
visittop = 0;
|
||||
x = mazestack[mazetop] % size;
|
||||
y = mazestack[mazetop] / size;
|
||||
if (x > 0 && !maze_visited(maze, x - 1, y, size)) {
|
||||
visitable[visittop++] = DIRWEST;
|
||||
}
|
||||
if (x < size - 1 && !maze_visited(maze, x + 1, y, size)) {
|
||||
visitable[visittop++] = DIREAST;
|
||||
}
|
||||
if (y > 0 && !maze_visited(maze, x, y - 1, size)) {
|
||||
visitable[visittop++] = DIRSOUTH;
|
||||
}
|
||||
if (y < size - 1 && !maze_visited(maze, x, y + 1, size)) {
|
||||
visitable[visittop++] = DIRNORTH;
|
||||
}
|
||||
// You can generate a random location!
|
||||
if (visittop) {
|
||||
// Readd ourselves, we're moving
|
||||
STACKPUSH(mazestack, mazetop, x + y * size);
|
||||
uint8_t dir = visitable[rand() % visittop];
|
||||
struct vec2i movedir = dirtovec(dir);
|
||||
int nx = x + movedir.x;
|
||||
int ny = y + movedir.y;
|
||||
// Trust that the visitable array is always valid
|
||||
if (dir == DIREAST) { // Tear down east wall
|
||||
// Extremely simple sidewinder algorithm. Because the maze grows northeast, we
|
||||
// actually have to start from the end and work backwards
|
||||
for (int y = size - 1; y >= 0; y--) {
|
||||
if (y == size - 1) {
|
||||
for (int x = 0; x < size - 1; x++) {
|
||||
maze[x + y * size] &= ~MAZEEAST;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int xs = 0;
|
||||
for (int x = 0; x < size; x++) {
|
||||
// If we decide to stop (or it's the end), find a place in our
|
||||
// current span to carve north
|
||||
if ((x == size - 1) || ((rand() % MAZEHRAND) > MAZEHBIAS)) {
|
||||
maze[xs + (rand() % (x - xs + 1)) + y * size] &= ~MAZENORTH;
|
||||
xs = x + 1;
|
||||
} else {
|
||||
maze[x + y * size] &= ~MAZEEAST;
|
||||
} else if (dir == DIRWEST) { // Move left and tear down east wall
|
||||
maze[(x - 1) + y * size] &= ~MAZEEAST;
|
||||
} else if (dir == DIRNORTH) { // tear down north wall
|
||||
maze[x + y * size] &= ~MAZENORTH;
|
||||
} else if (dir == DIRSOUTH) { // move down and tear down north wall
|
||||
maze[x + (y - 1) * size] &= ~MAZENORTH;
|
||||
}
|
||||
// Push onto stack and set visited
|
||||
STACKPUSH(mazestack, mazetop, nx + ny * size);
|
||||
maze[nx + ny * size] |= MAZEVISIT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,10 +196,22 @@ void maze_generate(uint8_t *maze, int size, struct vec2i *start,
|
||||
} while (abs(end->x - start->x) < MAZEENDGAP &&
|
||||
abs(end->y - start->y) < MAZEENDGAP);
|
||||
|
||||
eprintf("Maze generate: %d,%d -> %d,%d maxdepth: %d\n", start->x, start->y,
|
||||
end->x, end->y, maxmazetop);
|
||||
#ifdef PRINTMAZE
|
||||
char line[MAZESIZE * 4]; // IDK, just in case
|
||||
// -1 because we draw the top line
|
||||
for (int y = -1; y < size; y++) {
|
||||
for (int x = size - 1; x >= 0; x--) {
|
||||
line[x * 2] = (y == -1 || maze[x + y * size] & MAZENORTH) ? '_' : ' ';
|
||||
line[x * 2 + 1] =
|
||||
(y == -1 || (maze[x + y * size] & MAZEEAST) == 0) ? ' ' : '|';
|
||||
}
|
||||
line[size * 2] = 0;
|
||||
eprintf("|%s\n", line);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(mazestack);
|
||||
eprintf("Maze generate: %d,%d -> %d,%d\n", start->x, start->y, end->x,
|
||||
end->y);
|
||||
}
|
||||
|
||||
// int rand_painting(int size) {
|
||||
|
Loading…
Reference in New Issue
Block a user