Skip to content

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).

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.

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, like sim.hard_tuning. Only Survival reads it (active(sim) = Survival, no story, no tutorial).
  • Every knob is a static var multiplier per mode, registered as a remote/console tunable (registry entry + tools/tunable_docs/docs.d label + 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_tuning A/B (harder than today) is untouched and orthogonal.
  • /sim stays pure (no Node/Engine APIs); the save → sim.difficulty handoff happens render-side in MetaRunSetup.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.

  • survival_difficulty: String = "normal" | "hard". Missing or invalid → "normal". Saved as soon as the player flips it.
  • best_survival_s becomes best_survival_by_mode: Dictionary {normal, hard}. A legacy best_survival_s value 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_gold wallet.
  • Start menu Survival row: a NORMAL ‹ › HARD chip 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 / HARD tag 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-qa before merge.
  • Tutorial and Story never show or read the mode. Co-op (gated off): the host’s mode applies.
  • Telemetry: run_start / run_end payloads gain difficulty. A game setting like mode, 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_run compares 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 a control/src/whats_new.js build: null item. Marketing veracity rules apply (memory dark-cosmos-launch-assets).
  • 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_dead path (HardTuning’s tests/test_hard_tuning.gd style); XP is asserted as actually awarded via biomass, never by hand-setting pending_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 from balance-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 a docs/research/ doc; final values stay console tunables.
  • Chris’s device playtest: Eve on Normal, Toby on Hard.

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.

Per-mode wallets or shops; Story/Tutorial difficulty; changing the Dev hard_tuning A/B; the Orbit/DoT code issues; Adaptive (1.2).