@dreamboard-games/sdk 0.5.0-alpha.2 → 0.5.0-alpha.4

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 (151) hide show
  1. package/README.md +186 -45
  2. package/dist/board-target-B0QG6OYx.d.ts +8 -0
  3. package/dist/chunk-3JXUL4VN.js +139 -0
  4. package/dist/chunk-3JXUL4VN.js.map +1 -0
  5. package/dist/{chunk-S2JEDVWH.js → chunk-C77SYIVT.js} +6102 -6505
  6. package/dist/chunk-C77SYIVT.js.map +1 -0
  7. package/dist/chunk-DMFVAZI2.js +16 -0
  8. package/dist/chunk-DMFVAZI2.js.map +1 -0
  9. package/dist/chunk-OOFMBCFF.js +1338 -0
  10. package/dist/chunk-OOFMBCFF.js.map +1 -0
  11. package/dist/chunk-UG2Q4NLG.js +590 -0
  12. package/dist/chunk-UG2Q4NLG.js.map +1 -0
  13. package/dist/chunk-XU6WJW6K.js +847 -0
  14. package/dist/chunk-XU6WJW6K.js.map +1 -0
  15. package/dist/diagnostics-B8d5aLad.d.ts +65 -0
  16. package/dist/extract-gVKcB8Og.d.ts +4736 -0
  17. package/dist/index.d.ts +3782 -1
  18. package/dist/index.js +1096 -6
  19. package/dist/index.js.map +1 -1
  20. package/dist/model-vdpLHrxh.d.ts +432 -0
  21. package/dist/react.d.ts +60 -0
  22. package/dist/react.js +208 -0
  23. package/dist/react.js.map +1 -0
  24. package/dist/reducer.d.ts +1244 -78
  25. package/dist/reducer.js +4204 -121
  26. package/dist/reducer.js.map +1 -1
  27. package/dist/testing.d.ts +520 -564
  28. package/dist/testing.js +2451 -915
  29. package/dist/testing.js.map +1 -1
  30. package/dist/types-Bj5ZLTUV.d.ts +114 -0
  31. package/package.json +40 -142
  32. package/dist/HandView-Bi2lxzQP.d.ts +0 -79
  33. package/dist/ResourceCounter-BFxJknqp.d.ts +0 -98
  34. package/dist/ThemeProvider-CElaL2ik.d.ts +0 -99
  35. package/dist/attributes-DbvyMbXw.d.ts +0 -68
  36. package/dist/browser-interaction.d.ts +0 -910
  37. package/dist/browser-interaction.js +0 -119
  38. package/dist/browser-interaction.js.map +0 -1
  39. package/dist/chunk-32PFKDV7.js +0 -11705
  40. package/dist/chunk-32PFKDV7.js.map +0 -1
  41. package/dist/chunk-3BAD4VC2.js +0 -263
  42. package/dist/chunk-3BAD4VC2.js.map +0 -1
  43. package/dist/chunk-3SKDNDPG.js +0 -104
  44. package/dist/chunk-3SKDNDPG.js.map +0 -1
  45. package/dist/chunk-5YV2WHJ4.js +0 -25
  46. package/dist/chunk-5YV2WHJ4.js.map +0 -1
  47. package/dist/chunk-ANRB4XKA.js +0 -90
  48. package/dist/chunk-ANRB4XKA.js.map +0 -1
  49. package/dist/chunk-BI4G3PM2.js +0 -1864
  50. package/dist/chunk-BI4G3PM2.js.map +0 -1
  51. package/dist/chunk-EVCLTY4Q.js +0 -935
  52. package/dist/chunk-EVCLTY4Q.js.map +0 -1
  53. package/dist/chunk-GDPKTBUR.js +0 -564
  54. package/dist/chunk-GDPKTBUR.js.map +0 -1
  55. package/dist/chunk-H6VDGFL5.js +0 -2903
  56. package/dist/chunk-H6VDGFL5.js.map +0 -1
  57. package/dist/chunk-LR3ZTWQF.js +0 -5960
  58. package/dist/chunk-LR3ZTWQF.js.map +0 -1
  59. package/dist/chunk-PF7L4BMG.js +0 -117
  60. package/dist/chunk-PF7L4BMG.js.map +0 -1
  61. package/dist/chunk-PN5O6GG2.js +0 -32
  62. package/dist/chunk-PN5O6GG2.js.map +0 -1
  63. package/dist/chunk-PZ5AY32C.js +0 -10
  64. package/dist/chunk-PZ5AY32C.js.map +0 -1
  65. package/dist/chunk-S2JEDVWH.js.map +0 -1
  66. package/dist/chunk-T3ZKNUZ7.js +0 -1
  67. package/dist/chunk-T3ZKNUZ7.js.map +0 -1
  68. package/dist/chunk-UGH54WZ2.js +0 -223
  69. package/dist/chunk-UGH54WZ2.js.map +0 -1
  70. package/dist/chunk-VCDWP5VL.js +0 -746
  71. package/dist/chunk-VCDWP5VL.js.map +0 -1
  72. package/dist/chunk-VDXOF4FW.js +0 -69
  73. package/dist/chunk-VDXOF4FW.js.map +0 -1
  74. package/dist/chunk-WHR5UW3F.js +0 -1988
  75. package/dist/chunk-WHR5UW3F.js.map +0 -1
  76. package/dist/chunk-Y75CFE77.js +0 -17
  77. package/dist/chunk-Y75CFE77.js.map +0 -1
  78. package/dist/chunk-Z7QCREWI.js +0 -3435
  79. package/dist/chunk-Z7QCREWI.js.map +0 -1
  80. package/dist/chunk-ZZGN2ATS.js +0 -1941
  81. package/dist/chunk-ZZGN2ATS.js.map +0 -1
  82. package/dist/components-gAbIz7hK.d.ts +0 -1284
  83. package/dist/definitions-BgmV_GhC.d.ts +0 -300
  84. package/dist/diagnostics-DIi3ina7.d.ts +0 -50
  85. package/dist/digest.d.ts +0 -8
  86. package/dist/game-CsZScpcn.d.ts +0 -763
  87. package/dist/hex-board-view-aKkblDp6.d.ts +0 -1228
  88. package/dist/index-CcT9Q7N7.d.ts +0 -193
  89. package/dist/index.d-DjzoK7zn.d.ts +0 -2101
  90. package/dist/package-set.d.ts +0 -13
  91. package/dist/package-set.js +0 -12
  92. package/dist/package-set.js.map +0 -1
  93. package/dist/player-state-Cqpyeql0.d.ts +0 -371
  94. package/dist/plugin-runtime-contract.d.ts +0 -17
  95. package/dist/plugin-runtime-contract.js +0 -92
  96. package/dist/plugin-runtime-contract.js.map +0 -1
  97. package/dist/primitive-props-BNHDkgd7.d.ts +0 -16
  98. package/dist/protocol-dYgafTYY.d.ts +0 -314
  99. package/dist/reducer/advanced.d.ts +0 -82
  100. package/dist/reducer/advanced.js +0 -51
  101. package/dist/reducer/advanced.js.map +0 -1
  102. package/dist/reducer-contract.d.ts +0 -11
  103. package/dist/reducer-contract.js +0 -16
  104. package/dist/reducer-contract.js.map +0 -1
  105. package/dist/reference-games/index.d.ts +0 -31
  106. package/dist/reference-games/index.js +0 -48
  107. package/dist/reference-games/index.js.map +0 -1
  108. package/dist/runtime/primitives.d.ts +0 -250
  109. package/dist/runtime/primitives.js +0 -189
  110. package/dist/runtime/primitives.js.map +0 -1
  111. package/dist/runtime/runtime-api.d.ts +0 -2
  112. package/dist/runtime/runtime-api.js +0 -1
  113. package/dist/runtime/runtime-api.js.map +0 -1
  114. package/dist/runtime/workspace-contract.d.ts +0 -392
  115. package/dist/runtime/workspace-contract.js +0 -28
  116. package/dist/runtime/workspace-contract.js.map +0 -1
  117. package/dist/runtime-RJ5orDJU.d.ts +0 -1699
  118. package/dist/runtime-api-Bz5pwNU_.d.ts +0 -296
  119. package/dist/runtime-json-CQ9QbLZ5.d.ts +0 -5
  120. package/dist/runtime.d.ts +0 -83
  121. package/dist/runtime.js +0 -242
  122. package/dist/runtime.js.map +0 -1
  123. package/dist/schema.d.ts +0 -379
  124. package/dist/stale-contract-artifact-error-XLaweZtF.d.ts +0 -18
  125. package/dist/testing-compiler.d.ts +0 -37
  126. package/dist/testing-compiler.js +0 -272
  127. package/dist/testing-compiler.js.map +0 -1
  128. package/dist/testing-runtime.d.ts +0 -119
  129. package/dist/testing-runtime.js +0 -212
  130. package/dist/testing-runtime.js.map +0 -1
  131. package/dist/types-DJj5MJkl.d.ts +0 -256
  132. package/dist/types-DR7DoB1x.d.ts +0 -28
  133. package/dist/types-JWCYHmu7.d.ts +0 -122
  134. package/dist/types.d.ts +0 -1958
  135. package/dist/types.js +0 -14
  136. package/dist/types.js.map +0 -1
  137. package/dist/ui/components.d.ts +0 -17
  138. package/dist/ui/components.js +0 -216
  139. package/dist/ui/components.js.map +0 -1
  140. package/dist/ui/defaults.d.ts +0 -19
  141. package/dist/ui/defaults.js +0 -104
  142. package/dist/ui/defaults.js.map +0 -1
  143. package/dist/ui/player-state.d.ts +0 -2
  144. package/dist/ui/player-state.js +0 -1
  145. package/dist/ui/player-state.js.map +0 -1
  146. package/dist/ui/plugin-styles.css +0 -2
  147. package/dist/ui-contract-GTUPkf8z.d.ts +0 -1168
  148. package/dist/ui.d.ts +0 -317
  149. package/dist/ui.js +0 -277
  150. package/dist/ui.js.map +0 -1
  151. package/dist/views-BpuWcOyN.d.ts +0 -1641
@@ -1,1641 +0,0 @@
1
- import { bW as RuntimeTableRecord, aF as PlayerIdOfState, aA as PhaseStateOfState, aN as PublicStateOfState, a7 as HiddenStateOfState, aL as PrivateStateOfState, co as SharedZoneIdOfTable, cJ as TableOfState, F as DeckCardsOfTable, aG as PlayerIdOfTable, H as DeckIdOfTable, aJ as PlayerZoneIdOfTable, u as CompatibleCardIdForTwoPlayerZones, t as CompatibleCardIdForHandAndDeck, v as CompatibleHandIdForDeck, X as HandIdOfTable, p as CardIdOfTable, e as BoardIdOfTable, cq as SpaceIdOfTable, x as ComponentIdOfTable, c as BoardContainerIdOfTable, cM as TiledBoardIdOfTable, cO as TiledEdgeIdOfTable, cU as TiledVertexIdOfTable, b7 as ResourceAmountsOfTable, bc as ResourceIdOfTable, S as GameEvent, by as RuntimeInstructionForState, L as EffectSpecLike, K as EffectInvokeOptions, aO as ReducerAccept, aw as PhaseNameOfState, U as GameOutcome, aU as ReducerReject, cL as TableQueriesOfState, aR as ReducerGameState, cI as TableOfManifest, ab as ManifestContractOf, aM as PublicSchemaOfContract, aK as PrivateSchemaOfContract, a6 as HiddenSchemaOfContract, az as PhaseStateMapOfContract, au as PhaseNameOfContract, c2 as SchemaLike, cD as StateDefinition, a8 as InitContext, ai as ManifestOf, O as ExactManifestContractOf, cg as SetupProfileDefinition, aS as ReducerManifestContract, aX as ReducerSessionState, bL as RuntimeSetupSelection, bC as RuntimePhaseState, aa as ManifestContract, aW as ReducerRuntimeStateForState, ck as SetupSelectionOfManifest, cG as StringKeyOf, a as AnySchema, E as ContinuationToken, aV as ReducerResult, A as AnyContinuationToken, aH as PlayerZoneIdOfManifest, q as CardTypeOfState, o as CardIdOfState } from './runtime-RJ5orDJU.js';
2
- import { z } from 'zod';
3
-
4
- /**
5
- * State composition primitives.
6
- *
7
- * `pipe` threads a seed state through a sequence of `State -> State`
8
- * transformations, left to right. It is the preferred way to compose curried
9
- * writers (the `ops.*` namespace) in reducers:
10
- *
11
- * return accept(
12
- * pipe(state,
13
- * ops.spendPlayerResources({ playerId, resources: cost }),
14
- * ops.placePieceOnVertex({ boardId, vertexId, pieceId, ownerId: playerId }),
15
- * ),
16
- * );
17
- */
18
- /**
19
- * A state-preserving transformation.
20
- *
21
- * `Op<State>` is polymorphic in the exact input subtype — given a state `S`
22
- * that extends `State`, it returns the same `S`. This lets curried writers
23
- * from `ops.*` and author-written helpers thread through phase-scoped `pipe`
24
- * calls without losing the narrowed phase state type.
25
- */
26
- type Op<State> = <S extends State>(state: S) => S;
27
- declare function pipe<State>(state: State, ...ops: ReadonlyArray<Op<NoInfer<State>>>): State;
28
-
29
- /**
30
- * Curried state writers for use with `pipe`.
31
- *
32
- * Each entry in the returned `ops` namespace is a curried transformation
33
- * `(args) => (state) => state` that can be composed with `pipe`:
34
- *
35
- * const ops = createReducerOps<GameState>();
36
- *
37
- * return accept(
38
- * pipe(state,
39
- * ops.setActivePlayers([playerId]),
40
- * ops.moveCardFromPlayerZoneToSharedZone({
41
- * playerId,
42
- * fromZoneId: "things-hand",
43
- * toZoneId: "ring-1",
44
- * cardId: "a-dog",
45
- * }),
46
- * ),
47
- * );
48
- *
49
- * The factory binds all ops to a specific `State` type so that ID arguments
50
- * (deck ids, card ids, etc.) are checked against the manifest-derived table
51
- * shape of the game.
52
- */
53
-
54
- /**
55
- * Minimum shape required for any state targeted by reducer ops.
56
- *
57
- * All curried writers operate on a game state with a `table` field.
58
- */
59
- type ReducerStateBase = {
60
- table: RuntimeTableRecord;
61
- };
62
- type PipeTable<State extends ReducerStateBase> = TableOfState<State>;
63
- /**
64
- * Shallow patch or functional updater for one state slice. The updater is a
65
- * method-style callable so a transaction over a phase-scoped state stays
66
- * assignable to one over the base game state; a plain function type would be
67
- * invariant in `T` under `strictFunctionTypes`.
68
- */
69
- type StatePatch<T> = Partial<T> | {
70
- update(prev: T): T;
71
- }["update"];
72
- /**
73
- * Curried writer namespace for a specific game state type.
74
- *
75
- * Created via {@link createReducerOps}.
76
- */
77
- interface ReducerOps<State extends ReducerStateBase> {
78
- /** Set the list of players whose turn is currently active. */
79
- setActivePlayers(activePlayers: ReadonlyArray<PlayerIdOfState<State>>): Op<State>;
80
- /**
81
- * Advance `flow.activePlayers` to the single next seat in `playerOrder`.
82
- *
83
- * Uses `state.flow.activePlayers[0]` as the current seat (or the first
84
- * seat in `playerOrder` when `activePlayers` is empty) and sets
85
- * `activePlayers` to `[q.player.nextInOrder(current)]`. No-op when the
86
- * player order is empty.
87
- */
88
- advanceActivePlayer(): Op<State>;
89
- /**
90
- * Update the current phase's local state.
91
- *
92
- * Accepts either a `Partial<PhaseState>` which is shallow-merged into the
93
- * previous value, or a functional updater `(prev) => next` which must
94
- * return a complete `PhaseState`.
95
- */
96
- patchPhaseState(patch: StatePatch<PhaseStateOfState<State>>): Op<State>;
97
- /**
98
- * Update `state.publicState`.
99
- *
100
- * Accepts either a `Partial<PublicState>` which is shallow-merged into the
101
- * previous value, or a functional updater `(prev) => next` which must
102
- * return a complete `PublicState`.
103
- */
104
- patchPublicState(patch: StatePatch<PublicStateOfState<State>>): Op<State>;
105
- /**
106
- * Update `state.hiddenState`.
107
- *
108
- * Accepts either a `Partial<HiddenState>` or a functional updater.
109
- */
110
- patchHiddenState(patch: StatePatch<HiddenStateOfState<State>>): Op<State>;
111
- /**
112
- * Update a single player's entry in `state.privateState`.
113
- *
114
- * Accepts either a `Partial<PrivateState>` or a functional updater.
115
- */
116
- patchPlayerPrivateState(args: {
117
- playerId: PlayerIdOfState<State>;
118
- patch: StatePatch<PrivateStateOfState<State>>;
119
- }): Op<State>;
120
- /**
121
- * Append a card to a shared zone (deck). Defaults to placing the card at the
122
- * bottom; pass `position: "top"` for top-of-deck placement (e.g. Bureaucrat-style).
123
- */
124
- addCardToSharedZone<DeckId extends SharedZoneIdOfTable<PipeTable<State>>>(args: {
125
- deckId: DeckId;
126
- cardId: DeckCardsOfTable<PipeTable<State>, DeckId>[number];
127
- playedBy?: PlayerIdOfTable<PipeTable<State>> | null;
128
- position?: "top" | "bottom";
129
- }): Op<State>;
130
- /** Remove a card from a shared zone (deck). */
131
- removeCardFromSharedZone<DeckId extends DeckIdOfTable<PipeTable<State>>>(args: {
132
- deckId: DeckId;
133
- cardId: DeckCardsOfTable<PipeTable<State>, DeckId>[number];
134
- }): Op<State>;
135
- /**
136
- * Move a card between two shared zones (decks). Defaults to placing the card
137
- * at the bottom of the destination; pass `position: "top"` for top placement.
138
- */
139
- moveCardBetweenSharedZones<FromZoneId extends SharedZoneIdOfTable<PipeTable<State>>, ToZoneId extends SharedZoneIdOfTable<PipeTable<State>>>(args: {
140
- fromZoneId: FromZoneId;
141
- toZoneId: ToZoneId;
142
- cardId: DeckCardsOfTable<PipeTable<State>, FromZoneId>[number];
143
- playedBy?: PlayerIdOfTable<PipeTable<State>> | null;
144
- position?: "top" | "bottom";
145
- }): Op<State>;
146
- /**
147
- * Draw the top `count` cards from one perPlayer zone into another for the
148
- * same player (e.g. deck → hand at the start of a turn). Companion to
149
- * {@link dealCardsToPlayerZone} for the perPlayer → perPlayer case. Stops
150
- * silently if the source runs out before `count` is reached.
151
- */
152
- dealCardsBetweenPlayerZones<FromZoneId extends PlayerZoneIdOfTable<PipeTable<State>>, ToZoneId extends PlayerZoneIdOfTable<PipeTable<State>>, PlayerId extends PlayerIdOfTable<PipeTable<State>>>(args: {
153
- playerId: PlayerId;
154
- fromZoneId: FromZoneId;
155
- toZoneId: ToZoneId;
156
- count: number;
157
- }): Op<State>;
158
- /**
159
- * Move a card between two perPlayer zones owned by the same player (e.g.
160
- * hand → in-play → discard). Owner is preserved; visibility is recomputed
161
- * from the destination zone.
162
- */
163
- moveCardBetweenPlayerZones<FromZoneId extends PlayerZoneIdOfTable<PipeTable<State>>, ToZoneId extends PlayerZoneIdOfTable<PipeTable<State>>, PlayerId extends PlayerIdOfTable<PipeTable<State>>>(args: {
164
- playerId: PlayerId;
165
- fromZoneId: FromZoneId;
166
- toZoneId: ToZoneId;
167
- cardId: CompatibleCardIdForTwoPlayerZones<PipeTable<State>, FromZoneId, ToZoneId>;
168
- position?: "top" | "bottom";
169
- }): Op<State>;
170
- /**
171
- * Move a card from a player zone (hand) to a shared zone (deck). Defaults to
172
- * placing the card at the bottom; pass `position: "top"` to topdeck.
173
- */
174
- moveCardFromPlayerZoneToSharedZone<FromZoneId extends PlayerZoneIdOfTable<PipeTable<State>>, ToZoneId extends SharedZoneIdOfTable<PipeTable<State>>, PlayerId extends PlayerIdOfTable<PipeTable<State>>>(args: {
175
- playerId: PlayerId;
176
- fromZoneId: FromZoneId;
177
- toZoneId: ToZoneId;
178
- cardId: CompatibleCardIdForHandAndDeck<PipeTable<State>, FromZoneId, ToZoneId>;
179
- playedBy?: PlayerIdOfTable<PipeTable<State>> | null;
180
- position?: "top" | "bottom";
181
- }): Op<State>;
182
- /**
183
- * Move a named card from a shared zone (supply pile, deck) to a perPlayer
184
- * zone (e.g. discard). The "gain" verb in deck-builders. Distinct from
185
- * {@link dealCardsToPlayerZone}, which draws unspecified top-N cards from a
186
- * deck. Owner flips to the receiving player; visibility is recomputed.
187
- */
188
- moveCardFromSharedZoneToPlayerZone<FromZoneId extends SharedZoneIdOfTable<PipeTable<State>>, ToZoneId extends PlayerZoneIdOfTable<PipeTable<State>>, PlayerId extends PlayerIdOfTable<PipeTable<State>>>(args: {
189
- playerId: PlayerId;
190
- fromZoneId: FromZoneId;
191
- toZoneId: ToZoneId;
192
- cardId: CompatibleCardIdForHandAndDeck<PipeTable<State>, ToZoneId, FromZoneId>;
193
- position?: "top" | "bottom";
194
- }): Op<State>;
195
- /**
196
- * Deal the top `count` cards from a shared deck into a player's hand zone.
197
- *
198
- * This op does not consume RNG. If the deck needs to be random, shuffle it
199
- * first with `fx.shuffleSharedZone(...)`, then deal from the shuffled deck
200
- * inside the same reducer via this op.
201
- */
202
- dealCardsToPlayerZone<FromZoneId extends DeckIdOfTable<PipeTable<State>>, PlayerId extends PlayerIdOfTable<PipeTable<State>>, ToZoneId extends CompatibleHandIdForDeck<PipeTable<State>, FromZoneId> & HandIdOfTable<PipeTable<State>>>(args: {
203
- fromZoneId: FromZoneId;
204
- playerId: PlayerId;
205
- toZoneId: ToZoneId;
206
- count: number;
207
- }): Op<State>;
208
- /**
209
- * Atomically rotate cards in a per-player zone around the table.
210
- *
211
- * Defaults to rotating every card currently in `zoneId` for every player in
212
- * turn order. Pass `players` to use a smaller explicit order, or
213
- * `cardIdsByPlayer` to rotate only selected cards such as Hearts passes.
214
- */
215
- rotatePlayerZone<ZoneId extends PlayerZoneIdOfTable<PipeTable<State>>, PlayerId extends PlayerIdOfTable<PipeTable<State>>>(args: {
216
- zoneId: ZoneId;
217
- direction: "left" | "right";
218
- players?: readonly PlayerId[];
219
- cardIdsByPlayer?: Partial<Record<PlayerId, readonly CardIdOfTable<PipeTable<State>>[]>>;
220
- position?: "top" | "bottom";
221
- }): Op<State>;
222
- /** Move a component onto a board space. */
223
- moveComponentToSpace<BoardId extends BoardIdOfTable<PipeTable<State>>, SpaceId extends SpaceIdOfTable<PipeTable<State>, BoardId>, ComponentId extends ComponentIdOfTable<PipeTable<State>>>(args: {
224
- componentId: ComponentId;
225
- boardId: BoardId;
226
- spaceId: SpaceId;
227
- }): Op<State>;
228
- /** Move a component into a board container. */
229
- moveComponentToContainer<BoardId extends BoardIdOfTable<PipeTable<State>>, ContainerId extends BoardContainerIdOfTable<PipeTable<State>, BoardId>, ComponentId extends ComponentIdOfTable<PipeTable<State>>>(args: {
230
- componentId: ComponentId;
231
- boardId: BoardId;
232
- containerId: ContainerId;
233
- }): Op<State>;
234
- /** Move a component onto a tiled board edge. */
235
- moveComponentToEdge<BoardId extends TiledBoardIdOfTable<PipeTable<State>>, EdgeId extends TiledEdgeIdOfTable<PipeTable<State>, BoardId>, ComponentId extends ComponentIdOfTable<PipeTable<State>>>(args: {
236
- componentId: ComponentId;
237
- boardId: BoardId;
238
- edgeId: EdgeId;
239
- }): Op<State>;
240
- /** Move a component onto a tiled board vertex. */
241
- moveComponentToVertex<BoardId extends TiledBoardIdOfTable<PipeTable<State>>, VertexId extends TiledVertexIdOfTable<PipeTable<State>, BoardId>, ComponentId extends ComponentIdOfTable<PipeTable<State>>>(args: {
242
- componentId: ComponentId;
243
- boardId: BoardId;
244
- vertexId: VertexId;
245
- }): Op<State>;
246
- /** Move a component back to the detached pool. */
247
- moveComponentToDetached<ComponentId extends ComponentIdOfTable<PipeTable<State>>>(args: {
248
- componentId: ComponentId;
249
- }): Op<State>;
250
- /**
251
- * Credit the specified resources to a player.
252
- *
253
- * Amounts must be non-negative; use {@link spendResources} for deductions
254
- * so that affordability is checked explicitly.
255
- *
256
- * pipe(
257
- * state,
258
- * ops.addResources({ playerId, amounts: { wood: 1, brick: 1 } }),
259
- * )
260
- */
261
- addResources(args: {
262
- playerId: PlayerIdOfTable<PipeTable<State>>;
263
- amounts: ResourceAmountsOfTable<PipeTable<State>>;
264
- }): Op<State>;
265
- /**
266
- * Debit the specified resources from a player.
267
- *
268
- * Throws when the player cannot afford the full cost — gate with
269
- * `q.player.canAfford(...)` in your `validate` step before invoking.
270
- *
271
- * pipe(
272
- * state,
273
- * ops.spendResources({ playerId, amounts: COST_DEV_CARD }),
274
- * ops.dealCardsToPlayerZone({ ... }),
275
- * )
276
- */
277
- spendResources(args: {
278
- playerId: PlayerIdOfTable<PipeTable<State>>;
279
- amounts: ResourceAmountsOfTable<PipeTable<State>>;
280
- }): Op<State>;
281
- /**
282
- * Transfer the specified resources from one player to another.
283
- *
284
- * Throws when the source cannot afford the full amount. On success the
285
- * destination gains exactly what the source loses.
286
- */
287
- transferResources(args: {
288
- fromPlayerId: PlayerIdOfTable<PipeTable<State>>;
289
- toPlayerId: PlayerIdOfTable<PipeTable<State>>;
290
- amounts: ResourceAmountsOfTable<PipeTable<State>>;
291
- }): Op<State>;
292
- /**
293
- * Overwrite a single resource balance for a player. Prefer
294
- * {@link addResources} / {@link spendResources} — use this only when the
295
- * new balance is an absolute (e.g. scripted setup).
296
- */
297
- setResource(args: {
298
- playerId: PlayerIdOfTable<PipeTable<State>>;
299
- resourceId: ResourceIdOfTable<PipeTable<State>>;
300
- amount: number;
301
- }): Op<State>;
302
- }
303
- /**
304
- * Create the `ops.*` namespace specialised to a game state.
305
- *
306
- * Call this once (typically in a shared reducer-support module) and reuse the
307
- * resulting object across phases:
308
- *
309
- * export const ops = createReducerOps<GameState>();
310
- */
311
- declare function createReducerOps<State extends ReducerStateBase>(): ReducerOps<State>;
312
-
313
- type IsAny<Value> = 0 extends 1 & Value ? true : false;
314
- type WithFlow<State> = State extends {
315
- flow: {
316
- currentPhase: string;
317
- };
318
- } ? State : State & {
319
- flow: {
320
- currentPhase: string;
321
- };
322
- };
323
- /** Phase names a transaction may transition to; `string` when state is erased. */
324
- type TransitionTarget<State> = IsAny<State> extends true ? string : PhaseNameOfState<State>;
325
- type RotatePlayerZoneArgs<State extends {
326
- table: RuntimeTableRecord;
327
- }, ZoneId extends PlayerZoneIdOfTable<TableOfState<State>> = PlayerZoneIdOfTable<TableOfState<State>>, PlayerId extends PlayerIdOfTable<TableOfState<State>> = PlayerIdOfTable<TableOfState<State>>> = {
328
- zoneId: ZoneId;
329
- direction: "left" | "right";
330
- players?: readonly PlayerId[];
331
- cardIdsByPlayer?: Partial<Record<PlayerId, readonly CardIdOfTable<TableOfState<State>>[]>>;
332
- position?: "top" | "bottom";
333
- };
334
- /**
335
- * Method-style callable. Method parameters are compared bivariantly, so a
336
- * transaction over a phase-scoped state stays assignable to one over the base
337
- * game state (and vice versa for engine-erased states). Function-typed
338
- * properties would be invariant under `strictFunctionTypes`.
339
- */
340
- type BivariantMethod<Args extends readonly unknown[], Result> = {
341
- method(...args: Args): Result;
342
- }["method"];
343
- type TransactionMethods<State extends {
344
- table: RuntimeTableRecord;
345
- }> = {
346
- [Key in Exclude<keyof ReducerOps<State>, "moveComponentToSpace">]: ReducerOps<State>[Key] extends (...args: infer Args) => Op<State> ? BivariantMethod<Args, State> : never;
347
- } & {
348
- moveComponentToSpace<BoardId extends BoardIdOfTable<TableOfState<State>>, SpaceId extends SpaceIdOfTable<TableOfState<State>, BoardId>, ComponentId extends ComponentIdOfTable<TableOfState<State>>>(args: {
349
- componentId: ComponentId;
350
- boardId: BoardId;
351
- spaceId: SpaceId;
352
- }): State;
353
- };
354
- /**
355
- * Result builders on the transaction. A mutation callback ends with one of
356
- * these or with a bare `return` (accept the transaction as it stands).
357
- */
358
- type ReducerTransactionOutcome<State extends {
359
- table: RuntimeTableRecord;
360
- }, ErrorCode extends string = string> = {
361
- /** Record events on the eventual accept result. */
362
- emit(...events: GameEvent[]): void;
363
- /** Queue runtime instructions on the eventual accept result. */
364
- schedule(...instructions: RuntimeInstructionForState<State>[]): void;
365
- /** Queue an engine effect authored with `defineEffect`. */
366
- effect<Effect extends EffectSpecLike>(effect: Effect, options: EffectInvokeOptions<Effect, WithFlow<State>>): void;
367
- /** Accept with the current transaction state. Same as a bare `return`. */
368
- accept(): ReducerAccept<State>;
369
- /** Accept and move the flow to another declared phase. */
370
- transition<To extends TransitionTarget<State>>(to: To): ReducerAccept<State>;
371
- /**
372
- * Accept and end the game with a terminal outcome. Pass `transition` to
373
- * also move the flow to a terminal phase in the same result.
374
- */
375
- endGame(outcome: GameOutcome<PlayerIdOfState<State>>, options?: {
376
- transition?: TransitionTarget<State>;
377
- }): ReducerAccept<State>;
378
- /** Reject with a declared error code. The transaction is discarded. */
379
- reject(errorCode: ErrorCode, message?: string): ReducerReject;
380
- };
381
- type ReducerTransaction<State extends {
382
- table: RuntimeTableRecord;
383
- }, ErrorCode extends string = string> = TransactionMethods<State> & ReducerTransactionOutcome<State, ErrorCode> & {
384
- readonly state: State;
385
- readonly q: TableQueriesOfState<State>;
386
- apply(op: Op<State>): State;
387
- rotatePlayerZone<ZoneId extends PlayerZoneIdOfTable<TableOfState<State>>, PlayerId extends PlayerIdOfTable<TableOfState<State>>>(args: RotatePlayerZoneArgs<State, ZoneId, PlayerId>): State;
388
- };
389
-
390
- type ReducerGameContract<Table extends RuntimeTableRecord, Manifest extends ReducerManifestContract<Table, string, string, string, string, string>, PublicSchema extends SchemaLike<object>, PrivateSchema extends SchemaLike<object>, HiddenSchema extends SchemaLike<object>, Phases extends Record<string, SchemaLike<object>>, Errors extends Record<string, string> | undefined = undefined> = {
391
- manifest: Manifest;
392
- state: StateDefinition<PublicSchema, PrivateSchema, HiddenSchema>;
393
- phases: Phases;
394
- errors?: Errors;
395
- /** Derived from `phases`; retained as an internal runtime convenience. */
396
- phaseNames: readonly string[];
397
- };
398
- type ReducerStateForConfig<Table extends RuntimeTableRecord, PublicSchema extends SchemaLike<object>, PrivateSchema extends SchemaLike<object>, HiddenSchema extends SchemaLike<object>, PhaseName extends string> = ReducerGameState<Table, z.infer<PublicSchema>, z.infer<PrivateSchema>, z.infer<HiddenSchema>, RuntimePhaseState, PhaseName, Record<PhaseName, RuntimePhaseState>>;
399
- type ReducerSessionForConfig<Table extends RuntimeTableRecord, PublicSchema extends SchemaLike<object>, PrivateSchema extends SchemaLike<object>, HiddenSchema extends SchemaLike<object>, PhaseName extends string, Setup extends RuntimeSetupSelection = RuntimeSetupSelection> = ReducerSessionState<ReducerStateForConfig<Table, PublicSchema, PrivateSchema, HiddenSchema, PhaseName>, Setup>;
400
- type BaseGameStateOfContract<Contract> = ReducerGameState<TableOfManifest<ManifestContractOf<Contract>>, z.infer<PublicSchemaOfContract<Contract>>, z.infer<PrivateSchemaOfContract<Contract>>, z.infer<HiddenSchemaOfContract<Contract>>, PhaseStateMapOfContract<Contract>[PhaseNameOfContract<Contract>], PhaseNameOfContract<Contract>, PhaseStateMapOfContract<Contract>>;
401
- type BaseGameSessionOfContract<Contract> = ReducerSessionState<BaseGameStateOfContract<Contract>, RuntimeSetupSelection<ManifestContractOf<Contract>>>;
402
- /**
403
- * Heterogeneous phase map for a contract. Each phase carries its own local
404
- * `PhaseStateSchema` plus authoring-time Actions/Flows/Interactions/
405
- * Stages/Zones maps. The registries are bound to the contract's base state +
406
- * manifest so the runtime can iterate them through a single index type
407
- * without reaching for `any`.
408
- */
409
- type PhaseMapOf<Contract> = {
410
- [Name in PhaseNameOfContract<Contract>]: PhaseDefinition<SchemaLike<object>, BaseGameStateOfContract<Contract>, ManifestContractOf<Contract>, Record<string, InputCollector>, EffectMap<BaseGameStateOfContract<Contract>, ManifestContractOf<Contract>>, InteractionMap<BaseGameStateOfContract<Contract>, ManifestContractOf<Contract>>, StageMap<BaseGameStateOfContract<Contract>, ManifestContractOf<Contract>>, PhaseZoneList<ManifestContractOf<Contract>>, CardActionMap<BaseGameStateOfContract<Contract>, ManifestContractOf<Contract>>>;
411
- };
412
- type AnyPhaseDefinitionForContract<Contract> = PhaseMapOf<Contract>[PhaseNameOfContract<Contract>];
413
- /**
414
- * Helpers below accept heterogeneous phase maps (each phase binds its own
415
- * `PhaseStateSchema` + per-phase registries). TypeScript requires the
416
- * constraint to use a shape compatible with contract-bound state types in a
417
- * contravariant `initialState` position, so we erase the registry-bound
418
- * state/manifest generics with `any`. The only purpose of the constraint is
419
- * to guarantee `Definitions[Name]` is a `PhaseDefinition` so the `extends`
420
- * check below can infer `PhaseStateSchema`.
421
- */
422
- type PhaseStateMapOfDefinitions<Definitions extends Record<string, PhaseDefinition<SchemaLike<object>, any, any, Record<string, InputCollector>, EffectMap<any, any>, InteractionMap<any, any>, StageMap<any, any>, PhaseZoneList<any>, CardActionMap<any, any>>>> = Partial<{
423
- [Name in keyof Definitions & string]: Definitions[Name] extends {
424
- state: infer PhaseStateSchema extends SchemaLike<object>;
425
- } ? z.infer<PhaseStateSchema> : never;
426
- }>;
427
- type PhaseStateOfDefinitions<Definitions extends Record<string, PhaseDefinition<SchemaLike<object>, any, any, Record<string, InputCollector>, EffectMap<any, any>, InteractionMap<any, any>, StageMap<any, any>, PhaseZoneList<any>, CardActionMap<any, any>>>> = {
428
- [Name in keyof Definitions & string]: Definitions[Name] extends {
429
- state: infer PhaseStateSchema extends SchemaLike<object>;
430
- } ? z.infer<PhaseStateSchema> : never;
431
- }[keyof Definitions & string];
432
- type ResolvedGameStateOf<Contract, Definitions extends PhaseMapOf<Contract>> = {
433
- [Name in keyof Definitions & string]: ReducerGameState<TableOfManifest<ManifestContractOf<Contract>>, z.infer<PublicSchemaOfContract<Contract>>, z.infer<PrivateSchemaOfContract<Contract>>, z.infer<HiddenSchemaOfContract<Contract>>, Definitions[Name] extends {
434
- state: infer PhaseStateSchema extends SchemaLike<object>;
435
- } ? z.infer<PhaseStateSchema> : never, PhaseNameOfContract<Contract>> & {
436
- flow: ReducerGameState<TableOfManifest<ManifestContractOf<Contract>>, z.infer<PublicSchemaOfContract<Contract>>, z.infer<PrivateSchemaOfContract<Contract>>, z.infer<HiddenSchemaOfContract<Contract>>, PhaseStateOfDefinitions<Definitions>, PhaseNameOfContract<Contract>>["flow"] & {
437
- currentPhase: Name;
438
- };
439
- };
440
- }[keyof Definitions & string];
441
- type ResolvedGameSessionOf<Contract, Definitions extends PhaseMapOf<Contract>> = ReducerSessionState<ResolvedGameStateOf<Contract, Definitions>, RuntimeSetupSelection<ManifestContractOf<Contract>>>;
442
- type ViewMapOf<Contract, SharedProjection = unknown, PlayerProjection = unknown> = {
443
- shared: SharedViewDefinition<BaseGameStateOfContract<Contract>, ManifestContractOf<Contract>, SharedProjection>;
444
- player: PlayerViewDefinition<BaseGameStateOfContract<Contract>, ManifestContractOf<Contract>, SharedProjection, PlayerProjection>;
445
- };
446
- type PhasesOfDefinition<Definition> = Definition extends {
447
- phases: infer Definitions extends Record<string, unknown>;
448
- } ? Definitions : never;
449
- type ViewsOfDefinition<Definition> = Definition extends {
450
- views: infer Views;
451
- } ? Views : never;
452
- type NonNeverKeys<Registry> = {
453
- [Key in keyof Registry]-?: [Registry[Key]] extends [never] ? never : Key;
454
- }[keyof Registry];
455
- type ViewNamesOfDefinition<Definition> = NonNeverKeys<ViewsOfDefinition<Definition>> & string;
456
- type ViewDefinitionByName<Definition, ViewName extends ViewNamesOfDefinition<Definition>> = ViewsOfDefinition<Definition>[ViewName];
457
- type ViewOfDefinition<Definition, ViewName extends ViewNamesOfDefinition<Definition>> = ViewDefinitionByName<Definition, ViewName> extends {
458
- project: (...args: never[]) => infer Projection;
459
- } ? Projection : never;
460
- type PhaseNamesOfDefinition<Definition> = keyof PhasesOfDefinition<Definition> & string;
461
- type PhaseDefinitionByName<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>> = PhaseName extends keyof PhasesOfDefinition<Definition> & string ? PhasesOfDefinition<Definition>[PhaseName] : never;
462
- type EffectsOfDefinition<Definition> = PhasesOfDefinition<Definition>[keyof PhasesOfDefinition<Definition> & string] extends {
463
- effects?: infer Effects;
464
- } ? Effects extends Record<string, unknown> ? Effects[keyof Effects & string] : never : never;
465
- type EffectIdsOfDefinition<Definition> = EffectsOfDefinition<Definition> extends infer Effect ? Effect extends {
466
- id: infer Id;
467
- } ? Extract<Id, string> : never : never;
468
- type GameStateOf<Source> = Source extends {
469
- contract: infer Contract extends ReducerGameContractLike;
470
- phases: infer Definitions;
471
- } ? Definitions extends PhaseMapOf<Contract> ? ResolvedGameStateOf<Contract, Definitions> : never : Source extends ReducerGameContract<any, any, any, any, any, any, any> ? BaseGameStateOfContract<Source> : never;
472
- /**
473
- * Public structural upper bound for a reducer game contract.
474
- *
475
- * The `manifest` slot is intentionally erased with `any` because concrete
476
- * manifests bind per-contract branded literals (e.g. `PlayerId` unions with
477
- * specific string literals). Using a ground `ManifestContract<...>` type
478
- * here would prevent assignability from contract-bound manifests in a
479
- * contravariant position.
480
- */
481
- type ReducerGameContractLike = {
482
- manifest: any;
483
- state: StateDefinition<SchemaLike<object>, SchemaLike<object>, SchemaLike<object>>;
484
- };
485
- type InitialStateContextOf<Contract extends ReducerGameContractLike> = InitContext<TableOfManifest<ManifestOf<Contract>>, ExactManifestContractOf<Contract>>;
486
- type InitialStateCallbacks<Contract extends ReducerGameContractLike> = {
487
- public?: (ctx: InitialStateContextOf<Contract>) => z.infer<PublicSchemaOfContract<Contract>>;
488
- private?: (ctx: InitialStateContextOf<Contract> & {
489
- playerId: PlayerIdOfTable<TableOfManifest<ManifestOf<Contract>>>;
490
- }) => z.infer<PrivateSchemaOfContract<Contract>>;
491
- hidden?: (ctx: InitialStateContextOf<Contract>) => z.infer<HiddenSchemaOfContract<Contract>>;
492
- };
493
- type ReducerGameDefinition<Contract extends ReducerGameContractLike, Definitions extends PhaseMapOf<Contract>, Views extends ViewMapOf<Contract>> = {
494
- contract: Contract;
495
- initial?: InitialStateCallbacks<NoInfer<Contract>>;
496
- initialPhase?: keyof Definitions & string;
497
- setupProfiles?: Record<string, SetupProfileDefinition<keyof Definitions & string, ExactManifestContractOf<Contract>>>;
498
- phases: Definitions;
499
- views: Views;
500
- /**
501
- * Optional session-scoped static projection. Authored via
502
- * {@link StaticViewDefinition}; computed once per reducer session from the
503
- * manifest + setup profile and cached by the host. The client merges the
504
- * cached payload into every seat view, so the per-tick `project`
505
- * call no longer needs to re-serialize static board topology.
506
- */
507
- staticView?: StaticViewDefinition<ExactManifestContractOf<NoInfer<Contract>>, unknown>;
508
- };
509
- type AnyReducerGameDefinition = ReducerGameDefinition<ReducerGameContractLike, PhaseMapOf<ReducerGameContractLike>, ViewMapOf<ReducerGameContractLike>>;
510
- type InteractionRegistriesOfDefinition<Definition> = PhasesOfDefinition<Definition>[keyof PhasesOfDefinition<Definition> & string] extends {
511
- interactions?: infer Interactions;
512
- } ? NonNullable<Interactions> : never;
513
- type SimultaneousSubmitRegistriesOfDefinition<Definition> = PhasesOfDefinition<Definition>[keyof PhasesOfDefinition<Definition> & string] extends {
514
- submit?: infer Submit;
515
- } ? {
516
- submit: NonNullable<Submit>;
517
- } : never;
518
- type CardActionRegistriesOfDefinition<Definition> = PhasesOfDefinition<Definition>[keyof PhasesOfDefinition<Definition> & string] extends {
519
- cardActions?: infer CardActions;
520
- } ? NonNullable<CardActions> : never;
521
- type InteractionIdOfDefinition<Definition> = InteractionRegistriesOfDefinition<Definition> extends infer Interactions ? SimultaneousSubmitRegistriesOfDefinition<Definition> extends infer Submit ? CardActionRegistriesOfDefinition<Definition> extends infer CardActions ? Interactions extends Record<string, unknown> ? CardActions extends Record<string, unknown> ? Submit extends Record<string, unknown> ? (NonNeverKeys<Interactions> & string) | (NonNeverKeys<CardActions> & string) | (NonNeverKeys<Submit> & string) : (NonNeverKeys<Interactions> & string) | (NonNeverKeys<CardActions> & string) : Submit extends Record<string, unknown> ? (NonNeverKeys<Interactions> & string) | (NonNeverKeys<Submit> & string) : NonNeverKeys<Interactions> & string : CardActions extends Record<string, unknown> ? Submit extends Record<string, unknown> ? (NonNeverKeys<CardActions> & string) | (NonNeverKeys<Submit> & string) : NonNeverKeys<CardActions> & string : Submit extends Record<string, unknown> ? NonNeverKeys<Submit> & string : never : never : never : never;
522
- type InteractionRegistryOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>> = PhaseDefinitionByName<Definition, PhaseName> extends {
523
- interactions?: infer Interactions;
524
- } ? NonNullable<Interactions> : Record<string, never>;
525
- type SimultaneousSubmitRegistryOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>> = PhaseDefinitionByName<Definition, PhaseName> extends {
526
- submit?: infer Submit;
527
- } ? {
528
- submit: NonNullable<Submit>;
529
- } : Record<string, never>;
530
- type CardActionRegistryOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>> = PhaseDefinitionByName<Definition, PhaseName> extends {
531
- cardActions?: infer CardActions;
532
- } ? NonNullable<CardActions> : Record<string, never>;
533
- type NonNeverRegistryValue<Registry, Key extends string> = Registry extends Record<string, unknown> ? Key extends keyof Registry ? [Registry[Key]] extends [never] ? never : Registry[Key] : never : never;
534
- type InteractionIdOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>> = InteractionRegistryOfDefinitionPhase<Definition, PhaseName> extends infer Interactions ? SimultaneousSubmitRegistryOfDefinitionPhase<Definition, PhaseName> extends infer Submit ? CardActionRegistryOfDefinitionPhase<Definition, PhaseName> extends infer CardActions ? Interactions extends Record<string, unknown> ? CardActions extends Record<string, unknown> ? Submit extends Record<string, unknown> ? (NonNeverKeys<Interactions> & string) | (NonNeverKeys<CardActions> & string) | (NonNeverKeys<Submit> & string) : (NonNeverKeys<Interactions> & string) | (NonNeverKeys<CardActions> & string) : Submit extends Record<string, unknown> ? (NonNeverKeys<Interactions> & string) | (NonNeverKeys<Submit> & string) : NonNeverKeys<Interactions> & string : CardActions extends Record<string, unknown> ? Submit extends Record<string, unknown> ? (NonNeverKeys<CardActions> & string) | (NonNeverKeys<Submit> & string) : NonNeverKeys<CardActions> & string : Submit extends Record<string, unknown> ? NonNeverKeys<Submit> & string : never : never : never : never;
535
- type InteractionSpecByNameOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>, InteractionId extends InteractionIdOfDefinitionPhase<Definition, PhaseName>> = InteractionRegistryOfDefinitionPhase<Definition, PhaseName> extends infer Interactions ? Interactions extends Record<string, unknown> ? NonNeverRegistryValue<Interactions, InteractionId> extends infer InteractionSpec ? [InteractionSpec] extends [never] ? CardActionRegistryOfDefinitionPhase<Definition, PhaseName> extends infer CardActions ? NonNeverRegistryValue<CardActions, InteractionId> extends infer CardActionSpec ? [CardActionSpec] extends [never] ? SimultaneousSubmitRegistryOfDefinitionPhase<Definition, PhaseName> extends infer Submit ? NonNeverRegistryValue<Submit, InteractionId> : never : CardActionSpec : never : never : InteractionSpec : never : never : never;
536
- type CollectorKindsOf<Collectors> = Collectors extends Record<string, InputCollector> ? Collectors[keyof Collectors] extends infer Collector ? Collector extends {
537
- kind: infer Kind extends string;
538
- } ? Kind : never : never : never;
539
- type CollectorKeysWithKind<Collectors, Kind extends string> = Collectors extends Record<string, InputCollector> ? {
540
- [K in keyof Collectors]: Collectors[K] extends {
541
- kind: infer CollectorKind;
542
- } ? Extract<CollectorKind, Kind> extends never ? never : K : never;
543
- }[keyof Collectors] : never;
544
- type CardCollectorZoneIds<Collector> = Collector extends {
545
- kind: "card";
546
- meta: infer Meta;
547
- } ? Meta extends {
548
- readonly zoneIds: infer ZoneIds extends readonly string[];
549
- } ? ZoneIds[number] : Meta extends {
550
- readonly zoneId: infer ZoneId extends string;
551
- } ? ZoneId : never : never;
552
- type CollectorCardZoneIds<Collectors, Input extends string> = Collectors extends Record<string, InputCollector> ? Input extends keyof Collectors ? CardCollectorZoneIds<Collectors[Input]> : never : never;
553
- type CollectorsOfInteractionDefinition<Spec> = Spec extends {
554
- readonly inputs?: infer Collectors;
555
- } ? NonNullable<Collectors> extends Record<string, InputCollector> ? NonNullable<Collectors> : Record<string, never> : Record<string, never>;
556
- type CollectorKindsOfInteractionDefinition<Spec> = (Spec extends {
557
- readonly cardType: unknown;
558
- readonly playFrom: unknown;
559
- } ? "card" : never) | CollectorKindsOf<CollectorsOfInteractionDefinition<Spec>>;
560
- type InputKeysWithCollectorKindOfInteractionDefinition<Spec, Kind extends string> = (Spec extends {
561
- readonly cardType: unknown;
562
- readonly playFrom: unknown;
563
- } ? Extract<"card", Kind> extends never ? never : "cardId" : never) | (CollectorKeysWithKind<CollectorsOfInteractionDefinition<Spec>, Kind> & string);
564
- type CardInputZoneIdsOfInteractionDefinition<Spec, Input extends string> = Input extends "cardId" ? Spec extends {
565
- readonly playFrom: infer PlayFrom extends string;
566
- } ? PlayFrom : CollectorCardZoneIds<CollectorsOfInteractionDefinition<Spec>, Input> : CollectorCardZoneIds<CollectorsOfInteractionDefinition<Spec>, Input>;
567
- type ParamsOfCollectors<Collectors> = Collectors extends Record<string, InputCollector> ? {
568
- [K in keyof Collectors]: Collectors[K] extends InputCollector<infer S> ? S extends SchemaLike<infer V> ? V : never : never;
569
- } : never;
570
- type ClientParamsOfCollectors<Collectors> = Collectors extends Record<string, InputCollector> ? {
571
- [K in keyof Collectors as Collectors[K] extends {
572
- readonly kind: "rng";
573
- } ? never : K]: Collectors[K] extends InputCollector<infer S> ? S extends SchemaLike<infer V> ? V : never : never;
574
- } : never;
575
- type InteractionIdsWithCollectorKindOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>, Kind extends string> = {
576
- [InteractionId in InteractionIdOfDefinitionPhase<Definition, PhaseName>]: InteractionSpecByNameOfDefinitionPhase<Definition, PhaseName, InteractionId> extends infer Spec ? Extract<CollectorKindsOfInteractionDefinition<Spec>, Kind> extends never ? never : InteractionId : never;
577
- }[InteractionIdOfDefinitionPhase<Definition, PhaseName>];
578
- type QualifiedInteractionIdsWithCollectorKindOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>, Kind extends string> = InteractionIdsWithCollectorKindOfDefinitionPhase<Definition, PhaseName, Kind> extends infer InteractionId extends string ? `${PhaseName}.${InteractionId}` : never;
579
- type PromptInteractionKeyOfDefinition<Definition> = {
580
- [PhaseName in PhaseNamesOfDefinition<Definition>]: QualifiedInteractionIdsWithCollectorKindOfDefinitionPhase<Definition, PhaseName, "prompt">;
581
- }[PhaseNamesOfDefinition<Definition>];
582
- type BoardInteractionKeyOfDefinition<Definition> = {
583
- [PhaseName in PhaseNamesOfDefinition<Definition>]: QualifiedInteractionIdsWithCollectorKindOfDefinitionPhase<Definition, PhaseName, "board-edge" | "board-space" | "board-tile" | "board-vertex">;
584
- }[PhaseNamesOfDefinition<Definition>];
585
- type CardInteractionKeyOfDefinition<Definition> = {
586
- [PhaseName in PhaseNamesOfDefinition<Definition>]: QualifiedInteractionIdsWithCollectorKindOfDefinitionPhase<Definition, PhaseName, "card">;
587
- }[PhaseNamesOfDefinition<Definition>];
588
- type InputKeysWithCollectorKindOfDefinition<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>, InteractionId extends InteractionIdOfDefinitionPhase<Definition, PhaseName>, Kind extends string> = InteractionSpecByNameOfDefinitionPhase<Definition, PhaseName, InteractionId> extends infer Spec ? InputKeysWithCollectorKindOfInteractionDefinition<Spec, Kind> : never;
589
- type CardInputZoneIdsOfDefinition<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>, InteractionId extends InteractionIdOfDefinitionPhase<Definition, PhaseName>, Input extends string> = InteractionSpecByNameOfDefinitionPhase<Definition, PhaseName, InteractionId> extends infer Spec ? CardInputZoneIdsOfInteractionDefinition<Spec, Input> : never;
590
- type ParamsOfInteractionOfDefinition<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>, InteractionId extends InteractionIdOfDefinitionPhase<Definition, PhaseName>> = InteractionSpecByNameOfDefinitionPhase<Definition, PhaseName, InteractionId> extends infer Spec ? Spec extends {
591
- readonly cardType: unknown;
592
- readonly playFrom: unknown;
593
- } ? {
594
- cardId: string;
595
- } & ParamsOfCollectors<CollectorsOfInteractionDefinition<Spec>> : ParamsOfCollectors<CollectorsOfInteractionDefinition<Spec>> : never;
596
- /**
597
- * Client-facing params shape for an interaction. Omits engine-sampled
598
- * collectors (`rngInput.*`) — clients never supply those fields; the
599
- * trusted reducer bundle fills them during `submitInteraction`.
600
- *
601
- * This is the type that drives `submit(playerId, id, params)`,
602
- * `handle.submit(params)`, and the generated `InteractionParams` surface
603
- * through `createGameUi(game)`. The `reduce`-input counterpart is
604
- * {@link ParamsOfInteractionOfDefinition}, which includes every field
605
- * because the engine has already filled the sampled ones by then.
606
- */
607
- type ClientParamsOfInteractionOfDefinition<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>, InteractionId extends InteractionIdOfDefinitionPhase<Definition, PhaseName>> = InteractionSpecByNameOfDefinitionPhase<Definition, PhaseName, InteractionId> extends infer Spec ? Spec extends {
608
- readonly cardType: unknown;
609
- readonly playFrom: unknown;
610
- } ? {
611
- cardId: string;
612
- } & ClientParamsOfCollectors<CollectorsOfInteractionDefinition<Spec>> : ClientParamsOfCollectors<CollectorsOfInteractionDefinition<Spec>> : never;
613
- type DefaultedClientCollectorKeys<Collectors extends Record<string, InputCollector>> = {
614
- [K in keyof Collectors]: Collectors[K] extends {
615
- readonly kind: "rng";
616
- } ? never : Collectors[K] extends {
617
- readonly defaultValue: unknown;
618
- } ? K : never;
619
- }[keyof Collectors];
620
- type DefaultedClientParamKeysOfInteractionOfDefinition<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>, InteractionId extends InteractionIdOfDefinitionPhase<Definition, PhaseName>> = InteractionSpecByNameOfDefinitionPhase<Definition, PhaseName, InteractionId> extends infer Spec ? DefaultedClientCollectorKeys<CollectorsOfInteractionDefinition<Spec>> & string : never;
621
- type StageRegistryOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>> = PhaseDefinitionByName<Definition, PhaseName> extends {
622
- stages?: infer Stages;
623
- } ? NonNullable<Stages> : Record<string, never>;
624
- type StageNamesOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>> = StageRegistryOfDefinitionPhase<Definition, PhaseName> extends infer Stages ? Stages extends Record<string, unknown> ? NonNeverKeys<Stages> & string : never : never;
625
- type ZoneRegistriesOfDefinition<Definition> = PhasesOfDefinition<Definition>[keyof PhasesOfDefinition<Definition> & string] extends {
626
- zones?: infer Zones;
627
- } ? NonNullable<Zones> : never;
628
- type ZoneIdsOfDefinition<Definition> = ZoneRegistriesOfDefinition<Definition> extends infer Zones ? Zones extends readonly (infer ZoneId)[] ? Extract<ZoneId, string> : never : never;
629
- type ZoneListOfDefinitionPhase<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>> = PhaseDefinitionByName<Definition, PhaseName> extends {
630
- zones?: infer Zones;
631
- } ? NonNullable<Zones> : readonly [];
632
- type PlayableInteractionsOfZoneOfDefinition<Definition, PhaseName extends PhaseNamesOfDefinition<Definition>, ZoneId extends string> = ZoneListOfDefinitionPhase<Definition, PhaseName> extends readonly (infer From)[] ? Extract<From, ZoneId> extends never ? never : CardActionRegistryOfDefinitionPhase<Definition, PhaseName> extends infer CardActions ? CardActions extends Record<string, unknown> ? {
633
- [ActionId in keyof CardActions & string]: CardActions[ActionId] extends {
634
- playFrom: infer PlayFrom extends string;
635
- } ? Extract<PlayFrom, ZoneId> extends never ? never : ActionId : never;
636
- }[keyof CardActions & string] : never : never : never;
637
-
638
- /**
639
- * A freestanding, memoized projection of immutable game state.
640
- *
641
- * Use `defineDerived` for values that are pure functions of component
642
- * locations, zone contents, resources, or other state fields - and are
643
- * consumed from multiple reducer or view call sites, or whose compute cost
644
- * is non-trivial (graph walks, aggregate reductions).
645
- *
646
- * Do NOT cache derived values in `publicState`. State fields should be
647
- * inputs to derivations, not mirrors of them.
648
- */
649
- type DerivedDefinition<Contract, Value> = {
650
- /** Optional label for debugging. Does not affect caching. */
651
- readonly name?: string;
652
- readonly compute: (ctx: {
653
- readonly state: BaseGameStateOfContract<Contract>;
654
- readonly q: TableQueriesOfState<BaseGameStateOfContract<Contract>>;
655
- readonly derived: DerivedResolver;
656
- }) => Value;
657
- };
658
- /**
659
- * Resolves a `DerivedDefinition` to its value. Callers do not need to know
660
- * about memoization - the resolver handles caching internally.
661
- */
662
- type DerivedResolver = <Value>(def: DerivedDefinition<never, Value>) => Value;
663
- /**
664
- * Author-facing factory for creating a derived value tied to a game
665
- * contract. Usage:
666
- *
667
- * ```ts
668
- * export const longestRoad = defineDerived<GameContract>()({
669
- * name: "longestRoad",
670
- * compute: ({ q, derived }) => computeLongestRoad(q),
671
- * });
672
- * ```
673
- */
674
- declare function defineDerived<Contract>(): <Value>(def: {
675
- name?: string;
676
- compute: (ctx: {
677
- state: BaseGameStateOfContract<Contract>;
678
- q: TableQueriesOfState<BaseGameStateOfContract<Contract>>;
679
- derived: DerivedResolver;
680
- }) => Value;
681
- }) => DerivedDefinition<Contract, Value>;
682
- /**
683
- * Creates a resolver scoped to a single state snapshot. Each engine tick
684
- * and each view projection call creates its own resolver; cache lifetime
685
- * ends with the call. Cache key is the `DerivedDefinition` identity (the
686
- * object reference).
687
- *
688
- * Re-entry on an in-flight definition throws a readable error.
689
- */
690
- declare function createDerivedResolver<State extends {
691
- table: RuntimeTableRecord;
692
- }>(state: State, options?: {
693
- q?: TableQueriesOfState<State>;
694
- }): DerivedResolver;
695
-
696
- type StaticBoardsOfManifest<Manifest> = Manifest extends {
697
- staticBoards?: infer StaticBoards;
698
- } ? NonNullable<StaticBoards> : {
699
- byId: Record<string, never>;
700
- hex: Record<string, never>;
701
- square: Record<string, never>;
702
- };
703
- type StaticBoardMapOfManifest<Manifest> = StaticBoardsOfManifest<Manifest> extends {
704
- byId: infer Boards;
705
- } ? Boards : Record<string, never>;
706
- type StaticHexBoardMapOfManifest<Manifest> = StaticBoardsOfManifest<Manifest> extends {
707
- hex: infer Boards;
708
- } ? Boards : Record<string, never>;
709
- type StaticSquareBoardMapOfManifest<Manifest> = StaticBoardsOfManifest<Manifest> extends {
710
- square: infer Boards;
711
- } ? Boards : Record<string, never>;
712
- type StaticViewQueries<Manifest extends ManifestContract<RuntimeTableRecord>> = {
713
- board: {
714
- get: <BoardId extends StringKeyOf<StaticBoardMapOfManifest<Manifest>>>(boardId: BoardId) => StaticBoardMapOfManifest<Manifest>[BoardId];
715
- hex: <BoardId extends StringKeyOf<StaticHexBoardMapOfManifest<Manifest>>>(boardId: BoardId) => StaticHexBoardMapOfManifest<Manifest>[BoardId];
716
- square: <BoardId extends StringKeyOf<StaticSquareBoardMapOfManifest<Manifest>>>(boardId: BoardId) => StaticSquareBoardMapOfManifest<Manifest>[BoardId];
717
- };
718
- };
719
- type ContinuationSourceKind = "effect";
720
- type ResumableEffectKind = "rollDie" | "shuffleSharedZone" | "shufflePlayerZone";
721
- type ContinuationKind = ResumableEffectKind;
722
- type RollDieContinuationResponse = {
723
- dieId: string;
724
- value: number;
725
- };
726
- type ShuffleSharedZoneContinuationResponse = {
727
- zoneId: string;
728
- orderedCardIds: readonly string[];
729
- };
730
- type ShufflePlayerZoneContinuationResponse = {
731
- zoneId: string;
732
- playerId: string;
733
- orderedCardIds: readonly string[];
734
- };
735
- type EffectContinuationResponse<Kind extends ResumableEffectKind> = Kind extends "rollDie" ? RollDieContinuationResponse : Kind extends "shuffleSharedZone" ? ShuffleSharedZoneContinuationResponse : Kind extends "shufflePlayerZone" ? ShufflePlayerZoneContinuationResponse : never;
736
- type EffectContinuationInput<DataSchema extends AnySchema, Kind extends ResumableEffectKind = ResumableEffectKind> = {
737
- source: "effect";
738
- effectKind: Kind;
739
- data: z.infer<DataSchema>;
740
- response: EffectContinuationResponse<Kind>;
741
- };
742
- type ContinuationInput<DataSchema extends AnySchema> = EffectContinuationInput<DataSchema, ResumableEffectKind>;
743
- type ContinuationInputForSource<DataSchema extends AnySchema, EffectType extends ResumableEffectKind = ResumableEffectKind> = EffectContinuationInput<DataSchema, EffectType>;
744
- type PhaseEnterContext = {
745
- event: "initialize" | "transition";
746
- };
747
- type BivariantCallback<Args, Result> = {
748
- bivarianceHack(args: Args): Result;
749
- }["bivarianceHack"];
750
- type ActionContext<State extends {
751
- table: RuntimeTableRecord;
752
- flow: {
753
- currentPhase: string;
754
- };
755
- }, Manifest extends ManifestContract<TableOfState<State>>> = {
756
- currentPhase: PhaseNameOfState<State>;
757
- manifest: Manifest;
758
- playerOrder: PlayerIdOfState<State>[];
759
- activePlayers: PlayerIdOfState<State>[];
760
- runtime: Omit<ReducerRuntimeStateForState<State>, "rng">;
761
- setup: SetupSelectionOfManifest<Manifest> | null;
762
- };
763
- type ValidationIssue<ErrorCode extends string = string> = {
764
- errorCode: ErrorCode;
765
- message?: string;
766
- };
767
- /**
768
- * Read-only helpers available to every callback, including views, actor
769
- * selectors, and interaction rules.
770
- */
771
- type ReadHelpers<State extends {
772
- table: RuntimeTableRecord;
773
- flow: {
774
- currentPhase: string;
775
- };
776
- }> = {
777
- q: TableQueriesOfState<State>;
778
- derived: DerivedResolver;
779
- };
780
- type RandomHelpers = {
781
- integer(options: {
782
- minInclusive: number;
783
- maxInclusive: number;
784
- }): number;
785
- subset<const Values extends readonly unknown[]>(options: {
786
- from: Values;
787
- count: number;
788
- }): readonly Values[number][];
789
- };
790
- /**
791
- * Helpers available only to mutation callbacks (`enter`, `reduce`, `resolve`,
792
- * continuations). `tx` is the open transaction: mutate through it and end the
793
- * callback with a bare `return`, `tx.transition(...)`, `tx.endGame(...)`, or
794
- * `tx.reject(...)`.
795
- */
796
- type MutationHelpers<State extends {
797
- table: RuntimeTableRecord;
798
- flow: {
799
- currentPhase: string;
800
- };
801
- }, ErrorCode extends string = string> = {
802
- tx: ReducerTransaction<State, ErrorCode>;
803
- random: RandomHelpers;
804
- };
805
- type PhaseEnterArgs<State extends {
806
- table: RuntimeTableRecord;
807
- flow: {
808
- currentPhase: string;
809
- };
810
- }, Manifest extends ManifestContract<TableOfState<State>>, ErrorCode extends string = string> = ActionContext<State, Manifest> & ReadHelpers<State> & MutationHelpers<State, ErrorCode> & PhaseEnterContext & {
811
- state: State;
812
- };
813
- type ActorSelectorArgs<State extends {
814
- table: RuntimeTableRecord;
815
- flow: {
816
- currentPhase: string;
817
- };
818
- }, Manifest extends ManifestContract<TableOfState<State>>> = ActionContext<State, Manifest> & ReadHelpers<State> & {
819
- state: State;
820
- };
821
- type ActorSelection<State extends {
822
- table: RuntimeTableRecord;
823
- flow: {
824
- currentPhase: string;
825
- };
826
- }> = PlayerIdOfState<State> | readonly PlayerIdOfState<State>[] | null | undefined;
827
- type ActorSelector<State extends {
828
- table: RuntimeTableRecord;
829
- flow: {
830
- currentPhase: string;
831
- };
832
- }, Manifest extends ManifestContract<TableOfState<State>>> = BivariantCallback<ActorSelectorArgs<State, Manifest>, ActorSelection<State>>;
833
- type ContinuationReduceArgs<DataSchema extends AnySchema, State extends {
834
- table: RuntimeTableRecord;
835
- flow: {
836
- currentPhase: string;
837
- };
838
- }, Manifest extends ManifestContract<TableOfState<State>>, EffectType extends ResumableEffectKind = ResumableEffectKind> = ActionContext<State, Manifest> & ReadHelpers<State> & MutationHelpers<State> & {
839
- state: State;
840
- input: ContinuationInputForSource<DataSchema, EffectType>;
841
- };
842
- type ScopedPhaseState<State extends {
843
- table: RuntimeTableRecord;
844
- flow: {
845
- currentPhase: string;
846
- };
847
- phase: object;
848
- }, PhaseState extends object> = State & {
849
- phase: PhaseState;
850
- };
851
- type ContinuationCallable<DataSchema extends AnySchema, State extends {
852
- table: RuntimeTableRecord;
853
- flow: {
854
- currentPhase: string;
855
- };
856
- }, Manifest extends ManifestContract<TableOfState<State>>, ContinuationId extends string = string, EffectType extends ResumableEffectKind = ResumableEffectKind> = ((data: z.infer<DataSchema>) => ContinuationToken<z.infer<DataSchema>, ContinuationId, EffectContinuationResponse<EffectType>>) & {
857
- id: ContinuationId;
858
- source: "effect";
859
- dataSchema: DataSchema;
860
- responseSchema: AnySchema;
861
- effectKind?: EffectType;
862
- reduce: BivariantCallback<ContinuationReduceArgs<DataSchema, State, Manifest, EffectType>, ReducerResult<State>>;
863
- };
864
- type AnyContinuationCallable<State extends {
865
- table: RuntimeTableRecord;
866
- flow: {
867
- currentPhase: string;
868
- };
869
- }> = {
870
- (data: never): AnyContinuationToken;
871
- id: string;
872
- source: "effect";
873
- dataSchema: AnySchema;
874
- responseSchema: AnySchema;
875
- effectKind?: ResumableEffectKind;
876
- reduce: (args: unknown) => ReducerResult<State>;
877
- };
878
- type EffectContinuationCallable<DataSchema extends AnySchema, State extends {
879
- table: RuntimeTableRecord;
880
- flow: {
881
- currentPhase: string;
882
- };
883
- }, Manifest extends ManifestContract<TableOfState<State>>, ContinuationId extends string = string, Kind extends ResumableEffectKind = ResumableEffectKind> = ContinuationCallable<DataSchema, State, Manifest, ContinuationId, Kind>;
884
-
885
- /**
886
- * `rollDie` effect. Resolves a `rollDie` wire effect. `reduce` / `context`
887
- * are both optional so authors can fire-and-forget a die roll without
888
- * observing the result.
889
- */
890
- type EffectRollDieDefinition<Id extends string, ContextSchema extends AnySchema, State extends {
891
- table: RuntimeTableRecord;
892
- flow: {
893
- currentPhase: string;
894
- };
895
- }, Manifest extends ManifestContract<TableOfState<State>>> = {
896
- readonly type: "rollDie";
897
- readonly id: Id;
898
- readonly contextSchema?: ContextSchema;
899
- readonly __continuation?: EffectContinuationCallable<ContextSchema, State, Manifest, Id, "rollDie">;
900
- };
901
- /**
902
- * `shuffleSharedZone` effect. Resolves a `shuffleSharedZone` wire effect.
903
- * `reduce` / `context` are both optional.
904
- */
905
- type EffectShuffleDefinition<Id extends string, ContextSchema extends AnySchema, State extends {
906
- table: RuntimeTableRecord;
907
- flow: {
908
- currentPhase: string;
909
- };
910
- }, Manifest extends ManifestContract<TableOfState<State>>> = {
911
- readonly type: "shuffleSharedZone";
912
- readonly id: Id;
913
- readonly contextSchema?: ContextSchema;
914
- readonly __continuation?: EffectContinuationCallable<ContextSchema, State, Manifest, Id, "shuffleSharedZone">;
915
- };
916
- /**
917
- * `shufflePlayerZone` effect. Resolves a `shufflePlayerZone` wire effect for
918
- * a single player's perPlayer zone (e.g. deck-builder reshuffle of discard
919
- * into deck). `reduce` / `context` are both optional.
920
- */
921
- type EffectShufflePlayerZoneDefinition<Id extends string, ContextSchema extends AnySchema, State extends {
922
- table: RuntimeTableRecord;
923
- flow: {
924
- currentPhase: string;
925
- };
926
- }, Manifest extends ManifestContract<TableOfState<State>>> = {
927
- readonly type: "shufflePlayerZone";
928
- readonly id: Id;
929
- readonly contextSchema?: ContextSchema;
930
- readonly __continuation?: EffectContinuationCallable<ContextSchema, State, Manifest, Id, "shufflePlayerZone">;
931
- };
932
- /**
933
- * Discriminated union of every `defineEffect` output.
934
- */
935
- type EffectDefinition<State extends {
936
- table: RuntimeTableRecord;
937
- flow: {
938
- currentPhase: string;
939
- };
940
- }, Manifest extends ManifestContract<TableOfState<State>>> = EffectRollDieDefinition<string, AnySchema, State, Manifest> | EffectShuffleDefinition<string, AnySchema, State, Manifest> | EffectShufflePlayerZoneDefinition<string, AnySchema, State, Manifest>;
941
- type EffectMap<State extends {
942
- table: RuntimeTableRecord;
943
- flow: {
944
- currentPhase: string;
945
- };
946
- }, Manifest extends ManifestContract<TableOfState<State>>> = Record<string, EffectDefinition<State, Manifest>>;
947
- type EffectRegistryOfPhase<Phase> = Phase extends {
948
- effects?: infer Effects extends Record<string, unknown>;
949
- } ? Effects : Record<string, never>;
950
-
951
- type InputCollectorKind = "form" | "board-vertex" | "board-edge" | "board-tile" | "board-space" | "card" | "prompt" | "rng";
952
- type TargetKind = "edge" | "vertex" | "space" | "tile" | "card";
953
- type BoardInputCollectorKind = Exclude<InputCollectorKind, "form" | "card" | "prompt" | "rng">;
954
- type CardInputCollectorMeta = {
955
- readonly zoneId: string;
956
- readonly zoneIds?: readonly string[];
957
- readonly targetKind: "card";
958
- };
959
- type BoardInputCollectorMeta = {
960
- readonly targetKind: TargetKind;
961
- readonly boardId: string;
962
- readonly valueKind?: "board-id" | "player-board-space";
963
- };
964
- type PromptInputCollectorMeta = {
965
- readonly options: (state: unknown, playerId: unknown, q: unknown) => ReadonlyArray<{
966
- id: unknown;
967
- label?: string;
968
- }>;
969
- readonly eligibleOptions: (state: unknown, playerId: unknown, q: unknown) => ReadonlyArray<{
970
- id: unknown;
971
- label?: string;
972
- }>;
973
- };
974
- type RngInputCollectorMeta = {
975
- readonly rng: "d6";
976
- readonly count: number;
977
- } | {
978
- readonly rng: "coin";
979
- };
980
- type InputCollectorMetaForKind<Kind extends InputCollectorKind> = Kind extends "card" ? CardInputCollectorMeta : Kind extends BoardInputCollectorKind ? BoardInputCollectorMeta : Kind extends "prompt" ? PromptInputCollectorMeta | undefined : Kind extends "rng" ? RngInputCollectorMeta : never;
981
- type InputSelectionDescriptor = {
982
- readonly mode: "single";
983
- } | {
984
- readonly mode: "many";
985
- readonly min: number;
986
- readonly max?: number;
987
- readonly distinct?: boolean;
988
- };
989
- type InputDomainResolverDescriptor = {
990
- readonly interactionKey?: string;
991
- readonly inputKey: string;
992
- };
993
- type InputDomainDependencyCase<Domain extends InputDomainDescriptor = InputDomainDescriptor> = {
994
- when: Record<string, string>;
995
- domain: Domain;
996
- };
997
- type EagerInputDomainDependencies<Domain extends InputDomainDescriptor = InputDomainDescriptor> = {
998
- readonly mode: "eager";
999
- readonly dependentCases: readonly InputDomainDependencyCase<Domain>[];
1000
- };
1001
- type LazyInputDomainDependencies = {
1002
- readonly mode: "lazy";
1003
- readonly dependsOn: readonly string[];
1004
- readonly resolver: InputDomainResolverDescriptor;
1005
- };
1006
- type CardTargetDomainDescriptor = ResolvedCardTargetDomainDescriptor | LazyCardTargetDomainDescriptor;
1007
- type ResolvedCardTargetDomainDescriptor = {
1008
- readonly type: "cardTarget";
1009
- readonly projection: "resolved";
1010
- readonly targetKind: "card";
1011
- readonly zoneIds: readonly string[];
1012
- readonly eligibleTargets: readonly string[];
1013
- readonly selection?: InputSelectionDescriptor;
1014
- readonly dependencies?: EagerInputDomainDependencies<ResolvedCardTargetDomainDescriptor>;
1015
- };
1016
- type LazyCardTargetDomainDescriptor = {
1017
- readonly type: "cardTarget";
1018
- readonly projection: "lazy";
1019
- readonly targetKind: "card";
1020
- readonly zoneIds: readonly string[];
1021
- readonly eligibleTargets?: never;
1022
- readonly selection?: InputSelectionDescriptor;
1023
- readonly dependencies: LazyInputDomainDependencies;
1024
- };
1025
- type BoardTargetDomainDescriptor = ResolvedBoardTargetDomainDescriptor | LazyBoardTargetDomainDescriptor;
1026
- type ResolvedBoardTargetDomainDescriptor = {
1027
- readonly type: "boardTarget";
1028
- readonly projection: "resolved";
1029
- readonly targetKind: Exclude<TargetKind, "card">;
1030
- readonly boardId: string;
1031
- readonly valueKind?: "board-id" | "player-board-space";
1032
- readonly eligibleTargets: readonly string[];
1033
- readonly selection?: InputSelectionDescriptor;
1034
- readonly dependencies?: EagerInputDomainDependencies<ResolvedBoardTargetDomainDescriptor>;
1035
- };
1036
- type LazyBoardTargetDomainDescriptor = {
1037
- readonly type: "boardTarget";
1038
- readonly projection: "lazy";
1039
- readonly targetKind: Exclude<TargetKind, "card">;
1040
- readonly boardId: string;
1041
- readonly valueKind?: "board-id" | "player-board-space";
1042
- readonly eligibleTargets?: never;
1043
- readonly selection?: InputSelectionDescriptor;
1044
- readonly dependencies: LazyInputDomainDependencies;
1045
- };
1046
- type ResourceMapDomainDescriptor = {
1047
- type: "resourceMap";
1048
- resources: Array<{
1049
- resourceId: string;
1050
- label?: string;
1051
- icon?: string;
1052
- min: number;
1053
- max: number;
1054
- }>;
1055
- selection?: InputSelectionDescriptor;
1056
- };
1057
- type BoundedNumberDomainDescriptor = {
1058
- type: "boundedNumber";
1059
- min: number;
1060
- max: number;
1061
- step?: number;
1062
- selection?: InputSelectionDescriptor;
1063
- };
1064
- type ChoiceDomainDescriptor = {
1065
- type: "choice";
1066
- choices: Array<{
1067
- value: string | null;
1068
- label: string;
1069
- icon?: string;
1070
- badge?: string;
1071
- description?: string;
1072
- disabled?: boolean;
1073
- disabledReason?: string;
1074
- }>;
1075
- selection?: InputSelectionDescriptor;
1076
- dependencies?: EagerInputDomainDependencies<ChoiceDomainDescriptor>;
1077
- };
1078
- type ChoiceListDomainDescriptor = {
1079
- type: "choiceList";
1080
- choices: Array<{
1081
- value: string;
1082
- label: string;
1083
- icon?: string;
1084
- badge?: string;
1085
- description?: string;
1086
- disabled?: boolean;
1087
- disabledReason?: string;
1088
- }>;
1089
- min?: number;
1090
- max?: number;
1091
- selection?: InputSelectionDescriptor;
1092
- dependencies?: EagerInputDomainDependencies<ChoiceListDomainDescriptor>;
1093
- };
1094
- type InputDomainDescriptor = CardTargetDomainDescriptor | BoardTargetDomainDescriptor | ResourceMapDomainDescriptor | BoundedNumberDomainDescriptor | ChoiceDomainDescriptor | ChoiceListDomainDescriptor;
1095
- type DomainProjector<Domain extends InputDomainDescriptor> = (state: CollectorState, playerId: string, q: unknown, derived: DerivedResolver, values?: Readonly<Record<string, unknown>>) => Domain;
1096
- type InputDomainForCollectorKind<Kind extends InputCollectorKind> = Kind extends "card" ? CardTargetDomainDescriptor : Kind extends BoardInputCollectorKind ? BoardTargetDomainDescriptor : Exclude<InputDomainDescriptor, CardTargetDomainDescriptor | BoardTargetDomainDescriptor>;
1097
- /**
1098
- * Base state shape every collector is generic over. Collectors that need
1099
- * narrowed ids (card / player) use `PlayerIdOfState<State>` etc. to thread
1100
- * the manifest's branded types.
1101
- */
1102
- type CollectorState = {
1103
- table: RuntimeTableRecord;
1104
- flow: {
1105
- currentPhase: string;
1106
- };
1107
- };
1108
- /**
1109
- * An input collector declares:
1110
- * - a Zod schema for the parameter value the interaction expects. The
1111
- * schema's `z.infer` feeds `ParamsOf<Collectors>`, so downstream
1112
- * `reduce({ input: { params } })` sees branded ids from `cardInput` /
1113
- * `boardInput` without a second declaration.
1114
- * - an optional `eligibleTargets(state, playerId, q)` hook that the runtime
1115
- * calls to enumerate server-authoritative, submit-ready values accepted by
1116
- * the collector schema. The hook receives
1117
- * the same `q` table-queries helper that `validate` / `reduce` see, so
1118
- * board/card/prompt collectors can reuse whatever board-graph or zone
1119
- * lookups they already use for validation without rebuilding them from
1120
- * raw state. Each collector helper narrows the return type to its own
1121
- * branded id (`CardIdOfState<State>` for `cardInput`, the caller-supplied
1122
- * `Id extends string` for `boardInput.*`, etc.). At the generic interface
1123
- * level we keep inputs weak (`CollectorState`, `string`, `unknown`) and
1124
- * the return `ReadonlyArray<unknown>` so the runtime can treat all
1125
- * collectors uniformly; per-helper signatures provide the author-facing
1126
- * strong typing.
1127
- * - optional `meta` for collector-kind-specific routing (e.g. `cardInput`
1128
- * stores the `zoneId` the card must come from).
1129
- *
1130
- * Collectors without meaningful eligibility (`form`, `rng`) leave
1131
- * `eligibleTargets` undefined.
1132
- */
1133
- type InputCollectorMetaSlot<Kind extends InputCollectorKind> = [
1134
- InputCollectorMetaForKind<Kind>
1135
- ] extends [never] ? {
1136
- readonly meta?: never;
1137
- } : undefined extends InputCollectorMetaForKind<Kind> ? {
1138
- readonly meta?: Exclude<InputCollectorMetaForKind<Kind>, undefined>;
1139
- } : {
1140
- readonly meta: InputCollectorMetaForKind<Kind>;
1141
- };
1142
- type InputCollectorBase<Schema extends SchemaLike<unknown> = SchemaLike<unknown>, State extends CollectorState = CollectorState, Kind extends InputCollectorKind = InputCollectorKind> = {
1143
- readonly kind: Kind;
1144
- readonly schema: Schema;
1145
- readonly defaultValue?: z.infer<Schema>;
1146
- readonly selection?: InputSelectionDescriptor;
1147
- readonly eligibleTargets?: (state: CollectorState, playerId: string, q: unknown, values?: Readonly<Record<string, unknown>>) => ReadonlyArray<unknown>;
1148
- readonly validateTarget?: (state: CollectorState, playerId: string, q: unknown, targetId: unknown, values?: Readonly<Record<string, unknown>>) => ValidationIssue | null | undefined;
1149
- readonly dependsOn?: readonly string[];
1150
- readonly resolveDefaultValue?: (state: CollectorState, playerId: string, q: unknown, derived: DerivedResolver, domain: InputDomainDescriptor) => z.infer<Schema> | undefined;
1151
- } & (Kind extends "rng" ? {
1152
- readonly domain?: never;
1153
- } : Kind extends "card" | BoardInputCollectorKind ? {
1154
- readonly domain: DomainProjector<InputDomainForCollectorKind<Kind>>;
1155
- } : {
1156
- readonly domain?: DomainProjector<InputDomainForCollectorKind<Kind>>;
1157
- }) & InputCollectorMetaSlot<Kind>;
1158
- type InputCollector<Schema extends SchemaLike<unknown> = SchemaLike<unknown>, State extends CollectorState = CollectorState, Kind extends InputCollectorKind = InputCollectorKind> = Kind extends InputCollectorKind ? InputCollectorBase<Schema, State, Kind> : never;
1159
- type ParamsOf<Collectors extends Record<string, InputCollector>> = {
1160
- [K in keyof Collectors]: Collectors[K] extends InputCollector<infer S> ? S extends SchemaLike<infer V> ? V : never : never;
1161
- };
1162
- type EngineSampledCollectorKeys<Collectors extends Record<string, InputCollector>> = {
1163
- [K in keyof Collectors]: Collectors[K] extends InputCollector & {
1164
- kind: "rng";
1165
- } ? K : never;
1166
- }[keyof Collectors];
1167
- type ClientCollectorValue<Collector> = Collector extends InputCollector<infer S> ? S extends SchemaLike<infer V> ? V : never : never;
1168
- type ClientCollectorKeys<Collectors extends Record<string, InputCollector>> = Exclude<keyof Collectors, EngineSampledCollectorKeys<Collectors>>;
1169
- type OptionalClientCollectorKeys<Collectors extends Record<string, InputCollector>> = {
1170
- [K in ClientCollectorKeys<Collectors>]: undefined extends ClientCollectorValue<Collectors[K]> ? K : never;
1171
- }[ClientCollectorKeys<Collectors>];
1172
- type ClientParamsOf<Collectors extends Record<string, InputCollector>> = {
1173
- [K in Exclude<ClientCollectorKeys<Collectors>, OptionalClientCollectorKeys<Collectors>>]: ClientCollectorValue<Collectors[K]>;
1174
- } & {
1175
- [K in OptionalClientCollectorKeys<Collectors>]?: Exclude<ClientCollectorValue<Collectors[K]>, undefined>;
1176
- };
1177
-
1178
- type InteractionReduceInput<Collectors extends Record<string, InputCollector>, State extends {
1179
- table: RuntimeTableRecord;
1180
- flow: {
1181
- currentPhase: string;
1182
- };
1183
- }> = {
1184
- playerId: PlayerIdOfState<State>;
1185
- params: ParamsOf<Collectors>;
1186
- };
1187
- type InteractionValidateArgs<Collectors extends Record<string, InputCollector>, State extends {
1188
- table: RuntimeTableRecord;
1189
- flow: {
1190
- currentPhase: string;
1191
- };
1192
- }, Manifest extends ManifestContract<TableOfState<State>>> = ActionContext<State, Manifest> & ReadHelpers<State> & {
1193
- state: State;
1194
- input: InteractionReduceInput<Collectors, State>;
1195
- };
1196
- type InteractionReduceArgs<Collectors extends Record<string, InputCollector>, State extends {
1197
- table: RuntimeTableRecord;
1198
- flow: {
1199
- currentPhase: string;
1200
- };
1201
- }, Manifest extends ManifestContract<TableOfState<State>>, ErrorCode extends string = string> = InteractionValidateArgs<Collectors, State, Manifest> & MutationHelpers<State, ErrorCode>;
1202
- type InteractionAvailabilityArgs<State extends {
1203
- table: RuntimeTableRecord;
1204
- flow: {
1205
- currentPhase: string;
1206
- };
1207
- }, Manifest extends ManifestContract<TableOfState<State>>> = ActionContext<State, Manifest> & ReadHelpers<State> & {
1208
- state: State;
1209
- input: {
1210
- playerId: PlayerIdOfState<State>;
1211
- };
1212
- };
1213
- type InteractionRuleValidationResult<ErrorCode extends string = string> = boolean | string | ValidationIssue<ErrorCode> | null | undefined;
1214
- type InteractionRule<Collectors extends Record<string, InputCollector> = Record<string, InputCollector>, State extends {
1215
- table: RuntimeTableRecord;
1216
- flow: {
1217
- currentPhase: string;
1218
- };
1219
- } = {
1220
- table: RuntimeTableRecord;
1221
- flow: {
1222
- currentPhase: string;
1223
- };
1224
- }, Manifest extends ManifestContract<TableOfState<State>> = ManifestContract<TableOfState<State>>, ErrorCode extends string = string> = {
1225
- /**
1226
- * Stable rule id for diagnostics and tests. Rule ids are author-owned and
1227
- * should be unique within one interaction.
1228
- */
1229
- id: string;
1230
- /**
1231
- * Error code used when the rule fails. The same code is used for descriptor
1232
- * availability and submit-time validation unless `validate` returns a
1233
- * specific ValidationIssue.
1234
- */
1235
- errorCode: ErrorCode;
1236
- message?: string;
1237
- /**
1238
- * Projection-time rule. Runs without submitted params, so UI descriptors can
1239
- * reflect action availability before the user clicks.
1240
- */
1241
- available?: BivariantCallback<InteractionAvailabilityArgs<State, Manifest>, boolean>;
1242
- /**
1243
- * Submit-time rule. Runs with parsed params and may return false, a concrete
1244
- * ValidationIssue, null, or undefined.
1245
- */
1246
- validate?: BivariantCallback<InteractionValidateArgs<Collectors, State, Manifest>, InteractionRuleValidationResult<ErrorCode>>;
1247
- };
1248
- type InteractionCommitPolicy = {
1249
- mode: "manual";
1250
- } | {
1251
- mode: "autoWhenReady";
1252
- };
1253
- type HasManyInputCollector<Collectors extends Record<string, InputCollector>> = Extract<Collectors[keyof Collectors], {
1254
- readonly selection: {
1255
- readonly mode: "many";
1256
- };
1257
- }> extends never ? false : true;
1258
- type InteractionCommitPolicyFor<Collectors extends Record<string, InputCollector>> = HasManyInputCollector<Collectors> extends true ? {
1259
- mode: "manual";
1260
- } : InteractionCommitPolicy;
1261
- /**
1262
- * Projection-level interaction kind, derived by the trusted bundle from
1263
- * collector shape:
1264
- *
1265
- * - `"action"`: any interaction whose inputs are ordinary collectors
1266
- * (`formInput`, `cardInput`).
1267
- * - `"prompt"`: any interaction whose inputs include a `promptInput`
1268
- * collector. Prompt descriptors carry addressed-player context and options
1269
- * so UI primitives can render response controls without reducer-owned
1270
- * placement metadata.
1271
- *
1272
- * Authors never set this directly — the `promptInput(...)` collector is
1273
- * the single source of truth for prompt semantics. See {@link promptInput}
1274
- * and {@link InteractionDescriptor.kind}.
1275
- */
1276
- type InteractionKind = "action" | "prompt";
1277
- type InteractionPresentation = {
1278
- label: string;
1279
- help?: string;
1280
- };
1281
- type InteractionToArgs<State extends {
1282
- table: RuntimeTableRecord;
1283
- flow: {
1284
- currentPhase: string;
1285
- };
1286
- }, Manifest extends ManifestContract<TableOfState<State>>> = ActionContext<State, Manifest> & {
1287
- state: State;
1288
- };
1289
- type InteractionSpec<Collectors extends Record<string, InputCollector> = Record<string, InputCollector>, State extends {
1290
- table: RuntimeTableRecord;
1291
- flow: {
1292
- currentPhase: string;
1293
- };
1294
- } = {
1295
- table: RuntimeTableRecord;
1296
- flow: {
1297
- currentPhase: string;
1298
- };
1299
- }, Manifest extends ManifestContract<TableOfState<State>> = ManifestContract<TableOfState<State>>, ErrorCode extends string = string> = {
1300
- inputs: Collectors;
1301
- paramsSchema?: SchemaLike<ClientParamsOf<Collectors>>;
1302
- presentation?: InteractionPresentation;
1303
- /** @internal Phase-local step gates are attached by `defineStepPhase`. */
1304
- __steps?: readonly string[];
1305
- /**
1306
- * Draft commit policy. The input collectors still own value shape and
1307
- * validation; this only controls whether a ready draft may be submitted
1308
- * automatically by SDK controls.
1309
- *
1310
- * Multi-value collectors created with `many(...)` are always manual draft
1311
- * interactions. They represent a selection set that should be committed by
1312
- * explicit player intent, so `autoWhenReady` is intentionally not accepted.
1313
- */
1314
- commit?: InteractionCommitPolicyFor<Collectors>;
1315
- /**
1316
- * Addressed-player selector, used by prompt-kind interactions. When
1317
- * present, the trusted bundle only emits this descriptor for players in
1318
- * the returned set (or the single player, if a scalar is returned). Use
1319
- * to thread e.g. `state.publicState.knowerPlayerId` through without
1320
- * having to manage `activePlayers`. `undefined` / empty returns fall back
1321
- * to the standard `activePlayers` gating used by action-kind interactions.
1322
- */
1323
- to?: BivariantCallback<InteractionToArgs<State, Manifest>, PlayerIdOfState<State> | ReadonlyArray<PlayerIdOfState<State>> | null | undefined>;
1324
- /**
1325
- * Explicit actor selector. Overrides the phase-level actor for this
1326
- * interaction. Prefer this over `to` for new non-prompt interactions; `to`
1327
- * remains the prompt/addressee shorthand.
1328
- */
1329
- actor?: ActorSelector<State, Manifest>;
1330
- /**
1331
- * Descriptor visibility policy. `all` keeps non-actors visible but disabled;
1332
- * `actorsOnly` suppresses descriptors for seats that cannot act.
1333
- */
1334
- visibility?: "all" | "actorsOnly";
1335
- errorCodes?: readonly ErrorCode[];
1336
- cost?: BivariantCallback<InteractionValidateArgs<Collectors, State, Manifest>, Readonly<Record<string, number>>>;
1337
- rules?: readonly InteractionRule<NoInfer<Collectors>, State, Manifest, ErrorCode>[];
1338
- reduce: BivariantCallback<InteractionReduceArgs<Collectors, State, Manifest, ErrorCode>, ReducerResult<State> | void>;
1339
- };
1340
- type CardActionSpec<Collectors extends Record<string, InputCollector> = Record<string, InputCollector>, State extends {
1341
- table: RuntimeTableRecord;
1342
- flow: {
1343
- currentPhase: string;
1344
- };
1345
- } = {
1346
- table: RuntimeTableRecord;
1347
- flow: {
1348
- currentPhase: string;
1349
- };
1350
- }, Manifest extends ManifestContract<TableOfState<State>> = ManifestContract<TableOfState<State>>, PlayFrom extends PlayerZoneIdOfManifest<Manifest> = PlayerZoneIdOfManifest<Manifest>, ErrorCode extends string = string> = {
1351
- cardType: CardTypeOfState<State>;
1352
- playFrom: PlayFrom;
1353
- inputs?: Collectors;
1354
- paramsSchema?: SchemaLike<Record<string, unknown>>;
1355
- presentation?: InteractionPresentation;
1356
- /** @internal Phase-local step gates are attached by `defineStepPhase`. */
1357
- __steps?: readonly string[];
1358
- /**
1359
- * Draft commit policy. Card clicks still mutate the draft first;
1360
- * `autoWhenReady` submits only once the full interaction draft validates.
1361
- * Multi-value collectors created with `many(...)` are always manual draft
1362
- * interactions and cannot opt into `autoWhenReady`.
1363
- */
1364
- commit?: InteractionCommitPolicyFor<Collectors>;
1365
- actor?: ActorSelector<State, Manifest>;
1366
- visibility?: "all" | "actorsOnly";
1367
- errorCodes?: readonly ErrorCode[];
1368
- cost?: BivariantCallback<InteractionValidateArgs<Collectors & {
1369
- cardId: InputCollector<SchemaLike<CardIdOfState<State>>>;
1370
- }, State, Manifest>, Readonly<Record<string, number>>>;
1371
- rules?: readonly InteractionRule<NoInfer<Collectors & {
1372
- cardId: InputCollector<SchemaLike<CardIdOfState<State>>>;
1373
- }>, State, Manifest, ErrorCode>[];
1374
- reduce: BivariantCallback<InteractionReduceArgs<Collectors & {
1375
- cardId: InputCollector<SchemaLike<CardIdOfState<State>>>;
1376
- }, State, Manifest, ErrorCode>, ReducerResult<State>>;
1377
- };
1378
- type AnyInteractionRule = Omit<InteractionRule<any, any, any, any>, "available" | "validate"> & {
1379
- available?: BivariantCallback<any, boolean>;
1380
- validate?: BivariantCallback<any, InteractionRuleValidationResult<any>>;
1381
- };
1382
- type AnyCardActionSpec<State extends {
1383
- table: RuntimeTableRecord;
1384
- flow: {
1385
- currentPhase: string;
1386
- };
1387
- }, Manifest extends ManifestContract<TableOfState<State>>> = Omit<CardActionSpec<any, State, Manifest, any, any>, "actor" | "cost" | "rules" | "reduce"> & {
1388
- actor?: BivariantCallback<any, any>;
1389
- cost?: BivariantCallback<any, Readonly<Record<string, number>>>;
1390
- rules?: readonly AnyInteractionRule[];
1391
- reduce: BivariantCallback<any, ReducerResult<any> | void>;
1392
- };
1393
- type CardActionMap<State extends {
1394
- table: RuntimeTableRecord;
1395
- flow: {
1396
- currentPhase: string;
1397
- };
1398
- }, Manifest extends ManifestContract<TableOfState<State>>> = Record<string, AnyCardActionSpec<State, Manifest>>;
1399
- /**
1400
- * Type-safe erasure of {@link InteractionSpec} used by the runtime when it
1401
- * stores heterogeneous interactions in a single map. The collectors generic is
1402
- * intentionally erased with `any`: each authored interaction keeps a specific
1403
- * params shape, but phase registries need to store all of them together.
1404
- */
1405
- type AnyInteractionSpec<State extends {
1406
- table: RuntimeTableRecord;
1407
- flow: {
1408
- currentPhase: string;
1409
- };
1410
- }, Manifest extends ManifestContract<TableOfState<State>>> = Omit<InteractionSpec<any, State, Manifest, any>, "actor" | "cost" | "rules" | "reduce" | "to"> & {
1411
- actor?: BivariantCallback<any, any>;
1412
- cost?: BivariantCallback<any, Readonly<Record<string, number>>>;
1413
- rules?: readonly AnyInteractionRule[];
1414
- reduce: BivariantCallback<any, ReducerResult<any> | void>;
1415
- to?: BivariantCallback<any, any>;
1416
- };
1417
- type InteractionMap<State extends {
1418
- table: RuntimeTableRecord;
1419
- flow: {
1420
- currentPhase: string;
1421
- };
1422
- }, Manifest extends ManifestContract<TableOfState<State>>> = Record<string, AnyInteractionSpec<State, Manifest>>;
1423
- type StageSpec<State extends {
1424
- table: RuntimeTableRecord;
1425
- flow: {
1426
- currentPhase: string;
1427
- };
1428
- }, Manifest extends ManifestContract<TableOfState<State>>> = {
1429
- when?: BivariantCallback<ActionContext<State, Manifest> & {
1430
- state: State;
1431
- }, boolean>;
1432
- onEnter?: BivariantCallback<PhaseEnterArgs<State, Manifest>, ReducerResult<State> | void>;
1433
- onExit?: BivariantCallback<PhaseEnterArgs<State, Manifest>, ReducerResult<State> | void>;
1434
- allow: readonly string[];
1435
- };
1436
- type StageMap<State extends {
1437
- table: RuntimeTableRecord;
1438
- flow: {
1439
- currentPhase: string;
1440
- };
1441
- }, Manifest extends ManifestContract<TableOfState<State>>> = Record<string, StageSpec<State, Manifest>>;
1442
- type PhaseZoneList<Manifest extends ManifestContract<RuntimeTableRecord>> = readonly PlayerZoneIdOfManifest<Manifest>[];
1443
-
1444
- type SimultaneousSubmission<Collectors extends Record<string, InputCollector>, State extends {
1445
- table: RuntimeTableRecord;
1446
- flow: {
1447
- currentPhase: string;
1448
- };
1449
- }> = {
1450
- playerId: PlayerIdOfState<State>;
1451
- params: ParamsOf<Collectors>;
1452
- };
1453
- type SimultaneousResolveArgs<Collectors extends Record<string, InputCollector>, State extends {
1454
- table: RuntimeTableRecord;
1455
- flow: {
1456
- currentPhase: string;
1457
- };
1458
- }, Manifest extends ManifestContract<TableOfState<State>>, ErrorCode extends string = string> = ActionContext<State, Manifest> & ReadHelpers<State> & MutationHelpers<State, ErrorCode> & {
1459
- state: State;
1460
- submissions: Record<PlayerIdOfState<State>, SimultaneousSubmission<Collectors, State>>;
1461
- submittedPlayerIds: PlayerIdOfState<State>[];
1462
- waitingPlayerIds: PlayerIdOfState<State>[];
1463
- };
1464
- type SimultaneousSubmitSpec<Collectors extends Record<string, InputCollector> = Record<string, InputCollector>, State extends {
1465
- table: RuntimeTableRecord;
1466
- flow: {
1467
- currentPhase: string;
1468
- };
1469
- } = {
1470
- table: RuntimeTableRecord;
1471
- flow: {
1472
- currentPhase: string;
1473
- };
1474
- }, Manifest extends ManifestContract<TableOfState<State>> = ManifestContract<TableOfState<State>>> = Omit<InteractionSpec<Collectors, State, Manifest>, "reduce"> & {
1475
- /**
1476
- * Optional compatibility slot for callers that reuse `defineInteraction`.
1477
- * The simultaneous phase barrier stores submissions and invokes the
1478
- * phase-level `resolve`; this per-submission reducer is intentionally
1479
- * ignored when present.
1480
- */
1481
- reduce?: InteractionSpec<Collectors, State, Manifest>["reduce"];
1482
- };
1483
-
1484
- type PhaseGuidance = {
1485
- summary: string;
1486
- objective?: string;
1487
- };
1488
- type PhaseDefinitionCommon<PhaseStateSchema extends SchemaLike<object>, State extends {
1489
- table: RuntimeTableRecord;
1490
- flow: {
1491
- currentPhase: string;
1492
- };
1493
- phase: object;
1494
- }, Manifest extends ManifestContract<TableOfState<State>>, ErrorCode extends string = string> = {
1495
- name?: string;
1496
- guidance?: PhaseGuidance;
1497
- state: PhaseStateSchema;
1498
- initialState?: (ctx: {
1499
- manifest: Manifest;
1500
- state: State;
1501
- playerIds: PlayerIdOfState<State>[];
1502
- setup: SetupSelectionOfManifest<Manifest> | null;
1503
- }) => z.infer<PhaseStateSchema>;
1504
- enter?: BivariantCallback<PhaseEnterArgs<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest, ErrorCode>, ReducerResult<ScopedPhaseState<State, z.infer<PhaseStateSchema>>> | void>;
1505
- };
1506
- type AutoPhaseDefinition<PhaseStateSchema extends SchemaLike<object>, State extends {
1507
- table: RuntimeTableRecord;
1508
- flow: {
1509
- currentPhase: string;
1510
- };
1511
- phase: object;
1512
- }, Manifest extends ManifestContract<TableOfState<State>>, ErrorCode extends string = string> = PhaseDefinitionCommon<PhaseStateSchema, State, Manifest, ErrorCode> & {
1513
- kind: "auto";
1514
- actor?: never;
1515
- actors?: never;
1516
- submit?: never;
1517
- canResubmit?: never;
1518
- resolve?: never;
1519
- effects?: never;
1520
- interactions?: never;
1521
- stages?: never;
1522
- zones?: never;
1523
- cardActions?: never;
1524
- };
1525
- type PlayerPhaseDefinition<PhaseStateSchema extends SchemaLike<object>, State extends {
1526
- table: RuntimeTableRecord;
1527
- flow: {
1528
- currentPhase: string;
1529
- };
1530
- phase: object;
1531
- }, Manifest extends ManifestContract<TableOfState<State>>, Effects extends EffectMap<State, Manifest> = Record<string, never>, Interactions extends InteractionMap<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest> = Record<string, never>, Stages extends StageMap<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest> = Record<string, never>, Zones extends PhaseZoneList<Manifest> = readonly [], CardActions extends CardActionMap<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest> = Record<string, never>, ErrorCode extends string = string> = PhaseDefinitionCommon<PhaseStateSchema, State, Manifest, ErrorCode> & {
1532
- kind: "player";
1533
- /**
1534
- * Default actor selector for interactions in this phase. When omitted the
1535
- * runtime falls back to `flow.activePlayers`, preserving the existing turn
1536
- * ownership model. Returning multiple players models simultaneous actors.
1537
- */
1538
- actor?: ActorSelector<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest>;
1539
- actors?: never;
1540
- submit?: never;
1541
- canResubmit?: never;
1542
- resolve?: never;
1543
- effects?: Effects;
1544
- interactions?: Interactions;
1545
- stages?: Stages;
1546
- zones?: Zones;
1547
- cardActions?: CardActions;
1548
- };
1549
- type SimultaneousPlayerPhaseDefinition<PhaseStateSchema extends SchemaLike<object>, State extends {
1550
- table: RuntimeTableRecord;
1551
- flow: {
1552
- currentPhase: string;
1553
- };
1554
- phase: object;
1555
- }, Manifest extends ManifestContract<TableOfState<State>>, SubmitCollectors extends Record<string, InputCollector> = Record<string, InputCollector>, Effects extends EffectMap<State, Manifest> = Record<string, never>, Interactions extends InteractionMap<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest> = Record<string, never>, Stages extends StageMap<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest> = Record<string, never>, Zones extends PhaseZoneList<Manifest> = readonly [], CardActions extends CardActionMap<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest> = Record<string, never>, ErrorCode extends string = string> = PhaseDefinitionCommon<PhaseStateSchema, State, Manifest, ErrorCode> & {
1556
- kind: "simultaneousPlayer";
1557
- actor?: never;
1558
- /**
1559
- * Actor selector for `kind: "simultaneousPlayer"` phases. This is an alias
1560
- * of `actor` with wording that matches simultaneous submission semantics.
1561
- */
1562
- actors: ActorSelector<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest>;
1563
- /**
1564
- * Canonical sealed submission interaction for simultaneous phases. It is
1565
- * projected like a normal interaction, but the trusted runtime stores the
1566
- * parsed params until every actor has submitted, then calls `resolve`.
1567
- */
1568
- submit: SimultaneousSubmitSpec<SubmitCollectors, ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest>;
1569
- /**
1570
- * When false or omitted, each actor can submit once per simultaneous
1571
- * barrier. Set true to allow replacing the sealed submission before every
1572
- * required actor has submitted.
1573
- */
1574
- canResubmit?: boolean;
1575
- /**
1576
- * Batch resolver invoked once all simultaneous actors have submitted. The
1577
- * submitted params are passed together so game state mutates from one
1578
- * deterministic base state instead of one player at a time.
1579
- */
1580
- resolve: BivariantCallback<SimultaneousResolveArgs<SubmitCollectors, ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest, ErrorCode>, ReducerResult<ScopedPhaseState<State, z.infer<PhaseStateSchema>>> | void>;
1581
- effects?: Effects;
1582
- interactions?: Interactions;
1583
- stages?: Stages;
1584
- zones?: Zones;
1585
- cardActions?: CardActions;
1586
- };
1587
- type PhaseDefinition<PhaseStateSchema extends SchemaLike<object>, State extends {
1588
- table: RuntimeTableRecord;
1589
- flow: {
1590
- currentPhase: string;
1591
- };
1592
- phase: object;
1593
- }, Manifest extends ManifestContract<TableOfState<State>>, SubmitCollectors extends Record<string, InputCollector> = Record<string, InputCollector>, Effects extends EffectMap<State, Manifest> = Record<string, never>, Interactions extends InteractionMap<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest> = Record<string, never>, Stages extends StageMap<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest> = Record<string, never>, Zones extends PhaseZoneList<Manifest> = readonly [], CardActions extends CardActionMap<ScopedPhaseState<State, z.infer<PhaseStateSchema>>, Manifest> = Record<string, never>, ErrorCode extends string = string> = AutoPhaseDefinition<PhaseStateSchema, State, Manifest, ErrorCode> | PlayerPhaseDefinition<PhaseStateSchema, State, Manifest, Effects, Interactions, Stages, Zones, CardActions, ErrorCode> | SimultaneousPlayerPhaseDefinition<PhaseStateSchema, State, Manifest, SubmitCollectors, Effects, Interactions, Stages, Zones, CardActions, ErrorCode>;
1594
-
1595
- type SharedViewDefinition<State extends {
1596
- table: RuntimeTableRecord;
1597
- flow: {
1598
- currentPhase: string;
1599
- };
1600
- }, Manifest extends ManifestContract<TableOfState<State>>, Projection = unknown> = {
1601
- project: (args: ActionContext<State, Manifest> & ReadHelpers<State> & {
1602
- state: State;
1603
- }) => Projection;
1604
- };
1605
- type PlayerViewDefinition<State extends {
1606
- table: RuntimeTableRecord;
1607
- flow: {
1608
- currentPhase: string;
1609
- };
1610
- }, Manifest extends ManifestContract<TableOfState<State>>, SharedProjection = unknown, Projection = unknown> = {
1611
- project: (args: ActionContext<State, Manifest> & ReadHelpers<State> & {
1612
- state: State;
1613
- playerId: PlayerIdOfState<State>;
1614
- shared: SharedProjection;
1615
- }) => Projection;
1616
- };
1617
- type EmptyViewDefinition<State extends {
1618
- table: RuntimeTableRecord;
1619
- flow: {
1620
- currentPhase: string;
1621
- };
1622
- }, Manifest extends ManifestContract<TableOfState<State>>> = SharedViewDefinition<State, Manifest, Record<string, never>> & PlayerViewDefinition<State, Manifest, unknown, Record<string, never>>;
1623
- /**
1624
- * Session-scoped, once-per-init view. The `project` callback receives only
1625
- * the authored manifest — the mutable-state helpers (`state`, `playerId`,
1626
- * `runtime`, `fx`, `ops`, `accept`, `reject`, `q`) that `ViewDefinition.project`
1627
- * exposes are structurally absent, so an author cannot accidentally project
1628
- * per-tick state into the payload. The host calls this once per reducer
1629
- * session, caches the result, and merges it back into every seat view on
1630
- * the client. Moving static board topology here is what lets the adapter
1631
- * skip the ~87% of `project` wall time that used to re-serialize
1632
- * manifest-sourced fields on every input.
1633
- */
1634
- type StaticViewDefinition<Manifest extends ManifestContract<RuntimeTableRecord>, Projection = unknown> = {
1635
- project: (args: {
1636
- manifest: Manifest;
1637
- q: StaticViewQueries<Manifest>;
1638
- }) => Projection;
1639
- };
1640
-
1641
- export { type InputCollectorMetaForKind as $, type ActionContext as A, type BaseGameSessionOfContract as B, type CardActionMap as C, type ContinuationInput as D, type ContinuationInputForSource as E, type ContinuationKind as F, type ContinuationReduceArgs as G, type ContinuationSourceKind as H, type DefaultedClientParamKeysOfInteractionOfDefinition as I, type DerivedDefinition as J, type DerivedResolver as K, type EagerInputDomainDependencies as L, type EffectContinuationCallable as M, type EffectContinuationInput as N, type EffectContinuationResponse as O, type EffectDefinition as P, type EffectIdsOfDefinition as Q, type EffectMap as R, type EffectRegistryOfPhase as S, type EffectRollDieDefinition as T, type EffectShuffleDefinition as U, type EffectShufflePlayerZoneDefinition as V, type EmptyViewDefinition as W, type GameStateOf as X, type InitialStateCallbacks as Y, type InputCollector as Z, type InputCollectorKind as _, type ActorSelection as a, type ShuffleSharedZoneContinuationResponse as a$, type InputDomainDependencyCase as a0, type InputDomainDescriptor as a1, type InputDomainResolverDescriptor as a2, type InputKeysWithCollectorKindOfDefinition as a3, type InputSelectionDescriptor as a4, type InteractionAvailabilityArgs as a5, type InteractionCommitPolicy as a6, type InteractionIdOfDefinition as a7, type InteractionIdOfDefinitionPhase as a8, type InteractionKind as a9, type PlayerPhaseDefinition as aA, type PlayerViewDefinition as aB, type PromptInputCollectorMeta as aC, type PromptInteractionKeyOfDefinition as aD, type RandomHelpers as aE, type ReadHelpers as aF, type ReducerGameContract as aG, type ReducerGameContractLike as aH, type ReducerGameDefinition as aI, type ReducerOps as aJ, type ReducerSessionForConfig as aK, type ReducerStateBase as aL, type ReducerStateForConfig as aM, type ReducerTransaction as aN, type ReducerTransactionOutcome as aO, type ResolvedBoardTargetDomainDescriptor as aP, type ResolvedCardTargetDomainDescriptor as aQ, type ResolvedGameSessionOf as aR, type ResolvedGameStateOf as aS, type ResourceMapDomainDescriptor as aT, type ResumableEffectKind as aU, type RngInputCollectorMeta as aV, type RollDieContinuationResponse as aW, type RotatePlayerZoneArgs as aX, type ScopedPhaseState as aY, type SharedViewDefinition as aZ, type ShufflePlayerZoneContinuationResponse as a_, type InteractionMap as aa, type InteractionReduceArgs as ab, type InteractionReduceInput as ac, type InteractionRule as ad, type InteractionRuleValidationResult as ae, type InteractionSpec as af, type InteractionSpecByNameOfDefinitionPhase as ag, type InteractionToArgs as ah, type InteractionValidateArgs as ai, type LazyBoardTargetDomainDescriptor as aj, type LazyCardTargetDomainDescriptor as ak, type LazyInputDomainDependencies as al, type MutationHelpers as am, type Op as an, type ParamsOf as ao, type ParamsOfInteractionOfDefinition as ap, type PhaseDefinition as aq, type PhaseDefinitionByName as ar, type PhaseEnterArgs as as, type PhaseEnterContext as at, type PhaseMapOf as au, type PhaseNamesOfDefinition as av, type PhaseStateMapOfDefinitions as aw, type PhaseStateOfDefinitions as ax, type PhaseZoneList as ay, type PlayableInteractionsOfZoneOfDefinition as az, type ActorSelector as b, type SimultaneousPlayerPhaseDefinition as b0, type SimultaneousResolveArgs as b1, type SimultaneousSubmission as b2, type SimultaneousSubmitSpec as b3, type StageMap as b4, type StageNamesOfDefinitionPhase as b5, type StageSpec as b6, type StaticViewDefinition as b7, type StaticViewQueries as b8, type TargetKind as b9, type ValidationIssue as ba, type ViewDefinitionByName as bb, type ViewMapOf as bc, type ViewNamesOfDefinition as bd, type ViewOfDefinition as be, type ViewsOfDefinition as bf, type ZoneIdsOfDefinition as bg, createDerivedResolver as bh, createReducerOps as bi, defineDerived as bj, pipe as bk, type ActorSelectorArgs as c, type AnyCardActionSpec as d, type AnyContinuationCallable as e, type AnyInteractionSpec as f, type AnyPhaseDefinitionForContract as g, type AnyReducerGameDefinition as h, type AutoPhaseDefinition as i, type BaseGameStateOfContract as j, type BoardInputCollectorKind as k, type BoardInputCollectorMeta as l, type BoardInteractionKeyOfDefinition as m, type BoardTargetDomainDescriptor as n, type BoundedNumberDomainDescriptor as o, type CardActionSpec as p, type CardInputCollectorMeta as q, type CardInputZoneIdsOfDefinition as r, type CardInteractionKeyOfDefinition as s, type CardTargetDomainDescriptor as t, type ChoiceDomainDescriptor as u, type ChoiceListDomainDescriptor as v, type ClientParamsOf as w, type ClientParamsOfInteractionOfDefinition as x, type CollectorState as y, type ContinuationCallable as z };