diff --git a/docs/CURRENT_STATUS.md b/docs/CURRENT_STATUS.md index 98b6dfe3..7ec34789 100644 --- a/docs/CURRENT_STATUS.md +++ b/docs/CURRENT_STATUS.md @@ -20,6 +20,13 @@ open mode gates. Keep identified Basic-function gaps ahead of Advanced and wider interactions. Prototype labels and final acceptance gates remain. +**Preview-start guidance correction — 27 October. Integrated / Partial.** +Setup, selected expansion rule topics and Richese card inspectors now describe +supported faction starts as unfinished previews instead of claiming that all +expansion starts are unavailable. Rule and combination limitations remain; this +wording change does not certify full modes or deployed behavior. Five focused +reference/card tests, type/lint and the production build passed. + **Fremen and Guild Ambassador child arrivals — 27 October. Prototyped / Partial.** In supported bare Basic games, an Ambassador that shares an original entry with Terror may now relocate or ship its beneficiary's forces. The child arrival resolves first; a Terror token diff --git a/docs/IMPLEMENTATION_STATUS.md b/docs/IMPLEMENTATION_STATUS.md index c59496f9..d91c56e1 100644 --- a/docs/IMPLEMENTATION_STATUS.md +++ b/docs/IMPLEMENTATION_STATUS.md @@ -1,5 +1,12 @@ # Dune implementation status +## 27 October 2026 — Preview-start guidance correction + +Setup, card inspection and selected faction/card rule guides now identify +supported expansion starts as unfinished previews. Existing implementation +limits and full-mode acceptance remain open; this changes presentation only. +Five focused reference/card tests, type/lint and the production build passed. + ## 27 October 2026 — Ambassador child arrivals during overlap Fremen relocation and Guild shipment can resolve their native child arrival diff --git a/game/card-presentation.ts b/game/card-presentation.ts index 71194c68..deb9422e 100644 --- a/game/card-presentation.ts +++ b/game/card-presentation.ts @@ -90,14 +90,14 @@ export function cardPresentation(card: VisibleCard): CardPresentation { gameplay: richese.gameplay, availability: richese.card.effect === 'juiceOfSapho' - ? 'Richese effect integration and verification are incomplete. Supported controls cover Once Around first or last while your bid remains open, bounded movement and battle-choice ordering, and aggressor during the shared pre-plan opportunity. Earlier bids stay committed. Later aggressor intervention and other phase or auction modes remain unfinished; expansion starts remain disabled.' + ? 'Richese effect integration and verification are incomplete. Supported controls cover Once Around first or last while your bid remains open, bounded movement and battle-choice ordering, and aggressor during the shared pre-plan opportunity. Earlier bids stay committed. Later aggressor intervention and other phase or auction modes remain unfinished; supported Richese and expansion starts are available as unfinished previews.' : richese.card.effect === 'semutaDrug' ? 'The explicit Semuta development preview offers neutral responses after clean public ordinary-card discards, paid Box disposal, retired Ornithopter movement (including a following Bene Gesserit Intrusion), Distrans, ordinary and queued definite Truthtrance answers, four Sapho scopes, unready pre-leader Residual Poison, printed Karama cancelling CHOAM Charity/Inflation/Bene Gesserit Charity, native capture/Auditor/battle-income/Ix-substitution/Basic allied-retention powers, or settling a normal-auction purchase or winning bid, a completed CHOAM sale, clean Kulon, proactive or reactive La La La/Baliset, proactive/final-Mentat Trip to Gamont with an ordinary/elite force or concealed No-Field, accepted Jubba Cloak before storm protection, Ix-deck Thumper/Amal, three battle discard stages (including before original Tech award, native Advanced capture, Face Dance, quoted CHOAM income or Auditor) and private normal-auction or Black Market Ixian ally replacements. Acquiring a printed cancellation cost never restores its canceled effect. Tech requires a supported fresh 3–6-seat CHOAM/optional-Ix profile. Native Ixian casualty substitution keeps its original before-Tooth order. Native Basic Moritani cleanup offers only unkept played cards after the original choice and Karama response, preserving its kept card and unchanged original retention pool. The Basic Richese/Moritani CHOAM/Ecaz entry also adds private Sabotage and Robbery overflow after clean shipment/movement arrivals, preserving the original victim/draw and arrival suffix. Commitment is owner-only; the approved full-hand exchange spends Semuta without increasing your completed hand. Fresh bare Basic Richese previews now initialize these reactions with selected native E1/E2/E3 families. Clean native or BG-copy CHOAM and Ixian Ambassador private discards after ordinary shipment/movement retain the committed payout or pause before the replacement draw. Old games are unchanged; optional/Advanced entries retain their existing scope. Other pending rewards, producers and nested arrivals remain unfinished.' : richese.card.effect === 'mirrorWeapon' ? 'Mirror Weapon works in supported CHOAM/Richese-deck tables, including selected Ix/CHOAM with original Tech3+ and Advanced Strongholds2+, or existing Advanced native Ecaz/Moritani. Copied Tooth or Stone chooses before its original; a winning physical Mirror may be kept after copied Tooth or Artillery under the user-selected retention interpretation. Original Stone/Tooth uses provisional Stone-first. Typed public allocation safety, mixed E3 phase-module and other profile/full-start guards remain.' : richese.card.effect === 'stoneBurner' ? 'Stone Burner has development controls, including selected CHOAM/Ix with original Tech3+ and Advanced Strongholds2+. Earned Habbanya may decide a physical-token tie; +2 Reinforcements does not. Original Stone provisionally chooses before uncopied Tooth; Mirror copies still choose first as printed. Winner-changing physical allocations, mixed E3 phase modules and other profile/full-start limits remain guarded.' - : 'Richese effect integration and verification are incomplete. Karama, Distrans, Nullentropy Box, Ornithopter, Residual Poison, Portable Snooper, Stone Burner and Mirror Weapon have bounded card handlers; full expansion starts remain disabled.', + : 'Richese effect integration and verification are incomplete. Karama, Distrans, Nullentropy Box, Ornithopter, Residual Poison, Portable Snooper, Stone Burner and Mirror Weapon have bounded card handlers; supported Richese and expansion starts are available as unfinished previews.', topics: RULE_TOPICS.filter( (topic) => topic.id === diff --git a/game/reference.ts b/game/reference.ts index 2864bf88..a0321276 100644 --- a/game/reference.ts +++ b/game/reference.ts @@ -1312,7 +1312,7 @@ export const RULE_TOPICS: RuleTopic[] = [ definition.card.effect === 'juiceOfSapho' ? 'Use the Juice of Sapho panel for an available order change or pre-plan aggressor. Later intervention and other timing modes remain unfinished; consult the timing guide.' : definition.card.effect === 'karama' - ? 'This physical Karama uses the existing generic handler in development fixtures. In the explicit Semuta preview, clean printed cancellations of CHOAM Charity, Inflation or Bene Gesserit Charity pause on the public cost before settling that response; a clean printed normal-auction purchase or winning-bid payment pauses before its reserved lot settles; and a printed cancellation of any ordinary native CHOAM Worthless or Cunning power pauses on its public cost before the denial completes. Full Richese starts and other Karama-to-Semuta reactions remain unavailable.' + ? 'This physical Karama uses the existing generic handler in development fixtures. In the explicit Semuta preview, clean printed cancellations of CHOAM Charity, Inflation or Bene Gesserit Charity pause on the public cost before settling that response; a clean printed normal-auction purchase or winning-bid payment pauses before its reserved lot settles; and a printed cancellation of any ordinary native CHOAM Worthless or Cunning power pauses on its public cost before the denial completes. Richese starts are unfinished previews; other Karama-to-Semuta reactions remain unavailable.' : definition.card.effect === 'distrans' ? 'Use the Distrans transfer panel to choose another player and a separate held card. Open-bid timing and self-transfer remain guarded pending clarification.' : definition.card.effect === 'nullentropyBox' @@ -1328,7 +1328,7 @@ export const RULE_TOPICS: RuleTopic[] = [ : definition.card.effect === 'portableSnooper' ? 'Choose Portable Snooper as your ordinary poison defense, or use the late-defense panel after reveal before your own traitor decision. It uses ordinary winner retention and cannot stop Poison Tooth.' : definition.card.effect === 'semutaDrug' - ? 'In the explicit Richese development preview, every seat sees a neutral response to supported clean discards. A CHOAM & Richese game may include the Ix deck: Thumper pauses before worm/spice draw; Amal pauses after halving spice before opening resumes. Other public sources include ordinary cards, paid Box, Ornithopter, Distrans, definite ordinary Truthtrance answers including queued questions, supported shipment promises and battle answers before or after plan submission/reveal, four clean Sapho scopes, pre-leader Residual Poison, printed Karama canceling clean CHOAM Charity, Inflation or Bene Gesserit Charity, a clean printed Karama normal-auction purchase or winning-bid payment before lot settlement, a completed CHOAM card sale after its bank income, clean Kulon Worthless disposal before its movement bonus, proactive or reactive La La La disposal before blocking free revival, proactive or reactive Baliset before restricting movement, proactive Trip to Gamont before its ordinary/elite return or native No-Field reveal and capped recall, accepted Jubba Cloak before storm protection, and three battle batches. A private normal-auction or Black Market Ixian ally replacement also pauses before drawing, without showing its face until a holder commits; original payment and seller income settle once. Cache purchases cannot use native Ixian allied replacement. Ordinary definite Truthtrance answers pause even when another question stays reserved or the answer bound a supported shipment or unsubmitted battle-plan promise. Submitted/revealed plans bind no new promise, but their answers still offer Semuta without changing the plan. Under the user-selected exchange ruling, Commit may replace Semuta even at your faction hand limit: acquisition and Semuta disposal settle atomically, without increasing your completed hand. Reserved incoming cards still need room. For multiple eligible cards, inspect and select exactly one after commitment. Saved effects resume once. Other private discards, Karama uses, other reactive Worthless uses, inspected/partly ready Residual Poison battles, nested responses, other pending rewards and public starts remain unfinished.' + ? 'In the explicit Richese development preview, every seat sees a neutral response to supported clean discards. A CHOAM & Richese game may include the Ix deck: Thumper pauses before worm/spice draw; Amal pauses after halving spice before opening resumes. Other public sources include ordinary cards, paid Box, Ornithopter, Distrans, definite ordinary Truthtrance answers including queued questions, supported shipment promises and battle answers before or after plan submission/reveal, four clean Sapho scopes, pre-leader Residual Poison, printed Karama canceling clean CHOAM Charity, Inflation or Bene Gesserit Charity, a clean printed Karama normal-auction purchase or winning-bid payment before lot settlement, a completed CHOAM card sale after its bank income, clean Kulon Worthless disposal before its movement bonus, proactive or reactive La La La disposal before blocking free revival, proactive or reactive Baliset before restricting movement, proactive Trip to Gamont before its ordinary/elite return or native No-Field reveal and capped recall, accepted Jubba Cloak before storm protection, and three battle batches. A private normal-auction or Black Market Ixian ally replacement also pauses before drawing, without showing its face until a holder commits; original payment and seller income settle once. Cache purchases cannot use native Ixian allied replacement. Ordinary definite Truthtrance answers pause even when another question stays reserved or the answer bound a supported shipment or unsubmitted battle-plan promise. Submitted/revealed plans bind no new promise, but their answers still offer Semuta without changing the plan. Under the user-selected exchange ruling, Commit may replace Semuta even at your faction hand limit: acquisition and Semuta disposal settle atomically, without increasing your completed hand. Reserved incoming cards still need room. For multiple eligible cards, inspect and select exactly one after commitment. Saved effects resume once. Other private discards, Karama uses, other reactive Worthless uses, inspected/partly ready Residual Poison battles, nested responses, other pending rewards and wider interactions remain unfinished.' : 'Reference component only: this Richese card’s game actions are not enabled.', ...(definition.card.effect === 'semutaDrug' ? [ 'Mandatory and winner battle discards also pause before native Advanced Harkonnen capture. Claim or Continue completes the original casualties and card cleanup before the capture offer; it does not sample a captive early or repeat capture. Other pending rewards remain outside this bounded path.', @@ -2303,7 +2303,7 @@ export const RULE_TOPICS: RuleTopic[] = [ 'A pass commits until another opening card is played. Playing Amal resets the confirmations, so everyone can respond to the changed state before continuing.', 'Automatic auctions, collection and Mentat payments wait for confirmation. Unpaid bribes are not available spice until paid at Mentat. Income from the previous phase and unused ally credit are settled before the next opening.', 'In the explicitly opted-in Semuta preview with a physical Ix deck, a clean Amal discard pauses after the spice reduction and opening-pass reset. Another holder may claim only the used Amal card; all-seat decline leaves it discarded. Either path restores the same phase-opening confirmation window before bidding, draws or other opening effects begin.', - 'The server, phase controls and AI support this timing. Full expansion starts remain gated. Printed card timing, conflicts among simultaneous beginning-of-phase powers and later expansion economy interactions still need the complete audit.', + 'The server, phase controls and AI support this timing. Supported expansion starts are unfinished previews. Printed card timing, conflicts among simultaneous beginning-of-phase powers and later expansion economy interactions still need the complete audit.', ], related: ['bidding', 'collection', 'mentat', 'card-thumper', 'ix-modules'], }, @@ -2450,7 +2450,7 @@ export const RULE_TOPICS: RuleTopic[] = [ 'Each player receives four private traitor choices and keeps one. Harkonnen keeps all four automatically. Every remaining selection must finish before starting spice and forces are placed. Your starting Treachery hand is still empty.', 'Starting spice and fixed forces are then placed. Fremen distributes ten forces among Sietch Tabr, False Wall South and False Wall West, choosing their printed sectors. Basic Bene Gesserit starts with one fighter in Polar Sink. In Advanced setup, Bene Gesserit instead chooses a printed territory and sector after Fremen placement; its advisor becomes a fighter when alone.', 'After all starting force choices, each player receives one private Treachery Card and Harkonnen receives two. Dealing and entry into the first Storm phase are automatic. The table names the player whose setup choice is still required; there is no separate confirmation for dealing.', - 'Older saved tables that already received their cards keep those cards and their existing unfinished choices. Returning to a table does not restart setup or deal another hand. The six classic factions can start Advanced preview from the lobby while remaining rules and interactions are completed. Expansion starts remain unavailable.', + 'Older saved tables that already received their cards keep those cards and their existing unfinished choices. Returning to a table does not restart setup or deal another hand. Supported classic and expansion factions can start Basic or Advanced games as unfinished previews while rules and interactions are completed.', 'The browser keeps a private seat cookie. Returning to the same room in that browser restores your seat. Separate players should use separate browsers or profiles.', ], related: ['privacy', 'ai-players', 'storm', 'implementation-checklist'], @@ -4185,7 +4185,7 @@ export const RULE_TOPICS: RuleTopic[] = [ summary: 'Offer the entrant an alliance before revealing a would-trigger Terror token.', steps: [ - 'Supported entry opportunities offer private Moritani controls followed by a public Karama response and, if allowed, an accept/refuse decision for the entrant. The entrant sees the alliance terms, not the hidden token’s name, face or Moritani’s private eligibility details. Complete Moritani games remain unavailable.', + 'Supported entry opportunities offer private Moritani controls followed by a public Karama response and, if allowed, an accept/refuse decision for the entrant. The entrant sees the alliance terms, not the hidden token’s name, face or Moritani’s private eligibility details. Moritani can start as an unfinished preview; rules and interactions remain incomplete.', 'When an eligible faction would trigger Terror, Moritani may offer that entrant an alliance before revealing the token. This offer cannot be made to Ecaz.', 'If accepted, Moritani and the entrant become allies immediately, ending any existing alliance either had. Return the unrevealed Terror token to Moritani’s supply.', 'Accepting the alliance does not immediately remove shared forces. In Advanced, the ending player’s own shared fighters go to Tanks at each Shipment and Movement end, including this formation turn, unless a normal exception applies. Basic retains the later-player deadline on the following turn. This does not change the offer’s formation timing or open unsupported entry combinations.', @@ -4221,7 +4221,7 @@ export const RULE_TOPICS: RuleTopic[] = [ 'If Karama cancels the power, discard all of the defeated ally’s pending played cards. If the table allows it, retain the declared card and discard the rest. Cards awaiting this cleanup remain reserved and cannot be spent through another power during the decision or response.', 'The played cards were already revealed in battle. The table can see the retention declaration; inspection and selection do not reveal unrelated cards from the defeated ally’s hand.', 'After retention resolves, this implementation continues pending CHOAM battle income, technology transfer, Harkonnen capture and Face Dancer opportunities. The retained card is settled before those continuations; the original battle is not recalculated. This order is the current implementation of the combined rules, not a separate expansion priority ruling.', - 'The card choice, cancellation and cleanup have controls, but complete Moritani faction games remain unavailable while other powers and interactions are unfinished.', + 'The card choice, cancellation and cleanup have controls; Moritani starts remain unfinished previews while rules and interactions are completed.', ], related: [ 'faction-moritani', @@ -4707,7 +4707,7 @@ export const RULE_TOPICS: RuleTopic[] = [ 'The declared card, recipient, sector and force type are public before a Karama response. Cancellation leaves both card and force in place and prevents retrying that physical card’s effect for the phase. If the card or selected force disappears during an interruption, no return occurs and the card is not discarded for the effect.', 'At CHOAM tables, Mentat starts by settling bribes and Inflation, while victory remains pending. Play ordinary Mentat actions and mark ready, then finish the closing sales and allied exchange. CHOAM receives a final Trip to Gamont opportunity even with an empty hand. A copy acquired in the closing exchange can be used here.', 'After any final declaration and its response, CHOAM may make another available play or choose Finish and check victory. Normal stronghold wins, the tech-token bonus, Bene Gesserit prediction and final-turn special conditions use the resulting board. If nobody wins, the next turn begins. A prevented return does not skip this confirmation.', - 'The implemented timing prevents premature victory, but ordering with later simultaneous Mentat powers, future force types and module exceptions remains under audit. Full CHOAM starts remain gated alongside unfinished faction powers.', + 'The implemented timing prevents premature victory, but ordering with later simultaneous Mentat powers, future force types and module exceptions remains under audit. Supported CHOAM starts are unfinished previews, and faction powers still need complete verification.', ], related: [ 'faction-choam', @@ -4731,7 +4731,7 @@ export const RULE_TOPICS: RuleTopic[] = [ 'Protection does not cover spice, other factions or allied forces in that territory. Other CHOAM territories remain exposed. Sheltered forces need no Jubba protection. The current implementation protects against one storm movement, not later shipment or movement into the stationary storm.', 'If the effect is canceled, Jubba stays in hand and its effect is unavailable for the rest of the phase. If the declared card or threatened forces are no longer available, no card is discarded for this effect. CHOAM can then continue the storm, accepting any remaining losses.', 'A remaining-threat decision follows a successful or canceled play. Continue when finished; any Fremen storm-protection response and casualty choices follow before final movement settlement. Each successfully protected territory is listed. Protection ends when the storm finishes moving.', - 'Exact simultaneous-power ordering and the territory-wide timing interpretation remain under audit alongside the other expansion interactions. Full expansion starts remain unavailable until that audit and complete-game validation finish.', + 'Exact simultaneous-power ordering and the territory-wide timing interpretation remain under audit alongside the other expansion interactions. Supported expansion starts are unfinished previews; complete-game validation remains open.', ], related: [ 'choam-worthless', @@ -6670,7 +6670,7 @@ export const RULE_TOPICS: RuleTopic[] = [ : []), ...(id === 'ecaz-modules' ? [ - 'Ecaz inventory, public Ambassador inspection, end-of-Revival placement, six entry effects with Bene Gesserit copies and direct Ecaz Duke acquisition have focused support. Storm/explosion token returns are supported. Other effects and competing arrival ordering remain unfinished. See the linked feature checklist; full expansion starts remain disabled.', + 'Ecaz inventory, public Ambassador inspection, end-of-Revival placement, six entry effects with Bene Gesserit copies and direct Ecaz Duke acquisition have focused support. Storm/explosion token returns are supported. Other effects and competing arrival ordering remain unfinished. See the linked feature checklist; supported expansion starts are unfinished previews.', 'The Discovery prototype connects seven Spice Cards, eight tokens, Great Maker, private Collection inspection/reveal, stash rewards, revealed nested locations, next-turn free entry, sole-occupant Cistern income, bounded Orgiz transfers and later-turn Ornithopter movement. Jacurutu income, Testing Station and Shrine also have bounded prototypes. Mixed-force Jacurutu and contested benefits remain pending; see the Discovery checklist.', ] : []), diff --git a/tests/reference.test.ts b/tests/reference.test.ts index 0f03aaf8..dee7db82 100644 --- a/tests/reference.test.ts +++ b/tests/reference.test.ts @@ -15,3 +15,20 @@ void test('every phase and base faction has a discoverable rule topic with valid assert.ok(ids.has('ai-players')); }); +void test('setup and expansion guides describe available starts as unfinished previews', () => { + for (const id of [ + 'setup', + 'card-amal', + 'moritani-enemy', + 'moritani-ally-retention', + 'choam-gamont', + 'choam-jubba', + 'ecaz-modules', + ]) { + const topic = RULE_TOPICS.find((item) => item.id === id); + assert.ok(topic, `missing ${id}`); + const guidance = topic.steps.join(' '); + assert.match(guidance, /preview/i, id); + assert.doesNotMatch(guidance, /(?:expansion|CHOAM|Moritani) (?:faction )?(?:starts|games) remain (?:unavailable|disabled|gated)/i, id); + } +}); diff --git a/tests/richese-card-presentation.test.ts b/tests/richese-card-presentation.test.ts index 0fe5a233..dd2d9bf1 100644 --- a/tests/richese-card-presentation.test.ts +++ b/tests/richese-card-presentation.test.ts @@ -28,6 +28,21 @@ void test('presentation does not export source-verification metadata or unverifi } }); +void test('canonical Richese inspectors describe available previews and retain card-specific limits', () => { + const sapho = RICHESE_CARD_DEFINITIONS.find(row => row.card.effect === 'juiceOfSapho'); + const karama = RICHESE_CARD_DEFINITIONS.find(row => row.card.effect === 'karama'); + assert.ok(sapho && karama); + const saphoAvailability = cardPresentation(sapho.card).availability; + const karamaAvailability = cardPresentation(karama.card).availability; + assert.match(saphoAvailability ?? '', /supported Richese and expansion starts are available as unfinished previews/i); + assert.match(saphoAvailability ?? '', /Once Around first or last/); + assert.match(saphoAvailability ?? '', /other phase or auction modes remain unfinished/); + assert.match(karamaAvailability ?? '', /supported Richese and expansion starts are available as unfinished previews/i); + assert.match(karamaAvailability ?? '', /bounded card handlers/); + for (const definition of RICHESE_CARD_DEFINITIONS) + assert.doesNotMatch(cardPresentation(definition.card).availability ?? '', /expansion starts remain disabled/i); +}); + void test('missing, altered and merely similar Richese identities receive no canonical full guide', () => { for (const card of richeseCards()) { const impostors: Card[] = [