70 lines
4.2 KiB
TypeScript
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);
|
|
});
|