aissia/docs/02-systems/CLIMATE_SIMULATION_SYSTEM.md
StillHammer ba42b6d9c7 Update CDC with hybrid architecture (WarFactory + multi-target)
- Add hybrid deployment modes: local_dev (MVP) and production_pwa (optional)
- Integrate WarFactory engine reuse with hot-reload 0.4ms
- Define multi-target compilation strategy (DLL/SO/WASM)
- Detail both deployment modes with cost analysis
- Add progressive roadmap: Phase 1 (local), Phase 2 (POC WASM), Phase 3 (cloud)
- Budget clarified: $10-20/mois (local) vs $13-25/mois (cloud)
- Document open questions for technical validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 11:49:09 +08:00

16 KiB
Raw Blame History

Climate Simulation System

Status: Designed - Ready for Implementation Scope: Realistic climate patterns through mobile wind regions and convergence zones Integration: Uses existing TectonicRegions framework

System Overview

Revolutionary climate simulation using mobile wind regions that spawn, evolve, and interact to create emergent weather patterns. Solves the "Sahara vs Congo" problem through Inter-Tropical Convergence Zones (ITCZ) and planetary rotation bands without complex 3D atmospheric physics.

Key Innovations

  • Mobile WindRegions with token-based distribution system
  • ITCZ gravitational zones based on continental mass
  • Planetary rotation bands for realistic circulation patterns
  • Emergent storm evolution from simple wind interactions
  • Destruction token system for persistent terrain effects

Core Concepts

WindRegion Mobile Entities

"wind_region": {
  "position": [x, y],
  "wind_strength": 1.0,        // Base intensity (decays over time)
  "wetness": 0.0,              // Moisture content (gained over ocean)
  "velocity": [vx, vy],        // Movement vector
  "wind_tokens": 100,          // Distributed to tiles
  "decay_per_move": 0.02,      // -2% strength per movement
  "decay_per_tile": 0.01       // -1% strength per tile crossed
}

ITCZ Convergence Zones

"itcz_zone": {
  "center": [x, y],
  "gravitational_range": "sqrt(landmass_area) * 50",
  "aspiration_strength": "landmass_mass / distance^2",
  "amplification_factor": 3.0, // Wind strength multiplier at center
  "latitude_requirement": [0.45, 0.55]  // Equatorial band only
}

Simulation Architecture

Phase 1: Landmass Analysis and ITCZ Generation

Uses Existing TectonicRegions:

// Analyze continental masses from existing tectonic data
std::vector<Continent> continents = groupTectonicRegions();

// Generate water masses by inverse analysis
std::vector<WaterMass> oceans = detectOceanBasins(continents);

// Place ITCZ zones on qualifying equatorial landmasses
for (auto& continent : continents) {
    if (continent.latitude >= 0.45 && continent.latitude <= 0.55 &&
        continent.area > MIN_LANDMASS_SIZE) {
        createITCZ(continent.center, sqrt(continent.area));
    }
}

ITCZ Requirements:

  • Latitude Band: 45-55% of map height (equatorial)
  • Minimum Landmass: 10,000+ tiles
  • Ocean Proximity: Within 800km for moisture source
  • Continental Heating: Large thermal mass for convection

Phase 2: WindRegion Spawning System

Procedural Spawn Rules:

"wind_spawn_system": {
  "spawn_locations": "ocean_masses_only",
  "spawn_frequency": "water_mass_size / 1000",
  "initial_strength": "water_temperature * evaporation_factor",
  "region_size": "sqrt(water_mass_area) / 10",
  "tokens_per_region": "base_tokens * size_factor",
  "spawn_distribution": "random_within_water_region_biased_toward_center"
}

Note: WindRegions spawn aléatoirement dans le rayon de la waterRegion avec une distribution de spawn plutôt vers le centre pour éviter les spawns en bordure systématiques.

Spawn Distribution:

  • Large Oceans (Pacific): Big regions, high frequency
  • Medium Seas (Mediterranean): Medium regions, moderate frequency
  • Small Bays: Small regions, low frequency
  • No Land Spawning: All weather originates from water bodies

Phase 3: Movement and Planetary Circulation

Planetary Rotation Bands (based on real 10hPa atmospheric data):

"planetary_circulation": {
  "polar_jet_north": {
    "latitude_range": [0.10, 0.25],
    "direction": "west_to_east",
    "strength": 1.8
  },
  "calm_transition_1": {
    "latitude_range": [0.25, 0.40],
    "movement": "chaos_plus_procedural"
  },
  "equatorial_trades": {
    "latitude_range": [0.40, 0.60],
    "direction": "east_to_west",
    "strength": 1.5
  },
  "calm_transition_2": {
    "latitude_range": [0.60, 0.75],
    "movement": "chaos_plus_procedural"
  },
  "polar_jet_south": {
    "latitude_range": [0.75, 0.95],
    "direction": "west_to_east",
    "strength": 1.8
  }
}

Movement Calculation:

Vector2 movement =
  planetary_rotation_band * 0.6 +     // 60% planetary circulation
  equator_to_pole_bias * 0.2 +        // 20% thermal circulation
  terrain_deflection * 0.1 +          // 10% topographic influence
  random_variation * 0.1;             // 10% chaos

Phase 4: WindRegion Evolution and Interactions

Dynamic Evolution:

void updateWindRegion(WindRegion& region) {
    // Gain moisture over water
    if (currentTile.isOcean()) {
        region.wetness += OCEAN_MOISTURE_GAIN;
    }

    // Repulsion from other regions = acceleration
    // NOTE: Not physical repulsion - proxy for spatial competition and turbulence
    // Prevents region stacking while creating realistic dispersion patterns
    // CRITIQUE POINT: May cause "force field" effect around ITCZ zones where regions
    // oscillate/scatter instead of converging due to attraction vs repulsion conflict.
    // Alternative approaches: density-based drift, no interaction, or collision division.
    // TODO: Implement as configurable algorithm options for empirical testing.
    float repulsion = calculateRepulsionForce(region, nearbyRegions);
    region.wind_strength += repulsion * ACCELERATION_FACTOR;

    // Movement decay
    region.wind_strength *= (1.0 - DECAY_PER_MOVE);

    // Tile crossing cost
    region.wind_strength *= (1.0 - DECAY_PER_TILE);

    // Die when too weak
    if (region.wind_strength < MINIMUM_THRESHOLD) {
        destroyRegion(region);
    }
}

ITCZ Gravitational Effects:

void applyITCZGravity(WindRegion& region) {
    for (auto& itcz : active_itcz_zones) {
        float distance = calculateDistance(region.position, itcz.center);

        if (distance < itcz.gravitational_range) {
            // Attraction force (inverse square law)
            // NOTE: "Gravitational" metaphor for influence strength, not literal physics
            // Like saying someone has "gravitas" - clear semantic meaning for developers
            float attraction = itcz.mass / (distance * distance);
            Vector2 pull_direction = normalize(itcz.center - region.position);

            // Apply attraction
            region.velocity += pull_direction * attraction;

            // Amplification effect as region approaches
            float proximity = (itcz.range - distance) / itcz.range;
            float amplification = 1.0 + (itcz.max_amplification * proximity);

            region.wind_strength *= amplification;
            region.wetness *= amplification;
        }
    }
}

Phase 5: Storm Classification and Token Distribution

Climate Zone Classification:

// Simple thresholds for climate zone determination
const float HIGH_WIND_THRESHOLD = 2.0;
const float FLOOD_THRESHOLD = 1.5;
const float HURRICANE_WIND = 2.5;
const float HURRICANE_RAIN = 2.0;

bool isHighWindZone(const WindRegion& region) {
    return region.wind_strength >= HIGH_WIND_THRESHOLD;
}

bool isFloodZone(const WindRegion& region) {
    return region.wetness >= FLOOD_THRESHOLD;
}

bool isHurricaneZone(const WindRegion& region) {
    return region.wind_strength >= HURRICANE_WIND && region.wetness >= HURRICANE_RAIN;
}

Token Distribution System:

void distributeTokens(WindRegion& region) {
    // Basic climate tokens for all regions
    int wind_tokens = static_cast<int>(region.wind_strength * 10);
    int rain_tokens = static_cast<int>(region.wetness * 10);

    WorldTile& tile = world_map.getTile(region.position);
    tile.addTokens("wind", wind_tokens);
    tile.addTokens("rain", rain_tokens);

    // Special climate zone tokens for extreme weather
    if (isHighWindZone(region)) {
        tile.addTokens("highWind", 1);  // Hostile to forests
    }
    if (isFloodZone(region)) {
        tile.addTokens("flood", 1);     // Forces wetlands/marshes
    }
    if (isHurricaneZone(region)) {
        tile.addTokens("hurricane", 1); // Specialized hurricane biome
    }

    // Consume distributed tokens from region
    region.wind_tokens -= wind_tokens;
    region.rain_tokens -= rain_tokens;
}

Geographic Climate Patterns

Realistic Climate Formation

Congo Basin (Rainforest):

1. Large African landmass → Strong ITCZ at equator
2. Atlantic wind regions spawn → Move east via trade winds
3. ITCZ aspiration → Convergence at Congo → Amplification ×3
4. Super-humid storms → Massive rain token distribution
5. Result: Dense rainforest biome

Sahara Desert:

1. Sahara latitude (25-35°N) → Outside ITCZ band
2. No convergence zone → Wind regions pass through
3. Continental distance → Low initial moisture
4. Subtropical high pressure → Air descends (simulated via movement patterns)
5. Result: Minimal rain tokens → Desert biome

Egypt/Algeria Coastal:

1. Mediterranean wind regions → Moderate moisture
2. Coastal proximity → Some rain tokens
3. Sahara interior → Moisture depleted inland
4. Result: Mediterranean coastal climate → Desert interior gradient

Emergent Seasonal Patterns

ITCZ Strength Variation:

"seasonal_modulation": {
  "itcz_strength_summer": 1.5,     // Stronger convection
  "itcz_strength_winter": 0.8,     // Weaker convection
  "spawn_rate_summer": 1.3,        // More wind regions
  "spawn_rate_winter": 0.7         // Fewer wind regions
}

Results:

  • Monsoon Seasons: ITCZ amplification cycles
  • Hurricane Seasons: Increased spawn rates + ITCZ amplification
  • Dry Seasons: Reduced ITCZ strength + lower spawn rates

Climate Zone Effects on Biome Generation

Token-Based Biome Classification

Climate Token Usage:

BiomeType classifyBiome(const WorldTile& tile) {
    int total_rain = tile.getAccumulatedTokens("rain");
    int total_wind = tile.getAccumulatedTokens("wind");
    int highWind_tokens = tile.getAccumulatedTokens("highWind");
    int flood_tokens = tile.getAccumulatedTokens("flood");
    int hurricane_tokens = tile.getAccumulatedTokens("hurricane");

    // Special climate zones override normal biome classification
    if (hurricane_tokens > 0) {
        return BiomeType::HURRICANE_ZONE;     // Specialized storm-resistant vegetation
    }
    if (flood_tokens > FLOOD_THRESHOLD) {
        return BiomeType::WETLANDS;           // Forced marshes/swamps
    }
    if (highWind_tokens > STORM_THRESHOLD) {
        // High wind prevents forest growth
        if (total_rain > 300) {
            return BiomeType::STORM_PRAIRIE;  // Grasslands that can handle wind
        } else {
            return BiomeType::BADLANDS;       // Sparse, wind-resistant vegetation
        }
    }

    // Normal biome classification using basic rain/wind tokens
    if (total_rain > 500) {
        return BiomeType::TROPICAL_RAINFOREST;
    } else if (total_rain < 50) {
        return BiomeType::HOT_DESERT;
    }
    // ... additional normal biome logic
}

Climate Zone Characteristics:

  • Hurricane Zones → Storm-resistant palms, specialized coastal vegetation
  • Flood Zones → Wetlands, marshes, swamp vegetation mandatory
  • High Wind Zones → No forests allowed, prairie/badlands only
  • Normal Zones → Standard biome classification by rain/temperature

Performance Characteristics

Computational Complexity

  • Wind Regions: O(n) for n active regions (~50-200 simultaneously)
  • ITCZ Calculations: O(m) for m convergence zones (~5-15 globally)
  • Token Distribution: O(tiles_visited) per region movement
  • Total per cycle: O(n × average_movement_distance)

Memory Usage

  • WindRegion: 32 bytes per region
  • ITCZ Zone: 24 bytes per zone
  • Token accumulation: Uses existing tile data structure
  • Estimated total: <5MB for global weather simulation

Generation Time

  • Landmass analysis: 1-2 seconds (one-time setup)
  • Per simulation cycle: 10-50ms for 100-200 wind regions
  • Full climate stabilization: 100-500 cycles → 10-30 seconds total

Integration with Existing Systems

TectonicRegions Reuse

// Leverage existing tectonic analysis
class ClimateSystem {
    void initializeFromTectonics(const std::vector<TectonicRegion>& regions) {
        auto continents = groupRegionsByProximity(regions);
        auto oceans = calculateOceanBasins(continents);

        generateITCZFromContinents(continents);
        setupWindSpawnFromOceans(oceans);
    }
};

RegionalInfluence Framework

// Wind regions as mobile regional influences
class WindRegion : public RegionalInfluence {
    void applyInfluenceToTile(WorldTile& tile) override {
        distributeTokens(tile);

        // Create regional influence for persistent effects
        if (isStormLevel()) {
            createPersistentInfluence(tile, getStormType());
        }
    }
};

Biome Generation Integration

// Use accumulated climate tokens for biome classification
BiomeType classifyBiome(const WorldTile& tile) {
    int total_rain = tile.getAccumulatedTokens("rain");
    int total_wind = tile.getAccumulatedTokens("wind");
    float temperature = tile.getTemperature();

    if (total_rain > 500 && temperature > 20.0f) {
        return BiomeType::TROPICAL_RAINFOREST;
    } else if (total_rain < 50 && temperature > 15.0f) {
        return BiomeType::HOT_DESERT;
    }
    // ... additional biome logic
}

Implementation Priority

Phase 1: Core Framework (1-2 weeks)

  1. WindRegion class and basic movement
  2. Token distribution system
  3. Simple spawn from ocean detection
  4. Basic planetary circulation bands

Phase 2: ITCZ System (1-2 weeks)

  1. Landmass analysis from TectonicRegions
  2. ITCZ generation and gravitational effects
  3. Wind region amplification mechanics
  4. Storm classification system

Phase 3: Advanced Features (1-2 weeks)

  1. Destruction token system and persistent effects
  2. Seasonal variation and modulation
  3. Performance optimization
  4. Integration with biome generation

Phase 4: Tuning and Validation (1 week)

  1. Parameter adjustment for realistic patterns
  2. Verification of Congo/Sahara differentiation
  3. Performance profiling and optimization
  4. Documentation and examples

Configuration Example

{
  "climate_simulation": {
    "wind_spawn_system": {
      "base_spawn_rate": 0.1,
      "ocean_size_factor": 0.001,
      "max_concurrent_regions": 200
    },
    "planetary_circulation": {
      "trade_winds_strength": 1.5,
      "jet_stream_strength": 1.8,
      "calm_zone_chaos": 0.3
    },
    "itcz_system": {
      "latitude_band": [0.45, 0.55],
      "min_landmass_size": 10000,
      "max_ocean_distance": 800,
      "amplification_max": 3.0
    },
    "storm_thresholds": {
      "high_wind_min": 2.0,
      "flood_wetness_min": 1.5,
      "hurricane_wind_min": 2.5,
      "hurricane_rain_min": 2.0
    },
    "token_distribution": {
      "wind_token_factor": 10,
      "rain_token_factor": 10,
      "climate_zone_rate": 1
    }
  }
}

Note: All parameters are hot-reloadable via the modular configuration system. Magic numbers are intentionally externalizable for real-time tuning during development - adjust values, save config, see immediate results without recompilation.


## Scientific Accuracy vs Gameplay

### Scientifically Inspired Elements
- ✅ ITCZ formation from continental heating
- ✅ Planetary circulation bands (trade winds, jet streams)
- ✅ Storm formation from wind-moisture interaction
- ✅ Geographic influence on climate patterns
- ✅ Persistent landscape effects from weather

### Gameplay Simplifications
- ⚠️ 2D simulation instead of 3D atmospheric layers
- ⚠️ Simplified storm evolution (no pressure systems)
- ⚠️ Discrete token system instead of continuous fields
- ⚠️ Accelerated timeframes for practical simulation

### Result
**Plausible climate science** that creates **engaging gameplay** with **emergent complexity** from **simple, understandable rules**.

---

**Status**: System designed and ready for implementation. Provides realistic climate differentiation (Sahara vs Congo) through elegant mobile region simulation using existing tectonic framework.