nil_core/world/round/
mod.rs1mod behavior;
5mod maneuver;
6
7use crate::error::Result;
8use crate::player::{Player, PlayerId};
9use crate::resources::prelude::*;
10use crate::round::Round;
11use crate::ruler::Ruler;
12use crate::world::World;
13use std::collections::HashMap;
14
15impl World {
16 #[inline]
17 pub fn round(&self) -> &Round {
18 &self.round
19 }
20
21 pub fn start_round(&mut self) -> Result<()> {
22 let ids = self
23 .player_manager
24 .active_players()
25 .map(Player::id);
26
27 self.round.start(ids)?;
28 self.emit_round()?;
29
30 Ok(())
31 }
32
33 pub fn set_player_ready(&mut self, player: &PlayerId, is_ready: bool) -> Result<()> {
34 self.round.set_ready(player, is_ready);
35
36 if self.round.is_done() {
37 self.next_round(true)?;
38 } else {
39 self.emit_round()?;
40 }
41
42 Ok(())
43 }
44
45 pub fn dangerously_end_round(&mut self, emit: bool) -> Result<()> {
47 self.round.dangerously_set_done();
48 self.next_round(emit)?;
49 Ok(())
50 }
51
52 pub(super) fn next_round(&mut self, emit: bool) -> Result<()> {
53 let ids = self
54 .player_manager
55 .active_players()
56 .map(Player::id);
57
58 self.round.next(ids)?;
59 self.prepare_next_round()?;
60 self.consume_pending_save()?;
61
62 if emit {
63 self.emit_round()?;
64 }
65
66 if let Some(on_next_round) = self.on_next_round.clone() {
67 on_next_round.call(self);
68 }
69
70 Ok(())
71 }
72
73 fn prepare_next_round(&mut self) -> Result<()> {
74 self.update_resources()?;
75 self.process_city_queues();
76 self.collapse_armies();
77 self.process_maneuvers()?;
78 self.update_ranking()?;
79 self.process_npc_behavior()?;
80 Ok(())
81 }
82
83 fn update_resources(&mut self) -> Result<()> {
86 let stats = self.stats.infrastructure.as_ref();
87 let mut diff: HashMap<Ruler, ResourcesDiff> = HashMap::new();
88
89 for city in self.continent.cities() {
90 let owner = city.owner().clone();
91 let resources = diff.entry(owner).or_default();
92 *resources += city.round_production(stats)?;
93 resources.food -= city.maintenance(stats)?;
94 }
95
96 for (ruler, mut resources) in diff {
97 resources.food -= self.military.maintenance_of(ruler.clone());
98 let capacity = self.get_storage_capacity(ruler.clone())?;
99 self
100 .ruler_mut(&ruler)?
101 .resources_mut()
102 .add_within_capacity(&resources, &capacity);
103 }
104
105 Ok(())
106 }
107
108 fn process_city_queues(&mut self) {
110 let config = self.config();
111 for city in self.continent.cities_mut() {
112 let coord = city.coord();
113 let owner = city.owner().clone();
114 let infrastructure = city.infrastructure_mut();
115
116 infrastructure.process_prefecture_build_queue(&config);
117
118 macro_rules! process_recruit_queue {
119 ($building:ident) => {
120 paste::paste! {
121 if let Some(personnel) = infrastructure.[<process_ $building:snake _recruit_queue>](&config) {
122 self.military.spawn(coord, owner.clone(), personnel);
123 }
124 }
125 };
126 }
127
128 process_recruit_queue!(Academy);
129 process_recruit_queue!(Stable);
130 process_recruit_queue!(Workshop);
131 }
132 }
133}