Skip to main content

nil_core/infrastructure/building/impl/prefecture/
mod.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4#[cfg(test)]
5mod tests;
6
7pub mod build_catalog;
8pub mod build_queue;
9
10use crate::check_total_resource_ratio;
11use crate::infrastructure::building::{BuildingId, BuildingLevel};
12use crate::infrastructure::queue::InfrastructureQueue;
13use crate::infrastructure::requirements::InfrastructureRequirements;
14use crate::ranking::score::Score;
15use crate::resources::cost::{Cost, ResourceRatio};
16use crate::resources::maintenance::MaintenanceRatio;
17use crate::resources::workforce::{Workforce, WorkforceSource};
18use crate::world::config::WorldConfig;
19use build_queue::{PrefectureBuildOrder, PrefectureBuildQueue};
20use nil_core_macros::Building;
21use serde::{Deserialize, Serialize};
22
23#[derive(Building, Clone, Debug, Deserialize, Serialize)]
24#[serde(rename_all = "camelCase")]
25#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
26pub struct Prefecture {
27  level: BuildingLevel,
28  enabled: bool,
29  build_queue: PrefectureBuildQueue,
30}
31
32impl Prefecture {
33  pub const ID: BuildingId = BuildingId::Prefecture;
34
35  pub const MIN_LEVEL: BuildingLevel = BuildingLevel::new(1);
36  pub const MAX_LEVEL: BuildingLevel = BuildingLevel::new(30);
37
38  pub const MIN_COST: Cost = Cost::new(1_000);
39  pub const MAX_COST: Cost = Cost::new(150_000);
40
41  pub const FOOD_RATIO: ResourceRatio = ResourceRatio::new(0.0);
42  pub const IRON_RATIO: ResourceRatio = ResourceRatio::new(0.2);
43  pub const STONE_RATIO: ResourceRatio = ResourceRatio::new(0.5);
44  pub const WOOD_RATIO: ResourceRatio = ResourceRatio::new(0.3);
45
46  pub const MAINTENANCE_RATIO: MaintenanceRatio = MaintenanceRatio::new(0.005);
47
48  pub const MIN_WORKFORCE: Workforce = Workforce::new(1);
49  pub const MAX_WORKFORCE: Workforce = Workforce::new(50);
50
51  pub const MIN_SCORE: Score = Score::new(10);
52  pub const MAX_SCORE: Score = Score::new(1_978);
53
54  pub const INFRASTRUCTURE_REQUIREMENTS: InfrastructureRequirements =
55    InfrastructureRequirements::none();
56
57  pub fn build_queue(&self) -> &PrefectureBuildQueue {
58    &self.build_queue
59  }
60
61  pub(crate) fn build_queue_mut(&mut self) -> &mut PrefectureBuildQueue {
62    &mut self.build_queue
63  }
64
65  #[must_use]
66  pub(crate) fn process_queue(
67    &mut self,
68    config: &WorldConfig,
69  ) -> Option<Vec<PrefectureBuildOrder>> {
70    if self.enabled {
71      let workforce = self.workforce(config);
72      let orders = self.build_queue.process(workforce);
73      (!orders.is_empty()).then_some(orders)
74    } else {
75      None
76    }
77  }
78
79  pub fn resolve_level(&self, building: BuildingId, current_level: BuildingLevel) -> BuildingLevel {
80    self
81      .build_queue
82      .resolve_level(building, current_level)
83  }
84
85  pub(crate) fn turns_in_build_queue(&self, config: &WorldConfig) -> Option<f64> {
86    if self.level > 0u8 {
87      let turn = self.workforce(config);
88      let in_queue = self.build_queue.sum_pending_workforce();
89      Some(f64::from(in_queue) / f64::from(turn))
90    } else {
91      None
92    }
93  }
94}
95
96impl WorkforceSource for Prefecture {}
97
98impl Default for Prefecture {
99  fn default() -> Self {
100    Self {
101      level: BuildingLevel::new(1),
102      enabled: true,
103      build_queue: PrefectureBuildQueue::default(),
104    }
105  }
106}
107
108check_total_resource_ratio!(
109  Prefecture::FOOD_RATIO,
110  Prefecture::IRON_RATIO,
111  Prefecture::STONE_RATIO,
112  Prefecture::WOOD_RATIO
113);