Created
May 18, 2025 13:41
-
-
Save Hammer2900/499ef1dfcde3161c522f9c6d6cd626ee to your computer and use it in GitHub Desktop.
procedural dungeon generator using random walk in lobster
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
import vec | |
import color | |
import gl | |
import std | |
let screen_width = 800 | |
let screen_height = 600 | |
let tile_size = 20 | |
let map_width = screen_width / tile_size | |
let map_height = screen_height / tile_size | |
enum TileType: | |
WALL | |
FLOOR | |
class OptionalInt2Pos: | |
pos: int2 | |
class Dungeon: | |
width: int | |
height: int | |
tiles: [[TileType]] | |
floor_tiles: [int2] | |
def create_dungeon(width: int, height: int) -> Dungeon: | |
let initial_tiles = mapxy(int2 { width, height }) v: WALL | |
let initial_floor_tiles = [] | |
return Dungeon { width, height, initial_tiles, initial_floor_tiles } | |
def add_floor_tile(dungeon::Dungeon, pos: int2): | |
if pos.x >= 0 and pos.x < dungeon.width and pos.y >= 0 and pos.y < dungeon.height: | |
dungeon.tiles[pos.y][pos.x] = FLOOR | |
dungeon.floor_tiles.push(pos) | |
def create_room(dungeon::Dungeon, center_x: int, center_y: int, size: int) -> void: | |
let half_size = size / 2 | |
for_range_incl(center_y - half_size, center_y + half_size) y: | |
for_range_incl(center_x - half_size, center_x + half_size) x: | |
if x > 0 and x < dungeon.width - 1 and y > 0 and y < dungeon.height - 1: | |
add_floor_tile(dungeon, int2 { x, y }) | |
def add_random_rooms(dungeon::Dungeon, room_chance: float = 0.1) -> void: | |
let floor_tiles_copy = copy(dungeon.floor_tiles) | |
for (floor_tiles_copy) tile_pos: | |
if rnd_float() < room_chance: | |
let room_size = rnd(3) + 2 | |
create_room(dungeon, tile_pos.x, tile_pos.y, room_size) | |
def generate_dungeon(dungeon::Dungeon, num_steps: int, start_pos_opt: OptionalInt2Pos?) -> Dungeon: | |
var current_pos = if start_pos_opt != nil: | |
assert start_pos_opt | |
start_pos_opt.pos | |
else: | |
int2 { dungeon.width / 2, dungeon.height / 2 } | |
add_floor_tile(dungeon, current_pos) | |
for num_steps: | |
let dx = rnd(3) - 1 | |
let dy = rnd(3) - 1 | |
let new_pos_candidate = current_pos + int2 { dx, dy } | |
current_pos.x = clamp(new_pos_candidate.x, 1, dungeon.width - 2) | |
current_pos.y = clamp(new_pos_candidate.y, 1, dungeon.height - 2) | |
add_floor_tile(dungeon, current_pos) | |
add_random_rooms() | |
return dungeon | |
fatal(gl.window("Random Walk Dungeon Generator", screen_width, screen_height)) | |
gl.set_target_delta_time(1.0 / 60.0) | |
var font_loaded = gl.set_font_name("data/fonts/Droid_Sans/DroidSans.ttf") | |
if not font_loaded: font_loaded = gl.set_font_name("C:/Windows/Fonts/arial.ttf") | |
if not font_loaded: print "Warning: Font not loaded, text will not be visible." | |
rnd_seed(int(seconds_elapsed() * 1000100.0)) | |
var dungeon = create_dungeon(map_width, map_height) | |
var should_regenerate = true | |
while gl.frame() and gl.button("escape") != 1: | |
if gl.button("space") == 1: | |
should_regenerate = true | |
if should_regenerate: | |
dungeon = create_dungeon(map_width, map_height) | |
generate_dungeon(dungeon, 1000, nil) | |
// generate_dungeon(dungeon, 1000, OptionalInt2Pos { int2 { 10, 10 } }) | |
should_regenerate = false | |
gl.ortho(false, false) | |
gl.clear(color_black) | |
for (dungeon.height) y: | |
for (dungeon.width) x: | |
let pos_on_screen = float(int2 { x, y } * tile_size) | |
if dungeon.tiles[y][x] == FLOOR: | |
gl.color(color_grey) | |
gl.translate(pos_on_screen): | |
gl.rect(float2_1 * tile_size) | |
gl.line_mode(1) | |
gl.color(color_dark_grey) | |
gl.translate(pos_on_screen): | |
gl.rect(float2_1 * tile_size) | |
gl.line_mode(0) | |
if font_loaded: | |
gl.set_font_size(20) | |
gl.color(color_white) | |
gl.translate(float2 { 10.0, 10.0 }): | |
gl.text("Press SPACE to regenerate") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment