@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.
- package/README.md +882 -0
- package/package.json +58 -0
- package/src/__tests__/alpha-clash-engine-definition.test.ts +319 -0
- package/src/__tests__/createMockAlphaClashGame.ts +462 -0
- package/src/__tests__/createMockGrandArchiveGame.ts +373 -0
- package/src/__tests__/createMockGundamGame.ts +379 -0
- package/src/__tests__/createMockLorcanaGame.ts +328 -0
- package/src/__tests__/createMockOnePieceGame.ts +429 -0
- package/src/__tests__/createMockRiftboundGame.ts +462 -0
- package/src/__tests__/grand-archive-engine-definition.test.ts +118 -0
- package/src/__tests__/gundam-engine-definition.test.ts +110 -0
- package/src/__tests__/integration-complete-game.test.ts +508 -0
- package/src/__tests__/integration-network-sync.test.ts +469 -0
- package/src/__tests__/lorcana-engine-definition.test.ts +100 -0
- package/src/__tests__/move-enumeration.test.ts +725 -0
- package/src/__tests__/multiplayer-engine.test.ts +555 -0
- package/src/__tests__/one-piece-engine-definition.test.ts +114 -0
- package/src/__tests__/riftbound-engine-definition.test.ts +124 -0
- package/src/actions/action-definition.test.ts +201 -0
- package/src/actions/action-definition.ts +122 -0
- package/src/actions/action-timing.test.ts +490 -0
- package/src/actions/action-timing.ts +257 -0
- package/src/cards/card-definition.test.ts +268 -0
- package/src/cards/card-definition.ts +27 -0
- package/src/cards/card-instance.test.ts +422 -0
- package/src/cards/card-instance.ts +49 -0
- package/src/cards/computed-properties.test.ts +530 -0
- package/src/cards/computed-properties.ts +84 -0
- package/src/cards/conditional-modifiers.test.ts +390 -0
- package/src/cards/modifiers.test.ts +286 -0
- package/src/cards/modifiers.ts +51 -0
- package/src/engine/MULTIPLAYER.md +425 -0
- package/src/engine/__tests__/rule-engine-flow.test.ts +348 -0
- package/src/engine/__tests__/rule-engine-history.test.ts +535 -0
- package/src/engine/__tests__/rule-engine-moves.test.ts +488 -0
- package/src/engine/__tests__/rule-engine.test.ts +366 -0
- package/src/engine/index.ts +14 -0
- package/src/engine/multiplayer-engine.example.ts +571 -0
- package/src/engine/multiplayer-engine.ts +409 -0
- package/src/engine/rule-engine.test.ts +286 -0
- package/src/engine/rule-engine.ts +1539 -0
- package/src/engine/tracker-system.ts +172 -0
- package/src/examples/__tests__/coin-flip-game.test.ts +641 -0
- package/src/filtering/card-filter.test.ts +230 -0
- package/src/filtering/card-filter.ts +91 -0
- package/src/filtering/card-query.test.ts +901 -0
- package/src/filtering/card-query.ts +273 -0
- package/src/filtering/filter-matching.test.ts +944 -0
- package/src/filtering/filter-matching.ts +315 -0
- package/src/flow/SERIALIZATION.md +428 -0
- package/src/flow/__tests__/flow-definition.test.ts +427 -0
- package/src/flow/__tests__/flow-manager.test.ts +756 -0
- package/src/flow/__tests__/flow-serialization.test.ts +565 -0
- package/src/flow/flow-definition.ts +453 -0
- package/src/flow/flow-manager.ts +1044 -0
- package/src/flow/index.ts +35 -0
- package/src/game-definition/__tests__/game-definition-validation.test.ts +359 -0
- package/src/game-definition/__tests__/game-definition.test.ts +291 -0
- package/src/game-definition/__tests__/move-definitions.test.ts +328 -0
- package/src/game-definition/game-definition.ts +261 -0
- package/src/game-definition/index.ts +28 -0
- package/src/game-definition/move-definitions.ts +188 -0
- package/src/game-definition/validation.ts +183 -0
- package/src/history/history-manager.test.ts +497 -0
- package/src/history/history-manager.ts +312 -0
- package/src/history/history-operations.ts +122 -0
- package/src/history/index.ts +9 -0
- package/src/history/types.ts +255 -0
- package/src/index.ts +32 -0
- package/src/logging/index.ts +27 -0
- package/src/logging/log-formatter.ts +187 -0
- package/src/logging/logger.ts +276 -0
- package/src/logging/types.ts +148 -0
- package/src/moves/create-move.test.ts +331 -0
- package/src/moves/create-move.ts +64 -0
- package/src/moves/move-enumeration.ts +228 -0
- package/src/moves/move-executor.test.ts +431 -0
- package/src/moves/move-executor.ts +195 -0
- package/src/moves/move-system.test.ts +380 -0
- package/src/moves/move-system.ts +463 -0
- package/src/moves/standard-moves.ts +231 -0
- package/src/operations/card-operations.test.ts +236 -0
- package/src/operations/card-operations.ts +116 -0
- package/src/operations/card-registry-impl.test.ts +251 -0
- package/src/operations/card-registry-impl.ts +70 -0
- package/src/operations/card-registry.test.ts +234 -0
- package/src/operations/card-registry.ts +106 -0
- package/src/operations/counter-operations.ts +152 -0
- package/src/operations/game-operations.test.ts +280 -0
- package/src/operations/game-operations.ts +140 -0
- package/src/operations/index.ts +24 -0
- package/src/operations/operations-impl.test.ts +354 -0
- package/src/operations/operations-impl.ts +468 -0
- package/src/operations/zone-operations.test.ts +295 -0
- package/src/operations/zone-operations.ts +223 -0
- package/src/rng/seeded-rng.test.ts +339 -0
- package/src/rng/seeded-rng.ts +123 -0
- package/src/targeting/index.ts +48 -0
- package/src/targeting/target-definition.test.ts +273 -0
- package/src/targeting/target-definition.ts +37 -0
- package/src/targeting/target-dsl.ts +279 -0
- package/src/targeting/target-resolver.ts +486 -0
- package/src/targeting/target-validation.test.ts +994 -0
- package/src/targeting/target-validation.ts +286 -0
- package/src/telemetry/events.ts +202 -0
- package/src/telemetry/index.ts +21 -0
- package/src/telemetry/telemetry-manager.ts +127 -0
- package/src/telemetry/types.ts +68 -0
- package/src/testing/__tests__/testing-utilities-integration.test.ts +161 -0
- package/src/testing/index.ts +88 -0
- package/src/testing/test-assertions.test.ts +341 -0
- package/src/testing/test-assertions.ts +256 -0
- package/src/testing/test-card-factory.test.ts +228 -0
- package/src/testing/test-card-factory.ts +111 -0
- package/src/testing/test-context-factory.ts +187 -0
- package/src/testing/test-end-assertions.test.ts +262 -0
- package/src/testing/test-end-assertions.ts +95 -0
- package/src/testing/test-engine-builder.test.ts +389 -0
- package/src/testing/test-engine-builder.ts +46 -0
- package/src/testing/test-flow-assertions.test.ts +284 -0
- package/src/testing/test-flow-assertions.ts +115 -0
- package/src/testing/test-player-builder.test.ts +132 -0
- package/src/testing/test-player-builder.ts +46 -0
- package/src/testing/test-replay-assertions.test.ts +356 -0
- package/src/testing/test-replay-assertions.ts +164 -0
- package/src/testing/test-rng-helpers.test.ts +260 -0
- package/src/testing/test-rng-helpers.ts +190 -0
- package/src/testing/test-state-builder.test.ts +373 -0
- package/src/testing/test-state-builder.ts +99 -0
- package/src/testing/test-zone-factory.test.ts +295 -0
- package/src/testing/test-zone-factory.ts +224 -0
- package/src/types/branded-utils.ts +54 -0
- package/src/types/branded.test.ts +175 -0
- package/src/types/branded.ts +33 -0
- package/src/types/index.ts +8 -0
- package/src/types/state.test.ts +198 -0
- package/src/types/state.ts +154 -0
- package/src/validation/card-type-guards.test.ts +242 -0
- package/src/validation/card-type-guards.ts +179 -0
- package/src/validation/index.ts +40 -0
- package/src/validation/schema-builders.test.ts +403 -0
- package/src/validation/schema-builders.ts +345 -0
- package/src/validation/type-guard-builder.test.ts +216 -0
- package/src/validation/type-guard-builder.ts +109 -0
- package/src/validation/validator-builder.test.ts +375 -0
- package/src/validation/validator-builder.ts +273 -0
- package/src/zones/index.ts +28 -0
- package/src/zones/zone-factory.test.ts +183 -0
- package/src/zones/zone-factory.ts +44 -0
- package/src/zones/zone-operations.test.ts +800 -0
- package/src/zones/zone-operations.ts +306 -0
- package/src/zones/zone-state-helpers.test.ts +337 -0
- package/src/zones/zone-state-helpers.ts +128 -0
- package/src/zones/zone-visibility.test.ts +156 -0
- package/src/zones/zone-visibility.ts +36 -0
- package/src/zones/zone.test.ts +186 -0
- 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
|
+
};
|