Files
Dune/tests/selected-discovery-skills-runtime.test.ts
T
Quintine 77eb2392eb
Verify and publish checkpoint container / container (push) Canceled after 0s
Support mixed Discovery decks with Leader Skills
2026-10-30 17:49:26 +11:00

73 lines
4.0 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { applyAction, viewGame } from '../game/engine';
import { botActions } from '../game/bots';
import { DIFFICULTIES } from '../game/bot-profiles';
import { treacheryDeck } from '../game/cards';
import { DISCOVERY_CARD_PLACEMENTS, validateDiscoveryState } from '../game/discoveries';
import { validateLeaderSkills } from '../game/leader-skills';
import { selectedDiscoverySkillsLobby, selectedDiscoverySkillsStart,
advanceDiscoverySkillsBlow } from './selected-discovery-skills-fixture';
for (const advanced of [false, true]) for (const factions of [
['atreides', 'guild', 'emperor'],
['ixians', 'ecaz', 'guild'],
['moritani', 'choam', 'guild'],
['ecaz', 'moritani', 'guild'],
] as const) void test(
`public ${advanced ? 'Advanced' : 'Basic'} mixed Discovery/Skills: ${factions.join('/')}`, () => {
const fixture = selectedDiscoverySkillsStart({advanced, factions});
const game = fixture.game;
assert.deepEqual(game.expansions, ['ecaz', 'ix', 'choam']);
assert.equal(game.discoveryEnabled, true);
assert.ok(game.discoveries);
assert.equal(game.discoveries.tokens.length, 8);
assert.ok(!game.nexusCards && !game.ecazTreachery);
assert.equal(game.leaderSkills!.assignments.length, factions.length);
assert.equal(fixture.actions.filter(step => step.action.type === 'leaderSkill').length, factions.length);
assert.ok(fixture.actions.some(step => step.action.type === 'moduleOption' && step.action.module === 'discoveries'));
validateLeaderSkills(game.leaderSkills!, game.players);
validateDiscoveryState(game.discoveries!);
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 (game.players.some(player => player.faction === 'ecaz')) {
assert.equal(game.ecazOccupyPreview, true);
assert.ok(game.ecazAmbassadors);
}
if (game.players.some(player => player.faction === 'moritani')) {
assert.ok(game.moritaniTerror);
if (advanced) assert.ok(game.moritaniAssassinate);
}
if (game.players.some(player => player.faction === 'ixians')) assert.ok(game.mobileStronghold);
});
for (const advanced of [false, true]) void test(
`${advanced ? 'Advanced' : 'Basic'} mixed Discovery/Skills reaches a real Discovery Spice Blow`, () => {
const fixture = selectedDiscoverySkillsStart({advanced, factions:['ixians', 'ecaz', 'guild']});
const game = advanceDiscoverySkillsBlow(structuredClone(fixture.game), fixture.actions);
assert.ok(game.spiceDiscard.flat().some(card => 'territory' in card && card.discovery === 'discovery-hagga-basin'));
const placed = game.discoveries!.tokens.filter(token => token.status === 'placed');
assert.equal(placed.length, 1);
const source = DISCOVERY_CARD_PLACEMENTS['discovery-hagga-basin'];
assert.deepEqual([placed[0].type, placed[0].territory, placed[0].sector],
[source.type, source.territory, source.sector]);
validateDiscoveryState(game.discoveries!);
validateLeaderSkills(game.leaderSkills!, game.players);
assert.ok(!game.nexusCards && !game.ecazTreachery);
assert.ok(game.active);
for (const difficulty of DIFFICULTIES) {
const view = viewGame(game, game.active);
view.players.find(player => player.id === game.active)!.bot = difficulty;
const action = botActions(view)[0]; assert.ok(action, difficulty);
assert.doesNotThrow(() => applyAction(game, game.active!, action), difficulty);
}
});
for (const faction of ['ecaz', 'moritani'] as const) void test(
`Advanced mixed Discovery/Skills with Harkonnen and ${faction} stays guarded`, () => {
const fixture = selectedDiscoverySkillsLobby({advanced:true, factions:[faction, 'harkonnen', 'ixians']});
const before = structuredClone(fixture.game);
assert.throws(() => applyAction(fixture.game, fixture.host, {type:'start', advancedPreview:true}));
assert.deepEqual(fixture.game, before);
});