add a secondary failure cutoff

This commit is contained in:
Leijurv 2018-11-22 09:39:54 -08:00 committed by Brady
parent 5aa78cd478
commit 7632d667c9
5 changed files with 48 additions and 25 deletions

View File

@ -247,14 +247,24 @@ public class Settings {
public Setting<Integer> movementTimeoutTicks = new Setting<>(100); public Setting<Integer> movementTimeoutTicks = new Setting<>(100);
/** /**
* Pathing can never take longer than this * Pathing ends after this amount of time, if a path has been found
*/ */
public Setting<Long> pathTimeoutMS = new Setting<>(2000L); public Setting<Long> primaryTimeoutMS = new Setting<>(500L);
/** /**
* Planning ahead while executing a segment can never take longer than this * Pathing can never take longer than this, even if that means failing to find any path at all
*/ */
public Setting<Long> planAheadTimeoutMS = new Setting<>(4000L); public Setting<Long> failureTimeoutMS = new Setting<>(2000L);
/**
* Planning ahead while executing a segment ends after this amount of time, if a path has been found
*/
public Setting<Long> planAheadPrimaryTimeoutMS = new Setting<>(4000L);
/**
* Planning ahead while executing a segment can never take longer than this, even if that means failing to find any path at all
*/
public Setting<Long> planAheadFailureTimeoutMS = new Setting<>(5000L);
/** /**
* For debugging, consider nodes much much slower * For debugging, consider nodes much much slower

View File

@ -36,7 +36,7 @@ public interface IPathFinder {
* *
* @return The final path * @return The final path
*/ */
PathCalculationResult calculate(long timeout); PathCalculationResult calculate(long primaryTimeout, long failureTimeout);
/** /**
* Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet * Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet

View File

@ -40,7 +40,10 @@ import baritone.utils.PathRenderer;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk; import net.minecraft.world.chunk.EmptyChunk;
import java.util.*; import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Optional;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -396,11 +399,14 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
logDebug("no goal"); // TODO should this be an exception too? definitely should be checked by caller logDebug("no goal"); // TODO should this be an exception too? definitely should be checked by caller
return; return;
} }
long timeout; long primaryTimeout;
long failureTimeout;
if (current == null) { if (current == null) {
timeout = Baritone.settings().pathTimeoutMS.<Long>get(); primaryTimeout = Baritone.settings().primaryTimeoutMS.get();
failureTimeout = Baritone.settings().failureTimeoutMS.get();
} else { } else {
timeout = Baritone.settings().planAheadTimeoutMS.<Long>get(); primaryTimeout = Baritone.settings().planAheadPrimaryTimeoutMS.get();
failureTimeout = Baritone.settings().planAheadFailureTimeoutMS.get();
} }
CalculationContext context = new CalculationContext(baritone); // not safe to create on the other thread, it looks up a lot of stuff in minecraft CalculationContext context = new CalculationContext(baritone); // not safe to create on the other thread, it looks up a lot of stuff in minecraft
AbstractNodeCostSearch pathfinder = createPathfinder(start, goal, current == null ? null : current.getPath(), context); AbstractNodeCostSearch pathfinder = createPathfinder(start, goal, current == null ? null : current.getPath(), context);
@ -410,7 +416,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
logDebug("Starting to search for path from " + start + " to " + goal); logDebug("Starting to search for path from " + start + " to " + goal);
} }
PathCalculationResult calcResult = pathfinder.calculate(timeout); PathCalculationResult calcResult = pathfinder.calculate(primaryTimeout, failureTimeout);
Optional<IPath> path = calcResult.getPath(); Optional<IPath> path = calcResult.getPath();
if (Baritone.settings().cutoffAtLoadBoundary.get()) { if (Baritone.settings().cutoffAtLoadBoundary.get()) {
path = path.map(p -> { path = path.map(p -> {

View File

@ -49,7 +49,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
} }
@Override @Override
protected Optional<IPath> calculate0(long timeout) { protected Optional<IPath> calculate0(long primaryTimeout, long failureTimeout) {
startNode = getNodeAtPosition(startX, startY, startZ, BetterBlockPos.longHash(startX, startY, startZ)); startNode = getNodeAtPosition(startX, startY, startZ, BetterBlockPos.longHash(startX, startY, startZ));
startNode.cost = 0; startNode.cost = 0;
startNode.combinedCost = startNode.estimatedCostToGoal; startNode.combinedCost = startNode.estimatedCostToGoal;
@ -68,10 +68,11 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
long startTime = System.nanoTime() / 1000000L; long startTime = System.nanoTime() / 1000000L;
boolean slowPath = Baritone.settings().slowPath.get(); boolean slowPath = Baritone.settings().slowPath.get();
if (slowPath) { if (slowPath) {
logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + timeout + "ms"); logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + primaryTimeout + "ms");
} }
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : timeout); long primaryTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : primaryTimeout);
//long lastPrintout = 0; long failureTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : failureTimeout);
boolean failing = true;
int numNodes = 0; int numNodes = 0;
int numMovementsConsidered = 0; int numMovementsConsidered = 0;
int numEmptyChunk = 0; int numEmptyChunk = 0;
@ -79,7 +80,14 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get(); double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get();
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get(); boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.nanoTime() / 1000000L - timeoutTime < 0 && !cancelRequested) { while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
long now = System.nanoTime() / 1000000L;
if (now - failureTimeoutTime >= 0 || (!failing && now - primaryTimeoutTime >= 0)) {
break;
}
if (failing == bestPathSoFar().isPresent()) {
throw new IllegalStateException();
}
if (slowPath) { if (slowPath) {
try { try {
Thread.sleep(Baritone.settings().slowPathTimeDelayMS.<Long>get()); Thread.sleep(Baritone.settings().slowPathTimeDelayMS.<Long>get());
@ -166,6 +174,9 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
} }
bestHeuristicSoFar[i] = heuristic; bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor; bestSoFar[i] = neighbor;
if (getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
failing = false;
}
} }
} }
} }

View File

@ -83,13 +83,14 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
cancelRequested = true; cancelRequested = true;
} }
public synchronized PathCalculationResult calculate(long timeout) { @Override
public synchronized PathCalculationResult calculate(long primaryTimeout, long failureTimeout) {
if (isFinished) { if (isFinished) {
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!"); throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
} }
cancelRequested = false; cancelRequested = false;
try { try {
IPath path = calculate0(timeout).map(IPath::postProcess).orElse(null); IPath path = calculate0(primaryTimeout, failureTimeout).map(IPath::postProcess).orElse(null);
isFinished = true; isFinished = true;
if (cancelRequested) { if (cancelRequested) {
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, path); return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, path);
@ -112,7 +113,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
} }
} }
protected abstract Optional<IPath> calculate0(long timeout); protected abstract Optional<IPath> calculate0(long primaryTimeout, long failureTimeout);
/** /**
* Determines the distance squared from the specified node to the start * Determines the distance squared from the specified node to the start
@ -157,7 +158,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
@Override @Override
public Optional<IPath> bestPathSoFar() { public Optional<IPath> bestPathSoFar() {
if (startNode == null || bestSoFar == null || bestSoFar[0] == null) { if (startNode == null || bestSoFar == null) {
return Optional.empty(); return Optional.empty();
} }
for (int i = 0; i < bestSoFar.length; i++) { for (int i = 0; i < bestSoFar.length; i++) {
@ -165,12 +166,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
continue; continue;
} }
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
try { return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
} catch (IllegalStateException ex) {
System.out.println("Unable to construct path to render");
return Optional.empty();
}
} }
} }
// instead of returning bestSoFar[0], be less misleading // instead of returning bestSoFar[0], be less misleading