Files
Dune/tests/e3-independent-nexus-arrival.test.ts
Quintine 8793e23d6b Compose selected E3 independent cards with Nexus rules
Selected Ecaz/Moritani decks with independent cards and Nexus now retain native Occupy, Advanced assassination, arrival ordering and shared Duke consumers, including original optional modules. Keep the trained E3/Harkonnen capture boundary and remaining individual Nexus effect limits explicit.

Validation: frozen 17-file 168/168, types/lint/build, seven finite original-action and table-SSR programmes, plus four minimal legal Cunning/expiry policies. Fixture corrections preserve the printed alliance draw gate and real paid placement affordability. No stored-game or production change; comprehensive and deployed acceptance remain open.
2026-10-18 10:59:57 +11:00

34 lines
2.4 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { viewGame } from '../game/engine';
import { applyClassicDiscoveryNexusStep } from './fixture-discovery-classic-nexus';
import { createE3IndependentArrival, advanceE3IndependentArrival } from './fixture-e3-independent-nexus-arrival';
for (const modules of [false,true]) void test(`original selected E3 independent Nexus ${modules ? 'all14/World/phase' : 'Basic'} entry preserves both native arrival offers in Storm order`, () => {
const fixture = createE3IndependentArrival({advanced:modules, expansions:modules ? ['ecaz','ix','choam'] : ['ecaz'],
skills:modules, homeworlds:modules, tech:modules, strongholds:modules});
let game = fixture.game;
const original = structuredClone(game.pendingArrivalOverlap!);
assert.equal(original.entrant, 'guild');
assert.equal(original.amount, 2);
assert.equal(original.stage, 'first');
assert.equal(original.first, game.order.indexOf('ecaz') < game.order.indexOf('moritani') ? 'ambassador' : 'terror');
assert.equal(game.players.find(player=>player.id==='guild')!.forces['arrakeen:10'], 2);
assert.equal(game.ecazAmbassadors!.tokens.find(token=>token.id===fixture.ambassador)!.location, 'arrakeen');
assert.equal(game.moritaniTerror!.tokens.find(token=>token.id===fixture.terror)!.location, 'arrakeen');
for (const stage of ['first','second'] as const) {
assert.equal(game.pendingArrivalOverlap!.stage, stage);
const decision = game.decision!;
assert.ok(decision.kind === 'ecazAmbassador' || decision.kind === 'moritaniTerror');
assert.ok(viewGame(game, decision.player).arrivalOverlap);
game = applyClassicDiscoveryNexusStep(game, {actor:decision.player, action:{type:'decision',
...(decision.kind === 'ecazAmbassador' ? {event:game.pendingAmbassador!.event} : {}), decline:true}}, fixture.actions);
}
assert.ok(!game.pendingArrivalOverlap && !game.pendingAmbassador && !game.pendingTerrorEntry);
game = advanceE3IndependentArrival(game, state=>!state.phaseOpening && !state.response && !state.decision && !state.pendingGuildBetrayal);
assert.equal(game.phase, 5);
assert.equal(game.players.find(player=>player.id==='guild')!.shipped, true);
assert.equal(game.players.find(player=>player.id==='guild')!.forces['arrakeen:10'], 2);
assert.equal(game.nexusCards!.cards!.deck.length, 12, 'Without a real alliance there was no invented Nexus draw');
});