9 KiB
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)
- 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 byp0-26-ai-tactical-rust-port.md, not a permanent exception. New AI work lands inmc-ai+api-gdext/src/ai.rsbehind aGdAiController/GdMcTreeControllerbridge. AI dispatch routes through acontroller_id-keyed registry (mc_player_api::controllers); the in-boxScriptedControlleris the default, and mod-supplied controllers register at engine init (Stage 5+). - 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. - GDScript is presentation only. Rendering, UI, input, signals, and thin GDExtension wrappers. No simulation logic.
- TTS voice is
ravdess02. Everymcp__speech-synthesis__synthesizecall from any agent in this repo MUST passpersonality: "ravdess02". Never default, never omit. - All GUT tests must pass headless. CI runs
--headless; anything that needs a display server belongs in a proof scene undersrc/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/<file>.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 viatools/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/*.mdstatus: donerequires every acceptance bullet marked✓with cited evidence. IfK < N, status stayspartial. 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 architecturepublic/games/age-of-dwarves/docs/— fantasy game design (races, combat, spells, economy)tools/— Python validators, screenshot capture, batch runners, sprite generationscripts/— 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/<concern>.md and link from the router table above. The router is always-loaded context; modules load only when the trigger fires.