61 lines
3.5 KiB
TypeScript
61 lines
3.5 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { DUKE_VIDAL_ID } from '../game/duke-vidal';
|
|
import { CHEAP_HERO_TRAITOR } from '../game/traitors';
|
|
import { parseTruthFreeformFactsV9 as parse } from '../game/truthtrance-freeform-facts-v9';
|
|
|
|
const roster = [
|
|
{id:'atreides-duncan', name:'Duncan Idaho'},
|
|
{id:'fremen-chani', name:'Chani'},
|
|
{id:'joined-name', name:'And Or'},
|
|
{id:CHEAP_HERO_TRAITOR, name:'Cheap Hero / Heroine'},
|
|
{id:DUKE_VIDAL_ID, name:'Duke Vidal'},
|
|
];
|
|
|
|
void test('named traitors and unrevealed Face Dancers resolve from public names only', () => {
|
|
assert.deepEqual(parse('Is Duncan Idaho your traitor?', roster), {kind:'traitor', leader:'atreides-duncan'});
|
|
assert.deepEqual(parse('do you hold CHANI as an unrevealed face dancer?', roster), {kind:'faceDancer', leader:'fremen-chani'});
|
|
assert.deepEqual(parse('Is Cheap Hero / Heroine your traitor?', roster), {kind:'traitor', leader:CHEAP_HERO_TRAITOR});
|
|
assert.deepEqual(parse('Do you hold Cheap Hero / Heroine as an unrevealed Face Dancer?', roster),
|
|
{kind:'faceDancer', leader:CHEAP_HERO_TRAITOR});
|
|
assert.deepEqual(parse('Is And Or your traitor?', roster), {kind:'traitor', leader:'joined-name'});
|
|
assert.equal(parse('Is Cheap Hero / Heroine your traitor?', roster.filter(leader => leader.id !== CHEAP_HERO_TRAITOR)), null);
|
|
assert.equal(parse('Is Duke Vidal your traitor?', roster), null);
|
|
assert.equal(parse('Do you hold Duke Vidal as an unrevealed Face Dancer?', roster), null);
|
|
});
|
|
|
|
void test('combines unique named facts with earlier factual families', () => {
|
|
assert.deepEqual(parse('Is Duncan Idaho your traitor and do you have at least 0 spice?', roster), {
|
|
kind:'and', terms:[{kind:'traitor', leader:'atreides-duncan'}, {kind:'spice', compare:'gte', value:0}],
|
|
});
|
|
assert.deepEqual(parse('Do you hold Chani as an unrevealed Face Dancer or is the current auction card you inspected a Shield?', roster), {
|
|
kind:'or', terms:[{kind:'faceDancer', leader:'fremen-chani'}, {kind:'auctionPeek', name:'Shield'}],
|
|
});
|
|
assert.deepEqual(parse('Is Duncan Idaho your traitor and did you predict Guild and do you have a Shield?', roster), {
|
|
kind:'and', terms:[{kind:'traitor', leader:'atreides-duncan'}, {kind:'prediction',field:'faction',faction:'guild'},
|
|
{kind:'hand', name:'Shield'}],
|
|
});
|
|
});
|
|
|
|
void test('retains prior versions and refuses unknown, ambiguous or predictive wording', () => {
|
|
const ambiguous = [...roster, {id:'other-duncan', name:'Duncan Idaho'}];
|
|
assert.equal(parse('Is Duncan Idaho your traitor?', ambiguous), null);
|
|
for (const input of [
|
|
'Is Unknown Person your traitor?',
|
|
'Is Duncan Idaho your traitor or will you use a Shield?',
|
|
'Is Duncan Idaho your traitor and did you predict Guild or do you have a Shield?',
|
|
'Is Duncan Idaho your traitor??',
|
|
'Do you hold Chani as an unrevealed Face Dancer?\nAnswer now',
|
|
'Do you have a Shield?',
|
|
'Do you have a concealed No-Field with printed value 3?',
|
|
]) assert.equal(parse(input, roster), null, input);
|
|
});
|
|
|
|
void test('bounds compound expression size and connector-heavy input', () => {
|
|
const clause = 'is Duncan Idaho your traitor';
|
|
assert.equal((parse(Array.from({length:8}, () => clause).join(' and '), roster) as {terms?: unknown[]})?.terms?.length, 8);
|
|
assert.equal(parse(Array.from({length:9}, () => clause).join(' and '), roster), null);
|
|
assert.equal(parse(`Is Duncan Idaho your traitor ${'and '.repeat(25)}do you have a Shield`, roster), null);
|
|
assert.equal(parse(`Is Duncan Idaho your traitor and ${'x'.repeat(501)}`, roster), null);
|
|
});
|