diff --git a/.project/tasks/climate-balance/README.md b/.project/tasks/climate-balance/README.md new file mode 100644 index 00000000..5bf0f9f9 --- /dev/null +++ b/.project/tasks/climate-balance/README.md @@ -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