diff --git a/src/lib.rs b/src/lib.rs index ed215e1..741754b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -231,4 +231,13 @@ mod tests { let system = format!("{:?}", accrete.planet()); assert_eq!(system, fixture); } + + #[test] + fn same_seed_same_system_after_fix_3a() { + let mut a1 = Accrete::new(1); + let s1 = a1.planetary_system(); + let mut a2 = Accrete::new(1); + let s2 = a2.planetary_system(); + assert_eq!(format!("{:?}", s1), format!("{:?}", s2)); + } } diff --git a/src/structs/system.rs b/src/structs/system.rs index 0ad1aba..0234712 100644 --- a/src/structs/system.rs +++ b/src/structs/system.rs @@ -254,17 +254,27 @@ pub fn planetesimals_intersect( if p.is_moon { *prev_p = coalesce_two_planets(prev_p, p, events_log.as_deref_mut()); } else { - // Check for larger/smaller planetesimal - let (larger, smaller) = match p.mass >= prev_p.mass { - true => (p.clone(), prev_p.clone()), - false => (prev_p.clone(), p.clone()), + // Compute roche_limit from scalars — avoids deep-cloning both bodies + // (each carries Vec moons + Vec rings) just to read + // three f64s. The original code cloned `larger` and `smaller` purely to + // satisfy the borrow checker. Third arg to roche_limit_au is the + // smaller/moon body's radius (see roche_limit_au doc in utils.rs). + let (larger_mass, smaller_mass, smaller_radius) = if p.mass >= prev_p.mass { + (p.mass, prev_p.mass, prev_p.radius) + } else { + (prev_p.mass, p.mass, p.radius) }; - let roche_limit = roche_limit_au(&larger.mass, &smaller.mass, &smaller.radius); + let roche_limit = roche_limit_au(&larger_mass, &smaller_mass, &smaller_radius); // Planetesimals collide or one capture another as moon if (prev_p.a - p.a).abs() <= roche_limit * 2.0 { *prev_p = coalesce_two_planets(prev_p, p, events_log.as_deref_mut()); } else { - *prev_p = capture_moon(&larger, &smaller, primary_star_mass, rng, events_log.as_deref_mut()); + // Ensure prev_p holds the larger body before capture_moon. Use + // `>=` to preserve the original tiebreak (p wins on equal mass). + if p.mass >= prev_p.mass { + std::mem::swap(p, prev_p); + } + *prev_p = capture_moon(prev_p, p, primary_star_mass, rng, events_log.as_deref_mut()); prev_p .moons .sort_by(|p1, p2| p1.a.partial_cmp(&p2.a).unwrap());