#[cfg(test)]
mod tests;
use crate::error::{Error, Result};
use crate::military::army::{Army, ArmyState};
use crate::military::maneuver::{Maneuver, ManeuverId, ManeuverRequest};
use crate::world::World;
impl World {
#[inline]
pub fn collapse_armies(&mut self) {
self.military.collapse_armies();
}
#[inline]
pub fn request_maneuver(&mut self, request: ManeuverRequest) -> Result<ManeuverId> {
self.request_maneuver_with_emit(request, true)
}
pub(crate) fn request_maneuver_with_emit(
&mut self,
request: ManeuverRequest,
emit: bool,
) -> Result<ManeuverId> {
self
.military
.collapse_armies_in(request.origin);
let origin_ruler = self.city(request.origin)?.owner().clone();
let Some(army) = self
.military
.armies_mut_at(request.origin)
.iter_mut()
.find(|army| army.is_idle_and_owned_by(&origin_ruler))
.filter(|army| army.has_enough_personnel(&request.personnel))
else {
return Err(Error::InsufficientUnits);
};
let Some(remaining) = army
.personnel()
.checked_sub(&request.personnel)
else {
return Err(Error::InsufficientUnits);
};
let army_id = army.id();
let army_owner = army.owner().clone();
*army.personnel_mut() = request.personnel;
let army_speed = army.speed(&self.config);
let (id, maneuver) = Maneuver::builder()
.army(army_id)
.kind(request.kind)
.origin(request.origin)
.destination(request.destination)
.speed(army_speed)
.build()?;
self.military.insert_maneuver(maneuver);
let army = self.military.army_mut(army_id)?;
*army.state_mut() = ArmyState::with_maneuver(id);
if !remaining.is_empty() {
Army::builder()
.owner(army_owner)
.personnel(remaining)
.build()
.spawn(&mut self.military, request.origin);
}
let sender_player = origin_ruler.player();
let target_player = self.city(request.destination)?.player();
if emit {
if let Some(sender_player) = sender_player {
self.emit_military_updated(sender_player.clone())?;
}
if let Some(target_player) = target_player
&& sender_player.is_none_or(|it| it != &target_player)
{
self.emit_military_updated(target_player)?;
}
}
Ok(id)
}
}