From bd091e60dfba5365100fe4b03761523df2cb5cc1 Mon Sep 17 00:00:00 2001 From: chexit Date: Tue, 3 Nov 2026 10:35:58 +0300 Subject: [PATCH] Exercise overlapping Oreshnik splits and recording Co-authored-by: Codex --- airdef-core/tests/scenarios.rs | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/airdef-core/tests/scenarios.rs b/airdef-core/tests/scenarios.rs index e7b1936..1305c61 100644 --- a/airdef-core/tests/scenarios.rs +++ b/airdef-core/tests/scenarios.rs @@ -79,3 +79,43 @@ fn overlapping_mass_strikes_on_flat_world() { assert!(second && sim.launched >= 72, "second raid failed to launch; launched {}", sim.launched); assert!(peak > 36, "raids never overlapped; peak {peak}"); } + +#[test] +fn overlapping_oreshnik_splits_are_recorded() { + use airdef::sim::{Aim, Approach, DroneKind, Ground, Out, RaidOrder, Sim}; + use glam::DVec3; + let mut sim = Sim::new(1); + sim.damage = false; + let targets = vec![DVec3::new(0.0, 70.0, 0.0)]; + sim.targets = targets.clone(); + sim.target_health = vec![100.0]; + let order = RaidOrder { kinds: vec![(DroneKind::Oreshnik, 40)], approach: Approach::Sector, aim: Aim::Objects, dist: 2600.0 }; + let terrain = harness::Terrain::Flat(70); + let mut ground = Ground::default(); + let mut pending = Vec::new(); + let mut out = Out::default(); + assert_eq!(sim.order_raid(&order, &targets, &mut out), 40); + let mut second = false; + let mut peak = 0; + let mut peak_subs = 0; + for now in 1..=10000 { + if !second && !sim.planning() { + assert_eq!(sim.order_raid(&order, &targets, &mut out), 40); + second = true; + } + ground.answer(std::mem::take(&mut pending), now); + out = Out::default(); + sim.step(&mut ground, None, &mut out); + pending = ground.take_wanted().into_iter().map(|(x, z)| (x, z, 70)).collect(); + let sections = ground.world.take_wanted(now); + ground.world.serve(&terrain, sections, now); + peak = peak.max(sim.drones.iter().filter(|d| d.alive()).count()); + peak_subs = peak_subs.max(sim.drones.iter().filter(|d| d.alive() && d.kind == DroneKind::OreshnikSub).count()); + assert!(sim.drones.iter().all(|d| d.pos.is_finite() && d.vel.is_finite())); + if second && sim.launched >= 80 && !sim.replays.is_empty() { break; } + } + eprintln!("overlapping oreshnik: launched {}, peak airborne {peak}, peak submunitions {peak_subs}, replays {}", sim.launched, sim.replays.len()); + assert_eq!(sim.launched, 2880); + assert!(peak_subs > 36, "expected many simultaneous submunitions"); + assert!(!sim.replays.is_empty(), "recording did not finish"); +}