aboutsummaryrefslogtreecommitdiff
path: root/server/bot
diff options
context:
space:
mode:
Diffstat (limited to 'server/bot')
-rw-r--r--server/bot/src/algos/customer.rs219
-rw-r--r--server/bot/src/algos/mod.rs3
-rw-r--r--server/bot/src/algos/simple.rs1
-rw-r--r--server/bot/src/algos/test.rs1
-rw-r--r--server/bot/src/algos/waiter.rs1
-rw-r--r--server/bot/src/lib.rs3
-rw-r--r--server/bot/src/main.rs13
7 files changed, 239 insertions, 2 deletions
diff --git a/server/bot/src/algos/customer.rs b/server/bot/src/algos/customer.rs
new file mode 100644
index 00000000..167fc0d7
--- /dev/null
+++ b/server/bot/src/algos/customer.rs
@@ -0,0 +1,219 @@
+/*
+ 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::Path, BotAlgo, BotInput};
+use hurrycurry_protocol::{glam::IVec2, DemandIndex};
+
+#[derive(Debug, Clone)]
+pub enum Customer {
+ New,
+ Entering {
+ path: Path,
+ chair: IVec2,
+ },
+ Waiting {
+ demand: DemandIndex,
+ chair: IVec2,
+ timeout: f32,
+ },
+ Eating {
+ demand: DemandIndex,
+ target: IVec2,
+ progress: f32,
+ chair: IVec2,
+ },
+ Exiting {
+ path: Path,
+ },
+}
+
+impl Default for Customer {
+ fn default() -> Self {
+ Customer::New
+ }
+}
+
+impl BotAlgo for Customer {
+ fn tick(
+ &mut self,
+ me: hurrycurry_protocol::PlayerID,
+ game: &hurrycurry_client_lib::Game,
+ dt: f32,
+ ) -> BotInput {
+ let _ = (me, game, dt);
+ BotInput::default()
+ // let Some(playerdata) = game.players.get_mut(&player) else {
+ // return BotInput::default();
+ // };
+ // match state {
+ // let chair = self.select_chair().ok_or(anyhow!("no free chair found"))?;
+ // let from = game.data.customer_spawn.as_ivec2();
+ // let path = find_path(&game.walkable, from, chair)
+ // .ok_or(anyhow!("no path from {from} to {chair}"))?;
+ // info!("{id:?} -> entering");
+
+ // CustomerState::Entering { path, chair } => {
+ // playerdata
+ // .movement
+ // .input(path.next_direction(playerdata.position()), false);
+ // if path.is_done() {
+ // let demand = DemandIndex(random::<u32>() as usize % self.demands.len());
+ // self.cpackets.push_back(PacketS::Communicate {
+ // message: Some(Message::Item(self.demands[demand.0].from)),
+ // persist: true,
+ // player,
+ // });
+ // info!("{player:?} -> waiting");
+ // *state = CustomerState::Waiting {
+ // chair: *chair,
+ // timeout: 90. + random::<f32>() * 60.,
+ // demand,
+ // };
+ // }
+ // }
+ // CustomerState::Waiting {
+ // chair,
+ // demand,
+ // timeout,
+ // } => {
+ // playerdata
+ // .movement
+ // .input((chair.as_vec2() + 0.5) - playerdata.position(), false);
+ // *timeout -= dt;
+ // if *timeout <= 0. {
+ // self.cpackets.push_back(PacketS::Communicate {
+ // message: None,
+ // persist: true,
+ // player,
+ // });
+ // self.cpackets.push_back(PacketS::Communicate {
+ // message: Some(Message::Effect("angry".to_string())),
+ // persist: false,
+ // player,
+ // });
+ // let path = find_path(
+ // &game.walkable,
+ // playerdata.position().as_ivec2(),
+ // game.data.customer_spawn.as_ivec2(),
+ // )
+ // .expect("no path to exit");
+ // *self.chairs.get_mut(chair).unwrap() = true;
+ // game.score.demands_failed += 1;
+ // game.score.points -= 1;
+ // game.score_changed = true;
+ // info!("{player:?} -> exiting");
+ // *state = CustomerState::Exiting { path }
+ // } else {
+ // let demand_data = &self.demands[demand.0];
+ // let demand_pos = [IVec2::NEG_X, IVec2::NEG_Y, IVec2::X, IVec2::Y]
+ // .into_iter()
+ // .find_map(|off| {
+ // let pos = *chair + off;
+ // if game
+ // .tiles
+ // .get(&pos)
+ // .map(|t| {
+ // t.item
+ // .as_ref()
+ // .map(|i| i.kind == demand_data.from)
+ // .unwrap_or_default()
+ // })
+ // .unwrap_or_default()
+ // {
+ // Some(pos)
+ // } else {
+ // None
+ // }
+ // });
+ // if let Some(pos) = demand_pos {
+ // self.cpackets.push_back(PacketS::Communicate {
+ // persist: true,
+ // message: None,
+ // player,
+ // });
+ // self.cpackets.push_back(PacketS::Communicate {
+ // message: Some(Message::Effect("satisfied".to_string())),
+ // persist: false,
+ // player,
+ // });
+ // self.cpackets.push_back(PacketS::Interact {
+ // pos: Some(pos),
+ // player,
+ // });
+ // self.cpackets
+ // .push_back(PacketS::Interact { pos: None, player });
+ // info!("{player:?} -> eating");
+ // *state = CustomerState::Eating {
+ // demand: *demand,
+ // target: pos,
+ // progress: 0.,
+ // chair: *chair,
+ // }
+ // }
+ // }
+ // }
+ // CustomerState::Eating {
+ // demand,
+ // target,
+ // progress,
+ // chair,
+ // } => {
+ // playerdata
+ // .movement
+ // .input((chair.as_vec2() + 0.5) - playerdata.position(), false);
+ // let demand = &self.demands[demand.0];
+ // *progress += dt / demand.duration;
+ // if *progress >= 1. {
+ // self.cpackets.push_back(PacketS::ReplaceHand {
+ // player,
+ // item: demand.to,
+ // });
+ // if demand.to.is_some() {
+ // self.cpackets.push_back(PacketS::Interact {
+ // player,
+ // pos: Some(*target),
+ // });
+ // self.cpackets
+ // .push_back(PacketS::Interact { player, pos: None });
+ // }
+ // let path = find_path(
+ // &game.walkable,
+ // playerdata.position().as_ivec2(),
+ // game.data.customer_spawn.as_ivec2(),
+ // )
+ // .ok_or(anyhow!("no path to exit"))?;
+ // *self.chairs.get_mut(chair).unwrap() = true;
+ // game.score.demands_completed += 1;
+ // game.score.points += demand.points;
+ // game.score_changed = true;
+ // info!("{player:?} -> exiting");
+ // *state = CustomerState::Exiting { path }
+ // }
+ // }
+ // CustomerState::Exiting { path } => {
+ // playerdata
+ // .movement
+ // .input(path.next_direction(playerdata.position()), false);
+ // if path.is_done() {
+ // info!("{player:?} -> leave");
+ // self.cpackets.push_back(PacketS::Leave { player });
+ // customers_to_remove.push(player);
+ // }
+ // }
+ // }
+ }
+}
diff --git a/server/bot/src/algos/mod.rs b/server/bot/src/algos/mod.rs
index 7b165da4..d3aba8f4 100644
--- a/server/bot/src/algos/mod.rs
+++ b/server/bot/src/algos/mod.rs
@@ -15,10 +15,12 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+mod customer;
mod simple;
mod test;
mod waiter;
+pub use customer::Customer;
pub use simple::Simple;
pub use test::Test;
pub use waiter::Waiter;
@@ -27,4 +29,5 @@ pub const ALGO_CONSTRUCTORS: &'static [(&'static str, fn() -> Box<dyn crate::Bot
("test", || Box::new(Test::default())),
("simple", || Box::new(Simple::default())),
("waiter", || Box::new(Waiter::default())),
+ ("customer", || Box::new(Customer::default())),
];
diff --git a/server/bot/src/algos/simple.rs b/server/bot/src/algos/simple.rs
index 22ed50bd..6092e772 100644
--- a/server/bot/src/algos/simple.rs
+++ b/server/bot/src/algos/simple.rs
@@ -68,6 +68,7 @@ impl BotAlgo for Simple {
direction,
boost: false,
interact: if arrived { Some(target) } else { None },
+ ..Default::default()
};
}
diff --git a/server/bot/src/algos/test.rs b/server/bot/src/algos/test.rs
index d56aa00b..dee4cb88 100644
--- a/server/bot/src/algos/test.rs
+++ b/server/bot/src/algos/test.rs
@@ -41,6 +41,7 @@ impl BotAlgo for Test {
direction,
boost: false,
interact: None,
+ ..Default::default()
};
} else {
if let Some((item, near)) = find_demand(game) {
diff --git a/server/bot/src/algos/waiter.rs b/server/bot/src/algos/waiter.rs
index 7a25108b..ced3097b 100644
--- a/server/bot/src/algos/waiter.rs
+++ b/server/bot/src/algos/waiter.rs
@@ -56,6 +56,7 @@ impl BotAlgo for Waiter {
direction,
boost: false,
interact: if arrived { Some(target) } else { None },
+ ..Default::default()
};
}
Context {
diff --git a/server/bot/src/lib.rs b/server/bot/src/lib.rs
index 385e2334..543a1062 100644
--- a/server/bot/src/lib.rs
+++ b/server/bot/src/lib.rs
@@ -30,7 +30,10 @@ pub struct BotInput {
pub direction: Vec2,
pub boost: bool,
pub interact: Option<IVec2>,
+ pub leave: bool,
}
+
+pub type DynBotAlgo = Box<dyn BotAlgo + Send + Sync + 'static>;
pub trait BotAlgo {
fn tick(&mut self, me: PlayerID, game: &Game, dt: f32) -> BotInput;
}
diff --git a/server/bot/src/main.rs b/server/bot/src/main.rs
index 9ecd0a84..cf115358 100644
--- a/server/bot/src/main.rs
+++ b/server/bot/src/main.rs
@@ -57,6 +57,7 @@ fn main() -> Result<()> {
network.queue_out.push_back(PacketS::Join {
name: format!("{}-bot", args.username.clone().unwrap_or(args.algo.clone())),
character: args.character,
+ id: None,
});
let mut bots = Vec::new();
@@ -85,12 +86,19 @@ fn main() -> Result<()> {
game.apply_packet(packet);
}
- for b in &mut bots {
+ bots.retain_mut(|b| {
let BotInput {
direction,
boost,
interact,
+ leave,
} = b.state.tick(b.id, &game, dt);
+
+ if leave {
+ network.queue_out.push_back(PacketS::Leave { player: b.id });
+ return false;
+ }
+
if interact.is_some() != b.interacting {
b.interacting = interact.is_some();
network.queue_out.push_back(PacketS::Interact {
@@ -104,7 +112,8 @@ fn main() -> Result<()> {
boost,
pos: None,
});
- }
+ true
+ });
sleep(Duration::from_secs_f32(dt));
}