Skip to content

Instantly share code, notes, and snippets.

@brettchalupa
Last active March 24, 2026 02:42
Show Gist options
  • Select an option

  • Save brettchalupa/7a4899c12fbfe74ff16ae1dc5892eb0e to your computer and use it in GitHub Desktop.

Select an option

Save brettchalupa/7a4899c12fbfe74ff16ae1dc5892eb0e to your computer and use it in GitHub Desktop.
Enigmata's map gen code from v0.1-dev; the code below is released into the public domain
#include "map.h"
#include "platform.h"
#include "util.h"
#include <string.h>
static int pointToTileIndex(Map *map, Point p) { return p.y * map->width + p.x; }
static void setTileAtPoint(Map *map, Point p, TileType type) {
map->tiles[pointToTileIndex(map, p)] = type;
}
static void carveRooms(Map *map) {
// carve out rooms
for (int sectorY = 0; sectorY < SECTORS_V; sectorY++) {
for (int sectorX = 0; sectorX < SECTORS_H; sectorX++) {
// skip rooms 10% of the time
if (percentChance(10))
continue;
int roomW = randInRange(SECTOR_WIDTH - 6, SECTOR_WIDTH - 2);
int roomH = randInRange(SECTOR_HEIGHT - 8, SECTOR_HEIGHT - 4);
int roomX = randInRange(1, SECTOR_WIDTH - roomW - 1);
int roomY = randInRange(1, SECTOR_HEIGHT - roomH - 1);
int sectorOffsetX = sectorX * SECTOR_WIDTH;
int sectorOffsetY = sectorY * SECTOR_HEIGHT;
map->rooms[sectorY * SECTORS_H + sectorX] = (Room){
.pos = {.x = roomX + sectorOffsetX, .y = roomY + sectorOffsetY},
.w = roomW,
.h = roomH,
};
map->roomCount++;
for (int y = roomY; y < roomH + roomY; y++) {
for (int x = roomX; x < roomW + roomX; x++) {
map->tiles[(sectorOffsetY + y) * map->width + (sectorOffsetX + x)] = kTileFloor;
}
}
}
}
}
// carve horizontal from x1 to x2 at row y
static void carveH(Map *map, int x1, int x2, int y) {
int startX = x1 < x2 ? x1 : x2;
int endX = x1 < x2 ? x2 : x1;
for (int x = startX; x <= endX; x++) {
setTileAtPoint(map, (Point){.x = x, .y = y}, kTileFloor);
}
}
// carve vertical from y1 to y2 at column x
static void carveV(Map *map, int x, int y1, int y2) {
int startY = y1 < y2 ? y1 : y2;
int endY = y1 < y2 ? y2 : y1;
for (int y = startY; y <= endY; y++) {
setTileAtPoint(map, (Point){.x = x, .y = y}, kTileFloor);
}
}
static void carveCorridors(Map *map) {
// connect each room to the next existing room to its right
for (int sy = 0; sy < SECTORS_V; sy++) {
for (int sx = 0; sx < SECTORS_H; sx++) {
Room *a = &map->rooms[sy * SECTORS_H + sx];
if (a->w == 0)
continue;
for (int nx = sx + 1; nx < SECTORS_H; nx++) {
Room *b = &map->rooms[sy * SECTORS_H + nx];
if (b->w == 0)
continue;
Point pa = roomRandomPoint(a);
Point pb = roomRandomPoint(b);
carveH(map, pa.x, pb.x, pa.y);
carveV(map, pb.x, pa.y, pb.y);
sx = nx - 1;
break;
}
}
}
// connect each room to the next existing room below
for (int sx = 0; sx < SECTORS_H; sx++) {
for (int sy = 0; sy < SECTORS_V; sy++) {
Room *a = &map->rooms[sy * SECTORS_H + sx];
if (a->w == 0)
continue;
for (int ny = sy + 1; ny < SECTORS_V; ny++) {
Room *b = &map->rooms[ny * SECTORS_H + sx];
if (b->w == 0)
continue;
Point pa = roomRandomPoint(a);
Point pb = roomRandomPoint(b);
carveV(map, pa.x, pa.y, pb.y);
carveH(map, pa.x, pb.x, pb.y);
sy = ny - 1;
break;
}
}
}
}
void generateMap(Map *map) {
map->roomCount = 0;
memset(map->rooms, 0, sizeof(map->rooms));
map->width = MAX_MAP_WIDTH;
map->height = MAX_MAP_HEIGHT;
// fill with walls
for (int i = 0; i < map->width * map->height; i++) {
map->tiles[i] = kTileWall;
}
carveRooms(map);
carveCorridors(map);
}
void drawMap(Map *map, Point camera, int cellSize) {
int startTileX = camera.x / cellSize;
int startTileY = camera.y / cellSize;
int endTileX = (camera.x + screenWidth()) / cellSize + 1;
int endTileY = (camera.y + screenHeight()) / cellSize + 1;
if (startTileX < 0)
startTileX = 0;
if (startTileY < 0)
startTileY = 0;
if (endTileX >= map->width)
endTileX = map->width - 1;
if (endTileY >= map->height)
endTileY = map->height - 1;
for (int y = startTileY; y <= endTileY; y++) {
for (int x = startTileX; x <= endTileX; x++) {
int i = pointToIndex((Point){x, y}, map->width);
int px = x * cellSize - camera.x;
int py = y * cellSize - camera.y;
drawTile(map->tiles[i], px, py, cellSize);
}
}
}
void setStairsAtPoint(Map *map, Point p) { setTileAtPoint(map, p, kTileStairsDown); }
#ifndef MAP_H
#define MAP_H
#include "point.h"
#include "util.h"
#define MAX_MAP_WIDTH 44
#define MAX_MAP_HEIGHT 33
#define SECTORS_H 4
#define SECTORS_V 3
#define SECTOR_WIDTH (MAX_MAP_WIDTH / SECTORS_H)
#define SECTOR_HEIGHT (MAX_MAP_HEIGHT / SECTORS_V)
typedef enum {
kTileWall = 742,
kTileFloor = 0, // empty
kTileStairsDown = 297,
} TileType;
/**
* A rectangular area within a sector of a map, with its position and width and
* height in grid size, not pixel size.
*/
typedef struct {
Point pos;
int w;
int h;
} Room;
/**
* Generated floor that the player traverses
*/
typedef struct {
int width;
int height;
TileType tiles[MAX_MAP_WIDTH * MAX_MAP_HEIGHT];
Room rooms[SECTORS_H * SECTORS_V];
int roomCount;
} Map;
static inline bool isInBounds(Point p, Map *map) {
return p.x >= 0 && p.x < map->width && p.y >= 0 && p.y < map->height;
}
/** Return a random point in the room */
static inline Point roomRandomPoint(Room *room) {
return (Point){
.x = room->pos.x + randInRange(0, room->w - 1),
.y = room->pos.y + randInRange(0, room->h - 1),
};
}
/** Return a the center point of the room */
static inline Point roomCenter(Room *room) {
return (Point){
.x = room->pos.x + room->w / 2,
.y = room->pos.y + room->h / 2,
};
}
static inline bool isTileWalkable(TileType tile) {
return tile == kTileFloor || tile == kTileStairsDown;
}
static inline TileType tileAtPos(Map *map, Point pos) {
return map->tiles[pointToIndex(pos, map->width)];
}
/**
* Draw the map to the screen with the renderer, setting offset with the camera.
*
* @param cellSize pixel size of each grid cell (tiles are drawn at this size)
*/
void drawMap(Map *map, Point camera, int cellSize);
void generateMap(Map *map);
void setStairsAtPoint(Map *map, Point p);
#endif
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "../../../src/map.h"
#include "../../../src/platform.h"
#include "../../vendor/raygui.h"
#include "raylib.h"
#include <time.h>
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void) {
// Initialization
//--------------------------------------------------------------------------------------
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(1280, 720, "mapgen");
srand(time(NULL)); // NOLINT(bugprone-random-generator-seed)
initRenderer("../../Source/images/kenney-1bit-table-16-16.png", 16, 0, 0); // 0,0 = use window size
Point camera = {.x = 0, .y = 0};
int cameraSpeed = 16;
int cellSize = 16;
static Map map;
generateMap(&map);
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyDown(KEY_W))
camera.y -= cameraSpeed;
if (IsKeyDown(KEY_S))
camera.y += cameraSpeed;
if (IsKeyDown(KEY_A))
camera.x -= cameraSpeed;
if (IsKeyDown(KEY_D))
camera.x += cameraSpeed;
if (IsKeyPressed(KEY_Q))
cellSize -= 8;
if (IsKeyPressed(KEY_E))
cellSize += 8;
cellSize = max(cellSize, 8);
cellSize = min(cellSize, 128);
if (IsKeyPressed(KEY_R)) {
char screenshotName[64];
snprintf(screenshotName, sizeof(screenshotName), "map-%ld.png", (long)time(NULL));
TakeScreenshot(screenshotName);
}
if (IsKeyPressed(KEY_SPACE)) {
generateMap(&map);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(WHITE);
drawMap(&map, camera, cellSize);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
freeRenderer();
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment