[High] [Bug] Non-combat rooms grant repeated rewards during descent (library XP, treasure loot) #382

Closed
opened 2026-06-12 12:05:45 +02:00 by Anexim · 2 comments
Owner

Bug Summary

When descending the spire, non-combat rooms (especially library and treasure) grant rewards every tick without completion guards, causing repeated XP/loot accumulation.

Expected Behavior

Non-combat rooms should only grant rewards while progress < required. Once complete, no more rewards should be awarded.

Root Cause

Primary bug — tickLibraryRoom in src/lib/game/stores/non-combat-room-actions.ts:127-140: Library XP is granted unconditionally every tick BEFORE the completion check at line 141. There is no guard like if (progress < required)` around the XP grant.

Secondary bug — tickTreasureRoom in the same file, lines 174-222:
Loot is granted based on threshold ratios. Once progress >= required, advance() is called, but the loot for the final threshold is granted every subsequent tick.

Tertiary issue — combat-descent-actions.ts:66-100:
During descent, non-combat rooms are never initialized (no onEnter*Room calls), so they retain default progress=0, required=1 from generateSpireFloorState. The tick pipeline processes them and grants rewards.

Severity

High — Library rooms grant Math.floor(50 * 25 * hours) XP every tick unconditionally. At 200ms ticks, that's 250 XP/tick = 1,250 XP/second per library room, accumulating indefinitely during descent.

Files Involved

File Lines Issue
src/lib/game/stores/non-combat-room-actions.ts 127-140 Library XP granted unconditionally, no completion guard
src/lib/game/stores/non-combat-room-actions.ts 141 Completion check comes AFTER reward grant
src/lib/game/stores/non-combat-room-actions.ts 174-222 Treasure loot re-granted post-completion
src/lib/game/stores/combat-descent-actions.ts 66-100 Descent never initializes non-combat rooms

Fix Direction

  1. Wrap the library XP grant in if (progress < required)
  2. Move the completion check before the reward grant in all non-combat room tick handlers
  3. During descent, either properly initialize non-combat rooms or skip reward processing
## Bug Summary When descending the spire, non-combat rooms (especially library and treasure) grant rewards every tick without completion guards, causing repeated XP/loot accumulation. ## Expected Behavior Non-combat rooms should only grant rewards while `progress < required`. Once complete, no more rewards should be awarded. ## Root Cause **Primary bug — `tickLibraryRoom`** in `src/lib/game/stores/non-combat-room-actions.ts:127-140: Library XP is granted unconditionally every tick BEFORE the completion check at line 141. There is no guard like `if (progress < required)` around the XP grant. **Secondary bug — `tickTreasureRoom`** in the same file, lines 174-222: Loot is granted based on threshold ratios. Once `progress >= required`, `advance()` is called, but the loot for the final threshold is granted every subsequent tick. **Tertiary issue — `combat-descent-actions.ts:66-100`**: During descent, non-combat rooms are never initialized (no `onEnter*Room` calls), so they retain default progress=0, required=1 from `generateSpireFloorState`. The tick pipeline processes them and grants rewards. ## Severity **High** — Library rooms grant `Math.floor(50 * 25 * hours)` XP every tick unconditionally. At 200ms ticks, that's 250 XP/tick = 1,250 XP/second per library room, accumulating indefinitely during descent. ## Files Involved | File | Lines | Issue | |------|-------|------| | `src/lib/game/stores/non-combat-room-actions.ts` | 127-140 | Library XP granted unconditionally, no completion guard | | `src/lib/game/stores/non-combat-room-actions.ts` | 141 | Completion check comes AFTER reward grant | | `src/lib/game/stores/non-combat-room-actions.ts` | 174-222 | Treasure loot re-granted post-completion | | `src/lib/game/stores/combat-descent-actions.ts` | 66-100 | Descent never initializes non-combat rooms | ## Fix Direction 1. Wrap the library XP grant in `if (progress < required)` 2. Move the completion check before the reward grant in all non-combat room tick handlers 3. During descent, either properly initialize non-combat rooms or skip reward processing
Anexim added the ai:todo label 2026-06-12 12:05:45 +02:00
n8n-gitea was assigned by Anexim 2026-06-12 12:05:45 +02:00
Anexim added ai:in-progress and removed ai:todo labels 2026-06-12 13:09:21 +02:00
Author
Owner

Starting work on this bug. Reading the affected files to understand the current code structure before implementing fixes.

Starting work on this bug. Reading the affected files to understand the current code structure before implementing fixes.
Anexim added ai:done and removed ai:in-progress labels 2026-06-12 14:18:54 +02:00
Author
Owner

Fixed and pushed. All 1194 tests pass (0 regressions).

Changes made:

  1. non-combat-room-actions.ts — Wrapped library XP grant in if (progress < required) guard so completed rooms don't grant XP every tick
  2. non-combat-room-actions.ts — Added early return in tickTreasureRoom when progress >= required to skip loot processing
  3. combat-descent-actions.ts — Added non-combat room initialization (library, treasure, recovery) in onEnterRoomDescend during descent
  4. non-combat-room-reward-guards.test.ts — New regression test file with 8 tests covering all three fixes
✅ Fixed and pushed. All 1194 tests pass (0 regressions). **Changes made:** 1. `non-combat-room-actions.ts` — Wrapped library XP grant in `if (progress < required)` guard so completed rooms don't grant XP every tick 2. `non-combat-room-actions.ts` — Added early return in `tickTreasureRoom` when `progress >= required` to skip loot processing 3. `combat-descent-actions.ts` — Added non-combat room initialization (library, treasure, recovery) in `onEnterRoomDescend` during descent 4. `non-combat-room-reward-guards.test.ts` — New regression test file with 8 tests covering all three fixes
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Anexim/Mana-Loop#382