baritone/src/main/java/baritone/bot/pathing/calc/AbstractNodeCostSearch.java

153 lines
4.9 KiB
Java
Raw Normal View History

2018-08-08 03:16:53 +00:00
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
2018-08-08 03:16:53 +00:00
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
2018-08-03 04:50:45 +00:00
package baritone.bot.pathing.calc;
import baritone.bot.pathing.goals.Goal;
2018-08-05 03:25:05 +00:00
import baritone.bot.pathing.path.IPath;
2018-08-14 17:47:31 +00:00
import baritone.bot.utils.pathing.BetterBlockPos;
2018-08-03 04:50:45 +00:00
import net.minecraft.util.math.BlockPos;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
2018-08-03 04:50:45 +00:00
2018-08-03 13:55:17 +00:00
/**
* Any pathfinding algorithm that keeps track of nodes recursively by their cost (e.g. A*, dijkstra)
*
* @author leijurv
*/
2018-08-03 04:50:45 +00:00
public abstract class AbstractNodeCostSearch implements IPathFinder {
/**
* The currently running search task
*/
protected static AbstractNodeCostSearch currentlyRunning = null;
2018-08-03 04:50:45 +00:00
2018-08-14 17:47:31 +00:00
protected final BetterBlockPos start;
2018-08-03 04:50:45 +00:00
protected final Goal goal;
2018-08-14 17:47:31 +00:00
protected final Map<BetterBlockPos, PathNode> map;
2018-08-03 04:50:45 +00:00
protected PathNode startNode;
2018-08-03 04:50:45 +00:00
protected PathNode mostRecentConsidered;
2018-08-03 04:50:45 +00:00
protected PathNode[] bestSoFar;
2018-08-03 04:50:45 +00:00
private volatile boolean isFinished;
/**
* This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so
* long it was easier as a Google Doc (because I could insert charts).
*
* @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit"></a>
2018-08-03 04:50:45 +00:00
*/
2018-08-18 02:52:35 +00:00
protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10}; // big TODO tune
2018-08-03 05:06:49 +00:00
/**
* If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering.
*/
protected final static double MIN_DIST_PATH = 5;
2018-08-03 04:50:45 +00:00
2018-08-03 05:06:49 +00:00
AbstractNodeCostSearch(BlockPos start, Goal goal) {
2018-08-14 17:47:31 +00:00
this.start = new BetterBlockPos(start.getX(), start.getY(), start.getZ());
2018-08-03 04:50:45 +00:00
this.goal = goal;
this.map = new HashMap<>();
}
public synchronized Optional<IPath> calculate() {
2018-08-03 04:50:45 +00:00
if (isFinished) {
2018-08-14 17:47:31 +00:00
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
2018-08-03 04:50:45 +00:00
}
Optional<IPath> path = calculate0();
2018-08-03 04:50:45 +00:00
isFinished = true;
return path;
}
protected abstract Optional<IPath> calculate0();
2018-08-03 04:50:45 +00:00
/**
* Determines the distance squared from the specified node to the start
* node. Intended for use in distance comparison, rather than anything that
* considers the real distance value, hence the "sq".
*
* @param n A node
* @return The distance, squared
*/
protected double getDistFromStartSq(PathNode n) {
2018-08-03 05:06:49 +00:00
int xDiff = n.pos.getX() - start.getX();
int yDiff = n.pos.getY() - start.getY();
int zDiff = n.pos.getZ() - start.getZ();
return xDiff * xDiff + yDiff * yDiff + zDiff * zDiff;
2018-08-03 04:50:45 +00:00
}
/**
* Attempts to search the {@link BlockPos} to {@link PathNode} map
* for the node mapped to the specified pos. If no node is found,
* a new node is created.
*
* @param pos The pos to lookup
* @return The associated node
*/
2018-08-14 17:47:31 +00:00
protected PathNode getNodeAtPosition(BetterBlockPos pos) {
return map.computeIfAbsent(pos, p -> new PathNode(p, goal));
2018-08-03 04:50:45 +00:00
}
@Override
public Optional<IPath> pathToMostRecentNodeConsidered() {
2018-08-14 17:50:41 +00:00
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0));
2018-08-03 04:50:45 +00:00
}
@Override
public Optional<IPath> bestPathSoFar() {
if (startNode == null || bestSoFar[0] == null) {
return Optional.empty();
}
for (int i = 0; i < bestSoFar.length; i++) {
if (bestSoFar[i] == null) {
continue;
}
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
return Optional.of(new Path(startNode, bestSoFar[i], 0));
}
}
// instead of returning bestSoFar[0], be less misleading
// if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen
return Optional.empty();
2018-08-03 04:50:45 +00:00
}
2018-08-03 05:06:49 +00:00
@Override
public final boolean isFinished() {
return isFinished;
}
@Override
public final Goal getGoal() {
return goal;
}
@Override
public final BlockPos getStart() {
return start;
}
public static Optional<AbstractNodeCostSearch> getCurrentlyRunning() {
return Optional.ofNullable(currentlyRunning);
}
2018-08-03 04:50:45 +00:00
}