hayao 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/design/00-process/README.md +49 -0
- package/design/00-process/composition.md +148 -0
- package/design/00-process/core-loop.md +146 -0
- package/design/00-process/intent-to-brief.md +128 -0
- package/design/00-process/pillars.md +139 -0
- package/design/00-process/refine-and-handoff.md +156 -0
- package/design/00-process/the-twist.md +108 -0
- package/design/10-anchors/README.md +99 -0
- package/design/10-anchors/age-of-empires.md +103 -0
- package/design/10-anchors/baba-is-you.md +127 -0
- package/design/10-anchors/balatro.md +132 -0
- package/design/10-anchors/celeste.md +136 -0
- package/design/10-anchors/civilization.md +101 -0
- package/design/10-anchors/dead-cells.md +125 -0
- package/design/10-anchors/factorio.md +100 -0
- package/design/10-anchors/hades.md +127 -0
- package/design/10-anchors/into-the-breach.md +125 -0
- package/design/10-anchors/it-takes-two.md +104 -0
- package/design/10-anchors/loop-hero.md +131 -0
- package/design/10-anchors/nuclear-throne.md +130 -0
- package/design/10-anchors/outer-wilds.md +107 -0
- package/design/10-anchors/overcooked.md +102 -0
- package/design/10-anchors/peggle.md +133 -0
- package/design/10-anchors/reigns.md +99 -0
- package/design/10-anchors/return-of-the-obra-dinn.md +108 -0
- package/design/10-anchors/rimworld.md +101 -0
- package/design/10-anchors/shadow-of-mordor.md +106 -0
- package/design/10-anchors/slay-the-spire.md +127 -0
- package/design/10-anchors/starcraft.md +98 -0
- package/design/10-anchors/stardew-valley.md +103 -0
- package/design/10-anchors/tetris.md +122 -0
- package/design/10-anchors/vampire-survivors.md +122 -0
- package/design/20-genres/README.md +62 -0
- package/design/20-genres/action-adventure.md +126 -0
- package/design/20-genres/auto-battler.md +121 -0
- package/design/20-genres/bullet-hell.md +123 -0
- package/design/20-genres/city-builder.md +124 -0
- package/design/20-genres/coop-chaos.md +124 -0
- package/design/20-genres/deckbuilder.md +122 -0
- package/design/20-genres/exploration.md +131 -0
- package/design/20-genres/farming-sim.md +122 -0
- package/design/20-genres/grid-puzzle.md +126 -0
- package/design/20-genres/horde-survival.md +128 -0
- package/design/20-genres/incremental.md +120 -0
- package/design/20-genres/match3.md +120 -0
- package/design/20-genres/metroidvania.md +132 -0
- package/design/20-genres/narrative-decisions.md +122 -0
- package/design/20-genres/physics-arcade.md +124 -0
- package/design/20-genres/precision-platformer.md +127 -0
- package/design/20-genres/racing.md +126 -0
- package/design/20-genres/rhythm.md +125 -0
- package/design/20-genres/roguelike.md +122 -0
- package/design/20-genres/rts.md +169 -0
- package/design/20-genres/stealth.md +125 -0
- package/design/20-genres/survival-horror.md +124 -0
- package/design/20-genres/tactics.md +123 -0
- package/design/20-genres/tower-defense.md +120 -0
- package/design/30-systems/README.md +69 -0
- package/design/30-systems/accessibility.md +110 -0
- package/design/30-systems/boss-design.md +126 -0
- package/design/30-systems/build-diversity.md +120 -0
- package/design/30-systems/collectibles.md +108 -0
- package/design/30-systems/combat-model.md +113 -0
- package/design/30-systems/coop-and-competition.md +118 -0
- package/design/30-systems/counter-systems.md +115 -0
- package/design/30-systems/crafting.md +115 -0
- package/design/30-systems/difficulty-and-dda.md +114 -0
- package/design/30-systems/economy.md +117 -0
- package/design/30-systems/emergent-systems.md +114 -0
- package/design/30-systems/encounter-design.md +107 -0
- package/design/30-systems/enemy-ai.md +121 -0
- package/design/30-systems/enemy-archetypes.md +117 -0
- package/design/30-systems/faction-asymmetry.md +144 -0
- package/design/30-systems/grace.md +124 -0
- package/design/30-systems/mastery-curve.md +116 -0
- package/design/30-systems/meta-progression.md +114 -0
- package/design/30-systems/onboarding.md +115 -0
- package/design/30-systems/procgen-design.md +118 -0
- package/design/30-systems/progression.md +120 -0
- package/design/30-systems/resource-loops.md +112 -0
- package/design/30-systems/reward-schedules.md +124 -0
- package/design/30-systems/save-and-checkpoint.md +113 -0
- package/design/30-systems/session-structure.md +113 -0
- package/design/30-systems/skill-trees.md +111 -0
- package/design/30-systems/status-effects.md +111 -0
- package/design/30-systems/tech-tree.md +112 -0
- package/design/30-systems/telegraphs.md +106 -0
- package/design/30-systems/unit-rosters.md +123 -0
- package/design/40-worldbuilding/README.md +49 -0
- package/design/40-worldbuilding/aesthetic-direction.md +155 -0
- package/design/40-worldbuilding/faction-identity.md +136 -0
- package/design/40-worldbuilding/naming-and-tone.md +130 -0
- package/design/40-worldbuilding/narrative-delivery.md +129 -0
- package/design/40-worldbuilding/theme-vectors.md +134 -0
- package/design/40-worldbuilding/worldbuilding-scaffold.md +132 -0
- package/design/50-patterns/README.md +54 -0
- package/design/50-patterns/anti-frustration.md +121 -0
- package/design/50-patterns/emergence.md +121 -0
- package/design/50-patterns/feedback-loops.md +121 -0
- package/design/50-patterns/juice-choreography.md +124 -0
- package/design/50-patterns/mastery-and-flow.md +121 -0
- package/design/50-patterns/pacing-and-tension.md +120 -0
- package/design/50-patterns/readability.md +121 -0
- package/design/50-patterns/risk-reward.md +120 -0
- package/design/CONTRIBUTING.md +183 -0
- package/design/INDEX.md +133 -0
- package/design/README.md +86 -0
- package/design/_TEMPLATE.md +69 -0
- package/design/index.json +2720 -0
- package/package.json +2 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: system-procgen-design
|
|
3
|
+
title: Procedural Generation Design
|
|
4
|
+
kind: system
|
|
5
|
+
tags: [procgen, seeds, runs, variance, connectivity, controlled-randomness, generation, replayability]
|
|
6
|
+
summary: Runs, seeds, and variance as content — controlled randomness that always connects, proven before you tune a single number.
|
|
7
|
+
use-when: A design needs replayable, generated content (levels, dungeons, decks) instead of hand-authored maps.
|
|
8
|
+
composes-with: [system-session-structure, system-encounter-design, system-save-and-checkpoint, genre-roguelike]
|
|
9
|
+
anchors: [anchor-dead-cells, anchor-slay-the-spire]
|
|
10
|
+
verify-with: docs/FUN.md#10-traditional-roguelike
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Procedural Generation Design
|
|
14
|
+
|
|
15
|
+
**What it is.** Generating content from a **seed** instead of authoring it by
|
|
16
|
+
hand — so a run is a *fresh, reproducible* configuration of known parts. Procgen
|
|
17
|
+
turns "an agent hand-authors forty balanced rooms" (unreliable) into "an agent
|
|
18
|
+
calls a generator and gets forty *proven* rooms" (reliable). The design work is
|
|
19
|
+
choosing the **parts, the constraints, and the acceptance test** — not rolling
|
|
20
|
+
dice and hoping.
|
|
21
|
+
|
|
22
|
+
**Player fantasy / why it's fun.** *This run is mine.* Variance means the next run
|
|
23
|
+
surprises you; a seed means it's fair, not arbitrary. The pull is **discovery
|
|
24
|
+
under fairness** — every layout is new, but every layout is winnable (FUN.md §10).
|
|
25
|
+
|
|
26
|
+
## When to use / when NOT
|
|
27
|
+
|
|
28
|
+
| Use it when | Author by hand when |
|
|
29
|
+
|---|---|
|
|
30
|
+
| Replayability is the point (roguelike, survivors) | A crafted narrative sequence — procgen dilutes intent |
|
|
31
|
+
| Content *volume* exceeds what you can hand-build | A handful of set-piece bosses ([[system-boss-design]]) |
|
|
32
|
+
| You want a difficulty *band*, not fixed levels | Tutorial rooms — those teach a *specific* verb ([[system-onboarding]]) |
|
|
33
|
+
|
|
34
|
+
> **Connectivity first, numbers later.** The single most common procgen failure is
|
|
35
|
+
> an unreachable stair, item, or exit. Prove reachability across ~50 seeds *before*
|
|
36
|
+
> you tune a single difficulty value (FUN.md §10). A generator that can produce an
|
|
37
|
+
> unwinnable layout is a generator that *will*.
|
|
38
|
+
|
|
39
|
+
## Variants
|
|
40
|
+
|
|
41
|
+
| Variant | Generates | Grounded in Hayao |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| **Cellular cave** | organic open spaces | `generateCave(rng, opts)` (grep `docs/API.md`) |
|
|
44
|
+
| **Room-and-corridor dungeon** | connected rooms | `generateDungeon(rng, opts)` |
|
|
45
|
+
| **Solver-verified puzzle set** | in-band winnable levels | `generateLevels(factory, opts)` |
|
|
46
|
+
| **Grammar / template assembly** | rooms from hand-made chunks | your factory over `world.rng` |
|
|
47
|
+
| **Deck / drop draft** | reward pools | `pickEntry` / `weightedPick(rng, …)` |
|
|
48
|
+
| **Noise / distribution** | terrain, placement fields | `valueNoise` / `hashNoise` (stateless) |
|
|
49
|
+
|
|
50
|
+
## Tuning levers
|
|
51
|
+
|
|
52
|
+
| Lever | Turns up… | Watch for |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| **Fill % / smoothing** (caves) | openness vs. maze-ness | over-smoothing erases variety ([`sandboxes/procgen-lab`](../../sandboxes/procgen-lab/)) |
|
|
55
|
+
| **Difficulty band** | which candidates are kept | a band too narrow starves the generator (accept-rate) |
|
|
56
|
+
| **Variance budget** | how different runs are | too much = incoherent; too little = same run twice |
|
|
57
|
+
| **Reject hook** | genre rules a candidate must pass | the place to enforce "no start-adjacent goal" |
|
|
58
|
+
| **Dedupe key** | how near-identical layouts collapse | without it, two seeds ship the same map |
|
|
59
|
+
|
|
60
|
+
## How it wires to Hayao
|
|
61
|
+
|
|
62
|
+
- **The generator is solver-backed.** `generateLevels(factory, {count, minDepth,
|
|
63
|
+
maxDepth, minNodes, maxNodes, reject, dedupeKey})` builds a candidate from a
|
|
64
|
+
seeded `factory(rng) → Puzzle`, *solves* it, and keeps only the winnable ones
|
|
65
|
+
in-band. Every kept level carries the sub-seed that reproduces it exactly — so
|
|
66
|
+
the campaign that ships is **data (a list of seeds), not forty hand-written
|
|
67
|
+
maps** ([`src/content/generate.ts`](../../src/content/generate.ts)).
|
|
68
|
+
`generateLevelsReport` surfaces the accept-rate and difficulty spread.
|
|
69
|
+
`levelFromSeed(factory, seed)` rebuilds any one level from its seed.
|
|
70
|
+
- **Determinism is structural.** All randomness flows through `world.rng`;
|
|
71
|
+
sub-seeds derive from `hashString`, never wall-clock or `Math.random` — the same
|
|
72
|
+
`(seed, count, band, factory)` yields the same set on every machine (CLAUDE.md
|
|
73
|
+
invariant 2; FUN.md law 7).
|
|
74
|
+
- **Connectivity is a lint.** `connectedComponents` / `reachableRegions` /
|
|
75
|
+
`astarGrid` (grep `docs/API.md`) prove stairs + all loot + exits reachable across
|
|
76
|
+
a seed sweep before any tuning.
|
|
77
|
+
- **Learn the primitive alone:** [`sandboxes/procgen-lab`](../../sandboxes/procgen-lab/)
|
|
78
|
+
— `generateCave`, `valueNoise`, `autotileToCommands` with re-rollable seed, fill
|
|
79
|
+
%, smoothing passes. One mechanic, no genre.
|
|
80
|
+
|
|
81
|
+
## Fails when…
|
|
82
|
+
|
|
83
|
+
- **Unreachable content.** A stair, key, or exit behind an unbroken wall = an
|
|
84
|
+
unwinnable seed. The connectivity sweep catches it; skip the sweep and players
|
|
85
|
+
find it for you (FUN.md §10).
|
|
86
|
+
- **Tuning before connectivity.** Balancing numbers on a generator that still
|
|
87
|
+
produces dead layouts wastes both passes.
|
|
88
|
+
- **Wall-clock / Math.random inside generation.** Breaks reproducibility — a seed
|
|
89
|
+
no longer names a run, and goldens rot.
|
|
90
|
+
- **Variance for its own sake.** Randomness with no floor of *quality* produces
|
|
91
|
+
slop; the acceptance test is what makes variance content.
|
|
92
|
+
- **Same-map collapse.** No dedupe key and distinct seeds ship identical layouts.
|
|
93
|
+
|
|
94
|
+
## Verify
|
|
95
|
+
|
|
96
|
+
- **Connectivity sweep first:** stairs + all loot reachable across ~50 seeds
|
|
97
|
+
([FUN.md §10](../../docs/FUN.md#10-traditional-roguelike)).
|
|
98
|
+
- **Winnability, not experience:** a full-knowledge bot wins 10/10 random seeds —
|
|
99
|
+
that proves *a line exists*, the right claim for procgen (FUN.md §10).
|
|
100
|
+
- **Seeded reproducibility:** the same seed yields the same layout + a hash-identical
|
|
101
|
+
turn-log replay (FUN.md law 7).
|
|
102
|
+
- **In-band difficulty:** `generateLevelsReport` shows kept levels land inside the
|
|
103
|
+
target band; assert the ramp with `rampIssues`.
|
|
104
|
+
|
|
105
|
+
## Composes with
|
|
106
|
+
|
|
107
|
+
- [[system-session-structure]] — a seed defines one run; the run is the session container.
|
|
108
|
+
- [[system-encounter-design]] — generated rooms still need pockets and clear exits.
|
|
109
|
+
- [[system-save-and-checkpoint]] — a run resumes from `(seed, tuning, snapshot)`.
|
|
110
|
+
- [[genre-roguelike]] — the genre whose fairness *is* procgen connectivity.
|
|
111
|
+
- [[pattern-emergence]] — variance across systems is where generated stories come from.
|
|
112
|
+
|
|
113
|
+
## See also
|
|
114
|
+
|
|
115
|
+
- [`src/content/generate.ts`](../../src/content/generate.ts) — solver-backed level generation.
|
|
116
|
+
- [`sandboxes/procgen-lab`](../../sandboxes/procgen-lab/) — the generation primitives alone.
|
|
117
|
+
- [`docs/FUN.md` §10](../../docs/FUN.md#10-traditional-roguelike) — connectivity-first fairness.
|
|
118
|
+
- [[anchor-dead-cells]] · [[anchor-slay-the-spire]] — procgen as the shape of a run.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: system-progression
|
|
3
|
+
title: Progression — XP, Levels, the Power Curve
|
|
4
|
+
kind: system
|
|
5
|
+
tags: [progression, xp, levels, power-curve, pacing, growth, vertical, horizontal]
|
|
6
|
+
summary: Turning play into steadily-earned power; pacing the curve so growth never stalls and never trivialises the challenge it feeds.
|
|
7
|
+
use-when: The design promises the player gets stronger over time and you need to shape how fast, along which axes, and how it stays fun.
|
|
8
|
+
composes-with: [system-skill-trees, system-economy, system-reward-schedules, system-mastery-curve, system-difficulty-and-dda]
|
|
9
|
+
anchors: [anchor-hades, anchor-vampire-survivors, anchor-dead-cells]
|
|
10
|
+
verify-with: docs/FUN.md#14-incrementalidle
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Progression — XP, Levels, the Power Curve
|
|
14
|
+
|
|
15
|
+
**What it is.** The **curve** that converts time-and-skill spent into durable
|
|
16
|
+
power. XP fills a bar, the bar pops a level, the level buys a gain. The design
|
|
17
|
+
work is not the bar — it is the *shape* of the curve and *what each level is
|
|
18
|
+
worth*.
|
|
19
|
+
|
|
20
|
+
**Player fantasy / why it's fun.** "I am becoming stronger, and I can feel it."
|
|
21
|
+
Every session ends with the character measurably ahead of where it started. The
|
|
22
|
+
pull is the **next** gain always sitting just inside reach.
|
|
23
|
+
|
|
24
|
+
## When to use / when NOT
|
|
25
|
+
|
|
26
|
+
| Use it when | Skip it when |
|
|
27
|
+
|---|---|
|
|
28
|
+
| The fun is a rising arc — you *build* toward power | Mastery is the whole point; power is flat (Tetris, chess) |
|
|
29
|
+
| Sessions need a between-run ledger of "I earned something" | A run should reset clean every time with no carryover |
|
|
30
|
+
| You want a difficulty dial that the *player* turns by playing | Handing power out would erase the challenge that IS the game |
|
|
31
|
+
|
|
32
|
+
If the game is pure execution (**[[genre-precision-platformer]]**,
|
|
33
|
+
**[[genre-bullet-hell]]**), don't bolt on XP — the level *is* the reward. A
|
|
34
|
+
platformer's "progression" is new *verbs* (**[[genre-metroidvania]]**), not
|
|
35
|
+
bigger numbers.
|
|
36
|
+
|
|
37
|
+
## Variants
|
|
38
|
+
|
|
39
|
+
| Variant | Power comes from | Feels like | Example |
|
|
40
|
+
|---|---|---|---|
|
|
41
|
+
| **Vertical** | Bigger numbers on the same actions | Overwhelming what used to threaten you | Diablo levels; Vampire Survivors' in-run levels |
|
|
42
|
+
| **Horizontal** | New *options*, not more damage | A wider toolbox, same lethality | Zelda items; Hades' boon variety |
|
|
43
|
+
| **In-run (soft)** | Growth reset each run | A build arc per session | VS level-ups; roguelite per-run picks |
|
|
44
|
+
| **Meta (hard)** | Growth persists between runs | A campaign under the runs | See [[system-meta-progression]] |
|
|
45
|
+
| **Milestone** | Discrete unlocks at thresholds | Earned checkpoints, not a smooth ramp | "Beat act 2 → new class" |
|
|
46
|
+
|
|
47
|
+
Most games layer two: an **in-run** vertical ramp under a **meta** horizontal
|
|
48
|
+
one (Hades, Dead Cells). Name which axis carries the fantasy before you tune.
|
|
49
|
+
|
|
50
|
+
## Tuning levers
|
|
51
|
+
|
|
52
|
+
| Lever | What it controls | Healthy range / rule |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| **XP-to-next curve** | How fast levels come | Gentle geometric (×1.1–1.4/level). Flat = trivial; steep = a wall |
|
|
55
|
+
| **Power-per-level** | The size of a gain | Each level must be *felt* — no "+0.3% crit" filler levels |
|
|
56
|
+
| **Time-to-first-level** | The onboarding hook | Fast (< 60–90s of play). The first pop teaches the loop |
|
|
57
|
+
| **Power-vs-challenge gap** | Whether growth trivialises | Enemies/costs must ramp *with* the player (law 3 inequality) |
|
|
58
|
+
| **Level cap / soft cap** | Where the curve flattens | Cap before gains stop being felt, or switch axes (vertical→horizontal) |
|
|
59
|
+
| **Catch-up** | Whether a behind player recovers | Optional; XP scaling on lower levels. Pairs with [[system-difficulty-and-dda]] |
|
|
60
|
+
|
|
61
|
+
The one number that breaks games: **power outrunning challenge.** State it as a
|
|
62
|
+
law-3 inequality — *enemy HP(t) grows ≥ player DPS(t)* — and assert it, exactly
|
|
63
|
+
as horde-survival asserts superlinear spawn pressure against multiplicative
|
|
64
|
+
build growth (**[[FUN.md §6]]**).
|
|
65
|
+
|
|
66
|
+
## How it wires to Hayao
|
|
67
|
+
|
|
68
|
+
- **Power is state.** XP, level, and stat totals live in `world.state`; the
|
|
69
|
+
level-up is a **sim step**, and the pick that spends it is an **input action**
|
|
70
|
+
(never a direct mutation) so replays and goldens stay honest — the same rule
|
|
71
|
+
incremental/idle lives by (**[[FUN.md §14]]**).
|
|
72
|
+
- **The pop is choreography.** The sim resolves the level instantly and *returns*
|
|
73
|
+
a "leveled-up" beat; the view (flash, chime, particles on `LAYER_HUD`) replays
|
|
74
|
+
it and is `cosmetic = true`, deletable without changing `world.hash()`
|
|
75
|
+
(**[[FUN.md §6]]**).
|
|
76
|
+
- **The curve is content, not code.** Pace levels the way `src/content/`
|
|
77
|
+
generates and ramps levels: express the difficulty series and feed it to
|
|
78
|
+
`assertRamp`/`rampIssues` (grep `docs/API.md`) so "the curve has no deserts and
|
|
79
|
+
no walls" is a test, not a vibe. See the generated-campaign flagship
|
|
80
|
+
`examples/lanternfold/`.
|
|
81
|
+
- **Meta power persists** through `SaveManager` — see [[system-meta-progression]].
|
|
82
|
+
|
|
83
|
+
## Fails when…
|
|
84
|
+
|
|
85
|
+
- **Filler levels.** A gain you can't feel is a chore bar. Fewer, bigger levels
|
|
86
|
+
beat many tiny ones.
|
|
87
|
+
- **The curve deserts.** A long stretch with no reachable next gain — the
|
|
88
|
+
incremental sin (**[[FUN.md §14]]**). Assert first-gain times per tier.
|
|
89
|
+
- **Power laps challenge.** The build trivialises the content and the game turns
|
|
90
|
+
to autopilot; or challenge laps power and it's a wall. Both break the CI
|
|
91
|
+
*window* (**[[FUN.md §6]]**).
|
|
92
|
+
- **Vertical-only forever.** Numbers with no new decisions get boring; introduce
|
|
93
|
+
a horizontal axis (options, [[system-skill-trees]]) once damage stops thrilling.
|
|
94
|
+
- **Grind to progress.** If the only path to the next level is repeating a solved
|
|
95
|
+
encounter, you've built a timer, not a game.
|
|
96
|
+
|
|
97
|
+
## Verify
|
|
98
|
+
|
|
99
|
+
- Pacing/no-deserts and the payback discipline: **[[FUN.md §14]]** (incremental).
|
|
100
|
+
- Power-vs-challenge as an asserted inequality: **[[FUN.md §6]]** (horde) and law
|
|
101
|
+
3 (derive constraints).
|
|
102
|
+
- Ramp shape as a test: `assertRamp`/`rampIssues` over the level/curve series —
|
|
103
|
+
the same instrument `examples/lanternfold/` uses.
|
|
104
|
+
- Skill-delta: intended play out-earns null play by a margin (universal law 2).
|
|
105
|
+
|
|
106
|
+
## Composes with
|
|
107
|
+
|
|
108
|
+
- [[system-skill-trees]] — where horizontal power *branches* into builds.
|
|
109
|
+
- [[system-economy]] — XP is one faucet; levels are one sink among many.
|
|
110
|
+
- [[system-meta-progression]] — the persistent layer under run-scoped growth.
|
|
111
|
+
- [[system-mastery-curve]] — power should *raise the ceiling*, not replace skill.
|
|
112
|
+
- [[system-reward-schedules]] — the drip that fills the XP bar between levels.
|
|
113
|
+
- [[pattern-pacing-and-tension]] — the level curve IS a pacing curve.
|
|
114
|
+
|
|
115
|
+
## See also
|
|
116
|
+
|
|
117
|
+
- [`docs/FUN.md`](../../docs/FUN.md) §6, §14 — the pacing and challenge-gap proofs.
|
|
118
|
+
- `src/content/generate.ts` · `campaign.ts` — generate-and-ramp content, don't
|
|
119
|
+
hand-author the curve.
|
|
120
|
+
- `examples/lanternfold/` — a 42-level generated, ramp-asserted campaign.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: system-resource-loops
|
|
3
|
+
title: Resource Loops — Gather → Convert → Spend
|
|
4
|
+
kind: system
|
|
5
|
+
tags: [resource-loops, gather, convert, spend, bottleneck, production, pacing, chains]
|
|
6
|
+
summary: The gather→convert→spend cycle that structures effort; bottlenecks placed on purpose are the pacing, not a bug.
|
|
7
|
+
use-when: The game asks the player to turn raw inputs into refined outputs into results, and you need the chain to breathe rather than stall or trivialize.
|
|
8
|
+
composes-with: [system-economy, system-crafting, system-tech-tree, system-progression]
|
|
9
|
+
anchors: [anchor-factorio, anchor-stardew-valley]
|
|
10
|
+
verify-with: docs/FUN.md#14-incrementalidle
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Resource Loops — Gather → Convert → Spend
|
|
14
|
+
|
|
15
|
+
**What it is.** The **cycle** at the heart of production games: *gather* a raw
|
|
16
|
+
resource, *convert* it into something more useful, *spend* the result on progress —
|
|
17
|
+
which unlocks better gathering, and the loop turns again, wider. The design work
|
|
18
|
+
is deciding where the loop **narrows** — the bottleneck the player must solve.
|
|
19
|
+
|
|
20
|
+
**Player fantasy / why it's fun.** "I built the pipeline that makes the thing that
|
|
21
|
+
makes me stronger." Each loop closed is a small system mastered. The pull is the
|
|
22
|
+
*next* bottleneck — the one resource you don't have enough of yet.
|
|
23
|
+
|
|
24
|
+
## When to use / when NOT
|
|
25
|
+
|
|
26
|
+
| Use it when | Skip it when |
|
|
27
|
+
|---|---|
|
|
28
|
+
| Progress runs through *making*, not just buying | The game has no crafting/production layer |
|
|
29
|
+
| You want pacing to emerge from bottlenecks, not timers | A flat currency ([[system-economy]]) already carries it |
|
|
30
|
+
| Chains of resources create planning/optimization depth | Extra steps would be busywork with no decision |
|
|
31
|
+
|
|
32
|
+
A resource loop is **[[system-economy]]** with *structure*: instead of one bucket,
|
|
33
|
+
a directed chain where each node's output feeds the next. Use it when the *shape*
|
|
34
|
+
of the chain — what feeds what — is itself a puzzle.
|
|
35
|
+
|
|
36
|
+
## Variants
|
|
37
|
+
|
|
38
|
+
| Variant | Shape | Depth from | Example |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| **Linear chain** | A → B → C → goal | Clear ramp; one bottleneck at a time | Stardew crops → artisan goods → cash |
|
|
41
|
+
| **Branching tree** | One input, many outputs | Prioritisation | Factorio iron → plates/gears/etc |
|
|
42
|
+
| **Converging web** | Many inputs, one output | Logistics puzzle | Factorio science packs |
|
|
43
|
+
| **Cyclic (renewable)** | Output feeds back to input | Sustainable scaling | Seeds from crops; power → mining → power |
|
|
44
|
+
| **Sink loop** | Convert → spend → gone | Pacing pressure | Fuel: gather → burn → gather (survival) |
|
|
45
|
+
|
|
46
|
+
## Tuning levers
|
|
47
|
+
|
|
48
|
+
| Lever | What it controls | Healthy range / rule |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| **Bottleneck placement** | *Where* the player feels scarcity | One clear binding constraint at a time — that's the current puzzle |
|
|
51
|
+
| **Conversion ratio** | Inputs per output | Legible (2:1, 5:1), not 7.3:1 mystery math |
|
|
52
|
+
| **Chain length** | Steps from raw to result | Long enough to plan, short enough to hold in head; add steps as content, not on day one |
|
|
53
|
+
| **Throughput vs storage** | Flow rate vs stockpile | Flow-limited = active play; storage-limited = idle waiting |
|
|
54
|
+
| **Renewability** | Whether a resource runs out | Renewable = sustainable; finite = a clock ([[system-economy]] inflation) |
|
|
55
|
+
| **Parallel loops** | How many run at once | More loops = more to juggle; ramp the count |
|
|
56
|
+
|
|
57
|
+
The bottleneck **is** the pacing. A loop with no binding constraint is a firehose —
|
|
58
|
+
nothing to optimise. A loop with a *permanent* bottleneck is a wall. Good design
|
|
59
|
+
*moves* the bottleneck: solve iron, now you're copper-limited, now power-limited.
|
|
60
|
+
Each move is a fresh puzzle — the same "no deserts, no walls" discipline as an
|
|
61
|
+
economy's pacing window (**[[FUN.md §14]]**).
|
|
62
|
+
|
|
63
|
+
## How it wires to Hayao
|
|
64
|
+
|
|
65
|
+
- **The chain is data.** Resource counts and converter states live in
|
|
66
|
+
`world.state`; each gather/convert/spend is an **input action**, so the whole
|
|
67
|
+
production run replays and hashes (**[[FUN.md §14]]**, law 7).
|
|
68
|
+
- **Pacing is provable.** Balance-sim the loop with a bot that plays it out, then
|
|
69
|
+
assert *monotone production* and *no bottleneck desert* — the exact incremental
|
|
70
|
+
verify. The farming truth applies too: surface the player-critical number ("N
|
|
71
|
+
iron short") the way farming surfaces "nights left" (**[[FUN.md §15]]**).
|
|
72
|
+
- **Ratios are law-3 inequalities.** "Converter throughput ≥ demand at tier T" is a
|
|
73
|
+
constraint you state in a comment and assert against the actual config, not a
|
|
74
|
+
vibe (**[[FUN.md law 3]]**).
|
|
75
|
+
- **The reinvest-vs-hoard delta** is your skill proof: a bot that reinvests output
|
|
76
|
+
into more capacity beats one that hoards — farming measured 740 vs 236
|
|
77
|
+
(**[[FUN.md §15]]**, law 2).
|
|
78
|
+
|
|
79
|
+
## Fails when…
|
|
80
|
+
|
|
81
|
+
- **No bottleneck.** Everything abundant → no decisions → the loop is a chore of
|
|
82
|
+
clicking through steps. Always bind *one* constraint.
|
|
83
|
+
- **A permanent wall.** A bottleneck that never resolves halts progress. Move it.
|
|
84
|
+
- **Mystery ratios.** Illegible conversion math the player can't plan around.
|
|
85
|
+
- **Idle throughput.** If output accrues while away with no active choice, it's a
|
|
86
|
+
timer, not a loop.
|
|
87
|
+
- **Chain too long day one.** Ten steps before the first payoff buries the fun.
|
|
88
|
+
Introduce depth as the player scales, the way `src/content/` gates mechanics per
|
|
89
|
+
act.
|
|
90
|
+
|
|
91
|
+
## Verify
|
|
92
|
+
|
|
93
|
+
- Monotone production, no desert, pacing windows — the balance-sim:
|
|
94
|
+
**[[FUN.md §14]]**.
|
|
95
|
+
- Reinvest-vs-hoard skill delta: **[[FUN.md §15]]**, law 2.
|
|
96
|
+
- Conversion/throughput ratios as asserted inequalities: **[[FUN.md law 3]]**.
|
|
97
|
+
- Surface the binding number to the player (the farming truth): **[[FUN.md §15]]**.
|
|
98
|
+
|
|
99
|
+
## Composes with
|
|
100
|
+
|
|
101
|
+
- [[system-economy]] — a resource loop is an economy with an explicit chain.
|
|
102
|
+
- [[system-crafting]] — recipes are the *convert* step made combinatorial.
|
|
103
|
+
- [[system-tech-tree]] — research gates unlock new links in the chain.
|
|
104
|
+
- [[system-progression]] — spending the loop's output is how you grow.
|
|
105
|
+
- [[pattern-emergence]] — interacting loops (power↔mining) generate depth.
|
|
106
|
+
|
|
107
|
+
## See also
|
|
108
|
+
|
|
109
|
+
- [`docs/FUN.md`](../../docs/FUN.md) §14 (pacing) · §15 (farming solvency + reinvest
|
|
110
|
+
delta) — the loop proofs.
|
|
111
|
+
- **[[anchor-factorio]]** (the loop as the toy) · **[[anchor-stardew-valley]]**
|
|
112
|
+
(gentle linear chains).
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: system-reward-schedules
|
|
3
|
+
title: Reward Schedules — Drops, Chests & Ethical Compulsion
|
|
4
|
+
kind: system
|
|
5
|
+
tags: [rewards, variable-ratio, loot, drops, chests, compulsion, dark-patterns, ethics]
|
|
6
|
+
summary: How often and how surprisingly the game pays out; variable-ratio's grip, and the honest line between compelling and exploitative.
|
|
7
|
+
use-when: The design hands out loot, drops, or chests and you need the payout rhythm to feel exciting without tipping into manipulation.
|
|
8
|
+
composes-with: [system-economy, system-collectibles, system-meta-progression, system-progression, system-procgen-design]
|
|
9
|
+
anchors: [anchor-vampire-survivors, anchor-hades, anchor-peggle]
|
|
10
|
+
verify-with: docs/FUN.md#19-physics-arcade-breakoutpeggle
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Reward Schedules — Drops, Chests & Ethical Compulsion
|
|
14
|
+
|
|
15
|
+
**What it is.** The **schedule** on which the game pays out — fixed (every N), or
|
|
16
|
+
**variable-ratio** (random, averaging N). Variable-ratio is the most powerful
|
|
17
|
+
reinforcement pattern known, which is exactly why it demands an ethical hand. This
|
|
18
|
+
module is about wielding its *grip* to make earning thrilling — and refusing its
|
|
19
|
+
use to *extract*.
|
|
20
|
+
|
|
21
|
+
**Player fantasy / why it's fun.** "Maybe *this* one." Anticipation is the reward;
|
|
22
|
+
the drop is the payoff. Uncertainty makes a trivial input (Peggle's last peg,
|
|
23
|
+
opening a chest) feel enormous (**[[anchor-peggle]]**, maximal juice on trivial
|
|
24
|
+
input).
|
|
25
|
+
|
|
26
|
+
## When to use / when NOT
|
|
27
|
+
|
|
28
|
+
| Use it when | Skip it when |
|
|
29
|
+
|---|---|
|
|
30
|
+
| Loot/drops are a core reward channel | Rewards are deterministic and that's the point (puzzle clears) |
|
|
31
|
+
| Anticipation itself is fun (chests, gacha-of-cosmetics) | The randomness would gate *required* progress unfairly |
|
|
32
|
+
| You want surprise to punctuate a grind | It'd become a slot machine dressed as a game |
|
|
33
|
+
|
|
34
|
+
**The honesty line.** Variable-ratio is fine for *cosmetics, flavor, and bonus*
|
|
35
|
+
rewards where the base game is complete without them. It becomes a **dark pattern**
|
|
36
|
+
when it gates required power behind paid randomness, hides odds, or engineers
|
|
37
|
+
loss-aversion (streaks you'll "lose"). Design compulsion you'd be proud to explain.
|
|
38
|
+
|
|
39
|
+
## Variants
|
|
40
|
+
|
|
41
|
+
| Variant | Schedule | Feels like | Watch for |
|
|
42
|
+
|---|---|---|---|
|
|
43
|
+
| **Fixed-ratio** | Reward every N | Reliable, plannable | Predictable → less exciting |
|
|
44
|
+
| **Variable-ratio** | Random, averages N | The slot-machine pull | Ethics; the honest use is *cosmetic/bonus* |
|
|
45
|
+
| **Fixed-interval** | Reward every T time | Daily-login cadence | Retention manipulation if punitive |
|
|
46
|
+
| **Pity / bad-luck protection** | Guaranteed by attempt N | Fairness floor on RNG | *Always* add this to variable-ratio |
|
|
47
|
+
| **Tiered / weighted** | Common→rare distribution | Chase the rare | Odds must be *shown* |
|
|
48
|
+
| **Deterministic reveal** | RNG resolved, shown honestly | Trust | This is the ethical default |
|
|
49
|
+
|
|
50
|
+
## Tuning levers
|
|
51
|
+
|
|
52
|
+
| Lever | What it controls | Healthy range / rule |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| **Base rate** | How often you pay out | Frequent small + rare large — a steady drip with peaks |
|
|
55
|
+
| **Variance** | How swingy | Enough surprise to thrill; not so much it feels arbitrary |
|
|
56
|
+
| **Pity timer** | The fairness floor | *Mandatory* on any variable-ratio — guarantee by attempt N |
|
|
57
|
+
| **Odds transparency** | Whether players know the chances | Show them. Hidden odds are a dark pattern, full stop |
|
|
58
|
+
| **What's behind RNG** | Cosmetic vs required power | Keep *required* progress off the random schedule |
|
|
59
|
+
| **Anticipation window** | The pause before reveal | Long enough to build tension, short enough not to annoy ([[pattern-juice-choreography]]) |
|
|
60
|
+
|
|
61
|
+
### Dark patterns to refuse
|
|
62
|
+
|
|
63
|
+
- **Hidden odds** — never. Publish them.
|
|
64
|
+
- **Pay-to-random for power** — required strength behind a paywalled RNG box.
|
|
65
|
+
- **Loss-aversion engineering** — "your streak resets in 2h" pressure.
|
|
66
|
+
- **Near-miss manufacturing** — faking "so close!" reveals to bait retries.
|
|
67
|
+
- **FOMO scarcity** — artificial time-limited rarity to force impulse.
|
|
68
|
+
|
|
69
|
+
Compulsion is a tool; extraction is a choice. The Codex's stance: use anticipation
|
|
70
|
+
to *reward* engagement, never to *punish* disengagement.
|
|
71
|
+
|
|
72
|
+
## How it wires to Hayao
|
|
73
|
+
|
|
74
|
+
- **RNG is sim, through `world.rng`.** Every drop rolls on `world.rng` — never
|
|
75
|
+
`Math.random` (CLAUDE.md invariant 2). This makes the whole schedule
|
|
76
|
+
*deterministic per seed*: a golden run hashes identically, and you can *audit*
|
|
77
|
+
the payout distribution in a test.
|
|
78
|
+
- **Resolve, then choreograph.** The sim resolves the drop instantly and *returns*
|
|
79
|
+
the reveal as choreography; the view plays the chest-open, the flash, the rarity
|
|
80
|
+
color (`LAYER_HUD`, `cosmetic = true`) — deletable without changing the outcome
|
|
81
|
+
(**[[FUN.md law 6]]**). The anticipation is *view time over sim truth*, like
|
|
82
|
+
match-3's cascade script (**[[FUN.md §13]]**).
|
|
83
|
+
- **Audit odds and pity in CI.** Roll N drops over seeds; assert the empirical
|
|
84
|
+
distribution matches the *stated* odds and that pity fires by attempt N — the
|
|
85
|
+
same "intent honesty" audit deckbuilders run on telegraphs (**[[FUN.md §11]]**).
|
|
86
|
+
- **Prove the base game is complete without the RNG** — a bot that never opens a
|
|
87
|
+
random reward still clears the game. That's the ethical proof.
|
|
88
|
+
|
|
89
|
+
## Fails when…
|
|
90
|
+
|
|
91
|
+
- **No pity floor.** Pure RNG can strand a player for hundreds of attempts — cruel.
|
|
92
|
+
Always cap it.
|
|
93
|
+
- **Hidden or lying odds.** The distribution doesn't match the shown numbers — an
|
|
94
|
+
auditable, shippable-blocking bug *and* an ethics failure.
|
|
95
|
+
- **Required power behind RNG.** Progress gated on luck (or a wallet) — the game is
|
|
96
|
+
now a slot machine.
|
|
97
|
+
- **Reveal fatigue.** Anticipation windows so long or frequent they annoy — tune
|
|
98
|
+
the pause.
|
|
99
|
+
- **Reward inflation.** Everything's legendary → nothing is. Rarity needs scarcity
|
|
100
|
+
([[system-economy]] inflation).
|
|
101
|
+
|
|
102
|
+
## Verify
|
|
103
|
+
|
|
104
|
+
- Odds/pity distribution audit over seeds (intent honesty): **[[FUN.md §11]]**.
|
|
105
|
+
- Determinism per seed (golden hash of a drop run): **[[FUN.md law 7]]**.
|
|
106
|
+
- Reveal is cosmetic — sim resolves, view replays, hashes equal: **[[FUN.md law 6]]**.
|
|
107
|
+
- Base game clears without opening any random reward (a null-reward baseline):
|
|
108
|
+
**[[FUN.md law 4]]**.
|
|
109
|
+
|
|
110
|
+
## Composes with
|
|
111
|
+
|
|
112
|
+
- [[system-economy]] — drops are a faucet; rarity is inflation control.
|
|
113
|
+
- [[system-collectibles]] — variable-ratio drives set completion.
|
|
114
|
+
- [[system-meta-progression]] — the meta ledger fed by run rewards.
|
|
115
|
+
- [[system-procgen-design]] — seeded randomness shares the same rng discipline.
|
|
116
|
+
- [[pattern-juice-choreography]] — the anticipation→reveal is pure choreography.
|
|
117
|
+
- [[pattern-risk-reward]] — push-your-luck chests turn the schedule into a decision.
|
|
118
|
+
|
|
119
|
+
## See also
|
|
120
|
+
|
|
121
|
+
- [`docs/FUN.md`](../../docs/FUN.md) §11 (intent-honesty audit) · law 6 (resolve-
|
|
122
|
+
then-choreograph) · law 4 (null baseline).
|
|
123
|
+
- [`docs/JUICE.md`](../../docs/JUICE.md) — the anticipation→reveal feel gates.
|
|
124
|
+
- **[[anchor-peggle]]** — maximal juice on a trivial, uncertain input.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: system-save-and-checkpoint
|
|
3
|
+
title: Save & Checkpoint
|
|
4
|
+
kind: system
|
|
5
|
+
tags: [save, checkpoint, retry, respect-time, snapshot, hash, round-trip, resume]
|
|
6
|
+
summary: Save, checkpoint, and retry that respect the player's time — built free on Hayao's pure-state snapshot/hash round-trip.
|
|
7
|
+
use-when: The player can lose progress, needs to stop and resume, or should retry a failure without ceremony.
|
|
8
|
+
composes-with: [system-session-structure, system-meta-progression, system-grace, pattern-anti-frustration]
|
|
9
|
+
anchors: [anchor-celeste, anchor-hades]
|
|
10
|
+
verify-with: docs/CONVENTIONS.md
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Save & Checkpoint
|
|
14
|
+
|
|
15
|
+
**What it is.** The machinery that **preserves progress** — full saves, mid-level
|
|
16
|
+
checkpoints, and instant retry after failure. Its real subject is **respect for the
|
|
17
|
+
player's time**: never make someone redo what they've mastered, and never make a
|
|
18
|
+
failure cost more than the mistake did.
|
|
19
|
+
|
|
20
|
+
**Player fantasy / why it's fun.** Trust and momentum. Instant retry keeps a
|
|
21
|
+
platformer in flow (Celeste: "each retry is instant, keeping the momentum alive").
|
|
22
|
+
A checkpoint before a boss means the *fight* is the challenge, not the walk to it.
|
|
23
|
+
The pull is that the game values your hours as much as you do.
|
|
24
|
+
|
|
25
|
+
## When to use / when NOT
|
|
26
|
+
|
|
27
|
+
| Design it carefully when | It's simpler when |
|
|
28
|
+
|---|---|
|
|
29
|
+
| Runs/levels are long enough to lose real progress | A 90-second arcade loop — restart is the save |
|
|
30
|
+
| Failure is frequent (platformer, roguelite) | A turn-based game you can quit anytime (state is always saveable) |
|
|
31
|
+
| The player stops and resumes across sittings | A pure toy with no progress to keep |
|
|
32
|
+
|
|
33
|
+
> **The cost of failure should equal the mistake, not the walk back to it.**
|
|
34
|
+
> Re-treading solved content to reach the hard part is a tax on time, not a test of
|
|
35
|
+
> skill. Checkpoint *at* the challenge; retry *into* it.
|
|
36
|
+
|
|
37
|
+
## Variants
|
|
38
|
+
|
|
39
|
+
| Variant | Granularity | Feels like | Best for |
|
|
40
|
+
|---|---|---|---|
|
|
41
|
+
| **Instant retry** | the moment | "again, now" | precision platformer ([[anchor-celeste]]) |
|
|
42
|
+
| **Checkpoint** | before a hard beat | "the fight, not the trek" | action, boss runs |
|
|
43
|
+
| **Autosave** | on meaningful change | "I can quit safely" | sims, adventures |
|
|
44
|
+
| **Manual save** | player-chosen | "I own my progress" | long-form, strategy |
|
|
45
|
+
| **Roguelite persistence** | between runs | "death advanced *something*" | roguelites ([[anchor-hades]]) |
|
|
46
|
+
| **Run suspend** | mid-run, resume later | "stop without losing the run" | long sessions |
|
|
47
|
+
|
|
48
|
+
## Tuning levers
|
|
49
|
+
|
|
50
|
+
| Lever | Effect | Watch for |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| **Checkpoint density** | how much a death costs | too sparse = punishing; too dense = no stakes |
|
|
53
|
+
| **Retry latency** | flow vs. weight | any load screen breaks a platformer's momentum |
|
|
54
|
+
| **What persists** | run-reset vs. carry-over | defines how heavy death feels ([[system-meta-progression]]) |
|
|
55
|
+
| **Save scope** | full world vs. milestone flags | full snapshot is exact; flags are compact but lossy |
|
|
56
|
+
|
|
57
|
+
## How it wires to Hayao
|
|
58
|
+
|
|
59
|
+
- **Save is nearly free here.** `world.state` is plain JSON + `world.rng`; RNG and
|
|
60
|
+
clock state are part of `world.hash()`, `world.snapshot()`, and saves, so a
|
|
61
|
+
restored world **resumes identically** — the property that makes replay and save
|
|
62
|
+
the same mechanism (CONVENTIONS: "a restored world resumes identically";
|
|
63
|
+
FUN.md law 7).
|
|
64
|
+
- **Serialize / restore:** `serializeSnapshot(snap)` and `parseSnapshot(text)`
|
|
65
|
+
(grep `docs/API.md`) turn a `WorldSnapshot` into storable text and back —
|
|
66
|
+
round-trip a snapshot and hash both sides for a save-integrity test.
|
|
67
|
+
- **Checkpoints are cheap snapshots.** The engine already keeps a periodic
|
|
68
|
+
`SnapshotRing` (every N frames) for Studio scrubbing/tape
|
|
69
|
+
([`docs/STUDIO.md`](../../docs/STUDIO.md)) — the same primitive that powers
|
|
70
|
+
time-travel powers your checkpoints.
|
|
71
|
+
- **Instant retry is `restart`.** A clean rebuild of world state (no leaked nodes,
|
|
72
|
+
no stale RNG) is a verified checklist item (CONVENTIONS §6). Buffer the retry
|
|
73
|
+
input across the death pause ([[system-grace]], FUN.md law 5).
|
|
74
|
+
- **Meta persistence** is the between-run save ([[system-meta-progression]]).
|
|
75
|
+
|
|
76
|
+
## Fails when…
|
|
77
|
+
|
|
78
|
+
- **Re-treading solved content.** A death that sends you back through mastered
|
|
79
|
+
rooms taxes time, not skill — the anti-fun that grace exists to kill
|
|
80
|
+
([[pattern-anti-frustration]]).
|
|
81
|
+
- **Retry latency.** Any load/animation between death and retry drains a
|
|
82
|
+
platformer's momentum (contrast Celeste's instant retry).
|
|
83
|
+
- **Save corrupts on resume.** If snapshot→restore doesn't round-trip to an equal
|
|
84
|
+
hash, saves silently diverge — test it (CONVENTIONS §5).
|
|
85
|
+
- **Restart leaks.** Stale nodes or un-reset RNG after `restart` mean run N+1
|
|
86
|
+
inherits run N's ghosts (CONVENTIONS §6).
|
|
87
|
+
- **Non-determinism sneaks in.** Any wall-clock or `Math.random` outside `world.rng`
|
|
88
|
+
makes a restored world *not* resume identically.
|
|
89
|
+
|
|
90
|
+
## Verify
|
|
91
|
+
|
|
92
|
+
- **Snapshot round-trip:** `snapshot → serializeSnapshot → parseSnapshot → restore`,
|
|
93
|
+
assert equal `world.hash()` at every checkpoint (CONVENTIONS §5, FUN.md law 7).
|
|
94
|
+
- **Restart is clean:** `restart` fully rebuilds state — no leaked nodes, no stale
|
|
95
|
+
RNG (CONVENTIONS §6).
|
|
96
|
+
- **Retry buffers intent:** frame-pump the death→retry window and assert the
|
|
97
|
+
buffered input is accepted ([`src/verify/gates.ts`](../../src/verify/gates.ts)
|
|
98
|
+
forgiveness gate; FUN.md law 5).
|
|
99
|
+
- **Full run pinned:** `t.golden('full run', world.hash())` proves the whole
|
|
100
|
+
session replays bit-exactly (CONVENTIONS §7).
|
|
101
|
+
|
|
102
|
+
## Composes with
|
|
103
|
+
|
|
104
|
+
- [[system-session-structure]] — session length dictates checkpoint granularity.
|
|
105
|
+
- [[system-meta-progression]] — the persistent save between runs.
|
|
106
|
+
- [[system-grace]] — instant retry and input-buffering-through-a-pause are grace.
|
|
107
|
+
- [[pattern-anti-frustration]] — respecting time is the mindset this system enforces.
|
|
108
|
+
|
|
109
|
+
## See also
|
|
110
|
+
|
|
111
|
+
- [`docs/CONVENTIONS.md`](../../docs/CONVENTIONS.md) — pure state, snapshot/hash, restart cleanliness.
|
|
112
|
+
- [`docs/STUDIO.md`](../../docs/STUDIO.md) — the `SnapshotRing` and replay round-trip.
|
|
113
|
+
- [[anchor-celeste]] · [[anchor-hades]] — instant retry and death-as-progress.
|