From 6956bcac2d943a587a2f67601fdd8861755cbdae Mon Sep 17 00:00:00 2001 From: Leijurv Date: Wed, 1 Aug 2018 23:13:48 -0400 Subject: [PATCH] reintroduce goals (with javadocs) --- .../java/baritone/pathfinding/goals/Goal.java | 36 +++++++++ .../baritone/pathfinding/goals/GoalBlock.java | 77 +++++++++++++++++++ .../pathfinding/goals/GoalComposite.java | 61 +++++++++++++++ .../pathfinding/goals/GoalGetToBlock.java | 36 +++++++++ .../pathfinding/goals/GoalRunAway.java | 52 +++++++++++++ .../pathfinding/goals/GoalTwoBlocks.java | 43 +++++++++++ .../baritone/pathfinding/goals/GoalXZ.java | 73 ++++++++++++++++++ .../pathfinding/goals/GoalYLevel.java | 32 ++++++++ 8 files changed, 410 insertions(+) create mode 100644 src/main/java/baritone/pathfinding/goals/Goal.java create mode 100644 src/main/java/baritone/pathfinding/goals/GoalBlock.java create mode 100644 src/main/java/baritone/pathfinding/goals/GoalComposite.java create mode 100644 src/main/java/baritone/pathfinding/goals/GoalGetToBlock.java create mode 100644 src/main/java/baritone/pathfinding/goals/GoalRunAway.java create mode 100644 src/main/java/baritone/pathfinding/goals/GoalTwoBlocks.java create mode 100644 src/main/java/baritone/pathfinding/goals/GoalXZ.java create mode 100644 src/main/java/baritone/pathfinding/goals/GoalYLevel.java diff --git a/src/main/java/baritone/pathfinding/goals/Goal.java b/src/main/java/baritone/pathfinding/goals/Goal.java new file mode 100644 index 00000000..244b61da --- /dev/null +++ b/src/main/java/baritone/pathfinding/goals/Goal.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import net.minecraft.util.math.BlockPos; + +/** + * An abstract Goal for pathfinding, can be anything from a specific block to just a Y coordinate. + * @author leijurv + */ +public interface Goal { + /** + * Does this position satisfy the goal? + * + * @param pos + * @return + */ + public boolean isInGoal(BlockPos pos); + /** + * Estimate the number of ticks it will take to get to the goal + * + * @param pos + * @return + */ + public double heuristic(BlockPos pos); + + /** + * Summarize the goal + * @return + */ + @Override + public String toString(); +} diff --git a/src/main/java/baritone/pathfinding/goals/GoalBlock.java b/src/main/java/baritone/pathfinding/goals/GoalBlock.java new file mode 100644 index 00000000..1e9bf627 --- /dev/null +++ b/src/main/java/baritone/pathfinding/goals/GoalBlock.java @@ -0,0 +1,77 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import baritone.Baritone; +import baritone.pathfinding.actions.Action; +import net.minecraft.util.math.BlockPos; + +/** + * A specific BlockPos goal + * @author leijurv + */ +public class GoalBlock implements Goal { + + final int x, y, z; + + public GoalBlock() { + this(Baritone.playerFeet); + } + + public GoalBlock(BlockPos pos) { + this(pos.getX(), pos.getY(), pos.getZ()); + } + + public GoalBlock(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + public BlockPos pos() { + return new BlockPos(x, y, z); + } + + @Override + public boolean isInGoal(BlockPos pos) { + return pos.getX() == this.x && pos.getY() == this.y && pos.getZ() == this.z; + } + static final double MIN = 20; + static final double MAX = 150; + + @Override + public double heuristic(BlockPos pos) { + double xDiff = pos.getX() - this.x; + double yDiff = pos.getY() - this.y; + double zDiff = pos.getZ() - this.z; + return calculate(xDiff, yDiff, zDiff); + } + + public static double calculate(double xDiff, double yDiff, double zDiff) { + double pythaDist = Math.sqrt(xDiff * xDiff + zDiff * zDiff); + double heuristic = 0; + double baseline = (Action.PLACE_ONE_BLOCK_COST + Action.FALL_ONE_BLOCK_COST) * 32; + if (pythaDist < MAX) {//if we are more than MAX away, ignore the Y coordinate. It really doesn't matter how far away your Y coordinate is if you X coordinate is 1000 blocks away. + double multiplier = pythaDist < MIN ? 1 : 1 - (pythaDist - MIN) / (MAX - MIN); + if (yDiff < 0) {//pos.getY()-this.y<0 therefore pos.getY() blocks) { + goals = new Goal[blocks.size()]; + int i = 0; + for (BlockPos pos : blocks) { + goals[i] = new GoalBlock(pos); + i++; + } + } + public Goal[] goals() { + return goals; + } + @Override + public boolean isInGoal(BlockPos pos) { + for (Goal g : goals) { + if (g.isInGoal(pos)) { + return true; + } + } + return false; + } + @Override + public double heuristic(BlockPos pos) { + double min = Double.MAX_VALUE; + for (Goal g : goals) { + min = Math.min(min, g.heuristic(pos)); // whichever is closest + } + return min; + } + @Override + public String toString() { + return "GoalComposite" + Arrays.toString(goals); + } +} diff --git a/src/main/java/baritone/pathfinding/goals/GoalGetToBlock.java b/src/main/java/baritone/pathfinding/goals/GoalGetToBlock.java new file mode 100644 index 00000000..e8ee960d --- /dev/null +++ b/src/main/java/baritone/pathfinding/goals/GoalGetToBlock.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import baritone.Baritone; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +/** + * Don't get into the block, but get directly adjacent to it. + * Useful for chests. + * @author avecowa + */ +public class GoalGetToBlock extends GoalComposite { + + public static BlockPos goalPos; + + public GoalGetToBlock(BlockPos pos) { + super(ajacentBlocks(goalPos = pos)); + } + + public GoalGetToBlock() { + this(Baritone.playerFeet); + } + + public static BlockPos[] ajacentBlocks(BlockPos pos) { + BlockPos[] sides = new BlockPos[6]; + for (int i = 0; i < 6; i++) { + sides[i] = pos.offset(EnumFacing.values()[i]); + } + return sides; + } +} diff --git a/src/main/java/baritone/pathfinding/goals/GoalRunAway.java b/src/main/java/baritone/pathfinding/goals/GoalRunAway.java new file mode 100644 index 00000000..b8865d75 --- /dev/null +++ b/src/main/java/baritone/pathfinding/goals/GoalRunAway.java @@ -0,0 +1,52 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import java.util.Arrays; +import net.minecraft.util.math.BlockPos; + +/** + * Useful for automated combat (etreating specifically) + * @author leijurv + */ +public class GoalRunAway implements Goal { + public final BlockPos[] from; + final double distanceSq; + public GoalRunAway(double distance, BlockPos... from) { + if (from.length == 0) { + throw new IllegalArgumentException(); + } + this.from = from; + this.distanceSq = distance * distance; + } + @Override + public boolean isInGoal(BlockPos pos) { + for (BlockPos p : from) { + int diffX = pos.getX() - p.getX(); + int diffZ = pos.getZ() - p.getZ(); + double distSq = diffX * diffX + diffZ * diffZ; + if (distSq < distanceSq) { + return false; + } + } + return true; + } + @Override + public double heuristic(BlockPos pos) {//mostly copied from GoalBlock + double min = Double.MAX_VALUE; + for (BlockPos p : from) { + double h = GoalXZ.calculate(p.getX() - pos.getX(), p.getZ() - pos.getZ()); + if (h < min) { + min = h; + } + } + return -min; + } + @Override + public String toString() { + return "GoalRunAwayFrom[" + Arrays.asList(from) + "]"; + } +} diff --git a/src/main/java/baritone/pathfinding/goals/GoalTwoBlocks.java b/src/main/java/baritone/pathfinding/goals/GoalTwoBlocks.java new file mode 100644 index 00000000..bc84c53a --- /dev/null +++ b/src/main/java/baritone/pathfinding/goals/GoalTwoBlocks.java @@ -0,0 +1,43 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import net.minecraft.util.math.BlockPos; + +/** + * Useful if the goal is just to mine a block. + * This goal gets either the player's feet or head into the desired block. + * @author leijurv + */ +public class GoalTwoBlocks implements Goal { + final int x, y, z; + public GoalTwoBlocks(BlockPos pos) { + this(pos.getX(), pos.getY(), pos.getZ()); + } + public GoalTwoBlocks(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + @Override + public boolean isInGoal(BlockPos pos) { + return pos.getX() == this.x && (pos.getY() == this.y || pos.getY() == this.y - 1) && pos.getZ() == this.z; + } + @Override + public double heuristic(BlockPos pos) { + double xDiff = pos.getX() - this.x; + double yDiff = pos.getY() - this.y; + if (yDiff < 0) { + yDiff++; + } + double zDiff = pos.getZ() - this.z; + return GoalBlock.calculate(xDiff, yDiff, zDiff); + } + @Override + public String toString() { + return "GoalTwoBlocks{x=" + x + ",y=" + y + ",z=" + z + "}"; + } +} diff --git a/src/main/java/baritone/pathfinding/goals/GoalXZ.java b/src/main/java/baritone/pathfinding/goals/GoalXZ.java new file mode 100644 index 00000000..c9df9629 --- /dev/null +++ b/src/main/java/baritone/pathfinding/goals/GoalXZ.java @@ -0,0 +1,73 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import baritone.pathfinding.actions.Action; +import net.minecraft.util.math.BlockPos; + +/** + * Useful for long-range goals that don't have a specific Y level. + * @author leijurv + */ +public class GoalXZ implements Goal { + final int x; + final int z; + public GoalXZ(int x, int z) { + this.x = x; + this.z = z; + } + @Override + public boolean isInGoal(BlockPos pos) { + return pos.getX() == x && pos.getZ() == z; + } + @Override + public double heuristic(BlockPos pos) {//mostly copied from GoalBlock + double xDiff = pos.getX() - this.x; + double zDiff = pos.getZ() - this.z; + return calculate(xDiff, zDiff); + } + public static double calculate(double xDiff, double zDiff) { + return calculate(xDiff, zDiff, 0); + } + /* + public static double calculate(double xDiff, double zDiff) { + double pythaDist = Math.sqrt(xDiff * xDiff + zDiff * zDiff); + return calculate(xDiff, zDiff, pythaDist); + } + public static double calculateOld(double xDiff, double zDiff, double pythaDist) { + double heuristic = 0; + heuristic += Math.abs(xDiff) * Action.WALK_ONE_BLOCK_COST * 1.1;//overestimate + heuristic += Math.abs(zDiff) * Action.WALK_ONE_BLOCK_COST * 1.1; + heuristic += pythaDist / 10 * Action.WALK_ONE_BLOCK_COST; + return heuristic; + } + */ + static final double sq = Math.sqrt(2); + public static double calculate(double xDiff, double zDiff, double pythaDist) { + //This is a combination of pythagorean and manhattan distance + //It takes into account the fact that pathing can either walk diagonally or forwards + + //It's not possible to walk forward 1 and right 2 in sqrt(5) time + //It's really 1+sqrt(2) because it'll walk forward 1 then diagonally 1 + double x = Math.abs(xDiff); + double z = Math.abs(zDiff); + double straight; + double diagonal; + if (x < z) { + straight = z - x; + diagonal = x; + } else { + straight = x - z; + diagonal = z; + } + diagonal *= sq; + return (diagonal + straight) * Action.WALK_ONE_BLOCK_COST; + } + @Override + public String toString() { + return "Goal{x=" + x + ",z=" + z + "}"; + } +} diff --git a/src/main/java/baritone/pathfinding/goals/GoalYLevel.java b/src/main/java/baritone/pathfinding/goals/GoalYLevel.java new file mode 100644 index 00000000..f0f6223c --- /dev/null +++ b/src/main/java/baritone/pathfinding/goals/GoalYLevel.java @@ -0,0 +1,32 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package baritone.pathfinding.goals; + +import net.minecraft.util.math.BlockPos; + +/** + * Useful for mining (getting to diamond / iron level) + * @author leijurv + */ +public class GoalYLevel implements Goal { + final int level; + public GoalYLevel(int level) { + this.level = level; + } + @Override + public boolean isInGoal(BlockPos pos) { + return pos.getY() == level; + } + @Override + public double heuristic(BlockPos pos) { + return 20 * Math.abs(pos.getY() - level);//the number 20 was chosen somewhat randomly. + //TODO fix that + } + @Override + public String toString() { + return "Goal{y=" + level + "}"; + } +}