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 zonePopulationSnapshot 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, RecoveredSubscribe 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}.");}