nil_core/world/resources/
mod.rs1#[cfg(test)]
5mod tests;
6
7use crate::continent::index::ContinentKey;
8use crate::error::Result;
9use crate::resources::diff::ResourcesDiff;
10use crate::resources::maintenance::MaintenanceBalance;
11use crate::resources::prelude::Maintenance;
12use crate::resources::{Food, Resources};
13use crate::ruler::Ruler;
14use crate::world::World;
15use nil_num::mul_ceil::MulCeil;
16
17impl World {
18 pub(crate) fn add_resources_within_capacity<R>(
20 &mut self,
21 ruler: R,
22 resources: Resources,
23 ) -> Result<()>
24 where
25 R: Into<Ruler>,
26 {
27 let ruler: Ruler = ruler.into();
28 let capacity = self.get_storage_capacity(ruler.clone())?;
29 let resources_diff = ResourcesDiff::try_from(resources)?;
30
31 self
32 .ruler_mut(&ruler)?
33 .resources_mut()
34 .add_within_capacity(resources_diff, capacity);
35
36 Ok(())
37 }
38
39 pub(crate) fn get_maintenance<R>(&self, ruler: R) -> Result<Maintenance>
40 where
41 R: Into<Ruler>,
42 {
43 let ruler: Ruler = ruler.into();
44 let stats = self.stats().infrastructure();
45 let mut maintenance = self.military().maintenance_of(ruler.clone());
46
47 for city in self.continent().cities_of(ruler) {
48 maintenance += city.maintenance(&stats)?;
49 }
50
51 Ok(maintenance)
52 }
53
54 pub(crate) fn get_maintenance_balance<R>(&self, ruler: R) -> Result<MaintenanceBalance>
55 where
56 R: Into<Ruler>,
57 {
58 let ruler: Ruler = ruler.into();
59 let stats = self.stats().infrastructure();
60
61 let mut production = Food::new(0);
62 let mut maintenance = self.military().maintenance_of(ruler.clone());
63
64 for city in self.continent().cities_of(ruler) {
65 maintenance += city.maintenance(&stats)?;
66 production += city.round_production(&stats)?.food;
67 }
68
69 Ok(MaintenanceBalance { maintenance, production })
70 }
71
72 pub fn get_weighted_resources<K>(&self, key: K) -> Result<Resources>
73 where
74 K: ContinentKey,
75 {
76 let city = key
77 .into_coord(self.continent.size())
78 .and_then(|coord| self.city(coord))?;
79
80 let capacity_weight = self.get_storage_capacity_weight(city.coord())?;
81 let mut resources = self.ruler(city.owner())?.resources();
82
83 macro_rules! apply {
84 ($res:ident, $storage:ident) => {
85 let weight = f64::from(capacity_weight.$storage);
86 resources.$res = resources.$res.mul_ceil(weight).into();
87 };
88 }
89
90 apply!(food, silo);
91 apply!(iron, warehouse);
92 apply!(stone, warehouse);
93 apply!(wood, warehouse);
94
95 Ok(resources)
96 }
97
98 pub(crate) fn withdraw_resources_up_to<R>(
100 &mut self,
101 ruler: R,
102 resources: &mut Resources,
103 ) -> Result<()>
104 where
105 R: Into<Ruler>,
106 {
107 let mut ruler = self.ruler_mut(&ruler.into())?;
108 let current_resources = ruler.take_resources();
109 if let Some(result) = current_resources.checked_sub(*resources) {
110 *ruler.resources_mut() = result;
111 } else {
112 *resources = current_resources;
113 }
114
115 Ok(())
116 }
117}