← All entries

Daily Scrum Log — 2026-05-19 (Day 3)

Summary

Day 3 delivered the quest system: a two-class model (Quest + QuestSystem) with "slay N monsters" generation, kill tracking integrated into World, reward payouts and auto-reassignment in Simulation, a new [QUEST] log type in Logger, and a persistence stub that writes saves/hero-<name>.json at simulation end. Test count grew from 24 to 37 (all passing).


Project Manager

Contribution: Led scrum, locked scope, sequenced work to prevent integration conflicts.

Key Decisions:

  • Two-class quest model: Quest (data/state) vs QuestSystem (factory) — keeps responsibilities clean and each class independently testable.
  • Persistence scoped to write-only stub: no load logic until Day 4. Getting the file on disk proves the mechanic works before adding complexity.
  • Quest auto-reassignment on completion keeps the simulation feeling active — hero always has a contract.
  • Confirmed that quest target tiers should mirror the existing monster unlock curve in World.js to avoid assigning quests for monsters the hero hasn't encountered yet.

Reasoning: The quest system is the first feature that spans three layers (generation, World state, Simulation loop). Getting the contracts right between those layers before coding avoided interface bugs later.


Backend Developer

Contribution: Implemented all source changes for Day 3.

Files Created:

  • src/core/Quest.js — Data class. Fields: type, target, required, progress, xpReward, goldReward, completed. Key method: recordKill(monsterName) returns 'progress', 'complete', or false. Double-complete guard (if (this.completed) return false).
  • src/core/QuestSystem.js — Static factory. generate(heroLevel) selects from a tiered target list (tier 0: Goblin/Wolf; tier 1: +Orc; tier 2: +Troll/Drake), picks a random required count (randomInt(2, 3 + min(heroLevel, 5))), and scales rewards as required * 25 * heroLevel XP and required * 10 * heroLevel gold.

Files Modified:

  • src/entities/World.js — Added activeQuest and questsCompleted fields. Added recordKills(defeatedMonsters) method that iterates the dead list, calls quest.recordKill(m.name) on each, and stops early on completion.
  • src/core/Simulation.js — Added #assignQuest() private method (calls QuestSystem.generate, logs [QUEST] line). Added #processQuestProgress(defeatedMonsters) to handle progress/complete events after each encounter, pay out rewards, and immediately re-assign. Added #persist() method writing saves/hero-<name>.json via writeFileSync / mkdirSync.
  • src/utils/Logger.js — Added quest log type in bold blue. Fixed format string concatenation (avoiding template literals per Day 2 infrastructure note).

Key Technical Decisions:

  • recordKills breaks out of the loop on first 'complete' result — avoids overcounting kills toward the next quest before it's assigned.
  • mkdirSync('saves', { recursive: true }) creates the saves directory idempotently; wrapped in try/catch so a permissions error never kills the simulation.
  • All files written via bash heredoc to avoid template-literal parse corruption in the file write path.

Designer

Contribution: Defined quest flavor, log line format, target tier mapping.

Key Decisions:

  • Log format: Quest assigned: Slay 4 Goblins | Reward: 200 XP, 80 Gold — pipe separator keeps it compact on one line.
  • Progress format: Quest progress: Goblins 2/4 — uses plural of the target name to read naturally.
  • Completion format: Quest complete: Slay 4 Goblins! Rewarding 200 XP and 80 Gold. — exclamation mark adds moment of triumph.
  • Bold blue for [QUEST] — distinct from yellow (COMBAT) and magenta (LOOT); blue reads as "mission/objective" tone.
  • Target tier design: tier 0 = Goblin/Wolf (beginner zone feel), tier 1 adds Orc (mid tier), tier 2 adds Troll/Drake (advanced). Mirrors World's monster unlock curve exactly so no quest ever feels impossible.

Verified Output: Reviewed actual sim run — Thora the Warrior completed 2 quests (Slay 2 Goblins, then Slay 4 Goblins) before falling on Turn 14. Third quest (Slay 5 Trolls) appeared after leveling — tier progression visible. Log lines read clearly and distinct from combat noise.


Tester

Contribution: Designed and implemented the Quest.test.js test suite (13 new tests).

Test File Created:

  • src/core/Quest.test.js — Two describe blocks:
    • Quest (9 tests): empty-type/target throws, required < 1 throws, initial state (progress=0, completed=false), name pluralization (1 vs 2+), wrong-target recordKill returns false, progress case, completion case (returns 'complete', sets completed=true), double-complete guard (returns false, progress not incremented), summary format.
    • QuestSystem (4 tests): shape check for level 1 hero (type/target/required/xpReward/goldReward all correct), higher-level reward scaling, level 5 tier access (Drake available), level 1 tier restriction (only Goblin/Wolf).

Testing Approach: vi.mock('../utils/Random.js') for deterministic pickRandom and randomInt — same pattern as Day 2 CombatSystem tests. vi.clearAllMocks() in beforeEach to prevent state bleed between QuestSystem tests.

Results: 37/37 tests passing across all 4 test files. npm test exits 0.

Risk Log:

  • pickRandom.mockImplementation(arr => arr[arr.length - 1]) was the correct mock signature for the tier-5 test (Drake is the last entry in the full list) — avoids hard-coding an index that could break if the target array order changes.
  • Double-complete guard tested explicitly because quest chains reassign on first 'complete' — if the guard were absent, a second kill in the same encounter could register against a quest that was just replaced.

What Was Built

  • Quest.js: data object with kill tracking and double-complete guard
  • QuestSystem.js: tiered procedural quest generator scaling with hero level
  • World.js: activeQuest, questsCompleted, and recordKills integration
  • Simulation.js: quest assignment, progress/completion handling, reward payouts, and persistence stub
  • Logger.js: [QUEST] log type in bold blue
  • saves/hero-<name>.json: written at simulation end with full hero snapshot

Verified: Thora the Warrior completed 2 quests (Slay 2 Goblins → Slay 4 Goblins), received XP/gold rewards, was then assigned a Troll quest (tier 2 unlock at level 5) before falling on Turn 14. Save file confirmed written with correct fields.


Tomorrow (Day 4 Plan)

  • Persistence load: on simulation start, check saves/hero-<name>.json and resume from saved state
  • Hero selection: allow a fixed hero name rather than always picking randomly (to test continuity)
  • Consider: multiple hero simulation running in parallel — two heroes in different regions
  • Consider: quest variety — "collect" quest type (loot-based) in addition to slay