Compose Ornithopter with unused Hajr movement

Replace one unused movement entitlement by the selected card mode and retain independent Hajr movement after a completed two-group flight. Preserve distinct cohorts and later legal reuse. Adopt supplied Advanced immediate-after-movement Hajr play timing with explicit provisional online/card-group interpretation; Basic timing remains.

Validation: frozen11-file132/132, types/lint/build and12 original-action/rendered-table programmes; four minimal policies retain both continuations. Actual cards are acquired by original auctions and source groups use funded shipments. Multiple Hajr cards, advisors, wider combinations, final assurance and deployed acceptance remain open. No saved-game, reset, restart or deployment operation.
This commit is contained in:
Quintine committed 2026-10-18 12:23:37 +11:00
1 parent 6ccfaa1b4d
commit 72e77d7f4d
16 files changed
+522 -31

No files matched your search

+2 -2
View File
@@ -67,11 +67,11 @@ void test('played card escrow, owner-only remaining quotas and ended movement su
assert.equal(ended.active,'q');
});
void test('invalid source, blocked route, committed card and explicitly unresolved combinations are immutable',()=>{
for(const change of ['range','storm','prior','hajr','advisor','gift','wrongMode'] as const){
for(const change of ['range','storm','prior','advisor','gift','wrongMode'] as const){
const g=fixture(change==='advisor'?'beneGesserit':'emperor',change==='advisor');
let key=destination(g,origin,3);const extra:Partial<Action>={movementCard:card,ornithopter:'range3'};
if(change==='range')key=destination(g,origin,4);if(change==='storm')g.storm=splitLocation(key).sector;
if(change==='prior')g.players[0].moved=1;if(change==='hajr')g.hajr=['p'];
if(change==='prior')g.players[0].moved=1;
if(change==='advisor'){g.players[0].advisors={red_chasm:{}};g.players[1].forces={[origin]:1};}
if(change==='wrongMode')extra.ornithopter='both';
if(change==='gift')g.pendingRicheseGift={event:'reserved',intent:{owner:'p',recipient:'q',cardId:card},turn:g.turn,phase:g.phase,resume:{response:null,decision:null,pendingKarama:null,phaseOpening:null}} as Game['pendingRicheseGift'];