From 7da7e71d68b4bfa4e375117a35c3fad226de0c40 Mon Sep 17 00:00:00 2001 From: Natalie Date: Tue, 5 May 2026 17:21:50 -0400 Subject: [PATCH] =?UTF-8?q?feat(@projects/@magic-civilization):=20?= =?UTF-8?q?=E2=9C=A8=20upgrade=20queues=20to=20btreemap=20for=20determinis?= =?UTF-8?q?tic=20iteration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- src/simulator/crates/mc-city/src/city.rs | 21 +++++++++++++++------ src/simulator/crates/mc-combat/src/lair.rs | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/simulator/crates/mc-city/src/city.rs b/src/simulator/crates/mc-city/src/city.rs index 77b89d1e..84f1f825 100644 --- a/src/simulator/crates/mc-city/src/city.rs +++ b/src/simulator/crates/mc-city/src/city.rs @@ -13,8 +13,8 @@ use crate::production::{ use mc_core::collectibles::CollectibleRoll; use mc_core::ResourceId; use mc_economy::{Stockpile, StockpileError}; -use serde::{Deserialize, Serialize}; -use std::collections::{HashMap, HashSet}; +use serde::{Deserialize, Deserializer, Serialize}; +use std::collections::{BTreeMap, HashMap, HashSet}; /// Which `CityYields` channel a collectible resource_id maps to. /// Resources not matched here are silently skipped (they gate units/buildings @@ -265,8 +265,17 @@ pub struct City { // ── Buildings & queues (carried from production.rs) ──────────── pub buildings: Vec, - #[serde(default)] - queues: HashMap, + /// Per-origin production queues. Keyed by either a producer building id + /// (e.g. `smithy`, `marketplace`) or [`CITY_CENTER_QUEUE_ID`] for + /// `ProductionOrigin::CityCenter`. Backed by a [`BTreeMap`] so iteration + /// order is deterministic — the per-turn split allocator + /// (`tick_city_production`) relies on this for reproducible runs. + /// + /// `deserialize_with` accepts the legacy save schema where a flat + /// `production_queue: Vec` lived on the city; entries migrate + /// into the map keyed by their `origin` (p1-44 Phase B). + #[serde(default, deserialize_with = "deserialize_queues_with_legacy_fallback")] + queues: BTreeMap, /// Per-building flat yield bonuses keyed by building id. /// Populated by GDScript at game load from JSON `effects` arrays. @@ -303,7 +312,7 @@ impl Default for City { focus: CityFocus::Default, worked_tiles: Vec::new(), buildings: Vec::new(), - queues: HashMap::new(), + queues: BTreeMap::new(), building_yields: HashMap::new(), last_attacked_turn: None, captured_turn: None, @@ -365,7 +374,7 @@ impl City { focus: CityFocus::Default, worked_tiles: vec![position], buildings: Vec::new(), - queues: HashMap::new(), + queues: BTreeMap::new(), building_yields: HashMap::new(), last_attacked_turn: None, captured_turn: None, diff --git a/src/simulator/crates/mc-combat/src/lair.rs b/src/simulator/crates/mc-combat/src/lair.rs index 323005dd..53b2f15c 100644 --- a/src/simulator/crates/mc-combat/src/lair.rs +++ b/src/simulator/crates/mc-combat/src/lair.rs @@ -27,7 +27,7 @@ use serde::{Deserialize, Serialize}; -use mc_core::lair::{LairCombatMode, LairId, SiegeOutcome, SiegeState}; +use mc_core::lair::{LairCombatMode, LairId, RaidAftermath, RaidOutcome, SiegeOutcome, SiegeState}; use crate::bonuses::CombatBonuses; use crate::loot::{mix_seed, roll_loot_table, LootDrop, LootEntry};