diff --git a/server/src/atlas/attractor_matching.rs b/server/src/atlas/attractor_matching.rs index 424c39ce2..232bd2f5f 100644 --- a/server/src/atlas/attractor_matching.rs +++ b/server/src/atlas/attractor_matching.rs @@ -69,7 +69,7 @@ fn role_row(economic_role: &str) -> usize { "transit_hub" => 6, "research" => 7, "military" => 8, - "residential" | _ => 9, + _ => 9, } } @@ -132,8 +132,8 @@ fn hungarian(cost: &[Vec]) -> Vec { c[i][j] = cost[i][j]; } // Pad extra columns with high cost so overflow cities pick them last. - for j in m..sz { - c[i][j] = f32::MAX / 2.0; + for item in c[i].iter_mut().take(sz).skip(m) { + *item = f32::MAX / 2.0; } } // Pad extra rows with 0 cost (dummy workers). @@ -228,8 +228,8 @@ fn synthetic_attractor( let r = (dr * MIN_SPACING).min(grid_h as u16 - 1); let c = (dc * MIN_SPACING).min(grid_w as u16 - 1); let ok = placed.iter().all(|p| { - let dr2 = (p.position.0 as i32 - r as i32).abs() as u16; - let dc2 = (p.position.1 as i32 - c as i32).abs() as u16; + let dr2 = (p.position.0 as i32 - r as i32).unsigned_abs() as u16; + let dc2 = (p.position.1 as i32 - c as i32).unsigned_abs() as u16; dr2.max(dc2) >= MIN_SPACING }); if ok { @@ -379,7 +379,7 @@ pub fn match_cities( // ------------------------------------------------------------------------- // Phase 4: Synthetic overflow — all remaining cities // ------------------------------------------------------------------------- - let placed_ids: std::collections::HashSet = + let placed_ids: std::collections::BTreeSet = placements.iter().map(|p| p.city_id).collect(); for city in cities { @@ -401,7 +401,7 @@ pub fn match_cities( // ------------------------------------------------------------------------- // Phase 5: Name fulfillment check // ------------------------------------------------------------------------- - let placed_ids: std::collections::HashSet = + let placed_ids: std::collections::BTreeSet = placements.iter().map(|p| p.city_id).collect(); for city in cities { if !placed_ids.contains(&city.city_id) { diff --git a/server/src/atlas/body_world_state.rs b/server/src/atlas/body_world_state.rs index f1bcc9ae5..58f901bdc 100644 --- a/server/src/atlas/body_world_state.rs +++ b/server/src/atlas/body_world_state.rs @@ -8,7 +8,7 @@ //! evicted on overflow, unless it is pinned (current player location or an //! adjacent-system neighbor). -use std::collections::HashMap; +use std::collections::{BTreeMap, BTreeSet}; use bevy_ecs::prelude::Resource; @@ -87,17 +87,17 @@ pub struct BodyWorldState { /// invariant that `entries.len() <= capacity`. #[derive(Resource, Debug, Default)] pub struct BodyWorldStateCache { - entries: HashMap, + entries: BTreeMap, /// Body IDs that must not be evicted regardless of `last_accessed`. - pinned: std::collections::HashSet, + pinned: BTreeSet, capacity: usize, } impl BodyWorldStateCache { pub fn new(capacity: usize) -> Self { Self { - entries: HashMap::with_capacity(capacity), - pinned: std::collections::HashSet::new(), + entries: BTreeMap::new(), + pinned: BTreeSet::new(), capacity, } } diff --git a/server/src/atlas/district_mix.rs b/server/src/atlas/district_mix.rs index 6e3fc9f5a..1735de70c 100644 --- a/server/src/atlas/district_mix.rs +++ b/server/src/atlas/district_mix.rs @@ -92,7 +92,7 @@ fn role_row(economic_role: &str) -> usize { "transit_hub" => 6, "research" => 7, "military" => 8, - "residential" | _ => 9, + _ => 9, } } diff --git a/server/src/atlas/drainage.rs b/server/src/atlas/drainage.rs index 1deadb6de..5bb5e580b 100644 --- a/server/src/atlas/drainage.rs +++ b/server/src/atlas/drainage.rs @@ -181,8 +181,8 @@ fn flow_accumulation(fdir: &[i8], w: usize, h: usize) -> Vec { } let mut queue = VecDeque::new(); - for i in 0..n { - if in_degree[i] == 0 { + for (i, °) in in_degree.iter().enumerate().take(n) { + if deg == 0 { queue.push_back(i); } } @@ -314,11 +314,9 @@ fn label_basins(fdir: &[i8], accum: &[i32], w: usize, h: usize) -> Vec { for &(dr, dc) in &D8 { let nr = r as i32 + dr; let nc = (c as i32 + dc).rem_euclid(w as i32) as usize; - if nr >= 0 && nr < h as i32 { - if accum[nr as usize * w + nc] > accum[i] { - is_max = false; - break; - } + if nr >= 0 && nr < h as i32 && accum[nr as usize * w + nc] > accum[i] { + is_max = false; + break; } } if is_max { @@ -392,7 +390,7 @@ fn merge_small_basins( for _ in 0..200 { // Count basin sizes. - let mut sizes: std::collections::HashMap = std::collections::HashMap::new(); + let mut sizes: std::collections::BTreeMap = std::collections::BTreeMap::new(); for &l in &labels { *sizes.entry(l).or_insert(0) += 1; } @@ -432,15 +430,13 @@ fn merge_small_basins( // Renumber contiguously from 0. let unique: Vec = { - let mut set: std::collections::HashSet = std::collections::HashSet::new(); + let mut set: std::collections::BTreeSet = std::collections::BTreeSet::new(); for &l in &labels { set.insert(l); } - let mut v: Vec = set.into_iter().collect(); - v.sort(); - v + set.into_iter().collect() }; - let remap: std::collections::HashMap = unique + let remap: std::collections::BTreeMap = unique .iter() .enumerate() .map(|(new, &old)| (old, new as i32)) @@ -455,13 +451,13 @@ fn merge_small_basins( fn find_largest_neighbor( labels: &[i32], target_id: i32, - sizes: &std::collections::HashMap, + sizes: &std::collections::BTreeMap, w: usize, h: usize, ) -> Option { let n = w * h; - let mut neighbor_sizes: std::collections::HashMap = - std::collections::HashMap::new(); + let mut neighbor_sizes: std::collections::BTreeMap = + std::collections::BTreeMap::new(); for i in 0..n { if labels[i] != target_id { @@ -497,8 +493,8 @@ fn find_largest_neighbor( fn build_basins(labels: &[i32], w: usize, h: usize) -> Vec { let n = w * h; - let mut basin_map: std::collections::HashMap> = - std::collections::HashMap::new(); + let mut basin_map: std::collections::BTreeMap> = + std::collections::BTreeMap::new(); for (i, &l) in labels.iter().enumerate() { basin_map.entry(l).or_default().push(i); diff --git a/server/src/atlas/gen_queue.rs b/server/src/atlas/gen_queue.rs index 90c45f40e..5ab27afaf 100644 --- a/server/src/atlas/gen_queue.rs +++ b/server/src/atlas/gen_queue.rs @@ -109,7 +109,7 @@ pub struct GenerationQueue { /// Rayon thread pool dedicated to generation work. pool: rayon::ThreadPool, /// Set of body_ids currently in-flight to avoid duplicate submissions. - in_flight: Arc>>, + in_flight: Arc>>, } impl std::fmt::Debug for GenerationQueue { @@ -150,7 +150,7 @@ impl GenerationQueue { completion_tx: tx, completion_rx: rx, pool, - in_flight: Arc::new(Mutex::new(std::collections::HashSet::new())), + in_flight: Arc::new(Mutex::new(std::collections::BTreeSet::new())), } } @@ -169,7 +169,7 @@ impl GenerationQueue { // Check pending list. let pending = self.pending.lock().unwrap(); if pending.iter().any(|q| { - q.item.body_id().map_or(false, |id| id == body_id) + q.item.body_id() == Some(body_id) }) { return; } @@ -193,11 +193,8 @@ impl GenerationQueue { /// available without blocking. pub fn drain_completions(&self) -> Vec { let mut out = Vec::new(); - loop { - match self.completion_rx.try_recv() { - Ok(c) => out.push(c), - Err(_) => break, - } + while let Ok(c) = self.completion_rx.try_recv() { + out.push(c); } out } diff --git a/server/src/atlas/heightmap.rs b/server/src/atlas/heightmap.rs index 7f6c7c69e..fd0e6ea0d 100644 --- a/server/src/atlas/heightmap.rs +++ b/server/src/atlas/heightmap.rs @@ -43,7 +43,7 @@ impl BodyHeightmap { /// Returns `true` if the cell at (row, col) is land (above sea level). #[inline] pub fn is_land(&self, row: u32, col: u32) -> bool { - self.get(row, col).map_or(false, |e| e >= self.sea_level) + self.get(row, col).is_some_and(|e| e >= self.sea_level) } }