Skip to main content

nil_core/
ruler.rs

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