Making a Simulation game - Part 1: The Agent Simulation Engine
Before I knew much about game development, I already knew I wanted to make simulation/strategy games.
But. There's just not much information on the internet about making a simulation game. This is what I learned.
You can't make a simulation game without studying SimCity.
The first reference is the GlassBox engine behind SimCity. Here's a 14-year-old video on how it works.
It's old (from 2012!), but most of the ideas still hold up:
- Everything on the map is a building: actual buildings, houses, water sources, forests,... etc.
- Buildings store resources.
- Buildings run rules. Rules trigger effects and animations.
- A map defines resources and building distributions.
- Agents are the simulation entities that bring resources from one building to another.
- Agents trigger simulation rules when they arrive at their destination, but no rule runs during transit.
- Zones run rules to create buildings.
Examples:
- A request arrives at a house -> a car spawns and looks for work.
- A worker arrives at a factory -> the factory turns on and starts producing goods and air pollution.
- An agent (truck) moves resources to another building.
Against the Storm: Physicality
Another huge inspiration for simulation/strategy games is Against the Storm. IMO the most inspiring one in recent years.
The key concept is Physicality. A persistent actor that exists in world space. Walks paths between buildings, stands at one, performs timed work. Where Agent is a flow event with a speed, PhysicalAgent is a thing in the world: a worker, a cargo truck, a courier.
Abstract agents from a SimCity-style engine are one-shot, ephemeral, interchangeable flow events. They do their job (move a resource from A to B) and then disappear. This lets the game scale while keeping good performance.
Physical Agents have needs that flow events don't:
- positioning (dispatch_move),
- stationary labor (dispatch_work),
- state across many ticks,
- and view-layer interpolation along a path.
Modeling them with bare Agents is fragile. We end up bolting motion, animation, and persistent state onto a primitive built to be a one-shot event, and the resource ledger absorbs what is really view state.
Physical Agents also make the game more intuitive. The player sees them moving around the map. All of these are natural:
- long-distance traveling = slow
- lots of agents waiting near a building = bottleneck
Games like Mini Motorways have mastered this technique. Everything the player needs to know is clearly visible on screen. No charts, no numbers.
Implementing in Godot
My implementation mostly follows their ideas.
Everything is agents moving resources between buildings. That's the only verb the engine knows.
Wood reaching a construction site, beer reaching a town order, water filling a well, power lighting a district, pollution drifting downwind, happiness radiating from a park. All the same shape: an agent ferries a resource bundle from one Building to another.
While doing so, a few more benefits emerged:
- Clean engine/content separation:
- The engine focuses on simulating agents efficiently.
- The content side can focus on design: what the buildings/resources/agents are, how they flow, and how it should be fun.
- Each building is an isolated scene tree (in Godot's terms). They compose and interact with each other cleanly.
- The model is basically double-entry bookkeeping. Every resource movement is a transaction that can be verified to keep the books balanced. This lets me catch subtle simulation bugs easily and debug game sessions via logs.
- Determinism: the whole engine can be made deterministic if you want.
Brews & Kings
This engine powers Brews & Kings, a roguelike medieval city builder where your whole city feeds one sprawling brewing operation — and kings rise or fall on the strength of your beer. Wishlist it on Steam to follow along.
