Engine-Game Separation

January 12, 2026 · View on GitHub

Status: Production Standard


Core Principle

ENGINE provides mechanisms (HOW), GAME defines policy (WHAT).

ENGINE is a reusable foundation. GAME is the specific implementation. The same ENGINE should support different games (space strategy, fantasy conquest, modern warfare) with different policies.


The Separation

ENGINE Layer (Mechanism)

  • Generic primitives and data structures
  • Rendering infrastructure
  • Input handling
  • Networking infrastructure
  • Save/load framework
  • Command execution

ENGINE asks: "How do I store province state?" "How do I render a map?" "How do I process commands?"

GAME Layer (Policy)

  • Game-specific formulas and rules
  • Colors, visuals, UI content
  • AI behavior and goals
  • Victory conditions
  • Balance values

GAME asks: "What is the tax formula?" "What color is France?" "When does a country surrender?"


Why This Matters

Reusability

Same ENGINE can power different games:

  • Grand strategy (EU4-like)
  • Space 4X
  • Fantasy conquest
  • Modern political simulation

Each game implements different policies using the same mechanisms.

Maintainability

Changes to game balance don't touch ENGINE code. Changes to rendering don't affect game rules. Clear boundaries reduce bugs.

Testability

ENGINE mechanisms can be tested in isolation. GAME policies can be tested with mock ENGINE.


Extension Points

ENGINE provides interfaces that GAME implements:

CategoryENGINE ProvidesGAME Implements
Game SystemsIGameSystem lifecycleEconomy, Buildings, Military
Map ModesIMapModeHandler contractPolitical, Economic, Diplomatic modes
CommandsICommand interfaceDeclareWar, BuildBuilding, etc.
DefinitionsIDefinition loadingBuilding types, unit types, etc.
RenderingIRenderer interfacesCustom borders, fog, effects

Import Rules

Strict hierarchy prevents circular dependencies:

CORE (Simulation):

  • Cannot import Map or Game
  • Pure simulation logic
  • Deterministic operations only

MAP (Presentation):

  • Can import Core
  • Cannot import Game
  • Reads simulation state for rendering

GAME (Policy):

  • Can import Core and Map
  • Defines all game-specific behavior
  • Owns initialization order

Rule: Dependencies flow downward only. CORE → MAP → GAME.


Data Ownership

ENGINE Owns

  • Province state primitives (owner, controller, terrain)
  • Country state primitives (exists, tag)
  • Command processing
  • Event bus
  • Time management

GAME Owns

  • Game-specific province data (development, buildings)
  • Game-specific country data (treasury, relations)
  • All formulas and balance values
  • UI content and styling
  • AI decision making

Initialization Pattern

GAME layer controls all initialization order:

  • ENGINE systems initialize through GAME coordinator
  • Avoids rogue Start/Awake methods
  • Clear dependency chain
  • Predictable load order

Common Mistakes

Putting policy in ENGINE:

  • Tax formula in ENGINE → Should be in GAME
  • Country colors in ENGINE → Should be in GAME
  • Building definitions in ENGINE → Should be in GAME

Putting mechanism in GAME:

  • Province storage reimplemented → Use ENGINE's ProvinceSystem
  • Custom event system → Use ENGINE's EventBus
  • Duplicate rendering logic → Use ENGINE's pluggable renderers

Design Principles

Mechanisms, Not Policy

ENGINE provides generic state access. GAME defines what to do with state.

Flexible, But Opinionated

  • Opinionated: "Use FixedPoint64 for determinism"
  • Flexible: "But you define the formulas"

Abstract Hard Problems

ENGINE solves: determinism, performance, state management, events, persistence. GAME focuses on: gameplay, content, balance.

Zero Game Logic in ENGINE

No game-specific concepts (farms, armies, trade) in ENGINE code. Only generic concepts: provinces, countries, commands, events.


Trade-offs

AspectBenefitCost
Strict separationReusable ENGINEMore interfaces to implement
Interface contractsClear boundariesIndirection overhead
Layer hierarchyNo circular depsCan't call "up" the hierarchy

Success Metric

Can you build a different game in one week using the same ENGINE?

If yes: Separation is working. If no: Too much policy leaked into ENGINE.


  • Pattern 1 (Engine-Game Separation): This document
  • Pattern 20 (Pluggable Implementation): How GAME extends ENGINE rendering
  • Pattern 2 (Command Pattern): How state changes flow through layers

Mechanism belongs in ENGINE. Policy belongs in GAME. Never mix them.