@drmxrcy/tcg-core 0.0.0-202602060542

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 (157) hide show
  1. package/README.md +882 -0
  2. package/package.json +58 -0
  3. package/src/__tests__/alpha-clash-engine-definition.test.ts +319 -0
  4. package/src/__tests__/createMockAlphaClashGame.ts +462 -0
  5. package/src/__tests__/createMockGrandArchiveGame.ts +373 -0
  6. package/src/__tests__/createMockGundamGame.ts +379 -0
  7. package/src/__tests__/createMockLorcanaGame.ts +328 -0
  8. package/src/__tests__/createMockOnePieceGame.ts +429 -0
  9. package/src/__tests__/createMockRiftboundGame.ts +462 -0
  10. package/src/__tests__/grand-archive-engine-definition.test.ts +118 -0
  11. package/src/__tests__/gundam-engine-definition.test.ts +110 -0
  12. package/src/__tests__/integration-complete-game.test.ts +508 -0
  13. package/src/__tests__/integration-network-sync.test.ts +469 -0
  14. package/src/__tests__/lorcana-engine-definition.test.ts +100 -0
  15. package/src/__tests__/move-enumeration.test.ts +725 -0
  16. package/src/__tests__/multiplayer-engine.test.ts +555 -0
  17. package/src/__tests__/one-piece-engine-definition.test.ts +114 -0
  18. package/src/__tests__/riftbound-engine-definition.test.ts +124 -0
  19. package/src/actions/action-definition.test.ts +201 -0
  20. package/src/actions/action-definition.ts +122 -0
  21. package/src/actions/action-timing.test.ts +490 -0
  22. package/src/actions/action-timing.ts +257 -0
  23. package/src/cards/card-definition.test.ts +268 -0
  24. package/src/cards/card-definition.ts +27 -0
  25. package/src/cards/card-instance.test.ts +422 -0
  26. package/src/cards/card-instance.ts +49 -0
  27. package/src/cards/computed-properties.test.ts +530 -0
  28. package/src/cards/computed-properties.ts +84 -0
  29. package/src/cards/conditional-modifiers.test.ts +390 -0
  30. package/src/cards/modifiers.test.ts +286 -0
  31. package/src/cards/modifiers.ts +51 -0
  32. package/src/engine/MULTIPLAYER.md +425 -0
  33. package/src/engine/__tests__/rule-engine-flow.test.ts +348 -0
  34. package/src/engine/__tests__/rule-engine-history.test.ts +535 -0
  35. package/src/engine/__tests__/rule-engine-moves.test.ts +488 -0
  36. package/src/engine/__tests__/rule-engine.test.ts +366 -0
  37. package/src/engine/index.ts +14 -0
  38. package/src/engine/multiplayer-engine.example.ts +571 -0
  39. package/src/engine/multiplayer-engine.ts +409 -0
  40. package/src/engine/rule-engine.test.ts +286 -0
  41. package/src/engine/rule-engine.ts +1539 -0
  42. package/src/engine/tracker-system.ts +172 -0
  43. package/src/examples/__tests__/coin-flip-game.test.ts +641 -0
  44. package/src/filtering/card-filter.test.ts +230 -0
  45. package/src/filtering/card-filter.ts +91 -0
  46. package/src/filtering/card-query.test.ts +901 -0
  47. package/src/filtering/card-query.ts +273 -0
  48. package/src/filtering/filter-matching.test.ts +944 -0
  49. package/src/filtering/filter-matching.ts +315 -0
  50. package/src/flow/SERIALIZATION.md +428 -0
  51. package/src/flow/__tests__/flow-definition.test.ts +427 -0
  52. package/src/flow/__tests__/flow-manager.test.ts +756 -0
  53. package/src/flow/__tests__/flow-serialization.test.ts +565 -0
  54. package/src/flow/flow-definition.ts +453 -0
  55. package/src/flow/flow-manager.ts +1044 -0
  56. package/src/flow/index.ts +35 -0
  57. package/src/game-definition/__tests__/game-definition-validation.test.ts +359 -0
  58. package/src/game-definition/__tests__/game-definition.test.ts +291 -0
  59. package/src/game-definition/__tests__/move-definitions.test.ts +328 -0
  60. package/src/game-definition/game-definition.ts +261 -0
  61. package/src/game-definition/index.ts +28 -0
  62. package/src/game-definition/move-definitions.ts +188 -0
  63. package/src/game-definition/validation.ts +183 -0
  64. package/src/history/history-manager.test.ts +497 -0
  65. package/src/history/history-manager.ts +312 -0
  66. package/src/history/history-operations.ts +122 -0
  67. package/src/history/index.ts +9 -0
  68. package/src/history/types.ts +255 -0
  69. package/src/index.ts +32 -0
  70. package/src/logging/index.ts +27 -0
  71. package/src/logging/log-formatter.ts +187 -0
  72. package/src/logging/logger.ts +276 -0
  73. package/src/logging/types.ts +148 -0
  74. package/src/moves/create-move.test.ts +331 -0
  75. package/src/moves/create-move.ts +64 -0
  76. package/src/moves/move-enumeration.ts +228 -0
  77. package/src/moves/move-executor.test.ts +431 -0
  78. package/src/moves/move-executor.ts +195 -0
  79. package/src/moves/move-system.test.ts +380 -0
  80. package/src/moves/move-system.ts +463 -0
  81. package/src/moves/standard-moves.ts +231 -0
  82. package/src/operations/card-operations.test.ts +236 -0
  83. package/src/operations/card-operations.ts +116 -0
  84. package/src/operations/card-registry-impl.test.ts +251 -0
  85. package/src/operations/card-registry-impl.ts +70 -0
  86. package/src/operations/card-registry.test.ts +234 -0
  87. package/src/operations/card-registry.ts +106 -0
  88. package/src/operations/counter-operations.ts +152 -0
  89. package/src/operations/game-operations.test.ts +280 -0
  90. package/src/operations/game-operations.ts +140 -0
  91. package/src/operations/index.ts +24 -0
  92. package/src/operations/operations-impl.test.ts +354 -0
  93. package/src/operations/operations-impl.ts +468 -0
  94. package/src/operations/zone-operations.test.ts +295 -0
  95. package/src/operations/zone-operations.ts +223 -0
  96. package/src/rng/seeded-rng.test.ts +339 -0
  97. package/src/rng/seeded-rng.ts +123 -0
  98. package/src/targeting/index.ts +48 -0
  99. package/src/targeting/target-definition.test.ts +273 -0
  100. package/src/targeting/target-definition.ts +37 -0
  101. package/src/targeting/target-dsl.ts +279 -0
  102. package/src/targeting/target-resolver.ts +486 -0
  103. package/src/targeting/target-validation.test.ts +994 -0
  104. package/src/targeting/target-validation.ts +286 -0
  105. package/src/telemetry/events.ts +202 -0
  106. package/src/telemetry/index.ts +21 -0
  107. package/src/telemetry/telemetry-manager.ts +127 -0
  108. package/src/telemetry/types.ts +68 -0
  109. package/src/testing/__tests__/testing-utilities-integration.test.ts +161 -0
  110. package/src/testing/index.ts +88 -0
  111. package/src/testing/test-assertions.test.ts +341 -0
  112. package/src/testing/test-assertions.ts +256 -0
  113. package/src/testing/test-card-factory.test.ts +228 -0
  114. package/src/testing/test-card-factory.ts +111 -0
  115. package/src/testing/test-context-factory.ts +187 -0
  116. package/src/testing/test-end-assertions.test.ts +262 -0
  117. package/src/testing/test-end-assertions.ts +95 -0
  118. package/src/testing/test-engine-builder.test.ts +389 -0
  119. package/src/testing/test-engine-builder.ts +46 -0
  120. package/src/testing/test-flow-assertions.test.ts +284 -0
  121. package/src/testing/test-flow-assertions.ts +115 -0
  122. package/src/testing/test-player-builder.test.ts +132 -0
  123. package/src/testing/test-player-builder.ts +46 -0
  124. package/src/testing/test-replay-assertions.test.ts +356 -0
  125. package/src/testing/test-replay-assertions.ts +164 -0
  126. package/src/testing/test-rng-helpers.test.ts +260 -0
  127. package/src/testing/test-rng-helpers.ts +190 -0
  128. package/src/testing/test-state-builder.test.ts +373 -0
  129. package/src/testing/test-state-builder.ts +99 -0
  130. package/src/testing/test-zone-factory.test.ts +295 -0
  131. package/src/testing/test-zone-factory.ts +224 -0
  132. package/src/types/branded-utils.ts +54 -0
  133. package/src/types/branded.test.ts +175 -0
  134. package/src/types/branded.ts +33 -0
  135. package/src/types/index.ts +8 -0
  136. package/src/types/state.test.ts +198 -0
  137. package/src/types/state.ts +154 -0
  138. package/src/validation/card-type-guards.test.ts +242 -0
  139. package/src/validation/card-type-guards.ts +179 -0
  140. package/src/validation/index.ts +40 -0
  141. package/src/validation/schema-builders.test.ts +403 -0
  142. package/src/validation/schema-builders.ts +345 -0
  143. package/src/validation/type-guard-builder.test.ts +216 -0
  144. package/src/validation/type-guard-builder.ts +109 -0
  145. package/src/validation/validator-builder.test.ts +375 -0
  146. package/src/validation/validator-builder.ts +273 -0
  147. package/src/zones/index.ts +28 -0
  148. package/src/zones/zone-factory.test.ts +183 -0
  149. package/src/zones/zone-factory.ts +44 -0
  150. package/src/zones/zone-operations.test.ts +800 -0
  151. package/src/zones/zone-operations.ts +306 -0
  152. package/src/zones/zone-state-helpers.test.ts +337 -0
  153. package/src/zones/zone-state-helpers.ts +128 -0
  154. package/src/zones/zone-visibility.test.ts +156 -0
  155. package/src/zones/zone-visibility.ts +36 -0
  156. package/src/zones/zone.test.ts +186 -0
  157. package/src/zones/zone.ts +66 -0
@@ -0,0 +1,453 @@
1
+ import type { Draft } from "immer";
2
+ import type { CardOperations } from "../operations/card-operations";
3
+ import type { GameOperations } from "../operations/game-operations";
4
+ import type { ZoneOperations } from "../operations/zone-operations";
5
+
6
+ /**
7
+ * Task 9.9: FlowContext - Rich context API for flow hooks
8
+ *
9
+ * User requirement: "Flow (and moves) should receive a richer context"
10
+ *
11
+ * Provides access to:
12
+ * - State (as Immer draft for mutations)
13
+ * - Flow control methods (endPhase, endSegment, endTurn)
14
+ * - Current flow information (phase, segment, turn, player)
15
+ * - Game operations (OTP, mulligan, etc.)
16
+ * - Zone operations (move cards, query zones)
17
+ * - Card operations (metadata, queries)
18
+ *
19
+ * This replaces the simple (state: TState) => void pattern with a richer API
20
+ * that allows programmatic control of flow progression and access to game operations.
21
+ */
22
+ export type FlowContext<TState, TCardMeta = any> = {
23
+ /** Immer draft of game state - can be mutated */
24
+ state: Draft<TState>;
25
+
26
+ /**
27
+ * Game operations API
28
+ *
29
+ * Provides methods to interact with game-level state:
30
+ * - setOTP: Mark player as on the play (goes first)
31
+ * - getOTP: Get the OTP player
32
+ * - setPendingMulligan: Set players pending mulligan
33
+ * - getPendingMulligan: Get players pending mulligan
34
+ * - addPendingMulligan: Add player to mulligan list
35
+ * - removePendingMulligan: Remove player from mulligan list
36
+ *
37
+ * These are universal TCG concepts that apply across all card games.
38
+ */
39
+ game: GameOperations;
40
+
41
+ /**
42
+ * Zone operations API
43
+ *
44
+ * Provides methods to interact with the framework's zone management:
45
+ * - moveCard: Move cards between zones
46
+ * - getCardsInZone: Query cards in a zone
47
+ * - shuffleZone: Shuffle a zone
48
+ * - getCardZone: Find which zone contains a card
49
+ */
50
+ zones: ZoneOperations;
51
+
52
+ /**
53
+ * Card operations API
54
+ *
55
+ * Provides methods to interact with the framework's card metadata:
56
+ * - getCardMeta: Get dynamic card properties
57
+ * - updateCardMeta: Merge metadata updates
58
+ * - setCardMeta: Replace metadata completely
59
+ * - getCardOwner: Get card's owner
60
+ * - queryCards: Find cards by predicate
61
+ */
62
+ cards: CardOperations<TCardMeta>;
63
+
64
+ /**
65
+ * Programmatically end the current phase
66
+ *
67
+ * User requirement: "We should be able to end the phase programmatically"
68
+ *
69
+ * When called, the current phase will end and transition to the next phase.
70
+ * If no next phase is defined, the turn ends.
71
+ */
72
+ endPhase: () => void;
73
+
74
+ /**
75
+ * Programmatically end the current step
76
+ *
77
+ * User requirement: "We should be able to end the step programmatically"
78
+ *
79
+ * When called, the current step will end and transition to the next step.
80
+ * If no next step is defined, the phase ends.
81
+ */
82
+ endStep: () => void;
83
+
84
+ /**
85
+ * Programmatically end the current game segment
86
+ *
87
+ * User requirement: "We should be able to end the game segment programmatically"
88
+ *
89
+ * When called, the current game segment will end and transition to the next segment.
90
+ * Game segments are high-level divisions (e.g., sideboarding, draft, main game).
91
+ */
92
+ endGameSegment: (segmentName?: string) => void;
93
+
94
+ /**
95
+ * Programmatically end the current turn
96
+ *
97
+ * User requirement: "We should be able to end the turn programmatically"
98
+ *
99
+ * When called, the current turn will end and the next player's turn will begin
100
+ * (or game ends if this was the last turn).
101
+ */
102
+ endTurn: () => void;
103
+
104
+ /**
105
+ * Get the current phase name
106
+ *
107
+ * @returns Current phase name, or undefined if no phase is active
108
+ */
109
+ getCurrentPhase: () => string | undefined;
110
+
111
+ /**
112
+ * Get the current step name
113
+ *
114
+ * @returns Current step name, or undefined if no step is active
115
+ */
116
+ getCurrentStep: () => string | undefined;
117
+
118
+ /**
119
+ * Get the current game segment name
120
+ *
121
+ * @returns Current game segment name, or undefined if no game segment is active
122
+ */
123
+ getCurrentGameSegment: () => string | undefined;
124
+
125
+ /**
126
+ * Get the current player ID
127
+ *
128
+ * @returns Current player's ID
129
+ */
130
+ getCurrentPlayer: () => string;
131
+
132
+ /**
133
+ * Get the current turn number
134
+ *
135
+ * @returns Current turn number (1-indexed)
136
+ */
137
+ getTurnNumber: () => number;
138
+
139
+ /**
140
+ * Set the current player ID
141
+ *
142
+ * Allows explicit control over which player is "active" or has "priority".
143
+ * Useful for game segments where priority doesn't follow standard turn order
144
+ * (e.g., during game setup, mulligan phases, or special action sequences).
145
+ *
146
+ * @param playerId - Player ID to set as current, or undefined to clear
147
+ */
148
+ setCurrentPlayer: (playerId?: string) => void;
149
+ };
150
+
151
+ /**
152
+ * Task 9.2: Lifecycle hook type
153
+ *
154
+ * All lifecycle hooks receive FlowContext instead of just state.
155
+ * This allows hooks to:
156
+ * - Mutate state
157
+ * - Control flow progression
158
+ * - Access flow information
159
+ * - Access game, zone, and card operations
160
+ */
161
+ export type LifecycleHook<TState, TCardMeta = any> = (
162
+ context: FlowContext<TState, TCardMeta>,
163
+ ) => void;
164
+
165
+ /**
166
+ * Task 9.7: End condition type
167
+ *
168
+ * Automatically triggers transition when condition returns true.
169
+ * Checked after every state change.
170
+ */
171
+ export type EndCondition<TState, TCardMeta = any> = (
172
+ context: FlowContext<TState, TCardMeta>,
173
+ ) => boolean;
174
+
175
+ /**
176
+ * Task 9.13: StepDefinition - Steps within phases
177
+ *
178
+ * User requirement: "For steps, it's a bit different... combat has different steps"
179
+ *
180
+ * Steps are sub-divisions within a phase.
181
+ * Example: Combat phase has declare, target, damage steps.
182
+ * Once all steps are over, the phase ends.
183
+ */
184
+ export type StepDefinition<TState, TCardMeta = any> = {
185
+ /**
186
+ * Order/sequence number for this step
187
+ *
188
+ * Used for default sequential progression.
189
+ * Lower numbers execute first.
190
+ */
191
+ order: number;
192
+
193
+ /**
194
+ * Next step name
195
+ *
196
+ * When this step ends, transition to the named step.
197
+ * If undefined, the phase ends.
198
+ */
199
+ next?: string;
200
+
201
+ /**
202
+ * Task 9.5: Lifecycle hook called when step begins
203
+ */
204
+ onBegin?: LifecycleHook<TState, TCardMeta>;
205
+
206
+ /**
207
+ * Task 9.5: Lifecycle hook called when step ends
208
+ */
209
+ onEnd?: LifecycleHook<TState, TCardMeta>;
210
+
211
+ /**
212
+ * Task 9.7: Automatic end condition
213
+ *
214
+ * When returns true, step automatically ends and transitions to next.
215
+ */
216
+ endIf?: EndCondition<TState, TCardMeta>;
217
+ };
218
+
219
+ /**
220
+ * Task 9.13: PhaseDefinition - Phases within a turn
221
+ *
222
+ * User requirement: "phases, when the current phase ends, the next phase from
223
+ * the same player will start"
224
+ *
225
+ * Example: Disney Lorcana turn has ready, draw, main, end phases.
226
+ * Phases progress sequentially for the same player.
227
+ */
228
+ export type PhaseDefinition<TState, TCardMeta = any> = {
229
+ /**
230
+ * Initial step name (optional)
231
+ *
232
+ * If specified and current phase has steps, begins at this step.
233
+ * If not specified, uses first step by order.
234
+ */
235
+ initialStep?: string;
236
+
237
+ /**
238
+ * Order/sequence number for this phase
239
+ *
240
+ * Used for default sequential progression.
241
+ * Lower numbers execute first.
242
+ */
243
+ order: number;
244
+
245
+ /**
246
+ * Next phase name
247
+ *
248
+ * When this phase ends, transition to the named phase.
249
+ * If undefined, the turn ends.
250
+ */
251
+ next?: string;
252
+
253
+ /**
254
+ * Task 9.5: Lifecycle hook called when phase begins
255
+ */
256
+ onBegin?: LifecycleHook<TState, TCardMeta>;
257
+
258
+ /**
259
+ * Task 9.5: Lifecycle hook called when phase ends
260
+ */
261
+ onEnd?: LifecycleHook<TState, TCardMeta>;
262
+
263
+ /**
264
+ * Task 9.7: Automatic end condition
265
+ *
266
+ * When returns true, phase automatically ends and transitions to next.
267
+ */
268
+ endIf?: EndCondition<TState, TCardMeta>;
269
+
270
+ /**
271
+ * Task 9.13: Optional steps within this phase
272
+ *
273
+ * If defined, phase will progress through steps before ending.
274
+ * Steps execute in order, then phase ends.
275
+ */
276
+ steps?: Record<string, StepDefinition<TState, TCardMeta>>;
277
+ };
278
+
279
+ /**
280
+ * Task 9.2: TurnDefinition - Defines turn structure within a game segment
281
+ *
282
+ * User requirement: "When a turn ends, the next player starts their turn"
283
+ *
284
+ * A turn is owned by a single player and consists of phases.
285
+ * When turn ends, next player starts their turn.
286
+ */
287
+ export type TurnDefinition<TState, TCardMeta = any> = {
288
+ /**
289
+ * Initial phase name (optional)
290
+ *
291
+ * If specified, turn begins at this phase.
292
+ * If not specified, uses first phase by order.
293
+ */
294
+ initialPhase?: string;
295
+ /**
296
+ * Task 9.5: Lifecycle hook called when turn begins
297
+ *
298
+ * Typically used to:
299
+ * - Switch to next player
300
+ * - Reset turn-based state
301
+ * - Draw cards, ready resources, etc.
302
+ */
303
+ onBegin?: LifecycleHook<TState, TCardMeta>;
304
+
305
+ /**
306
+ * Task 9.5: Lifecycle hook called when turn ends
307
+ *
308
+ * Typically used to:
309
+ * - Clean up turn state
310
+ * - Trigger end-of-turn effects
311
+ */
312
+ onEnd?: LifecycleHook<TState, TCardMeta>;
313
+
314
+ /**
315
+ * Task 9.7: Automatic end condition
316
+ *
317
+ * When returns true, turn automatically ends and next player's turn begins.
318
+ */
319
+ endIf?: EndCondition<TState, TCardMeta>;
320
+
321
+ /**
322
+ * Task 9.3: Phases within this turn
323
+ *
324
+ * User requirement: "phases need to be a bit more structured"
325
+ *
326
+ * Phases progress sequentially for the same player.
327
+ * Example: ready → draw → main → end
328
+ */
329
+ phases?: Record<string, PhaseDefinition<TState, TCardMeta>>;
330
+ };
331
+
332
+ /**
333
+ * GameSegmentDefinition - High-level game segments
334
+ *
335
+ * User requirement: "Segments should be higher than Turns. Segments are used to
336
+ * segment a game, for example Sideboarding segment, preparing the game segment,
337
+ * draft segment, etc..."
338
+ *
339
+ * Game segments are the highest level of game flow organization.
340
+ * Each segment can have completely different turn structures.
341
+ *
342
+ * Examples:
343
+ * - Setup/Preparation segment: Initial game setup before main game
344
+ * - Draft segment: Card drafting with unique turn structure
345
+ * - Sideboarding segment: Between-game card swapping
346
+ * - Main game segment: Primary gameplay
347
+ * - Overtime segment: Extra turns or special win conditions
348
+ */
349
+ export type GameSegmentDefinition<TState, TCardMeta = any> = {
350
+ /**
351
+ * Order/sequence number for this game segment
352
+ *
353
+ * Used for default sequential progression.
354
+ * Lower numbers execute first.
355
+ */
356
+ order: number;
357
+
358
+ /**
359
+ * Next game segment name
360
+ *
361
+ * When this game segment ends, transition to the named segment.
362
+ * If undefined, the game ends.
363
+ */
364
+ next?: string;
365
+
366
+ /**
367
+ * Lifecycle hook called when game segment begins
368
+ */
369
+ onBegin?: LifecycleHook<TState, TCardMeta>;
370
+
371
+ /**
372
+ * Lifecycle hook called when game segment ends
373
+ */
374
+ onEnd?: LifecycleHook<TState, TCardMeta>;
375
+
376
+ /**
377
+ * Automatic end condition
378
+ *
379
+ * When returns true, game segment automatically ends and transitions to next.
380
+ */
381
+ endIf?: EndCondition<TState, TCardMeta>;
382
+
383
+ /**
384
+ * Turn structure for this game segment
385
+ *
386
+ * Each game segment defines its own turn structure.
387
+ * This allows different segments (draft vs. main game) to have
388
+ * completely different turn mechanics.
389
+ */
390
+ turn: TurnDefinition<TState, TCardMeta>;
391
+ };
392
+
393
+ /**
394
+ * Task 9.1, 9.2: FlowDefinition - Complete flow orchestration
395
+ *
396
+ * User requirements:
397
+ * - "The GameEngine should pass a consistent API to all moves and flow hooks"
398
+ * - "We should have defaults, but we should also be able to customize them"
399
+ * - "The flow mechanism needs to be aware that the way we break down a turn may differ"
400
+ * - "Segments should be higher than Turns"
401
+ *
402
+ * Defines the complete game flow structure:
403
+ * - Game segment definitions (high-level game phases)
404
+ * - Turn definitions (within segments)
405
+ * - Phase definitions (within turns)
406
+ * - Step definitions (within phases)
407
+ *
408
+ * Hierarchy: GameSegments → Turns → Phases → Steps
409
+ *
410
+ * Default behaviors:
411
+ * - Game Segments: Progress sequentially by order
412
+ * - Turns: Next player starts their turn
413
+ * - Phases: Progress sequentially by order
414
+ * - Steps: Progress sequentially by order
415
+ *
416
+ * All behaviors can be customized via:
417
+ * - onBegin/onEnd hooks
418
+ * - endIf conditions
419
+ * - Programmatic control (endGameSegment/endTurn/endPhase/endStep)
420
+ *
421
+ * For simple single-segment games, you can use the simplified syntax:
422
+ * { turn: TurnDefinition }
423
+ *
424
+ * For multi-segment games, use the full syntax:
425
+ * { gameSegments: { segment1: {...}, segment2: {...} } }
426
+ */
427
+ export type FlowDefinition<TState, TCardMeta = any> =
428
+ | {
429
+ /**
430
+ * Simplified single-segment game flow (most common case)
431
+ *
432
+ * Use this for games that don't need multiple segments.
433
+ * This creates an implicit "mainGame" segment.
434
+ */
435
+ turn: TurnDefinition<TState, TCardMeta>;
436
+ }
437
+ | {
438
+ /**
439
+ * Multi-segment game flow (advanced use case)
440
+ *
441
+ * High-level divisions of the game (e.g., setup, draft, main game, sideboarding).
442
+ * Each segment can have its own turn structure.
443
+ */
444
+ gameSegments: Record<string, GameSegmentDefinition<TState, TCardMeta>>;
445
+
446
+ /**
447
+ * Initial game segment name (optional)
448
+ *
449
+ * If specified, game begins at this segment.
450
+ * If not specified, uses first segment by order.
451
+ */
452
+ initialGameSegment?: string;
453
+ };