import assert from 'node:assert/strict'; import test from 'node:test'; import { applyAction, createGame, newPlayer } from '../game/engine'; import { baseDeck } from '../game/cards'; import { createDukeVidal, DUKE_VIDAL_ID } from '../game/duke-vidal'; import { newRevivalRules } from '../game/revival'; import { actDukeAmbassador, createDukeAmbassadorFixture } from './fixture-duke-ambassador'; /** Stage the public dead Duke and capture marker in an Advanced roster; the * actual return uses the native action. */ function revivalSource(legacy = false) { const game = createGame('DUKEPUBLICREVIVAL', newPlayer('ec', 'Ecaz', 'ecaz'), true, ['ecaz']); game.players.push(newPlayer('m', 'Moritani', 'moritani'), newPlayer('g', 'Guild', 'guild')); Object.assign(game, { status: 'playing', turn: 3, phase: 4, order: ['ec', 'm', 'g'], revivalRules: newRevivalRules() }); game.dukeVidal = createDukeVidal(); Object.assign(game.dukeVidal.leader, { dead: true, deaths: 1 }); game.players[0].spice = 10; game.players[0].leaders.slice(0, 4).forEach(leader => Object.assign(leader, { dead: true, deaths: 1 })); game.deck = baseDeck(); if (legacy) delete game.dukeCaptureUncertain; else game.dukeCaptureUncertain = true; return game; } for (const legacy of [false, true]) { void test(`public paid Duke revival clears ${legacy ? 'legacy' : 'uncertain'} capture history`, () => { const source = revivalSource(legacy), initial = structuredClone(source), before = source.players[0].spice; assert.throws(() => applyAction(source, 'ec', { type: 'reviveLeader', leader: 'not-a-leader' })); assert.deepEqual(source, initial, 'Rejected action does not clear uncertainty or spend spice'); const done = applyAction(source, 'ec', { type: 'reviveLeader', leader: DUKE_VIDAL_ID }); assert.equal(done.dukeCaptureUncertain, false); assert.equal(done.dukeVidal!.leader.dead, false); assert.equal(done.dukeVidal!.controller, null); assert.equal(done.players[0].spice, before - 5); assert.ok(done.log.some(entry => entry.text.includes('revived Duke Prad Vidal'))); }); void test(`public Ghola Duke revival clears ${legacy ? 'legacy' : 'uncertain'} capture history`, () => { const source = revivalSource(legacy); const index = source.deck.findIndex(card => card.effect === 'ghola'); assert.ok(index >= 0); const card = source.deck.splice(index, 1)[0]; source.players[0].hand.push(card); const done = applyAction(source, 'ec', { type: 'card', card: card.id, leader: DUKE_VIDAL_ID }); assert.equal(done.dukeCaptureUncertain, false); assert.equal(done.dukeVidal!.leader.dead, false); assert.equal(done.dukeVidal!.controller, null); assert.ok(done.log.some(entry => entry.text.includes('revived Duke Prad Vidal with Ghola'))); assert.ok(done.discard.some(item => item.id === card.id)); }); } void test('public Tleilaxu Ambassador Duke return clears uncertainty, but decline does not', () => { const f = createDukeAmbassadorFixture(), source = structuredClone(f.currentGrant); source.dukeCaptureUncertain = true; const declined = actDukeAmbassador(structuredClone(source), f.owner, { type: 'decision', event: f.event, decline: true }); assert.equal(declined.dukeCaptureUncertain, true); assert.equal(declined.dukeVidal!.leader.dead, true); const done = actDukeAmbassador(source, f.owner, { type: 'decision', event: f.event, leader: DUKE_VIDAL_ID }); assert.equal(done.dukeCaptureUncertain, false); assert.equal(done.dukeVidal!.leader.dead, false); assert.equal(done.dukeVidal!.controller, null); assert.ok(done.log.some(entry => entry.text.includes('revived Duke Prad Vidal for free through the Tleilaxu Ambassador'))); });