Skip to content

Instantly share code, notes, and snippets.

@solenum
Created July 11, 2018 18:17
Show Gist options
  • Save solenum/d48d9bd57c738701d1d5b3523d2099a4 to your computer and use it in GitHub Desktop.
Save solenum/d48d9bd57c738701d1d5b3523d2099a4 to your computer and use it in GitHub Desktop.
Worlds worst RL dungeon generator
/*
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