testsAndMisc/docs/superpowers/evidence/reverse-survivors-difficulty-tiers-2026-08-09.json
Krzysztof kuhy Rudnicki 5d0caa9725
Some checks failed
Pre-commit checks / pre-commit (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
reverse-survivors CI / check (push) Has been cancelled
reverse_survivors: difficulty tiers
Haunting, Normal and Crusade scale enemy hp and speed, the survivor's
health, your income, and the length of the night. Normal is exactly 1.0 on
every multiplier — it is the identity tier, which is what lets every
existing raw-value assertion keep passing untouched.

Enemy speed now derives from a single helper, so difficulty and frenzy
compose in one place rather than fighting at three call sites.

Also fixes a bug this surfaced: handleRestart ignored the selected tier, so
restarting after choosing Crusade silently reverted to Normal. The
react-hooks purity rule flagged Date.now() in the new handler, and
extracting restartSeed() exposed the omission.

Endless mode is deliberately left out — fmtTime(Infinity) renders
Infinity:NaN, which would cost a guard plus tests for a mode whose only
content is the same game but longer.

README rewritten for all four features, including the reversal of its old
placement promise.

160 tests, 100% coverage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VFyXexNjMQG9V7K8de17fc
2026-08-09 23:17:07 +02:00

43 lines
2.9 KiB
JSON

{
"intent": "Add Haunting/Normal/Crusade difficulty tiers and document the whole four-part extension in the README.",
"scope": [
"reverse_survivors/src/core/types.ts (DifficultyId, DifficultyConfig, DIFFICULTIES)",
"reverse_survivors/src/core/sim.ts (createInitialState parameter, enemySpeed helper, hp scaling), director.ts (regenRate rate)",
"reverse_survivors/src/App.tsx (tier selector), src/styles.css, README.md",
"Non-goal: endless mode and localStorage persistence, both deliberately excluded"
],
"changes": [
"Difficulty is a pure config object resolved once in createInitialState and stored on GameState, so no downstream code re-looks-it-up.",
"Normal is exactly 1.0 on every multiplier, which is what lets every pre-existing raw-hp assertion keep passing unchanged.",
"Enemy speed now derives from a single enemySpeed helper, so difficulty and frenzy compose in one place instead of fighting at three call sites.",
"regenRate gained an optional rate parameter defaulting to 1, keeping its existing call sites and assertions valid.",
"Fixed while wiring the selector: handleRestart ignored the chosen tier, so restarting after picking Crusade silently reverted to Normal. Surfaced by the react-hooks purity rule flagging Date.now() in the new handler, which led to extracting restartSeed().",
"README rewritten to cover the new units, powers, statuses and tiers, and to document the deliberate reversal of its former 'placement is never yours to choose' promise."
],
"verification": [
{
"command": "npm run check (typecheck + eslint --max-warnings 0 + vitest --coverage)",
"result": "pass",
"evidence": "160 tests passed. Coverage 100% on all four metrics: statements 531/531, branches 159/159, functions 101/101, lines 514/514."
},
{
"command": "npm run build",
"result": "pass",
"evidence": "tsc --noEmit clean, vite build in ~72ms, 210.08 kB / 66.26 kB gzip."
},
{
"command": "headless full-game playtest driving the real sim (vite-node)",
"result": "pass",
"evidence": "Banking energy then bursting wave+frenzy+ambush killed the survivor at t=53s with the warden's slow live (1.92s) and frenzy active (4.20s). A passive director loses on every tier; Crusade won at t=56s; Haunting and Normal went to the survivor. Same seed twice produced byte-identical outcomes."
}
],
"risks": [
"Tier multipliers are simulation-verified rather than human-playtested and may need retuning.",
"Pre-existing and unchanged here: with a trickle strategy the survivor out-kills a 6 energy/sec income, so banking and bursting is the effective approach."
],
"rollback": [
"git revert the commit; the game returns to a single fixed difficulty with no persisted state to migrate.",
"After rollback run `npm run check` in reverse_survivors/ and confirm the suite passes at 100% coverage."
]
}