Files
Dune/tests/world-skills-occupation-income.test.ts
T

84 lines
6.2 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { viewGame } from '../game/engine';
import { homeworldGameIntegrity } from '../game/homeworld-game';
import { TECH_TOKENS } from '../game/tech-tokens';
import {
completeWorldSkillsOccupation, createWorldSkillsOccupationFixture,
worldSkillsOccupationDeferred as deferred, worldSkillsOccupationInventory as inventory,
worldSkillsOccupationPlayer as player, worldSkillsOccupationSkillInventory as skills,
} from './fixture-world-skills-occupation';
for (const advanced of [false, true]) {
void test(`public trained ${advanced ? 'Advanced Worlds Tech Strongholds' : 'Basic Worlds Tech'} keeps Caladan income, other-payer Banker and phase rewards distinct`, () => {
const f = createWorldSkillsOccupationFixture({ advanced });
assert.equal(f.initial.status, 'lobby'); assert.equal(f.setup.status, 'setup');
assert.deepEqual(f.game.players.map(seat => seat.faction), ['atreides', 'ecaz', 'ixians']);
assert.deepEqual(f.game.expansions, ['ix', 'choam', 'ecaz']);
assert.ok(f.game.homeworlds && f.game.ecazTreachery && f.game.techTokens && f.game.leaderSkills);
assert.equal(!!f.game.strongholdCards, advanced);
assert.ok(f.game.homeworldOccupationPreview && f.game.spiceBankerIncomePreview);
assert.ok(!f.game.nexusCards && !f.game.discoveryEnabled && !f.game.semutaPreview);
assert.equal(f.originalInventory.length, 50); assert.equal(f.originalSkills.length, 14);
assert.deepEqual(inventory(f.game), f.originalInventory); assert.deepEqual(skills(f.game), f.originalSkills);
assert.equal(f.trainingActions.length, 3); assert.deepEqual(f.staging, []);
assert.equal(f.sourceActionCount, f.sourceActions.length);
for (const [actor, skill] of Object.entries(f.training)) {
const assignment = viewGame(f.game, actor).leaderSkills!.assignments.find(assignment => assignment.owner === actor);
assert.ok(assignment); assert.equal(assignment.skill, skill);
assert.equal(assignment.faceUp, true); assert.equal(assignment.captured, false);
assert.equal(assignment.controller, actor);
}
assert.deepEqual(f.evacuationSources, { 'homeworld:atreides': { normal: 10, elite: 0 } });
assert.equal(player(f.evacuation.after, f.native).reserves, 0);
assert.equal(player(f.evacuation.after, f.native).forces['arrakeen:10'], 20);
assert.equal(player(f.evacuation.before, f.native).spice - player(f.evacuation.after, f.native).spice, 10);
assert.deepEqual(f.bankerSource.source.bankLegs, [{ payer: f.native, amount: 10 }]);
assert.equal(f.bankerSource.source.phase, 5); assert.equal(f.bankerSource.source.turn, 1);
assert.equal(f.bankerSource.source.trainer?.assignment.owner, f.banker);
assert.equal(f.bankerSource.source.trainer?.faceUp, true);
assert.equal(f.bankerSource.grant?.owner, f.banker); assert.equal(f.bankerSource.grant?.amount, 1);
assert.notEqual(f.banker, f.native, 'The qualifying Bank10 belongs to another payer');
assert.equal(player(f.evacuation.after, f.banker).spice, player(f.evacuation.before, f.banker).spice,
'The mandatory normal grant waits in front of the shield');
assert.equal(deferred(f.evacuation.after, f.banker), 1); assert.equal(deferred(f.game, f.banker), 1);
assert.deepEqual(f.invasion.after.homeworlds?.custody?.visitors[f.world]?.[f.owner], { normal: 1, elite: 0 });
assert.equal(f.entitlement.qualification, f.qualification.event); assert.equal(f.entitlement.spice, 2);
assert.equal(f.game.techTokens?.heighliners.spice, 1);
assert.equal(f.game.spiceBankerIncome!.sources.filter(receipt => receipt.grant !== null).length, 1);
const before = structuredClone(f.game), originalTech = structuredClone(f.game.techTokens);
const result = completeWorldSkillsOccupation(f);
assert.deepEqual(f.game, before, 'The genuine trained source remains reusable before its final callback');
assert.deepEqual(result.collection.steps[0], { actor: f.current, action: f.action });
assert.equal(result.collection.after.phase, 7);
assert.equal(player(result.collection.after, f.owner).spice - player(result.collection.before, f.owner).spice, 2);
assert.equal(deferred(result.collection.after, f.banker), 1, 'Caladan Collection does not prematurely collect Banker');
assert.deepEqual(result.incomeReceipt, { world: f.world, status: 'settled', ownAmount: 2,
credits: [{ player: f.owner, amount: 2 }] });
assert.equal(player(result.collection.after, f.techOwner).spice - player(result.collection.before, f.techOwner).spice, 1);
assert.equal(result.collection.after.techTokens?.heighliners.spice, 0);
assert.equal(player(result.collection.after, f.native).spice - player(result.collection.before, f.native).spice, advanced ? 2 : 0,
'Ordinary Advanced Arrakeen Collection belongs to Atreides');
assert.equal(result.collection.after.spiceBankerIncome!.sources.length, before.spiceBankerIncome!.sources.length,
'Bank awards and Tech payouts are not another player Bank invoice');
assert.equal(player(result.mentat.after, f.banker).spice - player(result.mentat.before, f.banker).spice, 1);
assert.deepEqual(result.bankerCollection.credits, [{ owner: f.banker, amount: 1 }]);
assert.deepEqual(result.bankerCollection.grants, [f.bankerSource.cursor]);
assert.equal(result.bankerCollection.phase, 8); assert.equal(result.bankerCollection.turn, 1);
assert.equal(deferred(result.game, f.banker), 0);
assert.equal(result.game.spiceBankerIncome!.sources.filter(receipt => receipt.grant !== null).length, 1);
assert.equal(result.game.turn, 2); assert.equal(result.game.phase, 0);
for (const { id } of TECH_TOKENS) assert.equal(result.game.techTokens![id].owner, originalTech![id].owner);
if (advanced) {
assert.equal(result.game.strongholdCards?.claimedTurn, 1);
assert.equal(result.game.strongholdCards?.owners.arrakeen, f.native);
assert.equal(result.game.strongholdCards?.owners.hidden_mobile_stronghold, f.techOwner);
}
assert.deepEqual(inventory(result.game), f.originalInventory); assert.deepEqual(skills(result.game), f.originalSkills);
assert.deepEqual(result.game.leaderSkills?.assignments, f.game.leaderSkills!.assignments);
homeworldGameIntegrity(result.game);
});
}