Honor group alliances in Truthtrance
Verify and publish checkpoint container / container (push) Successful in 11m22s
Verify and publish checkpoint container / container (push) Successful in 11m22s
This commit is contained in:
1 parent
9cb65a21f5
commit
3e0fa2a8a2
11 files changed
+592
-24
No files matched your search
@@ -0,0 +1,61 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { baseDeck } from '../game/cards';
|
||||
import { coalitionOf, emptyCoalitionState } from '../game/coalition-alliance';
|
||||
import { applyAction, createGame, newPlayer, type Action, type Game } from '../game/engine';
|
||||
|
||||
const send = (game: Game, actor: string, action: Action) => applyAction(game, actor, action);
|
||||
|
||||
/** Stage the Nexus, spendable purse and physical card. The alliance and Truthtrance
|
||||
* priority are real actions; b and c are a's group allies, d and e outsiders. */
|
||||
function questionWindow(): Game {
|
||||
let game = createGame('GROUPBRIBETRUTH', newPlayer('a', 'Atreides', 'atreides'), false);
|
||||
game.players.push(newPlayer('b', 'Emperor', 'emperor'), newPlayer('c', 'Fremen', 'fremen'),
|
||||
newPlayer('d', 'Harkonnen', 'harkonnen'), newPlayer('e', 'Guild', 'guild'));
|
||||
Object.assign(game, {status:'playing', phase:1, turn:2, nexus:true,
|
||||
order:['a','b','c','d','e'], ready:[], deck:baseDeck()});
|
||||
game.coalitionState = emptyCoalitionState('unlimited');
|
||||
game.players.find(player => player.id === 'a')!.spice = 5;
|
||||
game = send(game, 'a', {type:'alliance', target:'b'});
|
||||
game = send(game, 'b', {type:'alliance', target:'a'});
|
||||
const group = coalitionOf(game.players, game.coalitionState, 'a'); assert.ok(group);
|
||||
game = send(game, 'a', {type:'coalitionPropose', groupId:group.id, entrant:'c',
|
||||
expectedRevision:game.coalitionState!.revision});
|
||||
for (const actor of ['b', 'c']) {
|
||||
const offer = game.coalitionState!.proposal!;
|
||||
game = send(game, actor, {type:'coalitionAnswer', event:offer.event, nexus:offer.nexus,
|
||||
turn:offer.turn, accept:true, expectedRevision:game.coalitionState!.revision});
|
||||
}
|
||||
const index = game.deck.findIndex(card => card.effect === 'truthtrance'); assert.ok(index >= 0);
|
||||
const [card] = game.deck.splice(index, 1); game.players.find(player => player.id === 'e')!.hand.push(card);
|
||||
game = send(game, 'e', {type:'card', card:card.id});
|
||||
while (game.truthtrance?.stage === 'priority') {
|
||||
const actor = game.players.find(player => !game.truthtrance!.passed.includes(player.id)); assert.ok(actor);
|
||||
game = send(game, actor.id, {type:'truthPass'});
|
||||
}
|
||||
return game;
|
||||
}
|
||||
|
||||
const fact = {kind:'fact', fact:{kind:'spice', compare:'gte', value:0}};
|
||||
function question(family: 'bribe' | 'bribeExpression' | 'mixedBribe' | 'turnActions', recipient: string) {
|
||||
const base = {kind:family, target:'a', turn:2};
|
||||
if (family === 'bribe') return {...base, recipient, minimum:1};
|
||||
if (family === 'bribeExpression') return {...base, claim:{kind:'and', terms:[
|
||||
{kind:'payment', recipient, minimum:1}, {kind:'payment', recipient:'d', minimum:1},
|
||||
]}};
|
||||
if (family === 'mixedBribe') return {...base, mixed:{kind:'or', terms:[fact,
|
||||
{kind:'action', action:{recipient, minimum:1}},
|
||||
]}};
|
||||
return {...base, mixed:{kind:'or', terms:[fact,
|
||||
{kind:'action', action:{kind:'payment', recipient, minimum:1}},
|
||||
]}};
|
||||
}
|
||||
|
||||
for (const family of ['bribe', 'bribeExpression', 'mixedBribe', 'turnActions'] as const)
|
||||
void test(`${family} question rejects an allied group payment and accepts an outsider`, () => {
|
||||
const game = questionWindow(), before = structuredClone(game);
|
||||
assert.throws(() => send(game, 'e', {type:'truthAsk', question:question(family, 'b')}));
|
||||
assert.deepEqual(game, before, 'A rejected allied-payment question retains its Truthtrance window.');
|
||||
const accepted = send(game, 'e', {type:'truthAsk', question:question(family, 'e')});
|
||||
assert.equal(accepted.truthtrance?.question?.kind, family);
|
||||
});
|
||||
Reference in new issue
Block a user