Compose native Guild rate with module and Homeworld price sources
This commit is contained in:
1 parent
0db84c81b7
commit
a12250320c
24 files changed
+1176
-50
No files matched your search
@@ -0,0 +1,51 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { applyAction, type Game } from '../game/engine';
|
||||
import { createGuildBetrayalFixture, settleGuildBetrayalFixture } from './fixture-nexus-guild-betrayal';
|
||||
const player = (g: Game, id: string) => g.players.find(p => p.id === id)!;
|
||||
|
||||
for (const source of ['reserve', 'guildTransport', 'homeworld'] as const) {
|
||||
for (const use of [false, true]) {
|
||||
void test(`native ${source} full-price cancellation survives deferred Guild Betrayal ${use ? 'Use' : 'Pass'} until physical settlement`, () => {
|
||||
const f = createGuildBetrayalFixture({ source, payer: 'guild', homeworlds: source === 'homeworld' });
|
||||
const before = structuredClone(f.before);
|
||||
// Explicit controlled extension of the existing native source fixture:
|
||||
// conserve a real undealt Karama into the future invoice holder's hand.
|
||||
const index = before.deck.findIndex(card => card.effect === 'karama');
|
||||
assert.ok(index >= 0);
|
||||
const card = before.deck.splice(index, 1)[0];
|
||||
player(before, f.holder).hand.push(card);
|
||||
let g = applyAction(structuredClone(before), f.guild, f.declaration);
|
||||
if (g.decision?.kind === 'guildShipment' || g.decision?.kind === 'homeworldShipmentGuild')
|
||||
g = applyAction(g, f.guild, { type: 'decision', allow: true,
|
||||
...(g.decision.kind === 'homeworldShipmentGuild' ? { event: g.decision.event } : {}) });
|
||||
assert.equal(g.response?.kind, 'guildRate');
|
||||
const amount = g.pendingShipment?.amount ?? g.pendingGuildTransport?.amount ?? g.pendingHomeworldShipment!.amount;
|
||||
assert.ok(amount > 1);
|
||||
assert.ok(player(before, f.guild).spice >= amount);
|
||||
assert.equal(player(g, f.guild).spice, player(before, f.guild).spice);
|
||||
g = applyAction(g, f.holder, { type: 'card', mode: 'cancel', card: card.id });
|
||||
const frame = g.pendingGuildBetrayal!;
|
||||
assert.ok(frame);
|
||||
assert.equal(frame.invoice.price, amount);
|
||||
assert.equal(player(g, f.guild).spice, player(before, f.guild).spice);
|
||||
assert.deepEqual(player(g, f.guild).forces, player(before, f.guild).forces);
|
||||
assert.equal(player(g, f.guild).reserves, player(before, f.guild).reserves);
|
||||
assert.equal(player(g, f.guild).shipped, false);
|
||||
assert.deepEqual(g.homeworlds, before.homeworlds);
|
||||
if (use) g = applyAction(g, f.holder, { type: 'guildBetrayalUse', event: frame.invoice.event });
|
||||
g = settleGuildBetrayalFixture(g);
|
||||
assert.equal(player(g, f.guild).spice, player(before, f.guild).spice - amount);
|
||||
assert.equal(player(g, f.holder).spice, player(before, f.holder).spice + (use ? amount : 0));
|
||||
assert.equal(player(g, f.guild).shipped, true);
|
||||
assert.deepEqual(player(g, f.guild).forces, player(f.original, f.guild).forces);
|
||||
assert.equal(player(g, f.guild).reserves, player(f.original, f.guild).reserves);
|
||||
assert.deepEqual(g.homeworlds, f.original.homeworlds);
|
||||
assert.equal(g.guildBetrayal?.status, 'completed');
|
||||
assert.ok(!g.pendingGuildBetrayal);
|
||||
assert.equal(g.discard.filter(c => c.id === card.id).length, 1);
|
||||
assert.throws(() => applyAction(structuredClone(g), f.holder,
|
||||
{ type: 'guildBetrayalUse', event: frame.invoice.event }));
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user