Connect Basic shared Ecaz Orgiz Collection settlement

This commit is contained in:
Quintine committed 2026-10-14 20:07:59 +11:00
1 parent bcd1b1041a
commit 1f38f12beb
11 files changed
+196 -73

No files matched your search

+56
View File
@@ -13,6 +13,7 @@ import {
ORGIZ_PROCESSING_STATION,
DiscoveryCollectionError,
quoteDiscoveryCollection,
quoteSharedOrgiz,
type DiscoveryCollectionContext,
type DiscoveryCollectionQuote,
} from '../game/discovery-collection';
@@ -676,3 +677,58 @@ void test('two Orgiz owners resolve available collector spice in original storm
assert.equal(balance(discovery,'h'),0);
}
});
function sharedOrgizBoundary(advanced:boolean) {
const game=fixture(advanced,[['a','atreides'],['e','ecaz'],['g','guild']]);
reveal(game,ORGIZ_PROCESSING_STATION);
game.players[0].forces={[`${ORGIZ_PROCESSING_STATION}:0`]:1};
game.players[1].forces={'hagga_basin:12':1};
game.players[2].forces={'hagga_basin:13':1,'red_chasm:7':1};
game.players[1].ally='g';game.players[2].ally='e';
game.spice={'hagga_basin:12':2,'hagga_basin:13':2,'imperial_basin:9':0,'red_chasm:7':3};
const ordinary=quoteSpiceCollection(game);
return {game,context:{...game,spice:ordinary.spice},originalSpice:game.spice,
allocation:{territory:'hagga_basin',ecaz:'e',ally:'g',ecazAmount:2,allyAmount:2,method:'equal' as const}};
}
void test('shared Orgiz counts actual positive source deposits in Basic, one territory in Advanced, excluding unrelated and empty keys',()=>{
for(const advanced of [false,true]) {
const f=sharedOrgizBoundary(advanced);
const before=structuredClone(f);
const effects=quoteSharedOrgiz(f.context,f.allocation,{a:0,e:2,g:4},f.originalSpice);
assert.deepEqual(effects.map(effect=>[effect.player,effect.from,effect.location]),
advanced?[['a','e','hagga_basin']]:
[['a','e','hagga_basin:12'],['a','e','hagga_basin:13']]);
assert.deepEqual(f,before);
}
});
void test('Basic shared Orgiz exhausts the first recipient then considers the actual ally, never self',()=>{
const f=sharedOrgizBoundary(false);
f.context.players[2].forces[`${ORGIZ_PROCESSING_STATION}:0`]=1;
const allocation={...f.allocation,ecazAmount:1,allyAmount:3,method:'agreement' as const};
const effects=quoteSharedOrgiz(f.context,allocation,{a:0,e:1,g:5},f.originalSpice);
assert.deepEqual(effects.map(effect=>[effect.player,effect.from,effect.location]),
[['a','e','hagga_basin:12'],['a','g','hagga_basin:13']]);
});
void test('Basic shared Orgiz skips a zero-share Ecaz wallet and charges only the positive foreign ally',()=>{
const f=sharedOrgizBoundary(false);
const allocation={...f.allocation,ecazAmount:0,allyAmount:4,method:'agreement' as const};
const balances={a:0,e:20,g:6},before=structuredClone(balances);
const effects=quoteSharedOrgiz(f.context,allocation,balances,f.originalSpice);
assert.deepEqual(effects.map(effect=>effect.from),['g','g']);
assert.deepEqual(balances,before);
});
void test('shared Orgiz checks cumulative income overflow without mutating either purse or original source',()=>{
const f=sharedOrgizBoundary(false);
const allocation={...f.allocation,ecazAmount:4,allyAmount:0,method:'agreement' as const};
const balances={a:Number.MAX_SAFE_INTEGER-1,e:4,g:2};
const before=structuredClone({f,balances});
assert.throws(()=>quoteSharedOrgiz(f.context,allocation,balances,f.originalSpice),DiscoveryCollectionError);
assert.deepEqual({f,balances},before);
f.context.advanced=true;
assert.deepEqual(quoteSharedOrgiz(f.context,allocation,balances,f.originalSpice),
[{kind:'orgiz',player:'a',from:'e',location:'hagga_basin',amount:1,source:'player'}]);
});
+6 -4
View File
@@ -7,9 +7,10 @@ import {prepareSharedOrgizCollection,settleSharedOrgiz} from './fixture-discover
const wallets=(game:Game)=>Object.fromEntries(game.players.map(p=>[p.id,p.spice]));
const transfers=(game:Game)=>game.log.filter(entry=>entry.automatic?.name==='Orgiz Processing Station');
for(const advanced of [false,true])
for(const split of ['equal','all-ecaz','all-guild'] as const) {
void test(`Advanced native shared Collection: ${split} respects the actual foreign recipient and sole Orgiz owner`,()=>{
const position=prepareSharedOrgizCollection();
void test(`${advanced?'Advanced':'Basic'} native shared Collection: ${split} respects the actual foreign recipient and sole Orgiz owner`,()=>{
const position=prepareSharedOrgizCollection(advanced);
const original=structuredClone(position.game);
const before=wallets(original);
const choice=split==='equal'?{kind:'equal' as const}:
@@ -35,8 +36,9 @@ for(const split of ['equal','all-ecaz','all-guild'] as const) {
});
}
void test('Native shared Orgiz waits for ally acceptance and rejects the wrong actor without changing wallets',()=>{
const position=prepareSharedOrgizCollection();
for(const advanced of [false,true])
void test(`${advanced?'Advanced':'Basic'} shared Orgiz waits for ally acceptance and rejects the wrong actor without changing wallets`,()=>{
const position=prepareSharedOrgizCollection(advanced);
const before=structuredClone(position.game);
const event=before.ecazCollection!.event;
const action={type:'decision' as const,event,allocation:{kind:'propose' as const,ecazShare:position.lot.amount}};
+2 -2
View File
@@ -69,8 +69,8 @@ function prepareOrgizCollectors(advanced:boolean,terrainType:'sand'|'rock',exhau
}
/** Desert collectors enter the original shared allocation before any credit. */
export function prepareSharedOrgizCollection() {
const position=prepareOrgizCollectors(true,'sand');
export function prepareSharedOrgizCollection(advanced=true) {
const position=prepareOrgizCollectors(advanced,'sand');
const game=applyAction(position.game,position.finalAction.actor,position.finalAction.action);
assert.equal(game.decision?.kind,'ecazSpice');
const pending=game.ecazCollection!.allocation!;