Files
Dune/tests/truthtrance-spice-peek-knowledge.test.ts

60 lines
3.6 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { createGame, newPlayer } from '../game/engine';
import { SPICE_CARDS } from '../game/cards';
import { truthFactAnswer } from '../game/truthtrance';
import {
SPICE_PEEK_VALUES, knowledgeFactAnswer, knowledgeFactText,
parseKnowledgeFact, truthKnowledgeOf,
} from '../game/truthtrance-knowledge';
void test('Spice knowledge questions accept only printed territories, worm and Sandtrout', () => {
assert.deepEqual(SPICE_PEEK_VALUES, ['worm', 'sandtrout', ...SPICE_CARDS.map(([id]) => id)]);
for (const value of SPICE_PEEK_VALUES)
assert.deepEqual(parseKnowledgeFact({ kind: 'spicePeek', value, extra: 'discarded' }), { kind: 'spicePeek', value });
for (const value of ['', 'arrakeen', 'unknown', 7, null, {}, ['worm']])
assert.throws(() => parseKnowledgeFact({ kind: 'spicePeek', value }));
assert.match(knowledgeFactText({ kind: 'spicePeek', value: 'worm' }), /sandworm/);
assert.match(knowledgeFactText({ kind: 'spicePeek', value: 'hagga_basin' }), /Hagga Basin/);
});
void test('only the Atreides respondent with a current successful peek can answer', () => {
const g = createGame('PEEKTEST', newPlayer('a', 'Atreides', 'atreides'));
const atreides = g.players[0];
const other = newPlayer('other', 'Other', 'guild');
g.phase = 5;
g.spicePeekKnown = true;
const fact = { kind: 'spicePeek', value: 'hagga_basin' } as const;
g.spiceDeck = [{ territory: 'hagga_basin', amount: 6, sector: 12 }];
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf(g, atreides)), 'yes');
assert.equal(knowledgeFactAnswer({ kind: 'spicePeek', value: 'worm' }, truthKnowledgeOf(g, atreides)), 'no');
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf(g, other)), 'unknown');
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf({ ...g, spicePeekKnown: false }, atreides)), 'unknown');
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf({ ...g, phase: 6 }, atreides)), 'unknown');
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf({ ...g, spiceDeck: [] }, atreides)), 'unknown');
assert.equal(knowledgeFactAnswer(fact), 'unknown');
// Private deck access itself is fenced when this respondent is not entitled.
const hidden = { ...g, get spiceDeck(): never { throw new Error('Private deck read'); } };
assert.equal(truthKnowledgeOf(hidden, other).spicePeek, null);
hidden.phase = 6;
assert.equal(truthKnowledgeOf(hidden, atreides).spicePeek, null);
});
void test('worm, Sandtrout and discovery blows stay distinct and compose with other facts', () => {
const g = createGame('PEEKTEST', newPlayer('a', 'Atreides', 'atreides'));
const p = g.players[0];
Object.assign(g, { phase: 5, spicePeekKnown: true, spiceDeck: [{ worm: true }] });
const worm = { kind: 'spicePeek', value: 'worm' } as const;
assert.equal(knowledgeFactAnswer(worm, truthKnowledgeOf(g, p)), 'yes');
g.spiceDeck = [{ sandtrout: true }];
assert.equal(knowledgeFactAnswer(worm, truthKnowledgeOf(g, p)), 'no');
assert.equal(knowledgeFactAnswer({ kind: 'spicePeek', value: 'sandtrout' }, truthKnowledgeOf(g, p)), 'yes');
g.spiceDeck = [{ territory: 'hagga_basin', amount: 6, sector: 12, discovery: 'discovery-hagga-basin' }];
const knowledge = truthKnowledgeOf(g, p);
const blow = { kind: 'spicePeek', value: 'hagga_basin' } as const;
assert.equal(knowledgeFactAnswer(blow, knowledge), 'yes');
assert.equal(truthFactAnswer(p, { kind: 'and', terms: [blow, { kind: 'spice', compare: 'gte', value: 0 }] }, knowledge), 'yes');
assert.equal(truthFactAnswer(p, { kind: 'or', terms: [worm, { kind: 'spice', compare: 'gte', value: 0 }] }, knowledge), 'yes');
});