Created
July 11, 2018 18:17
-
-
Save solenum/d48d9bd57c738701d1d5b3523d2099a4 to your computer and use it in GitHub Desktop.
Worlds worst RL dungeon generator
This file contains hidden or 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
/* | |
Generates a primitive dungeon/cave system thingy | |
by exezin, public domain, do what you want. | |
*/ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <time.h> | |
#include <math.h> | |
#define MAX(x, y) (((x) > (y)) ? (x) : (y)) | |
#define MIN(x, y) (((x) < (y)) ? (x) : (y)) | |
#define MAP_WIDTH 120 | |
#define MAP_HEIGHT 40 | |
#define CAVE_MIN 100 // min cave iterations | |
#define CAVE_MAX 250 // max cave iterations | |
#define CAVES 10 // total amount of caves to generate | |
#define FREESTANDING_BIAS 2 // set to 2 3 or 4 | |
char map[MAP_HEIGHT][MAP_WIDTH] = {0}; | |
typedef struct { | |
int x, y; | |
} vec2_t; | |
vec2_t sources[CAVES] = {0}; | |
// replace this with a generic min max clamp function lol | |
static inline int safe_index(int x, int y) | |
{ | |
x = MAX(0, MIN(MAP_WIDTH, x)); | |
y = MAX(0, MIN(MAP_HEIGHT, y)); | |
return map[y][x]; | |
} | |
// generates a random int | |
int random_int(int from, int to) | |
{ | |
return from + rand() % (to - from + 1); | |
} | |
// generates a random room at x y of size count | |
void place_room(int x, int y, int count) | |
{ | |
if (count == 0) | |
return; | |
if (y > 0 && y < MAP_HEIGHT-1) { | |
if (x > 0 && x < MAP_WIDTH-1) { | |
map[y][x] = 1; | |
} | |
} | |
x += random_int(-1, 1); | |
y += random_int(-1, 1); | |
count--; | |
place_room(x, y, count); | |
} | |
int main() | |
{ | |
srand(time(NULL)); | |
// generate caves | |
for (int i=0; i<CAVES; i++) { | |
sources[i].x = random_int(1, MAP_WIDTH-1); | |
sources[i].y = random_int(1, MAP_HEIGHT-1); | |
place_room(sources[i].x, sources[i].y, random_int(CAVE_MIN, CAVE_MAX)); | |
} | |
// make sure all caves are connected | |
int i=CAVES; | |
while (i) { | |
vec2_t source_a = sources[i]; | |
vec2_t source_b = sources[--i]; | |
float x = source_a.x; | |
float y = source_a.y; | |
float angle = atan2(source_b.y - source_a.y, source_b.x - source_a.x); | |
float dx = 0.01f * cos(angle); | |
float dy = 0.01f * sin(angle); | |
while (source_b.x != floor(x) && source_b.y != floor(y)) { | |
if (floor(x) == 0 || floor(y) == 0 || floor(x) == MAP_WIDTH-1 || floor(y) == MAP_HEIGHT-1) | |
break; | |
map[(int)floor(y)][(int)floor(x)] = 1; | |
x += dx; | |
y += dy; | |
} | |
} | |
// change the i iteration here for cleaner/messier caves | |
// clean up freestanding walls | |
for (int i=0; i<8; i++) { | |
for (int y=1; y<MAP_HEIGHT-1; y++) { | |
for (int x=1; x<MAP_WIDTH-1; x++) { | |
// its a wall | |
if (map[y][x] == 0) { | |
// check if freestanding | |
int bias = 0; | |
bias += safe_index(x-1, y); | |
bias += safe_index(x+1, y); | |
bias += safe_index(x, y-1); | |
bias += safe_index(x, y+1); | |
if (bias > FREESTANDING_BIAS) | |
map[y][x] = 1; | |
} | |
} | |
} | |
} | |
for (int y=0; y<MAP_HEIGHT; y++) { | |
for (int x=0; x<MAP_WIDTH; x++) { | |
if (map[y][x] == 1) { | |
printf(" "); | |
} else { | |
printf("#"); | |
} | |
} | |
printf("\n"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment