From 923af9c0ecdb0f71c590880a6ac2788b49649c40 Mon Sep 17 00:00:00 2001 From: Natalie Date: Thu, 25 Jun 2026 15:45:10 -0400 Subject: [PATCH] =?UTF-8?q?feat(@projects/@magic-civilization):=20?= =?UTF-8?q?=F0=9F=8C=AB=EF=B8=8F=20p3-20=20(core)=20=E2=80=94=20WeatherEve?= =?UTF-8?q?nt.vision=5Fpenalty=20(weather-producer=20side)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .project/objectives/README.md | 4 ++-- .../p3-20-weather-affects-scouting.md | 6 +++++- .../games/age-of-dwarves/data/objectives.json | 14 +++++++------- .../crates/mc-climate/src/climate_effects.rs | 1 + src/simulator/crates/mc-climate/src/weather.rs | 18 ++++++++++++++++++ 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/.project/objectives/README.md b/.project/objectives/README.md index 3ae5ad12..f464bba0 100644 --- a/.project/objectives/README.md +++ b/.project/objectives/README.md @@ -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** | diff --git a/.project/objectives/p3-20-weather-affects-scouting.md b/.project/objectives/p3-20-weather-affects-scouting.md index b4a9aab1..313bd398 100644 --- a/.project/objectives/p3-20-weather-affects-scouting.md +++ b/.project/objectives/p3-20-weather-affects-scouting.md @@ -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; diff --git a/public/games/age-of-dwarves/data/objectives.json b/public/games/age-of-dwarves/data/objectives.json index 4d9b13f9..61a367d7 100644 --- a/public/games/age-of-dwarves/data/objectives.json +++ b/public/games/age-of-dwarves/data/objectives.json @@ -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", diff --git a/src/simulator/crates/mc-climate/src/climate_effects.rs b/src/simulator/crates/mc-climate/src/climate_effects.rs index 463b7dbb..861e0f00 100644 --- a/src/simulator/crates/mc-climate/src/climate_effects.rs +++ b/src/simulator/crates/mc-climate/src/climate_effects.rs @@ -143,6 +143,7 @@ mod tests { temperature_delta: temp_d, movement_penalty: 0.5, unit_damage: dmg, + vision_penalty: 0, } } diff --git a/src/simulator/crates/mc-climate/src/weather.rs b/src/simulator/crates/mc-climate/src/weather.rs index 526d01a3..eaa74128 100644 --- a/src/simulator/crates/mc-climate/src/weather.rs +++ b/src/simulator/crates/mc-climate/src/weather.rs @@ -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]