diff options
Diffstat (limited to 'server/bot')
-rw-r--r-- | server/bot/src/algos/customer.rs | 219 | ||||
-rw-r--r-- | server/bot/src/algos/mod.rs | 3 | ||||
-rw-r--r-- | server/bot/src/algos/simple.rs | 1 | ||||
-rw-r--r-- | server/bot/src/algos/test.rs | 1 | ||||
-rw-r--r-- | server/bot/src/algos/waiter.rs | 1 | ||||
-rw-r--r-- | server/bot/src/lib.rs | 3 | ||||
-rw-r--r-- | server/bot/src/main.rs | 13 |
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)); } |