diff --git a/maze.c b/maze.c index 0f43ef5..644147a 100644 --- a/maze.c +++ b/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) {