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 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}