- Rust 100%
| config | ||
| src | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
| UNLICENSE | ||
terra-step
Fantasy world simulator — a terminal-based strategy game where procedurally generated worlds evolve through turn-based faction conflict.
Rust 2024 edition, ratatui TUI, deterministic simulation.
Features
- Procedural world generation — 3-level Voronoi hierarchy (Continents → Provinces → Counties) with Perlin noise terrain (plains, forest, mountain, desert, swamp, water)
- Turn-based simulation — deterministic AI factions gather income, build armies, construct buildings, and compete for territory
- 6 species, 12 factions — Elves, Dwarves, Catfolk, Orcs, Merfolk, and Dragonkin, each with unique traits, terrain affinities, and AI behaviors
- Building system — Farms, Lumbermills, Mines, Barracks, Mage Towers, and Forts, with terrain-specific production modifiers
- Trait-driven AI — 17 traits (greedy, cruel, expansive, militaristic, etc.) that influence attack decisions and stat bonuses
- Terminal UI — interactive map with zoom/pan, faction info panel, turn history scrubbing, county browser, and terrain legend
- Deterministic — same seed always produces the same world and simulation results
- Fully configurable — all species, factions, terrain, traits, buildings, and world parameters are defined in TOML files
Installation
git clone https://github.com/yourusername/terra-step
cd terra-step
cargo build --release
Requires Rust 2024 edition (Rust 1.85+).
Usage
# Run with default seed (42) for 100 turns
cargo run --release
# Custom seed and turn count
cargo run --release -- --seed 12345 --turns 200
# Headless log mode — print AI decisions to stdout (no TUI)
cargo run --release -- --log
# Verbose log output — full income/army/resource breakdown per faction
cargo run --release -- --log --verbose
# Pipe to a file for analysis
cargo run --release -- --seed 7 --turns 500 --log --verbose > run_7.log
# Show help
cargo run --release -- --help
Log output format
Simple (--log):
=== Turn 1 ===
Abyssal Trench: income=43.0 army=50→52 counties=5 stored=(F:71.7 W:43.9 S:23.8 I:10.0 G:49.5 M:12.5)
Bloodfang Horde → Attack #97 Laestock [cost 24G]
Bloodfang Horde → Build Barracks in #17 Dark Forest [cost {wood: 20, stone: 10}]
Bloodfang Horde → Develop #3 Blood Plains [cost 20G, dev 10%→20%]
Combat for Krofeworth: Sandswept Pride vs Abyssal Trench → Lost! Losses: 13.2/4.8
Verbose (--log --verbose):
======================================================================
Turn 1
======================================================================
--- Abyssal Trench (id=0) ---
Counties: 5 Army: 50.0
Income: +22.8F +13.9W +3.8S +2.5M (total: 43.0)
Building army: +0.0 Regen: +2.2 Upkeep: -0.5G -1.0F
Army: 50.0 → 52.2
Stored: Before: F:50.0 W:30.0 S:20.0 I:10.0 G:50.0 M:10.0
After: F:71.7 W:43.9 S:23.8 I:10.0 G:49.5 M:12.5
>> Attack #97 Laestock [cost 24G]
>< Combat for Laestock: Bloodfang Horde (atk) vs Abyssal Trench (def)
Attack roll: 48.2 Defense roll: 42.1 → Won!
Losses: atk -4.5 def -7.2
Controls
| Key | Action |
|---|---|
+/- |
Zoom in/out |
| Arrow keys | Navigate zoom items (map) / scroll faction list (info) |
W A S D |
Pan the viewport |
[/] |
Step back/forward through turn history |
Tab |
Toggle focus between map and info panel |
Enter |
Expand/collapse selected faction (info focus) |
n/p |
Next/previous county (county zoom level) |
c |
Toggle county browser |
l |
Toggle terrain legend overlay |
? |
Toggle help dialog |
Space |
Pause/resume auto-advance |
Ctrl+U/Ctrl+D |
Scroll info panel by 10 lines |
| Mouse click | Zoom to county (map) / select faction (info) |
| Mouse scroll | Zoom in/out |
q |
Quit |
Configuration
All game data is defined in TOML files under config/:
| File | Purpose |
|---|---|
world.toml |
Map dimensions, generation parameters, army regen rate |
terrain.toml |
Terrain types, colors, passability, base resources |
species.toml |
Playable species, stat modifiers, terrain affinities |
factions.toml |
Named factions, species assignment, traits, starting counties |
traits.toml |
Trait definitions with stat bonuses |
buildings.toml |
Buildable structures, costs, production, terrain modifiers |
Customization: place config files in ~/.config/terra-step/ to override the bundled defaults. Items are merged by name — project entries override home entries with the same name.
Architecture
src/
├── main.rs # CLI entry point (clap argument parsing)
├── app.rs # Application state, turn management, view scrubbing
├── config/
│ ├── mod.rs # Config loading and merging (home + project)
│ └── types.rs # Deserialization DTOs (TOML shapes)
├── world/
│ ├── generator.rs # Voronoi world generation, faction placement
│ ├── types.rs # Runtime types (World, Continent, County, Faction, etc.)
│ ├── names.rs # Procedural name generation (syllable-based)
│ └── faction.rs # (stub)
├── simulation/
│ ├── turn.rs # Turn loop: income → army regen → AI decisions → combat → snapshot
│ ├── economy.rs # Income calculation, building production
│ └── combat.rs # Attack resolution, defense bonuses
├── tui/
│ ├── mod.rs # Event loop, input handling, layout
│ ├── renderer.rs # Map rendering, faction borders, labels
│ ├── screens/ # (stub)
│ └── widgets/ # (stub)
└── persistence/
├── mod.rs # (stub)
└── save.rs # (stub)
The world is generated as a 3-level Voronoi diagram: continents are seeded from random points, subdivided into provinces, then into counties. Terrain is sampled from 2D Perlin noise (elevation + moisture).
Each turn: factions receive income → regenerate armies → make AI decisions (attack, build, or develop) → contested counties are resolved → a snapshot is recorded. The RNG is seeded from world.seed + turn * 7919 for full determinism.
Testing
cargo test # 57 tests, all deterministic
cargo check # 0 warnings expected
cargo clippy # run before pushing
License
This is free and unencumbered software released into the public domain. See UNLICENSE for details.