@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,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
+ }