path finding
This commit is contained in:
		
							
								
								
									
										180
									
								
								src/main/java/baritone/bot/pathing/calc/AStarPathFinder.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								src/main/java/baritone/bot/pathing/calc/AStarPathFinder.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| package baritone.bot.pathing.calc; | ||||
|  | ||||
|  | ||||
| import baritone.Baritone; | ||||
| import baritone.bot.pathing.goals.Goal; | ||||
| import baritone.bot.pathing.movement.ActionCosts; | ||||
| import baritone.bot.pathing.movement.Movement; | ||||
| import baritone.bot.utils.ToolSet; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
| import net.minecraft.world.chunk.EmptyChunk; | ||||
|  | ||||
| import java.util.Random; | ||||
| import java.util.logging.Level; | ||||
| import java.util.logging.Logger; | ||||
|  | ||||
| /** | ||||
|  * The actual A* pathfinding | ||||
|  * | ||||
|  * @author leijurv | ||||
|  */ | ||||
| public class AStarPathFinder extends AbstractNodeCostSearch { | ||||
|     public AStarPathFinder(BlockPos start, Goal goal) { | ||||
|         super(start, goal); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected IPath calculate0() { | ||||
|         startNode = getNodeAtPosition(start); | ||||
|         startNode.cost = 0; | ||||
|         IOpenSet openSet = new LinkedListOpenSet(); | ||||
|         startNode.isOpen = true; | ||||
|         openSet.insert(startNode); | ||||
|         bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i]) | ||||
|         double[] bestHeuristicSoFar = new double[COEFFICIENTS.length]; | ||||
|         for (int i = 0; i < bestHeuristicSoFar.length; i++) { | ||||
|             bestHeuristicSoFar[i] = Double.MAX_VALUE; | ||||
|         } | ||||
|         currentlyRunning = this; | ||||
|         long startTime = System.currentTimeMillis(); | ||||
|         long timeoutTime = startTime + (Baritone.slowPath ? 40000 : 4000); | ||||
|         long lastPrintout = 0; | ||||
|         int numNodes = 0; | ||||
|         ToolSet ts = new ToolSet(); | ||||
|         int numEmptyChunk = 0; | ||||
|         while (!openSet.isEmpty() && numEmptyChunk < 50 && System.currentTimeMillis() < timeoutTime) { | ||||
|             if (Baritone.slowPath) { | ||||
|                 try { | ||||
|                     Thread.sleep(100); | ||||
|                 } catch (InterruptedException ex) { | ||||
|                     Logger.getLogger(AStarPathFinder.class.getName()).log(Level.SEVERE, null, ex); | ||||
|                 } | ||||
|             } | ||||
|             PathNode currentNode = openSet.removeLowest(); | ||||
|             mostRecentConsidered = currentNode; | ||||
|             currentNode.isOpen = false; | ||||
|             currentNode.nextOpen = null; | ||||
|             BlockPos currentNodePos = currentNode.pos; | ||||
|             numNodes++; | ||||
|             if (System.currentTimeMillis() > lastPrintout + 1000) {//print once a second | ||||
|                 System.out.println("searching... at " + currentNodePos + ", considered " + numNodes + " nodes so far"); | ||||
|                 lastPrintout = System.currentTimeMillis(); | ||||
|             } | ||||
|             if (goal.isInGoal(currentNodePos)) { | ||||
|                 currentlyRunning = null; | ||||
|                 return new Path(startNode, currentNode, goal); | ||||
|             } | ||||
|             //long constructStart = System.nanoTime(); | ||||
|             Movement[] possibleMovements = getConnectedPositions(currentNodePos);//movement that we could take that start at myPos, in random order | ||||
|             shuffle(possibleMovements); | ||||
|             //long constructEnd = System.nanoTime(); | ||||
|             //System.out.println(constructEnd - constructStart); | ||||
|             for (Movement movementToGetToNeighbor : possibleMovements) { | ||||
|                 //long costStart = System.nanoTime(); | ||||
|                 // TODO cache cost | ||||
|                 double actionCost = movementToGetToNeighbor.calculateCost(ts); | ||||
|                 //long costEnd = System.nanoTime(); | ||||
|                 //System.out.println(movementToGetToNeighbor.getClass() + "" + (costEnd - costStart)); | ||||
|                 if (actionCost >= ActionCosts.COST_INF) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 if (Minecraft.getMinecraft().world.getChunk(movementToGetToNeighbor.getDest()) instanceof EmptyChunk) { | ||||
|                     numEmptyChunk++; | ||||
|                     continue; | ||||
|                 } | ||||
|                 PathNode neighbor = getNodeAtPosition(movementToGetToNeighbor.getDest()); | ||||
|                 double tentativeCost = currentNode.cost + actionCost; | ||||
|                 if (tentativeCost < neighbor.cost) { | ||||
|                     neighbor.previous = currentNode; | ||||
|                     neighbor.previousMovement = movementToGetToNeighbor; | ||||
|                     neighbor.cost = tentativeCost; | ||||
|                     if (!neighbor.isOpen) { | ||||
|                         openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there | ||||
|                         neighbor.isOpen = true; | ||||
|                     } | ||||
|                     for (int i = 0; i < bestSoFar.length; i++) { | ||||
|                         double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i]; | ||||
|                         if (heuristic < bestHeuristicSoFar[i]) { | ||||
|                             bestHeuristicSoFar[i] = heuristic; | ||||
|                             bestSoFar[i] = neighbor; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         double bestDist = 0; | ||||
|         for (int i = 0; i < bestSoFar.length; i++) { | ||||
|             if (bestSoFar[i] == null) { | ||||
|                 continue; | ||||
|             } | ||||
|             double dist = getDistFromStartSq(bestSoFar[i]); | ||||
|             if (dist > bestDist) { | ||||
|                 bestDist = dist; | ||||
|             } | ||||
|             if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared | ||||
|                 System.out.println("A* cost coefficient " + COEFFICIENTS[i]); | ||||
|                 if (COEFFICIENTS[i] >= 3) { | ||||
|                     System.out.println("Warning: cost coefficient is greater than three! Probably means that"); | ||||
|                     System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)"); | ||||
|                     System.out.println("But I'm going to do it anyway, because yolo"); | ||||
|                 } | ||||
|                 System.out.println("Path goes for " + dist + " blocks"); | ||||
|                 currentlyRunning = null; | ||||
|                 return new Path(startNode, bestSoFar[i], goal); | ||||
|             } | ||||
|         } | ||||
|         System.out.println("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + bestDist + " blocks =("); | ||||
|         System.out.println("No path found =("); | ||||
|         currentlyRunning = null; | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     private static Movement[] getConnectedPositions(BlockPos pos) { | ||||
|         int x = pos.getX(); | ||||
|         int y = pos.getY(); | ||||
|         int z = pos.getZ(); | ||||
|         /*Action[] actions = new Action[26]; | ||||
|         actions[0] = new ActionPillar(pos); | ||||
|         actions[1] = new ActionBridge(pos, new BlockPos(x + 1, y, z)); | ||||
|         actions[2] = new ActionBridge(pos, new BlockPos(x - 1, y, z)); | ||||
|         actions[3] = new ActionBridge(pos, new BlockPos(x, y, z + 1)); | ||||
|         actions[4] = new ActionBridge(pos, new BlockPos(x, y, z - 1)); | ||||
|         actions[5] = new ActionClimb(pos, new BlockPos(x + 1, y + 1, z)); | ||||
|         actions[6] = new ActionClimb(pos, new BlockPos(x - 1, y + 1, z)); | ||||
|         actions[7] = new ActionClimb(pos, new BlockPos(x, y + 1, z + 1)); | ||||
|         actions[8] = new ActionClimb(pos, new BlockPos(x, y + 1, z - 1)); | ||||
|         actions[9] = new ActionDescend(pos, new BlockPos(x, y - 1, z - 1)); | ||||
|         actions[10] = new ActionDescend(pos, new BlockPos(x, y - 1, z + 1)); | ||||
|         actions[11] = new ActionDescend(pos, new BlockPos(x - 1, y - 1, z)); | ||||
|         actions[12] = new ActionDescend(pos, new BlockPos(x + 1, y - 1, z)); | ||||
|         actions[13] = new ActionFall(pos); | ||||
|         actions[14] = new ActionDescendTwo(pos, new BlockPos(x, y - 2, z - 1)); | ||||
|         actions[15] = new ActionDescendTwo(pos, new BlockPos(x, y - 2, z + 1)); | ||||
|         actions[16] = new ActionDescendTwo(pos, new BlockPos(x - 1, y - 2, z)); | ||||
|         actions[17] = new ActionDescendTwo(pos, new BlockPos(x + 1, y - 2, z)); | ||||
|         actions[18] = new ActionDescendThree(pos, new BlockPos(x, y - 3, z - 1)); | ||||
|         actions[19] = new ActionDescendThree(pos, new BlockPos(x, y - 3, z + 1)); | ||||
|         actions[20] = new ActionDescendThree(pos, new BlockPos(x - 1, y - 3, z)); | ||||
|         actions[21] = new ActionDescendThree(pos, new BlockPos(x + 1, y - 3, z)); | ||||
|         actions[22] = new ActionWalkDiagonal(pos, EnumFacing.NORTH, EnumFacing.WEST); | ||||
|         actions[23] = new ActionWalkDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST); | ||||
|         actions[24] = new ActionWalkDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST); | ||||
|         actions[25] = new ActionWalkDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST); | ||||
|         return actions;*/ | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private final Random random = new Random(); | ||||
|  | ||||
|     private <T> void shuffle(T[] list) { | ||||
|         int len = list.length; | ||||
|         for (int i = 0; i < len; i++) { | ||||
|             int j = random.nextInt(len); | ||||
|             T t = list[j]; | ||||
|             list[j] = list[i]; | ||||
|             list[i] = t; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -6,11 +6,16 @@ import net.minecraft.util.math.BlockPos; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * Any pathfinding algorithm that keeps track of nodes recursively by their cost (e.g. A*, dijkstra) | ||||
|  * | ||||
|  * @author leijurv | ||||
|  */ | ||||
| public abstract class AbstractNodeCostSearch implements IPathFinder { | ||||
|  | ||||
|     /** | ||||
|      * The currently running search task | ||||
|      * | ||||
|      * <p> | ||||
|      * TODO: This shouldn't be necessary, investigate old purpose of this field and determine necessity. | ||||
|      */ | ||||
|     public static AbstractNodeCostSearch currentlyRunning = null; | ||||
| @@ -63,10 +68,9 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { | ||||
|      * node. Intended for use in distance comparison, rather than anything that | ||||
|      * considers the real distance value, hence the "sq". | ||||
|      * | ||||
|      * @see AbstractNodeCostSearch#getDistFromStart(PathNode) | ||||
|      * | ||||
|      * @param n A node | ||||
|      * @return The distance, squared | ||||
|      * @see AbstractNodeCostSearch#getDistFromStart(PathNode) | ||||
|      */ | ||||
|     protected double getDistFromStartSq(PathNode n) { | ||||
|         int xDiff = n.pos.getX() - start.getX(); | ||||
|   | ||||
							
								
								
									
										465
									
								
								src/main/java/baritone/bot/pathing/calc/FibonacciHeap.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										465
									
								
								src/main/java/baritone/bot/pathing/calc/FibonacciHeap.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,465 @@ | ||||
| //Source: https://github.com/nlfiedler/graphmaker/blob/master/core/src/com/bluemarsh/graphmaker/core/util/FibonacciHeap.java | ||||
| package baritone.bot.pathing.calc; | ||||
| /* | ||||
|  * The contents of this file are subject to the terms of the Common Development | ||||
|  * and Distribution License (the License). You may not use this file except in | ||||
|  * compliance with the License. | ||||
|  * | ||||
|  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html | ||||
|  * or http://www.netbeans.org/cddl.txt. | ||||
|  * | ||||
|  * When distributing Covered Code, include this CDDL Header Notice in each file | ||||
|  * and include the License file at http://www.netbeans.org/cddl.txt. | ||||
|  * If applicable, add the following below the CDDL Header, with the fields | ||||
|  * enclosed by brackets [] replaced by your own identifying information: | ||||
|  * "Portions Copyrighted [year] [name of copyright owner]" | ||||
|  * | ||||
|  * The Original Software is GraphMaker. The Initial Developer of the Original | ||||
|  * Software is Nathan L. Fiedler. Portions created by Nathan L. Fiedler | ||||
|  * are Copyright (C) 1999-2008. All Rights Reserved. | ||||
|  * | ||||
|  * Contributor(s): Nathan L. Fiedler. | ||||
|  * | ||||
|  * $Id$ | ||||
|  */ | ||||
| //package com.bluemarsh.graphmaker.core.util; | ||||
|  | ||||
| /** | ||||
|  * This class implements a Fibonacci heap data structure. Much of the | ||||
|  * code in this class is based on the algorithms in Chapter 21 of the | ||||
|  * "Introduction to Algorithms" by Cormen, Leiserson, Rivest, and Stein. | ||||
|  * The amortized running time of most of these methods is O(1), making | ||||
|  * it a very fast data structure. Several have an actual running time | ||||
|  * of O(1). removeMin() and delete() have O(log n) amortized running | ||||
|  * times because they do the heap consolidation. | ||||
|  * | ||||
|  * <p><strong>Note that this implementation is not synchronized.</strong> | ||||
|  * If multiple threads access a set concurrently, and at least one of the | ||||
|  * threads modifies the set, it <em>must</em> be synchronized externally. | ||||
|  * This is typically accomplished by synchronizing on some object that | ||||
|  * naturally encapsulates the set.</p> | ||||
|  * | ||||
|  * @author Nathan Fiedler | ||||
|  */ | ||||
| public class FibonacciHeap { | ||||
|     /** | ||||
|      * Points to the minimum node in the heap. | ||||
|      */ | ||||
|     private Node min; | ||||
|     /** | ||||
|      * Number of nodes in the heap. If the type is ever widened, | ||||
|      * (e.g. changed to long) then recalcuate the maximum degree | ||||
|      * value used in the consolidate() method. | ||||
|      */ | ||||
|     private int n; | ||||
|  | ||||
|     /** | ||||
|      * Joins two Fibonacci heaps into a new one. No heap consolidation is | ||||
|      * performed at this time. The two root lists are simply joined together. | ||||
|      * | ||||
|      * <p><em>Running time: O(1)</em></p> | ||||
|      * | ||||
|      * @param H1 first heap | ||||
|      * @param H2 second heap | ||||
|      * @return new heap containing H1 and H2 | ||||
|      */ | ||||
|     public static FibonacciHeap union(FibonacciHeap H1, FibonacciHeap H2) { | ||||
|         FibonacciHeap H = new FibonacciHeap(); | ||||
|         if (H1 != null && H2 != null) { | ||||
|             H.min = H1.min; | ||||
|             if (H.min != null) { | ||||
|                 if (H2.min != null) { | ||||
|                     H.min.right.left = H2.min.left; | ||||
|                     H2.min.left.right = H.min.right; | ||||
|                     H.min.right = H2.min; | ||||
|                     H2.min.left = H.min; | ||||
|                     if (H2.min.key < H1.min.key) { | ||||
|                         H.min = H2.min; | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 H.min = H2.min; | ||||
|             } | ||||
|             H.n = H1.n + H2.n; | ||||
|         } | ||||
|         return H; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Removes all elements from this heap. | ||||
|      * | ||||
|      * <p><em>Running time: O(1)</em></p> | ||||
|      */ | ||||
|     public void clear() { | ||||
|         min = null; | ||||
|         n = 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Consolidates the trees in the heap by joining trees of equal | ||||
|      * degree until there are no more trees of equal degree in the | ||||
|      * root list. | ||||
|      * | ||||
|      * <p><em>Running time: O(log n) amortized</em></p> | ||||
|      */ | ||||
|     private void consolidate() { | ||||
|         // The magic 45 comes from log base phi of Integer.MAX_VALUE, | ||||
|         // which is the most elements we will ever hold, and log base | ||||
|         // phi represents the largest degree of any root list node. | ||||
|         Node[] A = new Node[45]; | ||||
|  | ||||
|         // For each root list node look for others of the same degree. | ||||
|         Node start = min; | ||||
|         Node w = min; | ||||
|         do { | ||||
|             Node x = w; | ||||
|             // Because x might be moved, save its sibling now. | ||||
|             Node nextW = w.right; | ||||
|             int d = x.degree; | ||||
|             while (A[d] != null) { | ||||
|                 // Make one of the nodes a child of the other. | ||||
|                 Node y = A[d]; | ||||
|                 if (x.key > y.key) { | ||||
|                     Node temp = y; | ||||
|                     y = x; | ||||
|                     x = temp; | ||||
|                 } | ||||
|                 if (y == start) { | ||||
|                     // Because removeMin() arbitrarily assigned the min | ||||
|                     // reference, we have to ensure we do not miss the | ||||
|                     // end of the root node list. | ||||
|                     start = start.right; | ||||
|                 } | ||||
|                 if (y == nextW) { | ||||
|                     // If we wrapped around we need to check for this case. | ||||
|                     nextW = nextW.right; | ||||
|                 } | ||||
|                 // Node y disappears from root list. | ||||
|                 y.link(x); | ||||
|                 // We've handled this degree, go to next one. | ||||
|                 A[d] = null; | ||||
|                 d++; | ||||
|             } | ||||
|             // Save this node for later when we might encounter another | ||||
|             // of the same degree. | ||||
|             A[d] = x; | ||||
|             // Move forward through list. | ||||
|             w = nextW; | ||||
|         } while (w != start); | ||||
|  | ||||
|         // The node considered to be min may have been changed above. | ||||
|         min = start; | ||||
|         // Find the minimum key again. | ||||
|         for (Node a : A) { | ||||
|             if (a != null && a.key < min.key) { | ||||
|                 min = a; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Decreases the key value for a heap node, given the new value | ||||
|      * to take on. The structure of the heap may be changed, but will | ||||
|      * not be consolidated. | ||||
|      * | ||||
|      * <p><em>Running time: O(1) amortized</em></p> | ||||
|      * | ||||
|      * @param x node to decrease the key of | ||||
|      * @param k new key value for node x | ||||
|      * @throws IllegalArgumentException if k is larger than x.key value. | ||||
|      */ | ||||
|     public void decreaseKey(Node x, double k) { | ||||
|         decreaseKey(x, k, false); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Decrease the key value of a node, or simply bubble it up to the | ||||
|      * top of the heap in preparation for a delete operation. | ||||
|      * | ||||
|      * @param x      node to decrease the key of. | ||||
|      * @param k      new key value for node x. | ||||
|      * @param delete true if deleting node (in which case, k is ignored). | ||||
|      */ | ||||
|     private void decreaseKey(Node x, double k, boolean delete) { | ||||
|         if (!delete && k > x.key) { | ||||
|             throw new IllegalArgumentException("cannot increase key value"); | ||||
|         } | ||||
|         x.key = k; | ||||
|         Node y = x.parent; | ||||
|         if (y != null && (delete || k < y.key)) { | ||||
|             y.cut(x, min); | ||||
|             y.cascadingCut(min); | ||||
|         } | ||||
|         if (delete || k < min.key) { | ||||
|             min = x; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Deletes a node from the heap given the reference to the node. | ||||
|      * The trees in the heap will be consolidated, if necessary. | ||||
|      * | ||||
|      * <p><em>Running time: O(log n) amortized</em></p> | ||||
|      * | ||||
|      * @param x node to remove from heap. | ||||
|      */ | ||||
|     public void delete(Node x) { | ||||
|         // make x as small as possible | ||||
|         decreaseKey(x, 0, true); | ||||
|         // remove the smallest, which decreases n also | ||||
|         removeMin(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Tests if the Fibonacci heap is empty or not. Returns true if | ||||
|      * the heap is empty, false otherwise. | ||||
|      * | ||||
|      * <p><em>Running time: O(1)</em></p> | ||||
|      * | ||||
|      * @return true if the heap is empty, false otherwise. | ||||
|      */ | ||||
|     public boolean isEmpty() { | ||||
|         return min == null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Inserts a new data element into the heap. No heap consolidation | ||||
|      * is performed at this time, the new node is simply inserted into | ||||
|      * the root list of this heap. | ||||
|      * | ||||
|      * <p><em>Running time: O(1)</em></p> | ||||
|      * | ||||
|      * @param x   data object to insert into heap. | ||||
|      * @param key key value associated with data object. | ||||
|      * @return newly created heap node. | ||||
|      */ | ||||
|     public Node insert(Object x, double key) { | ||||
|         Node node = new Node(x, key); | ||||
|         // concatenate node into min list | ||||
|         if (min != null) { | ||||
|             node.right = min; | ||||
|             node.left = min.left; | ||||
|             min.left = node; | ||||
|             node.left.right = node; | ||||
|             if (key < min.key) { | ||||
|                 min = node; | ||||
|             } | ||||
|         } else { | ||||
|             min = node; | ||||
|         } | ||||
|         n++; | ||||
|         return node; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the smallest element in the heap. This smallest element | ||||
|      * is the one with the minimum key value. | ||||
|      * | ||||
|      * <p><em>Running time: O(1)</em></p> | ||||
|      * | ||||
|      * @return heap node with the smallest key, or null if empty. | ||||
|      */ | ||||
|     public Node min() { | ||||
|         return min; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Removes the smallest element from the heap. This will cause | ||||
|      * the trees in the heap to be consolidated, if necessary. | ||||
|      * | ||||
|      * <p><em>Running time: O(log n) amortized</em></p> | ||||
|      * | ||||
|      * @return data object with the smallest key. | ||||
|      */ | ||||
|     public Object removeMin() { | ||||
|         Node z = min; | ||||
|         if (z == null) { | ||||
|             return null; | ||||
|         } | ||||
|         if (z.child != null) { | ||||
|             z.child.parent = null; | ||||
|             // for each child of z do... | ||||
|             for (Node x = z.child.right; x != z.child; x = x.right) { | ||||
|                 // set parent[x] to null | ||||
|                 x.parent = null; | ||||
|             } | ||||
|             // merge the children into root list | ||||
|             Node minleft = min.left; | ||||
|             Node zchildleft = z.child.left; | ||||
|             min.left = zchildleft; | ||||
|             zchildleft.right = min; | ||||
|             z.child.left = minleft; | ||||
|             minleft.right = z.child; | ||||
|         } | ||||
|         // remove z from root list of heap | ||||
|         z.left.right = z.right; | ||||
|         z.right.left = z.left; | ||||
|         if (z == z.right) { | ||||
|             min = null; | ||||
|         } else { | ||||
|             min = z.right; | ||||
|             consolidate(); | ||||
|         } | ||||
|         // decrement size of heap | ||||
|         n--; | ||||
|         return z.data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the size of the heap which is measured in the | ||||
|      * number of elements contained in the heap. | ||||
|      * | ||||
|      * <p><em>Running time: O(1)</em></p> | ||||
|      * | ||||
|      * @return number of elements in the heap. | ||||
|      */ | ||||
|     public int size() { | ||||
|         return n; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Implements a node of the Fibonacci heap. It holds the information | ||||
|      * necessary for maintaining the structure of the heap. It acts as | ||||
|      * an opaque handle for the data element, and serves as the key to | ||||
|      * retrieving the data from the heap. | ||||
|      * | ||||
|      * @author Nathan Fiedler | ||||
|      */ | ||||
|     public static class Node { | ||||
|         /** | ||||
|          * Data object for this node, holds the key value. | ||||
|          */ | ||||
|         private Object data; | ||||
|         /** | ||||
|          * Key value for this node. | ||||
|          */ | ||||
|         private double key; | ||||
|         /** | ||||
|          * Parent node. | ||||
|          */ | ||||
|         private Node parent; | ||||
|         /** | ||||
|          * First child node. | ||||
|          */ | ||||
|         private Node child; | ||||
|         /** | ||||
|          * Right sibling node. | ||||
|          */ | ||||
|         private Node right; | ||||
|         /** | ||||
|          * Left sibling node. | ||||
|          */ | ||||
|         private Node left; | ||||
|         /** | ||||
|          * Number of children of this node. | ||||
|          */ | ||||
|         private int degree; | ||||
|         /** | ||||
|          * True if this node has had a child removed since this node was | ||||
|          * added to its parent. | ||||
|          */ | ||||
|         private boolean mark; | ||||
|  | ||||
|         /** | ||||
|          * Two-arg constructor which sets the data and key fields to the | ||||
|          * passed arguments. It also initializes the right and left pointers, | ||||
|          * making this a circular doubly-linked list. | ||||
|          * | ||||
|          * @param data data object to associate with this node | ||||
|          * @param key  key value for this data object | ||||
|          */ | ||||
|         public Node(Object data, double key) { | ||||
|             this.data = data; | ||||
|             this.key = key; | ||||
|             right = this; | ||||
|             left = this; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Performs a cascading cut operation. Cuts this from its parent | ||||
|          * and then does the same for its parent, and so on up the tree. | ||||
|          * | ||||
|          * <p><em>Running time: O(log n)</em></p> | ||||
|          * | ||||
|          * @param min the minimum heap node, to which nodes will be added. | ||||
|          */ | ||||
|         public void cascadingCut(Node min) { | ||||
|             Node z = parent; | ||||
|             // if there's a parent... | ||||
|             if (z != null) { | ||||
|                 if (mark) { | ||||
|                     // it's marked, cut it from parent | ||||
|                     z.cut(this, min); | ||||
|                     // cut its parent as well | ||||
|                     z.cascadingCut(min); | ||||
|                 } else { | ||||
|                     // if y is unmarked, set it marked | ||||
|                     mark = true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * The reverse of the link operation: removes x from the child | ||||
|          * list of this node. | ||||
|          * | ||||
|          * <p><em>Running time: O(1)</em></p> | ||||
|          * | ||||
|          * @param x   child to be removed from this node's child list | ||||
|          * @param min the minimum heap node, to which x is added. | ||||
|          */ | ||||
|         public void cut(Node x, Node min) { | ||||
|             // remove x from childlist and decrement degree | ||||
|             x.left.right = x.right; | ||||
|             x.right.left = x.left; | ||||
|             degree--; | ||||
|             // reset child if necessary | ||||
|             if (degree == 0) { | ||||
|                 child = null; | ||||
|             } else if (child == x) { | ||||
|                 child = x.right; | ||||
|             } | ||||
|             // add x to root list of heap | ||||
|             x.right = min; | ||||
|             x.left = min.left; | ||||
|             min.left = x; | ||||
|             x.left.right = x; | ||||
|             // set parent[x] to nil | ||||
|             x.parent = null; | ||||
|             // set mark[x] to false | ||||
|             x.mark = false; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Make this node a child of the given parent node. All linkages | ||||
|          * are updated, the degree of the parent is incremented, and | ||||
|          * mark is set to false. | ||||
|          * | ||||
|          * @param parent the new parent node. | ||||
|          */ | ||||
|         public void link(Node parent) { | ||||
|             // Note: putting this code here in Node makes it 7x faster | ||||
|             // because it doesn't have to use generated accessor methods, | ||||
|             // which add a lot of time when called millions of times. | ||||
|             // remove this from its circular list | ||||
|             left.right = right; | ||||
|             right.left = left; | ||||
|             // make this a child of x | ||||
|             this.parent = parent; | ||||
|             if (parent.child == null) { | ||||
|                 parent.child = this; | ||||
|                 right = this; | ||||
|                 left = this; | ||||
|             } else { | ||||
|                 left = parent.child; | ||||
|                 right = parent.child.right; | ||||
|                 parent.child.right = this; | ||||
|                 right.left = this; | ||||
|             } | ||||
|             // increase degree[x] | ||||
|             parent.degree++; | ||||
|             // set mark false | ||||
|             mark = false; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,19 @@ | ||||
| package baritone.bot.pathing.calc; | ||||
|  | ||||
| /** | ||||
|  * Wrapper adapter between FibonacciHeap and OpenSet | ||||
|  * | ||||
|  * @author leijurv | ||||
|  */ | ||||
| public class FibonacciHeapOpenSet extends FibonacciHeap implements IOpenSet { | ||||
|     //isEmpty is already defined in FibonacciHeap | ||||
|     @Override | ||||
|     public void insert(PathNode node) { | ||||
|         super.insert(node, node.estimatedCostToGoal + node.cost); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PathNode removeLowest() { | ||||
|         return (PathNode) super.removeMin(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/main/java/baritone/bot/pathing/calc/IOpenSet.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/main/java/baritone/bot/pathing/calc/IOpenSet.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| package baritone.bot.pathing.calc; | ||||
|  | ||||
| /** | ||||
|  * An open set for A* or similar graph search algorithm | ||||
|  * | ||||
|  * @author leijurv | ||||
|  */ | ||||
| public interface IOpenSet { | ||||
|     boolean isEmpty(); | ||||
|  | ||||
|     void insert(PathNode node); | ||||
|  | ||||
|     PathNode removeLowest(); | ||||
| } | ||||
| @@ -3,6 +3,11 @@ package baritone.bot.pathing.calc; | ||||
| import baritone.bot.pathing.goals.Goal; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
|  | ||||
| /** | ||||
|  * Generic path finder interface | ||||
|  * | ||||
|  * @author leijurv | ||||
|  */ | ||||
| public interface IPathFinder { | ||||
|  | ||||
|     BlockPos getStart(); | ||||
|   | ||||
| @@ -0,0 +1,49 @@ | ||||
| package baritone.bot.pathing.calc; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  */ | ||||
| public class LinkedListOpenSet implements IOpenSet { | ||||
|     private PathNode first = null; | ||||
|  | ||||
|     public boolean isEmpty() { | ||||
|         return first == null; | ||||
|     } | ||||
|  | ||||
|     public void insert(PathNode node) { | ||||
|         node.nextOpen = first; | ||||
|         first = node; | ||||
|     } | ||||
|  | ||||
|     public PathNode removeLowest() { | ||||
|         if (first == null) { | ||||
|             return null; | ||||
|         } | ||||
|         PathNode current = first.nextOpen; | ||||
|         if (current == null) { | ||||
|             PathNode n = first; | ||||
|             first = null; | ||||
|             return n; | ||||
|         } | ||||
|         PathNode previous = first; | ||||
|         double bestValue = first.estimatedCostToGoal + first.cost; | ||||
|         PathNode bestNode = first; | ||||
|         PathNode beforeBest = null; | ||||
|         while (current != null) { | ||||
|             double comp = current.estimatedCostToGoal + current.cost; | ||||
|             if (comp < bestValue) { | ||||
|                 bestValue = comp; | ||||
|                 bestNode = current; | ||||
|                 beforeBest = previous; | ||||
|             } | ||||
|             previous = current; | ||||
|             current = current.nextOpen; | ||||
|         } | ||||
|         if (beforeBest == null) { | ||||
|             first = first.nextOpen; | ||||
|             return bestNode; | ||||
|         } | ||||
|         beforeBest.nextOpen = bestNode.nextOpen; | ||||
|         return bestNode; | ||||
|     } | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| package baritone.bot.pathing.calc; | ||||
|  | ||||
| import baritone.bot.pathing.movement.Movement; | ||||
| import baritone.bot.pathing.goals.Goal; | ||||
| import baritone.bot.pathing.movement.Movement; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
|  | ||||
| import java.util.Objects; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user