/** * semantic.ts — the tile-agnostic vocabulary that decouples a map's LAYOUT from * the ART it is drawn with. * * The bundled reference maps are raw MV map JSON, so a template only works when * the project uses the same tileset the template was authored against: the tile * IDs are indices into one specific set of sheets. Change the tileset and the * map turns to noise. * * A semantic template stores what each cell *is* — ground, wall, water, a door, * a prop anchor — and a TilesetProfile says which concrete tile ID plays each * role in a given tileset. Materialising a template against a profile produces a * real map, so one layout can be a stone dungeon, a sci-fi corridor or a snow * fort, and third-party tilesets work as soon as someone (or the miner) fills in * a profile for them. */ /** * The token vocabulary. Deliberately small: every token must be answerable for * any tileset, including a custom one, or a profile cannot be written for it. */ export declare const SEMANTIC_TOKENS: readonly ["void", "ground", "ground_alt", "water", "waterfall", "wall", "wall_top", "roof", "prop", "door", "poi"]; export type SemanticToken = typeof SEMANTIC_TOKENS[number]; /** One prop instance: a multi-tile object kept whole rather than shredded. */ export interface SemanticProp { /** Anchor in template coordinates (top-left of the bounding box). */ x: number; y: number; width: number; height: number; /** Cells relative to the anchor: [dx, dy, layer, tileId]. */ cells: [number, number, number, number][]; /** Stable identity so the same object can be recognised across maps. */ signature: string; } /** A layout with no art attached. */ export interface SemanticTemplate { id: string; name: string; /** Which project map this came from, when mined rather than authored. */ sourceMapId?: number; /** The tileset it was observed on, which is the profile most likely to fit. */ sourceTilesetId?: number; width: number; height: number; /** Row-major, width*height tokens. */ grid: SemanticToken[]; props: SemanticProp[]; /** Cells worth annotating: doors, shops, chests, spawn points. */ markers: { x: number; y: number; role: string; note?: string; }[]; } /** * Which concrete tile ID plays each role in one tileset. Autotiles are stored as * the base ID for shape 0; the shape is recomputed by applyAutotileShapes after * the grid is laid down, which is the only correct order — the shape is a * consequence of the neighbourhood, never a free choice. */ export interface TilesetProfile { tilesetId: number; tilesetName?: string; /** token -> base tile ID. A token with no entry is skipped when materialising. */ tiles: Partial>; /** How many cells each mapping was observed on, so a better sample can win. */ confidence: Partial>; } export declare function emptyProfile(tilesetId: number, tilesetName?: string): TilesetProfile; /** * Classify one cell into a token. * * `lower` is the tile on layers 0/1 and `upper` the tile on layers 2/3; the * upper layer decides "prop" only when something is actually painted there. * Passage flags, when available, override the guess for impassable ground — a * custom tileset can put a wall on any sheet, and the flags are what the engine * itself believes. */ export declare function classifyTile(lower: number, upper: number, flags?: number[] | null): SemanticToken; export declare function profileTileFor(profile: TilesetProfile, token: SemanticToken): number;