import test from 'node:test'; import assert from 'node:assert/strict'; import { applyAction, viewGame } from '../game/engine'; import { botActions } from '../game/bots'; import { TERRITORIES } from '../game/board'; import { treacheryDeck } from '../game/cards'; import { nexusCoreProfile, selectedNexusWithoutCardsProfile } from '../game/faction-module-profile'; import { validateNexusCards } from '../game/nexus-cards'; import { validateDiscoveryState } from '../game/discoveries'; import { advanceSelectedIndependentNexus } from './fixture-selected-independent-nexus-cards'; import { createSelectedNexusNoCards, selectedNexusNoCardsDraw, type SelectedNexusNoCardsOptions } from './fixture-selected-nexus-no-cards'; const setups: SelectedNexusNoCardsOptions[] = [ { factions: ['atreides', 'guild', 'emperor'] as const }, { factions: ['atreides', 'guild', 'emperor'] as const, advanced: true }, { factions: ['ixians', 'ecaz', 'guild'] as const }, { factions: ['ixians', 'ecaz', 'guild'] as const, advanced: true, discovery: true }, ]; for (const options of setups) void test(`public ${options.advanced ? 'Advanced' : 'Basic'} selected Nexus without independent cards: ${options.factions.join('/')}${options.discovery ? ' Discovery' : ''}`, () => { const { lobby, setup, game, actions } = createSelectedNexusNoCards(options); assert.ok(actions.some(step => step.action.type === 'moduleOption' && step.action.module === 'nexusCards')); assert.ok(!actions.some(step => step.action.type === 'moduleOption' && step.action.module === 'ecazTreachery')); assert.notEqual(lobby.lobbyOptions?.ecazTreachery, true); assert.ok(selectedNexusWithoutCardsProfile(setup)); assert.ok(selectedNexusWithoutCardsProfile(game)); assert.ok(nexusCoreProfile(game)); assert.notEqual(game.ecazTreachery, true); assert.equal(game.leaderSkills, undefined); assert.deepEqual(game.expansions, ['ix', 'choam', 'ecaz']); assert.equal(game.phase, 0); validateNexusCards(game.nexusCards!.cards!, game.players); assert.equal(game.nexusCards!.cards!.deck.length, 12); assert.ok(Object.values(game.nexusCards!.cards!.hands).every(card => card === null)); assert.deepEqual([...game.deck, ...game.discard, ...game.players.flatMap(player => player.hand)] .map(card => card.id).sort(), treacheryDeck(game.expansions).map(card => card.id).sort()); if (options.discovery) { assert.ok(game.discoveries); validateDiscoveryState(game.discoveries); } if (options.factions.includes('ixians')) assert.equal(game.nexusIxianBetrayalPreview, true); if (options.factions.includes('ecaz')) assert.equal(game.ecazOccupyPreview, true); }); for (const advanced of [false, true]) void test(`${advanced ? 'Advanced' : 'Basic'} selected decks deal a real Nexus card and spend its shipment power`, () => { const fixture = selectedNexusNoCardsDraw(advanced); const { beforeDraw, afterDraw } = fixture; assert.equal(beforeDraw.nexusCards!.phase!.stage, 'drawing'); assert.equal(beforeDraw.nexusCards!.cards!.hands.atreides, null); const botView = viewGame(beforeDraw, 'atreides'); botView.players.find(player => player.id === 'atreides')!.bot = 'Easy'; const botChoice = botActions(botView).find(action => action.type === 'nexusCardChoice'); assert.ok(botChoice, 'The real eligible player has a legal bot choice'); assert.doesNotThrow(() => applyAction(beforeDraw, 'atreides', botChoice)); assert.equal(afterDraw.nexusCards!.cards!.hands.atreides, 'richese'); const offer = viewGame(fixture.game, 'atreides').nexusRichese; assert.ok(offer && !offer.blocked); const place = TERRITORIES.find(territory => territory.type === 'stronghold' && !territory.sectors.includes(fixture.game.storm) && fixture.game.players.every(player => Object.keys(player.forces).every(key => !key.startsWith(`${territory.id}:`)))); assert.ok(place); let game = applyAction(fixture.game, 'atreides', { type: 'ship', territory: place.id, sector: place.sectors[0], amount: 1, elite: 0, allyPayment: 0, nexus: offer.event }); game = advanceSelectedIndependentNexus(game, state => state.nexusRicheseLast?.stage === 'shipped'); assert.equal(game.nexusCards!.cards!.hands.atreides, null); assert.equal(game.nexusCards!.cards!.discard.filter(card => card === 'richese').length, 1); assert.equal(game.players.find(player => player.id === 'atreides')!.forces[`${place.id}:${place.sectors[0]}`], 1); });