nil_core/world/military/
mod.rs1#[cfg(test)]
5mod tests;
6
7use crate::error::{Error, Result};
8use crate::military::army::{Army, ArmyState};
9use crate::military::maneuver::{Maneuver, ManeuverId, ManeuverRequest};
10use crate::world::World;
11
12impl World {
13 #[inline]
14 pub fn collapse_armies(&mut self) {
15 self.military.collapse_armies();
16 }
17
18 #[inline]
19 pub fn request_maneuver(&mut self, request: ManeuverRequest) -> Result<ManeuverId> {
20 self.request_maneuver_with_emit(request, true)
21 }
22
23 pub(crate) fn request_maneuver_with_emit(
24 &mut self,
25 request: ManeuverRequest,
26 emit: bool,
27 ) -> Result<ManeuverId> {
28 self
29 .military
30 .collapse_armies_in(request.origin);
31
32 let origin_ruler = self.city(request.origin)?.owner().clone();
33 let Some(army) = self
34 .military
35 .armies_mut_at(request.origin)
36 .iter_mut()
37 .find(|army| army.is_idle_and_owned_by(&origin_ruler))
38 .filter(|army| army.has_enough_personnel(&request.personnel))
39 else {
40 return Err(Error::InsufficientUnits);
41 };
42
43 let Some(remaining) = army
44 .personnel()
45 .checked_sub(&request.personnel)
46 else {
47 return Err(Error::InsufficientUnits);
48 };
49
50 let army_id = army.id();
51 let army_owner = army.owner().clone();
52 *army.personnel_mut() = request.personnel;
53
54 let army_speed = army.speed(&self.config);
58
59 let (id, maneuver) = Maneuver::builder()
60 .army(army_id)
61 .kind(request.kind)
62 .origin(request.origin)
63 .destination(request.destination)
64 .speed(army_speed)
65 .build()?;
66
67 self.military.insert_maneuver(maneuver);
68
69 let army = self.military.army_mut(army_id)?;
70 *army.state_mut() = ArmyState::with_maneuver(id);
71
72 if !remaining.is_empty() {
75 Army::builder()
76 .owner(army_owner)
77 .personnel(remaining)
78 .build()
79 .spawn(&mut self.military, request.origin);
80 }
81
82 let sender_player = origin_ruler.player();
83 let target_player = self.city(request.destination)?.player();
84
85 if emit {
86 if let Some(sender_player) = sender_player {
87 self.emit_military_updated(sender_player.clone())?;
88 }
89
90 if let Some(target_player) = target_player
91 && sender_player.is_none_or(|it| it != &target_player)
92 {
93 self.emit_military_updated(target_player)?;
94 }
95 }
96
97 Ok(id)
98 }
99}