feat(city): Implement bridge occupation multiplier and capture marking in City struct

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-04-30 00:14:46 -07:00
parent 127d41dfe9
commit bcb464f1d4

View file

@ -276,6 +276,11 @@ pub struct City {
/// a city under sustained siege cannot out-regen incoming damage.
#[serde(default)]
pub last_attacked_turn: Option<u32>,
/// Turn this city was most recently captured. `None` = never captured.
/// Used to apply an occupation production penalty for OCCUPATION_TURNS after capture.
#[serde(default)]
pub captured_turn: Option<u32>,
}
impl Default for City {
@ -300,6 +305,7 @@ impl Default for City {
queues: HashMap::new(),
building_yields: HashMap::new(),
last_attacked_turn: None,
captured_turn: None,
}
}
}
@ -361,6 +367,7 @@ impl City {
queues: HashMap::new(),
building_yields: HashMap::new(),
last_attacked_turn: None,
captured_turn: None,
}
}
@ -664,6 +671,24 @@ impl City {
self.hp == 0
}
/// Record that this city was captured on `turn`.
/// Enables `occupation_production_mult` to apply the penalty.
pub fn mark_captured(&mut self, turn: u32) {
self.captured_turn = Some(turn);
}
/// Returns the production multiplier for `current_turn`.
/// Captured cities produce at 50% for `OCCUPATION_TURNS` turns
/// after capture to slow the attacker's production snowball.
pub fn occupation_production_mult(&self, current_turn: u32) -> f64 {
const OCCUPATION_TURNS: u32 = 5;
const OCCUPATION_PENALTY: f64 = 0.5;
match self.captured_turn {
Some(ct) if current_turn.saturating_sub(ct) < OCCUPATION_TURNS => OCCUPATION_PENALTY,
_ => 1.0,
}
}
// ── Production queue (carried from production.rs, unchanged) ──
/// Validate, charge, and enqueue an item into its producer building's queue.