61 lines
3.2 KiB
TypeScript
61 lines
3.2 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { applyAction, createGame, joinGame, newPlayer, type Game } from '../game/engine';
|
|
import { DISCOVERY_CARD_PLACEMENTS, validateDiscoveryState } from '../game/discoveries';
|
|
import { advanceTestingStationContest } from './fixture-testing-station-contest';
|
|
|
|
export const STATION = 'ecological-testing-station';
|
|
export const SAPHO = 'richese-juice-of-sapho';
|
|
|
|
export function stationSeat(game: Game, id: string) {
|
|
const player = game.players.find(seat => seat.id === id);
|
|
assert.ok(player);
|
|
return player;
|
|
}
|
|
|
|
export function stationCards(game: Game) {
|
|
return [...game.deck, ...game.discard, ...(game.richeseCache ?? []),
|
|
...(game.richeseRemoved ?? []), ...game.players.flatMap(player => player.hand)];
|
|
}
|
|
|
|
/** Public Richese/Discovery lobby and genuine first Storm progression. The
|
|
* rare revealed Station, its two physical occupants, and Sapho's custody are
|
|
* staged after real setup; no priority frame or station choice is fabricated. */
|
|
export function createSaphoStationPriorityFixture(advanced: boolean, holderHasSapho = true) {
|
|
let game = createGame('SAPHOSTATIONPRIORITY', newPlayer('richese', 'Richese', 'richese'), advanced, ['choam']);
|
|
for (const id of ['atreides', 'emperor'] as const) joinGame(game, newPlayer(id, id, id));
|
|
game = applyAction(game, game.host, {type:'moduleOption', module:'discoveries', enabled:true});
|
|
for (const player of game.players) game = applyAction(game, player.id, {type:'ready'});
|
|
game = applyAction(game, game.host, {type:'start', ...(advanced ? {advancedPreview:true} : {})});
|
|
game = advanceTestingStationContest(game, state => state.status === 'playing');
|
|
assert.equal(game.phase, 0);
|
|
const token = game.discoveries!.tokens.find(candidate => candidate.face === STATION);
|
|
assert.ok(token && token.status === 'supply');
|
|
const placement = Object.values(DISCOVERY_CARD_PLACEMENTS).find(candidate => candidate.type === token.type);
|
|
assert.ok(placement);
|
|
Object.assign(token, {status:'placed', territory:placement.territory, sector:placement.sector, revealedTurn:game.turn});
|
|
validateDiscoveryState(game.discoveries!);
|
|
for (const id of ['atreides', 'emperor']) {
|
|
const player = stationSeat(game, id);
|
|
assert.ok(player.reserves > 0);
|
|
player.reserves--;
|
|
player.forces[`${STATION}:0`] = (player.forces[`${STATION}:0`] ?? 0) + 1;
|
|
}
|
|
const order = game.order.filter(id => id === 'atreides' || id === 'emperor');
|
|
assert.equal(order.length, 2);
|
|
const [first, holder] = order;
|
|
stationSeat(game, first).bot = 'Easy';
|
|
const beforeCards = stationCards(game).map(card => card.id).sort();
|
|
if (holderHasSapho) {
|
|
const index = game.richeseCache!.findIndex(card => card.id === SAPHO);
|
|
assert.ok(index >= 0);
|
|
const target = stationSeat(game, holder);
|
|
if (target.hand.length >= 4) game.deck.push(target.hand.pop()!);
|
|
target.hand.push(...game.richeseCache!.splice(index, 1));
|
|
}
|
|
assert.deepEqual(stationCards(game).map(card => card.id).sort(), beforeCards);
|
|
game = advanceTestingStationContest(game, state => state.decision?.kind === 'ecologicalStorm');
|
|
assert.equal(game.ecologicalStorm?.owner, first);
|
|
assert.deepEqual(game.ecologicalStorm?.queue?.order, order);
|
|
return {game, first, holder, order, beforeCards};
|
|
}
|