1use crate::ethic::Ethics;
5use crate::npc::bot::{Bot, BotId};
6use crate::npc::precursor::{Precursor, PrecursorId};
7use crate::player::{Player, PlayerId};
8use crate::resources::Resources;
9use crate::resources::gold::Gold;
10use crate::resources::influence::Influence;
11use derive_more::{TryUnwrap, Unwrap};
12use serde::{Deserialize, Serialize};
13use std::{cmp, fmt, mem};
14use strum::EnumIs;
15
16#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize, EnumIs)]
17#[serde(tag = "kind", rename_all = "kebab-case")]
18#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
19pub enum Ruler {
20 Bot { id: BotId },
21 Player { id: PlayerId },
22 Precursor { id: PrecursorId },
23}
24
25impl Ruler {
26 #[inline]
27 pub fn bot(&self) -> Option<&BotId> {
28 if let Self::Bot { id } = self { Some(id) } else { None }
29 }
30
31 #[inline]
32 pub fn player(&self) -> Option<&PlayerId> {
33 if let Self::Player { id } = self { Some(id) } else { None }
34 }
35
36 #[inline]
37 pub fn precursor(&self) -> Option<PrecursorId> {
38 if let Self::Precursor { id } = self { Some(*id) } else { None }
39 }
40
41 pub fn is_bot_and<F>(&self, f: F) -> bool
42 where
43 F: FnOnce(&BotId) -> bool,
44 {
45 self.bot().is_some_and(f)
46 }
47
48 pub fn is_player_and<F>(&self, f: F) -> bool
49 where
50 F: FnOnce(&PlayerId) -> bool,
51 {
52 self.player().is_some_and(f)
53 }
54
55 pub fn is_precursor_and<F>(&self, f: F) -> bool
56 where
57 F: FnOnce(PrecursorId) -> bool,
58 {
59 self.precursor().is_some_and(f)
60 }
61}
62
63impl AsRef<str> for Ruler {
64 fn as_ref(&self) -> &str {
65 match self {
66 Self::Bot { id } => id.as_str(),
67 Self::Player { id } => id.as_str(),
68 Self::Precursor { id } => id.as_ref(),
69 }
70 }
71}
72
73impl fmt::Display for Ruler {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 Self::Bot { id } => id.fmt(f),
77 Self::Player { id } => id.fmt(f),
78 Self::Precursor { id } => id.fmt(f),
79 }
80 }
81}
82
83impl From<&Bot> for Ruler {
84 fn from(bot: &Bot) -> Self {
85 Self::Bot { id: bot.id() }
86 }
87}
88
89impl From<BotId> for Ruler {
90 fn from(id: BotId) -> Self {
91 Self::Bot { id }
92 }
93}
94
95impl From<&BotId> for Ruler {
96 fn from(id: &BotId) -> Self {
97 Self::Bot { id: id.clone() }
98 }
99}
100
101impl From<&Player> for Ruler {
102 fn from(player: &Player) -> Self {
103 Self::Player { id: player.id() }
104 }
105}
106
107impl From<PlayerId> for Ruler {
108 fn from(id: PlayerId) -> Self {
109 Self::Player { id }
110 }
111}
112
113impl From<&PlayerId> for Ruler {
114 fn from(id: &PlayerId) -> Self {
115 Self::Player { id: id.clone() }
116 }
117}
118
119impl From<&dyn Precursor> for Ruler {
120 fn from(precursor: &dyn Precursor) -> Self {
121 Self::Precursor { id: precursor.id() }
122 }
123}
124
125impl<T: Precursor> From<&T> for Ruler {
126 fn from(precursor: &T) -> Self {
127 Self::Precursor { id: precursor.id() }
128 }
129}
130
131impl From<PrecursorId> for Ruler {
132 fn from(id: PrecursorId) -> Self {
133 Self::Precursor { id }
134 }
135}
136
137impl From<RulerRef<'_>> for Ruler {
138 fn from(ruler: RulerRef<'_>) -> Self {
139 match ruler {
140 RulerRef::Bot(bot) => Self::Bot { id: bot.id() },
141 RulerRef::Player(player) => Self::Player { id: player.id() },
142 RulerRef::Precursor(precursor) => Self::Precursor { id: precursor.id() },
143 }
144 }
145}
146
147impl From<RulerRefMut<'_>> for Ruler {
148 fn from(ruler: RulerRefMut<'_>) -> Self {
149 match ruler {
150 RulerRefMut::Bot(bot) => Self::Bot { id: bot.id() },
151 RulerRefMut::Player(player) => Self::Player { id: player.id() },
152 RulerRefMut::Precursor(precursor) => Self::Precursor { id: precursor.id() },
153 }
154 }
155}
156
157impl PartialOrd for Ruler {
158 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
159 Some(self.cmp(other))
160 }
161}
162
163impl Ord for Ruler {
164 fn cmp(&self, other: &Self) -> cmp::Ordering {
165 match (self, other) {
166 (Self::Bot { id: a }, Self::Bot { id: b }) => a.cmp(b),
167 (Self::Player { id: a }, Self::Player { id: b }) => a.cmp(b),
168 (Self::Precursor { id: a }, Self::Precursor { id: b }) => a.cmp(b),
169 (Self::Bot { .. }, Self::Player { .. }) => cmp::Ordering::Less,
170 (Self::Bot { .. }, Self::Precursor { .. }) => cmp::Ordering::Greater,
171 (Self::Player { .. }, _) => cmp::Ordering::Greater,
172 (Self::Precursor { .. }, _) => cmp::Ordering::Less,
173 }
174 }
175}
176
177#[derive(EnumIs, TryUnwrap, Unwrap)]
178#[try_unwrap(ref)]
179#[unwrap(ref)]
180pub enum RulerRef<'a> {
181 Bot(&'a Bot),
182 Player(&'a Player),
183 Precursor(&'a dyn Precursor),
184}
185
186impl<'a> RulerRef<'a> {
187 pub fn ethics(&self) -> Option<&'a Ethics> {
188 match self {
189 Self::Bot(bot) => Some(bot.ethics()),
190 Self::Player(..) => None,
191 Self::Precursor(precursor) => Some(precursor.ethics()),
192 }
193 }
194
195 pub fn resources(&self) -> Resources {
196 match self {
197 Self::Bot(bot) => bot.resources(),
198 Self::Player(player) => player.resources(),
199 Self::Precursor(precursor) => precursor.resources(),
200 }
201 }
202
203 #[inline]
204 pub fn has_resources(&self, resources: Resources) -> bool {
205 self
206 .resources()
207 .checked_sub(resources)
208 .is_some()
209 }
210
211 pub fn gold(&self) -> Gold {
212 match self {
213 Self::Bot(bot) => bot.gold(),
214 Self::Player(player) => player.gold(),
215 Self::Precursor(precursor) => precursor.gold(),
216 }
217 }
218
219 pub fn influence(&self) -> Influence {
220 match self {
221 Self::Bot(bot) => bot.influence(),
222 Self::Player(player) => player.influence(),
223 Self::Precursor(precursor) => precursor.influence(),
224 }
225 }
226}
227
228impl<'a> From<&'a Bot> for RulerRef<'a> {
229 fn from(bot: &'a Bot) -> Self {
230 Self::Bot(bot)
231 }
232}
233
234impl<'a> From<&'a Player> for RulerRef<'a> {
235 fn from(player: &'a Player) -> Self {
236 Self::Player(player)
237 }
238}
239
240impl<'a> From<&'a dyn Precursor> for RulerRef<'a> {
241 fn from(precursor: &'a dyn Precursor) -> Self {
242 Self::Precursor(precursor)
243 }
244}
245
246#[derive(EnumIs, TryUnwrap, Unwrap)]
247#[try_unwrap(ref)]
248#[unwrap(ref)]
249pub enum RulerRefMut<'a> {
250 Bot(&'a mut Bot),
251 Player(&'a mut Player),
252 Precursor(&'a mut dyn Precursor),
253}
254
255impl<'a> RulerRefMut<'a> {
256 pub fn resources_mut(&'a mut self) -> &'a mut Resources {
257 match self {
258 Self::Bot(bot) => bot.resources_mut(),
259 Self::Player(player) => player.resources_mut(),
260 Self::Precursor(precursor) => precursor.resources_mut(),
261 }
262 }
263
264 pub fn take_resources(&mut self) -> Resources {
265 match self {
266 Self::Bot(bot) => mem::take(bot.resources_mut()),
267 Self::Player(player) => mem::take(player.resources_mut()),
268 Self::Precursor(precursor) => mem::take(precursor.resources_mut()),
269 }
270 }
271}
272
273impl<'a> From<&'a mut Bot> for RulerRefMut<'a> {
274 fn from(bot: &'a mut Bot) -> Self {
275 Self::Bot(bot)
276 }
277}
278
279impl<'a> From<&'a mut Player> for RulerRefMut<'a> {
280 fn from(player: &'a mut Player) -> Self {
281 Self::Player(player)
282 }
283}
284
285impl<'a> From<&'a mut dyn Precursor> for RulerRefMut<'a> {
286 fn from(precursor: &'a mut dyn Precursor) -> Self {
287 Self::Precursor(precursor)
288 }
289}