diff --git a/airdef-core/tests/scenarios.rs b/airdef-core/tests/scenarios.rs index 1305c61..6521c30 100644 --- a/airdef-core/tests/scenarios.rs +++ b/airdef-core/tests/scenarios.rs @@ -119,3 +119,48 @@ fn overlapping_oreshnik_splits_are_recorded() { assert!(peak_subs > 36, "expected many simultaneous submunitions"); assert!(!sim.replays.is_empty(), "recording did not finish"); } + +#[test] +fn two_maximum_menu_raids_with_answered_flat_terrain() { + use airdef::sim::{Aim, Approach, Ground, Out, RaidOrder, Sam, Sim, catalog::RAID_KINDS}; + use glam::DVec3; + let sc = harness::big_smart(); + let terrain = harness::Terrain::Flat(70); + let mut sim = Sim::new(sc.seed); + for unit in &sc.units { + let id = sim.id(); + sim.sams.push(Sam::new(id, unit.kind, DVec3::new(unit.pos.x, 70.0, unit.pos.z), unit.heading)); + } + let targets = vec![DVec3::new(0.0, 70.0, 0.0)]; + sim.targets = targets.clone(); + sim.target_health = vec![100.0]; + // The maximum selectable by the menu: 40 for each raid kind. + let order = RaidOrder { kinds: RAID_KINDS.iter().copied().map(|kind| (kind, 40)).collect(), approach: Approach::AllSides, aim: Aim::Smart, dist: 300.0 }; + let expected = RAID_KINDS.len() as u32 * 40; + let mut ground = Ground::default(); + let mut pending = Vec::new(); + let mut out = Out::default(); + assert_eq!(sim.order_raid(&order, &targets, &mut out), expected); + let mut second = false; + let mut overlap = false; + let mut peak = 0; + for now in 1..=5000 { + if !second && !sim.planning() { + overlap = !sim.queue.is_empty() || sim.drones.iter().any(|d| d.alive()); + assert_eq!(sim.order_raid(&order, &targets, &mut out), expected); + 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()); + assert!(sim.drones.iter().all(|d| d.pos.is_finite() && d.vel.is_finite())); + if second && sim.launched >= expected * 2 && !sim.replays.is_empty() { break; } + } + eprintln!("max menu raids: requested {}, launched {}, peak {peak}, replays {}", expected * 2, sim.launched, sim.replays.len()); + assert!(second && overlap && sim.launched >= expected * 2 && peak > 40); + assert!(!sim.replays.is_empty(), "raid recording did not finish"); +}