35 lines
1.8 KiB
TypeScript
35 lines
1.8 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { validateAmbassadors } from '../game/ecaz-ambassadors';
|
|
import { advancedOverlapChildFixture } from './fixture-advanced-overlap-child';
|
|
|
|
/** Genuine Advanced native lobby/setup and Guild shipment from the shared
|
|
* fixture. Select the existing Guild Ambassador and Sneak Attack markers at
|
|
* the earned clean turn boundary; no forces, spice or continuation are staged.
|
|
* The Guild entrant cannot trigger its own Ambassador, but Moritani can. */
|
|
export function advancedDirectSneakFixture(withBG: boolean) {
|
|
const f = advancedOverlapChildFixture('fremen', 'terror', withBG);
|
|
const game = structuredClone(f.game);
|
|
const ambassadors = game.ecazAmbassadors!;
|
|
const old = ambassadors.tokens.find(token => token.id === f.token);
|
|
const guild = ambassadors.tokens.find(token => token.effect === 'guild');
|
|
assert.ok(old && guild && old.zone === 'placed');
|
|
old.zone = 'supply'; old.location = null;
|
|
if (guild.zone === 'pool') {
|
|
const index = ambassadors.cohort.indexOf(old.id); assert.ok(index >= 0);
|
|
ambassadors.cohort[index] = guild.id;
|
|
old.zone = 'pool'; guild.zone = 'supply';
|
|
}
|
|
assert.equal(guild.zone, 'supply');
|
|
guild.zone = 'placed'; guild.location = f.destination;
|
|
validateAmbassadors(ambassadors);
|
|
const robbery = game.moritaniTerror!.tokens.find(token => token.id === f.terror);
|
|
const sneak = game.moritaniTerror!.tokens.find(token => token.kind === 'sneakAttack');
|
|
assert.ok(robbery && sneak);
|
|
robbery.status = 'available'; robbery.location = null;
|
|
// The six-seat shared fixture may already have staged Sneak at a second
|
|
// site. Move that same physical token rather than creating another one.
|
|
assert.ok(sneak.status === 'available' || sneak.status === 'placed');
|
|
sneak.status = 'placed'; sneak.location = f.destination;
|
|
return { ...f, game, ambassador:guild.id, sneak:sneak.id };
|
|
}
|