Summary
Day 2 delivered the combat system overhaul: dedicated CombatSystem.js extracted from Simulation.js, DEX-based turn order, miss chance, and the first full Vitest test suite (24 tests, all passing).
Project Manager
Contribution: Reviewed Day 1 deferred items, confirmed scope for Day 2, approved Day 3 forward plan.
Key Decisions:
- Prioritized
CombatSystemextraction over any new content — the simulation loop needed a real combat model before we add more on top. - Confirmed miss chance design: 15% base, DEX-adjusted, floored at 5%. Prevents the mechanic from trivializing combat at high DEX while keeping it meaningful at low DEX.
- Kept Persistence (save/load) and Quest Generation as Day 3/4 candidates — not today.
- Updated IDEAS.md implicitly via scope decisions; Inventory and Multi-Hero remain low priority.
Reasoning: A combat system with no miss chance and no initiative order was a placeholder. DEX stats existed on heroes but had no mechanical effect. Closing that gap before adding quests or inventory was the right sequencing.
Developer
Contribution: Implemented all Day 2 source changes.
Files Created:
src/core/CombatSystem.js— Static-method class.resolve(hero, monsters)is the public entry point. Private helpers:#buildOrder,#heroTurn,#monsterTurn,#grantRewards,#missChance.
Files Modified:
src/entities/Monster.js— Addeddexfield to all five monster templates (Goblin 5, Wolf 7, Orc 3, Troll 2, Drake 4) and includeddexin the scaled stats object.src/core/Simulation.js— Removed#resolveCombatprivate method. Now delegates toCombatSystem.resolve(). Simulation is now a thin orchestrator.
Key Technical Decisions:
- Private static methods (
static #buildOrder) used for encapsulation — consistent with the coding standards'#prefix convention. - Turn order re-sorted each round from
monsters.filter(m => m.isAlive)so dead participants never act. - Miss chance formula:
max(5, 15 - (attackerDex - defenderDex) * 2). A DEX 8 Rogue vs a DEX 2 Troll has a 5% floor; a DEX 2 Troll vs a DEX 8 Rogue has a 27% miss chance. pickRandomused from shared utils so the mock seam is clean for tests.
Infrastructure Note: Template literal syntax in source files caused Vite/esbuild parse failures when written via the file tool; corrected by writing files through the bash heredoc path.
Designer
Contribution: Defined monster DEX values, reviewed combat feel from the simulation output.
Key Decisions:
- Wolf gets DEX 7 (faster than heroes on average) — Wolves should feel like quick harassers.
- Troll at DEX 2 — slow brutes. A Rogue (DEX 8) reliably gets the first swing.
- Drake at DEX 4 — moderate; not trivially slow but beatable by a Mage (DEX 5).
- Orc at DEX 3, Goblin at DEX 5 — Goblins are scrappy and fast; Orcs are methodical.
- Miss log lines use distinct verbs:
swings at ... but MISSES!for heroes,lunges at ... but MISSES!for monsters — adds texture without extra infrastructure. - Reviewed simulation run: Kael the Paladin reached Level 4 over 10 encounters before being overwhelmed by three Goblins in Blackmire Swamp on turn 11. DEX ordering was clearly visible in the combat log (Wolves and Goblins acting before the Paladin). Combat felt appropriately tense.
Tester
Contribution: Designed and implemented the full test suite.
Test Files Created:
src/entities/Hero.test.js— 11 tests covering: empty name throw, unknown class throw, Warrior stat init, damage mitigation with def, HP floor at 0, heal cap, heal return value, XP gain/level-up, no level-up below threshold, full heal on level-up, XP threshold scaling.src/entities/Monster.test.js— 7 tests covering: unknown type throw, base stat init, level scaling (hp/atk/xpReward scale; def/dex do not), damage mitigation, HP floor at 0, gold range (Goblin), gold range (Wolf).src/core/CombatSystem.test.js— 6 tests covering: hero wins vs goblin, hero dies vs overwhelming force, XP/gold grants, level-up during combat, mixed encounter clears cleanly, crit multiplier confirmed via Rogue vs Troll.
Testing Approach: Used vi.mock('../utils/Random.js') to mock chance, rollDice, and pickRandom entirely, making all combat outcomes deterministic without relying on Math.random sequencing (which caused infinite loops in initial attempts when both miss checks fired).
Results: 24/24 tests passing. npm test exits 0. Simulation runs end-to-end without errors.
Risk Log:
- Template-literal corruption in write path discovered mid-session; resolved by using bash heredoc for file writes.
- Initial CombatSystem tests caused OOM via infinite combat loop (both sides'
chance(miss)returned true whenMath.random = 0.01). Fixed by mocking at the module level rather thanMath.random. - Vitest
vi.clearAllMocks()resetsmockImplementation— tests must re-declare mocks in each test body orbeforeEach.
What Was Built
CombatSystem.js: a dedicated, tested combat resolution engine with DEX initiative and miss chance- Monsters now have DEX stats contributing to turn order and attack reliability
- Simulation.js cleaned up to a pure orchestration loop
- 24 unit tests covering entities and combat system
Verified: Kael the Paladin — Level 4, 172 gold, fell to three Goblins on Turn 11 in the Blackmire Swamp. Turn order, miss messages, crits, and level-up events all visible in the log.
Tomorrow (Day 3 Plan)
- Quest generation system: procedurally assign "slay N monsters" quests with XP/gold rewards on completion
- Quest tracker in World: active quest, progress counter, completion callback
- Logger additions:
[QUEST]event type for quest assigned/progress/complete - Consider: persistence stub (write hero state to JSON on simulation end)