Repository navigation
task 7a report
Commit: 399b6947 feat(temples): a flight of stairs can be locked: a small key or the Boss Key opens the climb on feat/classic-temples-2 (committed only my paths; nothing under templeReveals.ts, TempleChestReveal.vue or TempleGrounds.*).
-
types.ts:ClimbLock = 'small' | 'master'andRoomContent.locked?: ClimbLock(the climb FROM a stairs room is locked; the landing is free). -
authoredDoors.ts:climbLockOf(room), the one place that readscontent.locked(a stray value locks nothing). The engine's climb, the sheet and the solver graph all ask it, so they agree. -
templeSystem/doors.ts:climbKey(level, position)=${roomPositionKey}:climb,isClimbUnlocked(runs, templeId, level, position),unlockClimb(runs, templeId, level, position, kind). State isTempleState.openedDoors, so a saved run keeps it and a blood moon (openedDoors: []in templeReset) locks it again.unlockClimb('small')spends one key and refuses with none;'master'needs the Boss Key and keeps it; an already-open climb returns true and spends nothing. The mark cannot be mistaken for a door when a save is loaded (heroRuns: no>, so the direction check skips it; covered by the reload test). -
TempleSystem.ts: two thin public wrappersisClimbUnlocked(templeId, level, position)andunlockClimb(templeId, level, position, kind)(+ a type import). File was already over 500 (685 -> 700). -
roomInteractions/travel.ts: newstairsSheet(room, ctx, way);climbnow checks rubble first, then opens the lock (no key is spent on stairs to nowhere), then climbs. Lines: sheet "Stairs lead up." with subHeader "A small lock bars the way." / "The Boss Door's lock bars the way."; actions[]without the key,Unlock and climbwith it, plainClimbon a free or already-open flight. Unlock-and-climb outcome: "Unlocked! You climb up to 2F." (small) / "The big lock falls away. You climb up to 2F." (master), sounduseKey,moved: true. A stale sheet tapped without the key answers with the lock line anderror. -
RoomInteractions.ts: the two stairs cases callstairsSheet. -
templeGraph.tslinkStairs: the stairs door leaving a room carriesclimbLockOf(room) ?? "none"; the solver already knewsmall/master. -
dungeonCounts.tscountKeysAndLocks: a stairs room withlocked: 'small'adds one lock (actualLocks = ceil(doors / 2) + lockedClimbs); a Boss Key climb adds none.
RED (before any implementation):
chemx test tests/unit/TempleKeyBalance.spec.ts
Test Failures (2 failed out of 10) (stairs counted as one small lock; stairs' lock added to the locked doors: Expected 2, Received 1)
chemx test tests/unit/TempleSolver.spec.ts
Test Failures (4 failed out of 53) (keyless locked climb solvable: Expected false, Received true; graph stairs door lock; R3 count; Boss Key climb solvable: Expected false, Received true)
chemx test tests/unit/RoomInteractions.spec.ts -t "a flight of stairs with a lock"
Test suite failed to run: TS2339 Property 'isClimbUnlocked' does not exist on type 'TempleSystem'
(RoomInteractions went red at compile because the API did not exist yet; its behaviour assertions first ran after the implementation.)
GREEN (after):
chemx test tests/unit/TempleKeyBalance.spec.ts All tests passed (10 passed)
chemx test tests/unit/TempleSolver.spec.ts All tests passed (52 passed, 1 skipped) # the skip is the existing it.skip for hand-made temples (line ~468)
chemx test tests/unit/RoomInteractions.spec.ts All tests passed (146 passed)
chemx test tests/unit/TempleDataModules.spec.ts All tests passed (62 passed) # extra: it also covers countKeysAndLocks
Tests added:
- TempleSolver: locked small climb solvable with the key on 1F and not without it (R2 reason, names the stairs door); the stairs door carries
small/masterone way (landingnone); R3 counts the stairs' lock; Boss Key climb solvable only with the Boss Key reachable before it (the same layout with the key above the climb is stuck, and solvable with free stairs). - RoomInteractions (9 tests in "a flight of stairs with a lock on it"): no key = barred sheet, no actions; key =
Unlock and climbspends exactly one and climbs; a second climb in the run is free; the landing climbs back with no key; stale sheet with no key is turned back; a small key does not open a master lock; Boss Key opens it and is not spent (small keys untouched); rubble comes before any key is taken; saved run keeps it open across a reload, andbloodMoonlocks it again. - TempleKeyBalance: small-locked stairs = 1 lock, Boss Key climb = 0, added on top of the halved door locks.
src/lib/engine/core/dungeons/types.ts, templeSystem/doors.ts, TempleSystem.ts; src/lib/services/temples/authoredDoors.ts, roomInteractions/travel.ts, RoomInteractions.ts; src/lib/engine/dungeons/generator/templeGraph.ts; src/app/Admin/XpCompendium/views/XpTemples/hooks/templeData/dungeonCounts.ts; tests/unit/TempleSolver.spec.ts (476 lines), RoomInteractions.spec.ts, TempleKeyBalance.spec.ts. All source files touched stay under 500 except TempleSystem.ts (already over; thin wrappers only).
- Names in
ifs:lockToOpen,hasOpened,hasTheKey,isFreeOrOpen,isSmallLock,isOutOfKeys,isKnownLock,isSmallLockedClimb. No object-literal parameter types added;CLIMB_*_LINESareRecord<ClimbLock, string>. - Not run (per rules): typecheck, lint, verify, build. ts-jest type-checked every file the three specs import, and it was clean.
- The solver already treated
small/masterstairs-door locks generically (passable,closedDoorsInReach, R3isCritical), so only the graph needed the field.
- If the hero's key is spent and then
arriveOnfinds no spot to stand on (a stairs room whose requested landing and same cell are both not rooms), the climb stays open and the hero gets "blocked by rubble". R8 already flags such stairs, so I left it. - The brief's sheet text "Stairs lead up. A small lock bars the way." is split as header "Stairs lead up." + subHeader "A small lock bars the way." (the same header/subHeader shape every other locked thing uses). A consumer matching one joined string would need adjusting.
- A shared room token (
roomstable entry reused by several cells) locks every cell that uses it, as with every other room property; the dress step should give a locked flight its own token. Also, the landing stairs of a locked flight must not use the locked token, or its climb back would be locked too. - Docs (
docs/Temple-Generation-Contract.md, a submodule) not touched.
- Architecture
- Component-Library
- Hooks-Reference
- Temple-System
- Battle-Field-Architecture
- current_context - For AI/Human Handoff
- User Menu
- General Settings
- Family Settings
- Sound Settings
- Notification Settings
- Reward Settings
- Party Settings
- Theme Settings
- Chore Settings