54 lines
3.0 KiB
TypeScript
54 lines
3.0 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { type Game } from '../game/engine';
|
|
import {
|
|
actTruthCharityPayments as act,
|
|
createTruthCharityPaymentsFixture as fixture,
|
|
truthCharityPaymentsInventory as inventory,
|
|
truthCharityPaymentsPlayer as player,
|
|
} from './fixture-truth-charity-payments';
|
|
|
|
function agree(game: Game, proposer: string, payer: string, amount: number) {
|
|
const offered = act(game, proposer, { type: 'dealOffer', target: payer, terms: 'Pay this turn.',
|
|
payment: { kind: 'deferredBribe', payer, recipient: proposer, amount, dueTurn: game.turn } });
|
|
const id = offered.deals!.at(-1)!.id;
|
|
return { game: act(offered, payer, { type: 'dealRespond', deal: id, accept: true }), id };
|
|
}
|
|
|
|
void test('two whole deal payments can be funded by paying one before a real Charity claim', () => {
|
|
// The native source plays the actual Amal at Spice Blow, halving the
|
|
// Emperor's original ten spice to five, then enters actual Basic Charity.
|
|
// Only unopened card/Spice ordering was selected; no wallet or hand staged.
|
|
const f = fixture({ source: 'phase2', advanced: false });
|
|
assert.equal(f.game.phase, 2);
|
|
assert.equal(player(f.game, f.target).spice, 5);
|
|
assert.notEqual(player(f.game, f.target).charityTurn, f.game.turn);
|
|
const first = agree(f.game, f.asker, f.target, 4);
|
|
const second = agree(first.game, f.asker, f.target, 2);
|
|
const accepted = second.game;
|
|
assert.equal(player(accepted, f.target).spice, 5, 'Both exact deals can be accepted before either payment.');
|
|
assert.equal(accepted.deals!.find(row => row.id === first.id)!.paymentStatus, 'pending');
|
|
assert.equal(accepted.deals!.find(row => row.id === second.id)!.paymentStatus, 'pending');
|
|
|
|
const beforeMalformed = structuredClone(accepted);
|
|
assert.throws(() => act(accepted, f.target, { type: 'dealPay', deal: first.id, amount: 1 }));
|
|
assert.deepEqual(accepted, beforeMalformed, 'A partial dealPay cannot settle either exact payment.');
|
|
const separate = act(accepted, f.target, { type: 'bribe', target: f.asker, amount: 1 });
|
|
assert.equal(separate.deals!.find(row => row.id === first.id)!.paymentStatus, 'pending');
|
|
assert.equal(separate.deals!.find(row => row.id === second.id)!.paymentStatus, 'pending',
|
|
'An untagged transfer does not silently settle either distinct deal.');
|
|
|
|
let game = act(accepted, f.target, { type: 'dealPay', deal: first.id });
|
|
assert.equal(player(game, f.target).spice, 1);
|
|
assert.equal(game.deals!.find(row => row.id === first.id)!.paymentStatus, 'paid');
|
|
assert.equal(game.deals!.find(row => row.id === second.id)!.paymentStatus, 'pending');
|
|
game = act(game, f.target, { type: 'charity' });
|
|
assert.equal(player(game, f.target).spice, 2);
|
|
assert.equal(player(game, f.target).charityTurn, game.turn);
|
|
game = act(game, f.target, { type: 'dealPay', deal: second.id });
|
|
assert.equal(player(game, f.target).spice, 0);
|
|
assert.equal(player(game, f.asker).bribes, 6);
|
|
assert.equal(game.deals!.find(row => row.id === second.id)!.paymentStatus, 'paid');
|
|
assert.deepEqual(inventory(game), f.originalCards);
|
|
});
|