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.
Files changed (110) hide show
  1. package/design/00-process/README.md +49 -0
  2. package/design/00-process/composition.md +148 -0
  3. package/design/00-process/core-loop.md +146 -0
  4. package/design/00-process/intent-to-brief.md +128 -0
  5. package/design/00-process/pillars.md +139 -0
  6. package/design/00-process/refine-and-handoff.md +156 -0
  7. package/design/00-process/the-twist.md +108 -0
  8. package/design/10-anchors/README.md +99 -0
  9. package/design/10-anchors/age-of-empires.md +103 -0
  10. package/design/10-anchors/baba-is-you.md +127 -0
  11. package/design/10-anchors/balatro.md +132 -0
  12. package/design/10-anchors/celeste.md +136 -0
  13. package/design/10-anchors/civilization.md +101 -0
  14. package/design/10-anchors/dead-cells.md +125 -0
  15. package/design/10-anchors/factorio.md +100 -0
  16. package/design/10-anchors/hades.md +127 -0
  17. package/design/10-anchors/into-the-breach.md +125 -0
  18. package/design/10-anchors/it-takes-two.md +104 -0
  19. package/design/10-anchors/loop-hero.md +131 -0
  20. package/design/10-anchors/nuclear-throne.md +130 -0
  21. package/design/10-anchors/outer-wilds.md +107 -0
  22. package/design/10-anchors/overcooked.md +102 -0
  23. package/design/10-anchors/peggle.md +133 -0
  24. package/design/10-anchors/reigns.md +99 -0
  25. package/design/10-anchors/return-of-the-obra-dinn.md +108 -0
  26. package/design/10-anchors/rimworld.md +101 -0
  27. package/design/10-anchors/shadow-of-mordor.md +106 -0
  28. package/design/10-anchors/slay-the-spire.md +127 -0
  29. package/design/10-anchors/starcraft.md +98 -0
  30. package/design/10-anchors/stardew-valley.md +103 -0
  31. package/design/10-anchors/tetris.md +122 -0
  32. package/design/10-anchors/vampire-survivors.md +122 -0
  33. package/design/20-genres/README.md +62 -0
  34. package/design/20-genres/action-adventure.md +126 -0
  35. package/design/20-genres/auto-battler.md +121 -0
  36. package/design/20-genres/bullet-hell.md +123 -0
  37. package/design/20-genres/city-builder.md +124 -0
  38. package/design/20-genres/coop-chaos.md +124 -0
  39. package/design/20-genres/deckbuilder.md +122 -0
  40. package/design/20-genres/exploration.md +131 -0
  41. package/design/20-genres/farming-sim.md +122 -0
  42. package/design/20-genres/grid-puzzle.md +126 -0
  43. package/design/20-genres/horde-survival.md +128 -0
  44. package/design/20-genres/incremental.md +120 -0
  45. package/design/20-genres/match3.md +120 -0
  46. package/design/20-genres/metroidvania.md +132 -0
  47. package/design/20-genres/narrative-decisions.md +122 -0
  48. package/design/20-genres/physics-arcade.md +124 -0
  49. package/design/20-genres/precision-platformer.md +127 -0
  50. package/design/20-genres/racing.md +126 -0
  51. package/design/20-genres/rhythm.md +125 -0
  52. package/design/20-genres/roguelike.md +122 -0
  53. package/design/20-genres/rts.md +169 -0
  54. package/design/20-genres/stealth.md +125 -0
  55. package/design/20-genres/survival-horror.md +124 -0
  56. package/design/20-genres/tactics.md +123 -0
  57. package/design/20-genres/tower-defense.md +120 -0
  58. package/design/30-systems/README.md +69 -0
  59. package/design/30-systems/accessibility.md +110 -0
  60. package/design/30-systems/boss-design.md +126 -0
  61. package/design/30-systems/build-diversity.md +120 -0
  62. package/design/30-systems/collectibles.md +108 -0
  63. package/design/30-systems/combat-model.md +113 -0
  64. package/design/30-systems/coop-and-competition.md +118 -0
  65. package/design/30-systems/counter-systems.md +115 -0
  66. package/design/30-systems/crafting.md +115 -0
  67. package/design/30-systems/difficulty-and-dda.md +114 -0
  68. package/design/30-systems/economy.md +117 -0
  69. package/design/30-systems/emergent-systems.md +114 -0
  70. package/design/30-systems/encounter-design.md +107 -0
  71. package/design/30-systems/enemy-ai.md +121 -0
  72. package/design/30-systems/enemy-archetypes.md +117 -0
  73. package/design/30-systems/faction-asymmetry.md +144 -0
  74. package/design/30-systems/grace.md +124 -0
  75. package/design/30-systems/mastery-curve.md +116 -0
  76. package/design/30-systems/meta-progression.md +114 -0
  77. package/design/30-systems/onboarding.md +115 -0
  78. package/design/30-systems/procgen-design.md +118 -0
  79. package/design/30-systems/progression.md +120 -0
  80. package/design/30-systems/resource-loops.md +112 -0
  81. package/design/30-systems/reward-schedules.md +124 -0
  82. package/design/30-systems/save-and-checkpoint.md +113 -0
  83. package/design/30-systems/session-structure.md +113 -0
  84. package/design/30-systems/skill-trees.md +111 -0
  85. package/design/30-systems/status-effects.md +111 -0
  86. package/design/30-systems/tech-tree.md +112 -0
  87. package/design/30-systems/telegraphs.md +106 -0
  88. package/design/30-systems/unit-rosters.md +123 -0
  89. package/design/40-worldbuilding/README.md +49 -0
  90. package/design/40-worldbuilding/aesthetic-direction.md +155 -0
  91. package/design/40-worldbuilding/faction-identity.md +136 -0
  92. package/design/40-worldbuilding/naming-and-tone.md +130 -0
  93. package/design/40-worldbuilding/narrative-delivery.md +129 -0
  94. package/design/40-worldbuilding/theme-vectors.md +134 -0
  95. package/design/40-worldbuilding/worldbuilding-scaffold.md +132 -0
  96. package/design/50-patterns/README.md +54 -0
  97. package/design/50-patterns/anti-frustration.md +121 -0
  98. package/design/50-patterns/emergence.md +121 -0
  99. package/design/50-patterns/feedback-loops.md +121 -0
  100. package/design/50-patterns/juice-choreography.md +124 -0
  101. package/design/50-patterns/mastery-and-flow.md +121 -0
  102. package/design/50-patterns/pacing-and-tension.md +120 -0
  103. package/design/50-patterns/readability.md +121 -0
  104. package/design/50-patterns/risk-reward.md +120 -0
  105. package/design/CONTRIBUTING.md +183 -0
  106. package/design/INDEX.md +133 -0
  107. package/design/README.md +86 -0
  108. package/design/_TEMPLATE.md +69 -0
  109. package/design/index.json +2720 -0
  110. package/package.json +2 -1
@@ -0,0 +1,113 @@
1
+ ---
2
+ id: system-session-structure
3
+ title: Session Structure
4
+ kind: system
5
+ tags: [session, run, campaign, level, world, pacing, length, structure, container]
6
+ summary: The nesting of play — run / campaign / level / world — and how session length and shape set the game's rhythm and stakes.
7
+ use-when: You need to decide how long a sitting is, what a "run" contains, and how sessions nest into a longer arc.
8
+ composes-with: [system-procgen-design, system-meta-progression, system-save-and-checkpoint, pattern-pacing-and-tension]
9
+ anchors: [anchor-hades, anchor-slay-the-spire]
10
+ verify-with: docs/FUN.md#14-incrementalidle
11
+ ---
12
+
13
+ # Session Structure
14
+
15
+ **What it is.** The **containers** play nests into — a *moment*, a *level* or
16
+ *encounter*, a *run* or *session*, and the *meta* arc across them — and the
17
+ **length and shape** of each. Session structure decides "how long is one sitting,
18
+ what does it contain, and how do sittings add up?" A 3-minute Vampire Survivors
19
+ push and a 40-turn Slay the Spire climb are the same genre-family with wildly
20
+ different session shapes.
21
+
22
+ **Player fantasy / why it's fun.** *A satisfying unit of time.* A good session has
23
+ a clean arc — start, build, climax, resolution — that fits a real sitting and
24
+ leaves a hook. The pull is closure-plus-appetite: "one more run" works because each
25
+ run *finishes* something and *promises* something.
26
+
27
+ ## When to use / when NOT
28
+
29
+ This is a **framing** system — every game has a session shape whether or not you
30
+ design it. Reach for it explicitly when:
31
+
32
+ | Design it deliberately when | It's near-trivial when |
33
+ |---|---|
34
+ | Runs/campaigns/roguelite structure is core | A single continuous level (endless arcade) |
35
+ | You're deciding meta vs. per-run persistence | A one-sitting puzzle box |
36
+ | Session length is a selling point (coffee-break vs. epic) | — |
37
+
38
+ ## The nesting
39
+
40
+ | Tier | Span | Owns | Ends when |
41
+ |---|---|---|---|
42
+ | **Moment** | seconds | one verb → feedback | the input resolves ([[process-core-loop]]) |
43
+ | **Encounter / level** | 1–5 min | one fight or room | cleared / failed |
44
+ | **Run / session** | 5–60 min | a sequence of encounters + choices | win / death / objective |
45
+ | **Meta / campaign** | many runs | persistent progress, unlocks, story | the long goal ([[system-meta-progression]]) |
46
+
47
+ The two big shape decisions:
48
+
49
+ | Decision | Options | Consequence |
50
+ |---|---|---|
51
+ | **Session length** | coffee-break (3–10 min) · sitting (20–60) · epic (hours) | sets stakes per run and save granularity |
52
+ | **Persistence** | fully reset · roguelite carry-over · fully persistent | resets make death cheap; persistence makes it heavy |
53
+
54
+ ## Tuning levers
55
+
56
+ | Lever | Effect | Watch for |
57
+ |---|---|---|
58
+ | **Run length** | stakes & commitment per session | too long = quitting mid-run loses progress; own it in [[system-save-and-checkpoint]] |
59
+ | **Encounters per run** | the run's internal pacing arc | too few = no arc; too many = a slog |
60
+ | **Meta gain per run** | how much a failed run still *earns* | zero = punishing; too much = trivial |
61
+ | **Hook strength** | the pull into the next session | none = the loop doesn't restart |
62
+
63
+ ## How it wires to Hayao
64
+
65
+ - **A run is a seed + a snapshot.** Because state is pure JSON in `world.state`
66
+ with `world.rng`, one run is fully described by `(seed, tuning, inputLog)` and
67
+ restorable from a snapshot — this is exactly the Studio session artifact
68
+ ([`docs/STUDIO.md`](../../docs/STUDIO.md), FUN.md law 7). Session structure and
69
+ the replay artifact are the *same* nesting.
70
+ - **Runs are generated.** A roguelite run is a `generateLevels`/`generateDungeon`
71
+ sequence over a per-run seed ([[system-procgen-design]],
72
+ [`src/content/generate.ts`](../../src/content/generate.ts)) — the campaign that
73
+ ships is a list of seeds.
74
+ - **Campaigns compose.** `composeCampaign(spec)` (grep `docs/API.md`,
75
+ [`src/content/campaign.ts`](../../src/content/campaign.ts)) assembles proven
76
+ levels into an ordered arc — the meta tier as data.
77
+ - **Between-run persistence** is meta-progression saved across sessions
78
+ ([[system-meta-progression]], [[system-save-and-checkpoint]]).
79
+
80
+ ## Fails when…
81
+
82
+ - **Length ≠ save granularity.** A 45-minute run with no checkpoint punishes anyone
83
+ who has to stop — respect the player's time ([[system-save-and-checkpoint]]).
84
+ - **No arc per session.** A run with no build-and-climax is texture, not an
85
+ experience ([[pattern-pacing-and-tension]]).
86
+ - **Failed runs earn nothing.** In roguelites, a death that advances *nothing*
87
+ feels like theft — grant meta or knowledge ([[anchor-hades]]).
88
+ - **No hook.** A run that finishes and dead-ends stops the "one more" loop.
89
+ - **Deserts in the meta.** Long stretches with no unlock or new goal
90
+ ([FUN.md §14](../../docs/FUN.md#14-incrementalidle) unlock-desert lint).
91
+
92
+ ## Verify
93
+
94
+ - **The whole arc paces:** balance-sim the run/campaign; assert pacing windows and
95
+ **no unlock deserts** across the arc ([FUN.md §14](../../docs/FUN.md#14-incrementalidle)).
96
+ - **A run is reproducible:** golden-hash a full scripted run; snapshot→restore→hash
97
+ round-trips (FUN.md law 7; [`docs/STUDIO.md`](../../docs/STUDIO.md)).
98
+ - **Every level in the campaign is winnable:** solver proof per level via the
99
+ generator (FUN.md §10, [`src/content/generate.ts`](../../src/content/generate.ts)).
100
+
101
+ ## Composes with
102
+
103
+ - [[system-procgen-design]] — a run's content is generated from its seed.
104
+ - [[system-meta-progression]] — the tier that persists across sessions.
105
+ - [[system-save-and-checkpoint]] — session length dictates save granularity.
106
+ - [[pattern-pacing-and-tension]] — each session tier needs its own arc.
107
+ - [[system-difficulty-and-dda]] — the curve spans a run and the campaign both.
108
+
109
+ ## See also
110
+
111
+ - [`src/content/campaign.ts`](../../src/content/campaign.ts) — `composeCampaign` (the meta tier as data).
112
+ - [`docs/STUDIO.md`](../../docs/STUDIO.md) — a session as a replayable artifact.
113
+ - [[anchor-hades]] · [[anchor-slay-the-spire]] — the run as the fundamental unit.
@@ -0,0 +1,111 @@
1
+ ---
2
+ id: system-skill-trees
3
+ title: Skill Trees — Branching Unlocks & Builds
4
+ kind: system
5
+ tags: [skill-tree, builds, unlocks, branching, exclusivity, respec, specialization]
6
+ summary: Branching unlock graphs that turn flat power into a build; meaningful exclusivity is what makes the choice a choice, and respec is its grace.
7
+ use-when: Progression should let the player CHOOSE a shape — a build, a specialization — not just accumulate the same power everyone gets.
8
+ composes-with: [system-progression, system-build-diversity, system-tech-tree, system-economy, system-collectibles]
9
+ anchors: [anchor-dead-cells, anchor-slay-the-spire]
10
+ verify-with: docs/FUN.md#2-skill-delta-proofs
11
+ ---
12
+
13
+ # Skill Trees — Branching Unlocks & Builds
14
+
15
+ **What it is.** A **graph of unlocks** the player buys with a progression
16
+ currency (points, cells, essence). The graph's *branches* — and the fact that you
17
+ can't afford all of them — turn "get stronger" into "become a *kind* of strong."
18
+
19
+ **Player fantasy / why it's fun.** "This build is *mine*." The tree is a canvas;
20
+ the player paints a strategy and then gets to test it. The pull is the road not
21
+ taken — every point spent is a small identity claim.
22
+
23
+ ## When to use / when NOT
24
+
25
+ | Use it when | Skip it when |
26
+ |---|---|
27
+ | You want players to express strategy through pre-commitment | There's no meaningful choice — every node is strictly good |
28
+ | Replay value comes from "try a different build" | One optimal path exists; the tree is a formality |
29
+ | Power is horizontal ([[system-progression]]) and needs structure | A flat list of upgrades reads clearer (small games) |
30
+
31
+ A tree with no **exclusivity** is just a shopping list. If the player will
32
+ eventually own every node, the branches are decoration — either add scarcity
33
+ (can't afford all) or opposition (this node locks that one).
34
+
35
+ ## Variants
36
+
37
+ | Variant | Structure | The choice is | Example |
38
+ |---|---|---|---|
39
+ | **Prerequisite web** | Nodes gate deeper nodes | *Order & reach* | Path of Exile's lattice |
40
+ | **Point-buy, no gates** | Flat pool, scarce points | *What to skip* | Classic RPG stat spend |
41
+ | **Mutually-exclusive forks** | Pick A xor B at each fork | *Identity* | "Fire OR frost, never both" |
42
+ | **Class/archetype trees** | Separate trees per role | *Which fantasy* | Diablo class trees |
43
+ | **Draft-as-tree** | The run's picks form an implicit build | *Emergent shape* | Hades boons; StS deck |
44
+
45
+ The **fork** variant carries the most meaning per node and the most respec
46
+ pressure — see levers.
47
+
48
+ ## Tuning levers
49
+
50
+ | Lever | What it controls | Healthy range / rule |
51
+ |---|---|---|
52
+ | **Point scarcity** | How much you must skip | You should afford ~40–70% of a tree per playthrough — enough to specialise, not complete |
53
+ | **Branch exclusivity** | Whether a choice costs another | At least the *capstones* should be exclusive, or builds converge |
54
+ | **Node granularity** | Fewer big nodes vs many small | Big nodes = legible builds; tiny nodes = fiddly filler |
55
+ | **Capstones** | The payoff that defines a build | Each branch needs a "this is why you went here" node |
56
+ | **Respec cost** | Reversibility | Free in experimental games; costed where commitment is the point |
57
+ | **Gating depth** | Prereqs before the good stuff | Shallow — burying power behind 8 filler nodes reads as grind |
58
+
59
+ **Respec is grace** (**[[FUN.md law 5]]**, the anti-frustration mindset). A tree
60
+ the player is afraid to touch is a tree they don't engage with. Default to
61
+ generous respec unless *permanent commitment* is an explicit pillar.
62
+
63
+ ## How it wires to Hayao
64
+
65
+ - **The tree is data.** A node graph (id, cost, prereqs, effect) in `world.state`;
66
+ unlocking is an **input action** that spends a currency and flips a flag. The
67
+ effect is applied by pure logic reading owned-node flags — so a build is a
68
+ reproducible input sequence, and clone-and-score bots can *pilot* builds to
69
+ measure them (**[[FUN.md law 7]]**).
70
+ - **Exclusivity is a solver constraint.** "Can't own A and B" is a rule the pure
71
+ logic enforces and a test asserts. Prove *every* branch is viable by piloting
72
+ each and asserting it beats a null build — the skill-delta proof
73
+ (**[[FUN.md law 2]]**), applied per branch, is your balance instrument for
74
+ [[system-build-diversity]].
75
+ - **The tree UI is chrome.** Draw it with `showScreen()` (DOM menu) — it's not
76
+ sim, so it doesn't belong in `world.hash()`. Grep `docs/API.md`; per CLAUDE.md
77
+ invariant 4, menus are DOM.
78
+ - **Persist unlocks** via `SaveManager` when the tree is meta
79
+ ([[system-meta-progression]]).
80
+
81
+ ## Fails when…
82
+
83
+ - **A trap node.** A branch that's strictly worse wastes the player's one
84
+ irreversible choice — punishing, not deep. Prove each branch viable.
85
+ - **A God node.** One branch dominates; everyone funnels to it and the tree
86
+ collapses to a line. The win-rate *window* per build catches this.
87
+ - **No exclusivity.** Own-everything trees have no decisions. Add scarcity or forks.
88
+ - **Filler gating.** Prereq chains of dead nodes to reach the good one — grind
89
+ wearing a tree costume.
90
+ - **Respec you fear.** No respec + a trap node = a bricked character. Give an out.
91
+
92
+ ## Verify
93
+
94
+ - Per-branch skill delta — each build beats a null build: **[[FUN.md law 2]]**.
95
+ - Build viability as a win-rate *window*, both edges break CI:
96
+ **[[FUN.md §11]]** (deckbuilder's balance instrument).
97
+ - Build as a reproducible pilot (clone-and-score): **[[FUN.md law 7]]**.
98
+
99
+ ## Composes with
100
+
101
+ - [[system-progression]] — the tree spends what progression earns.
102
+ - [[system-build-diversity]] — the tree is the machinery that makes many builds real.
103
+ - [[system-tech-tree]] — the same graph shape at the *strategy* scale (a whole faction).
104
+ - [[system-meta-progression]] — persistent trees between runs.
105
+ - [[system-economy]] — skill points are a currency; the tree is a sink.
106
+
107
+ ## See also
108
+
109
+ - [`docs/FUN.md`](../../docs/FUN.md) §11, law 2 — build deltas and win-rate windows.
110
+ - `examples/slay-the-spire`-style drafting (**[[anchor-slay-the-spire]]**) — the
111
+ deck IS the tree, built one card at a time.
@@ -0,0 +1,111 @@
1
+ ---
2
+ id: system-status-effects
3
+ title: Status Effects — damage and change over time
4
+ kind: system
5
+ tags: [status, dot, buff, debuff, stacking, poison, burn, legibility]
6
+ summary: DoT, buffs, and debuffs as first-class state — with stacking rules that are legible, bounded, and interact with builds instead of just piling up.
7
+ use-when: You want conditions (poison, burn, slow, shield, rage) that persist across turns/seconds and interact with the rest of combat.
8
+ composes-with: [system-combat-model, system-counter-systems, system-build-diversity, system-telegraphs]
9
+ anchors: [anchor-slay-the-spire, anchor-hades]
10
+ verify-with: docs/FUN.md#11-roguelike-deckbuilder
11
+ ---
12
+
13
+ # Status Effects — damage and change over time
14
+
15
+ **What it is.** **Conditions** that persist: poison ticking each turn, a burn, a
16
+ shield, a slow, a rage buff. Status turns a hit from a one-frame event into a
17
+ *state you carry* — the layer that lets [[system-build-diversity]] and
18
+ [[system-counter-systems]] interact instead of just stacking flat numbers.
19
+
20
+ **Player fantasy / why it's fun.** Setting up. The poison you stacked three turns
21
+ ago finally kills; the shield you pre-cast eats the boss's big hit. Status rewards
22
+ *plans*, not just reactions — it's the memory of combat.
23
+
24
+ ## When to use / when NOT
25
+
26
+ | Use status when… | Skip when… |
27
+ |---|---|
28
+ | You want set-up-then-payoff play | Combat is pure twitch reaction |
29
+ | Builds should interact (a synergy engine) | You have < ~4 effects (just make them direct) |
30
+ | Counters need a vocabulary (cleanse, resist) | Legibility budget is already spent |
31
+
32
+ Every status is a rule the player must hold in their head. Ship the fewest that
33
+ carry the most interaction — a bloated status list is unreadable, not deep.
34
+
35
+ ## Variants
36
+
37
+ | Kind | Shape | Stacking | Example |
38
+ |---|---|---|---|
39
+ | **DoT** (poison, burn) | damage per tick, N ticks | intensity or duration | Slay the Spire poison (−1/turn, decays) |
40
+ | **Debuff** (slow, weak, vuln) | multiplier on the target | usually duration | weak = −25% dmg dealt |
41
+ | **Buff** (rage, haste, shield) | multiplier / absorb on self | intensity or refresh | block that expires next turn |
42
+ | **CC** (stun, freeze, root) | skips/limits actions | rarely stacks; diminishing | one turn skipped |
43
+ | **Trigger** (mark, curse) | fires on a condition | count-based | "next hit crits" |
44
+
45
+ ## Stacking rules — pick one per effect, state it
46
+
47
+ | Rule | Behaviour | Good for |
48
+ |---|---|---|
49
+ | **Intensity** | more applications = bigger effect | poison, bleed |
50
+ | **Duration** | more applications = longer, same size | slow, weak |
51
+ | **Refresh** | re-apply resets the timer, no stack | most buffs |
52
+ | **Independent** | each application is its own timer | rare; hard to read |
53
+ | **Cap** | stacks up to N, then no-op | keep any of the above bounded |
54
+
55
+ Ambiguous stacking is the #1 status bug. Decide intensity-vs-duration *per effect*
56
+ and cap it — an uncapped intensity DoT trivializes the game (FUN.md law 3).
57
+
58
+ ## Tuning levers
59
+
60
+ | Lever | Does | Healthy range |
61
+ |---|---|---|
62
+ | **Tick timing** | when DoT resolves | fixed point in the turn/second; deterministic |
63
+ | **Decay** | how stacks fall off | poison −1/turn keeps it self-limiting |
64
+ | **Cap** | max stacks/intensity | always set one |
65
+ | **Cleanse cost** | price to remove a status | real, so statuses are a threat not a nuisance |
66
+ | **Duration** | turns/seconds it lasts | long enough to matter, short enough to plan around |
67
+
68
+ ## How it wires to Hayao
69
+
70
+ - **Status is pure state** on the entity in `world.state` — a `{ id, stacks, turns }`
71
+ list, resolved by a pure tick function; all rolls via `world.rng`. That makes
72
+ clone-and-score bots free (FUN.md law 7): pilot the intended build, assert it beats
73
+ the null build (FUN.md law 2, §11 draft-delta).
74
+ - **Legibility is intent honesty.** A shown "poison 6" must deal exactly 6 over its
75
+ ticks (FUN.md §11 — resolve the telegraph, compare to the number). Audit it.
76
+ - **The tick returns choreography** — the number pop and tint are cosmetic
77
+ (`FloatingText`, `FLOAT_PRESETS`; JUICE Part 1), out of `world.hash()`.
78
+ - No special engine primitive is needed — status is *your* data. Grep [`docs/API.md`](../../docs/API.md)
79
+ before citing; there is no `applyStatus` in the surface, and there shouldn't be.
80
+
81
+ ## Fails when…
82
+
83
+ - **Uncapped intensity.** One infinite-scaling DoT becomes the only strategy
84
+ (dominant, [[system-build-diversity]] collapses).
85
+ - **Illegible stacking.** The player can't predict the tick, so they stop planning —
86
+ status becomes noise, not depth.
87
+ - **No counter-play.** A status with no cleanse/resist and a long duration is just
88
+ unfair; give the vocabulary a full loop ([[system-counter-systems]]).
89
+ - **Silent resolution.** Ticks with no pop/tint read as HP randomly draining. Answer
90
+ on ≥ 2 senses (JUICE).
91
+
92
+ ## Verify
93
+
94
+ - **[FUN.md §11](../../docs/FUN.md)** — draft/build delta (the status build beats the
95
+ null build); intent honesty (shown status == resolved damage).
96
+ - **[FUN.md law 3](../../docs/FUN.md)** — the cap inequality asserted against config.
97
+ - Determinism: golden hash of a scripted fight with statuses; view-on == view-off.
98
+ - Feel: number pops answer on ≥ 2 senses → **[JUICE.md Part 3](../../docs/JUICE.md)**.
99
+
100
+ ## Composes with
101
+
102
+ - [[system-combat-model]] — status is damage/change that resolves over the model's clock.
103
+ - [[system-counter-systems]] — cleanse/resist/immunity are the counter vocabulary.
104
+ - [[system-build-diversity]] — status synergies are a primary source of viable builds.
105
+ - [[system-telegraphs]] — a big incoming debuff should itself telegraph.
106
+
107
+ ## See also
108
+
109
+ - [`docs/FUN.md`](../../docs/FUN.md) §11 — deckbuilder draft-delta and intent honesty.
110
+ - [`docs/JUICE.md`](../../docs/JUICE.md) Part 1 — `FloatingText` / `FLOAT_PRESETS` for pops.
111
+ - [[anchor-slay-the-spire]] — the reference for legible, capped, build-defining status.
@@ -0,0 +1,112 @@
1
+ ---
2
+ id: system-tech-tree
3
+ title: Tech Tree — Research Gating & the Ramp of Options
4
+ kind: system
5
+ tags: [tech-tree, research, gating, branch-exclusivity, strategy, unlocks, ramp]
6
+ summary: Research-gated unlocks at the strategy scale; branch exclusivity and a widening ramp of options that shape a whole playthrough's arc.
7
+ use-when: The game unlocks strategic capabilities (units, buildings, abilities) over a session and you need the order and exclusivity of those unlocks to matter.
8
+ composes-with: [system-skill-trees, system-resource-loops, system-economy, system-faction-asymmetry, system-progression]
9
+ anchors: [anchor-age-of-empires, anchor-civilization, anchor-factorio]
10
+ verify-with: docs/FUN.md#9-rts-lite
11
+ ---
12
+
13
+ # Tech Tree — Research Gating & the Ramp of Options
14
+
15
+ **What it is.** A **tech tree** is a **[[system-skill-trees]]** at the *strategy*
16
+ scale: a graph of researchable capabilities — units, buildings, upgrades, ages —
17
+ where each unlock widens what the player can *do*, and prerequisites impose an
18
+ order. Where a skill tree shapes a *character*, a tech tree shapes a *civilization's
19
+ whole arc*.
20
+
21
+ **Player fantasy / why it's fun.** "My tech path is my strategy." The order you
22
+ research is a plan; a well-timed unlock is a power spike (**[[anchor-age-of-empires]]**
23
+ age-ups). The pull is the branch just out of reach — the tech that would answer
24
+ what's beating you.
25
+
26
+ ## When to use / when NOT
27
+
28
+ | Use it when | Skip it when |
29
+ |---|---|
30
+ | Strategy is expressed through *what you unlock, when* (RTS, 4X) | The game has a fixed toolset from the start |
31
+ | Build orders and tech timing are a skill | Research would just be a passive timer |
32
+ | You want power spikes to punctuate a long session | Sessions are too short to ramp options |
33
+
34
+ The tech tree is the RTS/4X engine of **[[pattern-pacing-and-tension]]**: each age
35
+ or era is a plateau, each unlock a spike. If unlocks don't create *timing decisions*
36
+ (rush this or bank for that?), you have a checklist, not a tree.
37
+
38
+ ## Variants
39
+
40
+ | Variant | Structure | The decision is | Example |
41
+ |---|---|---|---|
42
+ | **Age/era gates** | Discrete tiers; advance to unlock a bracket | *When* to age up (spike vs eco) | AoE ages; Civ eras |
43
+ | **Prerequisite web** | Deep dependency graph | *Route* through the tree | Civ tech web; Factorio science |
44
+ | **Exclusive branches** | Pick a path, lock the other | *Identity/commitment* | Civ policy trees; StarCraft tech choices |
45
+ | **Cost-gated flat** | No prereqs, priced by power | *Priority* | Simple upgrade shops |
46
+ | **Faction trees** | Different tree per faction | *Asymmetric strategy* | See [[system-faction-asymmetry]] |
47
+
48
+ ## Tuning levers
49
+
50
+ | Lever | What it controls | Healthy range / rule |
51
+ |---|---|---|
52
+ | **Tier/age spacing** | Time between power spikes | Long enough to *feel* the plateau, short enough to keep momentum |
53
+ | **Branch exclusivity** | Whether a path costs another | Some branches exclusive, or every game converges to the same tech |
54
+ | **Research cost curve** | The ramp of options | Rising cost per tier; but each tier's *value* must rise with it |
55
+ | **Gate depth** | Prereqs before a payoff tech | Shallow — burying the fun behind filler tech is grind |
56
+ | **Counter-availability** | Can you tech *into* an answer? | Yes — a tech tree is where RTS counters live; every threat needs a reachable response |
57
+ | **Snowball vs comeback** | Does a tech lead compound? | Add catch-up / comeback techs, or leaders run away ([[pattern-feedback-loops]]) |
58
+
59
+ ## How it wires to Hayao
60
+
61
+ - **The tree is a data graph + pure logic.** Nodes (`id, cost, prereqs, unlocks`)
62
+ in `world.state`; researching is an **input action** that spends resources and
63
+ flips availability flags; unit/ability availability is pure logic reading those
64
+ flags. So a *build order* is a reproducible input script a bot can pilot
65
+ (**[[FUN.md law 7]]**).
66
+ - **Strategy is the balance test.** The RTS truth (**[[FUN.md §9]]**): the intended
67
+ line (e.g. turtle → tech → counterpush) must *beat* a naive line (attack-move /
68
+ one-tech rush). Pilot both, assert the delta — that's your proof the tech
69
+ choices matter (law 2).
70
+ - **Counters must be reachable.** Every enemy threat needs a tech-reachable answer;
71
+ assert it the way tower-defense proves counter duels from both sides
72
+ (**[[FUN.md §8]]**) and RTS proves every counter edge wins its NvN
73
+ (**[[FUN.md §9]]**).
74
+ - **The tech panel is chrome** — `showScreen()` DOM; the research *state* is sim
75
+ (CLAUDE.md invariant 4). Generate/ramp the option-unlock curve as content
76
+ (`src/content/`, `assertRamp`).
77
+
78
+ ## Fails when…
79
+
80
+ - **A dominant path.** One tech order is always best; the tree collapses to a line.
81
+ Skill-delta between *paths* should be small; each viable path should beat null.
82
+ - **Unreachable counters.** A threat with no tech answer is unfair — the RTS/TD
83
+ counter proof fails from one side.
84
+ - **Filler gating.** Dead prereq techs padding the route to the good one — grind.
85
+ - **Runaway snowball.** A tech lead that compounds into an unbeatable lead with no
86
+ comeback tech ([[pattern-feedback-loops]]).
87
+ - **Spikes with no plateau.** Constant unlocks = no pacing; the age-up thrill needs
88
+ the plateau before it.
89
+
90
+ ## Verify
91
+
92
+ - Intended tech line beats naive line (strategy is the test): **[[FUN.md §9]]**,
93
+ law 2.
94
+ - Every counter edge wins its duel, both sides: **[[FUN.md §9]]** (RTS) /
95
+ **[[FUN.md §8]]** (TD).
96
+ - Build order as a reproducible pilot: **[[FUN.md law 7]]**.
97
+ - Option ramp shape as a test: `assertRamp`/`rampIssues` over the unlock curve.
98
+
99
+ ## Composes with
100
+
101
+ - [[system-skill-trees]] — the same graph shape at the character scale.
102
+ - [[system-resource-loops]] — research consumes the production chain's output.
103
+ - [[system-economy]] — research points/cost are a currency and a sink.
104
+ - [[system-faction-asymmetry]] — different trees are a core asymmetry lever.
105
+ - [[system-counter-systems]] — the tree is where reachable counters live.
106
+ - [[pattern-pacing-and-tension]] — ages/eras are the plateau-and-spike engine.
107
+
108
+ ## See also
109
+
110
+ - [`docs/FUN.md`](../../docs/FUN.md) §9 (RTS strategy-as-test) · §8 (counter duels)
111
+ — the tech-tree proofs.
112
+ - **[[anchor-age-of-empires]]** (age spikes) · **[[anchor-civilization]]** (deep web).
@@ -0,0 +1,106 @@
1
+ ---
2
+ id: system-telegraphs
3
+ title: Telegraphs — readable threat
4
+ kind: system
5
+ tags: [telegraph, tells, windup, readability, reaction, threat, combat]
6
+ summary: The wind-up that makes a threat readable — every hitbox announces itself long enough to react, and the tell is stored as a direction, not a guess.
7
+ use-when: Any threat can hurt the player in real time or resolve on a turn; you need the danger to be reactable, not a surprise.
8
+ composes-with: [system-combat-model, system-boss-design, system-enemy-ai, system-grace, pattern-readability]
9
+ anchors: [anchor-into-the-breach, anchor-shadow-of-mordor]
10
+ verify-with: docs/FUN.md#4-top-down-action-adventure-zelda-like
11
+ ---
12
+
13
+ # Telegraphs — readable threat
14
+
15
+ **What it is.** The **tell**: the flash, wind-up, or warning tile that fires *before*
16
+ a threat can hurt you, giving a window to react. A telegraph is the contract that
17
+ makes reactive play possible — without it, damage is a dice roll disguised as a
18
+ fight. It is the readable half of every [[system-combat-model]].
19
+
20
+ **Player fantasy / why it's fun.** "I saw it coming and I moved." Every dodged blow
21
+ is the player's skill, not the game's mercy. A death after a telegraph is *fair* —
22
+ you read it or you didn't; a death with no telegraph is the designer's fault.
23
+
24
+ ## When to use / when NOT
25
+
26
+ | Telegraph when… | Skip when… |
27
+ |---|---|
28
+ | A threat can kill/hurt in real time | Damage is player-initiated only (you hit them) |
29
+ | Perfect information is the promise (tactics) | The threat is a slow, always-visible hazard (lava) |
30
+ | A boss/elite has committal, punishable moves | The genre's fun is *not* reacting (idle, puzzle) |
31
+
32
+ Turn-based games still telegraph — they just do it as **shown intent on the board**
33
+ (the arrow, the highlighted tiles), not a timed flash.
34
+
35
+ ## Variants
36
+
37
+ | Telegraph | Channel | Window | Anchor | Note |
38
+ |---|---|---|---|---|
39
+ | **Flash / color wind-up** | visual | ~0.45s (§4) | Zelda-likes | the default reactive tell |
40
+ | **Wind-up animation** | visual | scales to move weight | brawlers, [[anchor-shadow-of-mordor]] | big moves telegraph longer |
41
+ | **Audio cue** | audio | leads the visual | rhythm, horror | a growl before the lunge |
42
+ | **Ground marker / AoE** | visual | fills over the window | ARPGs, bosses | the red circle grows, then fires |
43
+ | **Shown intent (turn)** | visual, static | until next turn | [[anchor-into-the-breach]] | the arrow you rewrite |
44
+ | **Charge / meter** | visual | fills to threshold | bosses | commit-punish window |
45
+
46
+ ## Tuning levers
47
+
48
+ | Lever | Does | Healthy range |
49
+ |---|---|---|
50
+ | **Reaction window** | telegraph frames before the hitbox | **~0.45s** flash floor (FUN.md §4); scale up for heavier moves |
51
+ | **Salience** | how loud the tell reads | brightest thing after the avatar (JUICE salience gate) |
52
+ | **Recovery** | punish window after the move whiffs | long enough to answer; short enough to stay dangerous |
53
+ | **Overlap budget** | simultaneous telegraphs | few enough that each still reads (bullet-hell coherence, §7) |
54
+ | **Channels** | senses the tell fires on | ≥ 2 for the big ones (sfx + flash) |
55
+
56
+ The window is a **derived inequality** (FUN.md law 3): reaction window ≥ human
57
+ reaction floor + the frames the dodge costs. Don't vibe it — compute it.
58
+
59
+ ## How it wires to Hayao
60
+
61
+ - **The gate is real.** `telegraphIssues(timeline, minFrames)` (in `@hayao`) walks a
62
+ per-frame `TelegraphFrame[]` (`{ telegraphing, active }`) and flags any hitbox that
63
+ goes live after fewer than `minFrames` of contiguous wind-up. This is the direct
64
+ proof that reactive play is possible.
65
+ - **Store tells as DIRECTIONS, not target tiles.** FUN.md §12: a tactics telegraph is
66
+ a *direction on the unit*, so a shove/redirect rewrites the outcome for free — the
67
+ future is editable, which is the whole fun of the genre. Encode the intent, resolve
68
+ it late.
69
+ - **The tell is cosmetic; the timing is sim time.** The flash/marker are view; the
70
+ *window* is `world.time` and fixed `dt` (FUN.md law 6). Wire the flash to the sim
71
+ event, never to wall-clock — a replay reproduces the exact tell.
72
+ - Reference: the top-down §4 pattern (kiting bot reads flashes); [[anchor-into-the-breach]]
73
+ DNA for shown-intent telegraphs.
74
+
75
+ ## Fails when…
76
+
77
+ - **No wind-up.** A hitbox that goes live cold is an unfair death — `telegraphIssues`
78
+ fails and it *should*.
79
+ - **The tell is illegible.** Too dim, too brief, or buried under five other flashes.
80
+ If the salience gate can't find it, neither can the player ([[pattern-readability]]).
81
+ - **The telegraph lies.** The flash points left, the hit lands right. Perfect
82
+ information demands perfect honesty (FUN.md §12) — shown must equal resolved.
83
+ - **Uniform windows.** Every move telegraphs 0.45s regardless of weight, so nothing
84
+ reads as *scary*. Scale the tell to the threat.
85
+
86
+ ## Verify
87
+
88
+ - **[FUN.md §4](../../docs/FUN.md)** — ~0.45s flash makes reactive play possible;
89
+ kiting-bot telemetry with an hp floor.
90
+ - **[FUN.md §12](../../docs/FUN.md)** — telegraphs as directions; intent honesty
91
+ (resolve each telegraph, compare to the shown number/arrow).
92
+ - `telegraphIssues(timeline, minFrames)` → **[VERIFICATION Channel 4](../../docs/VERIFICATION.md)**.
93
+ - Salience: `salienceIssues` proves the tell out-contrasts scenery (JUICE Part 2/3).
94
+
95
+ ## Composes with
96
+
97
+ - [[system-combat-model]] — the telegraph is the reactive half of the resolution rule.
98
+ - [[system-boss-design]] — bosses live or die on legible, escalating tells across phases.
99
+ - [[system-enemy-ai]] — the AI must *commit* to a telegraphed move, not cancel it.
100
+ - [[pattern-readability]] — signposting and salience are how a tell gets read.
101
+
102
+ ## See also
103
+
104
+ - [`docs/FUN.md`](../../docs/FUN.md) §4 (flash window), §7 (pattern coherence), §12 (directions).
105
+ - [`docs/JUICE.md`](../../docs/JUICE.md) — salience gate; the avatar/threat contrast floor.
106
+ - [`src/verify/gates.ts`](../../src/verify/gates.ts) — `telegraphIssues`, `TelegraphFrame`.