Files
Dune/tests/richese-reveal-interruption.test.ts
T
Quintine a10e019b01
Verify and publish checkpoint container / container (push) Canceled after 0s
Allow Richese reveal during Emperor revival
2026-10-29 18:41:15 +11:00

61 lines
3.1 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { createGame, newPlayer, type Game } from '../game/engine';
import { richeseRevealInterruptSupported as supported } from '../game/richese-reveal-interruption';
/** Quote-only staged response; native action and physical continuation are
* exercised separately by the integration owner. */
function source(target: 'richese' | 'atreides' = 'atreides'): Game {
const game = createGame('REVEALEXTRAREVIVAL', newPlayer('richese', 'Richese', 'richese'), false, ['choam']);
game.players.push(newPlayer('emperor', 'Emperor', 'emperor'), newPlayer('atreides', 'Atreides', 'atreides'));
game.status = 'playing'; game.phase = 4; game.turn = 2;
const emperor = game.players.find(player => player.id === 'emperor')!;
const recipient = game.players.find(player => player.id === target)!;
emperor.ally = target; recipient.ally = emperor.id; recipient.tanks = 2; emperor.spice = 10;
game.response = { kind: 'emperorRevival', owner: emperor.id, recipient: target, amount: 2, elite: 0, passed: [] };
return game;
}
void test('a clean Emperor extra revival preserves the accepted response for either ally', () => {
for (const recipient of ['richese', 'atreides'] as const) {
const game = source(recipient), before = structuredClone(game);
assert.equal(supported(game), true, recipient);
assert.deepEqual(game, before);
}
});
void test('extra revival admission checks its original funding, physical forces and mutual ally', () => {
for (const mutate of [
(g: Game) => { g.phase = 3; },
(g: Game) => { g.response!.owner = 'atreides'; },
(g: Game) => { g.response!.recipient = 'emperor'; },
(g: Game) => { g.players.find(p => p.id === 'atreides')!.ally = null; },
(g: Game) => { g.players.find(p => p.id === 'atreides')!.tanks = 1; },
(g: Game) => { g.players.find(p => p.id === 'emperor')!.spice = 3; },
(g: Game) => { g.response!.amount = 0; },
(g: Game) => { g.response!.elite = 1; },
(g: Game) => { g.emperorExtra.atreides = 2; },
(g: Game) => { g.revivalPrevention = {player:'atreides',turn:g.turn}; },
(g: Game) => { g.response!.passed = ['atreides','atreides']; },
(g: Game) => { g.response!.intent = 'other'; },
(g: Game) => { g.decision = {kind:'auctionPayment',player:'emperor'}; },
(g: Game) => { g.pendingRevival = {} as NonNullable<Game['pendingRevival']>; },
]) {
const game = source(); mutate(game);
const before = structuredClone(game);
assert.equal(supported(game), false);
assert.deepEqual(game, before);
}
});
void test('Ixian extra revivals retain the special-force price and typed tanks', () => {
const game = source(); game.expansions.push('ix');
const recipient = game.players.find(player => player.id === 'atreides')!;
recipient.faction = 'ixians'; recipient.elites = {reserves:0,tanks:1,forces:{},revived:0};
game.response!.elite = 1;
const emperor = game.players.find(player => player.id === 'emperor')!;
emperor.spice = 5; assert.equal(supported(game), true);
emperor.spice = 4; assert.equal(supported(game), false);
emperor.spice = 5; game.response!.elite = 2; assert.equal(supported(game), false);
});