58 lines
3.3 KiB
TypeScript
58 lines
3.3 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { createGame, joinGame, newPlayer, type Action, type Game } from '../game/engine';
|
|
import { actKullPurpose as act, advanceKullPurpose as advance, kullPurposeClean as clean,
|
|
kullPurposePlayer as player, type KullPurposeStep } from './fixture-kull-purpose';
|
|
import { publicKullInventory as inventory } from './fixture-public-choam-kull';
|
|
|
|
export { act, advance, clean, player, inventory };
|
|
|
|
/** Genuine public Advanced preview entry with an explicit host Kull selection.
|
|
* The original unopened starting-deal and two Spice positions are selected;
|
|
* setup, paid shipment and subsequent decisions remain actual native actions. */
|
|
export function createAdvancedKullLobbyFixture() {
|
|
let game = createGame('ADVANCEDKULL', newPlayer('choam', 'CHOAM', 'choam'), true, ['choam', 'ix']);
|
|
for (const faction of ['emperor', 'guild'] as const) joinGame(game, newPlayer(faction, faction, faction));
|
|
const actions: KullPurposeStep[] = [];
|
|
const send = (actor: string, action: Action) => { game = act(game, actor, action, actions); };
|
|
const reach = (until: (g: Game) => boolean) => { game = advance(game, until, actions); };
|
|
send('choam', { type: 'moduleOption', module: 'kullPreview', enabled: true });
|
|
for (const seat of game.players) send(seat.id, { type: 'ready' });
|
|
const lobby = structuredClone(game);
|
|
send('choam', { type: 'start', advancedPreview: true });
|
|
const setup = structuredClone(game);
|
|
assert.equal(game.status, 'setup');
|
|
assert.equal(game.advanced, true);
|
|
assert.equal(game.kullPreview, true);
|
|
assert.ok(game.players.every(seat => seat.hand.length === 0));
|
|
const originalCards = game.deck.map(card => card.id).sort();
|
|
const selected: Game['deck'] = [];
|
|
for (const kind of ['kull', 'karama', 'karama'] as const) {
|
|
const index = game.deck.findIndex(card => kind === 'kull' ? card.id === 'ix-kull-wahad' : card.effect === 'karama');
|
|
assert.ok(index >= 0); selected.push(game.deck.splice(index, 1)[0]);
|
|
}
|
|
game.deck.unshift(...selected);
|
|
const beforeDeal = structuredClone(game);
|
|
reach(state => state.status === 'playing');
|
|
const afterSetup = structuredClone(game);
|
|
const [kull, karama, counter] = selected.map(card => card.id);
|
|
for (const [seat, card] of [['choam', kull], ['emperor', karama], ['guild', counter]] as const)
|
|
assert.ok(player(game, seat).hand.some(held => held.id === card));
|
|
assert.deepEqual(inventory(game), originalCards);
|
|
const safe: Game['spiceDeck'] = [];
|
|
for (let i = 0; i < 2; i++) {
|
|
const index = game.spiceDeck.findIndex(card => 'territory' in card && !card.discovery);
|
|
assert.ok(index >= 0); safe.push(game.spiceDeck.splice(index, 1)[0]);
|
|
}
|
|
game.spiceDeck.unshift(...safe);
|
|
reach(state => state.phase === 5 && state.active === 'choam' && clean(state));
|
|
send('choam', { type: 'endMovement' });
|
|
reach(state => state.phase === 5 && state.active === 'emperor' && clean(state));
|
|
assert.deepEqual(inventory(game), originalCards);
|
|
return { game, lobby, setup, beforeDeal, afterSetup, actions, originalCards,
|
|
kull, karama, counter, actor: 'emperor', reactor: 'choam', counterOwner: 'guild' };
|
|
}
|
|
|
|
export type AdvancedKullLobbyFixture = ReturnType<typeof createAdvancedKullLobbyFixture>;
|
|
export const advancedKullAttempt = (f: AdvancedKullLobbyFixture): Action =>
|
|
({ type: 'card', mode: 'shipment', card: f.karama, target: f.actor });
|