summaryrefslogtreecommitdiff
path: root/server/bot/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-09-14 16:21:37 +0200
committermetamuffin <metamuffin@disroot.org>2024-09-14 16:21:37 +0200
commit26af8f970dd5d28faf0e8244112a50505018eae0 (patch)
tree4181e64fc44620f540347242c2935dc661cb1aeb /server/bot/src
parent577c5324fa495adbde47a4d16bd39a4570a559b6 (diff)
downloadhurrycurry-26af8f970dd5d28faf0e8244112a50505018eae0.tar
hurrycurry-26af8f970dd5d28faf0e8244112a50505018eae0.tar.bz2
hurrycurry-26af8f970dd5d28faf0e8244112a50505018eae0.tar.zst
bot: frank
Diffstat (limited to 'server/bot/src')
-rw-r--r--server/bot/src/algos/frank.rs122
-rw-r--r--server/bot/src/algos/mod.rs3
2 files changed, 125 insertions, 0 deletions
diff --git a/server/bot/src/algos/frank.rs b/server/bot/src/algos/frank.rs
new file mode 100644
index 00000000..980d8c08
--- /dev/null
+++ b/server/bot/src/algos/frank.rs
@@ -0,0 +1,122 @@
+/*
+ Hurry Curry! - a game about cooking
+ Copyright 2024 metamuffin
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License only.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+*/
+use crate::{
+ pathfinding::{find_path_to_neighbour, Path},
+ BotAlgo, BotInput,
+};
+use hurrycurry_client_lib::Game;
+use hurrycurry_protocol::{glam::Vec2, Message, PacketS, PlayerID};
+use rand::{seq::IndexedRandom, thread_rng};
+
+#[derive(Default)]
+pub struct Frank {
+ sleep: f32,
+ idle: f32,
+ idle_dir: f32,
+
+ target: Option<PlayerID>,
+ path: Option<Path>,
+}
+
+const MESSAGES: &[fn(&str) -> String] = &[
+ |_name| format!("Work faster, {_name}!"),
+ |_name| format!("Quick! There is no time for chit-chat!"),
+ |_name| format!("Look what a mess you've made! Clean this up immediatly!"),
+ |_name| format!("Don't let the customers starve!"),
+ |_name| format!("You are wasting me money, {_name}!"),
+ |_name| format!("I'm not paying you to stand around!"),
+ |_name| format!("Get back to work, {_name}!"),
+ |_name| format!("You're FIRED!"),
+];
+
+impl BotAlgo for Frank {
+ fn tick(&mut self, me: PlayerID, game: &Game, dt: f32) -> BotInput {
+ let Some(player) = game.players.get(&me) else {
+ return BotInput::default();
+ };
+
+ if self.sleep > 0. {
+ self.sleep -= dt;
+ return BotInput::default();
+ }
+ if self.idle > 0. {
+ self.idle -= dt;
+ self.idle_dir += self.idle.sin() * dt * (self.idle / 10.).fract() * 10.;
+ return BotInput {
+ direction: Vec2::from_angle(self.idle_dir),
+ ..Default::default()
+ };
+ }
+
+ let pos = player.movement.position;
+
+ if let Some(target) = self.target {
+ if let Some(player) = game.players.get(&target) {
+ let tpos = player.movement.position;
+
+ if let Some(path) = &mut self.path {
+ let direction = path.next_direction(pos, dt);
+ if path.is_stuck() {
+ self.path = None;
+ } else if path.is_done() {
+ self.path = None;
+ if pos.distance(tpos) < 2. {
+ self.sleep = 8.;
+ self.idle = 15.;
+ let message = MESSAGES.choose(&mut thread_rng()).unwrap()(&player.name);
+ return BotInput {
+ extra: vec![PacketS::Communicate {
+ player: me,
+ message: Some(Message::Text(message)),
+ timeout: Some(3.),
+ }],
+ ..Default::default()
+ };
+ }
+ } else {
+ return BotInput {
+ direction,
+ boost: false,
+ interact: None,
+ ..Default::default()
+ };
+ }
+ } else if let Some(path) =
+ find_path_to_neighbour(&game.walkable, pos.as_ivec2(), tpos.as_ivec2())
+ {
+ self.path = Some(path);
+ }
+ } else {
+ self.target = None;
+ }
+ } else if let Some(target) = find_chef(game, me) {
+ self.target = Some(target);
+ }
+ BotInput::default()
+ }
+}
+
+fn find_chef(game: &Game, me: PlayerID) -> Option<PlayerID> {
+ let chefs = game
+ .players
+ .iter()
+ .filter(|(i, p)| p.character >= 0 && **i != me)
+ .map(|(i, _)| *i)
+ .collect::<Vec<_>>();
+ chefs.choose(&mut thread_rng()).copied()
+}
diff --git a/server/bot/src/algos/mod.rs b/server/bot/src/algos/mod.rs
index 54cdd495..bb1d615b 100644
--- a/server/bot/src/algos/mod.rs
+++ b/server/bot/src/algos/mod.rs
@@ -19,15 +19,18 @@ mod customer;
mod simple;
mod test;
mod waiter;
+pub mod frank;
pub use customer::Customer;
pub use simple::Simple;
pub use test::Test;
pub use waiter::Waiter;
+pub use frank::Frank;
pub const ALGO_CONSTRUCTORS: &'static [(&'static str, fn() -> crate::DynBotAlgo)] = &[
("test", || Box::new(Test::default())),
("simple", || Box::new(Simple::default())),
("waiter", || Box::new(Waiter::default())),
("customer", || Box::new(Customer::default())),
+ ("frank", || Box::new(Frank::default())),
];