v0.4.1 - bug fixes. initial d12 rolls determine what player in which seat.

This commit is contained in:
Jesse
2026-08-13 15:28:53 -04:00
parent 49f8504b05
commit a7221dcf20
22 changed files with 736 additions and 237 deletions
+12 -3
View File
@@ -1,9 +1,18 @@
/**
* Events — protocol.md §3.
*
* An event is a FACT. Events are ordered, append-only, and fully determine state:
* `state = fold(events)`. That one property gives reconnection, restart recovery and post-game
* replay together.
* An event is a FACT: ordered, append-only, and standalone. Events NARRATE the game — they drive the
* log, the sounds and the replay's captions.
*
* THEY DO NOT RECONSTRUCT IT. This header claimed `state = fold(events)` until v0.4.0 and it was
* never true. `applyIntent` does go through `reduce`, but the phase driver in `advance.ts` mutates
* state and THEN emits a descriptive event, so fourteen of the forty-six types below are never
* reduced — the clock, and the whole Mainline phase, which is every train movement in the game.
*
* The canonical record is `{ seed, history: Intent[] }`, replayed by `fromSave`. That is what save,
* restore, undo, restart recovery and post-game replay all run on. See
* `docs/architecture/protocol.md` §3, and `test/events.test.ts`, which pins the unreduced set so
* that closing the gap is a deliberate act rather than a surprise.
*
* DESIGN RULE (overview.md, post-game replay): events must render STANDALONE. Carry the from/to,
* not just an id the renderer has to resolve against live state — otherwise a replay viewer has to