66 lines
4.3 KiB
TypeScript
66 lines
4.3 KiB
TypeScript
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);
|
|
});
|