/** * graphGenerator.ts — layouts built from a mission, not from geometry. * * BSP splits a rectangle and hopes the result is interesting; cellular automata * make a cave-shaped blob. Neither knows what the space is FOR, so the key ends * up behind the door it opens as often as not. * * This generates the mission first — entrance, key, locked door, treasure, boss, * exit, plus optional side rooms — as a graph whose edges are the only ways * through. Then it lays that graph out as rooms and corridors. Because the lock * is an edge in the graph and the key sits on the entrance side of it, the * result is solvable by construction, and the shape metrics in mapMetrics have * real junctions and loops to find. * * The output is a semantic template, so the same mission can be materialised * onto any tileset (see materialize.ts). */ import type { SemanticTemplate } from '../knowledge/semantic.js'; export type RoomRole = 'entrance' | 'key' | 'lock' | 'treasure' | 'boss' | 'exit' | 'hall' | 'side'; export interface MissionNode { id: number; role: RoomRole; /** Depth from the entrance along the critical path. */ depth: number; } export interface MissionEdge { from: number; to: number; /** A locked edge needs the key from the node named here before it opens. */ lockedBy?: number; } export interface MissionGraph { nodes: MissionNode[]; edges: MissionEdge[]; } export interface LayoutOptions { width: number; height: number; /** Same seed and options produce the same layout. */ seed?: number; /** How many rooms on the critical path, before side rooms. Default 5. */ rooms?: number; /** Add a key and a locked door. Default true when there are 4+ rooms. */ locked?: boolean; /** Add dead-end side rooms with something in them. Default 2. */ sideRooms?: number; /** Join two rooms with an extra corridor so the map has a loop. Default true. */ loop?: boolean; name?: string; } /** * Build the mission. The spine is entrance to exit through the boss; the key * sits on a node strictly before the locked edge, which is what makes the map * solvable rather than merely connected. */ export declare function buildMissionGraph(opts: { rooms: number; locked: boolean; sideRooms: number; rand: () => number; }): MissionGraph; /** Generate a mission-shaped layout as a semantic template. */ export declare function generateSemanticLayout(opts: LayoutOptions): SemanticTemplate;