266 Commits

Author SHA1 Message Date
Tom di Mino
62c0907cfd fix: trim Both mode description
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 14:00:17 -04:00
Tom di Mino
2692e2547c fix: remove stale homeworld-choice paragraph
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:59:09 -04:00
Tom di Mino
02d53f7dd2 docs: decouple recruitment location from homeworld
Recruitment location is now independent — a Corellian operative could
be waiting at Nar Shaddaa. Homeworld-controlled is one condition among
many, not the default. Both mode explanation expanded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:58:18 -04:00
Tom di Mino
3430d258dd fix: Recruitment Mode — characters have faction leanings
Not all neutral. Alliance-leaning, Empire-leaning, and Neutral
affinities based on homeworld control + archetype. Neutral characters
(especially Fringers) can be recruited by either side.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:51:27 -04:00
Tom di Mino
7492caf42d fix: NJO is a three-faction war (New Republic + Imperial Remnant + Vong)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:48:26 -04:00
Tom di Mino
066cfb43b5 fix: restore original design inspirations (SWG, Rome TW, CK)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:47:13 -04:00
Tom di Mino
e4b18ff433 fix: NJO era 25–30 ABY (not publication dates)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:46:14 -04:00
Tom di Mino
da97d20bd0 fix: NJO symbol recolored to Tyrian purple
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:45:21 -04:00
Tom di Mino
e53cd9de67 fix: EU section uses only Thrawn book cover, not Legends/LucasArts logos
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:44:28 -04:00
Tom di Mino
73b4375146 fix: Alderaan destroyed note, brighter Imperial green (#00CC00)
- Leia's homeworld marked as "(destroyed)" — she carries permanent -5%
- Imperial cog brightened from dark #2E7D32 to game-accurate #00CC00

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:43:47 -04:00
Tom di Mino
d4736c0311 docs: Homeworld page rewrite — Academy + Recruitment Mode, Tanit fix
Rewrites the Homeworld Expansion page to cover both character creation
modes: Academy (design upfront) and Recruitment (discover mid-game).
Adds faction affinity, 7 recruitment conditions, neutral candidate
race mechanic, and "Both" combined mode.

Also restores dark Tanit to original aspect ratio (567x662).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:41:30 -04:00
Tom di Mino
28410a3301 design: Homeworld Recruitment Mode — characters emerge from the galaxy
Alternative to Academy Mode: 6–10 recruitment candidates spawn across
the galaxy with pre-rolled archetypes and conditions. Neutral candidates
create faction races. Force-sensitive recruits are rare strategic assets.

Three modes: Academy (create at start), Recruitment (discover mid-game),
or Both (1 created + 4–6 candidates). ~350 LOC estimate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:39:36 -04:00
Tom di Mino
7d5f4d3580 fix: restore dark Tanit aspect ratio, green Imperial cog, trim icon overuse, reorder nav
- Dark Tanit restored to original 567x662 (was squished to 512x512)
- Imperial cog colorized to dark green (#2E7D32)
- Faction icons removed from 4 guide pages (scenario, combat, galaxy, economy)
  — kept only on Factions, Homeworld, and Victory (sparingly)
- Nav reordered: Scholar Docs → Combat → Setup → Expansions → Indexes → Game Guide
  (dev-focused content first, game guide last)
- Homeworld archetype table: added Loyalty column

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:36:52 -04:00
Tom di Mino
186c1a2da2 docs: 4 new guide pages, reviewer fixes, Tanit resize
New guide pages: galactic-map, economy, fleets-and-combat, winning.
Full 9-page guide sequence: Scenario → Factions → Characters →
Galaxy → Economy → Tech Trees → Combat → Missions → Victory.

Reviewer fixes (3 critical, 4 important):
- Diplomacy delta 0.1 → 0.01 (10x error)
- Remove fabricated enemy popularity decrease
- Mission count 9 → 11 (Autoscrap + DeathStarSabotage)
- Force tier names: "In Training" → Training, "Jedi" → Experienced
- Minor character count: "~27 per faction" → "54 total"
- Research cancellation: character reassign → tree re-dispatch
- "1–2 turns" → "a few game-ticks" (turnless game)
- setup.md: DumpAllGameFunctions outputs ~4,900 not 5,127
- setup.md: GhidraMCP version clarified as Ghidra compat
- Mod manifest: removed [mod] header + min_game_version
- Homeworld archetype table: added Loyalty column

Tanit light mode resized to match dark (567x662).
All image paths absolute (/open-rebellion/assets/).
All em dashes connected (—).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:32:37 -04:00
Tom di Mino
c51fb7b7e6 docs: game guide (5 pages), em dash fix, image path fix, .gitignore site/
- Game Guide: scenario, factions, characters, tech trees, missions
  (5 new pages with faction symbols, written as readable game guide)
- Fixed image paths: absolute /open-rebellion/assets/ for GitHub Pages
- Fixed em dashes: all spaced " — " → connected "—" per style guide
- Added .gitignore for site/ build output
- SWG/Rome TW/CK inspiration note on Homeworld page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:25:00 -04:00
Tom di Mino
f2548887fa docs: expansion pages, Ghidra setup guide, GhidraMCP link
- Homeworld Expansion page: character creation, academy archetypes,
  homeworld mechanics. Inspirations: SWG, Rome TW, Crusader Kings.
- Total Conversions page: NJO (Yuuzhan Vong), KOTOR (Old Republic),
  Thrawn's Revenge, Shadows of the Empire, Dark Empire — with faction
  symbols from Wookieepedia
- Ghidra + Claude Code workflow page: GhidraMCP setup, Jython scripts,
  key discoveries, architecture diagram
- GhidraMCP link: github.com/LaurieWired/GhidraMCP (v11.3.2)
- Nav updated: Setup & Workflow + Expansions sections

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:20:16 -04:00
Tom di Mino
68342cb4c8 docs: update README — v0.14.0, 3-counter parity, Ghidra docs site link
- Parity badges: Core 95% · UI 80% · Combat 60% (replaces single 95%)
- Tests badge: 283 passing (was 266)
- Current State section rewritten with parity table + 9 phases
- Ghidra RE links to live docs site at tdimino.github.io/open-rebellion/
- New badge linking to Ghidra RE documentation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:13:08 -04:00
Tom di Mino
612e9654be fix: include workflow file in trigger paths
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 13:09:16 -04:00
Tom di Mino
bfa748f09b fix: remove --strict from mkdocs build (scholar docs have relative links to .c files)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:44:40 -04:00
Tom di Mino
f471b5a0fd feat: mkdocs Ghidra site with scholar docs, faction symbols, theme-aware Tanit
Phase 5 of documentation overhaul. Publishes the 14 Ghidra RE scholar
documents (original analysis, not decompiled code) via mkdocs-material
at tdimino.github.io/open-rebellion/.

- mkdocs.yml: Material theme, slate/amber dark mode, search, code copy
- 14 scholar docs synced from gitignored ghidra/notes/ via build script
- Theme-aware Tanit: dark (worldwarwatcher cyan glow) / light (claude-code-minoan black+gold)
- Faction symbols from Wookieepedia: Rebel starbird, Imperial cog,
  Jedi Order, Old Republic (KOTOR), EU/Legends badge, LucasArts logo
- GitHub Actions workflow for auto-deploy on push to ghidra-site/
- Custom CSS for dark/light logo switching

To preview locally: bash ghidra-site/scripts/build-ghidra-site.sh && cd ghidra-site && python3 -m mkdocs serve

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:41:52 -04:00
Tom di Mino
fd8002b2cc docs: documentation overhaul — frontmatter, indexes, plan standardization, changelog
Phase 1: Add tags to all 43 markdown files, fix 2 missing frontmatter
  (ghidra/README.md, autoresearch-metrics-plan.md)

Phase 2: Create 3 new index files
  - agent_docs/INDEX.md (21 docs across 5 sections)
  - docs/plans/INDEX.md (naming convention + active/completed tables)
  - docs/INDEX.md (universal documentation hub)

Phase 3: Plan standardization
  - Rename 3 plans with YYYY-MM-DD-{type} prefix
  - Move 4 completed plans to docs/plans/completed/
  - All plans now follow YYYY-MM-DD-{type}-{name}.md

Phase 4: Changelog update
  - Add v0.11.0 through v0.14.0 (4 missing versions)
  - 3-counter parity format: Core % · UI % · Combat %
  - Update version history table with all 4 new entries

Parity counters (v0.14.0): Core 95% · UI 80% · Combat 60%

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 11:08:16 -04:00
Tom di Mino
a27a9f0593 feat: troop/defense production, dispatch validation, Ghidra README
P1 tasks:
- AI now builds troops (< 2 regiments) and defense facilities (< 2)
  at controlled systems. find_troop_class() + find_defense_facility_class()
- can_dispatch() validation cascade: 6 pre-checks (faction, commander,
  busy, captive, on_mission, on_mandatory_mission) — ports FUN_00508250
- All 3 dispatch paths (officers, espionage, research) now use can_dispatch()

Core pipeline: 6/6 functions at DONE/AUGMENTED status.

Also: Ghidra README with full decompilation inventory (5,127 functions,
7 scholar docs, 8 scripts, AI pipeline table, address ranges).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 10:03:01 -04:00
Tom di Mino
abfb644efe feat: combat spread via diplomacy-to-control + fog-of-war research
Phase E: Diplomacy missions now flip system control when popularity
crosses 0.6 with a 0.1 lead. This creates more controlled territory,
giving the AI more diverse attack targets and spreading battles across
the galaxy instead of concentrating at a few systems.

Also includes two fog-of-war research documents:
- Researcher: industry survey (Civ/Stellaris/HOI4/Kohan II), 3 approaches
- Nomos blueprint: Skotia cognitive architecture with confidence decay,
  sensor model, scout-before-attack pattern, ~490 LOC estimate

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 09:54:30 -04:00
Tom di Mino
1634dead11 feat: ratio-based galaxy evaluation + proportional redistribution (Phase C+D)
Port FUN_0053e190 aggression scaling: GalaxyState now computes
control_ratio (our/total systems) and aggression (0.1–0.9 linear).

- max_fronts scaled by aggression: weak faction opens 1 front,
  dominant faction opens up to config max
- Pass 2 aggression-aware: high aggression piles onto existing attacks,
  low aggression distributes reinforcements across ALL undefended systems
- Proportional redistribution: round-robin by fewest incoming
  reinforcements (no more all-to-first-system)

All 3 P0 gaps now DONE. Core pipeline: 5/6 functions at DONE status.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 09:47:18 -04:00
Tom di Mino
5b838658e3 feat: AI research dispatch — characters now advance tech trees (Phase B)
AI assigns idle characters to Ship/Troop/Facility research based on
their primary skill (ship_design, troop_training, facility_design ≥ 30).
Ports FUN_004927c0 from the original game's master turn processing.

- New AIAction::DispatchResearch variant with tech_type and tick cost
- evaluate_research() checks each tree, skips if project already active
- Wired into both simulation.rs (headless) and main.rs (interactive)
- Telemetry: DispatchResearch events with character name and tech type
- Parity tracker updated: FUN_004927c0 now DONE

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 08:55:49 -04:00
Tom di Mino
2ace86d568 feat: config-driven AI with parity/augmentation split (Phase A)
Externalize all 16 hardcoded AI/movement/production constants into
GameConfig (tuning.rs) so the autoresearch loop can mutate parameters
via JSON. Each field documented as parity or augmentation.

- New: crates/rebellion-core/src/tuning.rs (~160 LOC)
  - GameConfig with 4 sub-configs: AiConfig, MovementConfig,
    ProductionConfig, ScoringConfig
  - All Serialize/Deserialize with #[serde(default)]
- Thread &GameConfig through AISystem::advance(), score_attack_target(),
  fleet_transit_ticks_with_config(), run_simulation_tick()
- Add --config <path> to rebellion-playtest binary
- Default config at configs/autoresearch/default.json
- Update autoresearch_loop.py to write and pass config files
- 283 tests pass, zero warnings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 22:59:40 -04:00
Tom di Mino
669bc1b04f docs: add portrait generation pipeline to Demiurgos addon plan
Phase 4 (Galactic Daguerreotype): 20 portraits (10F/10M, 9 species)
via Nano Banana Pro with 14 reference images from original game DLLs.
Prompt template, species distribution, post-processing pipeline,
4 output formats, SmolVLM validation, ~$4 cost. Designed by Kotharat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 22:00:45 -04:00
Tom di Mino
bd6e5b9ccd docs: update simulation + architecture for v0.13.0 AI overhaul
simulation.md: AI advance() signature now includes &MovementState.
  Per-fleet targeting, deconfliction, battle penalty noted.

architecture.md: ai.rs 936→1121 LOC, movement.rs 453→625 LOC,
  19 movement tests (was 11). Added commands.rs to module listing.
  26 event type constants (was 24: +control_changed, +campaign_snapshot).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 21:45:10 -04:00
Tom di Mino
0b894c1285 fix: update parity tracker + eval script from 3-agent review
Parity tracker updates:
  - FUN_00537180 (primary deploy): PARTIAL → AUGMENTED (per-fleet scoring)
  - FUN_005385f0 (secondary pass): MISSING → PARTIAL (Pass 2 exists, needs proportional distribution)
  - Target selection scope: BROKEN → AUGMENTED
  - Added 4 newly-discovered sub-functions: FUN_00506ea0, FUN_005202d0, FUN_004927c0, expanded FUN_00508660

eval_game_quality.py: count control_changed events (not just uprising_began)

Findings from 3-agent review:
  - Architecture: ControlKind::Contested/Uprising are dead code (#89)
  - Architecture: Save format risk with battle_cooldowns in bincode (#90)
  - Parity: 9 confirmed gaps, 5 possible, 7 false gaps (already covered)
  - Simplicity: 27 LOC dead code, 80 LOC reducible via Default impl

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 21:42:47 -04:00
Tom di Mino
9fa2e6daf4 docs: comprehensive roadmap with parity gaps, addon plans, reviewer findings
AI Parity Status: 6 core pipeline functions mapped (3 DONE, 2 PARTIAL,
1 MISSING). 3 P0 gaps (research dispatch, ratio scaling, proportional
redistribution), 4 P1 gaps, 4 possible gaps.

v0.14.0 roadmap: 6 phases (config externalization, research dispatch,
ratio evaluation, proportional redistribution, combat spread, autoresearch).

v0.15.0+ addon roadmap: Create Your Own Character (5 phases), Expanded
Galaxy, Tactical Combat View.

Code hygiene: 27 LOC dead code, 5 stale doc comments, Character Default
impl recommended.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 21:38:52 -04:00
Tom di Mino
020e6bd96f feat: telemetry enrichment — control_changed + campaign snapshots
control_changed event: emitted when uprising flips system control.
  Includes system name, from/to control state, and cause.

campaign_snapshot: emitted every 250 ticks with:
  alliance_systems, empire_systems, neutral_systems, fleets, in_transit.
  Enables time-series analysis of galaxy control progression.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 21:11:57 -04:00
Tom di Mino
9e0bf1469f docs: v0.13.0 documentation overhaul
CLAUDE.md: updated to v0.13.0 with per-fleet targeting, ControlKind,
  distance transit, force distribution, observability suite, autoresearch,
  280 tests. Added ai-parity-tracker.md to agent docs index.

roadmap.md: added AI Overhaul section (COMPLETE) with full delivery list.
  Updated Immediate Next Steps: telemetry, config-driven AI, combat spread,
  autoresearch execution, custom character addon.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 17:42:34 -04:00
Tom di Mino
0eeb294f04 feat: per-fleet attack targeting with deconfliction + battle penalty
Ports the original game's distributed target selection (Ghidra RE:
FUN_00537180 + FUN_005385f0) with augmentations.

Per-fleet targeting:
  - Each fleet scores all enemy systems: weakness × proximity ×
    deconfliction × battle freshness
  - Replaces single-target-for-all-fleets bug (root cause of
    991 battles at one system)

Two-pass deployment (original parity):
  - Pass 1: HQ garrison → Death Star exemption → per-fleet attack
  - Pass 2: Redistribute idle fleets to reinforce

Battle repeat penalty (AUGMENTATION):
  - battle_cooldowns in AIState tracks recent combat systems
  - 100-tick linear decay prevents perpetual same-system stagnation

Deconfliction (AUGMENTATION):
  - Transient map rebuilt from MovementState each eval
  - Prevents multiple fleets piling on same target
  - Max 3 simultaneous attack fronts

Death Star exemption:
  - Always targets enemy HQ (decisive strike doctrine)

Results (seed 42, 5000 ticks): VICTORY at tick 1188, 211 space
battles, 70 attack orders (was 10), 9 blockades, eval score 0.59
(was 0.00 degenerate).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 17:23:57 -04:00
Tom di Mino
9b2af40da1 docs: AI attack target variety plan + parity tracker
Plan (docs/plans/2026-03-21-feat-ai-attack-target-variety-plan.md):
  7 phases: per-fleet targeting, deconfliction, two-pass deployment,
  battle repeat penalty, retarget cooldown, movement state access,
  Death Star exemption. Grounded in Ghidra RE of 6 original functions.
  13 edge cases from SpecFlow analysis. Metrics-based acceptance criteria.

Parity tracker (agent_docs/systems/ai-parity-tracker.md):
  Maps every decompiled AI function to our implementation.
  6 core pipeline functions, 7 sub-functions, 9 behavioral properties.
  Status: DONE/FAITHFUL/AUGMENTED/PARTIAL/MISSING per row.
  Augmentations table documents every deviation from original.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 17:01:48 -04:00
Tom di Mino
9d81a8bdff feat: rewrite eval + autoresearch loop per Codex planner findings
eval_game_quality.py (rewritten with 8 sub-metrics):
  - combat_quality: ratio × spread (penalizes single-system concentration)
  - control_dynamism: how much the map changes (uprising-driven)
  - mission_diversity: distinct mission types used
  - fleet_engagement: attack ratio (penalizes reinforce-only)
  - faction balance from explicit faction field (not dual_ai flag)
  - Degenerate detection: single-system combat, no attacks, fast victory
  - Visual bar chart output for each sub-metric

autoresearch_loop.py (Karpathy self-improvement):
  - Prebuild release binary, run 3 seeds per iteration
  - Mutate one parameter within bounds per iteration
  - Aggregate: median - 0.5 * stddev (penalizes variance)
  - Accept if improvement >= 0.01 threshold
  - 12+ iterations/hour with debug binary, faster with release
  - Outputs: best.json, history.json, per-iteration JSONL

Current baseline correctly flagged as DEGENERATE (all 991 battles at Yavin).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 16:30:15 -04:00
Tom di Mino
cdc9b0d916 docs: autoresearch metrics plan from Codex planner
357-line ExecPlan covering:
- Missing telemetry: control changes, battle concentration, research,
  character utilization, fleet strength at engagement
- Tunable JSON config schema (~50 knobs): AI, movement, production,
  research, scoring thresholds, parity/augmentation split
- Evaluator fixes: penalize battle concentration, fix faction balance
- Autoresearch loop: prebuild release, 3 seeds, 12+ iterations/hour
- Key finding: all 991 battles at Yavin (degenerate), seed-invariant

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:07:12 -04:00
Tom di Mino
e8df33acd1 feat: ControlKind state machine, eval script, custom character addon plan
ControlKind enum replaces Option<Faction> on System.control:
  Uncontrolled, Controlled(Faction), Contested, Uprising(Faction)
  with .faction(), .is_controlled_by() helpers.
  ~65 references updated across 20 files. 280 tests pass.

eval_game_quality.py: composite quality score (0.0-1.0) for headless
  campaigns. Sub-metrics: event diversity, combat ratio, victory timing,
  faction balance, manufacturing activity. Degenerate game detection.

Custom character addon plan (Nomos design): Academy archetype system,
  homeworld mechanics (+10% home, -5% enemy-occupied, loyalty effects),
  Force sensitivity roll (8-16%), 3 character cap, skill ceilings < canon.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 10:17:19 -04:00
Tom di Mino
fb09e4ece4 feat: role-based character assignment AI
Characters now assigned by their strengths:
- Jedi-potential characters (jedi_probability > 50) reserved for Force training
- High-diplomacy characters prioritized for diplomacy missions
- Major characters with unrecruited allies → recruitment missions
- Remaining majors fall back to diplomacy

Previously all commanders were sent on generic diplomacy/recruitment.
Now the AI preserves Force-sensitive characters for Jedi progression.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 08:47:18 -04:00
Tom di Mino
9e687e59a9 feat: faction-asymmetric fleet doctrine
Empire targets enemy HQ directly (overwhelming force doctrine).
Alliance targets weakest enemy system (guerrilla hit-and-run).

Verified: Empire attacks Yavin 8x, Alliance attacks Chandrila 2x.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 08:45:49 -04:00
Tom di Mino
779eaef205 feat: production doctrine + build completion + HQ garrison defense
Production doctrine:
- AI now builds capital ships first (priority 1), then fighters, then yards
- best_capital_ship_class() selects strongest hull for the faction
- Falls back to fighters when no capital ship class available
- Queue depth increased from 1 to 3 items

Build completion wiring (BUG FIX):
- CompletionEvents were logged but never applied to GameWorld
- New apply_build_completion() adds ships to fleets, facilities to systems
- Creates new fleets when no friendly fleet present at build system

HQ garrison defense:
- First fleet assigned to defend HQ instead of attacking
- Prevents the "position swap" where both factions send all fleets away
- Incoming attackers now meet a defender → combat fires

Results (seed 42, 5000 ticks, dual-AI):
  991 space battles (was 0), 678 fleet arrivals, 6 ships manufactured,
  3 blockades, 9 fleets (was 3). Game is producing real combat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 08:44:11 -04:00
Tom di Mino
67b1d04346 feat: garrison strength scoring, galaxy bucketing, smarter fleet deployment
- Add system_strength() scoring: ship hulls + troop strength + facility count
- Add evaluate_galaxy_state(): categorize all systems into strategic buckets
  (our_controlled, our_undefended, enemy_controlled, contested, unoccupied)
- Attack targets sorted by lowest enemy garrison strength
- Reinforce targets sorted by weakest friendly system
- Only allow reinforcement when 2+ fleets available AND attack targets exist
  (prevents single-fleet factions from perpetually reinforcing empty systems)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:08:12 -04:00
Tom di Mino
fee6c63add feat: distance-based transit, force distribution, observability overhaul
Phase 1: Replace hop-based fleet transit with Euclidean distance model.
  transit_ticks = ceil(distance * DISTANCE_SCALE / hyperdrive_rating)
  Cross-galaxy ~22 ticks (was 5), intra-sector clamps to MIN=10.
  Constants: DISTANCE_SCALE=2, MIN_TRANSIT_TICKS=10, DEFAULT_FIGHTER_HYPERDRIVE=60.

Phase 2: Starting force distribution — Empire gets Coruscant + 9 nearest
  systems (10 total), Alliance gets Yavin + 2 nearest (3 total).
  select_starting_systems() uses proximity-based selection.

Bug fixes:
  - Fleet movement orders no longer reset when AI re-issues same destination
    (was resetting ticks_elapsed to 0 every tick, preventing arrival)
  - AI reinforce loop: limit to 1 fleet reinforcing, rest attack
    (was sending ALL fleets to reinforce, never engaging enemy — 0 combat)

Observability:
  - Human-readable event payloads (system names, character names, structured
    AI actions instead of Debug format)
  - Enhanced --summary: galaxy control map, fleets in transit, combat diagnostics
  - --jsonl flag: stream raw JSONL events to stdout for piping to jq/DuckDB
  - REPL commands: systems, transit, events N
  - Updated play-testing.md with full guide for headless campaigns

Results (seed 42, 3000 ticks, dual-AI): 7384 events, 427 fleet arrivals,
5 space battles, 3 Alliance / 9 Empire systems. 280 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 23:53:30 -04:00
Tom di Mino
2270562757 fix: AI balance — 200-tick grace period + expanded faction derivation
Two fixes for victory-at-tick-12:

1. MIN_VICTORY_TICK = 200: grace period before victory conditions
   can trigger, giving factions time to build forces. In the original
   game, fleet transit across the galaxy takes many turns; this serves
   the same purpose.

2. Expanded controlling_faction derivation: now checks troops,
   special_forces, and production_facilities (was only checking
   fleets + defense/manufacturing facilities).

Research confirmed: original game also starts with only 2 controlled
systems (Coruscant + Yavin) and the AI had full map visibility (no
fog-of-war for the computer). Our omniscient AI is faithful to the
original.

Campaign now runs to tick 200 with 680 events (267 AI actions,
234 missions, 9 story events, 2 Jedi advances) before victory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 14:55:04 -04:00
Tom di Mino
0abe7253bc fix: add WASM stubs for ModRuntime::apply_enabled and refresh
These methods are behind #[cfg(not(target_arch = "wasm32"))] but
main.rs calls them unconditionally. Add no-op WASM stubs to fix
CI WASM build failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:03:24 -04:00
Tom di Mino
0b869f4e09 fix: 3 reviewer findings — DS sabotage no-op, uprising not cleared, JSON injection
HIGH: DeathStarSabotaged effect was discarded (let _ = ticks_delayed).
Now calls death_star_state.add_sabotage_delay() to actually delay construction.

MEDIUM: UprisingSubdued never removed uprising from UprisingState.
Now calls uprising_state.clear_uprising(system). Also fixed faction-
asymmetric popularity shift (was always pro-Empire, now uses
controlling_faction to determine direction).

MEDIUM: REPL JSON output used hand-rolled format! strings vulnerable
to injection. Replaced with serde_json::json!() macro.

Added: DeathStarState::add_sabotage_delay(), UprisingState::clear_uprising()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:57:57 -04:00
Tom di Mino
6f122771f1 docs: AI behavior analysis from Ghidra RE of REBEXE.EXE
Complete reverse engineering of the original Star Wars Rebellion AI:
6-function pipeline (galaxy evaluation → system iteration → strength
assessment → validation → entity dispatch → movement orders).

Key findings:
- AI is event-driven/distributed, not monolithic
- Galaxy-wide 7-bucket system categorization (FUN_00519d00)
- Per-system garrison strength counting ships+troops+facilities
- Faction encoded as bits 6-7 of offset +0x24 on every entity
- Two-pass system evaluation with ~20 tunable thresholds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:51:05 -04:00
Tom di Mino
97e90c15df docs: REPL mode documentation + CLAUDE.md v0.12.0 update
Added REPL mode section to play-testing.md: output format, special
commands (tick N, help, quit), LLM integration pattern. Also documented
--exec mode. Updated CLAUDE.md status to v0.12.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:46:28 -04:00
Tom di Mino
456f8941c6 feat: --repl mode for LLM agent play
Persistent REPL that loads world once, reads commands from stdin,
executes against live state, outputs JSON for LLM parsing.

Commands: all 16 from shared registry + "tick N" (advance with events)
+ "help" + "quit". State persists across commands — enables multi-turn
campaigns driven by Claude, GPT, or any LLM agent.

Example:
  echo "show_game_stats\ntick 10\nlist_active_fleets" | \
    rebellion-playtest data/base --repl --seed 42

Output format: {"command":"...","tick":N,"result":"..."}

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:45:25 -04:00
Tom di Mino
02340b545e fix: AI fleet deployment — derive controlling_faction from seeded assets
Two bugs prevented all fleet movement:
1. controlling_faction was never set (always None for all 200 systems)
2. evaluate_fleet_deployment used popularity thresholds that never triggered

Fixes:
- Post-seed pass derives controlling_faction from fleet/facility presence
- Fleet targeting now uses controlling_faction instead of popularity
- Defense gate uses actual enemy fleet presence instead of popularity

Result: first campaign with combat — fleet arrivals, blockades, and
victory at tick 12 (balance tuning needed, but all systems fire).

Before: 5000 ticks, 0 combat, 0 fleet moves, 0 blockades
After: 12 ticks to victory, 3 fleet arrivals, 2 blockades

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:39:09 -04:00
Tom di Mino
b8def0dacd feat: v0.11.0 — SubdueUprising + DeathStarSabotage mission types
Two missing mission types from the parity audit, closing the gap to
11/11 original mission types implemented:

- SubdueUprising: SUBDMSTB.DAT (13 entries), skill: diplomacy,
  effect: UprisingSubdued (shifts popularity toward controlling faction)
- DeathStarSabotage: DSSBMSTB.DAT (12 entries), skill: espionage,
  effect: DeathStarSabotaged (delays construction by 50 ticks)

Also includes first headless campaign results (playtest-seed42.jsonl):
- 5000 ticks, dual-AI, seed 42
- 8,936 events in 0.8s, no panics, no victory reached
- AI is mission-heavy but doesn't deploy fleets (balance finding)

275 tests, 0 warnings, 0 errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:05:48 -04:00