nil_core/military/squad/
mod.rs1pub mod size;
5
6use crate::error::{Error, Result};
7use crate::military::unit::stats::haul::Haul;
8use crate::military::unit::stats::power::{AttackPower, DefensePower, Power};
9use crate::military::unit::stats::speed::Speed;
10use crate::military::unit::{Unit, UnitBox, UnitId, UnitKind};
11use crate::ranking::score::Score;
12use crate::resources::maintenance::Maintenance;
13use crate::world::config::WorldConfig;
14use serde::{Deserialize, Serialize};
15use size::SquadSize;
16use std::fmt;
17use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
18
19#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
21#[serde(rename_all = "camelCase")]
22#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
23pub struct Squad {
24 unit: UnitBox,
25 size: SquadSize,
26}
27
28impl Squad {
29 pub fn new(id: UnitId, size: impl Into<SquadSize>) -> Self {
30 Self {
31 unit: UnitBox::from(id),
32 size: size.into(),
33 }
34 }
35
36 #[inline]
37 pub fn unit(&self) -> &dyn Unit {
38 self.unit.as_dyn()
39 }
40
41 #[inline]
42 pub fn id(&self) -> UnitId {
43 self.unit.id()
44 }
45
46 #[inline]
47 pub fn kind(&self) -> UnitKind {
48 self.unit.kind()
49 }
50
51 #[inline]
52 pub fn size(&self) -> SquadSize {
53 self.size
54 }
55
56 #[inline]
57 pub fn score(&self) -> Score {
58 self.size * self.unit.score()
59 }
60
61 #[inline]
62 pub fn is_empty(&self) -> bool {
63 self.size == 0u32
64 }
65
66 pub fn maintenance(&self) -> Maintenance {
67 let chunk = self.unit.chunk();
68 let c_size = chunk.size();
69 let c_maintenance = chunk.maintenance();
70 (self.size() * c_maintenance) / c_size
71 }
72
73 #[inline]
75 pub fn power(&self) -> Power {
76 self.unit.power() * self.size
77 }
78
79 #[inline]
80 pub fn attack(&self) -> AttackPower {
81 self.unit.attack() * self.size
82 }
83
84 #[inline]
85 pub fn defense(&self) -> DefensePower {
86 self.unit.defense() * self.size
87 }
88
89 #[inline]
90 pub fn speed(&self, config: &WorldConfig) -> Speed {
91 self.unit.speed(config)
92 }
93
94 #[inline]
95 pub fn haul(&self) -> Haul {
96 self.unit.haul() * self.size
97 }
98
99 pub fn checked_sub(&self, rhs: &Self) -> Result<Option<Self>> {
100 if self.unit == rhs.unit {
101 Ok(try { Self::new(self.id(), self.size.checked_sub(rhs.size)?) })
102 } else {
103 Err(Error::UnexpectedUnit(self.id(), rhs.id()))
104 }
105 }
106}
107
108impl fmt::Display for Squad {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 write!(f, "{} ({})", self.unit, self.size)
111 }
112}
113
114impl From<UnitId> for Squad {
115 fn from(id: UnitId) -> Self {
116 Squad::new(id, SquadSize::new(0))
117 }
118}
119
120impl Add for Squad {
121 type Output = Squad;
122
123 fn add(mut self, rhs: Self) -> Self::Output {
124 self += rhs;
125 self
126 }
127}
128
129impl Add<SquadSize> for Squad {
130 type Output = Squad;
131
132 fn add(mut self, rhs: SquadSize) -> Self::Output {
133 self += rhs;
134 self
135 }
136}
137
138impl AddAssign for Squad {
139 fn add_assign(&mut self, rhs: Self) {
140 if self.id() == rhs.id() {
141 self.size += rhs.size;
142 }
143 }
144}
145
146impl AddAssign<SquadSize> for Squad {
147 fn add_assign(&mut self, rhs: SquadSize) {
148 self.size += rhs;
149 }
150}
151
152impl Sub for Squad {
153 type Output = Squad;
154
155 fn sub(mut self, rhs: Self) -> Self::Output {
156 self -= rhs;
157 self
158 }
159}
160
161impl Sub<SquadSize> for Squad {
162 type Output = Squad;
163
164 fn sub(mut self, rhs: SquadSize) -> Self::Output {
165 self -= rhs;
166 self
167 }
168}
169
170impl SubAssign for Squad {
171 fn sub_assign(&mut self, rhs: Self) {
172 if self.id() == rhs.id() {
173 self.size -= rhs.size;
174 }
175 }
176}
177
178impl SubAssign<SquadSize> for Squad {
179 fn sub_assign(&mut self, rhs: SquadSize) {
180 self.size -= rhs;
181 }
182}
183
184impl Mul<f64> for Squad {
185 type Output = Squad;
186
187 fn mul(mut self, rhs: f64) -> Self::Output {
188 self *= rhs;
189 self
190 }
191}
192
193impl MulAssign<f64> for Squad {
194 fn mul_assign(&mut self, rhs: f64) {
195 self.size *= rhs;
196 }
197}