# 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
```json
"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
```json
"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:**
```cpp
// 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:**
```json
"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):
```json
"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:**
```cpp
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:**
```cpp
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:**
```cpp
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:**
```cpp
// 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:**
```cpp
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:**
```json
"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:**
```cpp
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
```cpp
// 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
```cpp
// 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
```cpp
// 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

```json
{
  "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.