Skip to content

The Wild — Ecosystem Simulation

The Wild is the ecosystem simulation component of the Living World. It models species populations, predator-prey relationships, biome affinities, seasonal birth-rate variation, and territorial migration. The simulation runs server-side and is authoritative — your game reads Wild state, it does not compute it.

Species

A species is defined by a SpeciesDefinition asset. You author species in the editor’s Wild Zone Editor panel or as JSON in your content directory.

{
"id": "rabbit",
"displayName": "Rabbit",
"type": "Prey",
"biomeAffinity": ["Grassland", "Forest"],
"basePopulation": 200,
"populationFloor": 10,
"populationCeiling": 800,
"baseBirthRate": 0.15,
"seasonalBirthRateModifiers": {
"Spring": 1.8,
"Summer": 1.1,
"Autumn": 0.7,
"Winter": 0.3
},
"foodConsumptionRate": 0.02,
"foodSources": ["berries", "grass"],
"predators": ["fox", "wolf"]
}

Key fields:

  • populationFloor — the population cannot drop below this value through natural simulation. The floor prevents a species from being fully driven extinct by predator pressure alone. Echo events (hunting) can push a species to zero if the floor is set to 0.
  • populationCeiling — the carrying capacity. Growth slows as population approaches the ceiling.
  • seasonalBirthRateModifiers — multipliers applied per season. The example models a classic temperate pattern: boom in spring, decline through winter.
  • foodSources — the resource node IDs this species depletes. A large rabbit population will reduce berry node levels (via The Flow).

Predator-prey dynamics

Predator species consume prey species. The Wild uses a discrete-time Lotka-Volterra model:

  • Predator populations grow when prey is abundant
  • Predator populations shrink when prey is scarce
  • Prey populations recover when predator pressure drops
  • Oscillations are expected and intentional — they create natural cycles in resource availability

Predator species definitions include:

{
"id": "wolf",
"type": "Predator",
"prey": ["rabbit", "deer"],
"huntSuccessRate": 0.6,
"energyPerKill": 1.2,
"territoryRadiusZones": 2
}

territoryRadiusZones controls how many zones a predator pack can range across when hunting. A wolf with territoryRadiusZones: 2 will draw prey from the current zone and adjacent zones.

Reading Wild state from game code

var worldState = Services.Get<IWorldStateQuery>();
// Get current population of rabbits in a zone
PopulationSnapshot rabbits = worldState.GetPopulation(zoneId, speciesId: "rabbit");
Logger.Info($"Rabbit population: {rabbits.Current} (trend: {rabbits.Trend})");
// "Rabbit population: 142 (trend: Declining)"
// Trend is: Growing, Stable, Declining, Endangered, Recovered

Subscribe to population threshold events via WorldStateCache.Changed:

var cache = Services.Get<WorldStateCache>();
cache.Changed += (sender, change) =>
{
if (change is PopulationChangedEvent pop
&& pop.SpeciesId == "rabbit"
&& pop.Trend == PopulationTrend.Endangered)
{
// Trigger a quest: protect the rabbits from wolf predation
QuestSystem.Activate("quest_rabbit_population");
}
};

Territory and migration

When a predator species’ population in a zone exceeds 70% of its ceiling, the excess population migrates to adjacent zones with compatible biomes. Migration events are recorded by The Chronicle. If no compatible adjacent zone has capacity, the excess is simply capped — the population does not exceed the ceiling.

Prey species migrate away from zones where predator pressure is very high (predator-to-prey ratio > 1.5). This creates natural population flows across zones that players can observe over time.

Wild Zone Editor

The Wild Zone Editor panel in the Softfire editor (accessible from View → Living World → Wild Zone Editor) provides:

  • A visual map of zone boundaries and species assignments
  • Population graphs over world-time history
  • Biome-override controls per zone
  • Species assignment: drag species from the library onto a zone
  • Predator-prey relationship graph view

The Echo affects The Wild

Hunt Echo events submitted by players reduce prey populations in the zone where the hunt occurred. The Echo applies a huntMagnitude (1.0 = one typical kill) to the prey species’ population. Rate-limiting on the Root prevents a single player from flooding the simulation with Hunt events.

var chronicle = Services.Get<ChronicleService>();
var query = new ChronicleQuery
{
EventTypes = new[] { ChronicleEventType.SpeciesEndangered },
ZoneIds = new[] { myZoneId },
SinceTime = WorldTime.Now.MinusDays(30),
};
IReadOnlyList<ChronicleEvent> events = await chronicle.QueryAsync(query);
foreach (var e in events)
{
Logger.Info($"{e.Details["speciesId"]} is endangered in zone {e.ZoneId}.");
}