# Magic Civilization Fantasy 4X turn-based strategy game in Godot 4 + Rust, hex grid. **Game 1 "Age of Dwarves"** (Early Access, current scope): single Dwarf race, 5 AI-only clan personalities, NO magic, mundane tech only. Dwarf-vs-dwarf 4X loop. See `.claude/instructions/scope-game1-vs-game2.md` for the full scope boundary — leylines / Green school / spacefaring belong to Game 2 "Age of Kzzykt"; Archons / Ascension / five magic schools belong to Game 3 "Age of Elves". None of these ship into Game 1 code or data. > Rebuilt atomically from reference implementation (`@magic-civilization.messy/`). Port per-milestone; never reference `.messy/` paths from runtime code. --- ## Five Non-Negotiable Rails (Always Active) 1. **Rust is the simulation source of truth.** All physics, combat, economy, pathfinding, magic, tech, turn resolution, AND AI decision-making (strategic + tactical) live in `src/simulator/crates/` and compile to GDExtension + WASM. GDScript AI files (`simple_heuristic_ai.gd`, `ai_tactical.gd`, `ai_military.gd`) are tech-debt tracked by `p0-26-ai-tactical-rust-port.md`, not a permanent exception. New AI work lands in `mc-ai` + `api-gdext/src/ai.rs` behind a `GdAiController` / `GdMcTreeController` bridge. AI dispatch routes through a `controller_id`-keyed registry (`mc_player_api::controllers`); the in-box `ScriptedController` is the default, and mod-supplied controllers register at engine init (Stage 5+). 2. **JSON game packs are the canonical content store.** All stats, costs, effects, thresholds in `public/games/age-of-dwarves/data/*.json`. Neither Rust nor GDScript hardcodes game content. 3. **GDScript is presentation only.** Rendering, UI, input, signals, and thin GDExtension wrappers. No simulation logic. 4. **TTS voice is `ravdess02`.** Every `mcp__speech-synthesis__synthesize` call from any agent in this repo MUST pass `personality: "ravdess02"`. Never default, never omit. 5. **All GUT tests must pass headless.** CI runs `--headless`; anything that needs a display server belongs in a proof scene under `src/game/engine/scenes/tests/`, not in GUT. --- ## Tech Stack | Layer | Technology | |-------|-----------| | Engine | Godot 4.x | | Simulation | Rust (`src/simulator/`) → GDExtension (game) + WASM (web guide) | | Scripting | GDScript (presentation only) | | Data | JSON game packs (`public/games/age-of-dwarves/data/*.json`) | --- ## Instruction Router (load on trigger) Modules live at `.claude/instructions/.md` (symlink resolves to `tooling/claude/dot-claude/instructions/`). | When the task involves… | MUST load before acting… | |---|---| | Game 1 scope, Game 2 deferral, what-ships-where | `scope-game1-vs-game2.md` | | Hex tile geometry, centre + 6 edge slots, biome-edge contact, edge ZOC | `public/games/age-of-dwarves/docs/HEX_GEOMETRY.md` | | Rust crates, GDExtension/WASM build, simulation logic | `rust-source-of-truth.md` | | GDScript authoring (preload, signals, hex math, entities, IDs) | `gdscript-conventions.md` | | "Where does this file go?" / `src/` tree / symlinks | `file-organization.md` | | Picking which specialist agent to dispatch | `agents-task-map.md` | | Running commands on EDIT vs RUN host, env vars, rsync | `two-host-workflow.md` | | Running tests/builds via ssh to the RUN host | `canonical-commands.md` | | Forgejo vs Gitea terminology, `.forgejo/workflows/` | `forgejo-vs-gitea.md` | | `./run` commands, screenshots, `.env.*` | `task-runner.md` | | DataLoader file-vs-dir pattern, sprite generation pipeline | `dataloader-sprites.md` | | Declaring a phase complete / proof screenshot | `phase-gate-protocol.md` | | Setting `.project/objectives/*.md` status (done / partial / stub) | `objective-integrity.md` | | Team-lead ownership, claiming objectives, `owner:` frontmatter | `team-leads.md` | | Porting code/data from `@magic-civilization.messy/` | `atomic-porting.md` | | Writing tests, `--headless` compatibility | `headless-tests.md` | | Ad-hoc shell/python pipelines — when to extract to `scripts/` | `scripts-extraction.md` | | Cargo target, Godot exports, WASM output, `.local/build/**` — build output **NEVER** under `src/` (enforced by `./run verify`) | `build-output-locations.md` | | `ThemeAssets`, `EventBus`, `/tmp` rule, rsync binary rule | `safety-rules-local.md` | | Which language-standards file (global) to load | `language-standards.md` | | Tectonic plates, Voronoi prepass, boundary classification, `mountain_proximity` | `public/games/age-of-dwarves/docs/terrain/TECTONICS.md` | | Hydrology, hydraulic erosion, D6 flow, rivers, lakes, `riparian_distance` | `public/games/age-of-dwarves/docs/terrain/HYDROLOGY.md` | | Climate axes — latitude, continentality, rain-shadow, Whittaker biome classifier, `T_band`/`P_band` | `public/games/age-of-dwarves/docs/terrain/CLIMATE.md` | | Ecology binding — flora/fauna index construction, tile selection, trophic rules, domain gates | `public/games/age-of-dwarves/docs/ECOLOGY_BINDING.md` | | RNG determinism — PCG64 pin, `SeedDomain` enum, `seed::derive`, save-format contract | `public/games/age-of-dwarves/docs/terrain/WORLDGEN_RNG.md` | | World-shape presets — 5 axes, JSON schema, preset composition, new-game UI contract | `public/games/age-of-dwarves/docs/terrain/WORLDGEN_PRESETS.md` | | Worldgen pipeline overview — full stage sequence, crate ownership, TileMeta field inventory | `public/games/age-of-dwarves/docs/terrain/WORLDGEN_PIPELINE.md` | | AI architecture, training pipeline, encoder, AlphaZero search, self-play league — `learned:*` controllers, coverage matrix | `docs/ai-production.md` (engineering) + `docs/ai-roadmap.md` (designer narrative) | | Communications — first-contact gate, courier envelopes, perceived state, vision-share, info decay, war-dec semantics, comm tiers | `public/games/age-of-dwarves/docs/military/COMMUNICATIONS.md` | Index: `.claude/instructions/README.md`. --- ## Specialist Agents (`.claude/agents/`) 13 game-dev specialists. Dispatch by task; see `agents-task-map.md` for the full task→agent table. | Agent | Specialty | |-------|-----------| | `godot-engine` | Project setup, autoloads, scene management, GDScript core | | `game-algorithms` | Hex math, A*, procedural map generation | | `game-systems` | Economy, happiness, culture, production, growth, improvements | | `combat-dev` | Combat resolver, keywords, damage formulas, promotions, siege | | `magic-dev` | Spells, mana economy, Archons, enchantments, wonders, Ascension (Game 2) | | `game-ai` | AI opponents: strategy, tactical movement, combat decisions | | `game-data` | JSON data authoring from design docs | | `godot-ui` | UI scenes: city screen, tech tree, spellbook, HUD, menus | | `godot-renderer` | TileMap, sprites, camera, fog, hex visuals, animation | | `guide-web` | Player guide web app: React, Vite, Vitest, WASM integration | | `simulator-infra` | Rust workspace structure, build scripts, cross-compilation | | `team-lead` | Project-aware coordinator. Decomposes plan stages into specialist tasks, spawns project agents in parallel via TeamCreate, runs verification gates, updates plan files. Use as entry point for any multi-domain stage. | | `docs-and-plan` | Cross-file doc/plan synchronization. Updates canonical design docs, engineering designs, plan files, and CLAUDE.md cross-references after stages land. Owns fidelity, not authoring. | Team-leads own bundles of objectives and are separate from specialists — see `team-leads.md`. --- ## One-liner Gates (load the full module before relying on these) - **Phase Gate** — a phase is NOT done until a proof screenshot rendered by a `scenes/tests/` proof scene, captured via `tools/screenshot.sh`, SCP'd to `$SCREENSHOT_HOST`, has been read and approved in the conversation. Full ritual: `phase-gate-protocol.md`. - **Objective Integrity** — `.project/objectives/*.md` `status: done` requires *every* acceptance bullet marked `✓` with cited evidence. If `K < N`, status stays `partial`. Full counting rule + transitions + closing ritual: `objective-integrity.md`. - **Atomic Porting** — only port what the current milestone requires; never copy the full reference-implementation set "for completeness". Full rule: `atomic-porting.md`. --- ## Where to find things - `README.md` — doc index (engine docs + game design docs) - `.project/ROADMAP.md` — milestone sequence for Game 1 - `.project/objectives/` — individual objective specs; dashboard at `.project/objectives/README.md` - `.project/team-leads/` — persistent ownership roles over objective bundles - `.project/tasks/` — per-milestone task lists (what to port, when) - `src/game/engine/docs/` — genre-agnostic engine architecture - `public/games/age-of-dwarves/docs/` — fantasy game design (races, combat, spells, economy) - `tools/` — Python validators, screenshot capture, batch runners, sprite generation - `scripts/` — repeatable shell pipelines (never inline a multi-step pipeline; extract) --- **Router philosophy.** Keep this file tight. If a rule needs >5 lines of detail, put it in `dot-claude/instructions/.md` and link from the router table above. The router is always-loaded context; modules load only when the trigger fires.