001/****************************************************************************** 002 Copyright 2014 See AUTHORS file. 003 004 Licensed under the Apache License, Version 2.0 (the "License"); 005 you may not use this file except in compliance with the License. 006 You may obtain a copy of the License at 007 008 http://www.apache.org/licenses/LICENSE-2.0 009 010 Unless required by applicable law or agreed to in writing, software 011 distributed under the License is distributed on an "AS IS" BASIS, 012 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 See the License for the specific language governing permissions and 014 limitations under the License. 015 */ 016 017package squidpony.squidai.graph; 018 019import squidpony.squidmath.Coord; 020 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.List; 024 025/** A {@code Heuristic} generates estimates of the cost to move from a given node to the goal. 026 * <p> 027 * With a heuristic function pathfinding algorithms can choose the node that is most likely to lead to the optimal path. 028 * The notion of "most likely" is controlled by a heuristic. If the heuristic is accurate, then the algorithm will be 029 * efficient. If the heuristic is terrible, then it can perform even worse than other algorithms that don't use any 030 * heuristic function such as Dijkstra. SquidLib's {@link squidpony.squidai.DijkstraMap} is specialized for some cases 031 * that A* isn't, so there are reasons to prefer DijkstraMap when, for instance, you have multiple goals, or the goal is 032 * unchanging for some section of usage but the start point changes often (this is useful for mouse tracking when the 033 * path is reversed). The astar package should be significantly faster when paths are short and always have one goal, 034 * unless you compare it to DijkstraMap when it can reuse a scan and call 035 * {@link squidpony.squidai.DijkstraMap#findPathPreScanned(ArrayList, Coord)}. 036 * 037 * @param <V> Type of vertex; this is usually {@link Coord} 038 * 039 * @author davebaol */ 040public interface Heuristic<V> { 041 042 /** Calculates an estimated cost to reach the goal node from the given node. 043 * @param node the start node 044 * @param endNode the end node 045 * @return the estimated cost */ 046 double estimate(V node, V endNode); 047 048 /** 049 * A predefined Heuristic for Coord nodes in a 2D plane where diagonal movement is estimated as costing twice as 050 * much as orthogonal movement. This is a good choice for graphs where only four-way movement is used. 051 */ 052 Heuristic<Coord> MANHATTAN = new Heuristic<Coord>() { 053 @Override 054 public double estimate(Coord node, Coord endNode) { 055 return Math.abs(node.x - endNode.x) + Math.abs(node.y - endNode.y); 056 } 057 }; 058 /** 059 * A predefined Heuristic for Coord nodes in a 2D plane where diagonal movement is estimated as costing the same as 060 * orthogonal movement. This is only suggested for graphs where eight-way movement is used, and it may produce 061 * erratic paths compared to {@link #EUCLIDEAN}. 062 */ 063 Heuristic<Coord> CHEBYSHEV = new Heuristic<Coord>() { 064 @Override 065 public double estimate(Coord node, Coord endNode) { 066 return Math.max(Math.abs(node.x - endNode.x), Math.abs(node.y - endNode.y)); 067 } 068 }; 069 /** 070 * A predefined Heuristic for Coord nodes in a 2D plane where all movement is calculated "as-the-crow-flies," using 071 * the standard Pythagorean formula for distance as in the real world. This does not make diagonal connections, if 072 * they are allowed, actually cost more or less, but they won't be preferred if an orthogonal route can be taken. 073 * This is recommended for graphs where eight-way movement is used. 074 */ 075 Heuristic<Coord> EUCLIDEAN = new Heuristic<Coord>() { 076 @Override 077 public double estimate(Coord node, Coord endNode) { 078 return node.distance(endNode); 079 } 080 }; 081 /** 082 * A predefined Heuristic for Coord nodes in a 2D plane where the heuristic is not used, and all cells are 083 * considered equivalent regardless of actual distance. 084 */ 085 Heuristic<Coord> DIJKSTRA = new Heuristic<Coord>() { 086 @Override 087 public double estimate(Coord node, Coord endNode) { 088 return 0.0; 089 } 090 }; 091 /** 092 * An unmodifiable List of all the Heuristic implementations in this class. 093 */ 094 List<Heuristic<Coord>> HEURISTICS = Arrays.asList(MANHATTAN, CHEBYSHEV, EUCLIDEAN, DIJKSTRA); 095}