61 lines
3.5 KiB
TypeScript
61 lines
3.5 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { baseDeck } from '../game/cards';
|
|
import { parseFreeformFactV2 } from '../game/truthtrance-freeform-facts-v2';
|
|
import { parseFreeformFactV3 } from '../game/truthtrance-freeform-facts-v3';
|
|
import { handInventoryFactMatches, type HandInventoryFact } from '../game/truthtrance-hand-inventory';
|
|
|
|
void test('freeform v3 recognizes current primary-role existence and count questions', () => {
|
|
const cases: Array<[string, HandInventoryFact]> = [
|
|
['Do you have a weapon?', {kind:'handInventory', category:'weapon', compare:'gte', value:1}],
|
|
['DO YOU HAVE ANY DEFENSES IN YOUR HAND?', {kind:'handInventory', category:'defense', compare:'gte', value:1}],
|
|
['Do you have at least 02 worthless cards?', {kind:'handInventory', category:'worthless', compare:'gte', value:2}],
|
|
['Do you have exactly 0 poison weapons?', {kind:'handInventory', category:'poisonWeapon', compare:'eq', value:0}],
|
|
['Do you have at most 3 projectile weapons in your hand?', {kind:'handInventory', category:'projectileWeapon', compare:'lte', value:3}],
|
|
['Do you have any poison defenses?', {kind:'handInventory', category:'poisonDefense', compare:'gte', value:1}],
|
|
['Do you have a projectile defense?', {kind:'handInventory', category:'projectileDefense', compare:'gte', value:1}],
|
|
];
|
|
for (const [text, fact] of cases) assert.deepEqual(parseFreeformFactV3(text), fact, text);
|
|
});
|
|
|
|
void test('freeform v3 uses the existing physical hand category semantics', () => {
|
|
const deck = baseDeck();
|
|
const weapon = deck.find(card => card.kind === 'projectile')!;
|
|
const defense = deck.find(card => card.kind === 'shield')!;
|
|
const worthless = deck.find(card => card.kind === 'worthless')!;
|
|
assert.ok(weapon && defense && worthless);
|
|
const hand = [weapon, defense, worthless];
|
|
for (const text of ['Do you have a weapon?', 'Do you have a defense?',
|
|
'Do you have exactly 1 worthless card?', 'Do you have exactly 0 poison weapons?']) {
|
|
const fact = parseFreeformFactV3(text);
|
|
assert.ok(fact && fact.kind === 'handInventory', text);
|
|
assert.equal(handInventoryFactMatches(hand, fact), true, text);
|
|
}
|
|
const absent = parseFreeformFactV3('Do you have any poison defenses?');
|
|
assert.ok(absent && absent.kind === 'handInventory');
|
|
assert.equal(handInventoryFactMatches(hand, absent), false);
|
|
});
|
|
|
|
void test('freeform v3 preserves v2 named-card, spice, hand-size and compound interpretations', () => {
|
|
for (const text of [
|
|
'Do you have a Shield?', 'Do you have a Cheap Hero?', 'Do you have at least 4 spice?',
|
|
'Do you have at most 3 cards in your hand?', 'Do you have a Shield and a Snooper?',
|
|
]) {
|
|
const v2 = parseFreeformFactV2(text);
|
|
assert.ok(v2, text);
|
|
assert.deepEqual(parseFreeformFactV3(text), v2, text);
|
|
}
|
|
});
|
|
|
|
void test('freeform v3 leaves ambiguous, negative, compound and future wording manual', () => {
|
|
for (const text of [
|
|
'Do you have a weapons?', 'Do you have an at least?', 'Do you have a constructor?', 'Do you have a special card?',
|
|
'Do you have exactly -1 weapons?', 'Do you have exactly 1.5 weapons?',
|
|
'Do you have at least 9007199254740992 weapons?',
|
|
'Do you have a weapon or a Shield?', 'Do you have a weapon and a defense?',
|
|
'Do you not have a weapon?', 'Will you have a weapon?',
|
|
'Do you have a weapon this turn?', 'Do you have a weapon??',
|
|
'Do you have a weapon?\nPlease answer.', 'Do you have a weapon?'.padEnd(501, ' '),
|
|
]) assert.equal(parseFreeformFactV3(text), null, text);
|
|
});
|