UNPKG

shellquest

Version:

Terminal-based procedurally generated dungeon crawler

123 lines (114 loc) 4.58 kB
import type {PRNG} from 'seedrandom'; import type {LevelTile} from '../types.ts'; import {getTileName} from '../types.ts'; export class HouseGenerator { constructor( private tiles: LevelTile[][], private width: number, private height: number, ) {} generateHouse( x: number, y: number, width: number, height: number, houseType: 'house-1' | 'house-2', rng: PRNG, ): void { if (x + width > this.width || y + height > this.height) return; for (let dy = 0; dy < height; dy++) { for (let dx = 0; dx < width; dx++) { const tile = this.tiles[y + dy][x + dx]; tile.bottomTile = 'dirt-1'; tile.solid = false; tile.topTile = undefined; } } for (let dx = 0; dx < width; dx++) { if (dx === 0) { this.tiles[y][x + dx].topTile = `${houseType}-roof-top-top-left`; } else if (dx === width - 1) { this.tiles[y][x + dx].topTile = `${houseType}-roof-top-top-right`; } else { if (rng() < 0.3 && dx > 0 && dx < width - 1) { this.tiles[y][x + dx].topTile = `${houseType}-roof-top-chimney`; } else { this.tiles[y][x + dx].topTile = `${houseType}-roof-top-middle`; } } this.tiles[y][x + dx].solid = true; if (y + 1 < this.height) { if (dx === 0) { this.tiles[y + 1][x + dx].topTile = `${houseType}-roof-bottom-left`; } else if (dx === width - 1) { this.tiles[y + 1][x + dx].topTile = `${houseType}-roof-bottom-right`; } else { if (rng() < 0.2 && dx > 0 && dx < width - 1) { this.tiles[y + 1][x + dx].topTile = `${houseType}-roof-bottom-arch`; } else { this.tiles[y + 1][x + dx].topTile = `${houseType}-roof-bottom-middle`; } } this.tiles[y + 1][x + dx].solid = true; } } for (let dy = 2; dy < height; dy++) { if (y + dy >= this.height) break; for (let dx = 0; dx < width; dx++) { if (dx === 0) { if (rng() < 0.3 && dy > 2 && dy < height - 1) { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-left`; } else { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-left`; } } else if (dx === width - 1) { if (rng() < 0.3 && dy > 2 && dy < height - 1) { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-right`; } else { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-right`; } } else { if (dy === height - 1) { if (width === 3 && dx === 1) { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-door-single`; this.tiles[y + dy][x + dx].solid = false; } else if (width >= 4 && dx === Math.floor(width / 2) - 1) { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-door-double-left`; this.tiles[y + dy][x + dx].solid = false; } else if (width >= 4 && dx === Math.floor(width / 2)) { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-door-double-right`; this.tiles[y + dy][x + dx].solid = false; } else { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-middle`; } } else if (dy === height - 2 && rng() < 0.5) { if ( (width === 3 && dx === 1) || (width >= 4 && (dx === Math.floor(width / 2) - 1 || dx === Math.floor(width / 2))) ) { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-door-hole`; } else { if (rng() < 0.3) { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-window`; } else { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-middle`; } } } else { if (rng() < 0.2 && dy > 2) { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-window`; } else { this.tiles[y + dy][x + dx].topTile = `${houseType}-wall-middle`; } } } const topTileName = this.tiles[y + dy][x + dx].topTile ? getTileName(this.tiles[y + dy][x + dx].topTile!) : null; if (!topTileName?.includes('door')) { this.tiles[y + dy][x + dx].solid = true; } } } } }