AI Game World Design — From First Principles
SkillMediaComplete mastery guide for designing and building AI-powered game worlds — procedural world generation, NPC behavior trees, LLM-driven dialogue systems, emergent storytelling, economy simulation, player modeling, and real-time difficulty adaptation. Covers the full stack from world-building fundamentals to integrating large language models as game directors, with special focus on crypto-native economies (token rewards, NFT items, on-chain achievements) and agent-based game architectures.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the AI Game World Design — From First Principles skill
What this skill tells your AI
The instructions your AI receives, as published by nirholas/three.ws in data/skills/development/ai-game-world-design/SKILL.md and read by ahel’s review.
This skill teaches you to architect game worlds where AI doesn't just play — it narrates, adapts, economizes, and breathes life into every NPC, quest, and ecosystem. You'll learn to build worlds that feel alive because they actually are.
Core Philosophy
┌─────────────────────────────────────────────────────────┐
│ THE LIVING WORLD MANIFESTO │
├─────────────────────────────────────────────────────────┤
│ │
│ A great AI game world has three properties: │
│ │
│ 1. EMERGENT — behaviors arise that designers │
│ never explicitly programmed │
│ │
│ 2. REACTIVE — the world changes in response │
│ to player actions, not just scripted triggers │
│ │
│ 3. PERSISTENT — consequences compound over time, │
│ creating unique histories for every playthrough │
│ │
│ AI is the engine that makes all three possible. │
│ │
└─────────────────────────────────────────────────────────┘
World Generation
Procedural Terrain
The foundation of any game world is geography. Procedural generation creates infinite variety from algorithmic rules.
| Technique | Best For | Scale |
|---|---|---|
| Perlin/Simplex Noise | Terrain heightmaps, caves | Continental |
| Wave Function Collapse | Tiled environments, dungeons | Room/zone |
| L-Systems | Vegetation, branching structures | Object |
| Voronoi Diagrams | Biome boundaries, territories | Regional |
| Agent-Based | City layouts, road networks | City |
| Grammar-Based | Building interiors, quest structures | Structure |
Layered Noise for Terrain
import numpy as np
def generate_terrain(width, height, octaves=6):
"""Generate realistic terrain using layered Perlin noise."""
terrain = np.zeros((width, height))
for octave in range(octaves):
frequency = 2 ** octave
amplitude = 0.5 ** octave
# Each octave adds finer detail at lower amplitude
noise_layer = perlin_noise_2d(width, height, frequency)
terrain += noise_layer * amplitude
# Apply erosion simulation
terrain = simulate_hydraulic_erosion(terrain, iterations=50000)
# Place biomes based on elevation + moisture
biomes = classify_biomes(terrain, moisture_map(terrain))
return terrain, biomes
Biome Classification
Elevation ↑
│
│ 🏔️ Snow Peak (> 0.85)
│ 🪨 Rocky Alpine (0.70 - 0.85)
│ 🌲 Forest (0.40 - 0.70, moisture > 0.5)
│ 🌾 Grassland (0.40 - 0.70, moisture < 0.5)
│ 🏜️ Desert (0.20 - 0.40, moisture < 0.3)
│ 🌊 Ocean (< 0.20)
│
└──────────────────────── Moisture →
Wave Function Collapse for Dungeons
WFC uses constraint propagation to generate environments where every tile is compatible with its neighbors:
class WFCGenerator:
def __init__(self, tileset, grid_size):
self.grid = [[set(tileset.all_tiles) for _ in range(grid_size)]
for _ in range(grid_size)]
def collapse(self):
while not self.is_fully_collapsed():
# 1. Find cell with lowest entropy (fewest possibilities)
cell = self.lowest_entropy_cell()
# 2. Collapse it to a single tile (weighted random)
self.observe(cell)
# 3. Propagate constraints to neighbors
self.propagate(cell)
def propagate(self, cell):
"""Remove incompatible tiles from neighbors recursively."""
stack = [cell]
while stack:
current = stack.pop()
for neighbor in self.get_neighbors(current):
removed = self.constrain(neighbor, current)
if removed:
stack.append(neighbor)
NPC Intelligence
Behavior Trees
The industry standard for NPC decision-making:
[Selector]
/ | \
[Guard] [Patrol] [Idle]
/ \
[Detect [Attack
Enemy] Sequence]
/ \
[Move To] [Strike]
[Range]
class BehaviorTree:
"""Composable NPC decision system."""
@selector # Try children left-to-right, stop at first success
def root(self, npc, world):
return [
self.combat_branch,
self.social_branch,
self.economic_branch,
self.patrol_branch,
self.idle_branch
]
@sequence # All children must succeed
def combat_branch(self, npc, world):
return [
lambda: self.detect_threat(npc, world),
lambda: self.evaluate_combat_odds(npc),
lambda: self.engage_or_flee(npc)
]
@sequence
def social_branch(self, npc, world):
return [
lambda: self.detect_nearby_npcs(npc, world),
lambda: self.check_relationship(npc),
lambda: self.initiate_conversation(npc)
]
Utility AI for Complex Decisions
When NPCs need to weigh multiple competing needs:
class UtilityAI:
"""Score every possible action, pick the highest."""
def decide(self, npc, world):
actions = [
("eat", self.score_hunger(npc)),
("sleep", self.score_fatigue(npc)),
("trade", self.score_trade(npc, world)),
("explore", self.score_curiosity(npc)),
("craft", self.score_craft_need(npc)),
("socialize", self.score_loneliness(npc)),
("fight", self.score_aggression(npc, world)),
]
# Add randomness to prevent robotic predictability
scored = [(a, s + random.gauss(0, 0.1)) for a, s in actions]
return max(scored, key=lambda x: x[1])[0]
def score_hunger(self, npc):
"""S-curve: almost 0 when full, spikes sharply below 30%."""
return 1 / (1 + math.exp(5 * (npc.food - 0.3)))
LLM-Driven NPC Dialogue
The revolution: using large language models to generate contextual, personality-rich dialogue in real time.
class LLMDialogueSystem:
def generate_response(self, npc, player_input, world_state):
prompt = f"""You are {npc.name}, a {npc.role} in {world_state.location}.
Personality: {npc.personality}
Current mood: {npc.mood} (influenced by: {npc.recent_events})
Relationship with player: {npc.relationship_score}/100
Knowledge: {npc.known_facts}
Current quest state: {npc.active_quests}
RULES:
- Stay in character. Never break the fourth wall.
- Reference events the NPC has witnessed.
- If relationship < 30, be guarded. If > 70, be warm.
- Offer hints about nearby quests naturally, never as menu items.
- If the player asks about something the NPC doesn't know, say so.
The player says: "{player_input}"
Respond as {npc.name} (1-3 sentences, spoken dialogue only):"""
response = llm.generate(prompt, max_tokens=150, temperature=0.8)
# Update NPC memory
npc.conversation_history.append({
"player": player_input,
"npc": response,
"timestamp": world_state.time
})
return response
Economy Simulation
Supply-Demand Agent-Based Model
class GameEconomy:
"""Living economy where prices emerge from NPC behavior."""
def __init__(self):
self.markets = {} # item → {supply, demand, price}
self.merchants = []
self.crafters = []
def tick(self):
# 1. Crafters produce items based on profit margins
for crafter in self.crafters:
profitable_items = [
item for item in crafter.recipes
if self.selling_price(item) > self.crafting_cost(item) * 1.2
]
crafter.produce(random.choice(profitable_items))
# 2. Merchants set prices based on supply/demand
for item, market in self.markets.items():
ratio = market.demand / max(market.supply, 1)
# Price moves toward equilibrium
market.price *= (1 + 0.05 * (ratio - 1))
market.price = max(market.floor_price, market.price)
# 3. NPC consumers buy based on needs
for npc in self.all_npcs:
needs = npc.get_current_needs()
for item, urgency in needs:
if self.markets[item].price < npc.gold * urgency:
npc.buy(item)
Crypto-Native Game Economy
For Web3 games, the in-game economy connects to real tokens:
┌─────────────────────────────────────────────────────┐
│ CRYPTO GAME ECONOMY LOOP │
├─────────────────────────────────────────────────────┤
│ │
│ Player Action → In-Game Reward │
│ (quest, PvP) (gold token, NFT loot) │
│ │ │
│ ┌───────▼───────┐ │
│ │ On-Chain │ │
│ │ Settlement │ │
│ └───────┬───────┘ │
│ │ │
│ ┌─────────────────┼─────────────────┐ │
│ ▼ ▼ ▼ │
│ DEX Trading Marketplace Staking │
│ (SPA/Gold) (NFT Items) (Yield in USDs)│
│ │
│ 💡 Items earned in-game trade on Arbitrum DEXs │
│ 💡 Gold token backed by USDs in game treasury │
│ 💡 Rare items are ERC-721 with on-chain metadata │
│ │
└─────────────────────────────────────────────────────┘
Emergent Storytelling
The Director AI
Instead of scripted quest lines, a Director AI monitors the game state and creates dynamic narrative events:
class DirectorAI:
"""Monitors world state, creates narrative tension dynamically."""
def evaluate_world(self, world):
tension = self.measure_tension(world)
pacing = self.analyze_pacing(world.recent_events)
if tension < 0.3 and pacing == "lull":
# World is too calm — introduce conflict
return self.generate_event("rising_action", world)
elif tension > 0.8:
# Too intense — offer respite
return self.generate_event("relief", world)
elif world.player.idle_time > 300:
# Player seems lost — create a hook
return self.generate_event("hook", world)
def generate_event(self, type, world):
"""Use LLM to create contextual narrative events."""
prompt = f"""Generate a {type} event for this world state:
Player location: {world.player.location}
Recent events: {world.recent_events[-5:]}
Active factions: {world.faction_tensions}
Player level: {world.player.level}
Unresolved threads: {world.open_storylines}
Generate a single event that:
- Fits naturally into current narrative
- Involves NPCs the player has met
- Creates a meaningful choice
- Has consequences that ripple through the world"""
return llm.generate(prompt)
Faction Systems
class FactionSystem:
"""NPCs belong to factions. Factions have relationships.
Player actions shift the political landscape."""
def on_player_action(self, action, target):
# Every action has faction consequences
for faction in self.factions:
delta = self.calculate_reputation_change(faction, action, target)
self.player_reputation[faction.id] += delta
# Faction-to-faction relations also shift
for other_faction in self.factions:
if other_faction == faction:
continue
if faction.is_allied_with(other_faction):
# Allied factions mirror reputation changes (dampened)
self.player_reputation[other_faction.id] += delta * 0.3
elif faction.is_rival_of(other_faction):
# Rival factions invert reputation changes
self.player_reputation[other_faction.id] -= delta * 0.5
Adaptive Difficulty
Flow State Targeting
The ideal game keeps players in a "flow state" — challenged but not frustrated:
Difficulty ↑
│
│ ╔═══════════════╗
│ ║ ANXIETY ║ ← Too hard: player quits
│ ╠═══════════════╣
│ ║ FLOW STATE ║ ← Sweet spot: engaged + challenged
│ ╠═══════════════╣
│ ║ BOREDOM ║ ← Too easy: player disengages
│ ╚═══════════════╝
│
└──────────────────────── Player Skill →
class AdaptiveDifficulty:
"""Continuously adjust challenge to maintain flow state."""
def __init__(self):
self.player_skill_estimate = 0.5 # Bayesian estimate
self.target_win_rate = 0.65 # Sweet spot
def update_skill_estimate(self, encounter_result):
"""Bayesian update based on encounter outcome."""
if encounter_result.won:
difficulty = encounter_result.difficulty
# Player won a hard fight → skill estimate increases more
self.player_skill_estimate += 0.1 * difficulty
else:
self.player_skill_estimate -= 0.05
self.player_skill_estimate = max(0, min(1, self.player_skill_estimate))
def scale_encounter(self, base_encounter):
"""Scale enemy stats to target the flow state."""
scale = self.player_skill_estimate / 0.5
return base_encounter.scaled(
health_mult=scale,
damage_mult=scale * 0.9, # Slightly favor player
ai_aggression=min(1.0, scale * 1.1),
loot_quality=scale # Better loot from harder fights
)
Architecture Patterns
Entity-Component-System (ECS)
The dominant pattern for game world architecture:
┌─────────────────────────────────────────────┐
│ ECS ARCHITECTURE │
├─────────────────────────────────────────────┤
│ │
│ Entity = just an ID (uint32) │
│ Component = pure data (no logic) │
│ System = pure logic (no data) │
│ │
│ Entity: #4521 │
│ ├── Position { x: 100, y: 50 } │
│ ├── Health { current: 80, max: 100 } │
│ ├── AI { behavior_tree: "merchant" } │
│ ├── Inventory { items: [...] } │
│ └── Dialogue { personality: "grumpy" } │
│ │
│ Systems process ALL entities with │
│ matching components each tick: │
│ - MovementSystem → Position + Velocity │
│ - CombatSystem → Health + Weapon + AI │
│ - DialogueSystem → AI + Dialogue + Position│
│ - EconomySystem → Inventory + Merchant │
│ │
└─────────────────────────────────────────────┘
Sperax Integration Opportunities
AI game worlds naturally intersect with crypto infrastructure:
- USDs as Game Currency: In-game treasury backed by USDs earns auto-yield, funding ongoing development and player rewards
- ERC-8004 Agent NPCs: NPCs registered as on-chain agents via ERC-8004 — players can verify NPC behavior commitments, and NPCs build reputation
- SPA Governance: Players stake SPA to vote on world events, faction policies, and economy parameters
- Arbitrum Settlement: Low-cost L2 transactions enable microtransactions for every in-game trade without prohibitive gas
Reference Implementation
The HyperScape project (by nirholas) demonstrates many of these concepts in a working AI-powered MMORPG with procedural worlds, LLM NPCs, and crypto-native economy on Arbitrum.
Signals
- GitHub stars
- 114
- Forks
- 29
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
ai-game-world-design- Source
- github.com/nirholas/three.ws