chore(climate-balance): 🔧 Implement climate-balance validation tasks in CI/CD workflows

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-25 23:53:20 -07:00
parent bb55e78c68
commit a99196ae47

View file

@ -0,0 +1,136 @@
# Plan: Balance Baseline Climate Simulation
## Context
The baseline scenario (`base_no_magic`) is a **pure physics regression test** — no ley lines, no corruption, no magic. It should reach equilibrium, but instead after 2000 turns: temp climbs to 0.65 (+0.22), moisture crashes to 0.19 (-0.38), and ocean expands 15.7%. The scenario description itself says "persistent drift indicates a physics bug."
Three root causes identified through mathematical analysis of the equilibrium equations.
## Root Cause Analysis
### 1. Temperature: Net Solar Creates Permanent Heat Bias
The per-turn temperature equation:
```
new_T = T + solar*(1-albedo)*energy_scale + (solar - T)*relaxation
```
At equilibrium (dT=0):
```
T_eq = solar * (1 + (1-albedo) * energy_scale / relaxation)
T_eq = solar * (1 + (1-albedo) * 0.2) # with defaults
```
For grassland (albedo 0.35): **T_eq = solar × 1.13** — temperatures overshoot solar baseline by 13%. Equatorial tiles get pushed to the 1.0 clamp. Global average trends toward ~0.6-0.65 instead of ~0.5.
**The issue**: `net_solar` is a one-directional heat injection with no corresponding radiative loss. Relaxation pulls toward `solar`, but net_solar pushes above it.
### 2. Moisture: Decay Vastly Outpaces Relaxation
The per-turn moisture (ignoring transport):
```
new_M = M*0.98 + (baseline - M*0.98)*0.02 - M*0.98*0.001*T + evapotrans
```
At equilibrium (for equatorial coastal, baseline=0.5, T=0.5, evapotrans=0):
```
M_eq = 0.02*baseline / (0.02 + 0.0196 + 0.00098T) ≈ 0.25
```
**Equilibrium moisture is ~0.25** — half the baseline! The 2% decay is a flat multiplicative tax each turn, but relaxation only adds 2% of the *deficit*. At M=baseline, decay still removes 2% while relaxation adds 0%. These are fundamentally asymmetric.
### 3. Albedo Values Inverted for Desert
| Terrain | Game Albedo | Real-World Albedo |
|---------|------------|-------------------|
| Desert | **0.30** | 0.35-0.40 |
| Forest | 0.35 | 0.12-0.20 |
| Grassland | 0.35 | 0.20-0.25 |
Desert has LOWER albedo than forest/grassland, meaning deserts absorb MORE heat. This creates a warming feedback: land dries → desert → absorbs more heat → warms more → dries more. Real deserts are highly reflective (sand).
### 4. Most Terrains Have Zero Evapotranspiration
Only forests and swamp contribute moisture via ET. Grassland, plains, hills, tundra all have `evapotranspiration: 0.0`. Real grasslands transpire significantly. This means any non-forest tile is a moisture sink.
## Changes
### A. Fix Albedo Values (terrain JSON files)
**File**: `games/age-of-four/data/terrain/` (multiple JSON files)
| Terrain | Current | New | Rationale |
|---------|---------|-----|-----------|
| desert | 0.30 | 0.45 | Sand is highly reflective |
| plains | 0.38 | 0.30 | Dry grass/scrub, moderate reflection |
| grassland | 0.35 | 0.22 | Green vegetation absorbs well |
| forest | 0.35 | 0.15 | Dark canopy, low albedo |
| jungle | 0.30 | 0.12 | Dense canopy, very absorptive |
| boreal_forest | 0.35 | 0.20 | Mix of canopy and snow |
| swamp | 0.30 | 0.18 | Dark water + vegetation |
| tundra | 0.50 | 0.35 | Sparse vegetation on rock/soil |
| hills | 0.40 | 0.28 | Mixed terrain |
| volcano | 0.20 | 0.15 | Dark basalt |
| snow | 0.70 | 0.80 | Fresh snow is very reflective |
| ice | 0.80 | 0.85 | Keep high |
| ocean | 0.40 | 0.06 | Open water absorbs almost all light |
| coast | 0.35 | 0.08 | Shallow water, slightly more reflective |
| lake | 0.30 | 0.08 | Open water |
These align with real-world values from NASA Earth Energy Budget data. The key gameplay effect: deserts now REFLECT heat (negative feedback), forests ABSORB heat (positive feedback when cleared).
### B. Fix Evapotranspiration Values (terrain JSON files)
| Terrain | Current | New | Rationale |
|---------|---------|-----|-----------|
| grassland | 0.0 | 0.005 | Grass transpires |
| plains | 0.0 | 0.003 | Sparse vegetation |
| hills | 0.0 | 0.004 | Mixed vegetation |
| tundra | 0.0 | 0.001 | Minimal but present |
| forest | 0.01 | 0.012 | Slight increase |
| jungle | 0.02 | 0.025 | Slight increase |
| boreal_forest | 0.005 | 0.006 | Slight increase |
| swamp | 0.005 | 0.008 | Wetlands transpire heavily |
| desert | -0.01 | -0.005 | Less aggressive drying |
### C. Adjust Climate Parameters (`climate_params.json`)
| Parameter | Current | New | Rationale |
|-----------|---------|-----|-----------|
| `energy_scale` | 0.01 | 0.005 | Halve solar heat injection — with corrected albedos, water tiles (albedo 0.06) would absorb too aggressively at 0.01 |
| `equilibrium_relaxation` | 0.05 | 0.08 | Stronger pull toward equilibrium — counteracts net_solar bias faster |
| `moisture_decay` | 0.98 | 0.995 | Halve the moisture drain (0.5%/turn instead of 2%) |
| `moisture_relaxation` | 0.02 | 0.04 | Double the moisture recovery rate |
| `atmospheric_loss_rate` | 0.001 | 0.0003 | Reduce Jeans escape — was too aggressive for a habitable planet |
| `ocean_evaporation_hops` | 3 | 4 | One more hop inland for ocean moisture delivery |
| `subtropical_drying.rate_per_turn` | 0.013 | 0.008 | Less aggressive subtropical drying — was creating extreme deserts |
| `polar_drying.rate_per_turn` | 0.008 | 0.005 | Slightly less polar drying |
### D. No GDScript Logic Changes Needed
All adjustments are to data values in JSON. The physics equations themselves are sound; the parameters feeding them were wrong. The GDScript reads params from `climate_params.json` and terrain data at runtime.
### E. Regenerate TypeScript (if needed)
The TypeScript reads terrain data and climate params at runtime via `terrainCache` and `params`. Since we're only changing JSON data (not GDScript code), the transpiler should NOT need to run — verify by checking that the guide loads terrain JSON dynamically.
## Expected Outcomes
After parameter changes, the baseline scenario should:
- **Temperature**: Stabilize around 0.45-0.55 (global average) with latitude gradient intact
- **Moisture**: Stabilize around 0.35-0.45 (global average) with equatorial/coastal higher
- **Terrain**: Healthy mix — forests persist in wet zones, deserts form in rain shadows and subtropical bands, not globally
- **Ocean**: Stable (no expansion beyond initial generation)
## Verification
1. Run the baseline scenario in the web guide for 2000 turns
2. Check that temp/moisture trends flatten (no persistent drift)
3. Verify terrain distribution shows diverse biomes (not just desert/grassland)
4. Run the volcanic_winter scenario to ensure cooling events still work with new parameters
5. Spot-check that equatorial tiles are warm+wet, polar tiles are cold+dry, subtropical bands have deserts
## Files to Modify
1. `games/age-of-four/data/terrain/*.json` — albedo + evapotranspiration per terrain type
2. `games/age-of-four/data/climate_params.json` — 8 parameter adjustments