Expose an explicitly unfinished Advanced preview in normal lobbies

Add room-creation and host lobby rules selectors, readiness reset, explicit
preview start and a persistent warning. Admit the six classic factions,
Tech Tokens with 3+ players and optional Stronghold Cards through genuine
setup. Keep expansion/module gates and complete-rules/publication criteria.

Persist the preview marker and enforce fresh native leaders, unchanged
piece custody and clean runtime/pacing state. Preserve private projections,
JSON continuation, exact room-entry retries and version/CAS protection.
Independent review resolved malformed leader, extra card-zone, missing
required-key and stale bot-deadline admission gaps.

Validation on the shared development tree: types, lint, 5169 offline
tests, build and 50 HTTP tests passed. The tree also contained the
separate deployment task's changes; this commit stages only preview scope.
All 57 base rosters completed real setup with each legal AI profile. Five
normal-preview-start games (2–6 seats) completed 1950 actions and
51 JSON restores without rejected actions; no strategy calibration.

Browser: actual create, host switch/readiness/Stronghold reset, explicit
start, exact private refresh, desktop and mobile warning checked. Retained
dev process stopped; backed up 1,629 saved games, restored server with all
unchanged, and resumed the same traitor choice into Storm. Baseline all-table
preservation retained 1626 rooms and 3442 seats; totals
now 1669 rooms and 3536 seats. No reset or automation.

Preview remains incomplete. Legacy unsupported expansion creation payloads
remain accepted for exact retry compatibility but cannot start. Existing
rules ambiguities and full visual acceptance remain open.
This commit is contained in:
Quintine committed 2026-09-21 17:41:35 +10:00
1 parent 0f79f28ccb
commit c5508b727a
16 files changed
+998 -115

No files matched your search

+19 -7
View File
@@ -8,6 +8,7 @@ import { EcazLoyaltyCard } from './ecaz-loyalty';
import { DrawPiles } from './draw-piles';
import { HandBrowser } from './hand-browser';
import { LobbyBotControls } from './lobby-bot-controls';
import { AdvancedPreviewNotice, RulesetControls } from './ruleset-controls';
import { IxRicheseTechnology } from './ix-richese-technology';
import { nexusGuildCunningAction, nexusGuildCunningActive, nexusGuildMovementAvailable, nexusGuildShipmentAvailable, nexusGuildSkipShipmentAction } from '@/game/nexus-guild-cunning-options';
import {
@@ -988,6 +989,7 @@ export function GameTable({
: 'Simultaneous decisions'}
</span>
</div>
{g.advanced && g.status !== 'lobby' && <AdvancedPreviewNotice compact />}
{g.status !== 'lobby' && (
<nav className="phase-track" aria-label="Turn phases">
{PHASES.map((p, i) => (
@@ -1618,6 +1620,13 @@ export function GameTable({
Share the invite above. Every player chooses a faction and
confirms they are ready.
</p>
<RulesetControls
advanced={g.advanced}
disabled={busy}
lobby
host={g.host === me.id}
onChange={(advanced) => act({ type: 'rules', advanced })}
/>
<label>
Your faction
<select
@@ -1666,19 +1675,22 @@ export function GameTable({
/>
Stronghold Cards · Advanced rules required
</label>
{actionButton(me.ready ? 'Not ready' : 'Ready to play', {
type: 'ready',
})}
{actionButton(
me.ready ? 'Not ready' : g.advanced ? 'Ready for Advanced preview' : 'Ready to play',
{ type: 'ready' },
)}
{g.host === me.id &&
actionButton(
'Begin game',
{ type: 'start' },
g.advanced ? 'Begin Advanced preview' : 'Begin game',
g.advanced
? { type: 'start', advancedPreview: true }
: { type: 'start' },
g.players.length < (g.techTokens ? 3 : 2) ||
!g.players.every((p) => p.ready),
)}
<p className="development-note">
Playable core under development. Advanced rules and expansion
games are not yet available.
Playable core under development. Advanced is available as an
unfinished preview. Expansion games are not yet available.
</p>
</>
) : g.status === 'setup' && !g.decision ? (