import assert from 'node:assert/strict'; import test from 'node:test'; import { type HomeworldCustody, HomeworldCustodyError } from '../game/homeworld-custody'; import type { HomeworldShipmentContext } from '../game/homeworld-shipment'; import { homeworldCombatArmy, homeworldCombatLocation, type HomeworldCombatContext } from '../game/homeworld-combat'; import { currentHomeworldOccupationSnapshot, homeworldOccupationSnapshotPresence } from '../game/homeworld-occupation-history'; import { createRicheseNoField, deployRicheseNoField } from '../game/richese-no-field'; import { quoteRicheseHomeworldMarkerShipment, quoteRicheseHomeworldMarkerTransfer } from '../game/richese-homeworld-marker-shipment'; import { homeworldNoFieldPresence, quoteHomeworldBattlesWithNoField } from '../game/richese-homeworld-marker-combat'; const native = 'homeworld:richese'; const foreign = 'homeworld:atreides'; const other = 'homeworld:guild'; function fixture(tokenId = 'zero') { const context: HomeworldShipmentContext = { advanced: true, players: [ { id: 'r', faction: 'richese', reserves: 7, eliteReserves: 0, ally: null }, { id: 'a', faction: 'atreides', reserves: 17, eliteReserves: 0, ally: null }, { id: 'g', faction: 'guild', reserves: 20, eliteReserves: 0, ally: null }, ] }; const custody: HomeworldCustody = { salusa: null, visitors: { [foreign]: { r: { normal: 2, elite: 0 } } } }; const noField = deployRicheseNoField(createRicheseNoField(['zero', 'three', 'five']), { tokenId, controller: 'r', location: { homeworld: foreign } }); return { context, custody, noField }; } for (const tokenId of ['zero', 'three', 'five']) { void test(`Advanced native marker return and later exit preserve ${tokenId} without materializing it`, () => { const f = fixture(tokenId), before = structuredClone(f); const returnQuote = quoteRicheseHomeworldMarkerTransfer(f.context, f.custody, { player: 'r', tokenId, source: foreign, destination: native, forces: { normal: 2, elite: 0 } }, f.noField); assert.equal(returnQuote.amount, 3); assert.equal(returnQuote.cost, 3); assert.equal(returnQuote.players!.find(player => player.id === 'r')!.reserves, 9); assert.equal(returnQuote.state!.visitors[foreign]?.r, undefined); assert.deepEqual(returnQuote.noField.deployed, { tokenId, controller: 'r', location: { homeworld: native } }); assert.equal(returnQuote.noField.lastShipped, tokenId); assert.deepEqual(returnQuote.noField.tokens, f.noField.tokens); assert.deepEqual(f, before); const context: HomeworldShipmentContext = { ...f.context, players: f.context.players.map(seat => { const next = returnQuote.players!.find(player => player.id === seat.id)!; return { ...seat, reserves: next.reserves, eliteReserves: next.eliteReserves }; }) }; const exit = quoteRicheseHomeworldMarkerTransfer(context, returnQuote.state!, { player: 'r', tokenId, source: native, destination: other, forces: { normal: 2, elite: 0 } }, returnQuote.noField); assert.equal(exit.amount, 3); assert.equal(exit.cost, 3); assert.equal(exit.players!.find(player => player.id === 'r')!.reserves, 7); assert.deepEqual(exit.state!.visitors[other].r, { normal: 2, elite: 0 }); assert.deepEqual(exit.noField.deployed, { tokenId, controller: 'r', location: { homeworld: other } }); assert.equal(exit.noField.lastShipped, tokenId); assert.deepEqual(exit.noField.tokens, f.noField.tokens); }); } void test('Basic keeps foreign-only marker endpoints and fresh native placement remains unavailable', () => { const f = fixture(), basic = { ...f.context, advanced: false }; const intent = { player: 'r', tokenId: 'zero', source: foreign, destination: native }; assert.throws(() => quoteRicheseHomeworldMarkerTransfer(basic, f.custody, intent, f.noField), HomeworldCustodyError); const nativeMarker = deployRicheseNoField(createRicheseNoField(['zero', 'three', 'five']), { tokenId: 'zero', controller: 'r', location: { homeworld: native } }); assert.throws(() => quoteRicheseHomeworldMarkerTransfer(basic, f.custody, { player: 'r', tokenId: 'zero', source: native, destination: other }, nativeMarker), HomeworldCustodyError); assert.throws(() => quoteRicheseHomeworldMarkerShipment(f.context, f.custody, { player: 'r', tokenId: 'three', destination: native }, createRicheseNoField(['zero', 'three', 'five'])), HomeworldCustodyError); assert.throws(() => quoteRicheseHomeworldMarkerTransfer(f.context, f.custody, { player: 'r', tokenId: 'zero', source: foreign, destination: foreign }, f.noField), HomeworldCustodyError); const allied: HomeworldShipmentContext = { ...f.context, players: f.context.players.map(seat => seat.id === 'r' ? { ...seat, ally: 'g' } : seat.id === 'g' ? { ...seat, ally: 'r' } : seat) }; assert.throws(() => quoteRicheseHomeworldMarkerTransfer(allied, f.custody, { player: 'r', tokenId: 'zero', source: foreign, destination: other }, f.noField), HomeworldCustodyError); }); for (const reserves of [0, 7]) { void test(`Advanced native marker preserves physical population ${reserves} and adds only presence`, () => { const f = fixture(); f.context.players[0].reserves = reserves; f.custody.visitors[native] = { a: { normal: 1, elite: 0 } }; const context: HomeworldCombatContext = { ...f.context, order: ['r', 'a', 'g'] }; const marker = { controller: 'r', location: { homeworld: native } }; const before = structuredClone({ context, custody: f.custody }); assert.deepEqual(homeworldNoFieldPresence(context, f.custody, marker), { controller: 'r', homeworld: native, effectiveForces: 1 }); assert.equal(homeworldCombatLocation(context, f.custody, native).population, reserves); assert.equal(homeworldCombatArmy(context, f.custody, native, 'r').normal, reserves); const battles = quoteHomeworldBattlesWithNoField(context, f.custody, marker); assert.equal(battles.filter(battle => battle.territory === native && battle.attacker === 'r' && battle.defender === 'a').length, 1); const snapshot = currentHomeworldOccupationSnapshot(context, f.custody, { homeworld: native, controller: 'r' }); assert.deepEqual(homeworldOccupationSnapshotPresence(snapshot, native), ['a', 'r']); assert.deepEqual({ context, custody: f.custody }, before); const basic = { ...context, advanced: false }; assert.throws(() => homeworldNoFieldPresence(basic, f.custody, marker), /own Homeworld/); assert.throws(() => currentHomeworldOccupationSnapshot(basic, f.custody, { homeworld: native, controller: 'r' }), /foreign world/); }); }