From 2d89ddb6e1aaf63a178c22c4f511fa9f832477e7 Mon Sep 17 00:00:00 2001 From: Quintine <15965533+Quintine@users.noreply.github.com> Date: Sun, 18 Oct 2026 13:56:29 +1100 Subject: [PATCH] Allow Sapho first while preserving unspent Guild timing At a clean unstarted non-Guild movement boundary, Sapho FIRST now reorders the remaining turn queue and reopens the native Advanced Guild choice. Guild may take its turn ahead or wait while all non-Guild turns retain their relative order. Protect an already granted current Guild turn, keep canceled timing locked and preserve completed turns, payments and last protection. Existing discard continuations and minimal policy options need no new state or signature format. Explain the provisional precedence in the controls and reference. Validation:7-file97/97, types/lint/build and six original-action/rendered-table programmes. Actual cache1 Sapho, original Guild wait/take, paid completed Richese prefix, Emperor2/Guild1 shipments and native phase completion. An actually dealt Karama cancels TAKE without its privilege being revived; a granted current turn cannot be displaced. Four profiles make eight legal holder/Guild proposals. Corrected an obsolete first exclusion and a fixture that mistook a later response pass for a repeated movement turn; exact failures and then the whole batch pass. This nonconflicting composition is provisional. Actual competing first, partly completed turns, other ordered actions, direct combined Semuta claim/capture, full modes, final assurance and browser/deployed acceptance remain open. No saved-room/database/reset/restart/deployment operation. --- components/juice-of-sapho.tsx | 4 +- docs/CURRENT_STATUS.md | 30 +++++ docs/IMPLEMENTATION_STATUS.md | 27 ++++ docs/JUICE_OF_SAPHO_RUNTIME.md | 77 +++++++++++- docs/RULE_DECISIONS.md | 13 +- game/engine.ts | 6 +- game/reference.ts | 6 +- tests/fixture-sapho-guild-first.ts | 164 +++++++++++++++++++++++++ tests/juice-of-sapho-engine.test.ts | 11 +- tests/sapho-guild-first-engine.test.ts | 147 ++++++++++++++++++++++ 10 files changed, 469 insertions(+), 16 deletions(-) create mode 100644 tests/fixture-sapho-guild-first.ts create mode 100644 tests/sapho-guild-first-engine.test.ts diff --git a/components/juice-of-sapho.tsx b/components/juice-of-sapho.tsx index 3a0ddd80..8146b415 100644 --- a/components/juice-of-sapho.tsx +++ b/components/juice-of-sapho.tsx @@ -20,7 +20,7 @@ function unavailableReason(game: GameView) { return 'No order change is available for you in this lot. You must not have bid or passed; discarding this card can open a hand slot, but a completed opportunity cannot be repeated. A card already committed elsewhere cannot be used.'; } if (game.phase === 5) - return 'Movement order can change only before the current combined shipment and movement turn begins. First requires all remaining turns to be unstarted and the Advanced Guild to have finished or be absent. Completed turns stay completed. Already-held positions and committed cards are unavailable.'; + return 'Movement order can change only before the current combined shipment and movement turn begins. First requires all remaining turns to be unstarted. The Advanced Guild retains its next timing choice; an already granted current Guild turn cannot be displaced. A Karama-locked privilege stays locked. Completed turns, already-held positions and committed cards remain unavailable.'; if (game.phase === 6) return game.battle ? game.battle.saphoTimingVersion === 1 @@ -77,7 +77,7 @@ export function JuiceOfSapho({ ? `Bid ${option.mode} in the current Once Around lot. Each eligible player still has only one bidding opportunity.` : battle ? `Choose your remaining battles ${option.mode}. Completed battles stay resolved. This changes who chooses next, not the aggressor or tie advantage of a battle. Other players may still choose battles against you before your turn.` - : `Take the ${option.mode} remaining combined shipment and movement turn. Completed turns stay completed${option.mode === 'last' ? ', and the Guild cannot move behind you' : ''}.`} + : `Take the ${option.mode} remaining combined shipment and movement turn. Completed turns stay completed${option.mode === 'last' ? ', and the Guild cannot move behind you' : game.advanced && game.players.some(player => player.faction === 'guild' && player.id !== game.me) ? '. Provisional first priority: the Guild retains its next legal timing choice and may take its turn before yours; a Karama-locked privilege stays locked' : ''}.`}