Files
Dune/tests/truth-traitor-harkonnen-engine.test.ts
T

70 lines
4.2 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { viewGame } from '../game/engine';
import { nexusTraitorBotActions, nexusTraitorReturnAction } from '../game/nexus-traitor-options';
import { createTruthTraitorHarkonnenFixture as fixture, actTruthTraitorHarkonnen as act,
advanceTruthTraitorHarkonnen as advance, truthTraitorHarkonnenClean as clean,
truthTraitorHarkonnenInventory as inventory } from './fixture-truth-traitor-harkonnen';
import { askTruthTraitorDecision as ask } from './fixture-truth-traitor-decision';
for (const canceled of [false, true]) void test(`native allied Harkonnen declaration fulfills Yes before its ${canceled ? 'prevented' : 'allowed'} effect`, () => {
const f = fixture(); let g = ask(f.game, f.asker, f.truth, f.target);
assert.ok(viewGame(g, f.target).truthTraitorAnswers!.includes('yes'));
g = act(g, f.target, { type: 'truthAnswer', answer: 'yes' });
const promise = g.battle!.traitorDecisionPromises![0];
assert.equal(promise.beneficiary, f.beneficiary); assert.equal(promise.player, f.target);
g = act(g, f.target, { type: 'traitorCall', call: true });
assert.equal(g.response?.kind, 'harkonnenTraitor');
assert.equal(g.battle!.traitorDecisionPromises![0].fulfilled, true);
if (canceled) g = act(g, f.asker, { type: 'card', card: f.karama, mode: 'cancel' });
else g = advance(g, clean);
assert.equal(g.battle!.traitorCalls[f.target], !canceled);
assert.equal(g.battle!.traitorDecisionPromises![0].fulfilled, true);
assert.ok(!g.battle!.traitorDecisionPromises![0].released);
assert.deepEqual(inventory(g), f.originalCards);
});
void test('native Cunning return retains a promised matching identity through Truthtrance and permits another original choice', () => {
const f = fixture({ kind: 'cunning' });
const returnHeld = f.returnHeld; assert.ok(returnHeld);
let g = ask(f.game, f.asker, f.truth, f.target);
g = act(g, f.target, { type: 'truthAnswer', answer: 'yes' });
const view = viewGame(g, f.target), pending = view.nexusTraitors!.pending!;
assert.ok(pending.choices.find(choice => choice.id === f.traitorHeld)?.blocked);
assert.equal(nexusTraitorReturnAction(view, pending.event, [f.traitorHeld]), null);
const before = structuredClone(g);
assert.throws(() => act(g, f.target, returnHeld)); assert.deepEqual(g, before);
const safe = nexusTraitorBotActions(view)[0]; assert.ok(safe); assert.notDeepEqual(safe, returnHeld);
g = act(g, f.target, safe);
assert.equal(g.nexusTraitorPending, null);
g = act(g, f.target, { type: 'traitorCall', call: true });
assert.equal(g.battle!.traitorDecisionPromises![0].fulfilled, true);
assert.deepEqual(inventory(g), f.originalCards);
});
void test('native Cunning may return the matching identity after No without evading that declaration choice', () => {
const f = fixture({ kind: 'cunning' }); let g = ask(f.game, f.asker, f.truth, f.target);
assert.ok(f.returnHeld);
g = act(g, f.target, { type: 'truthAnswer', answer: 'no' });
assert.ok(!viewGame(g, f.target).nexusTraitors!.pending!.choices.find(choice => choice.id === f.traitorHeld)?.blocked);
g = act(g, f.target, f.returnHeld);
g = act(g, f.target, { type: 'traitorCall', call: false });
assert.equal(g.battle!.traitorDecisionPromises![0].fulfilled, true);
});
void test('native fulfilled declaration survives a later Cunning return of its original matching identity', () => {
const f = fixture({ kind: 'cunning' });
let g = ask(f.beforeCunning, f.asker, f.truth, f.target);
g = act(g, f.target, { type: 'truthAnswer', answer: 'yes' });
g = act(g, f.target, { type: 'traitorCall', call: true });
assert.equal(g.battle!.traitorDecisionPromises![0].fulfilled, true);
const offer = viewGame(g, f.target).nexusTraitors!.offer!; assert.ok(!offer.blocked);
g = act(g, f.target, { type: 'nexusTraitorDraw', mode: 'cunning', event: offer.event });
const pending = viewGame(g, f.target).nexusTraitors!.pending!;
assert.ok(!pending.choices.find(choice => choice.id === f.traitorHeld)?.blocked);
const returned = nexusTraitorReturnAction(viewGame(g, f.target), pending.event, [f.traitorHeld]); assert.ok(returned);
g = act(g, f.target, returned);
assert.equal(g.battle!.traitorCalls[f.target], true);
assert.equal(g.battle!.traitorDecisionPromises![0].fulfilled, true);
});