Population Simulation
The Go server runs a logistic growth model for each species in each habitat patch.
Logistic growth
Population change per tick follows the standard logistic equation:
dN/dt = r * N * (1 - N/K)Where:
N= current populationr= growth rate (configurable per species)K= carrying capacity (varies by patch size and quality)
Ticks are driven by the VS game clock via Heartbeat RPCs every 10s. If the server was offline, it uses analytical catch-up to fast-forward population changes for the elapsed real time.
Habitat patches
The world map is divided into habitat patches based on climate data exported by the C# mod.
- Climate regions are 16×16 chunk areas
- Each region is classified into one of 16 habitat types using temperature, rainfall, and vegetation thresholds
- Adjacent same-type regions are merged into patches
- Each patch has a carrying capacity based on its area and quality
Species-habitat matching
When a chunk loads, Heartwood queries which species can spawn there:
- Identify the habitat patch covering the chunk
- For each registered species, multiply
BaseCarryingCapacityby the species' affinity for the patch's habitat type - Compare to current population in the patch — spawn or despawn entities to match
Predator-prey dynamics
Predator populations consume prey populations on each simulation tick:
- Predation rate scales with predator population and prey availability
- If prey drops below a threshold, predator growth slows
- Modeled as a simplified Lotka-Volterra interaction (not full differential equations — logistic with prey-dependent growth rate)
Seasonal modifiers
Each species can have per-month presence modifiers. A modifier of 0.0 in January means the species doesn't appear in January (hibernating, migrated, etc.). Modifiers between 0 and 1 reduce the effective carrying capacity.
Migration
When a patch reaches carrying capacity, excess population migrates to neighboring patches with available capacity. Migration probability scales with the gradient between patches.
