diff options
| author | metamuffin <metamuffin@disroot.org> | 2025-10-20 00:56:32 +0200 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2025-10-20 00:56:32 +0200 |
| commit | f8d95d074c36ec35eee8def73b8d9f2b83c922cb (patch) | |
| tree | 0ab9faba2784a64eeb89688b292b831c50442a0e /server | |
| parent | 8961db68d063a2dda427e80601650e4674772685 (diff) | |
| download | hurrycurry-f8d95d074c36ec35eee8def73b8d9f2b83c922cb.tar hurrycurry-f8d95d074c36ec35eee8def73b8d9f2b83c922cb.tar.bz2 hurrycurry-f8d95d074c36ec35eee8def73b8d9f2b83c922cb.tar.zst | |
Pathfinding avoids chairs
Diffstat (limited to 'server')
| -rw-r--r-- | server/bot/src/algos/customer.rs | 9 | ||||
| -rw-r--r-- | server/bot/src/algos/frank.rs | 2 | ||||
| -rw-r--r-- | server/bot/src/algos/simple.rs | 2 | ||||
| -rw-r--r-- | server/bot/src/algos/test.rs | 2 | ||||
| -rw-r--r-- | server/bot/src/pathfinding.rs | 24 | ||||
| -rw-r--r-- | server/data/src/book/diagram_layout.rs | 1 | ||||
| -rw-r--r-- | server/game-core/src/interaction.rs | 6 | ||||
| -rw-r--r-- | server/game-core/src/lib.rs | 5 | ||||
| -rw-r--r-- | server/src/entity/tag_minigame.rs | 2 | ||||
| -rw-r--r-- | server/src/server.rs | 4 |
10 files changed, 32 insertions, 25 deletions
diff --git a/server/bot/src/algos/customer.rs b/server/bot/src/algos/customer.rs index 06dc373c..5a6f71f7 100644 --- a/server/bot/src/algos/customer.rs +++ b/server/bot/src/algos/customer.rs @@ -112,7 +112,7 @@ impl CustomerState { .map(|(p, _)| *p) .collect::<Vec<_>>(); if let Some(&chair) = chairs.get(random::<usize>(..) % chairs.len().max(1)) - && let Some(path) = find_path(&game.walkable, pos.as_ivec2(), chair) + && let Some(path) = find_path(game, pos.as_ivec2(), chair) { debug!("{me:?} -> entering"); *self = CustomerState::Entering { @@ -185,7 +185,7 @@ impl CustomerState { *self = CustomerState::New; BotInput::default() } else if path.is_stuck() { - if let Some(path) = find_path(&game.walkable, pos.as_ivec2(), *origin) { + if let Some(path) = find_path(game, pos.as_ivec2(), *origin) { *self = CustomerState::Exiting { path }; } BotInput::default() @@ -208,8 +208,7 @@ impl CustomerState { *timeout -= dt; *check += 1; if *timeout <= 0. { - let path = find_path(&game.walkable, pos.as_ivec2(), *origin) - .expect("no path to exit"); + let path = find_path(game, pos.as_ivec2(), *origin).expect("no path to exit"); debug!("{me:?} -> exiting"); *self = CustomerState::Exiting { path }; return BotInput { @@ -381,7 +380,7 @@ impl CustomerState { .is_some_and(|pl| pl.items[0].is_none()) // TODO index out of bounds? { - if let Some(path) = find_path(&game.walkable, pos.as_ivec2(), *origin) { + if let Some(path) = find_path(game, pos.as_ivec2(), *origin) { *self = CustomerState::Exiting { path }; } BotInput::default() diff --git a/server/bot/src/algos/frank.rs b/server/bot/src/algos/frank.rs index 3515f96d..489417a6 100644 --- a/server/bot/src/algos/frank.rs +++ b/server/bot/src/algos/frank.rs @@ -90,7 +90,7 @@ impl BotAlgo for Frank { }; } } else if let Some(path) = - find_path_to_neighbour(&game.walkable, pos.as_ivec2(), tpos.as_ivec2()) + find_path_to_neighbour(game, pos.as_ivec2(), tpos.as_ivec2()) { self.path = Some(path); } diff --git a/server/bot/src/algos/simple.rs b/server/bot/src/algos/simple.rs index 0145cfcb..9c17cd82 100644 --- a/server/bot/src/algos/simple.rs +++ b/server/bot/src/algos/simple.rs @@ -243,7 +243,7 @@ impl<S: State> Context<'_, S> { } } pub fn interact_with(&mut self, tile: IVec2, duration: f32) -> LogicRes { - if let Some(path) = find_path_to_neighbour(&self.game.walkable, self.own_position, tile) { + if let Some(path) = find_path_to_neighbour(self.game, self.own_position, tile) { self.state.queue_segment(path, tile, duration); Err(()) } else { diff --git a/server/bot/src/algos/test.rs b/server/bot/src/algos/test.rs index 20abbabd..387dd285 100644 --- a/server/bot/src/algos/test.rs +++ b/server/bot/src/algos/test.rs @@ -45,7 +45,7 @@ impl BotAlgo for Test { }; } else if let Some((item, near)) = find_demand(game) { info!("demand {item:?} near {near}"); - if let Some(path) = find_path_to_neighbour(&game.walkable, pos.as_ivec2(), near) { + if let Some(path) = find_path_to_neighbour(game, pos.as_ivec2(), near) { self.path = Some(path); } } diff --git a/server/bot/src/pathfinding.rs b/server/bot/src/pathfinding.rs index a32442b1..e17ca80c 100644 --- a/server/bot/src/pathfinding.rs +++ b/server/bot/src/pathfinding.rs @@ -15,11 +15,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +use hurrycurry_game_core::Game; use hurrycurry_protocol::glam::{IVec2, Vec2}; use log::{debug, trace}; use std::{ cmp::Ordering, - collections::{BinaryHeap, HashMap, HashSet}, + collections::{BinaryHeap, HashMap}, time::Instant, }; @@ -54,19 +55,19 @@ impl Path { } } -pub fn find_path_to_neighbour(walkable: &HashSet<IVec2>, from: IVec2, to: IVec2) -> Option<Path> { +pub fn find_path_to_neighbour(game: &Game, from: IVec2, to: IVec2) -> Option<Path> { let mut paths = Vec::new(); for xo in -1..=1 { for yo in -1..=1 { let to = to + IVec2::new(xo, yo); - if walkable.contains(&to) { - paths.extend(find_path(walkable, from, to)) + if game.walkable.contains(&to) { + paths.extend(find_path(game, from, to)) } } } paths.into_iter().min_by_key(|p| p.segments.len()) } -pub fn find_path(walkable: &HashSet<IVec2>, from: IVec2, to: IVec2) -> Option<Path> { +pub fn find_path(game: &Game, from: IVec2, to: IVec2) -> Option<Path> { #[derive(Debug, PartialEq, Eq)] struct Open { heuristic: i32, @@ -87,6 +88,7 @@ pub fn find_path(walkable: &HashSet<IVec2>, from: IVec2, to: IVec2) -> Option<Pa debug!("planning route from {from} to {to}"); let start = Instant::now(); + let chair = game.data.get_tile_by_name("chair"); let mut visited = HashMap::new(); let mut open = BinaryHeap::new(); open.push(Open { @@ -112,12 +114,20 @@ pub fn find_path(walkable: &HashSet<IVec2>, from: IVec2, to: IVec2) -> Option<Pa } for dir in [IVec2::NEG_X, IVec2::NEG_Y, IVec2::X, IVec2::Y] { let next = pos + dir; - if walkable.contains(&next) { + if game.walkable.contains(&next) { + let penalty = if let Some(chair) = chair + && let Some(set) = game.tile_index.get(&chair) + && set.contains(&next) + { + 8 + } else { + 0 + }; open.push(Open { heuristic: -(distance + next.distance_squared(to).isqrt()), pos: next, prev_pos: pos, - distance: distance + 1, + distance: distance + penalty + 1, }); } } diff --git a/server/data/src/book/diagram_layout.rs b/server/data/src/book/diagram_layout.rs index cd929f44..e2a18cb1 100644 --- a/server/data/src/book/diagram_layout.rs +++ b/server/data/src/book/diagram_layout.rs @@ -74,6 +74,7 @@ impl Graph { layers.push(next_layer); } + #[allow(clippy::needless_range_loop)] for y in 0..layers.iter().len() { let mut layer = layers[y].clone(); layer.sort_by_cached_key(|&vi| { diff --git a/server/game-core/src/interaction.rs b/server/game-core/src/interaction.rs index 407294d6..275e87d1 100644 --- a/server/game-core/src/interaction.rs +++ b/server/game-core/src/interaction.rs @@ -99,10 +99,8 @@ impl Game { { if edge { inv.players.extend(other_player_id); - } else { - if let Some(player) = other_player_id { - inv.players.remove(&player); - } + } else if let Some(player) = other_player_id { + inv.players.remove(&player); } inv.speed = speed * inv.players.len() as f32; diff --git a/server/game-core/src/lib.rs b/server/game-core/src/lib.rs index 994398c9..e05eec67 100644 --- a/server/game-core/src/lib.rs +++ b/server/game-core/src/lib.rs @@ -197,11 +197,10 @@ impl Game { pub fn set_tile(&mut self, pos: IVec2, kind: Option<TileIndex>) { self.tiles.remove(&pos); self.walkable.remove(&pos); - if let Some(prev) = self.tiles.get(&pos) { - if let Some(set) = self.tile_index.get_mut(&prev.kind) { + if let Some(prev) = self.tiles.get(&pos) + && let Some(set) = self.tile_index.get_mut(&prev.kind) { set.remove(&pos); } - } if let Some(kind) = kind { self.tiles.insert(pos, Tile { kind, item: None }); if self.data_index.tile_collide[kind.0] { diff --git a/server/src/entity/tag_minigame.rs b/server/src/entity/tag_minigame.rs index 089fd49e..a2b4da92 100644 --- a/server/src/entity/tag_minigame.rs +++ b/server/src/entity/tag_minigame.rs @@ -77,7 +77,7 @@ impl Entity for TagMinigame { // Award points to players with the item for (&id, player) in &c.game.players { - if let Some(slot) = player.items.get(0) + if let Some(slot) = player.items.first() && slot.is_none() { *self.scores.entry(id).or_default() += c.dt diff --git a/server/src/server.rs b/server/src/server.rs index f273564e..12b45aa1 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -567,7 +567,7 @@ impl Server { }; if let Some(message) = &message { let body = message.display_message(&FALLBACK_LOCALE, &self.game.data, &COLORED); - if player_data.name != "" { + if !player_data.name.is_empty() { info!("[{player} {:?}] {body}", player_data.name); } else { info!("[{player}] {body}",); @@ -629,7 +629,7 @@ impl Server { for loc in self.game.item_locations_index.clone() { if let Err(e) = self.game.tick_slot(loc, dt) { - warn!("Slot tick failed: {}", e.to_string()); + warn!("Slot tick failed: {}", e); } } |