// Simulation RNG system // Injectable ChaCha RNG resource for deterministic replay (D-030) // Ensures same seed produces same outcomes use bevy_ecs::prelude::*; use rand::SeedableRng; use rand_chacha::ChaCha20Rng; /// Simulation RNG resource /// ChaCha20 RNG with stored seed for deterministic replay #[derive(Resource)] pub struct SimRng { pub rng: ChaCha20Rng, seed: u64, } impl SimRng { /// Create a new SimRng with the given seed pub fn new(seed: u64) -> Self { Self { rng: ChaCha20Rng::seed_from_u64(seed), seed, } } /// Get the seed used to initialize this RNG pub fn seed(&self) -> u64 { self.seed } } #[cfg(test)] mod tests { use super::*; use rand::Rng; #[test] fn same_seed_same_sequence() { let mut rng1 = SimRng::new(42); let mut rng2 = SimRng::new(42); let vals1: Vec = (0..100).map(|_| rng1.rng.random()).collect(); let vals2: Vec = (0..100).map(|_| rng2.rng.random()).collect(); assert_eq!(vals1, vals2); } #[test] fn different_seed_different_sequence() { let mut rng1 = SimRng::new(42); let mut rng2 = SimRng::new(43); let val1: u32 = rng1.rng.random(); let val2: u32 = rng2.rng.random(); assert_ne!(val1, val2); } }