task 1 report - xopherdeep/do-it-for-the-xp GitHub Wiki

Task 1 report: Drops and Bombs in the grants and the solver (board #1455, first half)

Commit: 01da66ca feat(temples): fight rooms can drop keys, and a Bomb found inside a temple opens its cracked walls Status: DONE_WITH_CONCERNS (see Concerns)

What was implemented

  • types.ts: RoomDrops = Pick<RoomContent, 'chest' | 'dungeon' | 'items' | 'gold'> and RoomContent.drops?: RoomDrops.
  • fightDrops.ts (new): FIGHT_ROOM_TYPES, BOMB_ITEM = 'Bomb', roomDrops(room) (the non-empty content.drops of a monster/miniboss/boss room, else null; "non-empty" = a dungeon string, a non-empty items list, or gold > 0), dropKey(level, position) = ${roomPositionKey(...)}:drop.
  • roomGrants.ts: smallKeysGranted and grantsBossKey count the fight drop (ids through dungeonItemId; "key" rows of a drop count like a loot room's rows); new grantedDungeonItems(room) (chest's item, then the drop's) and isBombSource(room) (a shop, a loot chest or a fight drop whose items include Bomb); chestDungeonItem stays chest-only. Header notes updated (three places now; Bomb sources).
  • templeGraph.ts: LockKind gains "bomb"; a bombable side is a door with lock: "bomb" (a wall stays no door); GraphRoom.bombs = isBombSource(room). Header + linkNeighbours notes updated.
  • templeSolver.ts: Region.bombs; passable takes { master, bombs }; explore keeps cracked-wall doors waiting (as it does boss doors) until a room with bombs is reached, then walks through them. The way-back check carries region.bombs.
  • templeAudit.ts: maps and compasses counted with grantedDungeonItems.
  • dungeonCounts.ts: key items listed from grantedDungeonItems (plus the master-key Key room as before).
  • roomPosition.ts (new leaf) + DungeonManager.ts: roomPositionKey moved to a module with no imports and re-exported from DungeonManager, so fightDrops.ts (and so the solver's import chain: templeGraph -> roomGrants -> fightDrops) does not pull in DungeonManager (Vue, ChestSystem) and does not make a cycle (DungeonManager -> roomGrants -> fightDrops -> DungeonManager). Every existing import { roomPositionKey } from '.../DungeonManager' keeps working.

Decisions the brief left open

  • A cracked wall into a boss room stays lock: "master" (walking out of the boss room through one is bomb). The global constraint says every door into a boss room is a Boss door and Bombs never open locked doors; the solver is the stricter reader, so it can only reject, never accept, a temple the engine would let a hero skip the Boss Key in.
  • A bombable side with a small lock flag on the room is still bomb (the editor cannot draw both: one value per side).
  • Bomb doors count as open in reachableFrom (R1, R4, R7, R9 and isCritical treat every door as open, as they do boss and small doors), so a room behind only a cracked wall is no longer "out of reach" (R1), and a cracked-wall detour around the mini-boss now counts as a way around it (R4/R7), which is right once a Bomb is in the temple.

TDD evidence

RED (before any source change):

$ chemx test tests/unit/FightDrops.spec.ts
  ✖ Test suite failed to run
      tests/unit/FightDrops.spec.ts:7:10 - error TS2305: Module '"@/lib/services/temples/roomGrants"' has no exported member 'grantedDungeonItems'.
$ chemx test tests/unit/TempleSolver.spec.ts
  ✖ Test suite failed to run
      tests/unit/TempleSolver.spec.ts:349:74 - error TS2339: Property 'bombs' does not exist on type 'GraphRoom'.

GREEN (after the implementation):

$ chemx test tests/unit/FightDrops.spec.ts        ✔ All tests passed (19 passed)
$ chemx test tests/unit/TempleSolver.spec.ts      ✔ All tests passed (48 passed, 1 skipped)
$ chemx test tests/unit/MinibossBossKey.spec.ts   ✔ All tests passed (8 passed)
$ chemx test tests/unit/templeAudit.spec.ts       ✔ All tests passed (70 passed)
$ chemx test tests/unit/ShippedTemplesAudit.spec.ts ✔ All tests passed (218 passed)
$ chemx test tests/unit/WindTemple.spec.ts        ✔ All tests passed (12 passed)

The one skip in TempleSolver is the pre-existing wind-temple fails the solver title (R5: its two mini-bosses lack lockOnEnter; nothing to do with Bombs: the Wind Temple no longer fails R2).

Files changed

  • src/lib/engine/core/dungeons/types.ts, roomPosition.ts (new), DungeonManager.ts
  • src/lib/services/temples/fightDrops.ts (new), roomGrants.ts, templeAudit.ts
  • src/lib/engine/dungeons/generator/templeGraph.ts, templeSolver.ts
  • src/app/Admin/XpCompendium/views/XpTemples/hooks/templeData/dungeonCounts.ts
  • tests/unit/FightDrops.spec.ts (new), TempleSolver.spec.ts, ShippedTemplesAudit.spec.ts, WindTemple.spec.ts

Spec changes beyond the two new tests in the brief: the TempleSolver.spec.ts describe "walls and bombable sides are walls to the solver" was rewritten (a bombable side is now a Bomb door; a wall stays a wall; added: Bomb behind the wall no help, Bomb opens no small lock, boss-door wall stays master, shop and monster-drop Bomb sources). ShippedTemplesAudit.spec.ts: BOMB_SHOP and withWallsBlown removed, Wind read as shipped, header fixed. WindTemple.spec.ts (not in the brief): its "without a Bomb" block asserted the old behaviour (cracked wall = no door, Wind unsolvable); it would have gone red, so it now asserts the Boss Key is unreachable with the bomb doors closed, the shop is a Bomb source, the temple solves, and unsolves with the shop removed.

Self-review (diff read)

  • Behaviour for rooms without drops is unchanged: smallKeysGranted/grantsBossKey/chestDungeonItem give the same answers (MinibossBossKey, templeAudit, ShippedTemplesAudit green); dungeonCounts keeps one key item per room for every room that could give one before.
  • import type { GrantingRoom } in fightDrops keeps the fightDrops <-> roomGrants link one-way at runtime.
  • No new typecheck/lint run (lead's job). TS points I checked by reading: Carried is satisfied by Region; the lock const in linkNeighbours is LockKind; the aliased-condition narrowing in dropDungeonItem mirrors chestDungeonItem.

Concerns

  1. docs/Temple-Generation-Contract.md line 28 ("a cracked wall is a wall here ... never a way the solver counts on") is now stale. docs/ is a submodule, so I did not touch it.
  2. The engine's blowBombableSide writes the door into openedDoors, and doorKind treats an opened key as an opened boss door, so in play a Bomb on a cracked wall into a boss room would skip the Boss Key. The solver does not count on it (see decisions); the play task that touches doors.ts should refuse that case.
  3. stuckReason still says "no locked door in reach" when a cracked wall with no Bomb is what holds the hero; a hint could be added in a later task if the Game Master's audit should name it.
  4. Ran one spec the brief did not name (WindTemple.spec.ts) because this change breaks it; no other spec was run. TempleDataModules.spec.ts (covers buildComposition) and TempleGenerator.spec.ts were not run; the wave's CI run covers them.
⚠️ **GitHub.com Fallback** ⚠️