3.1 KiB
Task 8: RoomCarver Pass
Depends on: Task 6
Context Files
.dev/2026-05-28-procgen-map-core/spec/design.md— §4.7 (Shaper role), §5 (data flow)..dev/2026-05-28-procgen-map-core/README.md— inter-pass data contract (RoomCarver row).reikhelm-core/src/pass.rs—Pass,GenContext(Task 6).reikhelm-core/src/region.rs,reikhelm-core/src/map.rs—Region,RegionKind::Room,Tile::Floor.reikhelm-core/src/passes/mod.rs— append the module declaration here.
Files
- Create:
reikhelm-core/src/passes/room.rs—RoomConfig,RoomCarver. - Modify:
reikhelm-core/src/passes/mod.rs— appendpub mod room;and re-exportRoomCarver,RoomConfig.
What to Build
A shaper (spec §4.7) that turns BSP leaves into actual rooms. For each existing Room region (the placeholders from BspPartition), it picks a room rectangle that fits inside the leaf bounds (random size within RoomConfig limits, leaving a margin from the leaf edge so corridors and walls have room), carves Tile::Floor into ctx.tiles over that rectangle, and updates the region's bounds to the actual room rect and fills cells with the carved points. A leaf too small to hold a min_size room is skipped gracefully: its region is left in place with empty cells (never removed) — removal would break the RegionId-as-index invariant (Task 5). A Room region with empty cells denotes "not actually a room"; downstream room consumers (MstConnect, CorridorCarver) treat only Room regions with non-empty cells as real rooms. (In the assembled dungeon recipe this case never fires — Task 12's config validation guarantees every leaf fits a room — but the pass must handle it without panicking per spec §8.)
This pass reads/writes ctx.regions and ctx.tiles only; it does not depend on BspPartition's code, only on the documented "placeholder Room regions" precondition — so tests construct that precondition directly.
Interface Dependencies
- Consumes:
Pass,GenContext,Rng(Task 6);Region,Tile(Task 5). - Produces:
struct RoomConfig { min_size: i32, max_size: i32, margin: i32 }(+Default).struct RoomCarver { /* holds RoomConfig */ }—new(cfg) -> Self;impl Passwithname() == "room_carver".- Writes to context:
Floortiles; finalized Room regionbounds/cells.
Tests
- Given a
GenContextwith two placeholder Room regions over aWallgrid, after running: each carved room'sboundslies within its original leaf bounds and within the map; the floor cell count matchesboundsarea. - Carved floors do not extend outside the originating leaf (margin respected).
- A leaf smaller than
min_sizeis skipped without panicking. - Determinism: same seed/sub-stream → identical carved rooms.
Success Criteria
RoomCarvercarvesFloorrooms inside leaf bounds, respecting size/margin, and finalizes regionbounds/cells.- Undersized leaves are handled gracefully (no panic).
pub mod room;appended topasses/mod.rs.- Tests pass:
cargo test -p reikhelm-core room
Commit
"feat(core): RoomCarver pass"