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