@gamepark/zenith 0.1.2 → 0.1.6
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/dist/ZenithBot.d.ts +15 -0
- package/dist/ZenithBot.d.ts.map +1 -0
- package/dist/ZenithBot.js +106 -0
- package/dist/ZenithBot.js.map +1 -0
- package/dist/ZenithRules.d.ts +4 -1
- package/dist/ZenithRules.d.ts.map +1 -1
- package/dist/ZenithRules.js +6 -3
- package/dist/ZenithRules.js.map +1 -1
- package/dist/ZenithSetup.d.ts +0 -1
- package/dist/ZenithSetup.d.ts.map +1 -1
- package/dist/ZenithSetup.js +2 -16
- package/dist/ZenithSetup.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/material/Agents.d.ts +1 -2
- package/dist/material/Agents.d.ts.map +1 -1
- package/dist/material/LocationType.d.ts +2 -1
- package/dist/material/LocationType.d.ts.map +1 -1
- package/dist/material/LocationType.js +1 -0
- package/dist/material/LocationType.js.map +1 -1
- package/dist/rules/CustomMoveType.d.ts +3 -1
- package/dist/rules/CustomMoveType.d.ts.map +1 -1
- package/dist/rules/CustomMoveType.js +2 -0
- package/dist/rules/CustomMoveType.js.map +1 -1
- package/dist/rules/Memory.d.ts +7 -1
- package/dist/rules/Memory.d.ts.map +1 -1
- package/dist/rules/Memory.js +2 -0
- package/dist/rules/Memory.js.map +1 -1
- package/dist/rules/PlayCardRule.d.ts +4 -2
- package/dist/rules/PlayCardRule.d.ts.map +1 -1
- package/dist/rules/PlayCardRule.js +39 -1
- package/dist/rules/PlayCardRule.js.map +1 -1
- package/dist/rules/RefillRule.d.ts +2 -4
- package/dist/rules/RefillRule.d.ts.map +1 -1
- package/dist/rules/RefillRule.js +15 -18
- package/dist/rules/RefillRule.js.map +1 -1
- package/dist/rules/RuleId.d.ts +3 -1
- package/dist/rules/RuleId.d.ts.map +1 -1
- package/dist/rules/RuleId.js +2 -0
- package/dist/rules/RuleId.js.map +1 -1
- package/dist/rules/discard-action/DiplomacyBoardRule.d.ts +1 -0
- package/dist/rules/discard-action/DiplomacyBoardRule.d.ts.map +1 -1
- package/dist/rules/discard-action/DiplomacyBoardRule.js +7 -0
- package/dist/rules/discard-action/DiplomacyBoardRule.js.map +1 -1
- package/dist/rules/discard-action/TechnologyBoardRule.d.ts +1 -0
- package/dist/rules/discard-action/TechnologyBoardRule.d.ts.map +1 -1
- package/dist/rules/discard-action/TechnologyBoardRule.js +4 -6
- package/dist/rules/discard-action/TechnologyBoardRule.js.map +1 -1
- package/dist/rules/effect/AgentEffects.spec.d.ts +2 -0
- package/dist/rules/effect/AgentEffects.spec.d.ts.map +1 -0
- package/dist/rules/effect/AgentEffects.spec.js +703 -0
- package/dist/rules/effect/AgentEffects.spec.js.map +1 -0
- package/dist/rules/effect/EffectEdgeCases.spec.d.ts +2 -0
- package/dist/rules/effect/EffectEdgeCases.spec.d.ts.map +1 -0
- package/dist/rules/effect/EffectEdgeCases.spec.js +706 -0
- package/dist/rules/effect/EffectEdgeCases.spec.js.map +1 -0
- package/dist/rules/effect/GiveInfluenceRule.js +3 -3
- package/dist/rules/effect/GiveInfluenceRule.js.map +1 -1
- package/dist/rules/effect/MobilizeRule.d.ts +0 -1
- package/dist/rules/effect/MobilizeRule.d.ts.map +1 -1
- package/dist/rules/effect/MobilizeRule.js +32 -17
- package/dist/rules/effect/MobilizeRule.js.map +1 -1
- package/dist/rules/effect/WinInfluenceRule.d.ts +1 -0
- package/dist/rules/effect/WinInfluenceRule.d.ts.map +1 -1
- package/dist/rules/effect/WinInfluenceRule.js +42 -19
- package/dist/rules/effect/WinInfluenceRule.js.map +1 -1
- package/dist/rules/helper/DeckHelper.d.ts +9 -0
- package/dist/rules/helper/DeckHelper.d.ts.map +1 -0
- package/dist/rules/helper/DeckHelper.js +24 -0
- package/dist/rules/helper/DeckHelper.js.map +1 -0
- package/dist/rules/helper/MobilizeHelper.d.ts +1 -1
- package/dist/rules/helper/MobilizeHelper.d.ts.map +1 -1
- package/dist/rules/helper/MobilizeHelper.js +5 -6
- package/dist/rules/helper/MobilizeHelper.js.map +1 -1
- package/dist/rules/helper/PlanetHelper.d.ts +1 -0
- package/dist/rules/helper/PlanetHelper.d.ts.map +1 -1
- package/dist/rules/helper/PlanetHelper.js +13 -4
- package/dist/rules/helper/PlanetHelper.js.map +1 -1
- package/dist/rules/helper/PlayerHelper.d.ts +2 -0
- package/dist/rules/helper/PlayerHelper.d.ts.map +1 -1
- package/dist/rules/helper/PlayerHelper.js +9 -0
- package/dist/rules/helper/PlayerHelper.js.map +1 -1
- package/dist/tutorial/TutorialSetup.d.ts.map +1 -1
- package/dist/tutorial/TutorialSetup.js +0 -1
- package/dist/tutorial/TutorialSetup.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,703 @@
|
|
|
1
|
+
import { isMoveItemType } from '@gamepark/rules-api';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { Agent, agents } from '../../material/Agent';
|
|
4
|
+
import { Agents } from '../../material/Agents';
|
|
5
|
+
import { Credit } from '../../material/Credit';
|
|
6
|
+
import { Influence, influences } from '../../material/Influence';
|
|
7
|
+
import { LocationType } from '../../material/LocationType';
|
|
8
|
+
import { MaterialType } from '../../material/MaterialType';
|
|
9
|
+
import { TeamColor } from '../../TeamColor';
|
|
10
|
+
import { Memory } from '../Memory';
|
|
11
|
+
import { RuleId } from '../RuleId';
|
|
12
|
+
import { ZenithRules } from '../../ZenithRules';
|
|
13
|
+
import { ZenithSetup } from '../../ZenithSetup';
|
|
14
|
+
const player1 = 1;
|
|
15
|
+
const player2 = 2;
|
|
16
|
+
function createGameForAgent(agent) {
|
|
17
|
+
const setup = new TestSetup(agent);
|
|
18
|
+
const game = setup.setup({ players: 2 });
|
|
19
|
+
return new ZenithRules(game);
|
|
20
|
+
}
|
|
21
|
+
class TestSetup extends ZenithSetup {
|
|
22
|
+
testAgent;
|
|
23
|
+
constructor(testAgent) {
|
|
24
|
+
super();
|
|
25
|
+
this.testAgent = testAgent;
|
|
26
|
+
}
|
|
27
|
+
setupMaterial() {
|
|
28
|
+
this.setupTurnOrder();
|
|
29
|
+
this.setupTestHands();
|
|
30
|
+
this.setupRemainingDeck();
|
|
31
|
+
this.setupInfluences();
|
|
32
|
+
this.setupLeaderBadge();
|
|
33
|
+
this.setupTechnologyBoard();
|
|
34
|
+
this.setupTeams();
|
|
35
|
+
this.setupTestBonuses();
|
|
36
|
+
}
|
|
37
|
+
setupTurnOrder() {
|
|
38
|
+
this.memorize(Memory.TurnOrder, [player1, player2]);
|
|
39
|
+
}
|
|
40
|
+
setupTestHands() {
|
|
41
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
42
|
+
id: this.testAgent,
|
|
43
|
+
location: { type: LocationType.PlayerHand, player: player1 }
|
|
44
|
+
});
|
|
45
|
+
const fillers = agents.filter(a => a !== this.testAgent).slice(0, 3);
|
|
46
|
+
for (const agent of fillers) {
|
|
47
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
48
|
+
id: agent,
|
|
49
|
+
location: { type: LocationType.PlayerHand, player: player1 }
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const p2Fillers = agents.filter(a => a !== this.testAgent && !fillers.includes(a)).slice(0, 4);
|
|
53
|
+
for (const agent of p2Fillers) {
|
|
54
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
55
|
+
id: agent,
|
|
56
|
+
location: { type: LocationType.PlayerHand, player: player2 }
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
setupRemainingDeck() {
|
|
61
|
+
const usedAgents = new Set([
|
|
62
|
+
this.testAgent,
|
|
63
|
+
...agents.filter(a => a !== this.testAgent).slice(0, 7)
|
|
64
|
+
]);
|
|
65
|
+
const remaining = agents.filter(a => !usedAgents.has(a));
|
|
66
|
+
for (const agent of remaining) {
|
|
67
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
68
|
+
id: agent,
|
|
69
|
+
location: { type: LocationType.AgentDeck }
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
setupPlayers() { }
|
|
74
|
+
setupInfluences() {
|
|
75
|
+
for (const planet of influences) {
|
|
76
|
+
this.material(MaterialType.InfluenceDisc).createItem({
|
|
77
|
+
id: planet,
|
|
78
|
+
location: {
|
|
79
|
+
type: LocationType.PlanetBoardInfluenceDiscSpace,
|
|
80
|
+
id: planet,
|
|
81
|
+
x: planet === Influence.Venus ? 1 : 0
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
setupTestBonuses() {
|
|
87
|
+
const bonusIds = [1, 2, 3, 4, 5];
|
|
88
|
+
for (let i = 0; i < influences.length; i++) {
|
|
89
|
+
this.material(MaterialType.BonusToken).createItem({
|
|
90
|
+
id: bonusIds[i],
|
|
91
|
+
location: { type: LocationType.PlanetBoardBonusSpace, id: influences[i] }
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const techBoards = this.material(MaterialType.TechnologyBoard).getIndexes();
|
|
95
|
+
for (const boardIndex of techBoards) {
|
|
96
|
+
this.material(MaterialType.BonusToken).createItem({
|
|
97
|
+
id: bonusIds.length + boardIndex + 1,
|
|
98
|
+
location: { type: LocationType.TechnologyBoardBonusSpace, parent: boardIndex, x: 2 }
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
setupTeams() {
|
|
103
|
+
for (const team of [TeamColor.White, TeamColor.Black]) {
|
|
104
|
+
this.material(MaterialType.CreditToken).createItem({
|
|
105
|
+
id: Credit.Credit1,
|
|
106
|
+
location: { type: LocationType.TeamCredit, player: team },
|
|
107
|
+
quantity: 10
|
|
108
|
+
});
|
|
109
|
+
this.material(MaterialType.CreditToken).createItem({
|
|
110
|
+
id: Credit.Credit5,
|
|
111
|
+
location: { type: LocationType.TeamCredit, player: team }
|
|
112
|
+
});
|
|
113
|
+
this.material(MaterialType.ZenithiumToken).createItem({
|
|
114
|
+
location: { type: LocationType.TeamZenithium, player: team },
|
|
115
|
+
quantity: 3
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
start() {
|
|
120
|
+
this.startPlayerTurn(RuleId.PlayCard, player1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function playConsequences(rules, move) {
|
|
124
|
+
const consequences = rules.play(move);
|
|
125
|
+
while (consequences.length > 0) {
|
|
126
|
+
consequences.push(...rules.play(consequences.shift()));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function resolveAutoMoves(rules) {
|
|
130
|
+
let autoMoves = rules.getAutomaticMoves();
|
|
131
|
+
while (autoMoves.length > 0) {
|
|
132
|
+
for (const auto of autoMoves) {
|
|
133
|
+
playConsequences(rules, auto);
|
|
134
|
+
}
|
|
135
|
+
autoMoves = rules.getAutomaticMoves();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function playAgentAndResolveEffects(rules, agent) {
|
|
139
|
+
const cardIndex = rules.material(MaterialType.AgentCard)
|
|
140
|
+
.location(LocationType.PlayerHand)
|
|
141
|
+
.player(player1)
|
|
142
|
+
.id(agent)
|
|
143
|
+
.getIndex();
|
|
144
|
+
if (cardIndex === undefined) {
|
|
145
|
+
return { error: `Agent ${Agent[agent]} not found in player1 hand` };
|
|
146
|
+
}
|
|
147
|
+
const agentData = Agents[agent];
|
|
148
|
+
const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
|
|
149
|
+
type: LocationType.Influence,
|
|
150
|
+
id: agentData.influence,
|
|
151
|
+
player: TeamColor.White
|
|
152
|
+
});
|
|
153
|
+
playConsequences(rules, playMove);
|
|
154
|
+
resolveAutoMoves(rules);
|
|
155
|
+
let iterations = 0;
|
|
156
|
+
const maxIterations = 50;
|
|
157
|
+
while (iterations < maxIterations) {
|
|
158
|
+
const ruleId = rules.game.rule?.id;
|
|
159
|
+
if (ruleId === RuleId.Refill || ruleId === RuleId.PlayCard) {
|
|
160
|
+
return { finalRule: ruleId };
|
|
161
|
+
}
|
|
162
|
+
if (rules.game.rule === undefined) {
|
|
163
|
+
return { finalRule: undefined };
|
|
164
|
+
}
|
|
165
|
+
const legalMoves = rules.getLegalMoves(player1);
|
|
166
|
+
if (legalMoves.length === 0) {
|
|
167
|
+
resolveAutoMoves(rules);
|
|
168
|
+
const newRuleId = rules.game.rule?.id;
|
|
169
|
+
if (newRuleId === RuleId.Refill || newRuleId === RuleId.PlayCard || newRuleId === undefined) {
|
|
170
|
+
return { finalRule: newRuleId };
|
|
171
|
+
}
|
|
172
|
+
const p2Moves = rules.getLegalMoves(player2);
|
|
173
|
+
if (p2Moves.length > 0) {
|
|
174
|
+
return { finalRule: ruleId };
|
|
175
|
+
}
|
|
176
|
+
return { error: `No legal moves and no auto moves at rule ${RuleId[ruleId] ?? ruleId}` };
|
|
177
|
+
}
|
|
178
|
+
playConsequences(rules, legalMoves[0]);
|
|
179
|
+
resolveAutoMoves(rules);
|
|
180
|
+
iterations++;
|
|
181
|
+
}
|
|
182
|
+
return { error: `Max iterations reached at rule ${RuleId[rules.game.rule?.id] ?? rules.game.rule?.id}` };
|
|
183
|
+
}
|
|
184
|
+
describe('Agent effects resolution', () => {
|
|
185
|
+
for (const agent of agents) {
|
|
186
|
+
const agentName = Agent[agent];
|
|
187
|
+
const agentData = Agents[agent];
|
|
188
|
+
it(`${agentName} (cost ${agentData.cost}, ${agentData.effects.length} effects) should resolve all effects without error`, () => {
|
|
189
|
+
const rules = createGameForAgent(agent);
|
|
190
|
+
expect(rules.game.rule?.id).toBe(RuleId.PlayCard);
|
|
191
|
+
expect(rules.getActivePlayer()).toBe(player1);
|
|
192
|
+
const result = playAgentAndResolveEffects(rules, agent);
|
|
193
|
+
expect(result.error).toBeUndefined();
|
|
194
|
+
expect(result.finalRule).toBeDefined();
|
|
195
|
+
if (result.finalRule !== undefined) {
|
|
196
|
+
expect([RuleId.Refill, RuleId.PlayCard]).toContain(result.finalRule);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
describe('Gilgamesh opponentSide fallback', () => {
|
|
202
|
+
it('should allow pulling a different planet when the only opponent-side planet was pulled across by effect 2', () => {
|
|
203
|
+
const setup = new GilgameshTestSetup();
|
|
204
|
+
const game = setup.setup({ players: 2 });
|
|
205
|
+
const rules = new ZenithRules(game);
|
|
206
|
+
const venusStart = rules.material(MaterialType.InfluenceDisc)
|
|
207
|
+
.location(LocationType.PlanetBoardInfluenceDiscSpace)
|
|
208
|
+
.id(Influence.Venus).getItem();
|
|
209
|
+
expect(venusStart.location.x).toBe(-1);
|
|
210
|
+
const cardIndex = rules.material(MaterialType.AgentCard)
|
|
211
|
+
.location(LocationType.PlayerHand).player(player1).id(Agent.Gilgamesh).getIndex();
|
|
212
|
+
const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
|
|
213
|
+
type: LocationType.Influence,
|
|
214
|
+
id: Influence.Terra,
|
|
215
|
+
player: TeamColor.White
|
|
216
|
+
});
|
|
217
|
+
playConsequences(rules, playMove);
|
|
218
|
+
resolveAutoMoves(rules);
|
|
219
|
+
let iterations = 0;
|
|
220
|
+
while (iterations < 20) {
|
|
221
|
+
const ruleId = rules.game.rule?.id;
|
|
222
|
+
if (ruleId === RuleId.Refill || ruleId === RuleId.PlayCard)
|
|
223
|
+
break;
|
|
224
|
+
const moves = rules.getLegalMoves(player1);
|
|
225
|
+
if (moves.length === 0) {
|
|
226
|
+
resolveAutoMoves(rules);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
playConsequences(rules, moves[0]);
|
|
230
|
+
resolveAutoMoves(rules);
|
|
231
|
+
iterations++;
|
|
232
|
+
}
|
|
233
|
+
expect([RuleId.Refill, RuleId.PlayCard]).toContain(rules.game.rule?.id);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
describe('Planet capture', () => {
|
|
237
|
+
it('White pulling a planet at x=3 should capture it at x=4 into White TeamPlanets', () => {
|
|
238
|
+
const setup = new CaptureTestSetup(Agent.Mc4ffr3y, Influence.Mars, 3);
|
|
239
|
+
const game = setup.setup({ players: 2 });
|
|
240
|
+
const rules = new ZenithRules(game);
|
|
241
|
+
const marsStart = rules.material(MaterialType.InfluenceDisc)
|
|
242
|
+
.location(LocationType.PlanetBoardInfluenceDiscSpace)
|
|
243
|
+
.id(Influence.Mars).getItem();
|
|
244
|
+
expect(marsStart.location.x).toBe(3);
|
|
245
|
+
const cardIndex = rules.material(MaterialType.AgentCard)
|
|
246
|
+
.location(LocationType.PlayerHand).player(player1).id(Agent.Mc4ffr3y).getIndex();
|
|
247
|
+
const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
|
|
248
|
+
type: LocationType.Influence,
|
|
249
|
+
id: Influence.Mars,
|
|
250
|
+
player: TeamColor.White
|
|
251
|
+
});
|
|
252
|
+
playConsequences(rules, playMove);
|
|
253
|
+
resolveAutoMoves(rules);
|
|
254
|
+
let iterations = 0;
|
|
255
|
+
while (iterations < 20) {
|
|
256
|
+
const ruleId = rules.game.rule?.id;
|
|
257
|
+
if (ruleId === RuleId.Refill || ruleId === RuleId.PlayCard)
|
|
258
|
+
break;
|
|
259
|
+
if (rules.game.rule === undefined)
|
|
260
|
+
break;
|
|
261
|
+
const moves = rules.getLegalMoves(player1);
|
|
262
|
+
if (moves.length === 0) {
|
|
263
|
+
resolveAutoMoves(rules);
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
playConsequences(rules, moves[0]);
|
|
267
|
+
resolveAutoMoves(rules);
|
|
268
|
+
iterations++;
|
|
269
|
+
}
|
|
270
|
+
const marsInWhite = rules.material(MaterialType.InfluenceDisc)
|
|
271
|
+
.location(LocationType.TeamPlanets)
|
|
272
|
+
.player(TeamColor.White)
|
|
273
|
+
.id(Influence.Mars);
|
|
274
|
+
expect(marsInWhite.length).toBe(1);
|
|
275
|
+
const marsInBlack = rules.material(MaterialType.InfluenceDisc)
|
|
276
|
+
.location(LocationType.TeamPlanets)
|
|
277
|
+
.player(TeamColor.Black)
|
|
278
|
+
.id(Influence.Mars);
|
|
279
|
+
expect(marsInBlack.length).toBe(0);
|
|
280
|
+
const marsOnBoard = rules.material(MaterialType.InfluenceDisc)
|
|
281
|
+
.location(LocationType.PlanetBoardInfluenceDiscSpace)
|
|
282
|
+
.id(Influence.Mars);
|
|
283
|
+
expect(marsOnBoard.length).toBe(1);
|
|
284
|
+
expect(marsOnBoard.getItem().location.x).toBe(0);
|
|
285
|
+
});
|
|
286
|
+
it('Black pulling a planet at x=-3 should capture it at x=-4 into Black TeamPlanets', () => {
|
|
287
|
+
const setup = new CaptureTestSetupBlack(Agent.Mc4ffr3y, Influence.Mars, -3);
|
|
288
|
+
const game = setup.setup({ players: 2 });
|
|
289
|
+
const rules = new ZenithRules(game);
|
|
290
|
+
const marsStart = rules.material(MaterialType.InfluenceDisc)
|
|
291
|
+
.location(LocationType.PlanetBoardInfluenceDiscSpace)
|
|
292
|
+
.id(Influence.Mars).getItem();
|
|
293
|
+
expect(marsStart.location.x).toBe(-3);
|
|
294
|
+
const cardIndex = rules.material(MaterialType.AgentCard)
|
|
295
|
+
.location(LocationType.PlayerHand).player(player2).id(Agent.Mc4ffr3y).getIndex();
|
|
296
|
+
const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
|
|
297
|
+
type: LocationType.Influence,
|
|
298
|
+
id: Influence.Mars,
|
|
299
|
+
player: TeamColor.Black
|
|
300
|
+
});
|
|
301
|
+
playConsequences(rules, playMove);
|
|
302
|
+
resolveAutoMoves(rules);
|
|
303
|
+
let iterations = 0;
|
|
304
|
+
while (iterations < 20) {
|
|
305
|
+
const ruleId = rules.game.rule?.id;
|
|
306
|
+
if (ruleId === RuleId.Refill || ruleId === RuleId.PlayCard)
|
|
307
|
+
break;
|
|
308
|
+
if (rules.game.rule === undefined)
|
|
309
|
+
break;
|
|
310
|
+
const moves = rules.getLegalMoves(player2);
|
|
311
|
+
if (moves.length === 0) {
|
|
312
|
+
resolveAutoMoves(rules);
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
playConsequences(rules, moves[0]);
|
|
316
|
+
resolveAutoMoves(rules);
|
|
317
|
+
iterations++;
|
|
318
|
+
}
|
|
319
|
+
const marsInBlack = rules.material(MaterialType.InfluenceDisc)
|
|
320
|
+
.location(LocationType.TeamPlanets)
|
|
321
|
+
.player(TeamColor.Black)
|
|
322
|
+
.id(Influence.Mars);
|
|
323
|
+
expect(marsInBlack.length).toBe(1);
|
|
324
|
+
const marsInWhite = rules.material(MaterialType.InfluenceDisc)
|
|
325
|
+
.location(LocationType.TeamPlanets)
|
|
326
|
+
.player(TeamColor.White)
|
|
327
|
+
.id(Influence.Mars);
|
|
328
|
+
expect(marsInWhite.length).toBe(0);
|
|
329
|
+
const marsOnBoard = rules.material(MaterialType.InfluenceDisc)
|
|
330
|
+
.location(LocationType.PlanetBoardInfluenceDiscSpace)
|
|
331
|
+
.id(Influence.Mars);
|
|
332
|
+
expect(marsOnBoard.length).toBe(1);
|
|
333
|
+
expect(marsOnBoard.getItem().location.x).toBe(0);
|
|
334
|
+
});
|
|
335
|
+
it('White pushing Terra at x=-3 should capture it at x=-4 into Black TeamPlanets (opponent)', () => {
|
|
336
|
+
const setup = new CaptureTestSetup(Agent.Titus, Influence.Terra, -3);
|
|
337
|
+
const game = setup.setup({ players: 2 });
|
|
338
|
+
const rules = new ZenithRules(game);
|
|
339
|
+
const terraStart = rules.material(MaterialType.InfluenceDisc)
|
|
340
|
+
.location(LocationType.PlanetBoardInfluenceDiscSpace)
|
|
341
|
+
.id(Influence.Terra).getItem();
|
|
342
|
+
expect(terraStart.location.x).toBe(-3);
|
|
343
|
+
const cardIndex = rules.material(MaterialType.AgentCard)
|
|
344
|
+
.location(LocationType.PlayerHand).player(player1).id(Agent.Titus).getIndex();
|
|
345
|
+
const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
|
|
346
|
+
type: LocationType.Influence,
|
|
347
|
+
id: Agents[Agent.Titus].influence,
|
|
348
|
+
player: TeamColor.White
|
|
349
|
+
});
|
|
350
|
+
playConsequences(rules, playMove);
|
|
351
|
+
resolveAutoMoves(rules);
|
|
352
|
+
let iterations = 0;
|
|
353
|
+
while (iterations < 30) {
|
|
354
|
+
const ruleId = rules.game.rule?.id;
|
|
355
|
+
if (ruleId === RuleId.Refill || ruleId === RuleId.PlayCard)
|
|
356
|
+
break;
|
|
357
|
+
if (rules.game.rule === undefined)
|
|
358
|
+
break;
|
|
359
|
+
const moves = rules.getLegalMoves(player1);
|
|
360
|
+
if (moves.length === 0) {
|
|
361
|
+
resolveAutoMoves(rules);
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
const terraPush = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
|
|
365
|
+
rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Terra);
|
|
366
|
+
playConsequences(rules, terraPush ?? moves[0]);
|
|
367
|
+
resolveAutoMoves(rules);
|
|
368
|
+
iterations++;
|
|
369
|
+
}
|
|
370
|
+
const terraInBlack = rules.material(MaterialType.InfluenceDisc)
|
|
371
|
+
.location(LocationType.TeamPlanets)
|
|
372
|
+
.player(TeamColor.Black)
|
|
373
|
+
.id(Influence.Terra);
|
|
374
|
+
expect(terraInBlack.length).toBe(1);
|
|
375
|
+
const terraInWhite = rules.material(MaterialType.InfluenceDisc)
|
|
376
|
+
.location(LocationType.TeamPlanets)
|
|
377
|
+
.player(TeamColor.White)
|
|
378
|
+
.id(Influence.Terra);
|
|
379
|
+
expect(terraInWhite.length).toBe(0);
|
|
380
|
+
const terraOnBoard = rules.material(MaterialType.InfluenceDisc)
|
|
381
|
+
.location(LocationType.PlanetBoardInfluenceDiscSpace)
|
|
382
|
+
.id(Influence.Terra);
|
|
383
|
+
expect(terraOnBoard.length).toBe(1);
|
|
384
|
+
expect(terraOnBoard.getItem().location.x).toBe(0);
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
class CaptureTestSetup extends TestSetup {
|
|
388
|
+
captureTargetPlanet;
|
|
389
|
+
captureTargetX;
|
|
390
|
+
constructor(agent, targetPlanet, targetX) {
|
|
391
|
+
super(agent);
|
|
392
|
+
this.captureTargetPlanet = targetPlanet;
|
|
393
|
+
this.captureTargetX = targetX;
|
|
394
|
+
}
|
|
395
|
+
setupInfluences() {
|
|
396
|
+
for (const planet of influences) {
|
|
397
|
+
const x = planet === this.captureTargetPlanet ? this.captureTargetX : 0;
|
|
398
|
+
this.material(MaterialType.InfluenceDisc).createItem({
|
|
399
|
+
id: planet,
|
|
400
|
+
location: {
|
|
401
|
+
type: LocationType.PlanetBoardInfluenceDiscSpace,
|
|
402
|
+
id: planet,
|
|
403
|
+
x
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
class CaptureTestSetupBlack extends CaptureTestSetup {
|
|
410
|
+
setupTurnOrder() {
|
|
411
|
+
this.memorize(Memory.TurnOrder, [player2, player1]);
|
|
412
|
+
}
|
|
413
|
+
setupTestHands() {
|
|
414
|
+
const testAgent = agents.find(a => a === Agent.Mc4ffr3y);
|
|
415
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
416
|
+
id: testAgent,
|
|
417
|
+
location: { type: LocationType.PlayerHand, player: player2 }
|
|
418
|
+
});
|
|
419
|
+
const fillers = agents.filter(a => a !== testAgent).slice(0, 3);
|
|
420
|
+
for (const agent of fillers) {
|
|
421
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
422
|
+
id: agent,
|
|
423
|
+
location: { type: LocationType.PlayerHand, player: player2 }
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
const p1Fillers = agents.filter(a => a !== testAgent && !fillers.includes(a)).slice(0, 4);
|
|
427
|
+
for (const agent of p1Fillers) {
|
|
428
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
429
|
+
id: agent,
|
|
430
|
+
location: { type: LocationType.PlayerHand, player: player1 }
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
start() {
|
|
435
|
+
this.startPlayerTurn(RuleId.PlayCard, player2);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
class GilgameshTestSetup extends TestSetup {
|
|
439
|
+
constructor() {
|
|
440
|
+
super(Agent.Gilgamesh);
|
|
441
|
+
}
|
|
442
|
+
setupInfluences() {
|
|
443
|
+
for (const planet of influences) {
|
|
444
|
+
this.material(MaterialType.InfluenceDisc).createItem({
|
|
445
|
+
id: planet,
|
|
446
|
+
location: {
|
|
447
|
+
type: LocationType.PlanetBoardInfluenceDiscSpace,
|
|
448
|
+
id: planet,
|
|
449
|
+
x: planet === Influence.Venus ? -1 : 0
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
describe('Refill with low/empty deck', () => {
|
|
456
|
+
function createRefillSetup(deckCount) {
|
|
457
|
+
const setup = new RefillTestSetup(deckCount);
|
|
458
|
+
const game = setup.setup({ players: 2 });
|
|
459
|
+
return new ZenithRules(game);
|
|
460
|
+
}
|
|
461
|
+
function discardAndRefill(rules) {
|
|
462
|
+
const hand = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1);
|
|
463
|
+
const discardMove = hand.moveItems({ type: LocationType.AgentDiscard })[0];
|
|
464
|
+
playConsequences(rules, discardMove);
|
|
465
|
+
resolveAutoMoves(rules);
|
|
466
|
+
let iterations = 0;
|
|
467
|
+
while (iterations < 30) {
|
|
468
|
+
const ruleId = rules.game.rule?.id;
|
|
469
|
+
if (ruleId === RuleId.PlayCard && rules.getActivePlayer() === player2)
|
|
470
|
+
break;
|
|
471
|
+
if (ruleId === undefined)
|
|
472
|
+
break;
|
|
473
|
+
const moves = rules.getLegalMoves(rules.getActivePlayer());
|
|
474
|
+
if (moves.length === 0) {
|
|
475
|
+
resolveAutoMoves(rules);
|
|
476
|
+
if (rules.game.rule?.id === RuleId.PlayCard && rules.getActivePlayer() === player2)
|
|
477
|
+
break;
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
playConsequences(rules, moves[0]);
|
|
481
|
+
resolveAutoMoves(rules);
|
|
482
|
+
iterations++;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
it('deck=0: should reshuffle discard and refill hand to 4', () => {
|
|
486
|
+
const rules = createRefillSetup(0);
|
|
487
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(0);
|
|
488
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDiscard).length).toBeGreaterThan(0);
|
|
489
|
+
discardAndRefill(rules);
|
|
490
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).length).toBe(4);
|
|
491
|
+
expect(rules.game.rule?.id).toBe(RuleId.PlayCard);
|
|
492
|
+
expect(rules.getActivePlayer()).toBe(player2);
|
|
493
|
+
});
|
|
494
|
+
it('deck=1: should deal 1 from deck then reshuffle discard for remaining', () => {
|
|
495
|
+
const rules = createRefillSetup(1);
|
|
496
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(1);
|
|
497
|
+
discardAndRefill(rules);
|
|
498
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).length).toBe(4);
|
|
499
|
+
expect(rules.game.rule?.id).toBe(RuleId.PlayCard);
|
|
500
|
+
expect(rules.getActivePlayer()).toBe(player2);
|
|
501
|
+
});
|
|
502
|
+
it('deck=2: should deal 2 from deck then reshuffle discard for remaining', () => {
|
|
503
|
+
const rules = createRefillSetup(2);
|
|
504
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(2);
|
|
505
|
+
discardAndRefill(rules);
|
|
506
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).length).toBe(4);
|
|
507
|
+
expect(rules.game.rule?.id).toBe(RuleId.PlayCard);
|
|
508
|
+
expect(rules.getActivePlayer()).toBe(player2);
|
|
509
|
+
});
|
|
510
|
+
it('deck has exactly the needed amount: should refill without reshuffle', () => {
|
|
511
|
+
const rules = createRefillSetup(1);
|
|
512
|
+
discardAndRefill(rules);
|
|
513
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).length).toBe(4);
|
|
514
|
+
expect(rules.game.rule?.id).toBe(RuleId.PlayCard);
|
|
515
|
+
});
|
|
516
|
+
it('deck=0 after playing to influence (not discard): should still refill', () => {
|
|
517
|
+
const rules = createRefillSetup(0);
|
|
518
|
+
const hand = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1);
|
|
519
|
+
const cardIndex = hand.getIndex();
|
|
520
|
+
const card = hand.getItem(cardIndex);
|
|
521
|
+
const agentData = Agents[card.id];
|
|
522
|
+
const influenceMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
|
|
523
|
+
type: LocationType.Influence,
|
|
524
|
+
id: agentData.influence,
|
|
525
|
+
player: TeamColor.White
|
|
526
|
+
});
|
|
527
|
+
playConsequences(rules, influenceMove);
|
|
528
|
+
resolveAutoMoves(rules);
|
|
529
|
+
let iterations = 0;
|
|
530
|
+
while (iterations < 30) {
|
|
531
|
+
const ruleId = rules.game.rule?.id;
|
|
532
|
+
if (ruleId === RuleId.PlayCard && rules.getActivePlayer() === player2)
|
|
533
|
+
break;
|
|
534
|
+
if (ruleId === undefined)
|
|
535
|
+
break;
|
|
536
|
+
const moves = rules.getLegalMoves(rules.getActivePlayer());
|
|
537
|
+
if (moves.length === 0) {
|
|
538
|
+
resolveAutoMoves(rules);
|
|
539
|
+
if (rules.game.rule?.id === RuleId.PlayCard && rules.getActivePlayer() === player2)
|
|
540
|
+
break;
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
playConsequences(rules, moves[0]);
|
|
544
|
+
resolveAutoMoves(rules);
|
|
545
|
+
iterations++;
|
|
546
|
+
}
|
|
547
|
+
const p1HandAfter = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).length;
|
|
548
|
+
expect(p1HandAfter).toBe(4);
|
|
549
|
+
expect(rules.game.rule?.id).toBe(RuleId.PlayCard);
|
|
550
|
+
expect(rules.getActivePlayer()).toBe(player2);
|
|
551
|
+
});
|
|
552
|
+
it('deck has more than needed: normal refill', () => {
|
|
553
|
+
const rules = createRefillSetup(10);
|
|
554
|
+
discardAndRefill(rules);
|
|
555
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).length).toBe(4);
|
|
556
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(9);
|
|
557
|
+
expect(rules.game.rule?.id).toBe(RuleId.PlayCard);
|
|
558
|
+
});
|
|
559
|
+
});
|
|
560
|
+
describe('Mobilize with low/empty deck', () => {
|
|
561
|
+
function createMobilizeSetup(deckCount) {
|
|
562
|
+
const setup = new MobilizeTestSetup(deckCount);
|
|
563
|
+
const game = setup.setup({ players: 2 });
|
|
564
|
+
return new ZenithRules(game);
|
|
565
|
+
}
|
|
566
|
+
it('mobilize 2 with deck=1: should reshuffle discard and mobilize second card', () => {
|
|
567
|
+
const rules = createMobilizeSetup(1);
|
|
568
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(1);
|
|
569
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDiscard).length).toBeGreaterThan(0);
|
|
570
|
+
playAgentAndResolveEffects(rules, Agent.H4milt0n);
|
|
571
|
+
const mobilized = rules.material(MaterialType.AgentCard).location(LocationType.Influence).player(TeamColor.White);
|
|
572
|
+
expect(mobilized.length).toBe(3);
|
|
573
|
+
});
|
|
574
|
+
it('mobilize 2 with deck=0: should reshuffle discard and mobilize both', () => {
|
|
575
|
+
const rules = createMobilizeSetup(0);
|
|
576
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(0);
|
|
577
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDiscard).length).toBeGreaterThan(0);
|
|
578
|
+
playAgentAndResolveEffects(rules, Agent.H4milt0n);
|
|
579
|
+
const mobilized = rules.material(MaterialType.AgentCard).location(LocationType.Influence).player(TeamColor.White);
|
|
580
|
+
expect(mobilized.length).toBe(3);
|
|
581
|
+
});
|
|
582
|
+
it('mobilize 2 with deck=0 and discard=0: should skip mobilization without blocking', () => {
|
|
583
|
+
const setup = new MobilizeEmptySetup();
|
|
584
|
+
const game = setup.setup({ players: 2 });
|
|
585
|
+
const rules = new ZenithRules(game);
|
|
586
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(0);
|
|
587
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDiscard).length).toBe(0);
|
|
588
|
+
const result = playAgentAndResolveEffects(rules, Agent.H4milt0n);
|
|
589
|
+
expect(result.error).toBeUndefined();
|
|
590
|
+
expect(result.finalRule).toBeDefined();
|
|
591
|
+
const mobilized = rules.material(MaterialType.AgentCard).location(LocationType.Influence).player(TeamColor.White);
|
|
592
|
+
expect(mobilized.length).toBe(1);
|
|
593
|
+
});
|
|
594
|
+
it('mobilize 2 with deck=1 and discard=0: should mobilize 1 then skip remaining', () => {
|
|
595
|
+
const setup = new MobilizePartialSetup(1);
|
|
596
|
+
const game = setup.setup({ players: 2 });
|
|
597
|
+
const rules = new ZenithRules(game);
|
|
598
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(1);
|
|
599
|
+
expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDiscard).length).toBe(0);
|
|
600
|
+
const result = playAgentAndResolveEffects(rules, Agent.H4milt0n);
|
|
601
|
+
expect(result.error).toBeUndefined();
|
|
602
|
+
expect(result.finalRule).toBeDefined();
|
|
603
|
+
const mobilized = rules.material(MaterialType.AgentCard).location(LocationType.Influence).player(TeamColor.White);
|
|
604
|
+
expect(mobilized.length).toBe(2);
|
|
605
|
+
});
|
|
606
|
+
it('mobilize 2 with deck=2: normal mobilize without reshuffle', () => {
|
|
607
|
+
const rules = createMobilizeSetup(2);
|
|
608
|
+
playAgentAndResolveEffects(rules, Agent.H4milt0n);
|
|
609
|
+
const mobilized = rules.material(MaterialType.AgentCard).location(LocationType.Influence).player(TeamColor.White);
|
|
610
|
+
expect(mobilized.length).toBe(3);
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
class MobilizeTestSetup extends TestSetup {
|
|
614
|
+
deckCount;
|
|
615
|
+
constructor(deckCount) {
|
|
616
|
+
super(Agent.H4milt0n);
|
|
617
|
+
this.deckCount = deckCount;
|
|
618
|
+
}
|
|
619
|
+
setupRemainingDeck() {
|
|
620
|
+
const usedAgents = new Set([
|
|
621
|
+
Agent.H4milt0n,
|
|
622
|
+
...agents.filter(a => a !== Agent.H4milt0n).slice(0, 7)
|
|
623
|
+
]);
|
|
624
|
+
const remaining = agents.filter(a => !usedAgents.has(a));
|
|
625
|
+
let idx = 0;
|
|
626
|
+
for (let i = 0; i < this.deckCount && idx < remaining.length; i++, idx++) {
|
|
627
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
628
|
+
id: remaining[idx],
|
|
629
|
+
location: { type: LocationType.AgentDeck }
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
for (; idx < remaining.length; idx++) {
|
|
633
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
634
|
+
id: remaining[idx],
|
|
635
|
+
location: { type: LocationType.AgentDiscard }
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
class MobilizeEmptySetup extends TestSetup {
|
|
641
|
+
constructor() {
|
|
642
|
+
super(Agent.H4milt0n);
|
|
643
|
+
}
|
|
644
|
+
setupRemainingDeck() {
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
class MobilizePartialSetup extends TestSetup {
|
|
648
|
+
deckCount;
|
|
649
|
+
constructor(deckCount) {
|
|
650
|
+
super(Agent.H4milt0n);
|
|
651
|
+
this.deckCount = deckCount;
|
|
652
|
+
}
|
|
653
|
+
setupRemainingDeck() {
|
|
654
|
+
const usedAgents = new Set([
|
|
655
|
+
Agent.H4milt0n,
|
|
656
|
+
...agents.filter(a => a !== Agent.H4milt0n).slice(0, 7)
|
|
657
|
+
]);
|
|
658
|
+
const remaining = agents.filter(a => !usedAgents.has(a));
|
|
659
|
+
for (let i = 0; i < this.deckCount && i < remaining.length; i++) {
|
|
660
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
661
|
+
id: remaining[i],
|
|
662
|
+
location: { type: LocationType.AgentDeck }
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
class RefillTestSetup extends TestSetup {
|
|
668
|
+
deckCount;
|
|
669
|
+
constructor(deckCount) {
|
|
670
|
+
super(agents[0]);
|
|
671
|
+
this.deckCount = deckCount;
|
|
672
|
+
}
|
|
673
|
+
setupTestHands() {
|
|
674
|
+
for (let i = 0; i < 4; i++) {
|
|
675
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
676
|
+
id: agents[i],
|
|
677
|
+
location: { type: LocationType.PlayerHand, player: player1 }
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
for (let i = 4; i < 8; i++) {
|
|
681
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
682
|
+
id: agents[i],
|
|
683
|
+
location: { type: LocationType.PlayerHand, player: player2 }
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
setupRemainingDeck() {
|
|
688
|
+
let idx = 8;
|
|
689
|
+
for (let i = 0; i < this.deckCount && idx < agents.length; i++, idx++) {
|
|
690
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
691
|
+
id: agents[idx],
|
|
692
|
+
location: { type: LocationType.AgentDeck }
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
for (; idx < agents.length; idx++) {
|
|
696
|
+
this.material(MaterialType.AgentCard).createItem({
|
|
697
|
+
id: agents[idx],
|
|
698
|
+
location: { type: LocationType.AgentDiscard }
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
//# sourceMappingURL=AgentEffects.spec.js.map
|