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