@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,273 @@
|
|
|
1
|
+
import type { CardDefinition } from "../cards/card-definition";
|
|
2
|
+
import type { CardInstance } from "../cards/card-instance";
|
|
3
|
+
import type { CardRegistry } from "../operations/card-registry";
|
|
4
|
+
import type { PlayerId, ZoneId } from "../types";
|
|
5
|
+
import type { CardFilter, PropertyFilter } from "./card-filter";
|
|
6
|
+
import { anyCard, countCards, selectCards } from "./filter-matching";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Fluent builder API for constructing card queries
|
|
10
|
+
* Provides chainable methods to build complex CardFilter objects
|
|
11
|
+
* @template TGameState - The game state type
|
|
12
|
+
*/
|
|
13
|
+
export class CardQuery<
|
|
14
|
+
TGameState extends { cards: Record<string, CardInstance<any>> },
|
|
15
|
+
> {
|
|
16
|
+
private filter: CardFilter<TGameState> = {};
|
|
17
|
+
|
|
18
|
+
private constructor(
|
|
19
|
+
private state: TGameState,
|
|
20
|
+
private registry: CardRegistry<CardDefinition>,
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new CardQuery builder
|
|
25
|
+
* @template TGameState - The game state type
|
|
26
|
+
* @param state - Game state containing cards
|
|
27
|
+
* @param registry - Card definition registry
|
|
28
|
+
* @returns New CardQuery instance
|
|
29
|
+
*/
|
|
30
|
+
static create<
|
|
31
|
+
TGameState extends { cards: Record<string, CardInstance<any>> },
|
|
32
|
+
>(
|
|
33
|
+
state: TGameState,
|
|
34
|
+
registry: CardRegistry<CardDefinition>,
|
|
35
|
+
): CardQuery<TGameState> {
|
|
36
|
+
return new CardQuery(state, registry);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Filter by zone(s)
|
|
41
|
+
* @param zone - Single zone or array of zones
|
|
42
|
+
* @returns this for chaining
|
|
43
|
+
*/
|
|
44
|
+
inZone(zone: ZoneId | ZoneId[]): this {
|
|
45
|
+
this.filter.zone = zone;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Filter by owner(s)
|
|
51
|
+
* @param owner - Single owner or array of owners
|
|
52
|
+
* @returns this for chaining
|
|
53
|
+
*/
|
|
54
|
+
ownedBy(owner: PlayerId | PlayerId[]): this {
|
|
55
|
+
this.filter.owner = owner;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Filter by controller(s)
|
|
61
|
+
* @param controller - Single controller or array of controllers
|
|
62
|
+
* @returns this for chaining
|
|
63
|
+
*/
|
|
64
|
+
controlledBy(controller: PlayerId | PlayerId[]): this {
|
|
65
|
+
this.filter.controller = controller;
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Filter by card type(s)
|
|
71
|
+
* @param type - Single type or array of types
|
|
72
|
+
* @returns this for chaining
|
|
73
|
+
*/
|
|
74
|
+
ofType(type: string | string[]): this {
|
|
75
|
+
this.filter.type = type;
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Filter by exact card name
|
|
81
|
+
* @param name - Card name
|
|
82
|
+
* @returns this for chaining
|
|
83
|
+
*/
|
|
84
|
+
withName(name: string): this {
|
|
85
|
+
this.filter.name = name;
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Filter by name pattern
|
|
91
|
+
* @param pattern - RegExp pattern to match
|
|
92
|
+
* @returns this for chaining
|
|
93
|
+
*/
|
|
94
|
+
withNameMatching(pattern: RegExp): this {
|
|
95
|
+
this.filter.name = pattern;
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Filter by a generic card property from the definition
|
|
101
|
+
* Works for any game-specific property:
|
|
102
|
+
* - MTG: .withProperty("basePower", { gte: 3 })
|
|
103
|
+
* - Pokemon: .withProperty("hp", { gte: 100 })
|
|
104
|
+
* - Lorcana: .withProperty("inkCost", { lte: 3 })
|
|
105
|
+
* @param propertyName - Name of the property on the card definition
|
|
106
|
+
* @param filter - Filter to apply to the property value
|
|
107
|
+
* @returns this for chaining
|
|
108
|
+
*/
|
|
109
|
+
withProperty(propertyName: string, filter: PropertyFilter): this {
|
|
110
|
+
if (!this.filter.properties) {
|
|
111
|
+
this.filter.properties = {};
|
|
112
|
+
}
|
|
113
|
+
this.filter.properties[propertyName] = filter;
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Filter for tapped/exhausted cards
|
|
119
|
+
* @returns this for chaining
|
|
120
|
+
*/
|
|
121
|
+
tapped(): this {
|
|
122
|
+
this.filter.tapped = true;
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Filter for untapped cards
|
|
128
|
+
* @returns this for chaining
|
|
129
|
+
*/
|
|
130
|
+
untapped(): this {
|
|
131
|
+
this.filter.tapped = false;
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Filter for revealed cards
|
|
137
|
+
* @returns this for chaining
|
|
138
|
+
*/
|
|
139
|
+
revealed(): this {
|
|
140
|
+
this.filter.revealed = true;
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Filter for non-revealed cards
|
|
146
|
+
* @returns this for chaining
|
|
147
|
+
*/
|
|
148
|
+
notRevealed(): this {
|
|
149
|
+
this.filter.revealed = false;
|
|
150
|
+
return this;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Filter for flipped/face-down cards
|
|
155
|
+
* @returns this for chaining
|
|
156
|
+
*/
|
|
157
|
+
flipped(): this {
|
|
158
|
+
this.filter.flipped = true;
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Filter for face-up cards
|
|
164
|
+
* @returns this for chaining
|
|
165
|
+
*/
|
|
166
|
+
faceUp(): this {
|
|
167
|
+
this.filter.flipped = false;
|
|
168
|
+
return this;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Filter for phased cards
|
|
173
|
+
* @returns this for chaining
|
|
174
|
+
*/
|
|
175
|
+
phased(): this {
|
|
176
|
+
this.filter.phased = true;
|
|
177
|
+
return this;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Filter for non-phased cards
|
|
182
|
+
* @returns this for chaining
|
|
183
|
+
*/
|
|
184
|
+
notPhased(): this {
|
|
185
|
+
this.filter.phased = false;
|
|
186
|
+
return this;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Add AND composite filter
|
|
191
|
+
* @param filters - Array of filters that must all match
|
|
192
|
+
* @returns this for chaining
|
|
193
|
+
*/
|
|
194
|
+
and(filters: CardFilter<TGameState>[]): this {
|
|
195
|
+
this.filter.and = filters;
|
|
196
|
+
return this;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Add OR composite filter
|
|
201
|
+
* @param filters - Array of filters where at least one must match
|
|
202
|
+
* @returns this for chaining
|
|
203
|
+
*/
|
|
204
|
+
or(filters: CardFilter<TGameState>[]): this {
|
|
205
|
+
this.filter.or = filters;
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Add NOT filter
|
|
211
|
+
* @param filter - Filter that must not match
|
|
212
|
+
* @returns this for chaining
|
|
213
|
+
*/
|
|
214
|
+
not(filter: CardFilter<TGameState>): this {
|
|
215
|
+
this.filter.not = filter;
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Add custom predicate filter
|
|
221
|
+
* @param predicate - Custom filter function
|
|
222
|
+
* @returns this for chaining
|
|
223
|
+
*/
|
|
224
|
+
where(
|
|
225
|
+
predicate: TGameState extends { cards: Record<string, infer TCard> }
|
|
226
|
+
? (card: TCard, state: TGameState) => boolean
|
|
227
|
+
: (card: CardInstance<unknown>, state: TGameState) => boolean,
|
|
228
|
+
): this {
|
|
229
|
+
this.filter.where = predicate;
|
|
230
|
+
return this;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Execute the query and return matching cards
|
|
235
|
+
* @returns Array of matching cards
|
|
236
|
+
*/
|
|
237
|
+
execute(): TGameState["cards"][string][] {
|
|
238
|
+
return selectCards(this.state, this.filter, this.registry);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Count the number of matching cards
|
|
243
|
+
* @returns Number of cards that match the filter
|
|
244
|
+
*/
|
|
245
|
+
count(): number {
|
|
246
|
+
return countCards(this.state, this.filter, this.registry);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Check if any card matches the filter
|
|
251
|
+
* @returns true if at least one card matches
|
|
252
|
+
*/
|
|
253
|
+
any(): boolean {
|
|
254
|
+
return anyCard(this.state, this.filter, this.registry);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Get the first matching card
|
|
259
|
+
* @returns First matching card or undefined if none match
|
|
260
|
+
*/
|
|
261
|
+
first(): TGameState["cards"][string] | undefined {
|
|
262
|
+
const results = this.execute();
|
|
263
|
+
return results[0];
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Get the current filter being built (for debugging/testing)
|
|
268
|
+
* @returns Current CardFilter
|
|
269
|
+
*/
|
|
270
|
+
getFilter(): CardFilter<TGameState> {
|
|
271
|
+
return this.filter;
|
|
272
|
+
}
|
|
273
|
+
}
|