Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,20 @@ The Act 2 launch gate is simply **holding 250,000 prestige rank at the moment of

**System**: vessel (`src/vessel/`, launch gate).

### Vessel Launch Runway: ~828 Hours of Calendar Time — Arithmetic, Not a Simulation

The 250,000 PR gate is reachable, and the answer is **closed-form rather than empirical**. The Loom's WR→PR conversion is the dominant endgame PR source: `wr_to_pr_per_hour(wr) = wr × (1 + wr/100)` (`src/loom/logic.rs:811`), documented peak **131 WR/hr → 302 PR/hr**. The grant (`src/core/tick_stages.rs:1235-1248`) computes `fill_secs = 3600 / pr_per_hour`, then adds `elapsed / fill_secs` PR, where `elapsed = (now - wr_pr_last_granted_at).min(604_800)` — **wall-clock seconds, capped at 7 days**.

At peak: `250,000 ÷ 302 ≈ 828 hours ≈ 34.5 days` of *calendar* time, accruing with the game closed. The 7-day cap grants at most `302 × 168 ≈ 50,700` PR per catch-up, making the gate roughly **five weekly check-ins**. A player who leaves for a month and returns collects one week, not four — that cap is the only behavioral demand the runway makes.

**Why this is not a simulator question**: there is no RNG in that path. `wr_to_pr_per_hour` is a pure function of WR; the grant is integer division on wall-clock elapsed. Nothing is emergent, so simulation can reveal nothing that division cannot. Worth recording because the headless simulator *structurally cannot* answer it: `src/bin/simulator/strategy.rs:361-363` notes the Loom's pattern sustain runs on wall clock "which doesn't advance meaningfully in the headless simulator" and injects pattern completions instead. Two 3,000-hour runs started at P50,000 and P250,000 with different seeds returned `pr_earned` of 17,995 and 17,994 — identical, because that PR came from injected challenge wins at ~6 PR/hr, not from the Loom. The simulator is not broken; it is answering a different question.

**Scope of `balance-sim`, therefore**: it validates Act 1 progression to Z50 / Ascension X — the 28-pattern and Ascension X *prerequisites* of the gate. It does not and should not validate the PR runway. **Do not read a green balance-sim run as evidence about Act 2's entrance.**

**Alternatives considered**: giving the simulator a virtual wall clock so the Loom economy runs headless (rejected for this purpose — it would spend real effort reproducing a closed-form constant; revisit only if the Loom gains RNG or cross-system feedback that makes its output genuinely emergent); leaving the runway unrecorded (rejected — it was mistaken for an open empirical question and briefly treated as a release blocker, which is what prompted this entry).

**System**: vessel (launch gate) × loom (WR→PR) × simulator scope.

### Act 2 Souls: The Covenant — Nothing Harms a Soul While You Are Away

A hard, CI-enforced invariant: **no tick-driven code path may reduce the roster.** Nights, weather, drift, hold-station, and offline resolution never touch souls; a property test simulates arbitrary offline windows and asserts roster count is invariant. Souls are lost **only in authored scenes** attached to named threats — the threat was on the junction card, the road was chosen, and the scene offered a priced alternative. There is no dice-based loss. A loss is memorialized: the soul's name is carved into the hull art for the rest of the game (Act 3 included), their arc becomes a memorial manifest line, and their counsel lines go silent.
Expand Down
12 changes: 9 additions & 3 deletions docs/dossiers/act2-pilgrimage.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ Act 1 (everything) Act 2: launch → crossing 1 → the Ferryman
250,000 PR (burn) ─┘ │ │ (Act 3 hook #1 —
Zone 50 kill ─► signal ───────┘ │ spec-normative)
▼ │
Deep/Loom/etc. idle beneath ◄── untouched Colony founded ◄────────┘
Deep/Loom/etc. STOP (frozen, no ticks) Colony founded ◄────────┘
┌───────────────────► Reckoning: Salvage
│ ─► Drive / Shipwright / Ward
Expand All @@ -304,8 +304,14 @@ Act 1 (everything) Act 2: launch → crossing 1 → the Ferryman
- **In**: the launch gate deliberately braids *all* of Act 1 (Loom, Ascension,
PR economy, Zone 50) into one burn — the act's strongest cross-system edge.
- **During**: zero mechanical interaction with Act 1 — deliberate ("one-way
passage"); Act 1 idles untouched beneath. Narrative callbacks only
(Torvald is the Deep guild's captain).
passage"). Act 1 does not *idle* beneath: it **stops**. `main.rs:555` takes
the voyage branch and `continue`s past both `game_tick_with_context` call
sites, so no zone ticks, no PR accrues, no Haven builds — and permanently,
since `vessel_launched` is never unset. The hero the player spent hundreds of
hours building is inert for the whole era. Confirmed intended (2026-07-14);
noted here because the earlier "idles untouched" phrasing was read as "keeps
running" and became the (void) premise for the "Act 1 bridges" Phase 2 idea.
Narrative callbacks only (Torvald is the Deep guild's captain).
- **The ferry loop is the act's second major cross-system braid**, but an
internal one: Reckoning spend (Drive/Shipwright/Ward) feeds directly back
into how much of the old world the next crossing can rescue before the
Expand Down
24 changes: 24 additions & 0 deletions docs/explorations/2026-07-05-act2-systems-braiding.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,30 @@ most of Act 1's growth systems are already maxed.** Ascension X is the
level cap. 28/28 patterns is Loom's completion state. The two hardest gates
in the game are, definitionally, *finished* the moment Act 2 opens.

> **⚠️ CORRECTION (2026-07-14) — the paragraph below is factually wrong. Do
> not build on it.**
>
> Act 1 does **not** keep running during Act 2. `main.rs:555` takes the voyage
> branch on `vessel_launched && act2_enabled()` and `main.rs:1018` `continue`s,
> while both `game_tick_with_context` call sites sit at `main.rs:1253` / `:1608`
> — *after* it. Zones don't tick, Power Cores don't generate, Haven doesn't
> build, nothing is gettable. Act 1 is **frozen**, and permanently so
> (`vessel_launched` is only ever set `true`). Confirmed intended design,
> 2026-07-14.
>
> **What this voids:** there is no stranded output to redirect, so the "second
> outlet" framing below — and the "Act 1 bridges" Phase 2 item it justified
> (#734) — has no premise. Any such bridge is *new content*, not reuse, and
> must be re-argued from scratch on its own merits.
>
> **What survives:** the opening observation still holds — Ascension X and 28/28
> patterns *are* maxed at launch. But they're not "stranded and still
> producing"; they're switched off. The real question this exploration should
> have asked: **is it right that the hero a player built over hundreds of hours
> goes inert for a 3–7 month era?** That is a live design question, unanswered.
>
> Preserved verbatim below as the record of how the item came to be proposed.

So a player deep in a 3–5-month Ferryman era who keeps playing Act 1 in
parallel (zones still tick, Power Cores still generate PR, Haven rooms
still build, Fishing/Challenges/Achievements are all still gettable) is
Expand Down
13 changes: 10 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,9 +549,16 @@ fn main() -> io::Result<()> {
'game_loop: loop {
// ── Act 2: The Crossing ─────────────────────────────
// After the launch burn, the loop belongs to the
// voyage: chart, holds, junctions. Act 1 systems idle
// untouched beneath it; spec 6 (the Going-Dark) owns
// their eventual wind-down.
// voyage: chart, holds, junctions. This branch ends in
// `continue`, so everything below it — including both
// `game_tick_with_context` call sites — is skipped while
// launched. Act 1 is *frozen*, not idling: no zones
// tick, no PR accrues, no Haven builds. And because
// `vessel_launched` is only ever set true (never unset),
// that is permanent for this character. Do not write
// "Act 1 idles beneath" here — that phrasing has
// misled design docs into assuming Act 1 output keeps
// accumulating during the era. It does not.
if state.vessel_launched && vessel::act2_enabled() {
// The 5-beat launch transition (spec 4) plays once,
// between the burn and the first Voyage frame. It
Expand Down
Loading