Created
February 18, 2024 20:48
-
-
Save paskozdilar/48d7532733ccd11144bb43fed953c334 to your computer and use it in GitHub Desktop.
Random Dungeon Generator - de-obfuscated
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* NetHack-style dungeon generator. | |
* | |
* De-obfuscated version of: | |
* https://gist.github.com/munificent/b1bcd969063da3e6c298be070a22b604 | |
* | |
* Modify the #define parameters to change the dungeon and cave size. | |
*/ | |
#include <time.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#define MAP_HEIGHT 40 | |
#define MAP_WIDTH 80 | |
#define ITERATIONS 1000 | |
#define CAVE_MIN_WIDTH 5 | |
#define CAVE_MAX_WIDTH 14 | |
#define CAVE_MIN_HEIGHT 3 | |
#define CAVE_MAX_HEIGHT 8 | |
int map[MAP_HEIGHT][MAP_WIDTH]; | |
int randrange(int, int); | |
void cave(int); | |
int main(int argc, const char* argv[]) { | |
/* Initialize RNG */ | |
srand((int) time(NULL)); | |
/* Initialize map */ | |
for (int y = 0; y < MAP_HEIGHT; y++) { | |
for (int x = 0; x < MAP_WIDTH; x++) { | |
map[y][x] = ' '; | |
} | |
} | |
/** | |
* Attempt to draw a cave a bunch of times. | |
* | |
* Cave drawing works probabilistically - it randomly selects a rectangle | |
* in the map, and checks if its adjacent to any other cave. | |
* If yes, it draws the new cave, and if not, it cancels the process. | |
**/ | |
for(int iteration = 0; iteration < ITERATIONS; iteration++) { | |
cave(iteration); | |
} | |
/* Print map, replacing corners '!' with walls '#' */ | |
for (int y = 0; y < MAP_HEIGHT; y++) { | |
for (int x = 0; x < MAP_WIDTH; x++) { | |
int c = map[y][x]; | |
putchar(c == '!' ? '#' : c); | |
} | |
printf("\n"); | |
} | |
return 0; | |
} | |
int randrange(int a, int b) { | |
return a + (rand() % (b - a)); | |
} | |
void cave(int iteration) { | |
/* Random cave size (w/o walls): 5x3 -> 14x8 */ | |
int width = randrange(CAVE_MIN_WIDTH, CAVE_MAX_WIDTH + 1); | |
int height = randrange(CAVE_MIN_HEIGHT, CAVE_MAX_HEIGHT + 1); | |
/* Random cave position (w/o walls) */ | |
int column = randrange(1, MAP_WIDTH - width - 1); | |
int row = randrange(1, MAP_HEIGHT - height - 1); | |
/* If room (w/ walls) overlaps with another room (w/o walls), skip */ | |
for (int y = row - 1; y < row + height + 2; y++) { | |
for (int x = column - 1; x < column + width + 2; x++) { | |
if (map[y][x] == '.') { | |
return; | |
} | |
} | |
} | |
/** | |
* If not first iteration, check if cave has an adjacent cave. | |
* If it has an adjacent cave, record coordinates of the door. | |
**/ | |
int adjacent_count = 0; | |
int door_column, door_row; | |
if (iteration > 0) { | |
for (int y = row - 1; y < row + height + 2; y++) { | |
for (int x = column; x < column + width + 2; x++) { | |
int vertical_wall = x < column || x > column + width; | |
int horizontal_wall = y < row || y > row + height; | |
if ((vertical_wall ^ horizontal_wall) && map[y][x] == '#') { | |
adjacent_count++; | |
if (randrange(0, adjacent_count) == 0) { | |
door_column = x; | |
door_row = y; | |
} | |
} | |
} | |
} | |
if (adjacent_count == 0) { | |
return; | |
} | |
} | |
/** | |
* Fill out the cave: | |
* - inside is '.' | |
* - walls are '#' | |
* - corners are '!' | |
* | |
* The '!' corners are necessary for adjacency detection above. | |
* It will be replaced with '#' during the printing. | |
**/ | |
for (int y = row - 1; y < row + height + 2; y++) { | |
for (int x = column - 1; x < column + width + 2; x++) { | |
int vertical_wall = x < column || x > column + width; | |
int horizontal_wall = y < row || y > row + height; | |
if (vertical_wall && horizontal_wall) { | |
map[y][x] = '!'; // why? | |
} else if (vertical_wall ^ horizontal_wall) { | |
map[y][x] = '#'; | |
} else { | |
map[y][x] = '.'; | |
} | |
} | |
} | |
/** | |
* If not first iteration, create open or closed doors in recorded | |
* coordinates. | |
*/ | |
if (adjacent_count > 0) { | |
if (randrange(0, 2) == 0) { | |
map[door_row][door_column] = '\''; | |
} else { | |
map[door_row][door_column] = '+'; | |
} | |
} | |
/** | |
* Place random stuff in rooms. | |
* | |
* If first iteration, place player character: | |
* @ | |
* | |
* Otherwise, print 1..6 of the characters with probability: | |
* | |
* 25%: $ | |
* 75%: ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ | |
*/ | |
int y = randrange(row, row + height); | |
int x = randrange(column, column + width); | |
if (iteration == 0) { | |
map[y][x] = '@'; | |
} else for (int i = 0; i < randrange(1, 7); i++) { | |
if (randrange(0, 4) == 0) { | |
map[y][x] = '$'; | |
} else { | |
map[y][x] = randrange('A', '~' + 1); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment