Support unused selected decks with Nexus and Discovery
Verify and publish checkpoint container / container (push) Canceled after 0s
Verify and publish checkpoint container / container (push) Canceled after 0s
This commit is contained in:
1 parent
c8dbd44975
commit
91d45d1dec
14 files changed
+405
-17
No files matched your search
@@ -0,0 +1,71 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { createGame, joinGame, newPlayer, viewGame, type Game } from '../game/engine';
|
||||
import { botActions } from '../game/bots';
|
||||
import { DIFFICULTIES } from '../game/bot-profiles';
|
||||
import { spiceDeck, treacheryDeck } from '../game/cards';
|
||||
import { DISCOVERY_CARD_PLACEMENTS, DISCOVERY_SPICE_CARDS, validateDiscoveryState } from '../game/discoveries';
|
||||
import { actBasicSemutaAmbassador as act, basicSemutaAmbassadorClean } from './fixture-basic-semuta-ambassador';
|
||||
import { nextRicheseStrongholdsNativeStep } from './fixture-richese-strongholds';
|
||||
|
||||
function advance(game: Game, until: (state: Game) => boolean): Game {
|
||||
for (let count = 0; count < 1600; count++) {
|
||||
if (until(game)) return game;
|
||||
assert.notEqual(game.status, 'finished');
|
||||
const step = nextRicheseStrongholdsNativeStep(game);
|
||||
assert.ok(step, `No native continuation at ${game.status}/${game.turn}/${game.phase}`);
|
||||
game = act(game, step.actor, step.action);
|
||||
}
|
||||
throw Error('The original public game did not reach the requested boundary');
|
||||
}
|
||||
|
||||
for (const advanced of [false, true]) void test(
|
||||
`${advanced ? 'Advanced' : 'Basic'} classic seats with only E3 selected resolve an original Discovery Spice Blow`, () => {
|
||||
let game = createGame('UNUSEDE3DISCOVERY', newPlayer('guild', 'Guild', 'guild'), advanced, ['ecaz']);
|
||||
for (const faction of ['atreides', 'emperor'] as const)
|
||||
joinGame(game, newPlayer(faction, faction, faction));
|
||||
game = act(game, 'guild', {type:'moduleOption', module:'discoveries', enabled:true});
|
||||
for (const seat of game.players) game = act(game, seat.id, {type:'ready'});
|
||||
assert.equal(game.discoveryEnabled, true);
|
||||
game = act(game, 'guild', {type:'start', ...(advanced ? {advancedPreview:true} : {})});
|
||||
assert.equal(game.status, 'setup');
|
||||
assert.equal(game.advanced, advanced);
|
||||
assert.deepEqual(game.expansions, ['ecaz']);
|
||||
assert.deepEqual(game.players.map(p => p.faction).sort(), ['atreides', 'emperor', 'guild']);
|
||||
assert.ok(game.discoveries);
|
||||
assert.equal(game.discoveries.tokens.length, 8);
|
||||
assert.deepEqual(game.deck.map(c => c.id).sort(), treacheryDeck(['ecaz']).map(c => c.id).sort());
|
||||
assert.equal(game.spiceDeck.length, spiceDeck().length + 7);
|
||||
assert.deepEqual(game.spiceDeck.flatMap(c => 'territory' in c && c.discovery ? [c.discovery] : []).sort(),
|
||||
DISCOVERY_SPICE_CARDS.map(c => c.discovery).sort());
|
||||
assert.ok(!game.nexusCards && !game.ecazTreachery && !game.leaderSkills);
|
||||
assert.ok(!game.ecazAmbassadors && !game.moritaniTerror);
|
||||
validateDiscoveryState(game.discoveries);
|
||||
|
||||
game = advance(game, state => state.status === 'playing');
|
||||
// Reorder original unopened cards only; all draws, token selection and phase
|
||||
// transitions still pass through the native engine.
|
||||
for (const position of advanced ? [0, 1] : [0]) {
|
||||
const index = game.spiceDeck.findIndex((card, i) => i >= position && 'territory' in card &&
|
||||
(position === 0 ? card.discovery === 'discovery-hagga-basin' : !card.discovery));
|
||||
assert.ok(index >= position);
|
||||
[game.spiceDeck[position], game.spiceDeck[index]] = [game.spiceDeck[index], game.spiceDeck[position]];
|
||||
}
|
||||
game = advance(game, state => state.turn === 1 && state.phase === 5 && basicSemutaAmbassadorClean(state));
|
||||
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!);
|
||||
assert.ok(!game.nexusCards && !game.ecazTreachery);
|
||||
assert.ok(game.active);
|
||||
for (const difficulty of DIFFICULTIES) {
|
||||
const view = viewGame(game, game.active);
|
||||
view.players.find(p => p.id === game.active)!.bot = difficulty;
|
||||
const action = botActions(view)[0];
|
||||
assert.ok(action, difficulty);
|
||||
assert.doesNotThrow(() => act(game, game.active!, action), difficulty);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user