Preserve Basic shared arrival reactions through Semuta

Admit the original ordered Ecaz/Moritani entry in bare Basic Richese games, retain both native opportunities during fresh discard recovery, and bind each suspended child to its actual arrival. Show the current discard response in the table banner.

Cover real five-seat setup and placements, both owner orders, physical payouts/draws/gifts, persistent controls and minimal legal bot participation.
This commit is contained in:
Quintine committed 2026-10-24 17:17:36 +11:00
1 parent 7b9938219d
commit 4b2f4f3fa3
12 files changed
+815 -23

No files matched your search

+6 -2
View File
@@ -150,8 +150,12 @@ for (const answer of ['yes', 'no'] as const) void test(`actual bought two-group
if (answer === 'yes') {
game = act(game, f.target, second);
assert.equal(game.movementPromises![0].fulfilled, true, 'Physical commitment precedes final card disposal');
// Native Ecaz retains its existing final-move Semuta boundary; the
// physical card still retires once before the ordinary entry resumes.
// Completed native Basic flights now offer their physical card before
// the original arrival; the already fulfilled promise survives that pause.
assert.equal(game.pendingTreacheryDiscard?.continuation.kind, 'ornithopterDiscard');
assert.equal(game.pendingTreacheryDiscard.reaction?.stage, 'offer');
game = passSemuta(game);
assert.equal(game.movementPromises![0].fulfilled, true);
assert.equal(game.pendingTreacheryDiscard, null);
game = act(game, f.target, { type: 'endMovement' });
} else {