Files
Dune/tests/reinforcements-homeworld-guide-choice.test.ts
T
Quintine 89569e92a1
Verify and publish checkpoint container / container (push) Successful in 11m10s
Support Advanced native Homeworld return
2026-10-29 04:48:47 +11:00

65 lines
3.3 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { applyAction, viewGame } from '../game/engine';
import { takeHarassCard } from './fixture-harass-withdraw';
import {
createReinforcementsHomeworldFixture,
reinforcementsHomeworldPool as pool,
reinforcementsHomeworldPlayer as player,
REINFORCEMENTS_KAITAIN as K,
REINFORCEMENTS_SALUSA as S,
REINFORCEMENTS_CARD,
} from './fixture-reinforcements-homeworld';
/** The original native setup moves one actual ordinary counter to Salusa.
* Its remaining native troops, the real invading force and all cards are
* conserved; choosing the special reserve fee leaves two extra normal
* counters on the native battlefield compared with the legacy fee. */
void test('a named Reinforcements promise finds a necessary special-reserve Homeworld fee', () => {
const f = createReinforcementsHomeworldFixture({
advanced: true, role: 'native', nativeTransfer: 1, slot: 'weapon',
});
const owner = player(f.game, f.owner);
assert.deepEqual(pool(f.game, f.owner, K), { normal: 14, elite: 0 });
assert.deepEqual(pool(f.game, f.owner, S), { normal: 1, elite: 5 });
const support = Math.min(owner.spice, 14);
const wantedDial = (14 + support) / 2;
const legacyMax = (12 + Math.min(owner.spice, 12)) / 2;
assert.ok(wantedDial > legacyMax, 'The legal plan must require preserving normal counters at Kaitain');
const mixed = {
[K]: { normal: 0, elite: 0 },
[S]: { normal: 1, elite: 2 },
};
const manual = { ...f.planActions[0].action, type: 'battlePlan',
weapon: REINFORCEMENTS_CARD, defense: null, dial: wantedDial, support,
reinforcementsSources: mixed, reinforcementsElite: 2 };
assert.doesNotThrow(() => applyAction(f.game, f.owner, manual),
'The actual native plan establishes the chosen physical fee is legal');
let game = structuredClone(f.game);
const truth = game.deck.find(card => card.effect === 'truthtrance'); assert.ok(truth);
takeHarassCard(game, f.observer, truth.id);
game = applyAction(game, f.observer, { type: 'card', card: truth.id });
while (game.truthtrance!.stage === 'priority') {
const actor = game.players.find(p => !game.truthtrance!.passed.includes(p.id))!.id;
game = applyAction(game, actor, { type: 'truthPass' });
}
game = applyAction(game, f.observer, { type: 'truthAsk', question: {
kind: 'battlePlan', target: f.owner, claim: { kind: 'and', terms: [
{ kind: 'weapon', name: 'Reinforcements' },
{ kind: 'dial', compare: 'eq', value: wantedDial },
] },
} });
assert.ok(viewGame(game, f.owner).truthBattleAnswers!.includes('yes'),
'The real special-reserve plan supports a truthful Yes');
game = applyAction(game, f.owner, { type: 'truthAnswer', answer: 'yes' });
const witness = viewGame(game, f.owner).battle!.compliantPlan; assert.ok(witness);
assert.equal(witness.dial, wantedDial);
assert.ok((witness.reinforcementsElite ?? 0) >= 2);
assert.equal(Object.values(witness.reinforcementsSources!).reduce((sum, group) => sum + group.elite, 0),
witness.reinforcementsElite);
const sealed = applyAction(game, f.owner, { type: 'battlePlan', ...witness });
assert.equal(sealed.battle!.plans[f.owner].dial, wantedDial);
assert.equal(sealed.battle!.plans[f.owner].reinforcementsElite, witness.reinforcementsElite);
});