88 lines
5.2 KiB
TypeScript
88 lines
5.2 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import {applyAction,viewGame} from '../game/engine';
|
|
import {askMixedShipment,mixedShipmentGame,mixedSpiceShipment} from './fixture-mixed-shipment';
|
|
import {askCompoundShipment} from './fixture-compound-shipment';
|
|
|
|
void test('Yes OR a true current spice fact permits later spending and skipping shipment without changing its historical answer',()=>{
|
|
let game=askMixedShipment(mixedShipmentGame(),mixedSpiceShipment('or','gte',10));
|
|
assert.deepEqual(viewGame(game,'p').truthShipmentAnswers,['yes']);
|
|
game=applyAction(game,'p',{type:'truthAnswer',answer:'yes'});
|
|
assert.equal(game.truthHistory!.at(-1)!.answer,'yes');
|
|
game=applyAction(game,'p',{type:'bribe',target:'a',amount:20});
|
|
assert.equal(game.players[0].spice,0);
|
|
game=applyAction(game,'p',{type:'endMovement'});
|
|
assert.equal(game.shipmentPromises![0].fulfilled,true);
|
|
assert.equal(game.players[0].shipped,false);
|
|
assert.equal(game.truthHistory!.at(-1)!.answer,'yes');
|
|
});
|
|
|
|
void test('No AND a false current spice fact permits a shipment that changes that current fact to true',()=>{
|
|
let game=askMixedShipment(mixedShipmentGame(),mixedSpiceShipment('and','lte',10));
|
|
assert.deepEqual(viewGame(game,'p').truthShipmentAnswers,['no']);
|
|
game=applyAction(game,'p',{type:'truthAnswer',answer:'no'});
|
|
game=applyAction(game,'p',{type:'ship',territory:'arrakeen',sector:10,amount:15});
|
|
assert.equal(game.players[0].spice,5);
|
|
assert.equal(game.players[0].forces['arrakeen:10'],15);
|
|
assert.equal(game.shipmentPromises![0].fulfilled,true);
|
|
assert.equal(game.truthHistory!.at(-1)!.answer,'no');
|
|
});
|
|
|
|
void test('Yes AND a true current fact requires the exact future shipment while an impossible current branch cannot be answered Yes',()=>{
|
|
let game=askMixedShipment(mixedShipmentGame(),mixedSpiceShipment('and','gte',10));
|
|
assert.deepEqual(viewGame(game,'p').truthShipmentAnswers,['yes','no']);
|
|
game=applyAction(game,'p',{type:'truthAnswer',answer:'yes'});
|
|
const before=JSON.stringify(game);
|
|
assert.throws(()=>applyAction(game,'p',{type:'endMovement'}));
|
|
assert.throws(()=>applyAction(game,'p',{type:'ship',territory:'carthag',sector:11,amount:4}));
|
|
assert.throws(()=>applyAction(game,'p',{type:'ship',territory:'arrakeen',sector:10,amount:3}));
|
|
assert.equal(JSON.stringify(game),before);
|
|
game=applyAction(game,'p',{type:'ship',territory:'arrakeen',sector:10,amount:4});
|
|
assert.equal(game.players[0].forces['arrakeen:10'],4);
|
|
const impossible=askMixedShipment(mixedShipmentGame(),mixedSpiceShipment('and','gte',21));
|
|
assert.deepEqual(viewGame(impossible,'p').truthShipmentAnswers,['no']);
|
|
assert.throws(()=>applyAction(impossible,'p',{type:'truthAnswer',answer:'yes'}));
|
|
});
|
|
|
|
void test('No OR requires every frozen branch to be false and cannot negate an already true current clause',()=>{
|
|
let game=askMixedShipment(mixedShipmentGame(),mixedSpiceShipment('or','lte',10));
|
|
assert.deepEqual(viewGame(game,'p').truthShipmentAnswers,['yes','no']);
|
|
game=applyAction(game,'p',{type:'truthAnswer',answer:'no'});
|
|
assert.throws(()=>applyAction(game,'p',{type:'ship',territory:'arrakeen',sector:10,amount:4}));
|
|
game=applyAction(game,'p',{type:'ship',territory:'carthag',sector:11,amount:15});
|
|
assert.equal(game.players[0].spice,5);
|
|
assert.equal(game.players[0].forces['carthag:11'],15);
|
|
assert.equal(game.shipmentPromises![0].fulfilled,true);
|
|
const impossible=askMixedShipment(mixedShipmentGame(),mixedSpiceShipment('or','gte',10));
|
|
assert.deepEqual(viewGame(impossible,'p').truthShipmentAnswers,['yes']);
|
|
assert.throws(()=>applyAction(impossible,'p',{type:'truthAnswer',answer:'no'}));
|
|
});
|
|
|
|
void test('nested current branches keep the selected future destination after voluntary spice changes',()=>{
|
|
let game=askMixedShipment(mixedShipmentGame(),{kind:'or',terms:[
|
|
mixedSpiceShipment('and','gte',10),
|
|
{kind:'and',terms:[{kind:'fact',fact:{kind:'spice',compare:'lte',value:10}},
|
|
{kind:'shipment',territory:'carthag',minimum:4}]},
|
|
]});
|
|
game=applyAction(game,'p',{type:'truthAnswer',answer:'yes'});
|
|
game=applyAction(game,'p',{type:'bribe',target:'a',amount:12});
|
|
assert.equal(game.players[0].spice,8);
|
|
assert.throws(()=>applyAction(game,'p',{type:'ship',territory:'carthag',sector:11,amount:4}));
|
|
game=applyAction(game,'p',{type:'ship',territory:'arrakeen',sector:10,amount:4});
|
|
assert.equal(game.players[0].spice,4);
|
|
assert.equal(game.players[0].forces['arrakeen:10'],4);
|
|
});
|
|
|
|
void test('an unconstraining mixed answer cannot override an earlier pure shipment commitment',()=>{
|
|
let game=askCompoundShipment(mixedShipmentGame(),{territory:'carthag',minimum:4});
|
|
game=applyAction(game,'p',{type:'truthAnswer',answer:'yes'});
|
|
game=askMixedShipment(game,mixedSpiceShipment('or','gte',10));
|
|
game=applyAction(game,'p',{type:'truthAnswer',answer:'yes'});
|
|
assert.equal(game.shipmentPromises!.length,2);
|
|
assert.throws(()=>applyAction(game,'p',{type:'endMovement'}));
|
|
assert.throws(()=>applyAction(game,'p',{type:'ship',territory:'arrakeen',sector:10,amount:4}));
|
|
game=applyAction(game,'p',{type:'ship',territory:'carthag',sector:11,amount:4});
|
|
assert.deepEqual(game.shipmentPromises!.map(p=>p.fulfilled),[true,true]);
|
|
assert.equal(game.players[0].forces['carthag:11'],4);
|
|
});
|