import assert from 'node:assert/strict'; import test from 'node:test'; import { viewGame } from '../game/engine'; import { DIFFICULTIES } from '../game/bot-profiles'; import { botActions } from '../game/bots'; import { act, greatMakerSneakFixture, player } from './fixture-great-maker-sneak'; for (const withBG of [false,true]) void test( `Advanced Great Maker Sneak resolves its own arrival ${withBG ? 'after BG' : 'without BG'} before completing the Maker`, () => { const f = greatMakerSneakFixture(withBG, withBG); let game = f.game; assert.equal(viewGame(game,'moritani').terrorEntry?.sneakAttack?.blocked, null); game = act(game,'moritani',{type:'decision',reveal:true}); assert.equal(game.pendingTerrorEntry?.stage,'sneakAttack'); for (const difficulty of DIFFICULTIES) { const view = viewGame(game,'moritani'); view.players.find(row => row.id === 'moritani')!.bot = difficulty; const choice = botActions(view)[0]; assert.ok(choice, difficulty); assert.doesNotThrow(() => act(game,'moritani',choice), difficulty); } const reserves = player(game,'moritani').reserves; const spice = player(game,'moritani').spice; game = act(game,'moritani',{type:'decision',amount:1}); assert.equal(player(game,'moritani').reserves,reserves-1); assert.equal(player(game,'moritani').forces[`${f.destination}:${f.sector}`],1); assert.equal(player(game,'moritani').spice,spice); assert.equal(player(game,'fremen').reserves,f.originalReserves-1); if (withBG) { assert.equal(game.greatMaker?.stage,'arrival'); assert.equal(game.decision?.kind,'advisor'); assert.equal(game.decision?.player,'beneGesserit'); game = act(game,'beneGesserit',{type:'decision',accept:false}); const child = game.pendingAmbassador; assert.ok(child); assert.equal(child.token,f.ambassador); assert.equal(child.entrant,'moritani'); assert.equal(game.greatMaker?.stage,'arrival'); game = act(game,'ecaz',{type:'decision',event:child.event,decline:true}); } assert.equal(game.pendingSneakWorm ?? null,null); assert.equal(game.pendingTerrorEntry ?? null,null); assert.equal(game.pendingAmbassador ?? null,null); assert.equal(game.greatMaker?.event,f.event); assert.equal(game.greatMaker?.stage,'complete'); assert.equal(player(game,'fremen').reserves,f.originalReserves-1); assert.equal(player(game,'moritani').reserves,reserves-1); assert.equal(player(game,'moritani').forces[`${f.destination}:${f.sector}`],1); }); void test('Advanced Great Maker Sneak choosing zero finishes without BG or a child entry', () => { const f = greatMakerSneakFixture(true, true); let game = act(f.game,'moritani',{type:'decision',reveal:true}); const reserves = player(game,'moritani').reserves; game = act(game,'moritani',{type:'decision',amount:0}); assert.equal(player(game,'moritani').reserves,reserves); assert.equal(game.pendingSneakWorm ?? null,null); assert.equal(game.pendingTerrorEntry ?? null,null); assert.equal(game.pendingAmbassador ?? null,null); assert.notEqual(game.decision?.kind,'advisor'); assert.equal(game.greatMaker?.event,f.event); assert.equal(game.greatMaker?.stage,'complete'); }); for (const first of ['terror','ambassador'] as const) void test( `Advanced Great Maker ${first}-first overlap finishes both original owners before the Sneak child`, () => { const f = greatMakerSneakFixture(false, true, 'emperor', first); let game = f.game; assert.equal(game.pendingArrivalOverlap?.first, first); assert.equal(game.pendingArrivalOverlap?.resume, 'wormRide'); assert.equal(game.greatMaker?.stage, 'arrival'); if (first === 'ambassador') { const original = game.pendingAmbassador; assert.ok(original); assert.equal(original.entrant, 'fremen'); game = act(game,'ecaz',{type:'decision',event:original.event,decline:true}); } assert.equal(game.pendingTerrorEntry?.token, f.sneak); assert.equal(viewGame(game,'moritani').terrorEntry?.sneakAttack?.blocked, null); game = act(game,'moritani',{type:'decision',reveal:true}); const reserves = player(game,'moritani').reserves; game = act(game,'moritani',{type:'decision',amount:1}); assert.equal(game.greatMaker?.stage,'arrival'); if (first === 'terror') { const original = game.pendingAmbassador; assert.ok(original); assert.equal(original.entrant, 'fremen'); game = act(game,'ecaz',{type:'decision',event:original.event,decline:true}); } const child = game.pendingAmbassador; assert.ok(child); assert.equal(child.token, f.ambassador); assert.equal(child.entrant, 'moritani'); assert.equal(game.greatMaker?.stage,'arrival'); game = act(game,'ecaz',{type:'decision',event:child.event,decline:true}); assert.equal(game.pendingSneakWorm ?? null,null); assert.equal(game.pendingArrivalOverlap ?? null,null); assert.equal(game.pendingAmbassador ?? null,null); assert.equal(game.greatMaker?.event,f.event); assert.equal(game.greatMaker?.stage,'complete'); assert.equal(player(game,'moritani').reserves,reserves-1); assert.equal(player(game,'moritani').forces[`${f.destination}:${f.sector}`],1); assert.equal(player(game,'fremen').reserves,f.originalReserves-1); });