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}; }