Skip to main content

azalea/pathfinder/moves/
uncommon.rs

1//! Some moves which aren't used often but make execution slightly cleaner.
2
3use azalea_core::direction::CardinalDirection;
4
5use crate::pathfinder::{
6    astar::{self, Edge},
7    costs::{CENTER_AFTER_FALL_COST, FALL_N_BLOCKS_COST, WALK_OFF_BLOCK_COST, WALK_ONE_BLOCK_COST},
8    moves::{
9        BARITONE_COMPAT, MoveData, MovesCtx,
10        basic::{descend_is_reached, execute_descend_move},
11    },
12    positions::RelBlockPos,
13};
14
15pub fn uncommon_move(ctx: &mut MovesCtx, node: RelBlockPos) {
16    if BARITONE_COMPAT {
17        return;
18    }
19    descend_forward_1_move(ctx, node);
20}
21
22pub fn descend_forward_1_move(ctx: &mut MovesCtx, pos: RelBlockPos) {
23    for dir in CardinalDirection::iter() {
24        let dir_delta = RelBlockPos::new(dir.x(), 0, dir.z());
25        let gap_horizontal_position = pos + dir_delta;
26        let new_horizontal_position = pos + dir_delta * 2;
27
28        let gap_fall_distance = ctx.world.fall_distance(gap_horizontal_position);
29        let fall_distance = ctx.world.fall_distance(new_horizontal_position);
30
31        if fall_distance == 0 || fall_distance > 3 || gap_fall_distance < fall_distance {
32            continue;
33        }
34
35        let new_position = new_horizontal_position.down(fall_distance as i32);
36
37        // check whether 2 blocks vertically forward are passable
38        if !ctx.world.is_passable(new_horizontal_position) {
39            continue;
40        }
41        if !ctx.world.is_passable(gap_horizontal_position) {
42            continue;
43        }
44        // check whether we can stand on the target position
45        if !ctx.world.is_standable(new_position) {
46            continue;
47        }
48
49        let cost = WALK_OFF_BLOCK_COST
50            + WALK_ONE_BLOCK_COST
51            + f32::max(
52                FALL_N_BLOCKS_COST
53                    .get(fall_distance as usize)
54                    .copied()
55                    // avoid panicking if we fall more than the size of FALL_N_BLOCKS_COST
56                    // probably not possible but just in case
57                    .unwrap_or(f32::INFINITY),
58                CENTER_AFTER_FALL_COST,
59            );
60
61        ctx.edges.push(Edge {
62            movement: astar::Movement {
63                target: new_position,
64                data: MoveData {
65                    execute: &execute_descend_move,
66                    is_reached: &descend_is_reached,
67                },
68            },
69            cost,
70        })
71    }
72}