From 7fe84ffbbd41b400917bbc7279d8ecf5422362d3 Mon Sep 17 00:00:00 2001 From: Quintine <15965533+Quintine@users.noreply.github.com> Date: Sun, 18 Oct 2026 12:58:54 +1100 Subject: [PATCH] Allow Advanced advisors to use the physical Ornithopter Adopt the supplied advisor/city distinction: advisors do not grant city access, but both printed physical-card modes permit advisor groups. Retain native stance/arrival/locks and distinct original cohorts; use shared advisor-aware paths and entry for minimal bot candidates. Add persistent guidance and genuine paid-acquisition/native-advisor regressions. Validation: frozen10-file87/87, types/lint/build and three original-action/rendered-table programmes. Actual host/setup, cache1 purchase, foreign shipment/accompaniment and paid BG reinforcement cover range3, two groups and leaving the last city fighter. Eight minimal policy proposals remain legal; controlled geometry and UI checks are separate. No wider combinations, complete modes, final assurance or browser/deployed acceptance claimed. No saved-room/reset/restart/deployment operation. --- README.md | 3 + components/ornithopter-movement.tsx | 28 ++-- docs/CURRENT_STATUS.md | 25 +++ docs/IMPLEMENTATION_STATUS.md | 20 +++ docs/RICHESE_ORNITHOPTER_ENGINE_AUDIT.md | 60 ++++++- docs/RULE_DECISIONS.md | 1 + game/bots.ts | 12 +- game/engine.ts | 4 - game/reference.ts | 15 +- tests/fixture-ornithopter-advisors.ts | 159 +++++++++++++++++++ tests/ornithopter-advisor-rules.test.ts | 94 +++++++++++ tests/ornithopter-advisors-controls.test.tsx | 109 +++++++++++++ tests/ornithopter-advisors-engine.test.ts | 135 ++++++++++++++++ tests/ornithopter-engine.test.ts | 5 +- 14 files changed, 634 insertions(+), 36 deletions(-) create mode 100644 tests/fixture-ornithopter-advisors.ts create mode 100644 tests/ornithopter-advisor-rules.test.ts create mode 100644 tests/ornithopter-advisors-controls.test.tsx create mode 100644 tests/ornithopter-advisors-engine.test.ts diff --git a/README.md b/README.md index 97e55d66..5592441d 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,9 @@ uses one unused movement entitlement and retains Hajr's separate move. The single physical Hajr can be played again after legitimate [paid Box recovery](docs/RICHESE_ORNITHOPTER_ENGINE_AUDIT.md#recovered-hajr-replay--18-october-2026). Advanced still requires a fresh post-movement opportunity. +Advanced advisors may use both physical Ornithopter modes. Advisors do not grant +city access; normal-range groups use current fighter occupancy. See the +[advisor source cutover](docs/RICHESE_ORNITHOPTER_ENGINE_AUDIT.md#advanced-advisor-card-movement--18-october-2026). Before starting, open **Configure** on an AI seat to change its difficulty, faction or player circle without replacing it. Changes save immediately and diff --git a/components/ornithopter-movement.tsx b/components/ornithopter-movement.tsx index 5e654cf9..7c7ab02f 100644 --- a/components/ornithopter-movement.tsx +++ b/components/ornithopter-movement.tsx @@ -7,7 +7,6 @@ import { type OrnithopterMode, } from '@/game/ornithopter'; import { location, splitLocation, gameTerritories } from '@/game/board'; -import { isAdvisor } from '@/game/advisors'; import { botGroundMoveAllowed } from '@/game/bot-mobility'; import { Button } from './ui/button'; import { CardInspector, CardRules } from './card-inspector'; @@ -31,6 +30,7 @@ export function OrnithopterMovement({ const card = game.ornithopter; const me = game.players.find((p) => p.id === game.me); if (!card || !me) return null; + const advisorGuidance = game.advanced && me.faction === 'beneGesserit'; const active = card.active; const mode = active?.mode ?? @@ -59,18 +59,6 @@ export function OrnithopterMovement({ location(String(move.territory), Number(move.sector)), 0))) reason = 'The Fremen two-territory advantage is unavailable. Choose a reachable destination within the remaining normal range.'; } - const physicalSource = - typeof move?.from === 'string' - ? move.from - : move?.forces && typeof move.forces === 'object' - ? Object.keys(move.forces)[0] - : undefined; - if ( - !reason && - physicalSource && - isAdvisor(me, splitLocation(physicalSource).territory) - ) - reason = 'Advanced advisor use of the Ornithopter card awaits its ruling.'; if (!reason && active?.cohort && move) { const forces = (move.forces as Record | undefined) ?? @@ -194,6 +182,15 @@ export function OrnithopterMovement({

)} + {advisorGuidance && ( +

+ Advanced Bene Gesserit advisors can use both card modes. Advisors in + Arrakeen or Carthag do not grant the city’s movement range. This card’s + one-group mode independently gives range three. Two-group mode uses + your current normal range and different original forces. Normal entry + and advisor conversion still apply. +

+ )} {me.faction === 'choam' && game.choamMovementBonus > 0 && (

Provisional Kulon combination: the one-group card move stays capped @@ -209,7 +206,10 @@ export function OrnithopterMovement({