docs(claude): 📝 Update Claude feature documentation in CLAUDE.md
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
d18b4f4144
commit
9a18407a3e
1 changed files with 73 additions and 55 deletions
128
CLAUDE.md
128
CLAUDE.md
|
|
@ -11,7 +11,8 @@ Fantasy 4X turn-based strategy game (Civ5 + Master of Magic + Magic: The Gatheri
|
|||
## Tech Stack
|
||||
|
||||
- **Engine:** Godot 4.x
|
||||
- **Language:** GDScript only (no C#, no GDExtension)
|
||||
- **Simulation:** Rust (`packages/physics-rs/`) — compiled to GDExtension for the game, WASM for the web guide
|
||||
- **Scripting:** GDScript — presentation layer only (rendering, UI, input, signals)
|
||||
- **Data:** JSON game packs (`games/age-of-dwarves/data/*.json`)
|
||||
- **Architecture:** Genre-agnostic engine with game pack content system
|
||||
|
||||
|
|
@ -19,7 +20,9 @@ Fantasy 4X turn-based strategy game (Civ5 + Master of Magic + Magic: The Gatheri
|
|||
|
||||
The engine is **genre-agnostic**. All game content and display text comes from game packs. The fantasy game "Age of Dwarves" is the default. See `docs/engine/ABSTRACTION.md` (to be written).
|
||||
|
||||
**Godot is the primary runtime. GDScript + JSON is the source of truth for everything.** The TypeScript in `packages/` and `guide/` exists only to serve the web guide — it is secondary, generated, and must never be the canonical location for game data or logic. When creating new systems, data structures, or content packages: design for Godot/GDScript first, with JSON data files in the engine tree (`engine/` or `games/`). The TS side consumes those same JSON files through bundler imports. Never create TypeScript-only packages for game content that Godot needs to read.
|
||||
**Rust is the simulation source of truth.** All game logic (physics, combat, economy, AI, pathfinding, magic, tech, turn resolution) lives in `packages/physics-rs/` and is compiled to two targets: GDExtension for the Godot game, WASM for the web guide. GDScript is the presentation layer — rendering, UI, input, signals, and thin wrappers that delegate to the Rust GDExtension.
|
||||
|
||||
**JSON game packs remain the canonical content store.** Stats, costs, effects, thresholds — all in `games/age-of-dwarves/data/*.json`. Neither Rust nor GDScript hardcodes game content.
|
||||
|
||||
- UI labels resolve through `ThemeVocabulary.lookup(engine_key)` — never hardcode theme strings
|
||||
- Sprites resolve through `ThemeAssets.resolve(path)` — never hardcode asset paths
|
||||
|
|
@ -36,50 +39,39 @@ See `README.md` for the full doc index. Docs live in two places:
|
|||
|
||||
Build process docs (roadmap, feature gap, task lists) stay in `.project/`.
|
||||
|
||||
## Single Source of Truth: GDScript → TypeScript
|
||||
## Single Source of Truth: Rust → GDExtension + WASM
|
||||
|
||||
> **The GDScript climate engine is the source of truth for all simulation logic. The TypeScript in `guide/` is generated output — never edited directly. If the guide gives wrong results, fix the GDScript and re-run the transpiler.**
|
||||
|
||||
The climate simulation runs in two runtimes: GDScript (Godot game engine) and TypeScript (web guide). GDScript is written first; TypeScript is auto-generated from it via `lilith-gdscript-transpiler`.
|
||||
|
||||
### Architecture
|
||||
> **The Rust crate `packages/physics-rs/` is the source of truth for all simulation logic. It compiles to two targets. Never duplicate simulation logic in GDScript or TypeScript.**
|
||||
|
||||
```
|
||||
games/age-of-dwarves/data/climate_spec.json ← Canonical thresholds, events, ley rules
|
||||
↓ read at runtime by both engines
|
||||
engine/src/modules/climate/climate.gd ← SOURCE OF TRUTH (physics steps)
|
||||
engine/src/modules/climate/ecological_events.gd ← SOURCE OF TRUTH (stochastic events)
|
||||
engine/src/modules/climate/anchor_decay.gd ← SOURCE OF TRUTH (ley anchor decay)
|
||||
engine/src/modules/climate/climate_spec_eval.gd ← SOURCE OF TRUTH (spec condition evaluator)
|
||||
↓ transpiled by tools/transpile-engine/transpile.py
|
||||
packages/engine-ts/src/ClimatePhysics.generated.ts ← AUTO-GENERATED, never edit
|
||||
packages/engine-ts/src/index.ts ← Re-exports for @magic-civ/engine-ts
|
||||
guide/age-of-dwarves/ ← Consumes @magic-civ/engine-ts (workspace:*)
|
||||
games/age-of-dwarves/data/climate_spec.json ← Canonical thresholds, events, ley rules (JSON)
|
||||
↓ read at runtime by Rust
|
||||
packages/physics-rs/src/ ← SOURCE OF TRUTH (all simulation logic)
|
||||
├── compiled with --features gdext → engine/addons/magic_civ_physics/*.so/.dll
|
||||
│ ↓ loaded by Godot
|
||||
│ engine/src/modules/climate/climate.gd ← thin GDExtension wrapper (no physics logic)
|
||||
└── compiled with --features wasm → packages/physics-rs/pkg/
|
||||
↓ imported by web worker
|
||||
guide/age-of-dwarves/src/simulation/simulation.worker.ts
|
||||
```
|
||||
|
||||
### Transpiler Package
|
||||
|
||||
`lilith-gdscript-transpiler` — custom GDScript→TypeScript transpiler.
|
||||
|
||||
- **Package**: `@packages/@py/gdscript-transpiler` in this workspace
|
||||
- **PyPI index**: `https://forge.nasty.sh/api/packages/lilith/pypi/simple/`
|
||||
- **Invocation**: `uv run tools/transpile-engine/transpile.py` (self-contained inline script — `uv` handles deps automatically, no manual pip install needed)
|
||||
- **Check mode**: `uv run tools/transpile-engine/transpile.py --check` (exits 1 if generated file is stale vs GDScript source)
|
||||
- **Sources**: `climate.gd`, `ecological_events.gd`, `anchor_decay.gd`, `climate_spec_eval.gd`
|
||||
- **Output**: `packages/engine-ts/src/ClimatePhysics.generated.ts`
|
||||
### Build commands
|
||||
|
||||
```bash
|
||||
uv run tools/transpile-engine/transpile.py # regenerate
|
||||
uv run tools/transpile-engine/transpile.py --check # CI: exit 1 if stale
|
||||
# WASM (web guide)
|
||||
cd packages/physics-rs && bash build-wasm.sh
|
||||
|
||||
# GDExtension (Godot game, Linux dev)
|
||||
cd packages/physics-rs && bash build-gdext.sh
|
||||
```
|
||||
|
||||
### Rules
|
||||
|
||||
- **Never edit `ClimatePhysics.generated.ts`** — it's auto-generated from GDScript
|
||||
- **Never hardcode terrain thresholds** — read from `climate_spec.json`
|
||||
- **All simulation changes go in GDScript first** — then re-run transpiler
|
||||
- **Ecological events require a seed** — `process_turn(game_map, turn, seed)` for deterministic PRNG
|
||||
- **Golden test vectors** verify both engines produce identical output on the same seed
|
||||
- **All simulation changes go in Rust** (`packages/physics-rs/src/`) — never in GDScript or TypeScript
|
||||
- **Never hardcode thresholds** — read from `climate_spec.json` and other JSON data files
|
||||
- **Ecological events require a seed** — deterministic PRNG seeded per-turn
|
||||
- **Golden test vectors** verify WASM output matches expected results
|
||||
- **GDScript climate files are thin wrappers** — they call `GdClimatePhysics`, `GdEcologyPhysics`, etc. via GDExtension. No physics logic lives in GDScript.
|
||||
|
||||
## Project-Specific Agents
|
||||
|
||||
|
|
@ -102,16 +94,16 @@ uv run tools/transpile-engine/transpile.py --check # CI: exit 1 if stale
|
|||
|
||||
| Task pattern | Agent |
|
||||
|-------------|-------|
|
||||
| `project.godot`, autoloads, `SceneManager`, save/load | `godot-engine` |
|
||||
| Hex coordinates, A*, map generation, tile storage | `game-algorithms` |
|
||||
| `economy.gd`, `happiness.gd`, `culture.gd`, city production, growth | `game-systems` |
|
||||
| `combat_resolver.gd`, keywords, flanking, ZOC, promotions | `combat-dev` |
|
||||
| `spell_system.gd`, `mana_pool.gd`, `archon.gd`, spells, wonders | `magic-dev` |
|
||||
| `ai_player.gd`, AI decisions, difficulty modifiers | `game-ai` |
|
||||
| `project.godot`, autoloads, `SceneManager`, save/load, GDExtension setup | `godot-engine` |
|
||||
| `packages/physics-rs/src/algorithms/`, hex math, A*, map gen, tile storage | `game-algorithms` |
|
||||
| `packages/physics-rs/src/economy/`, `city/`, `happiness/`, `culture/`, turn sequencing | `game-systems` |
|
||||
| `packages/physics-rs/src/combat/`, keywords, flanking, ZOC, promotions | `combat-dev` |
|
||||
| `packages/physics-rs/src/magic/`, spells, mana, Archons, enchantments, Ascension | `magic-dev` |
|
||||
| `packages/physics-rs/src/ai/`, AI decisions, difficulty modifiers | `game-ai` |
|
||||
| `*.json` data files, `vocabulary.json`, `game.json` | `game-data` |
|
||||
| `*.tscn` UI scenes, HUD panels, overlays, menus | `godot-ui` |
|
||||
| TileMap, sprites, camera, fog, selection highlight, animation | `godot-renderer` |
|
||||
| `guide/age-of-dwarves/`, `guide/engine/`, React, Vite, climate sim | `guide-web` |
|
||||
| `guide/age-of-dwarves/`, `guide/engine/`, React, Vite, WASM integration | `guide-web` |
|
||||
|
||||
## Conventions
|
||||
|
||||
|
|
@ -175,25 +167,47 @@ Poly edge: 2 1 0 5 4 3
|
|||
|
||||
### File Organization
|
||||
```
|
||||
packages/
|
||||
physics-rs/ — Rust simulation engine (SOURCE OF TRUTH for all game logic)
|
||||
src/
|
||||
grid/ — GridState, TileState, hex math
|
||||
climate/ — ClimatePhysics, EcologyPhysics, atmosphere, spec evaluator
|
||||
map_gen/ — MapGenerator, terrain, hydrology, wind
|
||||
algorithms/ — HexUtils, A* variants, LoS, range
|
||||
combat/ — CombatResolver, keywords, flanking, ZOC, promotions
|
||||
economy/ — gold, upkeep, yields, improvements
|
||||
city/ — production queue, growth, buildings
|
||||
happiness/ — global pool, racial tiers, Golden Ages
|
||||
culture/ — generation, border expansion
|
||||
magic/ — mana, spells, archons, enchantments, ascension
|
||||
tech/ — TechWeb graph
|
||||
ai/ — strategic AI, tactical, city, magic, wild creatures
|
||||
turn/ — turn sequencing, victory, era progression
|
||||
api_gdext.rs — godot-rust class registrations
|
||||
api_wasm.rs — wasm-bindgen exports
|
||||
Cargo.toml
|
||||
build-wasm.sh
|
||||
build-gdext.sh
|
||||
engine-ts/ — @magic-civ/engine-ts (types, runner, HexGrid — no generated physics)
|
||||
|
||||
engine/
|
||||
addons/
|
||||
magic_civ_physics/ — compiled GDExtension .so/.dll/.framework
|
||||
src/
|
||||
autoloads/ — singletons (GameState, TurnManager, DataLoader, EventBus, ThemeVocabulary, ThemeAssets)
|
||||
entities/ — game objects (unit, city, building, improvement, archon)
|
||||
map/ — tile storage, hex utils, pathfinder, game_map
|
||||
generation/ — map generator, terrain refiner, hydrology, wind
|
||||
map/ — tile storage, game_map (hex math delegates to Rust GDExtension)
|
||||
rendering/ — hex, city, unit, fog, river, road, indicator renderers
|
||||
core/ — save manager, pending actions, terrain affinity
|
||||
modules/
|
||||
combat/ — combat_resolver, keyword_handler
|
||||
magic/ — spell_system, mana_pool, infusion_system
|
||||
climate/ — climate, atmosphere, weather, ecological_events
|
||||
combat/ — thin GDExtension wrappers (no logic)
|
||||
magic/ — thin GDExtension wrappers (no logic)
|
||||
climate/ — thin GDExtension wrappers (no logic)
|
||||
ley/ — ley_network
|
||||
empire/ — economy, happiness, culture, government
|
||||
management/ — city_manager, unit_manager, improvement_manager
|
||||
events/ — natural_events
|
||||
victory/ — victory_manager, ascension_ritual
|
||||
ai/ — ai_player, ai_tactical, ai_city, ai_magic_research, ai_military
|
||||
tech/ — tech_web
|
||||
empire/ — thin GDExtension wrappers (no logic)
|
||||
ai/ — thin GDExtension wrappers (no logic)
|
||||
tech/ — thin GDExtension wrappers (no logic)
|
||||
victory/ — thin GDExtension wrappers (no logic)
|
||||
scenes/
|
||||
main/ — entry point
|
||||
menus/ — main_menu, game_setup, options, load_game
|
||||
|
|
@ -216,13 +230,17 @@ games/
|
|||
|
||||
guide/
|
||||
engine/ — @magic-civ/guide-engine (shared UI components, types, utils)
|
||||
age-of-dwarves/ — @magic-civilization/guide-age-of-dwarves (all pages, app shell)
|
||||
age-of-dwarves/ — @magic-civilization/guide-age-of-dwarves (all pages, app shell)
|
||||
src/simulation/simulation.worker.ts — imports from @magic-civ/physics-rs (WASM)
|
||||
```
|
||||
|
||||
## DX Tooling
|
||||
|
||||
### Testing & Linting
|
||||
- **GUT** (Godot Unit Test) — unit + integration tests for GDScript
|
||||
- **Rust tests** — `cargo test` in `packages/physics-rs/`
|
||||
- **WASM build** — `cd packages/physics-rs && bash build-wasm.sh`
|
||||
- **GDExtension build** — `cd packages/physics-rs && bash build-gdext.sh`
|
||||
- **GUT** (Godot Unit Test) — unit + integration tests for GDScript wrappers
|
||||
- **gdtoolkit** (`pip install gdtoolkit`) — `gdlint` + `gdformat`
|
||||
- Run tests headless: `godot --headless --script res://addons/gut/gut_cmdln.gd`
|
||||
- Run lint: `gdlint engine/src/`
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue