Skip to content

Instantly share code, notes, and snippets.

@paskozdilar
Created February 18, 2024 20:48
Show Gist options
  • Save paskozdilar/48d7532733ccd11144bb43fed953c334 to your computer and use it in GitHub Desktop.
Save paskozdilar/48d7532733ccd11144bb43fed953c334 to your computer and use it in GitHub Desktop.
Random Dungeon Generator - de-obfuscated
/**
* 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