@drmxrcy/tcg-lorcana 0.0.0-202602060544

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 (100) hide show
  1. package/README.md +160 -0
  2. package/package.json +45 -0
  3. package/src/__tests__/integration/move-enumeration.test.ts +256 -0
  4. package/src/__tests__/rules/section-01-concepts.test.ts +426 -0
  5. package/src/__tests__/rules/section-03-gameplay.test.ts +298 -0
  6. package/src/__tests__/rules/section-04-turn-structure.test.ts +708 -0
  7. package/src/__tests__/rules/section-05-cards.test.ts +158 -0
  8. package/src/__tests__/rules/section-06-card-types.test.ts +342 -0
  9. package/src/__tests__/rules/section-07-abilities.test.ts +333 -0
  10. package/src/__tests__/rules/section-08-zones.test.ts +231 -0
  11. package/src/__tests__/rules/section-09-damage.test.ts +148 -0
  12. package/src/__tests__/rules/section-10-keywords.test.ts +469 -0
  13. package/src/__tests__/spec-01-foundation-types.test.ts +534 -0
  14. package/src/__tests__/spec-02-zones-card-states.test.ts +295 -0
  15. package/src/card-utils.ts +302 -0
  16. package/src/cards/README.md +296 -0
  17. package/src/cards/abilities/index.ts +175 -0
  18. package/src/cards/index.ts +10 -0
  19. package/src/deck-validation.ts +175 -0
  20. package/src/engine/lorcana-engine.ts +625 -0
  21. package/src/game-definition/__tests__/core-zone-integration.test.ts +553 -0
  22. package/src/game-definition/__tests__/zone-operations.test.ts +362 -0
  23. package/src/game-definition/__tests__/zones.test.ts +176 -0
  24. package/src/game-definition/definition.ts +45 -0
  25. package/src/game-definition/flow/turn-flow.ts +216 -0
  26. package/src/game-definition/index.ts +31 -0
  27. package/src/game-definition/moves/abilities/activate-ability.ts +51 -0
  28. package/src/game-definition/moves/core/__tests__/move-parameter-enumeration.test.ts +316 -0
  29. package/src/game-definition/moves/core/challenge.test.ts +545 -0
  30. package/src/game-definition/moves/core/challenge.ts +81 -0
  31. package/src/game-definition/moves/core/play-card.ts +83 -0
  32. package/src/game-definition/moves/core/quest.test.ts +448 -0
  33. package/src/game-definition/moves/core/quest.ts +49 -0
  34. package/src/game-definition/moves/debug/manual-exert.ts +36 -0
  35. package/src/game-definition/moves/effects/resolve-bag.ts +35 -0
  36. package/src/game-definition/moves/effects/resolve-effect.ts +34 -0
  37. package/src/game-definition/moves/index.ts +85 -0
  38. package/src/game-definition/moves/locations/move-character-to-location.ts +42 -0
  39. package/src/game-definition/moves/resources/put-card-into-inkwell.test.ts +462 -0
  40. package/src/game-definition/moves/resources/put-card-into-inkwell.ts +51 -0
  41. package/src/game-definition/moves/setup/alter-hand.test.ts +395 -0
  42. package/src/game-definition/moves/setup/alter-hand.ts +210 -0
  43. package/src/game-definition/moves/setup/choose-first-player.test.ts +450 -0
  44. package/src/game-definition/moves/setup/choose-first-player.ts +105 -0
  45. package/src/game-definition/moves/setup/draw-cards.ts +37 -0
  46. package/src/game-definition/moves/songs/sing-together.ts +47 -0
  47. package/src/game-definition/moves/songs/sing.ts +56 -0
  48. package/src/game-definition/moves/standard/concede.test.ts +189 -0
  49. package/src/game-definition/moves/standard/concede.ts +72 -0
  50. package/src/game-definition/moves/standard/pass-turn.ts +49 -0
  51. package/src/game-definition/setup/game-setup.ts +19 -0
  52. package/src/game-definition/trackers/tracker-config.ts +23 -0
  53. package/src/game-definition/win-conditions/lore-victory.ts +26 -0
  54. package/src/game-definition/zone-operations.ts +405 -0
  55. package/src/game-definition/zones/zone-configs.ts +59 -0
  56. package/src/game-definition/zones.ts +283 -0
  57. package/src/index.ts +189 -0
  58. package/src/operations/index.ts +7 -0
  59. package/src/operations/lorcana-operations.ts +288 -0
  60. package/src/queries/README.md +56 -0
  61. package/src/resolvers/__tests__/condition-resolver.test.ts +301 -0
  62. package/src/resolvers/condition-registry.ts +70 -0
  63. package/src/resolvers/condition-resolver.ts +85 -0
  64. package/src/resolvers/conditions/basic.ts +81 -0
  65. package/src/resolvers/conditions/card-state.ts +12 -0
  66. package/src/resolvers/conditions/comparison.ts +102 -0
  67. package/src/resolvers/conditions/existence.ts +219 -0
  68. package/src/resolvers/conditions/history.ts +68 -0
  69. package/src/resolvers/conditions/index.ts +15 -0
  70. package/src/resolvers/conditions/logical.ts +55 -0
  71. package/src/resolvers/conditions/resolution.ts +41 -0
  72. package/src/resolvers/conditions/revealed.ts +42 -0
  73. package/src/resolvers/conditions/zone.ts +84 -0
  74. package/src/setup.test.ts +18 -0
  75. package/src/targeting/__tests__/filter-resolver.test.ts +294 -0
  76. package/src/targeting/__tests__/real-cards-targeting.test.ts +303 -0
  77. package/src/targeting/__tests__/targeting-dsl.test.ts +386 -0
  78. package/src/targeting/enum-expansion.ts +387 -0
  79. package/src/targeting/filter-registry.ts +322 -0
  80. package/src/targeting/filter-resolver.ts +145 -0
  81. package/src/targeting/index.ts +91 -0
  82. package/src/targeting/lorcana-target-dsl.ts +495 -0
  83. package/src/targeting/targeting-ui.ts +407 -0
  84. package/src/testing/index.ts +14 -0
  85. package/src/testing/lorcana-test-engine.ts +813 -0
  86. package/src/types/README.md +303 -0
  87. package/src/types/__tests__/lorcana-state.test.ts +168 -0
  88. package/src/types/__tests__/move-enumeration.test.ts +179 -0
  89. package/src/types/branded-types.ts +106 -0
  90. package/src/types/game-state.ts +184 -0
  91. package/src/types/index.ts +87 -0
  92. package/src/types/keywords.ts +187 -0
  93. package/src/types/lorcana-state.ts +260 -0
  94. package/src/types/move-enumeration.ts +126 -0
  95. package/src/types/move-params.ts +216 -0
  96. package/src/validators/index.ts +7 -0
  97. package/src/validators/move-validators.ts +374 -0
  98. package/src/zones/card-state.ts +234 -0
  99. package/src/zones/index.ts +42 -0
  100. package/src/zones/zone-config.ts +150 -0
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Section 5: Cards
3
+ *
4
+ * Tests for rules 5.1 from Disney Lorcana Comprehensive Rules (Aug 22, 2025)
5
+ * Covers card conditions: Ready, Exerted, Damaged, Undamaged, Under, On Top, In a Stack.
6
+ */
7
+
8
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
9
+ import {
10
+ LorcanaTestEngine,
11
+ PLAYER_ONE,
12
+ PLAYER_TWO,
13
+ } from "../../testing/lorcana-test-engine";
14
+
15
+ describe("Section 5: Cards", () => {
16
+ let testEngine: LorcanaTestEngine;
17
+
18
+ beforeEach(() => {
19
+ testEngine = new LorcanaTestEngine(
20
+ { hand: 7, deck: 53, inkwell: 3 },
21
+ { hand: 7, deck: 53, inkwell: 3 },
22
+ { skipPreGame: true },
23
+ );
24
+ });
25
+
26
+ afterEach(() => {
27
+ testEngine.dispose();
28
+ });
29
+
30
+ describe("5.1. Conditions", () => {
31
+ /**
32
+ * Rule 5.1.1: Ready - Cards enter play ready. A player can't use any of an
33
+ * exerted card's abilities that include exert as part of the cost.
34
+ */
35
+ test.failing("Rule 5.1.1 - Cards enter play ready", () => {
36
+ // Arrange: Create a character
37
+ const character = testEngine.createCharacterInPlay(PLAYER_ONE, {
38
+ strength: 2,
39
+ willpower: 3,
40
+ });
41
+
42
+ // Assert: Should be ready (not exerted)
43
+ const meta = testEngine.getCardMeta(character);
44
+ expect(meta?.state).toBe("ready");
45
+ expect(true).toBe(false); // Will fail until ready state verified
46
+ });
47
+
48
+ /**
49
+ * Rule 5.1.1 (continued): Exerted card's exert abilities cannot be used.
50
+ */
51
+ test.failing("Rule 5.1.1 - Cannot use exert abilities when exerted", () => {
52
+ // Arrange: Create character with exert ability, then exert it
53
+ const character = testEngine.createCharacterInPlay(PLAYER_ONE, {
54
+ strength: 2,
55
+ willpower: 3,
56
+ });
57
+
58
+ // Exert by questing
59
+ testEngine.quest(character);
60
+
61
+ // Act: Try to use exert ability
62
+ // Assert: Should fail because character is exerted
63
+ expect(true).toBe(false); // Will fail until exert ability check implemented
64
+ });
65
+
66
+ /**
67
+ * Rule 5.1.2: Exerted - When a card is exerted, it's turned sideways.
68
+ * A player can use an exerted card's abilities that don't require exert.
69
+ */
70
+ test.failing("Rule 5.1.2 - Exerted cards can use non-exert abilities", () => {
71
+ // Arrange: Character with non-exert ability, exert it
72
+ const character = testEngine.createCharacterInPlay(PLAYER_ONE, {
73
+ strength: 2,
74
+ willpower: 3,
75
+ });
76
+
77
+ testEngine.quest(character);
78
+ expect(testEngine.getCardMeta(character)?.state).toBe("exerted");
79
+
80
+ // Act: Use non-exert ability
81
+ // Assert: Should succeed despite being exerted
82
+ expect(true).toBe(false); // Will fail until non-exert ability check implemented
83
+ });
84
+
85
+ /**
86
+ * Rule 5.1.3: Damaged - A card that has at least 1 damage is considered damaged.
87
+ */
88
+ test.failing("Rule 5.1.3 - Card with 1+ damage is damaged", () => {
89
+ // Arrange: Create character and give it damage
90
+ const character = testEngine.createCharacterInPlay(PLAYER_ONE, {
91
+ strength: 2,
92
+ willpower: 5,
93
+ });
94
+
95
+ // Would need a way to deal damage
96
+ // After damage dealt:
97
+ // Assert: Character should be considered "damaged"
98
+ expect(true).toBe(false); // Will fail until damage tracking implemented
99
+ });
100
+
101
+ /**
102
+ * Rule 5.1.4: Undamaged - A card that has no damage is considered undamaged.
103
+ */
104
+ test.failing("Rule 5.1.4 - Card with 0 damage is undamaged", () => {
105
+ // Arrange: Create fresh character
106
+ const character = testEngine.createCharacterInPlay(PLAYER_ONE, {
107
+ strength: 2,
108
+ willpower: 3,
109
+ });
110
+
111
+ // Assert: Should have 0 damage, be considered "undamaged"
112
+ expect(testEngine.getDamage(character)).toBe(0);
113
+ // Would need isDamaged() helper
114
+ expect(true).toBe(false); // Will fail until undamaged check implemented
115
+ });
116
+
117
+ /**
118
+ * Rule 5.1.5: Under - A card that has one or more cards on top of it is
119
+ * considered to be under the top card in a stack. A player can't choose
120
+ * any card that's under the top card.
121
+ */
122
+ test.failing("Rule 5.1.5 - Cards under others cannot be chosen", () => {
123
+ // Arrange: Create stack (e.g., Shift onto character)
124
+ // The base character is "under"
125
+
126
+ // Act: Try to target the under card
127
+
128
+ // Assert: Should not be choosable
129
+ expect(true).toBe(false); // Will fail until stack targeting implemented
130
+ });
131
+
132
+ /**
133
+ * Rule 5.1.6: On Top - A card on top of others doesn't gain the text
134
+ * of any card under it. The card on top is called the top card.
135
+ */
136
+ test.failing("Rule 5.1.6 - Top card doesn't gain text from cards under", () => {
137
+ // Arrange: Create stack via Shift
138
+ // Base card has ability X, top card has ability Y
139
+
140
+ // Assert: Top card should only have ability Y, not X
141
+ expect(true).toBe(false); // Will fail until stack text handling implemented
142
+ });
143
+
144
+ /**
145
+ * Rule 5.1.7: In a Stack - When a card is placed on top of one or more
146
+ * other cards in play, all cards are in a stack. If top card leaves play,
147
+ * all cards in stack move to the same zone.
148
+ */
149
+ test.failing("Rule 5.1.7 - Stack moves together when top card leaves", () => {
150
+ // Arrange: Create stack (Shift)
151
+
152
+ // Act: Banish the top card
153
+
154
+ // Assert: All cards in stack should go to discard together
155
+ expect(true).toBe(false); // Will fail until stack leaving play implemented
156
+ });
157
+ });
158
+ });
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Section 6: Card Types
3
+ *
4
+ * Tests for rules 6.1-6.5 from Disney Lorcana Comprehensive Rules (Aug 22, 2025)
5
+ * Covers Characters, Parts of a Card, Actions, Items, and Locations.
6
+ *
7
+ * Note: Some tests in spec-01-foundation-types.test.ts already cover card type guards.
8
+ */
9
+
10
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
11
+ import {
12
+ LorcanaTestEngine,
13
+ PLAYER_ONE,
14
+ PLAYER_TWO,
15
+ } from "../../testing/lorcana-test-engine";
16
+
17
+ describe("Section 6: Card Types", () => {
18
+ let testEngine: LorcanaTestEngine;
19
+
20
+ beforeEach(() => {
21
+ testEngine = new LorcanaTestEngine(
22
+ { hand: 7, deck: 53, inkwell: 3 },
23
+ { hand: 7, deck: 53, inkwell: 3 },
24
+ { skipPreGame: true },
25
+ );
26
+ });
27
+
28
+ afterEach(() => {
29
+ testEngine.dispose();
30
+ });
31
+
32
+ describe("6.1. Characters", () => {
33
+ /**
34
+ * Rule 6.1.1: Characters are a type of card that can be in play.
35
+ * A character card in the Play zone is a character; in other zones it's a character card.
36
+ */
37
+ test.failing("Rule 6.1.1 - Character card becomes character when in play", () => {
38
+ // Arrange: Character in hand (card) vs in play (character)
39
+
40
+ // Assert: Terminology distinction should apply
41
+ expect(true).toBe(false); // Will fail until zone-based terminology implemented
42
+ });
43
+
44
+ /**
45
+ * Rule 6.1.2.1: A character has a Strength value and a Willpower value.
46
+ */
47
+ test.failing("Rule 6.1.2.1 - Characters have Strength and Willpower", () => {
48
+ // Arrange: Create character with stats
49
+ const character = testEngine.createCharacterInPlay(PLAYER_ONE, {
50
+ strength: 3,
51
+ willpower: 4,
52
+ });
53
+
54
+ // Assert: Character should have both values accessible
55
+ // Would need getStrength/getWillpower helpers
56
+ expect(true).toBe(false); // Will fail until stat access implemented
57
+ });
58
+
59
+ /**
60
+ * Rule 6.1.2.2: A character has at least one classification
61
+ * (Storyborn, Dreamborn, Floodborn, Hero, Villain, etc.).
62
+ */
63
+ test.failing("Rule 6.1.2.2 - Characters have classifications", () => {
64
+ // Assert: Character should have at least one valid classification
65
+ expect(true).toBe(false); // Will fail until classification system implemented
66
+ });
67
+
68
+ /**
69
+ * Rule 6.1.3: Only characters can quest or challenge.
70
+ */
71
+ test.failing("Rule 6.1.3 - Only characters can quest or challenge", () => {
72
+ // Assert: Items and locations should not be able to quest/challenge
73
+ expect(true).toBe(false); // Will fail until type restrictions enforced
74
+ });
75
+
76
+ /**
77
+ * Rule 6.1.4: A character must have been in play at the beginning of the Set step
78
+ * to quest, challenge, or exert as part of a cost.
79
+ */
80
+ test.failing("Rule 6.1.4 - Fresh characters cannot quest/challenge (drying)", () => {
81
+ // Arrange: Create fresh character
82
+ const character = testEngine.createCharacterInPlay(PLAYER_ONE, {
83
+ strength: 2,
84
+ willpower: 3,
85
+ });
86
+
87
+ // Act: Try to quest immediately (this test uses a backdoor that skips drying)
88
+ // In real gameplay, fresh characters can't quest
89
+
90
+ // Assert: Should be blocked until dry
91
+ expect(true).toBe(false); // Will fail until drying properly enforced in moves
92
+ });
93
+ });
94
+
95
+ describe("6.2. Parts of a Card", () => {
96
+ /**
97
+ * Rule 6.2.3: Ink Type - The ink type of the card, identified by ink type symbol.
98
+ */
99
+ test.failing("Rule 6.2.3 - Cards have ink type", () => {
100
+ // Assert: Card should have identifiable ink type (amber, ruby, etc.)
101
+ expect(true).toBe(false); // Will fail until ink type access implemented
102
+ });
103
+
104
+ /**
105
+ * Rule 6.2.3.1: Some cards have more than one ink type (dual-ink cards).
106
+ */
107
+ test.failing("Rule 6.2.3.1 - Dual-ink cards have two ink types", () => {
108
+ // Assert: Dual-ink card should report both types
109
+ expect(true).toBe(false); // Will fail until dual-ink implemented
110
+ });
111
+
112
+ /**
113
+ * Rule 6.2.4: Name - An effect looking for a card with specified name looks
114
+ * only at this line and ignores the version. Full name = name + version.
115
+ */
116
+ test.failing("Rule 6.2.4 - Name matching ignores version", () => {
117
+ // Arrange: Effect that looks for "Elsa" should find both
118
+ // "Elsa - Ice Queen" and "Elsa - Snow Queen"
119
+
120
+ // Assert: Both versions should match
121
+ expect(true).toBe(false); // Will fail until name matching implemented
122
+ });
123
+
124
+ /**
125
+ * Rule 6.2.4.1: Some characters have two names (separated by &).
126
+ * Effect looking for specified name only needs to match one.
127
+ */
128
+ test.failing("Rule 6.2.4.1 - Dual-name characters match either name", () => {
129
+ // Arrange: "Flotsam & Jetsam" should match both "Flotsam" and "Jetsam"
130
+
131
+ // Assert: Effect targeting "Flotsam" should find this character
132
+ expect(true).toBe(false); // Will fail until dual-name matching implemented
133
+ });
134
+
135
+ /**
136
+ * Rule 6.2.4.2: A character with multiple names is still a single character.
137
+ */
138
+ test.failing("Rule 6.2.4.2 - Dual-name is one character", () => {
139
+ // Assert: Should count as 1 character, not 2
140
+ expect(true).toBe(false); // Will fail until dual-name counting verified
141
+ });
142
+
143
+ /**
144
+ * Rule 6.2.7: Card Cost - The amount of ink needed to play the card.
145
+ */
146
+ test.failing("Rule 6.2.7 - Card cost determines ink needed", () => {
147
+ // Assert: Playing card should require exerting ink equal to cost
148
+ expect(true).toBe(false); // Will fail until cost payment verified
149
+ });
150
+
151
+ /**
152
+ * Rule 6.2.8: Inkwell Symbol - If present, card can be put into inkwell.
153
+ */
154
+ test.failing("Rule 6.2.8 - Inkable cards have inkwell symbol", () => {
155
+ // Assert: Only cards with inkwell symbol can be inked
156
+ expect(true).toBe(false); // Will fail until inkable check implemented
157
+ });
158
+
159
+ /**
160
+ * Rule 6.2.9: Strength - How much damage character deals in challenge.
161
+ * If 0 or less, deals no damage.
162
+ */
163
+ test.failing("Rule 6.2.9 - Strength determines challenge damage", () => {
164
+ // Arrange: Create characters with different strengths
165
+
166
+ // Act: Challenge
167
+
168
+ // Assert: Damage dealt should equal strength
169
+ expect(true).toBe(false); // Will fail until strength-based damage verified
170
+ });
171
+
172
+ /**
173
+ * Rule 6.2.10: Willpower - If damage >= willpower, character is banished.
174
+ */
175
+ test.failing("Rule 6.2.10 - Damage >= Willpower banishes", () => {
176
+ // Arrange: Character with willpower 3
177
+
178
+ // Act: Deal 3 damage
179
+
180
+ // Assert: Character should be banished
181
+ expect(true).toBe(false); // Will fail until willpower threshold implemented
182
+ });
183
+
184
+ /**
185
+ * Rule 6.2.11: Lore Value - How much lore gained when character quests.
186
+ */
187
+ test.failing("Rule 6.2.11 - Lore value determines quest reward", () => {
188
+ // Arrange: Character with lore 2
189
+ const character = testEngine.createCharacterInPlay(PLAYER_ONE, {
190
+ strength: 2,
191
+ willpower: 3,
192
+ lore: 2,
193
+ });
194
+
195
+ // Act: Quest
196
+ testEngine.quest(character);
197
+
198
+ // Assert: Should gain 2 lore
199
+ expect(testEngine.getLore(PLAYER_ONE)).toBe(2);
200
+ expect(true).toBe(false); // Will fail until lore value properly used
201
+ });
202
+ });
203
+
204
+ describe("6.3. Actions", () => {
205
+ /**
206
+ * Rule 6.3.1: Actions are a type of card that can be played but can't be in play.
207
+ */
208
+ test.failing("Rule 6.3.1 - Actions are not in play after resolution", () => {
209
+ // Arrange: Play an action card
210
+
211
+ // Assert: Action should not be in play zone after resolving
212
+ expect(true).toBe(false); // Will fail until action zone handling implemented
213
+ });
214
+
215
+ /**
216
+ * Rule 6.3.1.2: Actions are played from hand but not considered in play.
217
+ * Effect from action doesn't enter the bag.
218
+ */
219
+ test.failing("Rule 6.3.1.2 - Action effects don't use the bag", () => {
220
+ // Arrange: Play action
221
+
222
+ // Assert: Effect should resolve immediately, not via bag
223
+ expect(true).toBe(false); // Will fail until action resolution implemented
224
+ });
225
+
226
+ /**
227
+ * Rule 6.3.2: Actions have effects rather than abilities.
228
+ */
229
+ test.failing("Rule 6.3.2 - Actions have effects, not abilities", () => {
230
+ // Terminology distinction
231
+ expect(true).toBe(false); // Will fail until effect/ability distinction implemented
232
+ });
233
+
234
+ /**
235
+ * Rule 6.3.3.3: Songs allow exerting a character to pay instead of ink cost.
236
+ * "Singer" keyword specifies minimum cost of character that can sing.
237
+ */
238
+ test.failing("Rule 6.3.3.3 - Songs can be sung by characters", () => {
239
+ // Arrange: Song with cost 4, character with Singer 4+
240
+
241
+ // Act: Exert character to play song for free
242
+
243
+ // Assert: Song should be played without paying ink
244
+ expect(true).toBe(false); // Will fail until singing implemented
245
+ });
246
+
247
+ /**
248
+ * Rule 6.3.4: Effects triggered by playing action wait until action resolves.
249
+ */
250
+ test.failing("Rule 6.3.4 - Triggers from action wait for resolution", () => {
251
+ // Arrange: Effect that triggers when action is played
252
+
253
+ // Act: Play action
254
+
255
+ // Assert: Trigger should resolve after action effect
256
+ expect(true).toBe(false); // Will fail until trigger ordering implemented
257
+ });
258
+ });
259
+
260
+ describe("6.4. Items", () => {
261
+ /**
262
+ * Rule 6.4.1: Items are a type of card that can be in play.
263
+ */
264
+ test.failing("Rule 6.4.1 - Items stay in play", () => {
265
+ // Arrange: Play an item
266
+
267
+ // Assert: Item should be in play zone
268
+ expect(true).toBe(false); // Will fail until item zone handling implemented
269
+ });
270
+
271
+ /**
272
+ * Rule 6.4.3: If an item has an ability, it can be used the turn played.
273
+ */
274
+ test.failing("Rule 6.4.3 - Item abilities usable same turn", () => {
275
+ // Arrange: Play item with activated ability
276
+
277
+ // Act: Use ability same turn
278
+
279
+ // Assert: Should work (no drying for items)
280
+ expect(true).toBe(false); // Will fail until item ability timing implemented
281
+ });
282
+ });
283
+
284
+ describe("6.5. Locations", () => {
285
+ /**
286
+ * Rule 6.5.1: Locations are a type of card that can be in play.
287
+ */
288
+ test.failing("Rule 6.5.1 - Locations stay in play", () => {
289
+ // Arrange: Play a location
290
+
291
+ // Assert: Location should be in play zone
292
+ expect(true).toBe(false); // Will fail until location zone handling implemented
293
+ });
294
+
295
+ /**
296
+ * Rule 6.5.4: Move Cost - Amount of ink needed to move a character to location.
297
+ */
298
+ test.failing("Rule 6.5.4 - Moving to location costs ink", () => {
299
+ // Arrange: Location with move cost 2
300
+
301
+ // Act: Move character to location
302
+
303
+ // Assert: Should spend 2 ink
304
+ expect(true).toBe(false); // Will fail until move cost implemented
305
+ });
306
+
307
+ /**
308
+ * Rule 6.5.5: Locations have Willpower but no Strength.
309
+ * They don't deal damage when challenged.
310
+ */
311
+ test.failing("Rule 6.5.5 - Locations have willpower, no strength", () => {
312
+ // Arrange: Challenge a location
313
+
314
+ // Assert: Attacker should take no damage from location
315
+ expect(true).toBe(false); // Will fail until location combat implemented
316
+ });
317
+
318
+ /**
319
+ * Rule 6.5.6: Location may have Lore value, gained at Set step.
320
+ */
321
+ test.failing("Rule 6.5.6 - Location lore gained at Set step", () => {
322
+ // Arrange: Location with lore 1 in play
323
+
324
+ // Act: Start turn (Set step)
325
+
326
+ // Assert: Should gain 1 lore from location
327
+ expect(true).toBe(false); // Will fail until location lore implemented
328
+ });
329
+
330
+ /**
331
+ * Rule 6.5.7: Location abilities can be used the turn played.
332
+ */
333
+ test.failing("Rule 6.5.7 - Location abilities usable same turn", () => {
334
+ // Arrange: Play location with activated ability
335
+
336
+ // Act: Use ability same turn
337
+
338
+ // Assert: Should work (no drying for locations)
339
+ expect(true).toBe(false); // Will fail until location ability timing implemented
340
+ });
341
+ });
342
+ });