85 lines
4.1 KiB
TypeScript
85 lines
4.1 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { type Action, type Game } from '../game/engine';
|
|
import { createTruthtranceRichesePromisesFixture, advanceTruthtranceRichesePromises as advance,
|
|
actTruthtranceRichesePromises as act, truthtranceRichesePromisesInventory as inventory } from './fixture-truthtrance-richese-promises';
|
|
|
|
const seat = (game: Game, id: string) => {
|
|
const player = game.players.find(row => row.id === id); assert.ok(player); return player;
|
|
};
|
|
|
|
function choose(game: Game, fields: Record<string, unknown>): Game {
|
|
assert.ok(game.decision && game.richeseBidding);
|
|
return act(game, game.decision.player, { type: 'decision', event: game.richeseBidding.event, ...fields } as Action);
|
|
}
|
|
|
|
function responses(game: Game): Game {
|
|
for (let count = 0; game.response && count < 20; count++) {
|
|
const player = game.players.find(row => !game.response!.passed.includes(row.id)); assert.ok(player);
|
|
game = act(game, player.id, { type: 'passResponse' });
|
|
}
|
|
assert.equal(game.response, null);
|
|
return game;
|
|
}
|
|
|
|
/** Native Advanced public Richese/Atreides/Emperor setup and original card
|
|
* chronology. The pair is explicitly staged at Charity; wallets are staged only
|
|
* once the native silent lot is open. No lot, payment or held card is created. */
|
|
function lot(source: 'cache' | 'blackMarket', buyer: 'atreides' | 'richese') {
|
|
const f = createTruthtranceRichesePromisesFixture({ advanced: true });
|
|
let game = structuredClone(f.game);
|
|
seat(game, buyer).ally = 'emperor'; seat(game, 'emperor').ally = buyer;
|
|
seat(game, buyer).allySinceTurn = game.turn; seat(game, 'emperor').allySinceTurn = game.turn;
|
|
game = advance(game, state => state.decision?.kind === 'richeseBlackMarket');
|
|
if (source === 'blackMarket') {
|
|
const card = seat(game, 'richese').hand[0]; assert.ok(card);
|
|
game = choose(game, { card: card.id, method: 'silent' });
|
|
} else {
|
|
game = choose(game, { decline: true });
|
|
game = advance(game, state => state.decision?.kind === 'richeseDeclaration');
|
|
game = choose(game, { position: 'first' });
|
|
game = responses(game);
|
|
game = advance(game, state => state.decision?.kind === 'richeseCache');
|
|
const card = game.richeseCache?.[0]; assert.ok(card);
|
|
game = choose(game, { card: card.id, method: 'silent' });
|
|
}
|
|
game = responses(game);
|
|
assert.equal(game.richeseAuction?.source, source);
|
|
assert.equal(game.richeseAuction?.method, 'silent');
|
|
seat(game, buyer).spice = 10;
|
|
seat(game, 'emperor').spice = 10;
|
|
if (buyer !== 'richese') seat(game, 'richese').spice = 10;
|
|
assert.deepEqual(inventory(game), f.originalCards);
|
|
return { game, buyer, card: game.richeseAuction!.cardId, originalCards: f.originalCards };
|
|
}
|
|
|
|
function purchase(f: ReturnType<typeof lot>): Game {
|
|
let game = act(f.game, 'emperor', { type: 'pledgeAid', amount: 2 });
|
|
const event = game.richeseAuction!.event, order = [...game.richeseAuction!.order];
|
|
for (const id of order)
|
|
game = act(game, id, { type: 'richeseBid', event, amount: id === f.buyer ? 6 : 0,
|
|
allyPayment: id === f.buyer ? 2 : 0 });
|
|
return responses(game);
|
|
}
|
|
|
|
for (const source of ['cache', 'blackMarket'] as const) {
|
|
void test(`Advanced ${source} sends an Emperor ally's contribution to bank, not Richese`, () => {
|
|
const f = lot(source, 'atreides');
|
|
const game = purchase(f);
|
|
assert.equal(seat(game, 'atreides').spice, 6);
|
|
assert.equal(seat(game, 'emperor').spice, 8);
|
|
assert.equal(seat(game, 'richese').spice, 14, 'Seller receives only the buyer-funded four spice.');
|
|
assert.equal(seat(game, 'atreides').hand.filter(card => card.id === f.card).length, 1);
|
|
assert.deepEqual(inventory(game), f.originalCards);
|
|
});
|
|
|
|
void test(`Advanced ${source} paid Richese self-purchase sends only its own share to Emperor`, () => {
|
|
const f = lot(source, 'richese');
|
|
const game = purchase(f);
|
|
assert.equal(seat(game, 'richese').spice, 6);
|
|
assert.equal(seat(game, 'emperor').spice, 12, 'Emperor gets four from Richese; its own two goes to bank.');
|
|
assert.equal(seat(game, 'richese').hand.filter(card => card.id === f.card).length, 1);
|
|
assert.deepEqual(inventory(game), f.originalCards);
|
|
});
|
|
}
|