Files
Dune/tests/coalition-three-bot-preview.test.ts
T
Quintine 3c1cbd071e
Verify and publish checkpoint container / container (push) Successful in 11m1s
Fix group preview bot admission and improve CI diagnostics
2026-10-29 04:05:16 +11:00

56 lines
3.4 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { botActions } from '../game/bots';
import { DIFFICULTIES } from '../game/bot-profiles';
import { coalitionOf } from '../game/coalition-alliance';
import { applyAction, createGame, joinGame, newPlayer, viewGame, type Action, type Game } from '../game/engine';
import { advanceShortAlliance, type ShortAllianceStep } from './fixture-short-alliance-victory';
const apply = (game: Game, actor: string, action: Action) => applyAction(game, actor, action);
/** Real setup and first turn; select only unopened Spice order to reach Nexus. */
function pairAtNexus(advanced: boolean): Game {
let game = createGame('THREEGROUPBOT', newPlayer('at', 'Atreides', 'atreides'));
joinGame(game, newPlayer('em', 'Emperor', 'emperor'));
joinGame(game, newPlayer('ha', 'Harkonnen', 'harkonnen'));
if (advanced) game = apply(game, 'at', { type: 'rules', advanced: true });
game = apply(game, 'at', { type: 'coalitionPreview', variant: 'three' });
for (const seat of game.players) game = apply(game, seat.id, { type: 'ready' });
game = apply(game, 'at', advanced ? { type: 'start', advancedPreview: true } : { type: 'start' });
const actions: ShortAllianceStep[] = [];
game = advanceShortAlliance(game, state => state.status === 'playing' && state.turn === 2 && state.phase === 0, actions);
const index = game.spiceDeck.findIndex(card => 'worm' in card && !card.greatMaker && !card.suppressed && !card.thumper);
assert.ok(index >= 0);
const before = game.spiceDeck.map(card => JSON.stringify(card)).sort();
game.spiceDeck.unshift(game.spiceDeck.splice(index, 1)[0]);
assert.deepEqual(game.spiceDeck.map(card => JSON.stringify(card)).sort(), before);
game = advanceShortAlliance(game, state => state.nexus && !state.spiceWindow && !state.spiceResolution &&
!state.response && !state.decision && !state.truthtrance && !state.phaseOpening, actions);
game = apply(game, 'at', { type: 'alliance', target: 'em' });
return apply(game, 'em', { type: 'alliance', target: 'at' });
}
void test('each bot can seek admission to the three-member four-stronghold preview in Basic and Advanced', () => {
for (const advanced of [false, true]) {
const initial = pairAtNexus(advanced);
const pair = coalitionOf(initial.players, initial.coalitionState, 'at'); assert.ok(pair);
assert.equal(initial.coalitionState!.variant, undefined);
assert.equal(viewGame(initial, 'ha').coalitionPreview, 'three');
for (const difficulty of DIFFICULTIES) {
const view = viewGame(initial, 'ha');
view.players.find(player => player.id === 'ha')!.bot = difficulty;
const proposal = botActions(view).find(action => action.type === 'coalitionPropose');
assert.ok(proposal, `${advanced ? 'Advanced' : 'Basic'} ${difficulty}`);
let game = apply(initial, 'ha', proposal);
for (const actor of ['at', 'em']) {
const offer = game.coalitionState!.proposal; assert.ok(offer);
game = apply(game, actor, { type: 'coalitionAnswer', event: offer.event, nexus: offer.nexus,
turn: offer.turn, accept: true, expectedRevision: game.coalitionState!.revision });
}
assert.deepEqual(new Set(coalitionOf(game.players, game.coalitionState, 'at')!.members),
new Set(['at', 'em', 'ha']));
assert.equal(viewGame(game, 'at').victoryProgress.find(row => row.player === 'at')!.target, 4);
}
}
});