Skip to content

Commit

Permalink
PathfinderCtx
Browse files Browse the repository at this point in the history
  • Loading branch information
mat-1 committed Oct 8, 2023
1 parent f10535b commit 0297b8a
Show file tree
Hide file tree
Showing 6 changed files with 452 additions and 437 deletions.
8 changes: 3 additions & 5 deletions azalea/benches/pathfinder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use azalea::{
pathfinder::{
astar::{self, a_star},
goals::BlockPosGoal,
moves::PathfinderCtx,
world::CachedWorld,
Goal,
},
BlockPos,
Expand Down Expand Up @@ -79,13 +79,11 @@ fn bench_pathfinder(c: &mut Criterion) {

b.iter(|| {
let (world, start, end) = generate_bedrock_world(&mut partial_chunks, 4);
let ctx = PathfinderCtx::new(Arc::new(RwLock::new(world.into())));
let cached_world = CachedWorld::new(Arc::new(RwLock::new(world.into())));
let goal = BlockPosGoal(end);

let successors = |pos: BlockPos| {
let mut edges = Vec::with_capacity(16);
successors_fn(&mut edges, &ctx, pos);
edges
azalea::pathfinder::call_successors_fn(&cached_world, successors_fn, pos)
};

let astar::Path { movements, partial } = a_star(
Expand Down
41 changes: 23 additions & 18 deletions azalea/src/pathfinder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod costs;
pub mod goals;
pub mod moves;
pub mod simulation;
pub mod world;

use crate::bot::{JumpEvent, LookAtEvent};
use crate::pathfinder::astar::a_star;
Expand All @@ -20,6 +21,7 @@ use crate::ecs::{
system::{Commands, Query, Res},
};
use crate::pathfinder::moves::PathfinderCtx;
use crate::pathfinder::world::CachedWorld;
use azalea_client::chat::SendChatEvent;
use azalea_client::movement::walk_listener;
use azalea_client::{StartSprintEvent, StartWalkEvent};
Expand Down Expand Up @@ -219,12 +221,8 @@ fn goto_listener(
let task = thread_pool.spawn(async move {
debug!("start: {start:?}");

let ctx = PathfinderCtx::new(world_lock);
let successors = |pos: BlockPos| {
let mut edges = Vec::with_capacity(16);
successors_fn(&mut edges, &ctx, pos);
edges
};
let cached_world = CachedWorld::new(world_lock);
let successors = |pos: BlockPos| call_successors_fn(&cached_world, successors_fn, pos);

let mut attempt_number = 0;

Expand Down Expand Up @@ -332,12 +330,9 @@ fn path_found_listener(
.get(instance_name)
.expect("Entity tried to pathfind but the entity isn't in a valid world");
let successors_fn: moves::SuccessorsFn = event.successors_fn;
let ctx = PathfinderCtx::new(world_lock);
let successors = |pos: BlockPos| {
let mut edges = Vec::with_capacity(16);
successors_fn(&mut edges, &ctx, pos);
edges
};
let cached_world = CachedWorld::new(world_lock);
let successors =
|pos: BlockPos| call_successors_fn(&cached_world, successors_fn, pos);

if let Some(first_node_of_new_path) = path.front() {
if successors(last_node_of_current_path.target)
Expand Down Expand Up @@ -521,12 +516,8 @@ fn check_for_path_obstruction(
.expect("Entity tried to pathfind but the entity isn't in a valid world");

// obstruction check (the path we're executing isn't possible anymore)
let ctx = PathfinderCtx::new(world_lock);
let successors = |pos: BlockPos| {
let mut edges = Vec::with_capacity(16);
successors_fn(&mut edges, &ctx, pos);
edges
};
let cached_world = CachedWorld::new(world_lock);
let successors = |pos: BlockPos| call_successors_fn(&cached_world, successors_fn, pos);

if let Some(obstructed_index) = check_path_obstructed(
executing_path.last_reached_node,
Expand Down Expand Up @@ -816,6 +807,20 @@ where
None
}

pub fn call_successors_fn(
cached_world: &CachedWorld,
successors_fn: SuccessorsFn,
pos: BlockPos,
) -> Vec<astar::Edge<BlockPos, moves::MoveData>> {
let mut edges = Vec::with_capacity(16);
let mut ctx = PathfinderCtx {
edges: &mut edges,
world: cached_world,
};
successors_fn(&mut ctx, pos);
edges
}

#[cfg(test)]
mod tests {
use std::{collections::HashSet, sync::Arc};
Expand Down
60 changes: 30 additions & 30 deletions azalea/src/pathfinder/moves/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@ use crate::pathfinder::{astar, costs::*};

use super::{default_is_reached, Edge, ExecuteCtx, IsReachedCtx, MoveData, PathfinderCtx};

pub fn basic_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, node: BlockPos) {
forward_move(edges, ctx, node);
ascend_move(edges, ctx, node);
descend_move(edges, ctx, node);
diagonal_move(edges, ctx, node);
descend_forward_1_move(edges, ctx, node);
pub fn basic_move(ctx: &mut PathfinderCtx, node: BlockPos) {
forward_move(ctx, node);
ascend_move(ctx, node);
descend_move(ctx, node);
diagonal_move(ctx, node);
descend_forward_1_move(ctx, node);
}

fn forward_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: BlockPos) {
fn forward_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
for dir in CardinalDirection::iter() {
let offset = BlockPos::new(dir.x(), 0, dir.z());

if !ctx.is_standable(pos + offset) {
if !ctx.world.is_standable(pos + offset) {
continue;
}

let cost = SPRINT_ONE_BLOCK_COST;

edges.push(Edge {
ctx.edges.push(Edge {
movement: astar::Movement {
target: pos + offset,
data: MoveData {
Expand All @@ -47,20 +47,20 @@ fn execute_forward_move(mut ctx: ExecuteCtx) {
ctx.sprint(SprintDirection::Forward);
}

fn ascend_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: BlockPos) {
fn ascend_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
for dir in CardinalDirection::iter() {
let offset = BlockPos::new(dir.x(), 1, dir.z());

if !ctx.is_block_passable(pos.up(2)) {
if !ctx.world.is_block_passable(pos.up(2)) {
continue;
}
if !ctx.is_standable(pos + offset) {
if !ctx.world.is_standable(pos + offset) {
continue;
}

let cost = SPRINT_ONE_BLOCK_COST + JUMP_PENALTY + *JUMP_ONE_BLOCK_COST;

edges.push(Edge {
ctx.edges.push(Edge {
movement: astar::Movement {
target: pos + offset,
data: MoveData {
Expand Down Expand Up @@ -119,22 +119,22 @@ pub fn ascend_is_reached(
BlockPos::from(position) == target || BlockPos::from(position) == target.down(1)
}

fn descend_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: BlockPos) {
fn descend_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
for dir in CardinalDirection::iter() {
let dir_delta = BlockPos::new(dir.x(), 0, dir.z());
let new_horizontal_position = pos + dir_delta;
let fall_distance = ctx.fall_distance(new_horizontal_position);
let fall_distance = ctx.world.fall_distance(new_horizontal_position);
if fall_distance == 0 || fall_distance > 3 {
continue;
}
let new_position = new_horizontal_position.down(fall_distance as i32);

// check whether 3 blocks vertically forward are passable
if !ctx.is_passable(new_horizontal_position) {
if !ctx.world.is_passable(new_horizontal_position) {
continue;
}
// check whether we can stand on the target position
if !ctx.is_standable(new_position) {
if !ctx.world.is_standable(new_position) {
continue;
}

Expand All @@ -149,7 +149,7 @@ fn descend_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: BlockPos) {
CENTER_AFTER_FALL_COST,
);

edges.push(Edge {
ctx.edges.push(Edge {
movement: astar::Movement {
target: new_position,
data: MoveData {
Expand Down Expand Up @@ -214,14 +214,14 @@ pub fn descend_is_reached(
&& (position.y - target.y as f64) < 0.5
}

fn descend_forward_1_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: BlockPos) {
fn descend_forward_1_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
for dir in CardinalDirection::iter() {
let dir_delta = BlockPos::new(dir.x(), 0, dir.z());
let gap_horizontal_position = pos + dir_delta;
let new_horizontal_position = pos + dir_delta * 2;

let gap_fall_distance = ctx.fall_distance(gap_horizontal_position);
let fall_distance = ctx.fall_distance(new_horizontal_position);
let gap_fall_distance = ctx.world.fall_distance(gap_horizontal_position);
let fall_distance = ctx.world.fall_distance(new_horizontal_position);

if fall_distance == 0 || fall_distance > 3 || gap_fall_distance < fall_distance {
continue;
Expand All @@ -230,14 +230,14 @@ fn descend_forward_1_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: Block
let new_position = new_horizontal_position.down(fall_distance as i32);

// check whether 2 blocks vertically forward are passable
if !ctx.is_passable(new_horizontal_position) {
if !ctx.world.is_passable(new_horizontal_position) {
continue;
}
if !ctx.is_passable(gap_horizontal_position) {
if !ctx.world.is_passable(gap_horizontal_position) {
continue;
}
// check whether we can stand on the target position
if !ctx.is_standable(new_position) {
if !ctx.world.is_standable(new_position) {
continue;
}

Expand All @@ -253,7 +253,7 @@ fn descend_forward_1_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: Block
CENTER_AFTER_FALL_COST,
);

edges.push(Edge {
ctx.edges.push(Edge {
movement: astar::Movement {
target: new_position,
data: MoveData {
Expand All @@ -266,7 +266,7 @@ fn descend_forward_1_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: Block
}
}

fn diagonal_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: BlockPos) {
fn diagonal_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
for dir in CardinalDirection::iter() {
let right = dir.right();
let offset = BlockPos::new(dir.x() + right.x(), 0, dir.z() + right.z());
Expand All @@ -276,8 +276,8 @@ fn diagonal_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: BlockPos) {
// +0.001 so it doesn't unnecessarily go diagonal sometimes
let mut cost = SPRINT_ONE_BLOCK_COST * SQRT_2 + 0.001;

let left_passable = ctx.is_passable(left_pos);
let right_passable = ctx.is_passable(right_pos);
let left_passable = ctx.world.is_passable(left_pos);
let right_passable = ctx.world.is_passable(right_pos);

if !left_passable && !right_passable {
continue;
Expand All @@ -288,11 +288,11 @@ fn diagonal_move(edges: &mut Vec<Edge>, ctx: &PathfinderCtx, pos: BlockPos) {
cost += WALK_ONE_BLOCK_COST / 2.;
}

if !ctx.is_standable(pos + offset) {
if !ctx.world.is_standable(pos + offset) {
continue;
}

edges.push(Edge {
ctx.edges.push(Edge {
movement: astar::Movement {
target: pos + offset,
data: MoveData {
Expand Down
Loading

0 comments on commit 0297b8a

Please sign in to comment.