using Theriapolis.Core.Tactical; using Theriapolis.Core.World; namespace Theriapolis.Core.Dungeons; /// /// Phase 7 M1 — runtime view of an interior dungeon. Generated lazily on /// the player's first entry to a PoI; persisted modifications live on /// and /// re-apply on reload. /// /// The dungeon owns its own bounded tactical-tile array (the scene-swap /// model from Phase 7 plan §4.2): movement, combat, dialogue, and save/load /// all work the same as the surface, but the renderer reads tiles from /// instead of the chunk streamer. /// /// Coordinate space: Tiles[x, y] where x ∈ [0, W) and /// y ∈ [0, H). Every 's AABB falls within these /// bounds; corridor tiles between rooms are also in this array. /// public sealed class Dungeon { /// Source PoI id. Identity for save lookups. public int PoiId { get; } /// Dungeon type — drives art family, default loot tier, etc. public PoiType Type { get; } /// The tactical-tile grid in dungeon-local coordinates. public TacticalTile[,] Tiles { get; } /// Every room in layout order. Rooms[i].Id == i. public Room[] Rooms { get; } /// /// Door-anchored connections between rooms. Authoritative for /// reachability — the graph is undirected (a connection from A→B is /// implicit B→A; do not double-store). /// public RoomConnection[] Connections { get; } /// /// Dungeon-local tile coords of the entrance. The player spawns here /// on enter and exits when they cross this tile inbound from inside. /// public (int X, int Y) EntranceTile { get; } /// Width of the tile array (dungeon-local tiles). public int W => Tiles.GetLength(0); /// Height of the tile array (dungeon-local tiles). public int H => Tiles.GetLength(1); public Dungeon( int poiId, PoiType type, TacticalTile[,] tiles, Room[] rooms, RoomConnection[] connections, (int X, int Y) entranceTile) { PoiId = poiId; Type = type; Tiles = tiles; Rooms = rooms; Connections = connections; EntranceTile = entranceTile; } }