diff --git a/README.md b/README.md index 1a3f39b2..1dd12a08 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,16 @@ other-buyer cache/Black Market sale diversion with unchanged delivery and price. See the [cost, private timing, recovery evidence and remaining boundaries](docs/NEXUS_RICHESE_RULES.md#bounded-betrayal-auction-contract--30-september-2026). This does not enable public expansion starts or certify the full Nexus family. +For local **Guild Nexus Betrayal** testing, use `node --import tsx tools/start-prototype.ts --profile guild-betrayal` +on a fresh ready Basic/Advanced classic lobby with native Guild, base decks +and Nexus. Enable Homeworlds in the lobby before readiness only when exercising +Homeworld/Junction routes; the tool does not add that module to an ordinary room. +The exact-version/private-backup safeguards apply. The holder takes one whole +funded shipment payment, including their own or income overridden at Junction; +this is not a second shipment, free upfront financing or extra Guild income. +See [payment custody and source boundaries](docs/NEXUS_GUILD_RULES.md#betrayal-payment-replacement). +Existing games and public start gates remain unchanged. + Above the board, **Treachery draw pile** and **Spice draw pile** show live card counts separately from hands, auction cards and discards. See [draw-pile counts](docs/DRAW_PILES.md). diff --git a/components/game-table.tsx b/components/game-table.tsx index 1411b11b..214a74ad 100644 --- a/components/game-table.tsx +++ b/components/game-table.tsx @@ -79,6 +79,7 @@ import { NullentropyBox, NullentropySearch } from './nullentropy-box'; import { SemutaReaction } from './semuta-reaction'; import { ChoamKull } from './choam-kull'; import { NexusRicheseBetrayal } from './nexus-richese-betrayal'; +import { NexusGuildBetrayal } from './nexus-guild-betrayal'; import { OrnithopterMovement } from './ornithopter-movement'; import { DiscoveryOrnithopterMovement } from './discovery-flight-movement'; import { PlanetologistMovement } from './planetologist-movement'; @@ -302,8 +303,8 @@ export function GameTable({ ); const reactionBusy = transportBusy || !!g.roomControl?.paused || !!g.roomControl?.closed || !!me.autopilot; - const busy = reactionBusy || g.automaticContinuationPending || !!g.semutaReaction || !!g.kullReaction || !!g.richeseBetrayalReaction; - const reactionOwnsControls = !!g.kullReaction || !!g.kullCounterEvent || !!g.richeseBetrayalReaction; + const busy = reactionBusy || g.automaticContinuationPending || !!g.semutaReaction || !!g.kullReaction || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction; + const reactionOwnsControls = !!g.kullReaction || !!g.kullCounterEvent || !!g.richeseBetrayalReaction || !!g.guildBetrayalReaction; const canActivateKarama = (card: Card) => !g.karamaBlocked && canUseAsKaramaRole(g, me, card); const traitorBattle = g.battle; @@ -779,7 +780,16 @@ export function GameTable({ count > 0 && !botGroundMoveAllowed(g, me, key, boardLocation(selected, sector), 0), ); - const act = (a: Action) => void send(a); + const act = (a: Action) => { + const guildReaction = g.guildBetrayalReaction; + if (guildReaction) { + if (reactionBusy || g.status !== 'playing' || !guildReaction.canPass || guildReaction.hasPassed || + (a.type !== 'guildBetrayalPass' && a.type !== 'guildBetrayalUse') || + a.event !== guildReaction.event || + (a.type === 'guildBetrayalUse' && (!guildReaction.canUse || guildReaction.blocked))) return; + } + void send(a); + }; const choose = (id: string) => { const location = gameTerritories(g).find((candidate) => candidate.id === id); if (!location) return; @@ -1009,6 +1019,8 @@ export function GameTable({ faction(g.players.find((p) => p.id === id)!.faction).name, ) .join(' + ') || 'No winner' + : g.guildBetrayalReaction + ? 'Shipment payment acknowledgement' : g.richeseBetrayalReaction ? 'Richese auction acknowledgement' : g.kullReaction @@ -1054,6 +1066,15 @@ export function GameTable({ Preview rules and limits

)} + {g.guildBetrayalPreview && ( +

+ Guild Nexus Betrayal development preview · whole funded shipment + payment replacement, including your own payment and occupied Junction. + Classic factions with native Guild and Nexus; optional genuinely + seeded Homeworlds only. Not complete Guild or certified Nexus rules.{' '} + Preview rules and limits +

+ )} {g.status !== 'lobby' && (