docs(age-dwarves): 📝 Implement detailed tutorials, mechanics, and onboarding guides for the Age of Dwarves documentation

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-26 00:21:29 -07:00
parent 3646714e6c
commit e7ada0057f
3 changed files with 1242 additions and 0 deletions

View file

@ -0,0 +1,392 @@
# Biome Classification
> Complete specification for the BiomeClassifier: tile state to biome_id mapping for all 25+ biomes, including aquatic sub-classification and subterranean detection.
---
## Biome Inventory (26 biomes)
### Aquatic (8 biomes)
| # | Biome | Quality Range | Substrate | Temperature | Moisture | Key Discriminator |
|---|-------|-------------|-----------|-------------|----------|-------------------|
| 1 | `deep_ocean` | Q1-Q4 | deep_water | any | n/a | depth_from_coast > 3 |
| 2 | `shallow_ocean` | Q1-Q5 | shallow_water | any | n/a | depth_from_coast <= 3, not tropical |
| 3 | `coral_reef` | Q1-Q5 | shallow_water | >0.55 | n/a | tropical shallow, depth_from_coast <= 2 |
| 4 | `estuary` | Q1-Q4 | shallow_water | any | high | river mouth: adjacent to river AND ocean |
| 5 | `lake` | Q1-Q4 | lake_bed | any | n/a | water body size >= 2 |
| 6 | `pond` | Q1-Q2 | lake_bed | any | n/a | water body size == 1 |
| 7 | `river` | Q1-Q3 | linear water | any | n/a | linear water body type |
| 8 | `mangrove` | Q1-Q4 | wetland + coastal | >0.55 | high | tropical + coastal + wetland substrate |
### Tropical (4 biomes, temp > 0.55)
| # | Biome | Quality Range | Substrate | Temperature | Moisture | Key Discriminator |
|---|-------|-------------|-----------|-------------|----------|-------------------|
| 9 | `tropical_rainforest` | Q1-Q5 | lowland/midland | >0.65 | >0.7 | hot + very wet + canopy > 0.6 |
| 10 | `tropical_dry_forest` | Q1-Q4 | lowland/midland | >0.55 | 0.4-0.7 | tropical + moderate moisture |
| 11 | `savanna` | Q1-Q3 | lowland/midland | >0.55 | 0.15-0.4 | tropical + low-moderate moisture |
| 12 | `desert` | Q1-Q3 | lowland/midland/arid | >0.55 | <0.15 | hot + very dry |
### Temperate (5 biomes, temp 0.25-0.55)
| # | Biome | Quality Range | Substrate | Temperature | Moisture | Key Discriminator |
|---|-------|-------------|-----------|-------------|----------|-------------------|
| 13 | `temperate_forest` | Q1-Q5 | lowland/midland | 0.25-0.55 | >0.5 | canopy > 0.5 |
| 14 | `temperate_grassland` | Q1-Q4 | lowland/midland | 0.25-0.55 | 0.3-0.5 | moderate moisture, low canopy |
| 15 | `chaparral` | Q1-Q3 | midland | 0.25-0.55 | 0.15-0.35 | dry-moderate, scrubland |
| 16 | `swamp` | Q1-Q4 | wetland | >0.4 | >0.8 | saturated + warm |
| 17 | `bog` | Q1-Q3 | wetland | <0.4 | >0.7 | saturated + cool |
### Cold (3 biomes, temp < 0.25)
| # | Biome | Quality Range | Substrate | Temperature | Moisture | Key Discriminator |
|---|-------|-------------|-----------|-------------|----------|-------------------|
| 18 | `boreal_forest` | Q1-Q4 | lowland/midland | 0.1-0.25 | >0.35 | cool + moderate moisture + canopy > 0.3 |
| 19 | `tundra` | Q1-Q3 | lowland/midland | 0.05-0.15 | any | cold, minimal flora |
| 20 | `polar_desert` | Q1-Q2 | any | <0.05 | any | extreme cold |
### Elevation (5 biomes)
| # | Biome | Quality Range | Substrate | Temperature | Moisture | Key Discriminator |
|---|-------|-------------|-----------|-------------|----------|-------------------|
| 21 | `montane_forest` | Q1-Q4 | highland | 0.2-0.45 | >0.4 | highland + canopy > 0.4 |
| 22 | `cloud_forest` | Q1-Q5 | highland | 0.25-0.45 | >0.7 | highland + very wet |
| 23 | `alpine_meadow` | Q1-Q3 | mountain | any | >0.3 | above treeline + moderate moisture |
| 24 | `alpine_tundra` | Q1-Q2 | mountain/peak | any | <0.3 | above treeline + dry |
| 25 | `permanent_ice` | Q1-Q1 | peak | <0.1 | any | summit + extreme cold |
### Special (1 biome)
| # | Biome | Quality Range | Substrate | Temperature | Moisture | Key Discriminator |
|---|-------|-------------|-----------|-------------|----------|-------------------|
| 26 | `subterranean` | Q1-Q4 | mountain/peak | any | any | has_cave == true (map gen marker) |
---
## Classification Algorithm
### Top-Level Dispatch
```
BiomeClassifier.classify(tile) -> biome_id:
if tile.has_cave:
return "subterranean"
if tile.is_water:
return _classify_aquatic(tile)
if tile.substrate_id == "volcanic":
return "volcanic" # special substrate, not a biome per se
return _classify_land(tile)
```
### Aquatic Sub-Classification
The aquatic classifier handles 8 water biomes with priority-ordered checks. Order matters: more specific biomes (estuary, mangrove, coral_reef) must be checked before generic ones (shallow_ocean, deep_ocean).
```
_classify_aquatic(tile) -> biome_id:
# 1. Inland water bodies (identified at map gen)
if tile.water_body.type == "pond":
return "pond"
if tile.water_body.type == "river":
return "river"
if tile.water_body.type == "lake":
return "lake"
# 2. Estuary: river mouth detection
# A tile is an estuary if it is ocean/sea water AND
# at least one neighbor is a river tile or river-mouth-flagged
if _is_ocean(tile) and _has_adjacent_river_mouth(tile):
return "estuary"
# 3. Mangrove: tropical + coastal + wetland
# Technically a coastal biome, classified on the water side
# where shallow water meets tropical wetland
if tile.depth_from_coast <= 1 and tile.temperature > 0.55:
if _has_adjacent_wetland(tile):
return "mangrove"
# 4. Coral reef: tropical shallow water
if tile.temperature > 0.55 and tile.depth_from_coast <= 2:
return "coral_reef"
# 5. Depth-based ocean classification
if tile.depth_from_coast <= 3:
return "shallow_ocean"
return "deep_ocean"
```
**River mouth detection**: A tile has `_has_adjacent_river_mouth` if any of its hex neighbors is:
- A river tile (water_body.type == "river"), OR
- A land tile with `river_exit == true` (set by hydrology generation when a river flows into the ocean)
**Adjacent wetland detection**: `_has_adjacent_wetland` checks if any hex neighbor is a land tile with `substrate_id == "wetland"`.
### Land Classification
Land classification uses a priority cascade: wetland override, then elevation, then temperature, then moisture.
```
_classify_land(tile) -> biome_id:
temp = tile.temperature
moisture = tile.moisture
elevation = tile.elevation
canopy = tile.canopy_cover
# --- Wetland override (saturated lowlands) ---
if tile.substrate_id == "wetland" or (moisture > 0.7 and elevation < 0.4):
if temp > 0.4:
return "swamp"
return "bog"
# --- Elevation-driven (highland/mountain/peak) ---
if elevation > 0.85:
if temp < 0.1:
return "permanent_ice"
return "alpine_tundra"
if elevation > 0.70:
if moisture > 0.3 and canopy > 0.2:
return "alpine_meadow"
return "alpine_tundra"
if elevation > 0.55:
if moisture > 0.7 and temp > 0.25:
return "cloud_forest"
if canopy > 0.4:
return "montane_forest"
if moisture > 0.3:
return "alpine_meadow"
return "alpine_tundra" # highland above treeline, dry
# --- Temperature-driven (lowland/midland) ---
# Hot (tropical)
if temp > 0.55:
if moisture > 0.7 and canopy > 0.6:
return "tropical_rainforest"
if moisture > 0.4:
return "tropical_dry_forest"
if moisture > 0.15:
return "savanna"
return "desert"
# Temperate
if temp > 0.25:
if canopy > 0.5 and moisture > 0.5:
return "temperate_forest"
if moisture > 0.3:
return "temperate_grassland"
return "chaparral"
# Cool
if temp > 0.1:
if canopy > 0.3 and moisture > 0.35:
return "boreal_forest"
return "tundra"
# Extreme cold
return "polar_desert"
```
### Subterranean Detection
The subterranean biome is a special case. Caves are not derived from climate — they require explicit map generation markers.
**Detection criteria**: `tile.has_cave == true`
**Map generation sets `has_cave`** on tiles meeting:
- `elevation > 0.7` (mountain or peak substrate)
- Geology noise layer exceeds cave threshold (configurable, ~0.65)
- Not underwater
**Priority**: `has_cave` is checked FIRST in `classify()`, before water or land classification. A mountain tile with a cave entrance is classified as `subterranean`, not `alpine_tundra`.
**Cave clusters**: Map gen typically creates 2-5 contiguous cave tiles per mountain range. Cave tiles are connected to surface tiles at their edges — the boundary between surface and subterranean is where creatures transition.
**Future**: If map gen does not yet set `has_cave`, the subterranean biome will not appear in classification results. This is acceptable for M2b — document the requirement and verify in Block 6 proof. If absent, the proof documents what map gen changes are needed.
---
## Edge Cases
### Biome Transition Zones
Tiles at the boundary between two biome regions may oscillate between classifications as climate fluctuates. This is intentional — biome boundaries are not hard lines in nature.
**Hysteresis**: To prevent rapid flipping, a tile retains its current biome_id unless the new classification score exceeds the current one by a stability margin of 0.05 on the controlling variable (temperature or moisture). Implementation: `BiomeClassifier` stores `last_biome_id` per tile and only reclassifies when the determining variable crosses the threshold by > 0.05.
### Ambiguous Classifications
| Situation | Resolution |
|-----------|-----------|
| Wetland substrate + high elevation | Wetland override takes priority (checked first) — results in swamp/bog even at elevation 0.5. Wetland substrate overrides elevation. |
| Highland + very wet + tropical | `cloud_forest` (elevation > 0.55, moisture > 0.7, temp > 0.25) |
| Highland + dry + cold | `alpine_tundra` (elevation > 0.55, moisture < 0.3) |
| Lowland + extreme cold | `polar_desert` (temp < 0.05 regardless of moisture) |
| Temperate + low moisture + low canopy | `chaparral` (catch-all for temperate drylands) |
| Tropical + moderate moisture + high canopy | `tropical_dry_forest` (canopy alone doesn't override moisture requirement for rainforest) |
| Cold + high canopy + moderate moisture | `boreal_forest` (canopy > 0.3, moisture > 0.35, temp 0.1-0.25) |
| Cold + high canopy + low moisture | `tundra` (moisture < 0.35 blocks boreal_forest, canopy ignored) |
| Mountain tile + has_cave | `subterranean` (cave checked first, overrides alpine) |
### Volcanic Substrate
Volcanic tiles are a substrate type, not a biome. The classifier returns `"volcanic"` as a special case. Volcanic tiles have:
- Unique flora (hardy pioneer species, fire-adapted)
- Low quality ceiling (Q1-Q3)
- Can transition to other biomes if volcanic activity ceases (substrate reclassification — rare)
### No-Gap Guarantee
Every valid combination of `substrate x temperature x moisture x elevation x canopy` maps to exactly one biome. The `_classify_land` cascade is designed as an exhaustive if-else chain with no missing branches:
1. Wetland override catches saturated lowlands
2. Elevation cascade catches highland/mountain/peak
3. Temperature cascade catches tropical/temperate/cold/polar
4. Each temperature band has a moisture+canopy cascade that terminates with a default
The only "gap" would be a water tile with an unrecognized `water_body.type` — this should not happen as water body types are assigned at map gen from a fixed enum.
---
## Classifier Threshold Values
These are the numeric boundaries used in the classification algorithm. Collected here for tuning reference.
### Temperature Thresholds
| Threshold | Value | Separates |
|-----------|-------|-----------|
| Tropical / temperate | 0.55 | tropical biomes above, temperate below |
| Rainforest (hot) | 0.65 | tropical_rainforest requires >0.65, dry_forest needs only >0.55 |
| Temperate / cool | 0.25 | temperate biomes above, cold below |
| Cool / cold | 0.1 | boreal/tundra above, polar below |
| Extreme cold | 0.05 | polar_desert below |
| Permanent ice | 0.1 | permanent_ice at peak elevation when temp <0.1 |
| Cloud forest min | 0.25 | cloud_forest requires temp >0.25 (not too cold) |
| Swamp min | 0.4 | swamp requires temp >0.4 (warm enough for swamp ecology) |
| Coral reef min | 0.55 | coral needs tropical waters |
### Moisture Thresholds
| Threshold | Value | Separates |
|-----------|-------|-----------|
| Very wet | 0.7 | tropical_rainforest, cloud_forest, bog, wetland override |
| Wet | 0.5 | temperate_forest |
| Moderate-wet | 0.4 | tropical_dry_forest |
| Moderate | 0.35 | boreal_forest, temperate_grassland |
| Moderate-dry | 0.3 | alpine_meadow, temperate_grassland |
| Dry | 0.15 | savanna / desert boundary |
| Saturated (wetland) | 0.8 | swamp (must exceed 0.7 for wetland override + be on wetland substrate or >0.7) |
### Elevation Thresholds
| Threshold | Value | Separates |
|-----------|-------|-----------|
| Peak | 0.85 | permanent_ice / alpine_tundra |
| Mountain | 0.70 | alpine_meadow / alpine_tundra |
| Highland | 0.55 | montane_forest / cloud_forest / alpine |
| Wetland ceiling | 0.4 | wetland override only applies below 0.4 |
| Cave eligibility | 0.7 | has_cave requires elevation > 0.7 |
### Canopy Thresholds
| Threshold | Value | Separates |
|-----------|-------|-----------|
| Dense tropical canopy | 0.6 | tropical_rainforest (with moisture >0.7) |
| Forest canopy | 0.5 | temperate_forest |
| Montane canopy | 0.4 | montane_forest |
| Boreal canopy | 0.3 | boreal_forest |
| Alpine meadow canopy | 0.2 | alpine_meadow (mountain with some vegetation) |
### Aquatic Thresholds
| Threshold | Value | Separates |
|-----------|-------|-----------|
| Coral reef depth | depth_from_coast <= 2 | coral_reef (tropical shallow) |
| Shallow ocean depth | depth_from_coast <= 3 | shallow_ocean vs deep_ocean |
| Mangrove depth | depth_from_coast <= 1 | mangrove (must be adjacent to coast) |
| Pond size | water_body.size == 1 | pond vs lake |
| Lake size | water_body.size >= 2 | lake |
---
## Reclassification Triggers
Biomes are recomputed when underlying state changes significantly. Not every turn — only when a controlling variable crosses a threshold.
### Trigger Conditions
| Variable | Threshold Delta | Triggers |
|----------|----------------|---------|
| `temperature` | > 0.05 from last classification | Full reclassification |
| `moisture` | > 0.05 from last classification | Full reclassification |
| `canopy_cover` | > 0.1 from last classification | Full reclassification |
| `has_cave` changed | any | Immediate reclassification |
| `substrate_id` changed | any | Immediate reclassification |
### Emergent Succession
Biome reclassification IS ecological succession. No separate succession system needed:
- Grassland with growing canopy (>0.5) → naturally classifies as temperate_forest
- Forest with declining canopy (<0.3, moisture dropping) naturally classifies as chaparral or grassland
- Temperate forest with rising temperature → naturally classifies as tropical_dry_forest
- Wetland drying out (moisture <0.7) naturally classifies as temperate biome based on canopy
This is the core design principle: biomes are labels computed from state, not fixed assignments.
---
## Data File Schema
### biomes.json
Each biome definition in `data/world/biomes/biomes.json`:
```json
{
"id": "temperate_forest",
"name": "Temperate Forest",
"quality_range": [1, 5],
"temp_range": [0.25, 0.55],
"moisture_range": [0.5, 1.0],
"substrate_types": ["lowland", "midland"],
"flora_climax": {
"canopy": 0.85,
"undergrowth": 0.6,
"fungi": 0.35
},
"fauna_capacity": 1.0,
"food_web_tier": "full"
}
```
### classification.json
Rules for the classifier, ordered by priority:
```json
{
"rules": [
{
"id": "subterranean",
"priority": 0,
"condition": "has_cave == true"
},
{
"id": "pond",
"priority": 10,
"condition": "is_water and water_body.type == 'pond'"
},
{
"id": "estuary",
"priority": 15,
"condition": "is_ocean and has_adjacent_river_mouth"
}
]
}
```
Rules are evaluated in priority order (lower number = higher priority). First match wins.

View file

@ -0,0 +1,302 @@
# Food Web Balance
> Tuning methodology for population stability across all 25+ biomes. Documents the approach Block 3 will use for growth rate tuning, stability verification, and population curve analysis.
---
## Stability Target
**Damped equilibrium by turn 50, stable through turn 200.**
Populations should oscillate (predator-prey cycles are natural) but converge. No mass extinction, no runaway growth.
### Quantitative Criteria
| Metric | Threshold | Measured Over |
|--------|-----------|--------------|
| Population variance | < 20% of mean | Turns 100-200 |
| No biome empty | 0 biomes with zero creatures | Turn 200, all 5 seeds |
| Food web pyramid | producer biomass > herbivore > predator | Turns 100-200 average |
| Equilibrium onset | Population oscillation amplitude decreasing | By turn 50 |
| No population explosion | No species exceeds 2x carrying capacity | Any turn |
| Migration recolonization | Empty tile recolonized within 20 turns | Artificial extinction test |
| Quality-survival | Q5 creature on Q2 tile declines within 10 turns | Artificial placement test |
---
## Growth Rate Formula
Species growth rate is derived from traits, not individually authored. The formula determines how fast a population reproduces on a tile with available food.
### Base Growth Rate Derivation
```
growth_rate = BASE_RATE * reproduction_modifier * thermal_modifier * social_modifier
BASE_RATE = 0.15 # turns^-1, tunable constant
reproduction_modifier:
r_strategy → 2.0 (fast breeders)
k_strategy → 0.5 (slow breeders)
thermal_modifier:
warm_blooded → 1.0 (constant activity)
cold_blooded → biome_temp_match(tile.temp, species.preferred_range)
# 1.0 if temp in preferred range, decays linearly to 0.3 at range edges
social_modifier:
solitary → 1.0
pack → 0.9 (slightly slower — fewer offspring per individual)
herd → 1.1 (safety increases survival of young)
swarm → 1.5 (rapid reproduction is the swarm strategy)
colony → 1.2 (colonial organisms reproduce efficiently)
```
### Carrying Capacity Derivation
```
carrying_capacity = BASE_CAPACITY * size_modifier * biome_fauna_capacity * flora_density_factor
BASE_CAPACITY = 100 # individuals per tile at baseline
size_modifier:
tiny → 5.0 (500 tiny creatures per tile)
small → 3.0 (300 small creatures)
medium → 1.0 (100 medium creatures)
large → 0.4 (40 large creatures)
huge → 0.15 (15 huge creatures)
biome_fauna_capacity:
From biomes.json fauna_capacity field (0.1 for polar_desert, 1.0 for temperate_forest)
flora_density_factor:
For herbivores: canopy_cover * 0.5 + undergrowth * 0.5 (clamped to [0.2, 1.5])
For carnivores: 1.0 (independent of flora, depends on prey availability)
For detritivores: fungi_network * 1.5 (clamped to [0.3, 1.5])
```
### Death Rate
```
death_rate = BASE_DEATH * age_factor * starvation_factor
BASE_DEATH = 0.05 # turns^-1, natural mortality
age_factor:
1.0 if age < 80% of max_age
Linearly increases to 3.0 at max_age (old age mortality)
starvation_factor:
1.0 if food_ratio >= 0.5
Linearly increases to 5.0 as food_ratio → 0 (starvation cascade)
```
---
## Lotka-Volterra with Substeps
The population dynamics use a modified Lotka-Volterra model with Holling Type II functional response, computed in 4 substeps per turn to prevent discrete-timestep instability.
### Why Substeps
Without substeps, a single predation calculation can consume more prey than exists (negative populations) or cause predator population to spike unrealistically. Substeps make the discrete simulation approximate continuous dynamics.
**4 substeps** is the minimum that prevents instability across all tested biome configurations. Testing showed:
- 1 substep: frequent extinctions in high-diversity biomes (tropical_rainforest)
- 2 substeps: occasional extinctions in predator-rich biomes (deep_ocean)
- 4 substeps: stable across all biomes
- 8 substeps: marginal improvement not worth the compute cost
### Holling Type II Functional Response
```
consumed = predation_rate * predator_pop * prey_pop / (prey_pop + half_saturation)
```
The `half_saturation` constant determines predator efficiency:
- Low half_saturation (10): predators are very efficient, prey crashes quickly
- High half_saturation (100): predators saturate, prey survives in large numbers
**Tuning target**: `half_saturation = 0.5 * carrying_capacity` for the prey species. This produces realistic predator-prey oscillations that dampen over time.
### Stochastic Noise
Each substep includes +-5% hash-based noise:
```
noise = hash_noise(seed, tile, species, turn, substep) * 0.05
```
This prevents synchronized population crashes across tiles (where all populations hit minimum simultaneously). Deterministic from seed for reproducibility.
---
## Tuning Methodology
### Phase 1: Single-Biome Isolation Tests
Test each biome in isolation (single tile, closed system — no migration) for 200 turns:
1. Generate species for the biome on 10 seeds
2. Initialize populations at 50% carrying capacity
3. Run 200 turns with no external inputs
4. Record population curves every turn
5. Verify:
- No species goes to zero by turn 200
- Population variance < 30% of mean over turns 100-200 (relaxed from 20% for single-tile)
- Food web pyramid holds at turn 200
**If a biome fails**: Adjust biome-specific constants:
- Increase producer growth_rate if herbivores crash (bottom-up starvation)
- Decrease predation_rate if prey crashes (top-down overconsumption)
- Increase half_saturation if oscillations don't dampen
### Phase 2: Multi-Biome Map Tests
Run 5 seeds on 60x40 maps for 200 turns:
1. Use standard map generation (all biomes present through climate variation)
2. Allow migration between tiles
3. Record per-biome population aggregates every 10 turns
4. Verify:
- No biome has zero total creatures at turn 200
- Global food web pyramid holds
- Migration fills gaps (some local extinctions OK, but biome-level populations persist)
- Population variance < 20% over turns 100-200
**If a biome fails at map scale but passed in isolation**: Migration rates may be too low for that biome's species, or carrying capacity is too close to minimum viable population threshold.
### Phase 3: Stress Tests
Specific scenarios to verify robustness:
| Test | Setup | Expected Outcome |
|------|-------|-----------------|
| Artificial extinction | Remove all creatures from one tile | Recolonized from neighbors within 20 turns |
| Quality mismatch | Place Q5 creature on Q2 tile | Population declines, migrates within 10 turns |
| Deforestation shock | Set canopy to 0 on a forest tile | Herbivore crash → predator crash → slow recovery as flora regrows |
| Climate shift | Raise temperature 0.1 on a temperate tile | Gradual species turnover, no mass death event |
| Predator removal | Remove all predators from a biome region | Herbivore explosion → overgrazing → flora crash → herbivore crash (trophic cascade) |
---
## Population Curve Analysis
### What Healthy Curves Look Like
**Producers**: Oscillate around 70-90% of carrying capacity. Dips from herbivore pressure, recovery when herbivores decline. Should stabilize with < 15% amplitude oscillations by turn 100.
**Herbivores**: Classic predator-prey lag. Population peaks ~5-10 turns after producer peak. Dips when predators respond. Equilibrium around 40-60% of carrying capacity.
**Predators**: Most volatile. Population peaks ~5-10 turns after herbivore peak. Sharp declines when prey is consumed. Equilibrium around 20-30% of carrying capacity. Largest oscillation amplitude, but must still dampen.
### Warning Signs
| Pattern | Indicates | Fix |
|---------|----------|-----|
| Predator population > herbivore | Predation rate too low or predator growth too high | Increase predation_rate or decrease predator growth_rate |
| Producer crashes to near-zero | Herbivore grazing pressure too high | Decrease herbivore consumption_rate or increase producer growth_rate |
| Oscillations growing (divergent) | System is unstable | Increase half_saturation, increase substeps, or decrease growth rates |
| All populations flat (no oscillation) | Dynamics are over-dampened | Decrease half_saturation to make predators more responsive |
| One species dominates, others extinct | Competitive exclusion | Adjust niche differentiation (trait-based carrying capacity differences) |
| Population hits 0 then stays at 0 | Extinction is absorbing — migration didn't save it | Lower min_viable_population threshold or increase migration_range |
### Recording Format
Population data is recorded as JSON for analysis:
```json
{
"seed": 42,
"map_size": [60, 40],
"snapshots": [
{
"turn": 0,
"biomes": {
"temperate_forest": {
"tile_count": 145,
"total_creatures": 2340,
"by_trophic": {"producer": 1200, "herbivore": 800, "predator": 340},
"by_quality": {"Q1": 900, "Q2": 800, "Q3": 450, "Q4": 150, "Q5": 40},
"species_count": 12,
"births": 0,
"deaths": 0,
"migrations": 0,
"extinctions": 0
}
}
}
]
}
```
Snapshots taken every 10 turns (turns 0, 10, 20, ... 200) = 21 snapshots per seed, 5 seeds = 105 total snapshots.
---
## Food Web Pyramid Verification
The ecological pyramid must hold at equilibrium: producer biomass > herbivore biomass > predator biomass.
### Biomass Calculation
```
biomass(species) = population * SIZE_BIOMASS[species.size]
SIZE_BIOMASS:
tiny → 0.01
small → 0.1
medium → 1.0
large → 5.0
huge → 20.0
```
### Verification
For each biome at turns 100-200:
```
producer_biomass = sum(biomass for all producer species in biome)
herbivore_biomass = sum(biomass for all herbivore + omnivore species)
predator_biomass = sum(biomass for all carnivore species)
assert producer_biomass > herbivore_biomass
assert herbivore_biomass > predator_biomass
```
**Exception**: Aquatic biomes with filter feeders may have flatter pyramids (filter feeders are very efficient at converting producer biomass). The pyramid ratio (producer:herbivore) may be as low as 1.2:1 in coral_reef and shallow_ocean. Land biomes should maintain at least 2:1.
**Detritivores** are excluded from the pyramid calculation — they recycle dead matter and exist outside the standard trophic chain.
---
## Tuning Constants Summary
All tunable constants collected for reference. These are the knobs Block 3 will adjust:
| Constant | Default | Range | Effect |
|----------|---------|-------|--------|
| `BASE_RATE` | 0.15 | 0.05-0.30 | Global growth speed |
| `BASE_CAPACITY` | 100 | 50-200 | Global population ceiling |
| `BASE_DEATH` | 0.05 | 0.02-0.10 | Natural mortality rate |
| `SUBSTEPS` | 4 | 2-8 | Simulation resolution |
| `half_saturation` | 0.5 * capacity | 0.2-0.8 * capacity | Predator efficiency |
| `predation_rate` | 0.3 | 0.1-0.5 | How fast predators consume prey |
| `grazing_rate` | 0.1 | 0.05-0.2 | Herbivore pressure on flora |
| `min_viable_population` | 0.15 * capacity | 0.05-0.25 * capacity | Migration trigger threshold |
| `noise_amplitude` | 0.05 | 0.01-0.10 | Stochastic variation |
| `migration_range` | by locomotion | 1-5 tiles | How far species can migrate |
| `stability_margin` | 0.05 | 0.02-0.10 | Biome reclassification hysteresis |
### Per-Biome Overrides
Some biomes need non-default constants:
| Biome | Override | Reason |
|-------|---------|--------|
| `polar_desert` | BASE_CAPACITY * 0.1 | Extreme environment, very few creatures |
| `deep_ocean` | half_saturation * 1.5 | Large predators need more prey saturation |
| `tropical_rainforest` | BASE_CAPACITY * 1.3 | Peak terrestrial biodiversity |
| `coral_reef` | BASE_CAPACITY * 1.5, grazing_rate * 0.5 | High density, coral is resilient producer |
| `desert` | BASE_CAPACITY * 0.3, BASE_RATE * 0.7 | Low density, slow ecology |
| `subterranean` | BASE_CAPACITY * 0.4, migration_range - 1 | Limited space, restricted movement |
| `permanent_ice` | BASE_CAPACITY * 0.05 | Near-zero life support |
| `pond` | BASE_CAPACITY * 0.2 | Tiny ecosystem |

View file

@ -0,0 +1,548 @@
# Species Trait Catalog
> Complete trait system specification for trait-based species generation. Replaces M2a's partial SPECIES_TRAITS.md.
---
## 7 Trait Categories
Every species is defined by exactly 7 traits. The combination determines biology, behavior, food web position, quality tier, and visual identity.
### 1. Size
| Value | Carrying Capacity Modifier | Quality Base | Notes |
|-------|---------------------------|-------------|-------|
| `tiny` | 5.0x | 1 | Insects, plankton, worms |
| `small` | 3.0x | 2 | Rabbits, small fish, rodents |
| `medium` | 1.0x | 3 | Deer, wolves, standard trees |
| `large` | 0.4x | 4 | Bears, sharks, giant eagles |
| `huge` | 0.15x | 5 | Whales, megafauna, ancient leviathans |
### 2. Diet
| Value | Trophic Level | Quality Modifier | Notes |
|-------|--------------|-----------------|-------|
| `producer` | 0 | -1 | Plants, algae, phytoplankton. Not fauna — flora proxy in food web |
| `herbivore` | 1 | 0 | Grazes on producers, exerts grazing pressure |
| `omnivore` | 1.5 | 0 | Eats producers AND smaller fauna |
| `carnivore` | 2 | +1 | Eats fauna of strictly smaller size (pack bonus: +1 size tier) |
| `detritivore` | 0.5 | -1 | Recycles dead matter, needs no live prey |
| `filter_feeder` | 1 | 0 | Aquatic only. Eats tiny aquatic producers |
### 3. Habitat
| Value | Valid Substrates | Notes |
|-------|-----------------|-------|
| `terrestrial` | lowland, midland, highland, mountain, peak, wetland | Standard land species |
| `aquatic` | deep_water, shallow_water, lake_bed | Water-only species |
| `amphibious` | Any water OR adjacent-to-water land tile | Can exist on both. M2b addition: migrate across land-water boundary |
| `aerial` | Any land substrate | Flying species. Can migrate seasonally (M2b) |
| `subterranean` | mountain, peak (with cave marker) | Cave species. M2b addition |
| `arboreal` | lowland, midland, highland (requires canopy > 0.3) | Tree-dwelling. Loses habitat if deforested |
### 4. Locomotion
| Value | Movement Range | Migration Range | Notes |
|-------|---------------|----------------|-------|
| `sessile` | 0 | 0 | Rooted. Coral, anemone, barnacle |
| `walking` | 1 | 2 | Standard terrestrial movement |
| `swimming` | 1 | 3 | Aquatic movement |
| `flying` | 2 | 5 | Aerial. Highest migration range |
| `burrowing` | 1 | 1 | Underground movement. Required for subterranean habitat |
| `climbing` | 1 | 2 | Cave walls, cliff faces. M2b addition for subterranean |
| `slithering` | 1 | 2 | Snakes, worms. Low movement cost through undergrowth |
### 5. Reproduction
| Value | Growth Rate Modifier | Litter Size | Quality Modifier | Notes |
|-------|---------------------|-------------|-----------------|-------|
| `r_strategy` | 2.0x | 3-8 | -1 | Fast breeders, many offspring, high mortality |
| `k_strategy` | 0.5x | 1-2 | 0 | Slow breeders, few offspring, high parental investment |
### 6. Thermal
| Value | Climate Tolerance | Activity | Notes |
|-------|------------------|---------|-------|
| `cold_blooded` | Narrow temp range (biome-specific) | Reduced in cold | Reptiles, insects, fish |
| `warm_blooded` | Wide temp range | Constant | Mammals, birds. Higher food requirement |
### 7. Social
| Value | Group Size | Hunting Modifier | Notes |
|-------|-----------|-----------------|-------|
| `solitary` | 1 | 1.0x | Lone hunters/grazers |
| `pack` | 3-6 | 1.5x (can prey +1 size tier) | Coordinated hunters |
| `herd` | 10-30 | 0.8x | Safety in numbers, defensive bonus |
| `swarm` | 50-200 | 0.5x per individual, collective 5.0x | Insects, bats. Tiny/small only |
| `colony` | 20-100 | n/a (sessile or burrowing) | Ants, coral, cave insects |
---
## Subterranean Additions (M2b)
### New Locomotion Value: `climbing`
Cave-wall climbing for species that traverse vertical cave surfaces. Required alongside `burrowing` for full subterranean mobility.
### Visual Mode Sub-traits
These are flavor properties attached to subterranean species by FlavorGenerator, not gameplay traits. They affect sprite prompts and names only.
| Visual Mode | Description | Prompt Keywords |
|-------------|-------------|----------------|
| `blind` | No functional eyes. Relies on other senses | eyeless, smooth face, no eye sockets, vestigial eye bumps |
| `echolocation` | Bat-like sonar sensing | large ears, flattened nose, wide mouth, ultrasonic |
| `bioluminescent` | Self-illuminating organs | glowing spots, phosphorescent markings, light organs, eerie glow |
Species in the subterranean biome are assigned 1-2 visual modes probabilistically:
| Visual Mode | Weight in Subterranean | Can Combine With |
|-------------|----------------------|-----------------|
| `blind` | 0.50 | echolocation, bioluminescent |
| `echolocation` | 0.30 | blind, bioluminescent |
| `bioluminescent` | 0.40 | blind, echolocation |
### Subterranean Flavor Additions
**Prefixes** (added to `flavor.json` subterranean biome entry):
Pale, Crystal, Cave, Blind, Hollow, Deepstone, Gloom, Vein, Fungal, Phosphor
**Motifs**:
- translucent skin revealing internal structures
- crystalline growths on carapace or hide
- eyeless smooth face
- oversized ears or antennae
- pheromone sacs (colony species)
- bioluminescent markings along body
- pallid coloration (white, grey, translucent pink)
- elongated limbs adapted for cave traversal
---
## 9 Trait Constraints (Invalid Combinations)
| # | Constraint | Reason |
|---|-----------|--------|
| 1 | `aquatic` + `burrowing` | Can't burrow through water |
| 2 | `sessile` + `carnivore` | Rooted organisms can't hunt |
| 3 | `aerial` + `huge` | Too heavy to fly |
| 4 | `subterranean` + `aerial` | Can't fly underground |
| 5 | `filter_feeder` + `terrestrial` | Filter feeding requires water |
| 6 | `sessile` + `walking`/`flying`/`swimming` | Sessile means immobile |
| 7 | `arboreal` + `aquatic` | Can't be in trees and water simultaneously |
| 8 | `swarm` + `huge` | Ecological impossibility, breaks carrying capacity |
| 9 | `sessile` + non-`colony` social | Sessile organisms only form colonies |
Additional M2b constraints:
| # | Constraint | Reason |
|---|-----------|--------|
| 10 | `climbing` + `aquatic` | Climbing is for cave walls, not water |
| 11 | `climbing` + `aerial` | Flyers don't need to climb |
| 12 | `subterranean` + `arboreal` | No trees underground |
| 13 | `subterranean` + `herd` | Caves are too confined for herds |
---
## Per-Biome Trait Weight Summaries
Weights are relative probabilities (0.0-1.0) for SpeciesGenerator. Each biome generates species with trait distributions appropriate to its ecology.
### Aquatic Biomes
#### deep_ocean
| Trait | High Weight (>0.5) | Medium (0.2-0.5) | Low (<0.2) |
|-------|--------------------|-------------------|------------|
| size | huge (0.3), large (0.3) | medium (0.25) | small (0.1), tiny (0.05) |
| diet | carnivore (0.4) | filter_feeder (0.25), herbivore (0.15) | omnivore (0.1), detritivore (0.1) |
| habitat | aquatic (1.0) | | |
| locomotion | swimming (0.9) | | sessile (0.1) |
| reproduction | k_strategy (0.6) | r_strategy (0.4) | |
| thermal | cold_blooded (0.7) | warm_blooded (0.3) | |
| social | solitary (0.5) | pack (0.2), herd (0.2) | swarm (0.1) |
#### shallow_ocean
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.3), medium (0.3) | large (0.2) | tiny (0.15), huge (0.05) |
| diet | herbivore (0.3), carnivore (0.25) | omnivore (0.2), filter_feeder (0.15) | detritivore (0.1) |
| habitat | aquatic (1.0) | | |
| locomotion | swimming (0.85) | | sessile (0.15) |
| reproduction | r_strategy (0.55) | k_strategy (0.45) | |
| thermal | cold_blooded (0.6) | warm_blooded (0.4) | |
| social | herd (0.3), solitary (0.3) | pack (0.2) | swarm (0.1), colony (0.1) |
#### coral_reef
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | tiny (0.3), small (0.4) | medium (0.2) | large (0.08), huge (0.02) |
| diet | herbivore (0.3), omnivore (0.25) | carnivore (0.2), filter_feeder (0.15) | detritivore (0.1) |
| habitat | aquatic (1.0) | | |
| locomotion | swimming (0.7) | sessile (0.3) | |
| reproduction | r_strategy (0.7) | k_strategy (0.3) | |
| thermal | cold_blooded (0.9) | warm_blooded (0.1) | |
| social | colony (0.3), herd (0.25) | swarm (0.2), solitary (0.15) | pack (0.1) |
#### estuary
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.35), medium (0.3) | tiny (0.15), large (0.15) | huge (0.05) |
| diet | omnivore (0.3), herbivore (0.25) | carnivore (0.2), detritivore (0.15) | filter_feeder (0.1) |
| habitat | amphibious (0.4), aquatic (0.4) | | aerial (0.2) |
| locomotion | swimming (0.5) | walking (0.25), flying (0.15) | slithering (0.1) |
| reproduction | r_strategy (0.6) | k_strategy (0.4) | |
| thermal | cold_blooded (0.55) | warm_blooded (0.45) | |
| social | herd (0.3), solitary (0.25) | pack (0.2), colony (0.15) | swarm (0.1) |
#### pond
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | tiny (0.5), small (0.35) | | medium (0.15) |
| diet | herbivore (0.3), detritivore (0.25) | omnivore (0.25) | carnivore (0.15), filter_feeder (0.05) |
| habitat | aquatic (0.5), amphibious (0.3) | | aerial (0.2) |
| locomotion | swimming (0.5) | walking (0.2), flying (0.2) | slithering (0.1) |
| reproduction | r_strategy (0.8) | k_strategy (0.2) | |
| thermal | cold_blooded (0.7) | warm_blooded (0.3) | |
| social | swarm (0.3), colony (0.25) | solitary (0.25) | herd (0.1), pack (0.1) |
#### river
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.4), medium (0.3) | tiny (0.15) | large (0.12), huge (0.03) |
| diet | herbivore (0.25), omnivore (0.25) | carnivore (0.25) | detritivore (0.15), filter_feeder (0.1) |
| habitat | aquatic (0.5), amphibious (0.3) | | aerial (0.2) |
| locomotion | swimming (0.6) | walking (0.15), flying (0.15) | slithering (0.1) |
| reproduction | r_strategy (0.6) | k_strategy (0.4) | |
| thermal | cold_blooded (0.5) | warm_blooded (0.5) | |
| social | solitary (0.3), herd (0.25) | pack (0.2) | swarm (0.15), colony (0.1) |
#### lake
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.35), medium (0.3) | tiny (0.15), large (0.15) | huge (0.05) |
| diet | herbivore (0.25), omnivore (0.25) | carnivore (0.2), filter_feeder (0.15) | detritivore (0.15) |
| habitat | aquatic (0.6), amphibious (0.25) | | aerial (0.15) |
| locomotion | swimming (0.65) | walking (0.15), flying (0.1) | slithering (0.1) |
| reproduction | r_strategy (0.55) | k_strategy (0.45) | |
| thermal | cold_blooded (0.55) | warm_blooded (0.45) | |
| social | herd (0.3), solitary (0.25) | pack (0.2) | swarm (0.15), colony (0.1) |
#### mangrove
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.35), medium (0.3) | tiny (0.15), large (0.15) | huge (0.05) |
| diet | omnivore (0.3), carnivore (0.25) | herbivore (0.2), detritivore (0.15) | filter_feeder (0.1) |
| habitat | amphibious (0.5), aquatic (0.2) | arboreal (0.15) | aerial (0.15) |
| locomotion | swimming (0.3), walking (0.25) | climbing (0.2), flying (0.15) | slithering (0.1) |
| reproduction | r_strategy (0.6) | k_strategy (0.4) | |
| thermal | cold_blooded (0.65) | warm_blooded (0.35) | |
| social | solitary (0.3), colony (0.25) | pack (0.2) | swarm (0.15), herd (0.1) |
### Tropical Biomes
#### tropical_rainforest
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), small (0.25) | large (0.2), tiny (0.15) | huge (0.1) |
| diet | herbivore (0.25), omnivore (0.25) | carnivore (0.2), detritivore (0.15) | producer (0.1), filter_feeder (0.05) |
| habitat | arboreal (0.35), terrestrial (0.35) | | aerial (0.2), amphibious (0.1) |
| locomotion | climbing (0.3), walking (0.25) | flying (0.2) | slithering (0.15), burrowing (0.1) |
| reproduction | r_strategy (0.5) | k_strategy (0.5) | |
| thermal | warm_blooded (0.5) | cold_blooded (0.5) | |
| social | solitary (0.25), pack (0.2) | herd (0.2), swarm (0.2) | colony (0.15) |
#### tropical_dry_forest
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), small (0.3) | large (0.2) | tiny (0.1), huge (0.1) |
| diet | herbivore (0.3), omnivore (0.25) | carnivore (0.2) | detritivore (0.15), producer (0.1) |
| habitat | terrestrial (0.45), arboreal (0.25) | | aerial (0.2), amphibious (0.1) |
| locomotion | walking (0.35), climbing (0.2) | flying (0.2) | slithering (0.15), burrowing (0.1) |
| reproduction | r_strategy (0.55) | k_strategy (0.45) | |
| thermal | warm_blooded (0.45) | cold_blooded (0.55) | |
| social | herd (0.25), solitary (0.25) | pack (0.2) | swarm (0.15), colony (0.15) |
#### savanna
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | large (0.3), medium (0.3) | small (0.2) | huge (0.1), tiny (0.1) |
| diet | herbivore (0.35), carnivore (0.25) | omnivore (0.2) | detritivore (0.1), producer (0.1) |
| habitat | terrestrial (0.7) | | aerial (0.2), amphibious (0.1) |
| locomotion | walking (0.6) | flying (0.2) | burrowing (0.1), slithering (0.1) |
| reproduction | k_strategy (0.5) | r_strategy (0.5) | |
| thermal | warm_blooded (0.6) | cold_blooded (0.4) | |
| social | herd (0.35), pack (0.25) | solitary (0.2) | swarm (0.1), colony (0.1) |
#### desert
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.35), tiny (0.3) | medium (0.2) | large (0.1), huge (0.05) |
| diet | omnivore (0.3), carnivore (0.25) | herbivore (0.2), detritivore (0.15) | producer (0.1) |
| habitat | terrestrial (0.7) | subterranean (0.15) | aerial (0.15) |
| locomotion | walking (0.3), burrowing (0.25) | slithering (0.25) | flying (0.15), climbing (0.05) |
| reproduction | r_strategy (0.65) | k_strategy (0.35) | |
| thermal | cold_blooded (0.7) | warm_blooded (0.3) | |
| social | solitary (0.45), colony (0.2) | pack (0.15) | swarm (0.15), herd (0.05) |
### Temperate Biomes
#### temperate_forest
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), small (0.25) | large (0.2) | tiny (0.1), huge (0.15) |
| diet | herbivore (0.3), omnivore (0.25) | carnivore (0.2) | detritivore (0.15), producer (0.1) |
| habitat | terrestrial (0.5), arboreal (0.2) | | aerial (0.2), amphibious (0.1) |
| locomotion | walking (0.4) | climbing (0.2), flying (0.2) | burrowing (0.1), slithering (0.1) |
| reproduction | k_strategy (0.5) | r_strategy (0.5) | |
| thermal | warm_blooded (0.65) | cold_blooded (0.35) | |
| social | solitary (0.25), pack (0.25) | herd (0.2) | colony (0.15), swarm (0.15) |
#### temperate_grassland
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), small (0.25) | large (0.2) | tiny (0.1), huge (0.15) |
| diet | herbivore (0.35), carnivore (0.25) | omnivore (0.2) | detritivore (0.1), producer (0.1) |
| habitat | terrestrial (0.7) | | aerial (0.2), amphibious (0.1) |
| locomotion | walking (0.5) | flying (0.2), burrowing (0.15) | slithering (0.1), climbing (0.05) |
| reproduction | r_strategy (0.5) | k_strategy (0.5) | |
| thermal | warm_blooded (0.6) | cold_blooded (0.4) | |
| social | herd (0.35), pack (0.25) | solitary (0.2) | swarm (0.1), colony (0.1) |
#### chaparral
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.35), medium (0.3) | tiny (0.15) | large (0.15), huge (0.05) |
| diet | omnivore (0.3), herbivore (0.25) | carnivore (0.2) | detritivore (0.15), producer (0.1) |
| habitat | terrestrial (0.7) | | aerial (0.15), subterranean (0.15) |
| locomotion | walking (0.35), burrowing (0.2) | slithering (0.2) | flying (0.15), climbing (0.1) |
| reproduction | r_strategy (0.6) | k_strategy (0.4) | |
| thermal | cold_blooded (0.55) | warm_blooded (0.45) | |
| social | solitary (0.35), pack (0.2) | colony (0.2) | herd (0.15), swarm (0.1) |
#### swamp
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), small (0.25) | large (0.2), tiny (0.15) | huge (0.1) |
| diet | omnivore (0.25), carnivore (0.25) | herbivore (0.2), detritivore (0.2) | filter_feeder (0.1) |
| habitat | amphibious (0.4), terrestrial (0.3) | | aquatic (0.15), aerial (0.15) |
| locomotion | swimming (0.3), walking (0.25) | slithering (0.2) | flying (0.15), burrowing (0.1) |
| reproduction | r_strategy (0.6) | k_strategy (0.4) | |
| thermal | cold_blooded (0.6) | warm_blooded (0.4) | |
| social | solitary (0.3), colony (0.2) | swarm (0.2), pack (0.15) | herd (0.15) |
#### bog
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | tiny (0.35), small (0.35) | medium (0.2) | large (0.08), huge (0.02) |
| diet | detritivore (0.3), herbivore (0.25) | omnivore (0.2) | carnivore (0.15), filter_feeder (0.1) |
| habitat | amphibious (0.35), terrestrial (0.35) | | aerial (0.2), aquatic (0.1) |
| locomotion | walking (0.25), swimming (0.2) | flying (0.2), burrowing (0.15) | slithering (0.15), climbing (0.05) |
| reproduction | r_strategy (0.7) | k_strategy (0.3) | |
| thermal | cold_blooded (0.6) | warm_blooded (0.4) | |
| social | swarm (0.3), colony (0.25) | solitary (0.2) | herd (0.15), pack (0.1) |
### Cold Biomes
#### boreal_forest
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), large (0.25) | small (0.2) | huge (0.15), tiny (0.1) |
| diet | herbivore (0.3), carnivore (0.25) | omnivore (0.25) | detritivore (0.1), producer (0.1) |
| habitat | terrestrial (0.6) | arboreal (0.15) | aerial (0.15), amphibious (0.1) |
| locomotion | walking (0.5) | climbing (0.15), flying (0.15) | burrowing (0.1), slithering (0.1) |
| reproduction | k_strategy (0.55) | r_strategy (0.45) | |
| thermal | warm_blooded (0.75) | cold_blooded (0.25) | |
| social | pack (0.3), solitary (0.25) | herd (0.2) | colony (0.15), swarm (0.1) |
#### tundra
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | large (0.3), medium (0.3) | small (0.2) | huge (0.1), tiny (0.1) |
| diet | herbivore (0.35), carnivore (0.25) | omnivore (0.2) | detritivore (0.15), producer (0.05) |
| habitat | terrestrial (0.8) | | aerial (0.15), amphibious (0.05) |
| locomotion | walking (0.6) | flying (0.2) | burrowing (0.1), slithering (0.05), climbing (0.05) |
| reproduction | k_strategy (0.6) | r_strategy (0.4) | |
| thermal | warm_blooded (0.85) | cold_blooded (0.15) | |
| social | herd (0.4), pack (0.25) | solitary (0.2) | colony (0.1), swarm (0.05) |
#### polar_desert
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), small (0.3) | large (0.2) | tiny (0.15), huge (0.05) |
| diet | carnivore (0.3), herbivore (0.25) | omnivore (0.2) | detritivore (0.15), filter_feeder (0.1) |
| habitat | terrestrial (0.5), aquatic (0.3) | | amphibious (0.2) |
| locomotion | walking (0.35), swimming (0.3) | | flying (0.15), burrowing (0.1), slithering (0.1) |
| reproduction | k_strategy (0.65) | r_strategy (0.35) | |
| thermal | warm_blooded (0.9) | cold_blooded (0.1) | |
| social | herd (0.3), solitary (0.3) | pack (0.2) | colony (0.15), swarm (0.05) |
### Elevation Biomes
#### montane_forest
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), large (0.25) | small (0.2) | huge (0.15), tiny (0.1) |
| diet | herbivore (0.3), omnivore (0.25) | carnivore (0.2) | detritivore (0.15), producer (0.1) |
| habitat | terrestrial (0.5), arboreal (0.2) | | aerial (0.2), amphibious (0.1) |
| locomotion | walking (0.35), climbing (0.25) | flying (0.2) | burrowing (0.1), slithering (0.1) |
| reproduction | k_strategy (0.55) | r_strategy (0.45) | |
| thermal | warm_blooded (0.7) | cold_blooded (0.3) | |
| social | solitary (0.3), pack (0.25) | herd (0.2) | colony (0.15), swarm (0.1) |
#### cloud_forest
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.3), medium (0.3) | tiny (0.2) | large (0.15), huge (0.05) |
| diet | herbivore (0.25), omnivore (0.25) | detritivore (0.2) | carnivore (0.15), producer (0.15) |
| habitat | arboreal (0.4), terrestrial (0.3) | | aerial (0.2), amphibious (0.1) |
| locomotion | climbing (0.35), flying (0.2) | walking (0.2) | slithering (0.15), burrowing (0.1) |
| reproduction | r_strategy (0.5) | k_strategy (0.5) | |
| thermal | warm_blooded (0.5) | cold_blooded (0.5) | |
| social | solitary (0.3), colony (0.2) | swarm (0.2) | pack (0.15), herd (0.15) |
#### alpine_meadow
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), small (0.25) | large (0.2) | tiny (0.15), huge (0.1) |
| diet | herbivore (0.4), omnivore (0.2) | carnivore (0.2) | detritivore (0.1), producer (0.1) |
| habitat | terrestrial (0.7) | | aerial (0.25), amphibious (0.05) |
| locomotion | walking (0.45), climbing (0.2) | flying (0.2) | burrowing (0.1), slithering (0.05) |
| reproduction | k_strategy (0.55) | r_strategy (0.45) | |
| thermal | warm_blooded (0.75) | cold_blooded (0.25) | |
| social | herd (0.3), solitary (0.25) | pack (0.25) | colony (0.1), swarm (0.1) |
#### alpine_tundra
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | medium (0.3), small (0.25) | large (0.2) | tiny (0.15), huge (0.1) |
| diet | herbivore (0.35), carnivore (0.25) | omnivore (0.2) | detritivore (0.15), producer (0.05) |
| habitat | terrestrial (0.8) | | aerial (0.15), subterranean (0.05) |
| locomotion | walking (0.4), climbing (0.25) | flying (0.15) | burrowing (0.15), slithering (0.05) |
| reproduction | k_strategy (0.6) | r_strategy (0.4) | |
| thermal | warm_blooded (0.8) | cold_blooded (0.2) | |
| social | herd (0.3), pack (0.25) | solitary (0.25) | colony (0.15), swarm (0.05) |
#### permanent_ice
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.3), medium (0.3) | tiny (0.2) | large (0.15), huge (0.05) |
| diet | carnivore (0.3), herbivore (0.25) | omnivore (0.2) | detritivore (0.15), producer (0.1) |
| habitat | terrestrial (0.5), aquatic (0.3) | | amphibious (0.2) |
| locomotion | walking (0.3), swimming (0.3) | | flying (0.15), climbing (0.15), burrowing (0.1) |
| reproduction | k_strategy (0.7) | r_strategy (0.3) | |
| thermal | warm_blooded (0.9) | cold_blooded (0.1) | |
| social | herd (0.3), solitary (0.3) | pack (0.2) | colony (0.15), swarm (0.05) |
### Subterranean Biome
#### subterranean
| Trait | High Weight | Medium | Low |
|-------|-----------|---------|----|
| size | small (0.35), tiny (0.3) | medium (0.2) | large (0.1), huge (0.05) |
| diet | omnivore (0.25), detritivore (0.25) | carnivore (0.2), herbivore (0.15) | producer (0.1), filter_feeder (0.05) |
| habitat | subterranean (0.8) | | amphibious (0.1), terrestrial (0.1) |
| locomotion | burrowing (0.35), climbing (0.3) | walking (0.15) | slithering (0.15), swimming (0.05) |
| reproduction | r_strategy (0.65) | k_strategy (0.35) | |
| thermal | cold_blooded (0.75) | warm_blooded (0.25) | |
| social | colony (0.35), swarm (0.2) | solitary (0.2) | pack (0.15), herd (0.1) |
Typical generated species:
- small + burrowing + cold_blooded + colony + omnivore = "cave insect-like"
- medium + climbing + cold_blooded + solitary + carnivore = "giant spider-like"
- small + flying + warm_blooded + swarm + carnivore = "bat-like"
- tiny + burrowing + cold_blooded + colony + detritivore = "cave worm-like"
- medium + swimming + cold_blooded + solitary + carnivore = "blind cave fish-like" (in flooded caves)
---
## Quality Tier Derivation
### Formula
```
species_quality = clamp(base + modifiers, 1, 5)
base = SIZE_QUALITY[size]
tiny → 1
small → 2
medium → 3
large → 4
huge → 5
modifiers:
r_strategy → -1
k_strategy → 0
detritivore → -1
carnivore → +1
```
### Quality Range (species lifetime)
Species don't stay at one quality. They have a quality range based on the derived base:
| Derived Quality | Quality Range | Example |
|----------------|-------------|---------|
| Q1 | Q1-Q2 | Worms, algae, tiny insects |
| Q2 | Q1-Q3 | Common fish, rabbits, cave insects |
| Q3 | Q2-Q4 | Deer, wolves (young), standard predators |
| Q4 | Q3-Q5 | Bears, sharks, dire wolves |
| Q5 | Q4-Q5 | Ancient leviathans, megafauna |
An individual creature spawns at `quality_range[0]` and ages up toward `quality_range[1]`, capped by `min(species.max_quality, tile.quality)`.
---
## Spawn Probability Table
Tile quality gates which species quality tiers can spawn. Higher-quality tiles support rarer species.
| Tile Quality | Q1 species | Q2 species | Q3 species | Q4 species | Q5 species |
|-------------|-----------|-----------|-----------|-----------|-----------|
| Q1 tile | 50% | 30% | 10% | 0% | 0% |
| Q2 tile | 30% | 40% | 25% | 5% | 0% |
| Q3 tile | 10% | 25% | 40% | 20% | 5% |
| Q4 tile | 5% | 15% | 30% | 35% | 15% |
| Q5 tile | 0% | 10% | 25% | 35% | 30% |
Species can only spawn on tiles where `tile.quality >= species.min_quality`. The table above gives the probability of each quality tier being selected when the tile generates a new species.
---
## Minimum Species Per Biome
After generation across 10 seeds, each biome must produce:
| Trophic Level | Minimum Count | Rationale |
|--------------|---------------|-----------|
| Producer | 3 | Base of food web, must be diverse enough to support herbivores |
| Herbivore | 3 | Multiple prey species prevent single-point food web collapse |
| Predator | 2 | At least one solitary + one pack predator for ecological balance |
| Detritivore | 1 | Recycler role, prevents dead-matter buildup |
If any biome fails these minimums across the seed set, its trait weights need adjustment (increase weight for the underrepresented trophic level).