@gamepark/zenith 1.0.4 → 1.0.8

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.
@@ -15,7 +15,7 @@ const player1 = 1;
15
15
  const player2 = 2;
16
16
  function createGameForAgent(agent) {
17
17
  const setup = new TestSetup(agent);
18
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
18
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
19
19
  return new ZenithRules(game);
20
20
  }
21
21
  class TestSetup extends ZenithSetup {
@@ -47,14 +47,14 @@ class TestSetup extends ZenithSetup {
47
47
  id: this.testAgent,
48
48
  location: { type: LocationType.PlayerHand, player: player1 }
49
49
  });
50
- const fillers = agents.filter(a => a !== this.testAgent).slice(0, 3);
50
+ const fillers = agents.filter((a) => a !== this.testAgent).slice(0, 3);
51
51
  for (const agent of fillers) {
52
52
  this.material(MaterialType.AgentCard).createItem({
53
53
  id: agent,
54
54
  location: { type: LocationType.PlayerHand, player: player1 }
55
55
  });
56
56
  }
57
- const p2Fillers = agents.filter(a => a !== this.testAgent && !fillers.includes(a)).slice(0, 4);
57
+ const p2Fillers = agents.filter((a) => a !== this.testAgent && !fillers.includes(a)).slice(0, 4);
58
58
  for (const agent of p2Fillers) {
59
59
  this.material(MaterialType.AgentCard).createItem({
60
60
  id: agent,
@@ -63,11 +63,8 @@ class TestSetup extends ZenithSetup {
63
63
  }
64
64
  }
65
65
  setupRemainingDeck() {
66
- const usedAgents = new Set([
67
- this.testAgent,
68
- ...agents.filter(a => a !== this.testAgent).slice(0, 7)
69
- ]);
70
- const remaining = agents.filter(a => !usedAgents.has(a));
66
+ const usedAgents = new Set([this.testAgent, ...agents.filter((a) => a !== this.testAgent).slice(0, 7)]);
67
+ const remaining = agents.filter((a) => !usedAgents.has(a));
71
68
  for (const agent of remaining) {
72
69
  this.material(MaterialType.AgentCard).createItem({
73
70
  id: agent,
@@ -141,11 +138,7 @@ function resolveAutoMoves(rules) {
141
138
  }
142
139
  }
143
140
  function playAgentAndResolveEffects(rules, agent) {
144
- const cardIndex = rules.material(MaterialType.AgentCard)
145
- .location(LocationType.PlayerHand)
146
- .player(player1)
147
- .id(agent)
148
- .getIndex();
141
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(agent).getIndex();
149
142
  if (cardIndex === undefined) {
150
143
  return { error: `Agent ${Agent[agent]} not found in player1 hand` };
151
144
  }
@@ -206,14 +199,11 @@ describe('Agent effects resolution', () => {
206
199
  describe('Gilgamesh opponentSide fallback', () => {
207
200
  it('should allow pulling a different planet when the only opponent-side planet was pulled across by effect 2', () => {
208
201
  const setup = new GilgameshTestSetup();
209
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
202
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
210
203
  const rules = new ZenithRules(game);
211
- const venusStart = rules.material(MaterialType.InfluenceDisc)
212
- .location(LocationType.PlanetBoardInfluenceDiscSpace)
213
- .id(Influence.Venus).getItem();
204
+ const venusStart = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Venus).getItem();
214
205
  expect(venusStart.location.x).toBe(-1);
215
- const cardIndex = rules.material(MaterialType.AgentCard)
216
- .location(LocationType.PlayerHand).player(player1).id(Agent.Gilgamesh).getIndex();
206
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Gilgamesh).getIndex();
217
207
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
218
208
  type: LocationType.Influence,
219
209
  id: Influence.Terra,
@@ -241,14 +231,11 @@ describe('Gilgamesh opponentSide fallback', () => {
241
231
  describe('Planet capture', () => {
242
232
  it('White pulling a planet at x=3 should capture it at x=4 into White TeamPlanets', () => {
243
233
  const setup = new CaptureTestSetup(Agent.Mc4ffr3y, Influence.Mars, 3);
244
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
234
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
245
235
  const rules = new ZenithRules(game);
246
- const marsStart = rules.material(MaterialType.InfluenceDisc)
247
- .location(LocationType.PlanetBoardInfluenceDiscSpace)
248
- .id(Influence.Mars).getItem();
236
+ const marsStart = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars).getItem();
249
237
  expect(marsStart.location.x).toBe(3);
250
- const cardIndex = rules.material(MaterialType.AgentCard)
251
- .location(LocationType.PlayerHand).player(player1).id(Agent.Mc4ffr3y).getIndex();
238
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Mc4ffr3y).getIndex();
252
239
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
253
240
  type: LocationType.Influence,
254
241
  id: Influence.Mars,
@@ -272,32 +259,21 @@ describe('Planet capture', () => {
272
259
  resolveAutoMoves(rules);
273
260
  iterations++;
274
261
  }
275
- const marsInWhite = rules.material(MaterialType.InfluenceDisc)
276
- .location(LocationType.TeamPlanets)
277
- .player(TeamColor.White)
278
- .id(Influence.Mars);
262
+ const marsInWhite = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Mars);
279
263
  expect(marsInWhite.length).toBe(1);
280
- const marsInBlack = rules.material(MaterialType.InfluenceDisc)
281
- .location(LocationType.TeamPlanets)
282
- .player(TeamColor.Black)
283
- .id(Influence.Mars);
264
+ const marsInBlack = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.Black).id(Influence.Mars);
284
265
  expect(marsInBlack.length).toBe(0);
285
- const marsOnBoard = rules.material(MaterialType.InfluenceDisc)
286
- .location(LocationType.PlanetBoardInfluenceDiscSpace)
287
- .id(Influence.Mars);
266
+ const marsOnBoard = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars);
288
267
  expect(marsOnBoard.length).toBe(1);
289
268
  expect(marsOnBoard.getItem().location.x).toBe(0);
290
269
  });
291
270
  it('Black pulling a planet at x=-3 should capture it at x=-4 into Black TeamPlanets', () => {
292
271
  const setup = new CaptureTestSetupBlack(Agent.Mc4ffr3y, Influence.Mars, -3);
293
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
272
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
294
273
  const rules = new ZenithRules(game);
295
- const marsStart = rules.material(MaterialType.InfluenceDisc)
296
- .location(LocationType.PlanetBoardInfluenceDiscSpace)
297
- .id(Influence.Mars).getItem();
274
+ const marsStart = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars).getItem();
298
275
  expect(marsStart.location.x).toBe(-3);
299
- const cardIndex = rules.material(MaterialType.AgentCard)
300
- .location(LocationType.PlayerHand).player(player2).id(Agent.Mc4ffr3y).getIndex();
276
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player2).id(Agent.Mc4ffr3y).getIndex();
301
277
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
302
278
  type: LocationType.Influence,
303
279
  id: Influence.Mars,
@@ -321,32 +297,21 @@ describe('Planet capture', () => {
321
297
  resolveAutoMoves(rules);
322
298
  iterations++;
323
299
  }
324
- const marsInBlack = rules.material(MaterialType.InfluenceDisc)
325
- .location(LocationType.TeamPlanets)
326
- .player(TeamColor.Black)
327
- .id(Influence.Mars);
300
+ const marsInBlack = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.Black).id(Influence.Mars);
328
301
  expect(marsInBlack.length).toBe(1);
329
- const marsInWhite = rules.material(MaterialType.InfluenceDisc)
330
- .location(LocationType.TeamPlanets)
331
- .player(TeamColor.White)
332
- .id(Influence.Mars);
302
+ const marsInWhite = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Mars);
333
303
  expect(marsInWhite.length).toBe(0);
334
- const marsOnBoard = rules.material(MaterialType.InfluenceDisc)
335
- .location(LocationType.PlanetBoardInfluenceDiscSpace)
336
- .id(Influence.Mars);
304
+ const marsOnBoard = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars);
337
305
  expect(marsOnBoard.length).toBe(1);
338
306
  expect(marsOnBoard.getItem().location.x).toBe(0);
339
307
  });
340
308
  it('White pushing Terra at x=-3 should capture it at x=-4 into Black TeamPlanets (opponent)', () => {
341
309
  const setup = new CaptureTestSetup(Agent.Titus, Influence.Terra, -3);
342
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
310
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
343
311
  const rules = new ZenithRules(game);
344
- const terraStart = rules.material(MaterialType.InfluenceDisc)
345
- .location(LocationType.PlanetBoardInfluenceDiscSpace)
346
- .id(Influence.Terra).getItem();
312
+ const terraStart = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra).getItem();
347
313
  expect(terraStart.location.x).toBe(-3);
348
- const cardIndex = rules.material(MaterialType.AgentCard)
349
- .location(LocationType.PlayerHand).player(player1).id(Agent.Titus).getIndex();
314
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Titus).getIndex();
350
315
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
351
316
  type: LocationType.Influence,
352
317
  id: Agents[Agent.Titus].influence,
@@ -366,25 +331,16 @@ describe('Planet capture', () => {
366
331
  resolveAutoMoves(rules);
367
332
  continue;
368
333
  }
369
- const terraPush = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
370
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Terra);
334
+ const terraPush = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) && rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Terra);
371
335
  playConsequences(rules, terraPush ?? moves[0]);
372
336
  resolveAutoMoves(rules);
373
337
  iterations++;
374
338
  }
375
- const terraInBlack = rules.material(MaterialType.InfluenceDisc)
376
- .location(LocationType.TeamPlanets)
377
- .player(TeamColor.Black)
378
- .id(Influence.Terra);
339
+ const terraInBlack = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.Black).id(Influence.Terra);
379
340
  expect(terraInBlack.length).toBe(1);
380
- const terraInWhite = rules.material(MaterialType.InfluenceDisc)
381
- .location(LocationType.TeamPlanets)
382
- .player(TeamColor.White)
383
- .id(Influence.Terra);
341
+ const terraInWhite = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Terra);
384
342
  expect(terraInWhite.length).toBe(0);
385
- const terraOnBoard = rules.material(MaterialType.InfluenceDisc)
386
- .location(LocationType.PlanetBoardInfluenceDiscSpace)
387
- .id(Influence.Terra);
343
+ const terraOnBoard = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra);
388
344
  expect(terraOnBoard.length).toBe(1);
389
345
  expect(terraOnBoard.getItem().location.x).toBe(0);
390
346
  });
@@ -392,16 +348,12 @@ describe('Planet capture', () => {
392
348
  describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
393
349
  it('should allow capturing Mercury and still apply remaining pattern moves to Venus and Terra', () => {
394
350
  const setup = new AugustusPatternSetup({ [Influence.Mercury]: 3 });
395
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
351
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
396
352
  const rules = new ZenithRules(game);
397
- expect(rules.material(MaterialType.InfluenceDisc)
398
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mercury).getItem().location.x).toBe(3);
399
- expect(rules.material(MaterialType.InfluenceDisc)
400
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Venus).getItem().location.x).toBe(0);
401
- expect(rules.material(MaterialType.InfluenceDisc)
402
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra).getItem().location.x).toBe(0);
403
- const cardIndex = rules.material(MaterialType.AgentCard)
404
- .location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
353
+ expect(rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mercury).getItem().location.x).toBe(3);
354
+ expect(rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Venus).getItem().location.x).toBe(0);
355
+ expect(rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra).getItem().location.x).toBe(0);
356
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
405
357
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
406
358
  type: LocationType.Influence,
407
359
  id: Influence.Terra,
@@ -421,33 +373,29 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
421
373
  resolveAutoMoves(rules);
422
374
  continue;
423
375
  }
424
- const mercuryMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
425
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mercury);
426
- const venusMove = !mercuryMove ? moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
427
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Venus &&
428
- m.location.x === 2) : undefined;
376
+ const mercuryMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) && rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mercury);
377
+ const venusMove = !mercuryMove
378
+ ? moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
379
+ rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Venus &&
380
+ m.location.x === 2)
381
+ : undefined;
429
382
  playConsequences(rules, mercuryMove ?? venusMove ?? moves[0]);
430
383
  resolveAutoMoves(rules);
431
384
  iterations++;
432
385
  }
433
- const mercuryCaptured = rules.material(MaterialType.InfluenceDisc)
434
- .location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Mercury);
386
+ const mercuryCaptured = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Mercury);
435
387
  expect(mercuryCaptured.length).toBe(1);
436
- const venus = rules.material(MaterialType.InfluenceDisc)
437
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Venus);
388
+ const venus = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Venus);
438
389
  expect(venus.getItem().location.x).toBe(2);
439
- const terra = rules.material(MaterialType.InfluenceDisc)
440
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra);
390
+ const terra = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra);
441
391
  expect(terra.getItem().location.x).toBe(2);
442
392
  });
443
393
  it('should allow truncated pattern at left edge — Mercury+2 capture with Venus+1', () => {
444
394
  const setup = new AugustusPatternSetup({ [Influence.Mercury]: 2 });
445
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
395
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
446
396
  const rules = new ZenithRules(game);
447
- expect(rules.material(MaterialType.InfluenceDisc)
448
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mercury).getItem().location.x).toBe(2);
449
- const cardIndex = rules.material(MaterialType.AgentCard)
450
- .location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
397
+ expect(rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mercury).getItem().location.x).toBe(2);
398
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
451
399
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
452
400
  type: LocationType.Influence,
453
401
  id: Influence.Terra,
@@ -467,28 +415,24 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
467
415
  resolveAutoMoves(rules);
468
416
  continue;
469
417
  }
470
- const mercuryMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
418
+ const mercuryMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
471
419
  rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mercury &&
472
420
  m.location.x === 4);
473
421
  playConsequences(rules, mercuryMove ?? moves[0]);
474
422
  resolveAutoMoves(rules);
475
423
  iterations++;
476
424
  }
477
- const mercuryCaptured = rules.material(MaterialType.InfluenceDisc)
478
- .location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Mercury);
425
+ const mercuryCaptured = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Mercury);
479
426
  expect(mercuryCaptured.length).toBe(1);
480
- const venus = rules.material(MaterialType.InfluenceDisc)
481
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Venus);
427
+ const venus = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Venus);
482
428
  expect(venus.getItem().location.x).toBe(1);
483
429
  });
484
430
  it('should allow truncated pattern at right edge — Jupiter+2 capture with Mars+1', () => {
485
431
  const setup = new AugustusPatternSetup({ [Influence.Jupiter]: 2 });
486
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
432
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
487
433
  const rules = new ZenithRules(game);
488
- expect(rules.material(MaterialType.InfluenceDisc)
489
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Jupiter).getItem().location.x).toBe(2);
490
- const cardIndex = rules.material(MaterialType.AgentCard)
491
- .location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
434
+ expect(rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Jupiter).getItem().location.x).toBe(2);
435
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
492
436
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
493
437
  type: LocationType.Influence,
494
438
  id: Influence.Terra,
@@ -508,26 +452,23 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
508
452
  resolveAutoMoves(rules);
509
453
  continue;
510
454
  }
511
- const jupiterMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
455
+ const jupiterMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
512
456
  rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Jupiter &&
513
457
  m.location.x === 4);
514
458
  playConsequences(rules, jupiterMove ?? moves[0]);
515
459
  resolveAutoMoves(rules);
516
460
  iterations++;
517
461
  }
518
- const jupiterCaptured = rules.material(MaterialType.InfluenceDisc)
519
- .location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Jupiter);
462
+ const jupiterCaptured = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Jupiter);
520
463
  expect(jupiterCaptured.length).toBe(1);
521
- const mars = rules.material(MaterialType.InfluenceDisc)
522
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars);
464
+ const mars = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars);
523
465
  expect(mars.getItem().location.x).toBe(1);
524
466
  });
525
467
  it('should not allow moving Mercury+2 when it is not at the edge (no truncated pattern needed)', () => {
526
468
  const setup = new AugustusPatternSetup({});
527
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
469
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
528
470
  const rules = new ZenithRules(game);
529
- const cardIndex = rules.material(MaterialType.AgentCard)
530
- .location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
471
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
531
472
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
532
473
  type: LocationType.Influence,
533
474
  id: Influence.Terra,
@@ -539,8 +480,7 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
539
480
  let iterations = 0;
540
481
  while (iterations < 20) {
541
482
  const moves = rules.getLegalMoves(player1);
542
- const mercuryMoves = moves.filter(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
543
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mercury);
483
+ const mercuryMoves = moves.filter((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) && rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mercury);
544
484
  if (mercuryMoves.length > 0) {
545
485
  patternMoves = moves;
546
486
  break;
@@ -554,18 +494,16 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
554
494
  }
555
495
  iterations++;
556
496
  }
557
- const mercuryMoves = patternMoves.filter(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
558
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mercury);
559
- const mercuryTargetXs = mercuryMoves.map(m => m.location.x).sort();
497
+ const mercuryMoves = patternMoves.filter((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) && rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mercury);
498
+ const mercuryTargetXs = mercuryMoves.map((m) => m.location.x).sort();
560
499
  expect(mercuryTargetXs).toContain(1);
561
500
  expect(mercuryTargetXs).toContain(2);
562
501
  });
563
502
  it('should not allow moving a non-adjacent planet with pattern', () => {
564
503
  const setup = new AugustusPatternSetup({});
565
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
504
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
566
505
  const rules = new ZenithRules(game);
567
- const cardIndex = rules.material(MaterialType.AgentCard)
568
- .location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
506
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
569
507
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
570
508
  type: LocationType.Influence,
571
509
  id: Influence.Terra,
@@ -576,7 +514,7 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
576
514
  let iterations = 0;
577
515
  while (iterations < 20) {
578
516
  const moves = rules.getLegalMoves(player1);
579
- const mercuryMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
517
+ const mercuryMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
580
518
  rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mercury &&
581
519
  m.location.x === 1);
582
520
  if (mercuryMove) {
@@ -595,8 +533,8 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
595
533
  }
596
534
  const nextMoves = rules.getLegalMoves(player1);
597
535
  const movablePlanets = new Set(nextMoves
598
- .filter(m => isMoveItemType(MaterialType.InfluenceDisc)(m))
599
- .map(m => rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id));
536
+ .filter((m) => isMoveItemType(MaterialType.InfluenceDisc)(m))
537
+ .map((m) => rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id));
600
538
  expect(movablePlanets.has(Influence.Venus)).toBe(true);
601
539
  expect(movablePlanets.has(Influence.Terra)).toBe(true);
602
540
  expect(movablePlanets.has(Influence.Mars)).toBe(false);
@@ -604,10 +542,9 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
604
542
  });
605
543
  it('should not allow moving only Jupiter+2 without Mars (pattern requires adjacency)', () => {
606
544
  const setup = new AugustusPatternSetup({ [Influence.Jupiter]: 2 });
607
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
545
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
608
546
  const rules = new ZenithRules(game);
609
- const cardIndex = rules.material(MaterialType.AgentCard)
610
- .location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
547
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
611
548
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
612
549
  type: LocationType.Influence,
613
550
  id: Influence.Terra,
@@ -618,13 +555,12 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
618
555
  let iterations = 0;
619
556
  while (iterations < 20) {
620
557
  const moves = rules.getLegalMoves(player1);
621
- const jupiterMoves = moves.filter(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
622
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Jupiter);
558
+ const jupiterMoves = moves.filter((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) && rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Jupiter);
623
559
  if (jupiterMoves.length > 0) {
624
- const jupiterTargetXs = jupiterMoves.map(m => m.location.x).sort();
560
+ const jupiterTargetXs = jupiterMoves.map((m) => m.location.x).sort();
625
561
  expect(jupiterTargetXs).toContain(3);
626
562
  expect(jupiterTargetXs).toContain(4);
627
- const captureMove = jupiterMoves.find(m => m.location.x === 4);
563
+ const captureMove = jupiterMoves.find((m) => m.location.x === 4);
628
564
  playConsequences(rules, captureMove);
629
565
  resolveAutoMoves(rules);
630
566
  break;
@@ -654,16 +590,14 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
654
590
  resolveAutoMoves(rules);
655
591
  iterations++;
656
592
  }
657
- const mars = rules.material(MaterialType.InfluenceDisc)
658
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars);
593
+ const mars = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars);
659
594
  expect(mars.getItem().location.x).toBe(1);
660
595
  });
661
596
  it('should continue pattern when Venus is clamped at limit — Mercury+1, Venus captured, Terra+1', () => {
662
597
  const setup = new AugustusPatternSetup({ [Influence.Venus]: 3 });
663
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
598
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
664
599
  const rules = new ZenithRules(game);
665
- const cardIndex = rules.material(MaterialType.AgentCard)
666
- .location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
600
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
667
601
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
668
602
  type: LocationType.Influence,
669
603
  id: Influence.Terra,
@@ -683,35 +617,28 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
683
617
  resolveAutoMoves(rules);
684
618
  continue;
685
619
  }
686
- const mercuryMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
620
+ const mercuryMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
687
621
  rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mercury &&
688
622
  m.location.x === 1);
689
- const venusMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
690
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Venus);
691
- const terraMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
692
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Terra);
623
+ const venusMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) && rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Venus);
624
+ const terraMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) && rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Terra);
693
625
  playConsequences(rules, mercuryMove ?? venusMove ?? terraMove ?? moves[0]);
694
626
  resolveAutoMoves(rules);
695
627
  iterations++;
696
628
  }
697
- const mercury = rules.material(MaterialType.InfluenceDisc)
698
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mercury);
629
+ const mercury = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mercury);
699
630
  expect(mercury.getItem().location.x).toBe(1);
700
- const venusCaptured = rules.material(MaterialType.InfluenceDisc)
701
- .location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Venus);
702
- const venusOnBoard = rules.material(MaterialType.InfluenceDisc)
703
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Venus);
631
+ const venusCaptured = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Venus);
632
+ const venusOnBoard = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Venus);
704
633
  expect(venusCaptured.length + (venusOnBoard.length > 0 && venusOnBoard.getItem().location.x === 4 ? 1 : 0)).toBeGreaterThanOrEqual(1);
705
- const terra = rules.material(MaterialType.InfluenceDisc)
706
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra);
634
+ const terra = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra);
707
635
  expect(terra.getItem().location.x).toBe(2);
708
636
  });
709
637
  it('should work with pattern on right side — Terra+1, Mars+2 clamped/captured, Jupiter+1', () => {
710
638
  const setup = new AugustusPatternSetup({ [Influence.Mars]: 3 });
711
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
639
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
712
640
  const rules = new ZenithRules(game);
713
- const cardIndex = rules.material(MaterialType.AgentCard)
714
- .location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
641
+ const cardIndex = rules.material(MaterialType.AgentCard).location(LocationType.PlayerHand).player(player1).id(Agent.Augustus).getIndex();
715
642
  const playMove = rules.material(MaterialType.AgentCard).index(cardIndex).moveItem({
716
643
  type: LocationType.Influence,
717
644
  id: Influence.Terra,
@@ -731,27 +658,21 @@ describe('Augustus pattern [1,2,1] at extreme — Mercury capture', () => {
731
658
  resolveAutoMoves(rules);
732
659
  continue;
733
660
  }
734
- const marsMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
735
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mars);
736
- const jupiterMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
661
+ const marsMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) && rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Mars);
662
+ const jupiterMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
737
663
  rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Jupiter &&
738
664
  m.location.x === 1);
739
- const terraMove = moves.find(m => isMoveItemType(MaterialType.InfluenceDisc)(m) &&
740
- rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Terra);
665
+ const terraMove = moves.find((m) => isMoveItemType(MaterialType.InfluenceDisc)(m) && rules.material(MaterialType.InfluenceDisc).getItem(m.itemIndex).id === Influence.Terra);
741
666
  playConsequences(rules, marsMove ?? jupiterMove ?? terraMove ?? moves[0]);
742
667
  resolveAutoMoves(rules);
743
668
  iterations++;
744
669
  }
745
- const marsCaptured = rules.material(MaterialType.InfluenceDisc)
746
- .location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Mars);
747
- const marsOnBoard = rules.material(MaterialType.InfluenceDisc)
748
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars);
670
+ const marsCaptured = rules.material(MaterialType.InfluenceDisc).location(LocationType.TeamPlanets).player(TeamColor.White).id(Influence.Mars);
671
+ const marsOnBoard = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Mars);
749
672
  expect(marsCaptured.length + (marsOnBoard.length > 0 && marsOnBoard.getItem().location.x === 4 ? 1 : 0)).toBeGreaterThanOrEqual(1);
750
- const jupiter = rules.material(MaterialType.InfluenceDisc)
751
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Jupiter);
673
+ const jupiter = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Jupiter);
752
674
  expect(jupiter.getItem().location.x).toBe(1);
753
- const terra = rules.material(MaterialType.InfluenceDisc)
754
- .location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra);
675
+ const terra = rules.material(MaterialType.InfluenceDisc).location(LocationType.PlanetBoardInfluenceDiscSpace).id(Influence.Terra);
755
676
  expect(terra.getItem().location.x).toBe(2);
756
677
  });
757
678
  });
@@ -801,19 +722,19 @@ class CaptureTestSetupBlack extends CaptureTestSetup {
801
722
  this.memorize(Memory.TurnOrder, [player2, player1]);
802
723
  }
803
724
  setupTestHands() {
804
- const testAgent = agents.find(a => a === Agent.Mc4ffr3y);
725
+ const testAgent = agents.find((a) => a === Agent.Mc4ffr3y);
805
726
  this.material(MaterialType.AgentCard).createItem({
806
727
  id: testAgent,
807
728
  location: { type: LocationType.PlayerHand, player: player2 }
808
729
  });
809
- const fillers = agents.filter(a => a !== testAgent).slice(0, 3);
730
+ const fillers = agents.filter((a) => a !== testAgent).slice(0, 3);
810
731
  for (const agent of fillers) {
811
732
  this.material(MaterialType.AgentCard).createItem({
812
733
  id: agent,
813
734
  location: { type: LocationType.PlayerHand, player: player2 }
814
735
  });
815
736
  }
816
- const p1Fillers = agents.filter(a => a !== testAgent && !fillers.includes(a)).slice(0, 4);
737
+ const p1Fillers = agents.filter((a) => a !== testAgent && !fillers.includes(a)).slice(0, 4);
817
738
  for (const agent of p1Fillers) {
818
739
  this.material(MaterialType.AgentCard).createItem({
819
740
  id: agent,
@@ -845,7 +766,7 @@ class GilgameshTestSetup extends TestSetup {
845
766
  describe('Refill with low/empty deck', () => {
846
767
  function createRefillSetup(deckCount) {
847
768
  const setup = new RefillTestSetup(deckCount);
848
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
769
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
849
770
  return new ZenithRules(game);
850
771
  }
851
772
  function discardAndRefill(rules) {
@@ -950,7 +871,7 @@ describe('Refill with low/empty deck', () => {
950
871
  describe('Mobilize with low/empty deck', () => {
951
872
  function createMobilizeSetup(deckCount) {
952
873
  const setup = new MobilizeTestSetup(deckCount);
953
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
874
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
954
875
  return new ZenithRules(game);
955
876
  }
956
877
  it('mobilize 2 with deck=1: should reshuffle discard and mobilize second card', () => {
@@ -971,7 +892,7 @@ describe('Mobilize with low/empty deck', () => {
971
892
  });
972
893
  it('mobilize 2 with deck=0 and discard=0: should skip mobilization without blocking', () => {
973
894
  const setup = new MobilizeEmptySetup();
974
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
895
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
975
896
  const rules = new ZenithRules(game);
976
897
  expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(0);
977
898
  expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDiscard).length).toBe(0);
@@ -983,7 +904,7 @@ describe('Mobilize with low/empty deck', () => {
983
904
  });
984
905
  it('mobilize 2 with deck=1 and discard=0: should mobilize 1 then skip remaining', () => {
985
906
  const setup = new MobilizePartialSetup(1);
986
- const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N', secretAgent: false });
907
+ const game = setup.setup({ players: [{}, {}], animodBoard: 'S', humanBoard: 'U', robotBoard: 'N' });
987
908
  const rules = new ZenithRules(game);
988
909
  expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDeck).length).toBe(1);
989
910
  expect(rules.material(MaterialType.AgentCard).location(LocationType.AgentDiscard).length).toBe(0);
@@ -1007,11 +928,8 @@ class MobilizeTestSetup extends TestSetup {
1007
928
  this.deckCount = deckCount;
1008
929
  }
1009
930
  setupRemainingDeck() {
1010
- const usedAgents = new Set([
1011
- Agent.H4milt0n,
1012
- ...agents.filter(a => a !== Agent.H4milt0n).slice(0, 7)
1013
- ]);
1014
- const remaining = agents.filter(a => !usedAgents.has(a));
931
+ const usedAgents = new Set([Agent.H4milt0n, ...agents.filter((a) => a !== Agent.H4milt0n).slice(0, 7)]);
932
+ const remaining = agents.filter((a) => !usedAgents.has(a));
1015
933
  let idx = 0;
1016
934
  for (let i = 0; i < this.deckCount && idx < remaining.length; i++, idx++) {
1017
935
  this.material(MaterialType.AgentCard).createItem({
@@ -1041,11 +959,8 @@ class MobilizePartialSetup extends TestSetup {
1041
959
  this.deckCount = deckCount;
1042
960
  }
1043
961
  setupRemainingDeck() {
1044
- const usedAgents = new Set([
1045
- Agent.H4milt0n,
1046
- ...agents.filter(a => a !== Agent.H4milt0n).slice(0, 7)
1047
- ]);
1048
- const remaining = agents.filter(a => !usedAgents.has(a));
962
+ const usedAgents = new Set([Agent.H4milt0n, ...agents.filter((a) => a !== Agent.H4milt0n).slice(0, 7)]);
963
+ const remaining = agents.filter((a) => !usedAgents.has(a));
1049
964
  for (let i = 0; i < this.deckCount && i < remaining.length; i++) {
1050
965
  this.material(MaterialType.AgentCard).createItem({
1051
966
  id: remaining[i],