aboutsummaryrefslogtreecommitdiff
path: root/azalea/src/pathfinder/moves/basic.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2023-12-15 11:26:40 -0600
committerGitHub <noreply@github.com>2023-12-15 11:26:40 -0600
commita707e2eb82b74994a16083b31fa4576332cf1995 (patch)
treedb6c2ac94dd73590befd68a9b1b0ef960410b0df /azalea/src/pathfinder/moves/basic.rs
parent59e140ddd655c7dc6e35109b91286118c51bcc06 (diff)
downloadazalea-drasl-a707e2eb82b74994a16083b31fa4576332cf1995.tar.xz
Add mining to the pathfinder (#122)
* basic pathfinder mining poc * mining descending and autotool * pathfinder mining descending * pathfinder fixes * allow disabling pathfinder miner and other fixes * small optimization to avoid chunk vec iter lookup sometimes * seeded rng in pathfinder bench * consistently use f32::INFINITY this brings performance much closer to how it was before * astar heuristic optimization from baritone * add downward_move * fix downward move execute * avoid liquids and falling blocks when mining * fix COST_HEURISTIC * fix to not path through flowing liquids * only reset pathfinder timeout while mining if the block is close enough * cache mining costs of block positions * fix mine_while_at_start and move PathfinderDebugParticles to its own module * add ReachBlockPosGoal in other news: azalea's sin/cos functions were broken this whole time and i never noticed * clippy and add things that i accidentally didn't commit * improve wording on doc for azalea::pathfinder
Diffstat (limited to 'azalea/src/pathfinder/moves/basic.rs')
-rw-r--r--azalea/src/pathfinder/moves/basic.rs141
1 files changed, 124 insertions, 17 deletions
diff --git a/azalea/src/pathfinder/moves/basic.rs b/azalea/src/pathfinder/moves/basic.rs
index 957e24c6..54a6dc6a 100644
--- a/azalea/src/pathfinder/moves/basic.rs
+++ b/azalea/src/pathfinder/moves/basic.rs
@@ -16,17 +16,20 @@ pub fn basic_move(ctx: &mut PathfinderCtx, node: BlockPos) {
descend_move(ctx, node);
diagonal_move(ctx, node);
descend_forward_1_move(ctx, node);
+ downward_move(ctx, node);
}
fn forward_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
for dir in CardinalDirection::iter() {
let offset = BlockPos::new(dir.x(), 0, dir.z());
- if !ctx.world.is_standable(pos + offset) {
+ let mut cost = SPRINT_ONE_BLOCK_COST;
+
+ let break_cost = ctx.world.cost_for_standing(pos + offset, ctx.mining_cache);
+ if break_cost == f32::INFINITY {
continue;
}
-
- let cost = SPRINT_ONE_BLOCK_COST;
+ cost += break_cost;
ctx.edges.push(Edge {
movement: astar::Movement {
@@ -43,6 +46,14 @@ fn forward_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
fn execute_forward_move(mut ctx: ExecuteCtx) {
let center = ctx.target.center();
+
+ if ctx.mine_while_at_start(ctx.target.up(1)) {
+ return;
+ }
+ if ctx.mine_while_at_start(ctx.target) {
+ return;
+ }
+
ctx.look_at(center);
ctx.sprint(SprintDirection::Forward);
}
@@ -51,14 +62,22 @@ fn ascend_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
for dir in CardinalDirection::iter() {
let offset = BlockPos::new(dir.x(), 1, dir.z());
- if !ctx.world.is_block_passable(pos.up(2)) {
+ let break_cost_1 = ctx
+ .world
+ .cost_for_breaking_block(pos.up(2), ctx.mining_cache);
+ if break_cost_1 == f32::INFINITY {
continue;
}
- if !ctx.world.is_standable(pos + offset) {
+ let break_cost_2 = ctx.world.cost_for_standing(pos + offset, ctx.mining_cache);
+ if break_cost_2 == f32::INFINITY {
continue;
}
- let cost = SPRINT_ONE_BLOCK_COST + JUMP_PENALTY + *JUMP_ONE_BLOCK_COST;
+ let cost = SPRINT_ONE_BLOCK_COST
+ + JUMP_PENALTY
+ + *JUMP_ONE_BLOCK_COST
+ + break_cost_1
+ + break_cost_2;
ctx.edges.push(Edge {
movement: astar::Movement {
@@ -81,6 +100,16 @@ fn execute_ascend_move(mut ctx: ExecuteCtx) {
..
} = ctx;
+ if ctx.mine_while_at_start(start.up(2)) {
+ return;
+ }
+ if ctx.mine_while_at_start(target) {
+ return;
+ }
+ if ctx.mine_while_at_start(target.up(1)) {
+ return;
+ }
+
let target_center = target.center();
ctx.look_at(target_center);
@@ -123,19 +152,39 @@ 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.world.fall_distance(new_horizontal_position);
- if fall_distance == 0 || fall_distance > 3 {
+
+ let break_cost_1 = ctx
+ .world
+ .cost_for_passing(new_horizontal_position, ctx.mining_cache);
+ if break_cost_1 == f32::INFINITY {
continue;
}
- let new_position = new_horizontal_position.down(fall_distance as i32);
- // check whether 3 blocks vertically forward are passable
- if !ctx.world.is_passable(new_horizontal_position) {
+ let mut fall_distance = ctx.world.fall_distance(new_horizontal_position);
+ if fall_distance > 3 {
continue;
}
- // check whether we can stand on the target position
- if !ctx.world.is_standable(new_position) {
- continue;
+
+ if fall_distance == 0 {
+ // if the fall distance is 0, set it to 1 so we try mining
+ fall_distance = 1
+ }
+
+ let new_position = new_horizontal_position.down(fall_distance as i32);
+
+ // only mine if we're descending 1 block
+ let break_cost_2;
+ if fall_distance == 1 {
+ break_cost_2 = ctx.world.cost_for_standing(new_position, ctx.mining_cache);
+ if break_cost_2 == f32::INFINITY {
+ continue;
+ }
+ } else {
+ // check whether we can stand on the target position
+ if !ctx.world.is_standable(new_position) {
+ continue;
+ }
+ break_cost_2 = 0.;
}
let cost = WALK_OFF_BLOCK_COST
@@ -145,9 +194,11 @@ fn descend_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
.copied()
// avoid panicking if we fall more than the size of FALL_N_BLOCKS_COST
// probably not possible but just in case
- .unwrap_or(f32::MAX),
+ .unwrap_or(f32::INFINITY),
CENTER_AFTER_FALL_COST,
- );
+ )
+ + break_cost_1
+ + break_cost_2;
ctx.edges.push(Edge {
movement: astar::Movement {
@@ -169,6 +220,12 @@ fn execute_descend_move(mut ctx: ExecuteCtx) {
..
} = ctx;
+ for i in (0..=(start.y - target.y + 1)).rev() {
+ if ctx.mine_while_at_start(target.up(i)) {
+ return;
+ }
+ }
+
let start_center = start.center();
let center = target.center();
@@ -249,7 +306,7 @@ fn descend_forward_1_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
.copied()
// avoid panicking if we fall more than the size of FALL_N_BLOCKS_COST
// probably not possible but just in case
- .unwrap_or(f32::MAX),
+ .unwrap_or(f32::INFINITY),
CENTER_AFTER_FALL_COST,
);
@@ -310,3 +367,53 @@ fn execute_diagonal_move(mut ctx: ExecuteCtx) {
ctx.look_at(target_center);
ctx.sprint(SprintDirection::Forward);
}
+
+/// Go directly down, usually by mining.
+fn downward_move(ctx: &mut PathfinderCtx, pos: BlockPos) {
+ // make sure we land on a solid block after breaking the one below us
+ if !ctx.world.is_block_solid(pos.down(2)) {
+ return;
+ }
+
+ let break_cost = ctx
+ .world
+ .cost_for_breaking_block(pos.down(1), ctx.mining_cache);
+ if break_cost == f32::INFINITY {
+ return;
+ }
+
+ let cost = FALL_N_BLOCKS_COST[1] + break_cost;
+
+ ctx.edges.push(Edge {
+ movement: astar::Movement {
+ target: pos.down(1),
+ data: MoveData {
+ execute: &execute_downward_move,
+ is_reached: &default_is_reached,
+ },
+ },
+ cost,
+ })
+}
+fn execute_downward_move(mut ctx: ExecuteCtx) {
+ let ExecuteCtx {
+ target, position, ..
+ } = ctx;
+
+ let target_center = target.center();
+
+ let horizontal_distance_from_target =
+ (target_center - position).horizontal_distance_sqr().sqrt();
+
+ if horizontal_distance_from_target > 0.25 {
+ ctx.look_at(target_center);
+ ctx.walk(WalkDirection::Forward);
+ } else if ctx.mine_while_at_start(target) {
+ ctx.walk(WalkDirection::None);
+ } else if BlockPos::from(position) != target {
+ ctx.look_at(target_center);
+ ctx.walk(WalkDirection::Forward);
+ } else {
+ ctx.walk(WalkDirection::None);
+ }
+}