Files
Dune/tests/junction-atomics-shipment.test.ts
T
Quintine 0f8e0b4153
Verify and publish checkpoint container / container (push) Successful in 10m7s
Enforce Atomics shipment ban across transport
2026-10-29 03:03:18 +11:00

52 lines
3.0 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { TERRITORIES } from '../game/board';
import { applyAction, viewGame, type Action } from '../game/engine';
import { junctionTransportActions, junctionTransportChoice } from '../game/junction-transport-options';
import { TERROR_STRONGHOLDS } from '../game/moritani-terror';
import { createJunctionPurchasedPrice, type PurchasedJunctionRoute } from './fixture-junction-purchased-price';
/** Original public setup, physical purchased rate and Guild's actual Junction
* offer come from the native fixture. To examine the later persisted state,
* Atomics' removed token, original victim and hand-limit marker are staged;
* any excess held card is moved into the original deck, not duplicated. */
function staged(route: PurchasedJunctionRoute) {
const f=createJunctionPurchasedPrice({route});
const g=structuredClone(f.beforeAction);
const available=TERRITORIES.filter(t=>TERROR_STRONGHOLDS.includes(t.id)).flatMap(t=>
t.sectors.map(sector=>`${t.id}:${sector}`)).find(destination=>
!!junctionTransportChoice(viewGame(g,f.shipper),destination,f.sources).action);
assert.ok(available,'An original offered Junction route needs an eligible stronghold.');
const target=available.split(':')[0];
const owner=g.players.find(player=>player.faction==='moritani'); assert.ok(owner);
const token=g.moritaniTerror?.tokens.find(candidate=>candidate.kind==='atomics'); assert.ok(token);
token.status='removed'; token.location=null;
owner.atomicsHandLimitPenalty=true;
if (owner.hand.length>3) g.deck.push(...owner.hand.splice(3));
g.moritaniAtomics={territory:target,turn:g.turn,moritaniId:owner.id,
allyAtActivation:null,alliancePolicy:'activation-targets'};
return {f,g,destination:available,target};
}
for (const route of ['nativeArrival','arrakisReturn'] as const) {
void test(`Junction ${route==='nativeArrival'?'Homeworld-to-Arrakis':'Arrakis-to-Arrakis'} cannot enter Atomics Aftermath`,()=>{
const {f,g,destination,target}=staged(route);
const view=viewGame(g,f.shipper);
const quoted=junctionTransportChoice(view,destination,f.sources);
assert.match(quoted.blocked??'',/Atomics Aftermath/);
assert.equal(quoted.action,null);
const offer=view.junctionTransport?.offer; assert.ok(offer);
const declaration: Action={type:'junctionShip',event:view.junctionTransport!.event,
offer:offer.event,destination,sources:f.sources,allyPayment:0,forfeitPurchasedRate:true};
const before=structuredClone(g);
assert.throws(()=>applyAction(g,f.shipper,declaration),/Atomics Aftermath/);
assert.deepEqual(g,before);
for (let level=0;level<4;level++)
assert.ok(!junctionTransportActions(view,level).some(action=>
action.type==='junctionShip' && typeof action.destination==='string' && action.destination.split(':')[0]===target));
// A Homeworld destination remains legal because the marker affects only Arrakis.
const world=junctionTransportChoice(view,'homeworld:ecaz',f.sources);
assert.ok(!world.blocked?.includes('Atomics'));
});
}