random-dungeon-generator-ts
v1.0.0
Published
A Telengard-style random dungeon generator for TypeScript/JavaScript projects.
Maintainers
Readme
Random Dungeon Generator
A Telengard-style random dungeon generator for TypeScript/JavaScript projects. Generates repeatable, room-and-hallway dungeons using a seeded PRNG.
Features
- Generates dungeons with rooms and hallways
- Seeded for repeatable results
- TypeScript and JavaScript compatible
- Easily integrated into games or map tools
Installation
npm install random-dungeon-generatorRepeatability & Seeding
This generator uses a seeded pseudo-random number generator (PRNG). If you provide the same seed and parameters, you will always get the same dungeon layout. This is useful for:
- Sharing dungeon layouts with others
- Debugging and testing
- Saving and reloading specific dungeons
Example:
import { DungeonGenerator } from 'random-dungeon-generator';
const generator = new DungeonGenerator();
const result1 = generator.generate(30, 20, 12345);
const result2 = generator.generate(30, 20, 12345);
console.log(result1.map);
console.log(result2.map);
// result1.map and result2.map will be identicalimport { DungeonGenerator } from 'random-dungeon-generator';
const generator = new DungeonGenerator();
const result = generator.generate(30, 20, 12345);
console.log(result.map);API
DungeonGenerator
generate(width: number, height: number, seed?: number | null, roomAttempts?: number, minRoomSize?: number, maxRoomSize?: number): DungeonResult
width(number): Number of columns in the dungeon (horizontal size)height(number): Number of rows in the dungeon (vertical size)seed(number, optional): Integer seed for repeatability (same seed = same dungeon)roomAttempts(number, optional): How many times to try placing a room (default: 30)minRoomSize(number, optional): Minimum width/height of a room (default: 3)maxRoomSize(number, optional): Maximum width/height of a room (default: 7)- Returns:
DungeonResultobject containing the map, seed, and rooms
Example
import { DungeonGenerator } from 'random-dungeon-generator';
const generator = new DungeonGenerator();
const result = generator.generate(30, 20, 12345);
console.log(result.map);exportDungeonToJson(width, height, seed?)
- Utility function to generate a dungeon and export it as a JSON string.
- Parameters are the same as
generateabove. - Returns: JSON string representing the dungeon result.
Types
Tile:'wall' | 'floor'RoomType:'start' | 'end' | 'safe' | 'none'Room:x,y: Top-left coordinatesw,h: Width and heightroomNumber: Unique room number (starts at 1)roomType: RoomType enum valuenumberFromStart: Number of rooms to traverse from start
DungeonResult:map: 2D array ofTilevaluesseed: The seed used for generationrooms: Array ofRoomobjects
Example
See test_dungeon.ts for a full example that prints a dungeon to the console.
Why use this package?
- TypeScript-first: Full type support and documentation for modern JS/TS projects.
- Repeatable dungeons: Seeded PRNG ensures the same parameters always generate the same map.
- Simple API: Minimal, easy-to-use interface for quick integration.
- Room and hallway style: Classic Telengard-style layouts, great for roguelikes and retro games.
- Framework agnostic: Use in Node.js, browser, or with game engines like Phaser or PixiJS.
Usage Example & Sample Output
Here’s a demo script that prints a dungeon to the console, marking the start room (S), end room (E), room numbers, hallways (H), and unreachable spaces:
import { DungeonGenerator, RoomType } from 'random-dungeon-generator';
const generator = new DungeonGenerator();
const result = generator.generate(30, 20, 12345);
const map = result.map;
const rooms = result.rooms;
// Build a lookup for room positions and types
const roomLookup = new Map();
const roomNumberLookup = new Map();
for (const room of rooms) {
for (let ry = room.y; ry < room.y + room.h; ry++) {
for (let rx = room.x; rx < room.x + room.w; rx++) {
roomLookup.set(`${ry},${rx}`, room.roomType);
roomNumberLookup.set(`${ry},${rx}`, room.roomNumber);
}
}
}
// BFS to find reachable floor tiles from the start room
let startRoom = rooms.find(r => r.roomType === RoomType.Start);
const reachable = new Set<string>();
if (startRoom) {
const queue: [number, number][] = [];
const visited = new Set<string>();
for (let ry = startRoom.y; ry < startRoom.y + startRoom.h; ry++) {
for (let rx = startRoom.x; rx < startRoom.x + startRoom.w; rx++) {
queue.push([ry, rx]);
visited.add(`${ry},${rx}`);
}
}
while (queue.length > 0) {
const next = queue.shift();
if (!next) continue;
const [y, x] = next;
reachable.add(`${y},${x}`);
for (const [dy, dx] of [[0,1],[1,0],[0,-1],[-1,0]] as [number, number][]) {
const ny = y + dy, nx = x + dx;
if (ny >= 0 && ny < map.length && nx >= 0 && nx < map[0].length) {
if (map[ny][nx] === 'floor' && !visited.has(`${ny},${nx}`)) {
queue.push([ny, nx]);
visited.add(`${ny},${nx}`);
}
}
}
}
}
function roomNumChar(num: number | undefined) {
if (num == null) return '?';
if (num >= 1 && num <= 9) return String(num);
if (num >= 10 && num <= 35) return String.fromCharCode(55 + num); // 10->A, 11->B, ...
if (num >= 36 && num <= 61) return String.fromCharCode(61 + num); // 36->a, 37->b, ...
return '*';
}
const out = map.map((row, y) => row.map((t, x) => {
const key = `${y},${x}`;
if (!reachable.has(key)) return ' ';
const type = roomLookup.get(key);
const num = roomNumberLookup.get(key);
if (type === RoomType.Start) return 'S';
if (type === RoomType.End) return 'E';
if (type === undefined) return 'H'; // Hallway
if (typeof num === 'number') return roomNumChar(num);
return ' ';
}).join('')).join('\n');
console.log(out);Sample Output:
##############################
# 1HHH2HHH3HHH4HHH5HHH6HHH #
# H H H H H H #
# 7HHH8HHH9HHHAHHHBHHHCHHH #
# H H H H H H #
# DHHHEHHHFHHHGHHHHHHIHHH #
# H H H H H H #
# JHHHKHHHLHHHMHHHNHHHOHHH #
# H H H H H H #
# PHHHQHHHRHHHSHHHTHHHUHHH #
# H H H H H H #
# VHHHWHHHXHHHYHHHZHHH1HHH #
# H H H H H H #
# 2HHH3HHH4HHH5HHH6HHH7HHH #
# H H H H H H #
# 8HHH9HHHAHHHBHHHCHHHDHHH #
# H H H H H H #
# EHHHFHHHGHHHHHHIHHHJHHH #
# H H H H H H #
# KHHHLHHHMHHHNHHHOHHHPHHH #
##############################See test_dungeon.ts for a full working example.
License
MIT
