From 36cfcbbbe3cfcb0d6b609da31cf6306e22cdbaa7 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 2 Dec 2018 19:25:59 -0800 Subject: [PATCH] avoidances --- .../baritone/behavior/PathingBehavior.java | 12 +-- .../pathing/calc/AStarPathFinder.java | 16 +-- .../{AvoidanceHelper.java => Avoidance.java} | 51 +++++++-- .../java/baritone/utils/pathing/Favoring.java | 100 ++++++++++++++++++ 4 files changed, 151 insertions(+), 28 deletions(-) rename src/main/java/baritone/utils/pathing/{AvoidanceHelper.java => Avoidance.java} (51%) create mode 100644 src/main/java/baritone/utils/pathing/Favoring.java diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index ec83a268..53bea705 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -37,8 +37,7 @@ import baritone.pathing.path.CutoffPath; import baritone.pathing.path.PathExecutor; import baritone.utils.Helper; import baritone.utils.PathRenderer; -import baritone.utils.pathing.AvoidanceHelper; -import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; +import baritone.utils.pathing.Favoring; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.EmptyChunk; @@ -504,13 +503,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, transformed = new GoalXZ(pos.getX(), pos.getZ()); } } - Long2DoubleOpenHashMap favoredPositions = new Long2DoubleOpenHashMap(); - double coeff = Baritone.settings().backtrackCostFavoringCoefficient.get(); - if (coeff != 1D && previous != null) { - previous.positions().forEach(pos -> favoredPositions.put(BetterBlockPos.longHash(pos), coeff)); - } - AvoidanceHelper.INSTANCE.apply(favoredPositions, context.getBaritone().getPlayerContext()); - return new AStarPathFinder(start.getX(), start.getY(), start.getZ(), transformed, favoredPositions, context); + Favoring favoring = new Favoring(context.getBaritone().getPlayerContext(), previous); + return new AStarPathFinder(start.getX(), start.getY(), start.getZ(), transformed, favoring, context); } @Override diff --git a/src/main/java/baritone/pathing/calc/AStarPathFinder.java b/src/main/java/baritone/pathing/calc/AStarPathFinder.java index 14b17b80..06f25d9c 100644 --- a/src/main/java/baritone/pathing/calc/AStarPathFinder.java +++ b/src/main/java/baritone/pathing/calc/AStarPathFinder.java @@ -27,8 +27,8 @@ import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Moves; import baritone.utils.Helper; import baritone.utils.pathing.BetterWorldBorder; +import baritone.utils.pathing.Favoring; import baritone.utils.pathing.MutableMoveResult; -import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import java.util.Optional; @@ -39,12 +39,12 @@ import java.util.Optional; */ public final class AStarPathFinder extends AbstractNodeCostSearch implements Helper { - private final Long2DoubleOpenHashMap favoredPositions; + private final Favoring favoring; private final CalculationContext calcContext; - public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Long2DoubleOpenHashMap favoredPositions, CalculationContext context) { + public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) { super(startX, startY, startZ, goal, context); - this.favoredPositions = favoredPositions; + this.favoring = favoring; this.calcContext = context; } @@ -63,8 +63,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel bestSoFar[i] = startNode; } MutableMoveResult res = new MutableMoveResult(); - Long2DoubleOpenHashMap favored = favoredPositions; - favored.defaultReturnValue(1.0D); + Favoring favored = favoring; BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world().getWorldBorder()); long startTime = System.nanoTime() / 1000000L; boolean slowPath = Baritone.settings().slowPath.get(); @@ -97,6 +96,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel mostRecentConsidered = currentNode; numNodes++; if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) { + favored.printStats(); logDebug("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, " + numMovementsConsidered + " movements considered"); return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext)); } @@ -137,10 +137,9 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset)); } long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z); - favored.get(hashCode); if (favoring) { // see issue #18 - actionCost *= favored.get(hashCode); + actionCost *= favored.calculate(res.x, res.y, res.z, hashCode); } PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode); double tentativeCost = currentNode.cost + actionCost; @@ -178,6 +177,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel } } } + favored.printStats(); if (cancelRequested) { return Optional.empty(); } diff --git a/src/main/java/baritone/utils/pathing/AvoidanceHelper.java b/src/main/java/baritone/utils/pathing/Avoidance.java similarity index 51% rename from src/main/java/baritone/utils/pathing/AvoidanceHelper.java rename to src/main/java/baritone/utils/pathing/Avoidance.java index 0201eef2..92170849 100644 --- a/src/main/java/baritone/utils/pathing/AvoidanceHelper.java +++ b/src/main/java/baritone/utils/pathing/Avoidance.java @@ -24,32 +24,61 @@ import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import net.minecraft.entity.monster.EntityMob; import net.minecraft.util.math.BlockPos; -public enum AvoidanceHelper { - INSTANCE; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; - public void apply(Long2DoubleOpenHashMap map, IPlayerContext ctx) { +public class Avoidance { + public final int centerX; + public final int centerY; + public final int centerZ; + public final double coefficient; + public final int radius; + public final int radiusSq; + + public Avoidance(BlockPos center, double coefficient, int radius) { + this(center.getX(), center.getY(), center.getZ(), coefficient, radius); + } + + public Avoidance(int centerX, int centerY, int centerZ, double coefficient, int radius) { + this.centerX = centerX; + this.centerY = centerY; + this.centerZ = centerZ; + this.coefficient = coefficient; + this.radius = radius; + this.radiusSq = radius * radius; + } + + public double coefficient(int x, int y, int z) { + int xDiff = x - centerX; + int yDiff = y - centerY; + int zDiff = z - centerZ; + return xDiff * xDiff + yDiff * yDiff + zDiff * zDiff <= radiusSq ? coefficient : 1.0D; + } + + public static List create(IPlayerContext ctx) { if (!Baritone.settings().avoidance.get()) { - return; + return Collections.emptyList(); } - long start = System.currentTimeMillis(); + List res = new ArrayList<>(); double mobSpawnerCoeff = Baritone.settings().mobSpawnerAvoidanceCoefficient.get(); double mobCoeff = Baritone.settings().mobAvoidanceCoefficient.get(); if (mobSpawnerCoeff != 1.0D) { - ctx.worldData().getCachedWorld().getLocationsOf("mob_spawner", 1, ctx.playerFeet().x, ctx.playerFeet().z, 2).forEach(mobspawner -> sphere(mobspawner, Baritone.settings().mobSpawnerAvoidanceRadius.get(), map, mobSpawnerCoeff)); + ctx.worldData().getCachedWorld().getLocationsOf("mob_spawner", 1, ctx.playerFeet().x, ctx.playerFeet().z, 2).forEach(mobspawner -> res.add(new Avoidance(mobspawner, mobSpawnerCoeff, Baritone.settings().mobSpawnerAvoidanceRadius.get()))); } if (mobCoeff != 1.0D) { - ctx.world().loadedEntityList.stream().filter(entity -> entity instanceof EntityMob).forEach(entity -> sphere(new BlockPos(entity), Baritone.settings().mobAvoidanceRadius.get(), map, mobCoeff)); + ctx.world().loadedEntityList.stream().filter(entity -> entity instanceof EntityMob).forEach(entity -> res.add(new Avoidance(new BlockPos(entity), mobCoeff, Baritone.settings().mobAvoidanceRadius.get()))); } - long end = System.currentTimeMillis(); - System.out.println("Took " + (end - start) + "ms to generate avoidance of " + map.size() + " blocks"); + return res; } - private void sphere(BlockPos center, int radius, Long2DoubleOpenHashMap map, double coeff) { + public void applySpherical(Long2DoubleOpenHashMap map) { for (int x = -radius; x <= radius; x++) { for (int y = -radius; y <= radius; y++) { for (int z = -radius; z <= radius; z++) { if (x * x + y * y + z * z <= radius * radius) { - map.put(BetterBlockPos.longHash(center.getX() + x, center.getY() + y, center.getZ() + z), coeff); + long hash = BetterBlockPos.longHash(centerX + x, centerY + y, centerZ + z); + map.put(hash, map.get(hash) * coefficient); } } } diff --git a/src/main/java/baritone/utils/pathing/Favoring.java b/src/main/java/baritone/utils/pathing/Favoring.java new file mode 100644 index 00000000..e39d3165 --- /dev/null +++ b/src/main/java/baritone/utils/pathing/Favoring.java @@ -0,0 +1,100 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser 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, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.utils.pathing; + +import baritone.Baritone; +import baritone.api.pathing.calc.IPath; +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.IPlayerContext; +import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; + +import java.util.List; + +public class Favoring { + private final LongOpenHashSet backtrackFavored = new LongOpenHashSet(); + private final double backtrackCoefficient; + + private final List avoidances; + + private final Long2DoubleOpenHashMap favorings = new Long2DoubleOpenHashMap(); + + private long mapMethodNano = 0; + private long hybridMethodNano = 0; + + + public Favoring(IPlayerContext ctx, IPath previous) { + long start = System.currentTimeMillis(); + backtrackCoefficient = Baritone.settings().backtrackCostFavoringCoefficient.get(); + if (backtrackCoefficient != 1D && previous != null) { + previous.positions().forEach(pos -> backtrackFavored.add(BetterBlockPos.longHash(pos))); + } + + avoidances = Avoidance.create(ctx); + long end = System.currentTimeMillis(); + System.out.println("Hybrid method init took " + (end - start) + "ms"); + + favorings.defaultReturnValue(1.0D); + backtrackFavored.forEach(l -> favorings.put((long) l, backtrackCoefficient)); + for (Avoidance avoid : avoidances) { + avoid.applySpherical(favorings); + } + long end2 = System.currentTimeMillis(); + System.out.println("Map method init took " + (end2 - end) + "ms"); + System.out.println("Size: " + favorings.size()); + } + + public void printStats() { + System.out.println("Map method nanos: " + mapMethodNano); + System.out.println("Hybrid method nano: " + hybridMethodNano); + } + + public boolean isEmpty() { + return backtrackFavored.isEmpty() && favorings.isEmpty() && avoidances.isEmpty(); + } + + public double calculate(int x, int y, int z, long hash) { + long start = System.nanoTime(); + double result = calculateMap(x, y, z, hash); + long mid = System.nanoTime(); + double result2 = calculateHybrid(x, y, z, hash); + long end = System.nanoTime(); + mapMethodNano += mid - start; + hybridMethodNano += end - mid; + if (result != result2) { + System.out.println("NO MATCH " + result + " " + result2); + } + return result; + } + + + public double calculateMap(int x, int y, int z, long hash) { + return favorings.get(hash); + } + + public double calculateHybrid(int x, int y, int z, long hash) { + double result = 1.0D; + if (backtrackFavored.contains(hash)) { + result *= backtrackCoefficient; + } + for (Avoidance avoid : avoidances) { + result *= avoid.coefficient(x, y, z); + } + return result; + } +}