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