Difficulty modes: Normal (default) + Hard for Survival (1.1)
Difficulty modes: Normal (default) + Hard for Survival
Section titled “Difficulty modes: Normal (default) + Hard for Survival”Status: design approved in chat by Chris, 2026-10-15. Target: store 1.1 (iOS + tvOS + macOS), feature freeze 2026-10-17. Adaptive mode is designed here but ships in 1.2.
Chris, after watching Eve play (2026-10-15): “we have been tuning for Toby, lets make the current setup a hard mode and lets do something to make it all more fun for normal level players … for this next release we need to make the normal level the default.”
Evidence it is needed: the Survival median death is ~68 s, 5/14 human runs die under 30 s, and
nobody in that sample reached a boss (docs/research/2026-10-14-qol-and-marketing-audit-1.1.md).
The new-player bot proxy survives a 59 s median on today’s tuning
(docs/research/2026-10-14-balance-1.1-proposals.md, branch balance-1.1-proposals).
Decisions (Chris, 2026-10-15)
Section titled “Decisions (Chris, 2026-10-15)”| Question | Decision |
|---|---|
| Scope for 1.1 | Normal + Hard. Adaptive designed, ships 1.2. Submission moves to the 10-17 freeze. |
| Gold per mode | ONE wallet and one shop; both modes pay 1.0x (Chris 2026-10-15). |
| What Normal changes | All four: gentler first 2-3 min, faster early levels, softer bosses, more forgiving hits. |
| Existing players | Everyone lands on Normal after the update; the choice is remembered. |
| Personal bests | Separate best per mode. |
| Picker | A NORMAL / HARD switch on the start-menu Survival row. No extra screen. |
| Orbit/Nova B1 | A weapon fix, not difficulty: ships as a separate remote patch for every mode, so Hard differs from today only for those two weapons. |
Architecture
Section titled “Architecture”A new sim/difficulty.gd (class_name Difficulty extends RefCounted), built on the
sim/hard_tuning.gd pattern:
Sim.difficulty: int(Difficulty.HARD,Difficulty.NORMAL), set at run start from the save, likesim.hard_tuning. Only Survival reads it (active(sim)= Survival, no story, no tutorial).- Every knob is a
static varmultiplier per mode, registered as a remote/console tunable (registry entry +tools/tunable_docs/docs.dlabel + LiveScope hook, per CLAUDE.md), in an “Difficulty” console group. Every Hard value is the identity (1.0 / off), so Hard is today’s game exactly, the seed-1234 baselines run on Hard unchanged, and no re-pin is needed. - Multipliers apply ON TOP of whatever base values are live, so remote-config balance patches keep working in both modes (a patch moves the base; Normal scales it).
- The existing Dev-only
DevFlags.hard_tuningA/B (harder than today) is untouched and orthogonal. /simstays pure (no Node/Engine APIs); the save →sim.difficultyhandoff happens render-side inMetaRunSetup.apply(the only place shop/meta state reaches a run).
Normal’s knobs (Hard = identity for all)
Section titled “Normal’s knobs (Hard = identity for all)”| Feel | Knob (Normal only) | Hook point | Starting value source |
|---|---|---|---|
| Gentler first 2-3 min | Field-density ramp: BIOMASS_TARGET starts at NORMAL_BIOMASS_START_FRAC and ramps linearly to full by NORMAL_BIOMASS_RAMP_S |
wave refill (Sim.BIOMASS_TARGET read) |
the emulated 200 → 400 over 120 s ramp in the balance proposals |
Shooter shot damage × NORMAL_SHOT_DMG_MULT; Charger contact × NORMAL_CHARGER_DMG_MULT and telegraph × NORMAL_CHARGER_TELEGRAPH_MULT |
spawn-time columns / shot spawn | A1c / A2 values | |
Opening one-shots (Chris 2026-10-18: “make the initial enemies die on one hit”): regular-enemy spawn HP × NORMAL_EARLY_HP_MULT (0.35), ramping linearly to 1.0 by NORMAL_EARLY_HP_RAMP_S (120 s). 0.35 puts a wave-1 Swarmer’s worst roll (14.4 HP) under one base Blaster shot (5.2). Bosses keep NORMAL_BOSS_HP_MULT; Wyrm / Halo Chain packs have their own spawn paths and are not scaled. Added after the 2026-10-16 calibration, so the 282 s median predates it |
Sim._spawn_one HP product, next to HardTuning.enemy_hp_mult |
tests/test_difficulty_early_hp.gd |
|
| Faster early levels | XP × NORMAL_XP_MULT while level < NORMAL_XP_BOOST_LEVELS, then 1.0 |
Sim._xp_worth (biomass path) |
new, bot-measured |
| Softer bosses | Boss HP × NORMAL_BOSS_HP_MULT, boss damage × NORMAL_BOSS_DMG_MULT |
same hooks HardTuning uses (boss_hp_mult, boss_dmg_mult) |
mirror of HardTuning |
| Forgiving hits | Post-hit grace × NORMAL_HIT_GRACE_MULT; max HP × NORMAL_MAX_HP_MULT at run start |
the hurt path’s grace timer; MetaRunSetup |
new |
| Gold | Run gold × GOLD_MULT_NORMAL (1.0) / GOLD_MULT_HARD (1.0) |
Sim._add_gold, next to meta_gold_mult |
economy sim checks |
Both modes pay 1.0x gold (Chris 2026-10-15; an earlier draft had Hard at 1.25x). Gold is paid per
kill, so Hard’s denser spawns already earn a surviving player more per minute; a bonus on top would
double-dip, and a Hard rate below Normal’s would make Normal the best place to farm gold. The rates
stay separate console tunables so the economy sim can move one if it shows a real gap. Run gold is
outside state_checksum (_add_gold’s comment), so a later rate change does not move the
determinism baselines.
Known code issues from the balance proposals (Orbit hit test ignores enemy size; armor floors all DoT ticks to 25%; no Orbit/Nova damage rung in Survival) are NOT in this scope. B1 ships as a patch.
Save (sim/meta_state.gd)
Section titled “Save (sim/meta_state.gd)”survival_difficulty: String="normal"|"hard". Missing or invalid →"normal". Saved as soon as the player flips it.best_survival_sbecomesbest_survival_by_mode: Dictionary{normal, hard}. A legacybest_survival_svalue loads as the Hard best. (That field shipped only on Dev saves, tonight’s ratings-prompt merge a67b0d36; no store save holds it.)- Gold stays the one
banked_goldwallet.
- Start menu Survival row: a
NORMAL ‹ › HARDchip on the row’s right. Pad / Siri Remote: left/right on the focused row flips it, select starts the run. Touch / mouse: a tap on the chip flips, a tap elsewhere on the row starts. Subtitle follows the mode: Normal “Endless waves, build your run”; Hard “The full challenge”. - Results screen + pause menu: a small
NORMAL/HARDtag beside the run time; “new best” is per mode. - Fit tests at the iPad (985), iPhone (1204) and TV (1280) profiles via
ShopLayoutFixture, with the chip on the row (CLAUDE.md fit-test rule).bh-visual-qabefore merge. - Tutorial and Story never show or read the mode. Co-op (gated off): the host’s mode applies.
Data, replays, ratings, copy
Section titled “Data, replays, ratings, copy”- Telemetry:
run_start/run_endpayloads gaindifficulty. A game setting likemode, not a new kind of data: the privacy page and ASC label do not change. - Replays: the replay header records the difficulty; playback applies it (a Hard replay on Normal would drift). The replay viewer shows it.
- Ratings prompt:
ReviewPrompt.note_runcompares against the current mode’s best. First-boss trigger unchanged. - Attract mode / autopilot: plays Normal (the default view); its telemetry carries the field.
- Copy: a What’s New line in
marketing/appstore/whats_new_1.1_{ios,tvos,macos}.txt(“Normal and Hard Survival: Normal is the new default, Hard is the full challenge”) and one description line; plus acontrol/src/whats_new.jsbuild: nullitem. Marketing veracity rules apply (memorydark-cosmos-launch-assets).
Testing and acceptance
Section titled “Testing and acceptance”- Determinism: the three pinned baseline files pass unchanged (Hard). A test asserts every Hard multiplier is the identity, gold rate included.
- Liveness: each Normal knob gets a test through the real spawn → hit →
_sweep_deadpath (HardTuning’stests/test_hard_tuning.gdstyle); XP is asserted as actually awarded via biomass, never by hand-settingpending_levelups. - Save: old save → Normal + legacy best as Hard best; round trip; corrupt value → Normal.
- UI: chip flip by pad left/right and by touch; row fit at the three device profiles.
- Balance acceptance (
tools/balance_probe, merged frombalance-1.1-proposals; 40 seeds per arm): Normal new-player proxy median survival ≥ 150 s with most runs seeing the first boss; Hard unchanged within noise. Economy sim on both modes to confirm 1.0x / 1.0x holds (only change a rate if it shows a real gap). Results in adocs/research/doc; final values stay console tunables. - Chris’s device playtest: Eve on Normal, Toby on Hard.
Adaptive mode (1.2, design only)
Section titled “Adaptive mode (1.2, design only)”Chris’s balance rule is “no rubber-banding enemies to the player” (memory
bullet-heaven-balance-philosophy). The defensible form adapts BETWEEN runs from recent results,
never within a run from the build: a third chip value, ADAPTIVE, that sets the next run’s position
on a Normal ↔ Hard blend (each knob interpolated) from the last few runs’ survival time, e.g. step
toward Hard after runs past a target time, toward Normal after early deaths. A strong build still
stomps weak enemies inside the run. Its gold rate follows the blend. Needs its own measuring pass and
Chris’s go-ahead; not in 1.1.
Out of scope
Section titled “Out of scope”Per-mode wallets or shops; Story/Tutorial difficulty; changing the Dev hard_tuning A/B; the
Orbit/DoT code issues; Adaptive (1.2).