-
-
Save airstrike/66e0152e75c3a81fd1496bfbf590105a to your computer and use it in GitHub Desktop.
Dungeon Generator (Uncompressed, MS Visual Studio 2008)
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
// Uncompressed version of dungeon generator, backported for MS Visual Studio 2008 | |
// Original work: https://gist.github.com/munificent/b1bcd969063da3e6c298be070a22b604 | |
// Original uncompressed version: https://gist.github.com/Joker-vD/cc5372a349559b9d1a3b220d5eaf2b01 | |
// Tested with Microsoft (R) C/C++ Optimizing Compiler Version 16.00.30319.01 for x64 | |
#include <time.h> // Robert Nystrom | |
#include <stdio.h> // @munificentbob | |
#include <stdlib.h> // for Ginny | |
// #include <stdbool.h> // 2008-2019 | |
typedef int bool; | |
#define false 0 | |
#define true 1 | |
const int HEIGHT = 40; | |
const int WIDTH = 80; | |
int FIELD[40][80]; | |
int c; | |
int x, y, j, i; | |
#define IN_BOX(top, bottom, left, right) \ | |
for (y = top; y < bottom; y++) \ | |
for (x = left; x < right; x++) | |
int randInt(int upperBound) { | |
return rand() % upperBound; | |
} | |
#define TILE_VOID ' ' | |
#define TILE_FLOOR '.' | |
#define TILE_WALL '#' | |
#define TILE_CORNER '!' | |
#define TILE_OPEN_DOOR '\'' | |
#define TILE_CLOSED_DOOR '+' | |
#define TILE_PLAYER '@' | |
void cave(bool withPlayer) { | |
int doorX, doorY; | |
int doorCounter = 0; | |
bool atVerticalWall; | |
bool atHorizontalWall; | |
bool atWallButNotAtCorner; | |
bool atCorner; | |
// width, height, left and top are all inner | |
// dimensions/coordinates (w/o walls) | |
int width = randInt(10) + 5; // from [5..14] range | |
int height = randInt(6) + 3; // from [3..8] range | |
int left = randInt(WIDTH - width - 2) + 1; | |
int top = randInt(HEIGHT - height - 2) + 1; | |
// Check if the new cave (with walls) intersects with the interior of | |
// any already existing cave. Touching walls/corners are okay | |
IN_BOX(top - 1, top + height + 2, left - 1, left + width + 2) | |
if (FIELD[y][x] == TILE_FLOOR) { return; } | |
// Find a suitable place for a door | |
if (!withPlayer) { | |
IN_BOX(top - 1, top + height + 2, left - 1, left + width + 2) { | |
atVerticalWall = (x < left) || (x > left + width); | |
atHorizontalWall = (y < top) || (y > top + height); | |
atWallButNotAtCorner = atVerticalWall ^ atHorizontalWall; | |
// The door should not be created in the cave's corner or over | |
// another door, or in another cave's corner. It's impossible | |
// to make a cave without a door, because randInt(1) always | |
// returns 0. | |
if (atWallButNotAtCorner && FIELD[y][x] == TILE_WALL) { | |
doorCounter++; | |
if (randInt(doorCounter) == 0) { | |
doorX = x; | |
doorY = y; | |
} | |
} | |
} | |
// If the cave's walls were made completely out of corners | |
// and doors, don't make such a cave | |
if (doorCounter == 0) { return; } | |
} | |
// The cave looks okay, let's draw it. First, draw the walls and the floor | |
IN_BOX(top - 1, top + height + 2, left - 1, left + width + 2) { | |
atVerticalWall = (x < left) || (x > left + width); | |
atHorizontalWall = (y < top) || (y > top + height); | |
atCorner = atVerticalWall && atHorizontalWall; | |
atWallButNotAtCorner = atVerticalWall ^ atHorizontalWall; | |
// We need to somehow record corners of all caves to check | |
// for intersections later, so we use a special tile for it | |
FIELD[y][x] = atCorner | |
? TILE_CORNER | |
: (atWallButNotAtCorner ? TILE_WALL : TILE_FLOOR); | |
} | |
// Now draw the door. The test is redundant, btw, because | |
// of "if (doorCounter == 0) { return; }" earlier | |
if (doorCounter > 0) { | |
FIELD[doorY][doorX] = randInt(2) ? TILE_OPEN_DOOR : TILE_CLOSED_DOOR; | |
} | |
if (withPlayer) { | |
// A cave with the player has only the player inside it | |
FIELD[randInt(height) + top][randInt(width) + left] = TILE_PLAYER; | |
} | |
else { | |
// A cave without the player has some random mobs and/or gold in it; | |
// 1d6 of entities total, 25% chance of gold, 75% of a mob. | |
// Mob letters range from 'A' to '~', inclusive | |
for (j = 0; j < randInt(6) + 1; j++) { | |
FIELD[randInt(height) + top][randInt(width) + left] = | |
randInt(4) == 0 ? '$' : 'A' + randInt('~' - 'A' + 1); | |
} | |
} | |
} | |
int main(int argc, const char* argv[]) { | |
srand((int)time(((void *)0))); | |
// Fill the field with the void | |
IN_BOX(0, HEIGHT, 0, WIDTH) { | |
FIELD[y][x] = TILE_VOID; | |
} | |
// A call to cave() is not guaranteed to actually make a new cave, | |
// so call it many times | |
for (j = 0; j < 1000; j++) { | |
cave(j == 0); | |
} | |
// Print the generated field | |
IN_BOX(0, HEIGHT, 0, WIDTH) { | |
c = FIELD[y][x]; | |
// The cave corners should be drawn as walls | |
putchar(c == TILE_CORNER ? TILE_WALL : c); | |
if (x == WIDTH - 1) { | |
printf("\n"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment