50 lines
2.9 KiB
TypeScript
50 lines
2.9 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { applyAction, handLimit, type Action, type Game } from '../game/engine';
|
|
import { SEMUTA_DRUG_ID } from '../game/semuta-drug';
|
|
import {
|
|
createSemutaRevivalBenefitsForcesFixture,
|
|
finishSemutaRevivalBenefitsForces,
|
|
semutaRevivalBenefitsForcesInventory as inventory,
|
|
semutaRevivalBenefitsForcesPlayer as player,
|
|
} from './fixture-semuta-revival-benefits-forces';
|
|
|
|
export { inventory, player, finishSemutaRevivalBenefitsForces as finishRevival };
|
|
export const act = (game: Game, actor: string, action: Action) => applyAction(game, actor, action);
|
|
|
|
/** Original public Basic source has a real paid cache Semuta, real shipment,
|
|
* Storm casualties and CHOAM's actual three-force pending revival. This
|
|
* supplement moves only original physical Semuta, Kull and a distinct Karama
|
|
* among zones; no force, purse, quota, phase, response or request is installed. */
|
|
export function createKullRevivalSemutaFixture() {
|
|
const source = createSemutaRevivalBenefitsForcesFixture({ kind: 'choamRevival', advanced: false });
|
|
const game = structuredClone(source.game);
|
|
assert.ok(game.semutaPreview && game.kullPreview, 'Use the public Basic Kull and Semuta profile.');
|
|
const reactor = source.holder, holder = source.seller, actor = source.spender, counterOwner = source.atreides;
|
|
const originalCards = inventory(game);
|
|
const zones = [game.deck, game.discard, ...(game.richeseCache ? [game.richeseCache] : []),
|
|
...(game.richeseRemoved ? [game.richeseRemoved] : []), ...game.players.map(row => row.hand)];
|
|
const move = (id: string, destination: string) => {
|
|
const zone = zones.find(cards => cards.some(card => card.id === id));
|
|
assert.ok(zone, `The original ${id} must occupy one physical zone.`);
|
|
const [card] = zone.splice(zone.findIndex(candidate => candidate.id === id), 1);
|
|
const receiver = player(game, destination);
|
|
assert.ok(receiver.hand.length < handLimit(receiver), `The staged recipient ${destination} must have room.`);
|
|
receiver.hand.push(card);
|
|
};
|
|
move(SEMUTA_DRUG_ID, holder);
|
|
move('ix-kull-wahad', reactor);
|
|
const counter = zones.flat().find(card => card.effect === 'karama' && card.id !== source.cost &&
|
|
!card.id.startsWith('richese-'));
|
|
assert.ok(counter, 'A second actual physical Karama must exist.');
|
|
move(counter.id, counterOwner);
|
|
assert.ok(player(game, reactor).hand.some(card => card.id === 'ix-kull-wahad'));
|
|
assert.ok(player(game, holder).hand.some(card => card.id === SEMUTA_DRUG_ID));
|
|
assert.ok(player(game, actor).hand.some(card => card.id === source.cost));
|
|
assert.ok(player(game, counterOwner).hand.some(card => card.id === counter.id));
|
|
assert.deepEqual(inventory(game), originalCards);
|
|
assert.deepEqual(game.pendingRevival, source.pending);
|
|
assert.deepEqual(game.response, source.originalResponse);
|
|
return { game, source, originalCards, reactor, holder, actor, counterOwner,
|
|
kull: 'ix-kull-wahad', karama: source.cost, counter: counter.id, semuta: SEMUTA_DRUG_ID };
|
|
}
|