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}