aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/bot/src/algos/customer.rs4
-rw-r--r--server/bot/src/algos/frank.rs2
-rw-r--r--server/bot/src/lib.rs12
-rw-r--r--server/bot/src/pathfinding.rs22
-rw-r--r--server/bot/src/step.rs79
-rw-r--r--test-client/main.ts11
-rw-r--r--test-client/visual.ts14
7 files changed, 96 insertions, 48 deletions
diff --git a/server/bot/src/algos/customer.rs b/server/bot/src/algos/customer.rs
index fa10410b..fe665f47 100644
--- a/server/bot/src/algos/customer.rs
+++ b/server/bot/src/algos/customer.rs
@@ -175,7 +175,7 @@ impl CustomerState {
})
{
*self = CustomerState::New;
- } else if path.is_stuck() {
+ } else if path.is_stuck(3.) {
if let Some(path) = find_path(game, pos.as_ivec2(), *origin) {
*self = CustomerState::Exiting { path };
}
@@ -392,7 +392,7 @@ impl CustomerState {
}
}
CustomerState::Exiting { path } => {
- if path.is_done() || path.is_stuck() {
+ if path.is_done() || path.is_stuck(3.) {
debug!("{me:?} -> leave");
*self = CustomerState::Exited
} else {
diff --git a/server/bot/src/algos/frank.rs b/server/bot/src/algos/frank.rs
index eeee3b61..a02b0112 100644
--- a/server/bot/src/algos/frank.rs
+++ b/server/bot/src/algos/frank.rs
@@ -76,7 +76,7 @@ impl BotAlgo for Frank {
if let Some(path) = &mut self.path {
let direction = path.next_direction(pos, dt);
- if path.is_stuck() {
+ if path.is_stuck(3.) {
self.path = None;
} else if path.is_done() {
self.path = None;
diff --git a/server/bot/src/lib.rs b/server/bot/src/lib.rs
index 337d18e8..078314b1 100644
--- a/server/bot/src/lib.rs
+++ b/server/bot/src/lib.rs
@@ -22,6 +22,8 @@ pub mod step;
use hurrycurry_game_core::Game;
use hurrycurry_protocol::PacketS;
+#[cfg(feature = "debug_events")]
+use hurrycurry_protocol::{PlayerID, glam::Vec3};
use std::{collections::VecDeque, random::random};
pub struct PacketSink<'a> {
@@ -55,3 +57,13 @@ impl<T: BotAlgo + ?Sized> BotAlgo for Box<T> {
fn random_float() -> f32 {
random::<u32>(..) as f32 / u32::MAX as f32
}
+
+#[cfg(feature = "debug_events")]
+fn debug_player_color(d: PlayerID) -> Vec3 {
+ use std::f32::consts::TAU;
+ Vec3::new(
+ (d.0 as f32 + TAU / 3. * 0.).sin(),
+ (d.0 as f32 + TAU / 3. * 1.).sin(),
+ (d.0 as f32 + TAU / 3. * 2.).sin(),
+ )
+}
diff --git a/server/bot/src/pathfinding.rs b/server/bot/src/pathfinding.rs
index 5c5551dd..936f99dd 100644
--- a/server/bot/src/pathfinding.rs
+++ b/server/bot/src/pathfinding.rs
@@ -16,12 +16,9 @@
*/
use hurrycurry_game_core::Game;
+use hurrycurry_protocol::glam::{IVec2, Vec2};
#[cfg(feature = "debug_events")]
-use hurrycurry_protocol::{DebugEvent, PlayerID};
-use hurrycurry_protocol::{
- DebugEventDisplay,
- glam::{IVec2, Vec2},
-};
+use hurrycurry_protocol::{DebugEvent, DebugEventDisplay, PlayerID};
use log::{debug, trace};
use std::{
cmp::Ordering,
@@ -56,8 +53,8 @@ impl Path {
pub fn is_done(&self) -> bool {
self.segments.is_empty()
}
- pub fn is_stuck(&self) -> bool {
- self.seg_time > 3.
+ pub fn is_stuck(&self, thres: f32) -> bool {
+ self.seg_time > thres
}
pub fn remaining_segments(&self) -> usize {
self.segments.len()
@@ -65,17 +62,10 @@ impl Path {
#[cfg(feature = "debug_events")]
pub fn debug(&self, id: PlayerID) -> DebugEvent {
- use std::f32::consts::TAU;
-
- use hurrycurry_protocol::glam::Vec3;
- let a = id.0 as f32;
+ use crate::debug_player_color;
DebugEvent {
key: format!("path-{id}"),
- color: Vec3::new(
- (a + TAU / 3. * 0.).sin(),
- (a + TAU / 3. * 1.).sin(),
- (a + TAU / 3. * 2.).sin(),
- ),
+ color: debug_player_color(id),
display: DebugEventDisplay::Path {
points: self.segments.clone(),
},
diff --git a/server/bot/src/step.rs b/server/bot/src/step.rs
index 34793466..8ef9556d 100644
--- a/server/bot/src/step.rs
+++ b/server/bot/src/step.rs
@@ -33,6 +33,8 @@ pub struct StepState {
interact_start_pending: bool,
interact_stop_pending: bool,
me: PlayerID,
+ #[cfg(feature = "debug_events")]
+ init: bool,
}
impl StepState {
@@ -50,6 +52,8 @@ impl StepState {
item_current: None,
path: Path::EMPTY,
wait_timer: timer,
+ #[cfg(feature = "debug_events")]
+ init: false,
}
}
pub fn new_segment(
@@ -74,16 +78,37 @@ impl StepState {
interact_start_pending: true,
interact_position: pos,
item_expected: destination_item,
- item_current: None,
+ item_current: destination_item,
+ #[cfg(feature = "debug_events")]
+ init: false,
})
}
pub fn is_busy(&self) -> bool {
- self.wait_timer >= 0. || self.interact_stop_pending
- // && self.item_current == self.item_expected
+ (self.wait_timer >= 0. || self.interact_stop_pending)
+ && !self.path.is_stuck(3.)
+ && (self.path.is_done() || self.item_current == self.item_expected)
}
pub fn tick(&mut self, out: &mut PacketSink, game: &Game, dt: f32) {
+ #[cfg(feature = "debug_events")]
+ if !self.init {
+ use crate::debug_player_color;
+ use hurrycurry_protocol::{DebugEvent, DebugEventDisplay};
+ out.push(PacketS::Debug(DebugEvent {
+ key: format!("step-{}", self.me),
+ color: debug_player_color(self.me),
+ display: DebugEventDisplay::Label {
+ pos: self.interact_position.as_vec2(),
+ text: format!(
+ "done={} expected={}",
+ self.path.is_done(),
+ self.item_expected == self.item_current
+ ),
+ },
+ }));
+ self.init = true;
+ }
if self.path.is_done() {
if self.interact_start_pending {
self.interact_start_pending = false;
@@ -93,7 +118,9 @@ impl StepState {
target: Some(ItemLocation::Tile(self.interact_position)),
});
} else {
- if self.wait_timer < 0. {
+ if self.wait_timer > 0. {
+ self.wait_timer -= dt;
+ } else {
if self.interact_stop_pending {
self.interact_stop_pending = false;
out.push(PacketS::Interact {
@@ -102,34 +129,32 @@ impl StepState {
target: None,
});
}
- } else {
- self.wait_timer -= dt;
}
}
- }
-
- self.item_current = game
- .tiles
- .get(&self.interact_position)
- .and_then(|t| t.item.as_ref().map(|i| i.kind));
+ } else {
+ self.item_current = game
+ .tiles
+ .get(&self.interact_position)
+ .and_then(|t| t.item.as_ref().map(|i| i.kind));
- let position = game
- .players
- .get(&self.me)
- .as_ref()
- .map(|p| p.movement.position)
- .unwrap_or_default();
+ let position = game
+ .players
+ .get(&self.me)
+ .as_ref()
+ .map(|p| p.movement.position)
+ .unwrap_or_default();
- let dir = self.path.next_direction(position, dt);
+ let dir = self.path.next_direction(position, dt);
- #[cfg(feature = "debug_events")]
- out.push(PacketS::Debug(self.path.debug(self.me)));
+ #[cfg(feature = "debug_events")]
+ out.push(PacketS::Debug(self.path.debug(self.me)));
- out.push(PacketS::Movement {
- player: self.me,
- dir,
- boost: false,
- pos: None,
- });
+ out.push(PacketS::Movement {
+ player: self.me,
+ dir,
+ boost: self.path.is_stuck(2.),
+ pos: None,
+ });
+ }
}
}
diff --git a/test-client/main.ts b/test-client/main.ts
index 091e0535..9267270b 100644
--- a/test-client/main.ts
+++ b/test-client/main.ts
@@ -321,6 +321,8 @@ function packet(p: PacketC) {
break;
case "flush_map":
break;
+ case "pause":
+ break; // TODO
case "menu":
switch (p.menu) {
case "score":
@@ -336,7 +338,7 @@ function packet(p: PacketC) {
}
break;
case "debug":
- debug_events.set(p.key, { timeout: 0.1, ...p })
+ debug_events.set(p.key, { timeout: 0.5, ...p })
break;
default:
console.warn("unknown packet", p);
@@ -498,6 +500,13 @@ function frame_update(dt: number) {
}
remove.forEach(i => items_removed.delete(i))
+ const remove_events: string[] = []
+ for (const [key, ev] of debug_events.entries()) {
+ ev.timeout -= dt
+ if (ev.timeout < 0) remove_events.push(key)
+ }
+ remove_events.forEach(i => debug_events.delete(i))
+
for (const [_, h] of server_hints)
tick_message(h, dt);
diff --git a/test-client/visual.ts b/test-client/visual.ts
index 20bd7ae2..c06edff0 100644
--- a/test-client/visual.ts
+++ b/test-client/visual.ts
@@ -101,16 +101,28 @@ export function draw_ingame() {
function draw_debug_events() {
for (const ev of debug_events.values()) {
+ const color = `rgb(${ev.color[0] * 100}%,${ev.color[1] * 100}%,${ev.color[2] * 100}%)`
if (ev.display.ty == "path") {
ctx.lineWidth = 0.1
ctx.lineCap = "round"
- ctx.strokeStyle = `rgb(${ev.color[0] * 100}%,${ev.color[1] * 100}%,${ev.color[2] * 100}%)`
+ ctx.strokeStyle = color
ctx.beginPath()
if (ev.display.points.length)
ctx.moveTo(...ev.display.points[0])
for (let i = 1; i < ev.display.points.length; i++)
ctx.lineTo(...ev.display.points[i])
ctx.stroke()
+ } else if (ev.display.ty == "label") {
+ ctx.font = "0.2px sans-serif"
+ ctx.strokeStyle = "black"
+ ctx.fillStyle = color
+ ctx.lineWidth = 0.1
+ ctx.textAlign = "center"
+ ctx.textBaseline = "middle"
+ ctx.lineJoin = "round"
+ ctx.lineCap = "round"
+ ctx.strokeText(ev.display.text, ev.display.pos[0], ev.display.pos[1])
+ ctx.fillText(ev.display.text, ev.display.pos[0], ev.display.pos[1])
}
}
}