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::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 From<&Bot> for Ruler {
63  fn from(bot: &Bot) -> Self {
64    Self::Bot { id: bot.id() }
65  }
66}
67
68impl From<BotId> for Ruler {
69  fn from(id: BotId) -> Self {
70    Self::Bot { id }
71  }
72}
73
74impl From<&BotId> for Ruler {
75  fn from(id: &BotId) -> Self {
76    Self::Bot { id: id.clone() }
77  }
78}
79
80impl From<&Player> for Ruler {
81  fn from(player: &Player) -> Self {
82    Self::Player { id: player.id() }
83  }
84}
85
86impl From<PlayerId> for Ruler {
87  fn from(id: PlayerId) -> Self {
88    Self::Player { id }
89  }
90}
91
92impl From<&PlayerId> for Ruler {
93  fn from(id: &PlayerId) -> Self {
94    Self::Player { id: id.clone() }
95  }
96}
97
98impl From<&dyn Precursor> for Ruler {
99  fn from(precursor: &dyn Precursor) -> Self {
100    Self::Precursor { id: precursor.id() }
101  }
102}
103
104impl<T: Precursor> From<&T> for Ruler {
105  fn from(precursor: &T) -> Self {
106    Self::Precursor { id: precursor.id() }
107  }
108}
109
110impl From<PrecursorId> for Ruler {
111  fn from(id: PrecursorId) -> Self {
112    Self::Precursor { id }
113  }
114}
115
116impl From<RulerRef<'_>> for Ruler {
117  fn from(ruler: RulerRef<'_>) -> Self {
118    match ruler {
119      RulerRef::Bot(bot) => Self::Bot { id: bot.id() },
120      RulerRef::Player(player) => Self::Player { id: player.id() },
121      RulerRef::Precursor(precursor) => Self::Precursor { id: precursor.id() },
122    }
123  }
124}
125
126impl From<RulerRefMut<'_>> for Ruler {
127  fn from(ruler: RulerRefMut<'_>) -> Self {
128    match ruler {
129      RulerRefMut::Bot(bot) => Self::Bot { id: bot.id() },
130      RulerRefMut::Player(player) => Self::Player { id: player.id() },
131      RulerRefMut::Precursor(precursor) => Self::Precursor { id: precursor.id() },
132    }
133  }
134}
135
136#[derive(EnumIs, TryUnwrap, Unwrap)]
137#[try_unwrap(ref)]
138#[unwrap(ref)]
139pub enum RulerRef<'a> {
140  Bot(&'a Bot),
141  Player(&'a Player),
142  Precursor(&'a dyn Precursor),
143}
144
145impl<'a> RulerRef<'a> {
146  pub fn ethics(&self) -> Option<&'a Ethics> {
147    match self {
148      Self::Bot(bot) => Some(bot.ethics()),
149      Self::Player(..) => None,
150      Self::Precursor(precursor) => Some(precursor.ethics()),
151    }
152  }
153
154  pub fn resources(&'a self) -> &'a Resources {
155    match self {
156      Self::Bot(bot) => bot.resources(),
157      Self::Player(player) => player.resources(),
158      Self::Precursor(precursor) => precursor.resources(),
159    }
160  }
161
162  #[inline]
163  pub fn has_resources(&self, resources: &Resources) -> bool {
164    self
165      .resources()
166      .checked_sub(resources)
167      .is_some()
168  }
169
170  pub fn influence(&self) -> Influence {
171    match self {
172      Self::Bot(bot) => bot.influence(),
173      Self::Player(player) => player.influence(),
174      Self::Precursor(precursor) => precursor.influence(),
175    }
176  }
177}
178
179impl<'a> From<&'a Bot> for RulerRef<'a> {
180  fn from(bot: &'a Bot) -> Self {
181    Self::Bot(bot)
182  }
183}
184
185impl<'a> From<&'a Player> for RulerRef<'a> {
186  fn from(player: &'a Player) -> Self {
187    Self::Player(player)
188  }
189}
190
191impl<'a> From<&'a dyn Precursor> for RulerRef<'a> {
192  fn from(precursor: &'a dyn Precursor) -> Self {
193    Self::Precursor(precursor)
194  }
195}
196
197#[derive(EnumIs, TryUnwrap, Unwrap)]
198#[try_unwrap(ref)]
199#[unwrap(ref)]
200pub enum RulerRefMut<'a> {
201  Bot(&'a mut Bot),
202  Player(&'a mut Player),
203  Precursor(&'a mut dyn Precursor),
204}
205
206impl<'a> RulerRefMut<'a> {
207  pub fn resources_mut(&'a mut self) -> &'a mut Resources {
208    match self {
209      Self::Bot(bot) => bot.resources_mut(),
210      Self::Player(player) => player.resources_mut(),
211      Self::Precursor(precursor) => precursor.resources_mut(),
212    }
213  }
214
215  pub fn take_resources(&mut self) -> Resources {
216    match self {
217      Self::Bot(bot) => mem::take(bot.resources_mut()),
218      Self::Player(player) => mem::take(player.resources_mut()),
219      Self::Precursor(precursor) => mem::take(precursor.resources_mut()),
220    }
221  }
222}
223
224impl<'a> From<&'a mut Bot> for RulerRefMut<'a> {
225  fn from(bot: &'a mut Bot) -> Self {
226    Self::Bot(bot)
227  }
228}
229
230impl<'a> From<&'a mut Player> for RulerRefMut<'a> {
231  fn from(player: &'a mut Player) -> Self {
232    Self::Player(player)
233  }
234}
235
236impl<'a> From<&'a mut dyn Precursor> for RulerRefMut<'a> {
237  fn from(precursor: &'a mut dyn Precursor) -> Self {
238    Self::Precursor(precursor)
239  }
240}