Files
Dune/tests/fixture-bureaucrat-split-threshold.ts
T

70 lines
3.6 KiB
TypeScript

import assert from 'node:assert/strict';
import { applyAction, createGame, joinGame, newPlayer, type Action, type Game } from '../game/engine';
import { initializeClassicNexusSkillsPaymentsSetup, nextClassicNexusSkillsPaymentsNativeStep } from './fixture-classic-nexus-skills-payments';
/** Original skill offers/setup and actual turn-two worm alliance. Conserved
* starting counters are staged into reserves to isolate payment, not combat.
* Wallets, alliances, clocks and payment records are never assigned. */
export function createBureaucratSplitThresholdFixture(advanced = false) {
const lobby = createGame('BUREAUCRATTHRESHOLD', newPlayer('b', 'Bureaucrat', 'atreides'), advanced);
for (const [id, faction] of [['p', 'harkonnen'], ['f', 'fremen'], ['e', 'emperor'], ['g', 'guild']] as const)
joinGame(lobby, newPlayer(id, faction, faction));
let game = initializeClassicNexusSkillsPaymentsSetup({ initial: lobby, skill: 'bureaucrat' });
const actions: { actor: string; action: Action }[] = [];
const step = () => {
const next = nextClassicNexusSkillsPaymentsNativeStep(game);
assert.ok(next, `Native payment setup/progression stalled at ${game.phase}/${game.setupStage}`);
actions.push(next);
game = applyAction(game, next.actor, next.action);
};
for (let n = 0; game.status === 'setup' && n < 240; n++) step();
assert.equal(game.status, 'playing');
assert.ok(game.leaderSkills!.assignments.some(a => a.owner === 'b' && a.skill === 'bureaucrat'));
for (const player of game.players) {
player.reserves += Object.values(player.forces).reduce((a, b) => a + b, 0);
player.forces = {};
if (player.elites) {
player.elites.reserves += Object.values(player.elites.forces).reduce((a, b) => a + b, 0);
player.elites.forces = {};
}
if (player.advisors) player.advisors = {};
}
const orderSpice = (kinds: ('land' | 'worm')[]) => {
const front = kinds.map(kind => {
const index = game.spiceDeck.findIndex(card => kind === 'land' ? 'territory' in card : 'worm' in card);
assert.ok(index >= 0);
return game.spiceDeck.splice(index, 1)[0];
});
game.spiceDeck.unshift(...front);
};
orderSpice(['land', 'land']);
for (let n = 0; !(game.turn === 2 && game.phase === 1) && n < 1800; n++) step();
assert.equal(game.turn, 2); assert.equal(game.phase, 1);
orderSpice(['worm', 'land', 'land']);
let allied = false;
for (let n = 0; !(allied && game.phase === 3 && game.auction && !game.phaseOpening && !game.response && !game.decision) && n < 600; n++) {
if (game.nexus && !game.phaseOpening && !game.response && !game.decision && !game.spiceWindow && !allied) {
for (const [actor, target] of [['p', 'f'], ['f', 'p']]) {
const action: Action = { type: 'alliance', target };
actions.push({ actor, action }); game = applyAction(game, actor, action);
}
allied = true;
} else step();
}
assert.ok(allied && game.auction);
assert.equal(game.players.find(p => p.id === 'p')!.ally, 'f');
assert.equal(game.players.find(p => p.id === 'f')!.ally, 'p');
return { game, actions, payer: 'p', donor: 'f', trainer: 'b', guild: 'g', emperor: 'e' };
}
export function advanceBureaucratThresholdToMovement(state: Game, actor: string): Game {
let game = state;
for (let n = 0; !(game.phase === 5 && game.active === actor && !game.phaseOpening && !game.response && !game.decision) && n < 600; n++) {
const next = nextClassicNexusSkillsPaymentsNativeStep(game);
assert.ok(next, 'Native payment continuation stalled');
game = applyAction(game, next.actor, next.action);
}
assert.equal(game.phase, 5); assert.equal(game.active, actor);
return game;
}