Files
Dune/tests/fixture-truth-richese-silent.ts
T

56 lines
3.1 KiB
TypeScript

import assert from 'node:assert/strict';
import { viewGame, type Action, type Game } from '../game/engine';
import {
actTruthtranceRichesePromises as act,
advanceTruthtranceRichesePromises as advance,
createTruthtranceRichesePromisesFixture,
passTruthRicheseFreshDiscard,
truthtranceRichesePromisesClean as clean,
truthtranceRichesePromisesInventory as inventory,
truthtranceRichesePromisesPlayer as player,
} from './fixture-truthtrance-richese-promises';
export { act, inventory, player, passTruthRicheseFreshDiscard };
/** Original public Basic/Advanced Richese/Atreides/Emperor setup, genuine
* Charity prefix and actual first Silent cache declaration. The parent fixture
* selects unopened deal and Spice positions and native scalar lotteries; no
* hand, spice, auction, answer or receipt is installed. */
export function createTruthRicheseSilentFixture(advanced = false) {
const original = createTruthtranceRichesePromisesFixture({ advanced });
const game = advance(structuredClone(original.earlySource), state => clean(state) &&
!!state.richeseAuction && state.richeseAuction.method === 'silent' && !state.richeseAuction.outcome,
[], { position: 'first', method: 'silent' });
const lot = game.richeseAuction!;
const asker = original.asker, target = original.emperor, owner = original.richese;
assert.equal(lot.source, 'cache'); assert.equal(lot.active, null);
assert.ok(lot.eligible.includes(asker) && lot.eligible.includes(target) && lot.eligible.includes(owner));
assert.deepEqual(lot.sealed, {});
assert.ok(player(game, asker).hand.some(card => card.id === original.truth));
assert.deepEqual(inventory(game), original.originalCards);
return { original, game, asker, target, owner, lot:lot.event, card:lot.cardId,
truth:original.truth, originalCards:original.originalCards, staging:original.staging };
}
export type TruthRicheseSilentFixture = ReturnType<typeof createTruthRicheseSilentFixture>;
export function askTruthRicheseSilent(f: TruthRicheseSilentFixture, minimum = 4, source = f.game) {
let game = act(source, f.asker, { type:'card', card:f.truth });
for (let count = 0; game.truthtrance?.stage === 'priority' && count < game.players.length; count++) {
const seat = game.players.find(row => !game.truthtrance!.passed.includes(row.id)); assert.ok(seat);
game = act(game, seat.id, { type:'truthPass' });
}
assert.equal(game.truthtrance?.stage, 'ask');
return act(game, f.asker, { type:'truthAsk', question:{kind:'richeseBid', target:f.target,
turn:source.turn, event:f.lot, minimum} });
}
export function bindTruthRicheseSilent(f: TruthRicheseSilentFixture, answer: 'yes'|'no', minimum = 4, source = f.game) {
const asked = askTruthRicheseSilent(f, minimum, source);
assert.ok(viewGame(asked, f.target).truthRicheseBidAnswers?.includes(answer));
return { asked, game:passTruthRicheseFreshDiscard(act(asked, f.target, {type:'truthAnswer', answer})) };
}
export function rejectTruthRicheseSilent(game: Game, actor: string, action: Action) {
const before = structuredClone(game);
assert.throws(() => act(game, actor, action));
assert.deepEqual(game, before, 'A rejected action cannot mutate its input');
}