import assert from 'node:assert/strict'; import test from 'node:test'; import { viewGame, type Action } from '../game/engine'; import type { TruthQuestion } from '../game/truthtrance'; import { createTruthtranceRichesePromisesFixture as fixture, actTruthtranceRichesePromises as act, askTruthtranceRichesePromises as ask, advanceTruthtranceRichesePromises as advance, truthtranceRichesePromisesClean as clean, truthtranceRichesePromisesPlayer as player, truthtranceRichesePromisesInventory as inventory, } from './fixture-truthtrance-richese-promises'; void test('a No-Field shipment guide preserves an earlier physical ground-movement Yes', () => { const f = fixture({kind:'movement'}), source = structuredClone(f.game); // Controlled conserved supplement: acquire the other original physical // Truthtrance from the unopened deck, leaving every card in one location. const at = source.deck.findIndex(card => card.effect === 'truthtrance'); assert.ok(at >= 0); const extra = source.deck.splice(at, 1)[0]; player(source, f.asker).hand.push(extra); assert.deepEqual(inventory(source), f.originalInventory); let game = ask(source, f); assert.ok(viewGame(game, f.target).truthMovementAnswers?.includes('yes')); game = advance(act(game, f.target, {type:'truthAnswer', answer:'yes'}), clean); game = act(game, f.asker, {type:'card', card:extra.id}); game = advance(game, state => state.truthtrance?.stage === 'ask'); const markerQuestion = {kind:'shipment', target:f.target, claim:{kind:'noField', territory:'arrakeen', sector:10}} as unknown as TruthQuestion; game = act(game, f.asker, {type:'truthAsk', question:markerQuestion}); assert.ok(viewGame(game, f.target).truthShipmentAnswers?.includes('yes')); game = advance(act(game, f.target, {type:'truthAnswer', answer:'yes'}), clean); game = advance(game, state => state.phase === 5 && state.active === f.target && clean(state)); assert.equal(game.movementPromises?.[0].answer, true); assert.equal(game.shipmentPromises?.[0].answer, true); assert.equal(game.movementPromises?.[0].released, undefined); const first = viewGame(game, f.target).shipmentCompletion?.actions[0]; assert.equal(first?.type, 'ship'); assert.equal(typeof first.noField, 'string'); const selected = player(game).noField!.tokens.find(token => token.id === first.noField); assert.ok(selected && selected.value >= 1, 'A zero marker cannot supply the promised physical movement'); const otherView = viewGame(game, f.asker); assert.equal(otherView.shipmentCompletion, null); assert.equal(otherView.richeseNoField?.private, null); assert.equal(JSON.stringify(otherView).includes(first.noField as string), false); game = advance(act(game, f.target, first), clean); assert.equal(game.shipmentPromises![0].fulfilled, true); // Follow the same private legal guidance to reveal the marker and move its // actual physical forces; neither promise is satisfied by the marker alone. for (let step = 0; !game.movementPromises![0].fulfilled && step < 4; step++) { const next: Action | undefined = viewGame(game, f.target).movementPromisePolicy?.[0]; assert.ok(next, 'An owned completion must remain available after the shipment'); game = advance(act(game, f.target, next), clean); } assert.equal(game.movementPromises![0].fulfilled, true); assert.equal(game.movementPromises![0].released, undefined); assert.ok(player(game).forces['carthag:11'] >= 1); assert.deepEqual(inventory(game), f.originalInventory); });