namespace Theriapolis.Core.Dungeons; /// /// Phase 7 M1 — runtime state for a single room inside a generated dungeon. /// /// A Room records its template id, its dungeon-local axis-aligned bounding /// box (top-left corner + dimensions, in tactical tiles), the clade that /// built it (drives clade-responsive movement cost per Phase 7 plan §5.4), /// and the role it occupies in the dungeon's layout. Mutable runtime state /// (cleared / looted flags) lives on the /// snapshot, not here, so this record stays a deterministic baseline view. /// public sealed class Room { /// Stable id within a dungeon (0..Dungeon.Rooms.Length-1). public int Id { get; init; } /// Reference back to the source . public string TemplateId { get; init; } = ""; /// Dungeon-local AABB top-left X (tile units). Inclusive. public int AabbX { get; init; } /// Dungeon-local AABB top-left Y (tile units). Inclusive. public int AabbY { get; init; } /// AABB width in tactical tiles (matches the source template's footprint_w_tiles). public int AabbW { get; init; } /// AABB height in tactical tiles (matches the source template's footprint_h_tiles). public int AabbH { get; init; } /// /// Builder clade — drives the clade-responsive movement multiplier /// (ClademorphicMovement.GetCostMultiplier) the player pays /// while moving through this room. Empty / "none" means no penalty. /// public string BuiltBy { get; init; } = "none"; /// Role assigned at layout-build time. public RoomRole Role { get; init; } /// /// Optional environmental-storytelling prose surfaced by the /// InteractionScreen scent-overlay panel (Phase 6.5 M1) and the /// dungeon-clear coda. Null when the source template doesn't carry one. /// public string? NarrativeText { get; init; } public override string ToString() => $"Room[id={Id} role={Role} aabb=({AabbX},{AabbY},{AabbW}x{AabbH}) tpl={TemplateId}]"; }