Add Nexus alliance and shared-victory practice
Expand the internal introduction to nine lessons and seven Basic exercises. The four-player Nexus example teaches incoming consent, outgoing accepted and unanswered offers, withdrawal, unilateral breaks and the ordinary three-solo/four-allied stronghold target. Formation shows prospective progress; victory appears only at an explicit later Mentat check on the unchanged teaching board. Fixed responses demonstrate legal choices without refining live AI. Extract ordinary pairing into quoteNexusAlliance used by both practice and engine. Keep phase and Homeworld checks, alliance dates, Nexus-card forfeiture, readiness and history in the authoritative engine. Use production strongholdProgress and quoteVictory for the example; physical forces remain separately owned. No mode, expansion or publication gate changes. Version 4 practice saves migrate all five v1, seven v2 and eight v3 lesson identities and preserve prior auction, movement, combat, Traitor and collection choices. Alliance inputs are whitelisted and semantically replayed, with impossible action sequences and phase order rejected. Nine new regression tests cover helper immutability, live engine side effects, all 24 offered practice combinations, prior-version migration and saved continuation. Existing Nexus-card forfeiture tests also pass. Independent review found no material defect. Required types, lint, 4934 offline tests and production build pass on stable final source. Browser checks confirm old completed-auction migration, keyboard consent, formed and pending refresh restoration, withdrawal/break, closed-Nexus controls, three-stronghold shortfall and four-stronghold joint win with saved result. Controls fit a 390px viewport at 309px wide and at least44px high; viewport reset. No external lesson links. Screenshot capture remains unavailable, so visual screenshot acceptance remains unverified. Fixed lessons do not certify the full curriculum, live AI strength or all rules interactions. The local development server was confirmed stopped by refused localhost connection and no matching processes. Started it once against the existing database without migration/reset. The existing K2V47CSN QA seat restored in setup with owning Atreides private hand/Traitors and rival privacy intact; its Hard Guild and circle6 remained visible. All 1337 rooms, 2805 seats and every original recovery/entry/handover/delegation/migration row are unchanged. SQLite integrity and foreign keys pass. No human play was interrupted, no recurring automation installed and no usage check or AI calibration run. HTTP/auth/schema source did not change; offline checks include recovery tests, and no broad HTTP suite was rerun. Private evidence: 20260921-alliance-practice. Full rules, expansion, multiplayer and presentation goal remains incomplete. Verified source tree: 9c74a3141aca4e049e0734209b96f68ee0e6d0e127a155a2a7562a79ea8a1a6b
This commit is contained in:
1 parent
b7ec94015a
commit
c4ff75a56d
16 files changed
+619
-81
No files matched your search
+12
-10
@@ -7,6 +7,7 @@ import { CardInspector, CardRules } from './card-inspector';
|
||||
import { PHASES } from '@/game/catalog';
|
||||
import { MovementLesson, TraitorLesson } from './introduction-practice';
|
||||
import { BiddingLesson } from './introduction-bidding';
|
||||
import { AllianceLesson } from './introduction-alliance';
|
||||
import {
|
||||
INTRODUCTION_CARDS, INTRODUCTION_LEADERS, INTRODUCTION_STEPS, INTRODUCTION_STORAGE_KEY,
|
||||
introductionBattle, introductionCollection, introductionShipment, newIntroduction, restoreIntroduction,
|
||||
@@ -25,10 +26,10 @@ export function Introduction() {
|
||||
<Link href="/">← Return to Arrakis</Link>
|
||||
<p className="eyebrow">LEARN TO PLAY · BASIC GAME</p>
|
||||
<h1>A first turn on Arrakis</h1>
|
||||
<p>Practice bidding, shipping, movement, battle plans, Traitor calls and collection, then take a seat at a real table. These are separate examples; they do not change any saved game.</p>
|
||||
<p>Practice alliances, bidding, shipping, movement, battle plans, Traitor calls and collection, then take a seat at a real table. These are separate examples; they do not change any saved game.</p>
|
||||
</header>
|
||||
{/* Remount on schema changes so a development hot update also migrates old state. */}
|
||||
{hydrated ? <IntroductionLessons key="v3" /> : <output>Restoring your lesson…</output>}
|
||||
{hydrated ? <IntroductionLessons key="v4" /> : <output>Restoring your lesson…</output>}
|
||||
</main>;
|
||||
}
|
||||
|
||||
@@ -76,8 +77,9 @@ function IntroductionLessons() {
|
||||
<ol className={styles.phases}>{PHASES.map(phase => <li key={phase}>{phase}</li>)}</ol>
|
||||
<p>The table tells you who must act. Your decisions can wait while another player seals a plan or answers a power. Automatic effects show in the chronicle.</p>
|
||||
</>}
|
||||
{state.step === 1 && <BiddingLesson state={state} update={update} />}
|
||||
{state.step === 2 && <>
|
||||
{state.step === 1 && <AllianceLesson state={state} update={update} />}
|
||||
{state.step === 2 && <BiddingLesson state={state} update={update} />}
|
||||
{state.step === 3 && <>
|
||||
<p>You have <strong>8 spice</strong> and six available reserve forces. Ship from reserves before moving on the board. This example has no discount, storm, occupancy restriction or reacting faction power.</p>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.controls}>
|
||||
@@ -101,8 +103,8 @@ function IntroductionLessons() {
|
||||
</div>
|
||||
<p className="fine">Ordinary movement reaches an adjacent territory. Ornithopters and faction powers can extend its range. Inspect the live destination guide before committing.</p>
|
||||
</>}
|
||||
{state.step === 3 && <MovementLesson state={state} update={update} />}
|
||||
{state.step === 4 && <>
|
||||
{state.step === 4 && <MovementLesson state={state} update={update} />}
|
||||
{state.step === 5 && <>
|
||||
<p>A separate battle: you are the aggressor in Wind Pass with six ordinary forces and {INTRODUCTION_LEADERS.you.name}, strength {INTRODUCTION_LEADERS.you.strength}. Your opponent also has six forces. Neither side calls a Traitor or uses a faction power in this example.</p>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.controls}>
|
||||
@@ -130,8 +132,8 @@ function IntroductionLessons() {
|
||||
</div>
|
||||
</div>
|
||||
</>}
|
||||
{state.step === 5 && <TraitorLesson state={state} update={update} />}
|
||||
{state.step === 6 && <>
|
||||
{state.step === 6 && <TraitorLesson state={state} update={update} />}
|
||||
{state.step === 7 && <>
|
||||
<p>A fresh position has 8 spice in Wind Pass, sector 14. You have surviving forces in that same sector, outside the storm. Collection uses the forces still on the board after battles.</p>
|
||||
<div className={styles.columns}>
|
||||
<div className={styles.controls}>
|
||||
@@ -147,8 +149,8 @@ function IntroductionLessons() {
|
||||
</div>
|
||||
</div>
|
||||
</>}
|
||||
{state.step === 7 && <>
|
||||
<p>You can revisit any example. This introduction covers bidding, core resources, movement and battle choices; it does not teach every faction, card, alliance, storm exception or expansion.</p>
|
||||
{state.step === 8 && <>
|
||||
<p>You can revisit any example. This introduction covers ordinary alliances, bidding, core resources, movement and battle choices; it does not teach every faction, card, alliance power, storm exception or expansion.</p>
|
||||
<ul>
|
||||
<li>Create a private room, choose a faction, and add friends or AI players. Share the room invitation.</li>
|
||||
<li>Mark yourself ready after reviewing the selected rules. The host begins once all seats are ready.</li>
|
||||
|
||||
Reference in new issue
Block a user