An AI-driven civilization simulation where every NPC is powered by an LLM (large language model). Characters have needs, memories, personalities, relationships, and make autonomous decisions in a procedurally generated world. Watch an emergent society unfold — or run it headless and observe the results.
┌───────────────────────────────────────────────────────────────┐
│ CivilizationSim │
├───────────────────────────────────────────────────────────────┤
│ main.py — Pygame render loop + simulation tick │
│ observer.py — Headless simulation runner (no GUI) │
│ config.py — All tuning knobs in one place │
├───────────────────────────────────────────────────────────────┤
│ engine/ — World generation + time │
│ world.py Procedural tile map (biomes, rivers, caves)│
│ time_engine.py Day/night cycle, seasons, years │
├───────────────────────────────────────────────────────────────┤
│ entities/ — Game objects │
│ character.py Human NPC with needs, skills, memory │
│ animal.py Rabbits, deer, wolves, goats, fish, etc. │
│ item.py Items, recipes, crafting registries │
├───────────────────────────────────────────────────────────────┤
│ agents/ — LLM integration │
│ character_agent.py Prompt engineering + JSON extraction │
│ crafting_agent.py LLM-guided discovery of new recipes │
│ memory.py SQLite-backed shared world database │
├───────────────────────────────────────────────────────────────┤
│ systems/ — Gameplay subsystems (18 total) │
│ needs.py Hunger, thirst, energy, warmth, social │
│ crafting.py Item combination + recipe discovery │
│ social.py Talking, relationship building, mating │
│ personality.py Big Five traits + random generation │
│ memory_stream.py Importance-weighted memory retrieval │
│ reflection.py LLM synthesis of memories into beliefs │
│ planning.py Multi-step goal planning via LLM │
│ tribe.py Group formation + knowledge sharing │
│ culture.py Memes, traditions, cultural spread │
│ economy.py Item valuation, trading, sharing │
│ governance.py Elder councils, decision-making │
│ religion.py Beliefs, rituals, shamanism │
│ ecology.py Resource regrowth, animal population │
│ weather.py Seasons, storms, rain, snow, fog │
│ health.py Wounds, sickness, treatment, death │
│ reputation.py Social standing, titles, fame │
│ stats.py Time-series metrics collection │
│ spatial.py Chunk-based spatial indexing (perf) │
│ ai_tiers.py Tier 1 (LLM) vs Tier 2 (rule-based) │
│ arcs.py Narrative arcs (tragedy, redemption, etc.)│
│ quests.py Generated quests with deadlines │
│ storyteller.py Narrative tension + dramatic events │
│ chronicle.py Markdown chronicle of world events │
├───────────────────────────────────────────────────────────────┤
│ renderer/ — Pygame visualization (10 panels) │
│ tile_renderer.py Tiled world map (biome-aware) │
│ entity_renderer.py Characters, animals, particles │
│ hud.py Character panel, event log, time bar │
│ relationship_web.py Force-directed relationship graph │
│ minimap.py Zoomed-out world overview │
│ timeline.py Population/event timeline │
│ stats_dashboard.py Charts and metrics │
│ god_panel.py Click-to-inspect God Mode │
├───────────────────────────────────────────────────────────────┤
│ tests/ — Unit tests (pytest) │
│ assets/ — Sprites, fonts, tile sets │
└───────────────────────────────────────────────────────────────┘
Each tick (6 per real second), every character decays their needs (hunger, thirst, energy, warmth, social). Every ~120 ticks (~20 real seconds), a character "thinks" — their current state is sent to a reasoning LLM (deepseek-v4-flash) which returns a JSON decision with an action, a thought, and an emotion.
{
"action": "gather_berries",
"thought": "I'm getting hungry, better find food before nightfall.",
"emotion": "concerned"
}When needs hit critical thresholds (hunger < 20, thirst < 15, energy < 10, warmth < 15), a deterministic rules engine takes over — bypassing the LLM entirely. Characters will automatically seek water, eat from inventory, gather nearby berries, start fires, or sleep. This ensures no character dies from LLM latency or bad outputs.
Characters have a memory stream — every significant event is stored with an importance score. Periodically, the reflection system synthesizes multiple memories into higher-level beliefs via the LLM:
"I've gathered berries near the river three times now. The riverbank seems to be the most reliable food source."
Characters are generated with Big Five personality traits (Openness, Conscientiousness, Extraversion, Agreeableness, Neuroticism) that affect their behavior — extraverts seek social interaction sooner, neurotic characters sleep at higher energy thresholds, etc. Over time, identity evolution shifts traits based on lifetime actions — a character who hunts frequently becomes more conscientious and less agreeable.
The 80×60 tile world is generated with:
- Height map using box-blur noise
- River snaking from top to bottom with shoreline
- 5 biomes: Forest, Plains, Mountains, Swamp, Desert
- Cave systems (3-5) in mountain peaks
- 80+ animals across 7 species, with breeding, predation, starvation
- Resources scattered by biome: wood (trees), stone, berries, flint, mushrooms, reeds, cacti, fish
- Day/night cycle and 4 seasons (spring, summer, autumn, winter)
Press G to enter God Mode — click any entity or tile to inspect its full state, relationships, memories, inventory, and skills. Press R for the relationship web, S for the stats dashboard, T for the population timeline.
- Python 3.10+ (tested on 3.10)
- A running display for the GUI (or use
observer.pyfor headless mode)
cd civilization_sim
pip install -r requirements.txtThis simulation requires an LLM API key. It uses the OpenCode Go API (OpenAI-compatible endpoint) with deepseek-v4-flash by default.
Create a .env file in the civilization_sim/ directory:
OPENROUTER_API_KEY=your_api_key_here
The .env file is gitignored — it will never be committed.
GUI mode (requires display):
cd civilization_sim
python3 main.pyHeadless observer (terminal only, runs N ticks and reports stats):
cd civilization_sim
python3 observer.pyThe observer runs 240 ticks, logs every 10 ticks, and prints a summary: per-character need changes, action distribution, inventory, skills, and any critical issues detected.
All tuning parameters live in config.py. Key sections:
| Section | Controls |
|---|---|
| World | Map size (80×60), tick rate, aging speed |
| Needs | Max values, decay rates, critical thresholds |
| LLM | Model, endpoint, token budget, think interval |
| Personality | Trait thresholds, identity evolution cadence |
| Ecology | Resource regrowth, animal breeding, seasonal multipliers |
| Economy | Item values, sharing thresholds |
| Health | Wound severity, treatment, death risk |
| Weather | Season transitions, weather effects |
| AI Tiers | Which characters get full LLM vs. rule-based |
CivilizationSim/
├── civilization_sim/
│ ├── main.py # Pygame entry point
│ ├── observer.py # Headless runner
│ ├── config.py # All configuration
│ ├── .env # API key (gitignored)
│ ├── engine/
│ │ ├── world.py # Procedural world generation
│ │ └── time_engine.py # Day/night/season cycle
│ ├── entities/
│ │ ├── character.py # Human NPC entity
│ │ ├── animal.py # Animal entity
│ │ └── item.py # Item/recipe definitions
│ ├── agents/
│ │ ├── character_agent.py # LLM prompt + JSON parsing
│ │ ├── crafting_agent.py # LLM recipe discovery
│ │ └── memory.py # SQLite world database
│ ├── systems/
│ │ ├── needs.py # Need decay + survival checks
│ │ ├── crafting.py # Item combinations
│ │ ├── social.py # Talk, mate, reproduce
│ │ ├── personality.py # Big Five traits
│ │ ├── memory_stream.py # Importance-weighted memory
│ │ ├── reflection.py # Memory → belief synthesis
│ │ ├── planning.py # LLM goal planning
│ │ ├── tribe.py # Group dynamics
│ │ ├── culture.py # Cultural transmission
│ │ ├── economy.py # Trade + sharing
│ │ ├── governance.py # Leadership
│ │ ├── religion.py # Belief systems
│ │ ├── ecology.py # Resource/animal cycles
│ │ ├── weather.py # Seasons + weather
│ │ ├── health.py # Wounds + sickness
│ │ ├── reputation.py # Social standing
│ │ ├── stats.py # Metrics collection
│ │ ├── spatial.py # Chunk indexing
│ │ ├── ai_tiers.py # Tiered AI quality
│ │ ├── arcs.py # Narrative arcs
│ │ ├── quests.py # Generated quests
│ │ ├── storyteller.py # Drama injection
│ │ └── chronicle.py # World event log
│ ├── renderer/
│ │ ├── tile_renderer.py # Map rendering
│ │ ├── entity_renderer.py # Character/animal sprites
│ │ ├── hud.py # UI panels + event log
│ │ ├── relationship_web.py # Social graph
│ │ ├── minimap.py # World overview
│ │ ├── timeline.py # Population timeline
│ │ ├── stats_dashboard.py # Metrics charts
│ │ └── god_panel.py # Inspection mode
│ ├── tests/
│ │ ├── test_world.py
│ │ ├── test_character.py
│ │ └── test_tile_renderer.py
│ └── assets/
│ ├── grass_tiles.png
│ ├── PublicPixel.ttf
│ └── CREDITS.md
├── .gitignore
└── requirements.txt
| Key | Action |
|---|---|
| Arrow keys | Pan camera |
G |
Toggle God Mode (click to inspect) |
R |
Toggle relationship web |
S |
Toggle stats dashboard |
T |
Toggle timeline |
ESC |
Exit |
SPACE |
Pause/Resume |
- pygame — Rendering and input
- httpx — Async HTTP client for LLM API calls
- python-dotenv — Load
.envconfiguration - pytest — Test framework
Assets from:
- Public Pixel Font by GGBotNet (CC0)
- Pixel Art Top Down - Basic by Cainos (free commercial use)
- Stone Age Sprite Set by VWolfdog (CC0)
MIT