Support Truthtrance questions about battle prescience
This commit is contained in:
1 parent
7d26929abd
commit
ee3e1a0ab2
10 files changed
+395
-11
No files matched your search
@@ -0,0 +1,86 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { baseDeck } from '../game/cards';
|
||||
import { ecazTreacheryCards } from '../game/ecaz-cards';
|
||||
import { createGame, newPlayer, type Game } from '../game/engine';
|
||||
import { truthFactAnswer } from '../game/truthtrance';
|
||||
import {
|
||||
knowledgeFactAnswer, knowledgeFactText, parseKnowledgeFact, truthKnowledgeOf,
|
||||
PRESCIENCE_LEADER_NAMES,
|
||||
} from '../game/truthtrance-knowledge';
|
||||
|
||||
function fixture() {
|
||||
const game = createGame('PRESTEST', newPlayer('a', 'Atreides', 'atreides'));
|
||||
const target = newPlayer('e', 'Emperor', 'emperor');
|
||||
const outsider = newPlayer('g', 'Guild', 'guild');
|
||||
game.players.push(target, outsider);
|
||||
game.phase = 6;
|
||||
const shield = baseDeck().find(card => card.name === 'Shield')!;
|
||||
target.hand.push(shield);
|
||||
game.battle = {
|
||||
territory: 'arrakeen', attacker: 'a', defender: 'e', plans: {}, revealed: false,
|
||||
traitorCalls: {}, prescience: { player: 'a', field: 'weapon', value: shield.id },
|
||||
} as NonNullable<Game['battle']>;
|
||||
return { game, owner: game.players[0], target, outsider, shield };
|
||||
}
|
||||
|
||||
void test('Prescience questions validate public faces and normalize their input', () => {
|
||||
assert.ok(PRESCIENCE_LEADER_NAMES.includes('Hasimir Fenring'));
|
||||
assert.deepEqual(parseKnowledgeFact({ kind: 'presciencePeek', field: 'leader', name: 'Hasimir Fenring', extra: true }),
|
||||
{ kind: 'presciencePeek', field: 'leader', name: 'Hasimir Fenring' });
|
||||
assert.deepEqual(parseKnowledgeFact({ kind: 'presciencePeek', field: 'dial', value: 2.5, extra: true }),
|
||||
{ kind: 'presciencePeek', field: 'dial', value: 2.5 });
|
||||
for (const fact of [
|
||||
{ kind: 'presciencePeek', field: 'leader', name: 'secret' },
|
||||
{ kind: 'presciencePeek', field: 'weapon', name: 'secret' },
|
||||
{ kind: 'presciencePeek', field: 'dial', value: -1 },
|
||||
{ kind: 'presciencePeek', field: 'dial', value: Infinity },
|
||||
{ kind: 'presciencePeek', field: 'anything', name: 'None' },
|
||||
]) assert.throws(() => parseKnowledgeFact(fact));
|
||||
assert.match(knowledgeFactText({ kind: 'presciencePeek', field: 'dial', value: 2.5 }), /dial.*2.5/);
|
||||
});
|
||||
|
||||
void test('only an entitled viewer answers from the answered live battle element', () => {
|
||||
const { game, owner, target, outsider, shield } = fixture();
|
||||
const fact = { kind: 'presciencePeek', field: 'weapon', name: shield.name } as const;
|
||||
const different = { kind: 'presciencePeek', field: 'weapon', name: 'None' } as const;
|
||||
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf(game, owner)), 'yes');
|
||||
assert.equal(knowledgeFactAnswer(different, truthKnowledgeOf(game, owner)), 'no');
|
||||
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf(game, target)), 'yes');
|
||||
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf(game, outsider)), 'unknown');
|
||||
assert.equal(knowledgeFactAnswer({ kind: 'presciencePeek', field: 'defense', name: shield.name }, truthKnowledgeOf(game, owner)), 'unknown');
|
||||
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf({ ...game, phase: 7 }, owner)), 'unknown');
|
||||
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf({ ...game, battle: null }, owner)), 'unknown');
|
||||
const pending = { ...game.battle!, prescience: { player: 'a', field: 'weapon' as const } };
|
||||
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf({ ...game, battle: pending }, owner)), 'unknown');
|
||||
const canceled = { ...game.battle!, prescience: undefined };
|
||||
assert.equal(knowledgeFactAnswer(fact, truthKnowledgeOf({ ...game, battle: canceled }, owner)), 'unknown');
|
||||
});
|
||||
|
||||
void test('dial, leader, absent card and suppressed Ecaz card follow visible battle insight', () => {
|
||||
const { game, owner, target } = fixture();
|
||||
game.battle!.prescience = { player: 'a', field: 'dial', value: 2.5 };
|
||||
assert.equal(knowledgeFactAnswer({ kind: 'presciencePeek', field: 'dial', value: 2.5 }, truthKnowledgeOf(game, owner)), 'yes');
|
||||
game.battle!.prescience = { player: 'a', field: 'leader', value: target.leaders[0].id };
|
||||
assert.equal(knowledgeFactAnswer({ kind: 'presciencePeek', field: 'leader', name: target.leaders[0].name }, truthKnowledgeOf(game, owner)), 'yes');
|
||||
game.battle!.prescience = { player: 'a', field: 'defense', value: null };
|
||||
assert.equal(knowledgeFactAnswer({ kind: 'presciencePeek', field: 'defense', name: 'None' }, truthKnowledgeOf(game, owner)), 'yes');
|
||||
const harass = ecazTreacheryCards().find(card => card.effect === 'harassWithdraw')!;
|
||||
target.hand.push(harass);
|
||||
game.battle!.prescience = { player: 'a', field: 'defense', value: harass.id };
|
||||
const knowledge = truthKnowledgeOf(game, owner);
|
||||
assert.equal(knowledgeFactAnswer({ kind: 'presciencePeek', field: 'defense', name: 'None' }, knowledge), 'yes');
|
||||
assert.equal(knowledgeFactAnswer({ kind: 'presciencePeek', field: 'defense', name: harass.name }, knowledge), 'no');
|
||||
assert.equal(truthFactAnswer(owner, { kind: 'and', terms: [
|
||||
{ kind: 'presciencePeek', field: 'defense', name: 'None' }, { kind: 'spice', compare: 'gte', value: 0 },
|
||||
] }, knowledge), 'yes');
|
||||
});
|
||||
|
||||
void test('non-entitled players never inspect the concealed answer', () => {
|
||||
const { game, outsider } = fixture();
|
||||
game.battle!.prescience = {
|
||||
player: 'a', field: 'weapon',
|
||||
get value(): never { throw new Error('Unentitled prescience access'); },
|
||||
};
|
||||
assert.equal(truthKnowledgeOf(game, outsider).presciencePeek, null);
|
||||
});
|
||||
Reference in new issue
Block a user