92 lines
5.7 KiB
TypeScript
92 lines
5.7 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { applyAction, normalizeAutomaticGame, viewGame } from '../game/engine';
|
|
import { advancedNativePlayer, assertAdvancedNativeCustody } from './fixture-advanced-native-skills';
|
|
import {
|
|
createSmugglerKwisatzJourney, finishSmugglerKwisatzJourney,
|
|
revealSmugglerKwisatzJourney, settleSmugglerKwisatzJourney,
|
|
} from './fixture-smuggler-kwisatz-journey';
|
|
|
|
void test('native Atreides earns KH with seven paid Arrakeen casualties, then its original Smuggler collects a short real Spice Blow', () => {
|
|
const fixture = createSmugglerKwisatzJourney();
|
|
const { game, owner, opponent, trainer, key, firstBattle } = fixture;
|
|
assert.equal(advancedNativePlayer(fixture.afterSetup, 'atreides').forces['arrakeen:10'], 10);
|
|
assert.equal(viewGame(firstBattle.game, owner).players.find(p => p.id === owner)!.kwisatz!.active, false);
|
|
assert.notEqual(firstBattle.revealed.battle!.plans[owner].leader, trainer);
|
|
assert.equal(firstBattle.revealed.battle!.plans[owner].dial, 7);
|
|
assert.equal(firstBattle.revealed.battle!.plans[owner].support, 7);
|
|
assert.equal(firstBattle.settled.lastBattleContext!.winner, owner);
|
|
const veteran = advancedNativePlayer(firstBattle.settled, 'atreides');
|
|
assert.equal(veteran.battleLosses, 7);
|
|
assert.equal(veteran.tanks, 7);
|
|
assert.equal(veteran.forces['arrakeen:10'], 3);
|
|
assert.equal(veteran.spice, advancedNativePlayer(firstBattle.revealed, 'atreides').spice - 7,
|
|
'The actual supported battle pays seven before the pending first Collection opens.');
|
|
assert.equal(viewGame(game, owner).players.find(p => p.id === owner)!.kwisatz!.active, true);
|
|
for (const shipment of fixture.shipments) {
|
|
const payerBefore = shipment.before.players.find(p => p.id === shipment.step.actor)!;
|
|
const payerAfter = shipment.after.players.find(p => p.id === shipment.step.actor)!;
|
|
assert.equal(payerBefore.spice - payerAfter.spice, shipment.step.actor === owner ? 2 : 1);
|
|
assert.equal(payerBefore.reserves - payerAfter.reserves, 1);
|
|
}
|
|
assert.equal(game.turn, 2);
|
|
assert.equal(game.phase, 6);
|
|
assert.deepEqual(game.battle!.plans, {});
|
|
assert.equal(game.spice[key], 6);
|
|
const wallet = advancedNativePlayer(game, 'atreides').spice;
|
|
const ownSealed = applyAction(game, owner, fixture.planActions[0].action);
|
|
assert.equal(ownSealed.battle!.plans[owner].kwisatz, true);
|
|
assert.equal(ownSealed.battle!.plans[owner].defense, fixture.shield);
|
|
assert.deepEqual(viewGame(ownSealed, opponent).battle!.plans, {});
|
|
assert.equal(advancedNativePlayer(ownSealed, 'atreides').spice, wallet);
|
|
const pending = revealSmugglerKwisatzJourney(fixture);
|
|
const printed = advancedNativePlayer(game, 'atreides').leaders.find(l => l.id === trainer)!.strength;
|
|
assert.equal(pending.battle!.smugglerCollection!.strength, printed + 2);
|
|
assert.equal(pending.battle!.smugglerCollection!.amount, Math.min(printed + 2, 6));
|
|
assert.equal(pending.battle!.smugglerCollection!.stage, 'pending');
|
|
assert.equal(advancedNativePlayer(pending, 'atreides').spice, wallet);
|
|
assert.equal(pending.spice[key], 6);
|
|
const paid = settleSmugglerKwisatzJourney(pending);
|
|
assert.equal(paid.phase, 6);
|
|
assert.equal(paid.decision?.player, owner);
|
|
assert.equal(paid.lastBattleContext!.smugglerCollection!.stage, 'collected');
|
|
assert.equal(advancedNativePlayer(paid, 'atreides').spice, wallet + 6);
|
|
assert.equal(paid.spice[key], 0);
|
|
assert.equal(advancedNativePlayer(paid, 'atreides').leaders.find(l => l.id === trainer)!.dead, false);
|
|
assert.equal(advancedNativePlayer(paid, 'atreides').kwisatz!.usedAt, fixture.territory);
|
|
assertAdvancedNativeCustody(paid);
|
|
});
|
|
|
|
void test('earned KH adds two beyond printed Smuggler strength, pays once before cleanup, and leaves ordinary Collection separate', () => {
|
|
const fixture = createSmugglerKwisatzJourney({ pile: 'ample' });
|
|
const wallet = advancedNativePlayer(fixture.game, 'atreides').spice;
|
|
const pending = revealSmugglerKwisatzJourney(fixture);
|
|
const printed = advancedNativePlayer(pending, 'atreides').leaders.find(l => l.id === fixture.trainer)!.strength;
|
|
const amount = printed + 2;
|
|
assert.ok(amount < pending.spice[fixture.key]);
|
|
assert.equal(pending.battle!.smugglerCollection!.amount, amount);
|
|
assert.equal(advancedNativePlayer(pending, 'atreides').spice, wallet);
|
|
const paid = settleSmugglerKwisatzJourney(normalizeAutomaticGame(JSON.parse(JSON.stringify(pending))));
|
|
assert.equal(paid.phase, 6);
|
|
assert.equal(paid.decision?.kind, 'battleCards');
|
|
assert.equal(paid.lastBattleContext!.winner, fixture.owner);
|
|
assert.equal(paid.lastBattleContext!.smugglerCollection!.stage, 'collected');
|
|
assert.equal(advancedNativePlayer(paid, 'atreides').spice, wallet + amount);
|
|
assert.equal(paid.spice[fixture.key], 8 - amount);
|
|
assert.equal(advancedNativePlayer(paid, 'atreides').tanks, 7);
|
|
const restored = normalizeAutomaticGame(JSON.parse(JSON.stringify(paid)));
|
|
assert.equal(advancedNativePlayer(restored, 'atreides').spice, wallet + amount);
|
|
assert.equal(restored.spice[fixture.key], 8 - amount);
|
|
const beforeDuplicate = structuredClone(restored);
|
|
assert.throws(() => applyAction(restored, fixture.opponent, { type: 'traitorCall', call: false }));
|
|
assert.deepEqual(restored, beforeDuplicate);
|
|
const collected = finishSmugglerKwisatzJourney(restored);
|
|
assert.equal(collected.phase, 7);
|
|
assert.equal(collected.spice[fixture.key], 0);
|
|
assert.equal(advancedNativePlayer(collected, 'atreides').spice, wallet + amount + (8 - amount) + 2,
|
|
'Ordinary Collection separately gathers the remainder and native Arrakeen income; it does not pay the skill again.');
|
|
assert.equal(collected.lastBattleContext!.smugglerCollection!.amount, amount);
|
|
assert.equal(collected.lastBattleContext!.smugglerCollection!.stage, 'collected');
|
|
assertAdvancedNativeCustody(collected);
|
|
});
|