diff options
author | metamuffin <metamuffin@disroot.org> | 2024-08-13 16:03:19 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-08-13 16:03:38 +0200 |
commit | 8d83fcef94ce1558a2c0e29e8be6c966c7e10a5b (patch) | |
tree | f674b2ea255a5d80ef7ee320e313a02a9a72bc4b | |
parent | 0f94e292bde8b9614aa48a6ba87f1a8d927b8133 (diff) | |
download | hurrycurry-8d83fcef94ce1558a2c0e29e8be6c966c7e10a5b.tar hurrycurry-8d83fcef94ce1558a2c0e29e8be6c966c7e10a5b.tar.bz2 hurrycurry-8d83fcef94ce1558a2c0e29e8be6c966c7e10a5b.tar.zst |
trying to reimplement customers
-rw-r--r-- | server/bot/src/algos/customer.rs | 368 | ||||
-rw-r--r-- | server/bot/src/lib.rs | 5 | ||||
-rw-r--r-- | server/protocol/src/lib.rs | 9 | ||||
-rw-r--r-- | server/src/data/mod.rs | 11 |
4 files changed, 213 insertions, 180 deletions
diff --git a/server/bot/src/algos/customer.rs b/server/bot/src/algos/customer.rs index 167fc0d7..69712ba8 100644 --- a/server/bot/src/algos/customer.rs +++ b/server/bot/src/algos/customer.rs @@ -15,8 +15,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -use crate::{pathfinding::Path, BotAlgo, BotInput}; -use hurrycurry_protocol::{glam::IVec2, DemandIndex}; +use crate::{ + pathfinding::{find_path, Path}, + BotAlgo, BotInput, +}; +use hurrycurry_client_lib::Game; +use hurrycurry_protocol::{glam::IVec2, DemandIndex, Message, PacketS, PlayerID}; +use log::info; +use rand::random; #[derive(Debug, Clone)] pub enum Customer { @@ -48,172 +54,198 @@ impl Default for Customer { } impl BotAlgo for Customer { - fn tick( - &mut self, - me: hurrycurry_protocol::PlayerID, - game: &hurrycurry_client_lib::Game, - dt: f32, - ) -> BotInput { + fn tick(&mut self, me: PlayerID, game: &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); - // } - // } - // } + let Some(playerdata) = game.players.get_mut(&me) else { + return BotInput::default(); + }; + let pos = playerdata.movement.position; + match self { + Customer::New => { + if let Some((chair, _)) = game + .tiles + .iter() + .find(|(_, t)| game.data.tile_name(t.kind) == "chair") + { + if let Some(path) = find_path(&game.walkable, pos.as_ivec2(), *chair) { + info!("{me:?} -> entering"); + *self = Customer::Entering { + path, + chair: *chair, + }; + } + } + BotInput::default() + } + Customer::Entering { path, chair } => { + let direction = path.next_direction(pos); + if path.is_done() { + let demand = DemandIndex(random::<u32>() as usize % game.data.demands.len()); + info!("{me:?} -> waiting"); + *self = Customer::Waiting { + chair: *chair, + timeout: 90. + random::<f32>() * 60., + demand, + }; + BotInput { + extra: vec![PacketS::Communicate { + message: Some(Message::Item(game.data.demands[demand.0].input)), + persist: true, + player: me, + }], + ..Default::default() + } + } else { + BotInput { + direction, + ..Default::default() + } + } + } + Customer::Waiting { + chair, + demand, + timeout, + } => { + playerdata + .movement + .input((chair.as_vec2() + 0.5) - pos, false); + *timeout -= dt; + if *timeout <= 0. { + let path = find_path( + &game.walkable, + pos.as_ivec2(), + pos.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!("{me:?} -> exiting"); + *self = Customer::Exiting { path }; + BotInput { + extra: vec![ + PacketS::Communicate { + message: None, + persist: true, + player: me, + }, + PacketS::Communicate { + message: Some(Message::Effect("angry".to_string())), + persist: false, + player: me, + }, + ], + ..Default::default() + } + } else { + let demand_data = &game.data.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.input) + .unwrap_or_default() + }) + .unwrap_or_default() + { + Some(pos) + } else { + None + } + }); + if let Some(pos) = demand_pos { + info!("{me:?} -> eating"); + *self = Customer::Eating { + demand: *demand, + target: pos, + progress: 0., + chair: *chair, + }; + BotInput { + extra: vec![ + PacketS::Communicate { + persist: true, + message: None, + player: me, + }, + PacketS::Communicate { + message: Some(Message::Effect("satisfied".to_string())), + persist: false, + player: me, + }, + PacketS::Interact { + pos: Some(pos), + player: me, + }, + PacketS::Interact { + pos: None, + player: me, + }, + ], + ..Default::default() + } + } else { + BotInput::default() + } + } + } + Customer::Eating { + demand, + target, + progress, + chair, + } => { + playerdata + .movement + .input((chair.as_vec2() + 0.5) - playerdata.position(), false); + let demand = &game.data.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 = Customer::Exiting { path } + } + } + Customer::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/lib.rs b/server/bot/src/lib.rs index 543a1062..b2334333 100644 --- a/server/bot/src/lib.rs +++ b/server/bot/src/lib.rs @@ -22,15 +22,16 @@ pub mod pathfinding; use hurrycurry_client_lib::Game; use hurrycurry_protocol::{ glam::{IVec2, Vec2}, - PlayerID, + PacketS, PlayerID, }; -#[derive(Default, Clone, Copy)] +#[derive(Default, Clone)] pub struct BotInput { pub direction: Vec2, pub boost: bool, pub interact: Option<IVec2>, pub leave: bool, + pub extra: Vec<PacketS>, } pub type DynBotAlgo = Box<dyn BotAlgo + Send + Sync + 'static>; diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index 695d45cf..80d94192 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -69,6 +69,14 @@ pub struct MapMetadata { difficulty: i32, } +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] +pub struct Demand { + pub input: ItemIndex, + pub output: Option<ItemIndex>, + pub duration: f32, + pub points: i64, +} + #[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, Default)] #[rustfmt::skip] pub struct Gamedata { @@ -79,6 +87,7 @@ pub struct Gamedata { pub tile_interact: Vec<bool>, pub maps: HashMap<String, MapMetadata>, pub recipes: Vec<Recipe>, + pub demands: Vec<Demand>, } #[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] diff --git a/server/src/data/mod.rs b/server/src/data/mod.rs index 6555fbc4..f7f184d2 100644 --- a/server/src/data/mod.rs +++ b/server/src/data/mod.rs @@ -92,18 +92,9 @@ pub struct DemandDecl { points: i64, } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Demand { - pub from: ItemIndex, - pub to: Option<ItemIndex>, - pub duration: f32, - pub points: i64, -} - #[derive(Debug,Clone, Default)] #[rustfmt::skip] pub struct Serverdata { - pub demands: Vec<Demand>, pub spec: String, pub initial_map: HashMap<IVec2, (TileIndex, Option<ItemIndex>)>, pub chef_spawn: Vec2, @@ -301,11 +292,11 @@ pub fn build_data( tile_interact, recipes, item_names, + demands, tile_names, }, Serverdata { spec, - demands, initial_map, chef_spawn, customer_spawn, |