feat(@projects/@magic-civilization): 🌫️ p3-20 (core) — WeatherEvent.vision_penalty (weather-producer side)
The producer side of weather→scouting: WeatherEvent gains vision_penalty: i32 (serde-default + flexible deser), and derive_events sets it per kind — storm 1, blizzard 2, dust_storm 2; heat_wave/drought/flood 0 (clear-weather events don't impair sight). This is the sight-radius reduction the vision computation will consume so units under storms/blizzards/dust storms scout less. Tests: storm/blizzard/heat_wave assertions for vision_penalty; mc-climate 45/0. p3-20 stays partial — compute_vision consumption + bridge/GDScript wiring next. (Per-kind values inline; data-drive to thresholds/json is a noted follow-up.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bb38d5db0e
commit
923af9c0ec
5 changed files with 33 additions and 10 deletions
|
|
@ -17,8 +17,8 @@
|
|||
| **P0** | 44 | 0 | 0 | 0 | 0 | 0 | 44 |
|
||||
| **P1** | 88 | 0 | 0 | 0 | 0 | 1 | 89 |
|
||||
| **P2** | 130 | 0 | 0 | 0 | 0 | 1 | 131 |
|
||||
| **P3 (oos)** | 31 | 0 | 3 | 0 | 1 | 29 | 64 |
|
||||
| **total** | **293** | **0** | **3** | **0** | **1** | **31** | **328** |
|
||||
| **P3 (oos)** | 31 | 0 | 4 | 0 | 0 | 29 | 64 |
|
||||
| **total** | **293** | **0** | **4** | **0** | **0** | **31** | **328** |
|
||||
|
||||
</td><td valign='top' style='padding-left:2em'>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
id: p3-20
|
||||
title: Weather affects scouting — vision/LoS penalty under storms, blizzards, dust
|
||||
priority: p3
|
||||
status: missing
|
||||
status: partial
|
||||
scope: game1
|
||||
owner: warcouncil
|
||||
updated_at: 2026-06-25
|
||||
|
|
@ -18,6 +18,10 @@ effect** — weather slows movement and hurts units, but does not reduce scoutin
|
|||
range. So storms/blizzards/dust have no effect on exploration, fog reveal, or
|
||||
surprise — a missed gameplay lever for the weather system.
|
||||
|
||||
## Progress (2026-06-25)
|
||||
|
||||
Weather-producer side done: `WeatherEvent.vision_penalty: i32` added (`mc-climate`); `derive_events` sets it per kind (storm 1, blizzard 2, dust_storm 2; heat_wave/drought/flood 0). Tests assert the per-kind values (mc-climate 45/0). **Remaining:** `compute_vision` (mc-vision) consumes a per-tile vision-penalty to shrink a unit's effective sight under weather + the bridge/GDScript wiring (build the penalty map from live weather) + dylib/GUT. *(Per-kind values inline for now; data-drive to WeatherThresholds/climate_spec.json is a follow-up.)*
|
||||
|
||||
## Acceptance
|
||||
|
||||
- [ ] `mc-climate::weather::WeatherEvent` gains a `vision_penalty` (per type;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"generated_at": "2026-06-25T19:16:18Z",
|
||||
"generated_at": "2026-06-25T19:45:10Z",
|
||||
"totals": {
|
||||
"stub": 0,
|
||||
"oos": 31,
|
||||
"partial": 3,
|
||||
"done": 293,
|
||||
"missing": 1,
|
||||
"in_progress": 0,
|
||||
"oos": 31,
|
||||
"stub": 0,
|
||||
"missing": 0,
|
||||
"partial": 4,
|
||||
"done": 293,
|
||||
"total": 328
|
||||
},
|
||||
"objectives": [
|
||||
|
|
@ -3244,7 +3244,7 @@
|
|||
"id": "p3-20",
|
||||
"title": "Weather affects scouting — vision/LoS penalty under storms, blizzards, dust",
|
||||
"priority": "p3",
|
||||
"status": "missing",
|
||||
"status": "partial",
|
||||
"scope": "game1",
|
||||
"owner": "warcouncil",
|
||||
"updated_at": "2026-06-25",
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ mod tests {
|
|||
temperature_delta: temp_d,
|
||||
movement_penalty: 0.5,
|
||||
unit_damage: dmg,
|
||||
vision_penalty: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@ pub struct WeatherEvent {
|
|||
pub movement_penalty: f32,
|
||||
#[serde(deserialize_with = "crate::gd_compat::de_i32_flexible")]
|
||||
pub unit_damage: i32,
|
||||
/// p3-20 — sight-radius reduction for units under this event. Storms,
|
||||
/// blizzards and dust storms cut scouting/vision; clear-weather events leave
|
||||
/// it 0. Consumed by the vision computation (mc-vision) to shrink a unit's
|
||||
/// effective sight while it stands in the event's footprint.
|
||||
#[serde(default, deserialize_with = "crate::gd_compat::de_i32_flexible")]
|
||||
pub vision_penalty: i32,
|
||||
}
|
||||
|
||||
/// Thresholds pulled from climate_spec.json → `weather.thresholds`.
|
||||
|
|
@ -251,6 +257,7 @@ pub fn derive_events(
|
|||
temperature_delta: 0.0,
|
||||
movement_penalty: thresholds.storm_movement_penalty,
|
||||
unit_damage: 0,
|
||||
vision_penalty: 1,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
|
@ -270,6 +277,7 @@ pub fn derive_events(
|
|||
temperature_delta: thresholds.heat_wave_temperature_delta,
|
||||
movement_penalty: 0.0,
|
||||
unit_damage: thresholds.heat_wave_unit_damage,
|
||||
vision_penalty: 0,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
|
@ -289,6 +297,7 @@ pub fn derive_events(
|
|||
temperature_delta: thresholds.blizzard_temperature_delta,
|
||||
movement_penalty: thresholds.blizzard_movement_penalty,
|
||||
unit_damage: thresholds.blizzard_unit_damage,
|
||||
vision_penalty: 2,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
|
@ -312,6 +321,7 @@ pub fn derive_events(
|
|||
temperature_delta: 0.0,
|
||||
movement_penalty: 0.0,
|
||||
unit_damage: 0,
|
||||
vision_penalty: 0,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
|
@ -332,6 +342,7 @@ pub fn derive_events(
|
|||
temperature_delta: 0.0,
|
||||
movement_penalty: thresholds.flood_movement_penalty,
|
||||
unit_damage: thresholds.flood_unit_damage,
|
||||
vision_penalty: 0,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
|
@ -353,6 +364,7 @@ pub fn derive_events(
|
|||
temperature_delta: 0.0,
|
||||
movement_penalty: thresholds.dust_storm_movement_penalty,
|
||||
unit_damage: thresholds.dust_storm_unit_damage,
|
||||
vision_penalty: 2,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -390,6 +402,8 @@ mod tests {
|
|||
let events = derive_events(&g, &t, 1, 42);
|
||||
assert_eq!(events.len(), 16);
|
||||
assert!(events.iter().all(|e| e.kind == "storm"));
|
||||
// p3-20: storms cut scouting (vision_penalty > 0).
|
||||
assert!(events.iter().all(|e| e.vision_penalty == 1), "storms reduce vision");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -401,6 +415,8 @@ mod tests {
|
|||
assert_eq!(events.len(), 16);
|
||||
assert!(events.iter().all(|e| e.kind == "heat_wave"));
|
||||
assert!(events[0].unit_damage > 0);
|
||||
// p3-20: heat waves don't impair scouting.
|
||||
assert_eq!(events[0].vision_penalty, 0, "heat waves do not reduce vision");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -411,6 +427,8 @@ mod tests {
|
|||
let events = derive_events(&g, &t, 1, 42);
|
||||
assert_eq!(events.len(), 16);
|
||||
assert!(events.iter().all(|e| e.kind == "blizzard"));
|
||||
// p3-20: blizzards cut scouting hardest.
|
||||
assert!(events.iter().all(|e| e.vision_penalty == 2), "blizzards reduce vision most");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue