Skip to main content

nil_core/npc/bot/
mod.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4use crate::error::{Error, Result};
5use crate::ethic::Ethics;
6use crate::resources::Resources;
7use crate::resources::influence::Influence;
8use derive_more::{Display, From, Into};
9use serde::{Deserialize, Serialize};
10use std::borrow::{Borrow, Cow};
11use std::collections::HashMap;
12use std::ops::Deref;
13use std::sync::Arc;
14
15#[derive(Clone, Debug, Default, Deserialize, Serialize)]
16#[serde(rename_all = "camelCase")]
17pub struct BotManager(HashMap<BotId, Bot>);
18
19impl BotManager {
20  pub(crate) fn manage(&mut self, id: BotId) -> Result<()> {
21    if self.0.contains_key(&id) {
22      return Err(Error::BotAlreadySpawned(id));
23    }
24
25    self.0.insert(id.clone(), Bot::new(id));
26
27    Ok(())
28  }
29
30  pub fn bot(&self, id: &BotId) -> Result<&Bot> {
31    self
32      .0
33      .get(id)
34      .ok_or_else(|| Error::BotNotFound(id.clone()))
35  }
36
37  pub(crate) fn bot_mut(&mut self, id: &BotId) -> Result<&mut Bot> {
38    self
39      .0
40      .get_mut(id)
41      .ok_or_else(|| Error::BotNotFound(id.clone()))
42  }
43
44  pub fn bots(&self) -> impl Iterator<Item = &Bot> {
45    self.0.values()
46  }
47}
48
49#[derive(Clone, Debug, Deserialize, Serialize)]
50#[serde(rename_all = "camelCase")]
51#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
52pub struct Bot {
53  id: BotId,
54  ethics: Ethics,
55  resources: Resources,
56  influence: Influence,
57}
58
59impl Bot {
60  pub(crate) fn new(id: BotId) -> Self {
61    Self {
62      id,
63      ethics: Ethics::random(),
64      resources: Resources::BOT.clone(),
65      influence: Influence::MIN,
66    }
67  }
68
69  #[inline]
70  pub fn id(&self) -> BotId {
71    self.id.clone()
72  }
73
74  #[inline]
75  pub fn ethics(&self) -> &Ethics {
76    &self.ethics
77  }
78
79  #[inline]
80  pub(crate) fn ethics_mut(&mut self) -> &mut Ethics {
81    &mut self.ethics
82  }
83
84  #[inline]
85  pub fn resources(&self) -> &Resources {
86    &self.resources
87  }
88
89  pub(crate) fn resources_mut(&mut self) -> &mut Resources {
90    &mut self.resources
91  }
92
93  #[inline]
94  pub fn influence(&self) -> Influence {
95    self.influence
96  }
97}
98
99#[derive(Debug, Display, PartialEq, Eq, Hash, From, Into, Deserialize, Serialize)]
100#[from(String, &str, Arc<str>, Box<str>, Cow<'_, str>)]
101#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
102pub struct BotId(Arc<str>);
103
104impl Clone for BotId {
105  fn clone(&self) -> Self {
106    Self(Arc::clone(&self.0))
107  }
108}
109
110impl AsRef<str> for BotId {
111  fn as_ref(&self) -> &str {
112    self.0.as_str()
113  }
114}
115
116impl Deref for BotId {
117  type Target = str;
118
119  fn deref(&self) -> &Self::Target {
120    self.0.as_str()
121  }
122}
123
124impl Borrow<str> for BotId {
125  fn borrow(&self) -> &str {
126    self.0.as_str()
127  }
128}
129
130impl From<BotId> for String {
131  fn from(value: BotId) -> Self {
132    String::from(value.0.as_ref())
133  }
134}
135
136#[derive(Clone, Debug, Deserialize, Serialize)]
137#[serde(rename_all = "camelCase")]
138#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
139pub struct PublicBot {
140  id: BotId,
141}
142
143impl From<&Bot> for PublicBot {
144  fn from(bot: &Bot) -> Self {
145    Self { id: bot.id.clone() }
146  }
147}