No description
Ports the decisive-war mechanic from the juiced harness auto_play.gd:1109-1189
into the shipping Rust AI so the scripted controller fields it natively
(removing the dependency on the GDScript harness for decisiveness).
Capability (acceptance bullets 1, 2, 4):
- New `mc_ai::tactical::TacticalMemory { locked_target, commitment_turns }` —
the cross-turn persistence channel. Lives on `mc_turn::PlayerState`
(`#[serde(skip)]`, transient), NOT on the per-turn TacticalState snapshot
(which round-trips FFI as JSON — a field there would mean GDScript shadow
state, violating Rail 1) and NOT on the controller (a stateless shared
singleton). Borrowed `&mut` by `dispatch::drive_ai_slot` via mem::take and
threaded through `decide_turn → run_ai_turn → decide_tactical_actions →
decide_movement` — the pure-Rust path p1-29d measures, zero GDScript.
- `TacticalMemory::resolve` folds the auto_play state machine: acquire nearest
target when attacking, HOLD through tactical-score wobble for the commitment
window (hysteresis), PRESS ON to the next objective when the locked target
falls (capture → don't disperse), clear when all enemy cities are gone.
- `decide_movement` computes the army-wide lock once per turn (step 5b) and
every non-adjacent military unit drives on it instead of per-unit greedy
re-targeting — so captures get finished into eliminations.
- Commitment length is personality-derived (`thresholds::commitment_turns`,
aggression 0.6 / grudge 0.4; axis=5 reproduces auto_play's =5) — Rail 2
(ai_personalities.json axes), not a hardcoded constant.
- AiController trait gains `&mut TacticalMemory`; scripted threads it, mod
(wasm/native) + learned + FFI-shim controllers take a documented transient.
Tests (cargo test -p mc-ai green: 278 lib, all integration; workspace --tests
checks clean on apricot):
- 10 `memory::` unit tests: acquire/hold/expire/press-on/clear/determinism.
- 2 `thresholds::commitment_turns` tests (auto_play baseline + personality).
- 1 `movement::army_lock_concentrates_and_persists_across_turns` integration
test: a PERSISTED memory across two real decide_movement calls concentrates
3 units on ONE locked city and holds it through a want_attack=false turn.
- No regression: mc-turn 235/235, mc-player-api 126+, mc-mod-host all green.
Phase 1 is the clean green commit boundary. Objective stays 🟡 partial:
bullets 3 (≥1 elimination measured), 5 (AUTO_PLAY_ALL_AI / asymmetric harness),
6 (p1-29d re-score) are Phase 2 (batch validation on apricot), not yet done.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .ai-arena-test | ||
| .forgejo | ||
| .out-of-scope | ||
| .project | ||
| docs | ||
| drafts | ||
| engine/addons/magic_civ_physics | ||
| public | ||
| screenshots | ||
| scripts | ||
| src | ||
| tooling | ||
| tools | ||
| .claude | ||
| .env | ||
| .env.example | ||
| .gdlintrc | ||
| .gitignore | ||
| .gutconfig.json | ||
| .mcp.json | ||
| .pnpmfile.cjs | ||
| aod_bears_retiered.png | ||
| aod_canines.png | ||
| aod_canines_retiered.png | ||
| aod_evolution_map_default.png | ||
| aod_felids_retiered.png | ||
| aod_freefolk_dwarves.png | ||
| aod_lens_canines.png | ||
| aod_lens_canines_2.png | ||
| aod_lens_canines_scrolled.png | ||
| aod_lens_canines_t8.png | ||
| aod_lens_default.png | ||
| aod_raptors_retiered.png | ||
| aod_snapshot.md | ||
| calc-mountain-king-vs-apex.png | ||
| CLAUDE.md | ||
| climate-fix-check.png | ||
| climate-sim-1.png | ||
| climate-sim-2.png | ||
| climate-sim-3.png | ||
| climate-sim-4.png | ||
| climate-sim-check.png | ||
| climate-sim-final.png | ||
| climate-sim-fixed.png | ||
| early-access-bottom.png | ||
| early-access-current.png | ||
| early-access-updated.png | ||
| earth-42vh.png | ||
| earth-charts-visible.png | ||
| earth-fixed.png | ||
| earth-normal-mode.png | ||
| earth-scrolled-down.png | ||
| earth-scrolled-stats.png | ||
| earth-scrolled.png | ||
| earth-with-stats.png | ||
| enc-arctic-fox-modal.png | ||
| enc-arctic-fox.png | ||
| enc-audit-home.png | ||
| enc-combat-filter.png | ||
| enc-concept-modal.png | ||
| enc-first-forge.png | ||
| enc-fox-stats.png | ||
| encyclopedia-302-clean.png | ||
| encyclopedia-after-reload.png | ||
| encyclopedia-alias-glob.png | ||
| encyclopedia-detail-bottom.png | ||
| encyclopedia-detail-combat.png | ||
| encyclopedia-embedded.png | ||
| encyclopedia-full-page.png | ||
| encyclopedia-populated.png | ||
| encyclopedia-registry-working.png | ||
| encyclopedia-registry.png | ||
| encyclopedia-restarted.png | ||
| encyclopedia-search-warrior.png | ||
| encyclopedia-warrior-modal.png | ||
| evolution-aquatic-insects.png | ||
| evolution-arachnids.png | ||
| evolution-canines.png | ||
| evolution-frogs-toads.png | ||
| export_presets.cfg | ||
| full-game-final.png | ||
| full-game-page-bottom.png | ||
| full-game-page-bottom2.png | ||
| full-game-page-updated.png | ||
| gdformatrc | ||
| gdlintrc | ||
| lairs-filter-bar.png | ||
| lairs-page-tierrange.png | ||
| mcp_climate_sim.png | ||
| mcp_climate_sim_t10.png | ||
| mcp_dev_sprites.png | ||
| mcp_expansions.png | ||
| mcp_home.png | ||
| mcp_home_after_race_gate.png | ||
| mcp_populations.png | ||
| mcp_prod_after_feature_fix.png | ||
| mcp_prod_build_home.png | ||
| mcp_promotions.png | ||
| mcp_resources.png | ||
| mcp_wave_b_c_d_home.png | ||
| nogui-final.png | ||
| permutations-default.png | ||
| permutations-light-melee-filter.png | ||
| personality-axes-page-v2.png | ||
| personality-axes-page.png | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| run | ||
| sheets-page.png | ||
| sheets-skeleton.png | ||
| sim-30s.png | ||
| sim-after-10s.png | ||
| sim-after-90s.png | ||
| sim-after-fix.png | ||
| sim-after-wait.png | ||
| sim-check.png | ||
| sim-check2.png | ||
| sim-complete.png | ||
| sim-debug.png | ||
| sim-done.png | ||
| sim-earth-check.png | ||
| sim-equal-split.png | ||
| sim-final-layout.png | ||
| sim-final.png | ||
| sim-initial.png | ||
| sim-layout-check.png | ||
| sim-layout-check2.png | ||
| sim-layout-check3.png | ||
| sim-layout-final.png | ||
| sim-layout-verify.png | ||
| sim-loading.png | ||
| sim-nostart.png | ||
| sim-now.png | ||
| sim-playback.png | ||
| sim-playing.png | ||
| sim-progress-2.png | ||
| sim-streaming.png | ||
| spritegen.db | ||
| ss | ||
Magic Civilization
Fantasy 4X turn-based strategy game in Godot 4 + Rust, hex grid.
Game 1 — "Age of Dwarves" (current Early Access): single race (Dwarves), 5 AI-only clan personalities the player can face as opponents (Ironhold, Goldvein, Blackhammer, Deepforge, Runesmith), no magic mechanics, mundane tech only. Full 4X loop (cities, tech tree, wonders T1-T10, combat, wild creatures, domination victory). High-tier items and late-game wonders carry ancient/inexplicable flavor as Game 2 teasers — effects remain strictly mundane numeric bonuses.
Game 2 — "Age of Kzzykt" (future): adds magic, ley lines, Archons, spells, Ascension victory, more races. Eventual vision includes 16 races and 5 magic schools (Civ5 + Master of Magic + Magic: The Gathering color pie).
Structure
engine/ — genre-agnostic game engine (GDScript)
src/ — autoloads, entities, map, generation, modules, rendering
scenes/ — Godot scenes (.tscn + .gd)
docs/ — engine architecture docs
games/
age-of-dwarves/ — fantasy game pack (the default theme)
data/ — all JSON game content
assets/ — sprites, icons
docs/ — game design docs (combat, economy — spells/races are Game 2 scope)
guide/ — player guide web app (React/TypeScript)
engine/ — @magic-civ/guide-engine (shared components)
age-of-dwarves/ — guide pages for Age of Dwarves
packages/
engine-ts/ — @magic-civ/engine-ts (auto-generated climate simulation)
tools/ — sprite generation, transpiler, screenshot capture
Docs
Engine (engine/docs/)
| Doc | Covers |
|---|---|
| ARCHITECTURE.md | Project structure, autoloads, scene lifecycle |
| ABSTRACTION.md | Genre-agnostic vocabulary, theme pack system |
| DATA_FORMAT.md | JSON data schemas, DataLoader patterns |
Game Design (public/games/age-of-dwarves/docs/)
| Doc | Covers |
|---|---|
| RACES.md | 4 demo races, gendering, fusions, release schedule |
| ECONOMIC_SYSTEMS.md | Economy, civic axis, capitalism cascade |
| GOVERNMENTS.md | Government types and mechanics |
| GLOSSARY.md | Term definitions |
| COMBAT_SYSTEM.md | Combat mechanics (written when M8 is built) |
| military/COMMUNICATIONS.md | Comms tiers, first-contact, courier envelopes, perceived state, war-dec semantics |
| SPELL_SYSTEM.md | Spell/mana system (written when M9 is built) |
| ERA_SYSTEM.md | Era progression (written when needed) |
Build Process (.project/)
| Doc | Covers |
|---|---|
| ROADMAP.md | Demo scope + 12-phase build sequence |
| FEATURE_GAP.md | New systems beyond the reference implementation |
tasks/m0-m4/ |
Milestone task lists with porting checklists |
Quick Start
./run play # Launch the game
./run editor # Open Godot editor
./run lint # gdlint engine/src/
./run test # GUT tests headless
pnpm dev # Serve the player guide