60 lines
3.6 KiB
TypeScript
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');
|
|
});
|