Parcourir la source

Delete stuff I don't use

smelc il y a 7 ans
Parent
commit
517095ca7a

+ 0 - 212
squidlib-util/src/main/java/squidpony/squidai/AOE.java

@@ -1,212 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.annotation.GwtIncompatible;
-import squidpony.squidgrid.FOVCache;
-import squidpony.squidgrid.Radius;
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.OrderedMap;
-
-import java.util.ArrayList;
-import java.util.Set;
-
-/**
- * Area of Effect interface meant to be implemented by various specific burst, line, flowing, and user-made AOE types.
- * Created by Tommy Ettinger on 5/8/2015.
- */
-public interface AOE {
-    /**
-     * After an AOE has been constructed, it may need to have the affected area shifted over to a different position
-     * without changing any other properties of the AOE. Some AOE implementations may have an origin where the AOE
-     * starts emanating from, but the origin will not be affected by this method; instead the cell specified by target
-     * must be enough on its own to select a different target area without the producer of the AOE needing to move.
-     * @param aim a  that will be used to change the location of the AOE without its producer needing to move
-     */
-    void shift(Coord aim);
-
-    /**
-     * Given a Set of Points that the producer of the AOE wants to include in the region of this AOE, this method does
-     * a quick approximation to see if there is any possibility that the AOE as currently configured might include one
-     * of those Points within itself. It does not do a full, detailed scan, nor does it count how many opponents might
-     * be included. It does not check the map to verify that there is any sort of path to a target. It is recommended
-     * that the Set of Points consist only of enemies that are within FOV, which cuts down a lot on the amount of checks
-     * this needs to make; if the game doesn't restrict the player's FOV, this is still recommended (just with a larger
-     * FOV radius) because it prevents checking enemies on the other side of the map and through multiple walls.
-     * @param targets a Set of Points that are desirable targets to include in this AOE
-     * @return true if there could be at least one target within the AOE, false otherwise. Very approximate.
-     */
-    boolean mayContainTarget(Set<Coord> targets);
-
-    /**
-     * Returns a OrderedMap of Coord keys and ArrayList of Coord values, where each Coord key is an ideal location to
-     * hit as many of the Points in targets as possible without hitting any Points in requiredExclusions, and each value
-     * is the collection of targets that will be hit if the associated key is used. The length of any ArrayList in the
-     * returned collection's values will be the number of targets likely to be affected by the AOE when shift() is
-     * called with the Coord key as an argument; all of the ArrayLists should have the same length. The second argument
-     * may be null, in which case this will initialize it to an empty Set of Coord and disregard it.
-     *
-     * With complex maps and varied arrangements of obstacles and desirable targets, calculating the best points to
-     * evaluate for AI can be computationally difficult. This method provides a way to calculate with good accuracy
-     * the best Points to pass to shift(Coord) before calling findArea(). For "blackened thrash industrial death metal"
-     * levels of brutality for the AI, the results of this can be used verbatim, but for more reasonable AI levels, you
-     * can intentionally alter the best options to simulate imperfect aim or environmental variance on the AOE.
-     *
-     * Beast-like creatures that do not need devious AI should probably not use this method at all and instead use
-     * shift(Coord) with the location of some enemy (probably the closest) as its argument.
-     * @param targets a Set of Points that are desirable targets to include in this AOE
-     * @param requiredExclusions a Set of Points that this tries strongly to avoid including in this AOE
-     * @return a OrderedMap of Coord keys and ArrayList of Coord values where keys are ideal locations and values are the target points that will be hit when that key is used.
-     */
-    OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions);
-
-    /**
-     * A variant of idealLocations that takes two groups of desirable targets, and will rate locations by how many
-     * priorityTargets are in the AOE, then by how many lesserTargets are in the AOE, and will only consider locations
-     * that do not affect a Coord in requiredExclusions. Unlike the variant of idealLocations that only takes one group
-     * of targets, this variant can return a collection with ArrayList values where the same Coord appears four times
-     * in the same ArrayList; this is done only for priorityTargets that are affected by the target Coord at the
-     * associated key, and is done so that the length of each similar-quality ArrayList should be identical (since a
-     * priorityTarget is worth four times what a lesserTarget is worth in the calculation this uses).
-     * @param priorityTargets A Set of Points that are the most-wanted targets to include in this AOE
-     * @param lesserTargets A Set of Points that are the less-wanted targets to include in this AOE, should not overlap with priorityTargets
-     * @param requiredExclusions a Set of Points that this tries strongly to avoid including in this AOE
-     * @return a OrderedMap of Coord keys and ArrayList of Coord values where keys are ideal locations and values are the target points that will be hit when that key is used.
-     */
-    OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> priorityTargets, Set<Coord> lesserTargets, Set<Coord> requiredExclusions);
-
-    /**
-     * This must be called before any other methods, and takes a char[][] with '#' for walls, anything else for floors.
-     * It must be bounded with walls, which DungeonGenerator does automatically.
-     * @param map width first, height second, 2D char array.
-     */
-    void setMap(char[][] map);
-
-    /**
-     * This is how an AOE interacts with anything that uses it. It expects a map to have already been set with setMap,
-     * with '#' for walls, '.' for floors and potentially other chars that implementors can use if they are present in
-     * the map. The map must be bounded by walls, which DungeonGenerator does automatically and other generators can
-     * easily add with two loops.
-     *
-     * This returns an OrderedMap of Coord keys to Double values; if a cell is 100% affected by the AOE then the value
-     * should be 1.0; if it is 50% affected it should be 0.5, if unaffected should be 0.0, etc. The Coord keys should
-     * have the same x and y as the x,y map positions they correspond to.
-     * @return an OrderedMap of Coord keys to Double values from 1.0 (fully affected) to 0.0 (unaffected).
-     */
-    OrderedMap<Coord, Double> findArea();
-
-    /**
-     * Get the position from which the AOE originates, which may be related to the location of the AOE's effect, as for
-     * lines, cones, and other emitted effects, or may be unrelated except for determining which enemies can be seen
-     * or targeted from a given origin point (as for distant effects that radiate from a chosen central point, but
-     * have a maxRange at which they can deliver that effect).
-     */
-    Coord getOrigin();
-
-    /**
-     * Set the position from which the AOE originates, which may be related to the location of the AOE's effect, as for
-     * lines, cones, and other emitted effects, or may be unrelated except for determining which enemies can be seen
-     * or targeted from a given origin point (as for distant effects that radiate from a chosen central point, but
-     * have a maxRange at which they can deliver that effect).
-     */
-    void setOrigin(Coord origin);
-
-    /**
-     * Gets the AimLimit enum that can be used to restrict points this checks (defaults to null if not set).
-     * You can use limitType to restrict any Points that might be processed based on the given origin (which will be
-     * used as the geometric origin for any calculations this makes) with AimLimit values having the following meanings:
-     *
-     * <ul>
-     *     <li>AimLimit.FREE makes no restrictions; it is equivalent here to passing null for limit.</li>
-     *     <li>AimLimit.EIGHT_WAY will only consider Points to be valid targets
-     *     if they are along a straight line with an angle that is a multiple of 45 degrees, relative to the positive x
-     *     axis. Essentially, this limits the points to those a queen could move to in chess.</li>
-     *     <li>AimLimit.ORTHOGONAL will cause the AOE to only consider Points to be valid targets if
-     *     they are along a straight line with an angle that is a multiple of 90 degrees, relative to the positive x
-     *     axis. Essentially, this limits the points to those a rook could move to in chess.</li>
-     *     <li>AimLimit.DIAGONAL will cause the AOE to only consider Points to be valid targets if they are along a
-     *     straight line with an angle that is 45 degrees greater than a multiple of 90 degrees, relative to the
-     *     positive x axis. Essentially, this limits the points to those a bishop could move to in chess.</li>
-     *     <li>null will cause the AOE to consider all points.</li>
-     * </ul>
-     */
-    AimLimit getLimitType();
-    /**
-     * The minimum inclusive range that the AOE can be shift()-ed to using the distance measurement from radiusType.
-     */
-    int getMinRange();
-    /**
-     * The maximum inclusive range that the AOE can be shift()-ed to using the distance measurement from radiusType.
-     */
-    int getMaxRange();
-    /**
-     * Used to determine distance from origin for the purposes of selecting a target location that is within the bounds
-     * of minRange and maxRange. Not necessarily used for the implementation of the AOE (randomized-floodfill-based AOE
-     * should almost always use Manhattan distance for its spread due to how the algorithm works, but the positioning of
-     * where that floodfill should be allowed to start should likely follow the same distance measurement as the rest of
-     * the game, like Radius.SQUARE for Chebyshev distance/8-way movement).
-     */
-    Radius getMetric();
-
-    /**
-     * Gets the same values returned by getLimitType(), getMinRange(), getMaxRange(), and getMetric() bundled into one
-     * Reach object.
-     * @return a non-null Reach object.
-     */
-    Reach getReach();
-
-    /**
-     * You can use limitType to restrict any Points that might be processed based on the given origin (which will be
-     * used as the geometric origin for any calculations this makes) with AimLimit values having the following meanings:
-     *
-     * <ul>
-     *     <li>AimLimit.FREE makes no restrictions; it is equivalent here to passing null for limit.</li>
-     *     <li>AimLimit.EIGHT_WAY will only consider Points to be valid targets
-     *     if they are along a straight line with an angle that is a multiple of 45 degrees, relative to the positive x
-     *     axis. Essentially, this limits the points to those a queen could move to in chess.</li>
-     *     <li>AimLimit.ORTHOGONAL will cause the AOE to only consider Points to be valid targets if
-     *     they are along a straight line with an angle that is a multiple of 90 degrees, relative to the positive x
-     *     axis. Essentially, this limits the points to those a rook could move to in chess.</li>
-     *     <li>AimLimit.DIAGONAL will cause the AOE to only consider Points to be valid targets if they are along a
-     *     straight line with an angle that is 45 degrees greater than a multiple of 90 degrees, relative to the
-     *     positive x axis. Essentially, this limits the points to those a bishop could move to in chess.</li>
-     * </ul>
-     *
-     * Points that are not valid for this limit will simply not be considered.
-     * @param limitType an AimLimit enum
-     */
-    void setLimitType(AimLimit limitType);
-    /**
-     * The minimum inclusive range that the AOE can be shift()-ed to using the distance measurement from radiusType.
-     */
-    void setMinRange(int minRange);
-    /**
-     * The maximum inclusive range that the AOE can be shift()-ed to using the distance measurement from radiusType.
-     */
-    void setMaxRange(int maxRange);
-    /**
-     * Used to determine distance from origin for the purposes of selecting a target location that is within the bounds
-     * of minRange and maxRange. Not necessarily used for the implementation of the AOE (randomized-floodfill-based AOE
-     * should almost always use Manhattan distance for its spread due to how the algorithm works, but the positioning of
-     * where that floodfill should be allowed to start should likely follow the same distance measurement as the rest of
-     * the game, like Radius.SQUARE for Chebyshev distance/8-way movement).
-     */
-    void setMetric(Radius metric);
-
-    /**
-     * Sets the same values as setLimitType(), setMinRange(), setMaxRange(), and setMetric() using one Reach object.
-     * @param reach a non-null Reach object.
-     */
-    void setReach(Reach reach);
-
-    /**
-     * If you use FOVCache to pre-compute FOV maps for a level, you can share the speedup from using the cache with
-     * some AOE implementations that rely on FOV. Not all implementations need to actually make use of the cache, but
-     * those that use FOV for calculations should benefit. The cache parameter this receives should have completed its
-     * calculations, which can be confirmed by calling awaitCache(). Ideally, the FOVCache will have done its initial
-     * calculations in another thread while the previous level or menu was being displayed, and awaitCache() will only
-     * be a formality.
-     * @param cache The FOVCache for the current level; can be null to stop using the cache
-     */
-    @GwtIncompatible
-    void setCache(FOVCache cache);
-
-}

+ 0 - 774
squidlib-util/src/main/java/squidpony/squidai/BeamAOE.java

@@ -1,774 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.annotation.GwtIncompatible;
-import squidpony.squidgrid.FOVCache;
-import squidpony.squidgrid.LOS;
-import squidpony.squidgrid.Radius;
-import squidpony.squidgrid.mapping.DungeonUtility;
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.OrderedSet;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Queue;
-import java.util.Set;
-
-import static java.lang.Math.*;
-
-/**
- * Beam Area of Effect that affects an slightly expanded (Elias) line from a given origin Coord out to a given length,
- * plus an optional radius of cells around the path of the line, while respecting obstacles in its path and possibly
- * stopping if obstructed. There are several ways to specify the BeamAOE's direction and length, including specifying
- * an endpoint or specifying an angle in degrees and a distance to the end of the line (without the radius included).
- * You can specify the RadiusType to Radius.DIAMOND for Manhattan distance, RADIUS.SQUARE for Chebyshev, or
- * RADIUS.CIRCLE for Euclidean.
- *
- * You may want the LineAOE class instead of this. LineAOE travels point-to-point and does not restrict length, while
- * BeamAOE travels a specific length (and may have a radius, like LineAOE) but then stops only after the travel down the
- * length and radius has reached its end. This difference is relevant if a game has effects that have a definite
- * area measured in a rectangle or elongated pillbox shape, such as a "20-foot-wide bolt of lightning, 100 feet long."
- * BeamAOE is more suitable for that effect, while LineAOE may be more suitable for things like focused lasers that
- * pass through small (likely fleshy) obstacles but stop after hitting the aimed-at target.
- *
- * BeamAOE will strike a small area behind the user and in the opposite direction of the target if the radius is
- * greater than 0. This behavior may be altered in a future version.
- *
- * This will produce doubles for its findArea() method which are equal to 1.0.
- *
- * This class uses squidpony.squidmath.Elias and squidpony.squidai.DijkstraMap to create its area of effect.
- * Created by Tommy Ettinger on 7/14/2015.
- */
-public class BeamAOE implements AOE {
-    private Coord origin, end;
-    private int radius;
-    private int length;
-    private char[][] dungeon;
-    private DijkstraMap dijkstra;
-    private Radius rt;
-    private LOS los;
-
-    private Reach reach = new Reach(1, 1, Radius.SQUARE, null);
-
-    public BeamAOE(Coord origin, Coord end)
-    {
-        dijkstra = new DijkstraMap();
-        dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-        rt = Radius.SQUARE;
-        this.origin = origin;
-        this.end = end;
-        length =(int)Math.round(rt.radius(origin.x, origin.y, end.x, end.y));
-        reach.maxDistance = length;
-        radius = 0;
-        los = new LOS(LOS.THICK);
-    }
-    public BeamAOE(Coord origin, Coord end, int radius)
-    {
-        dijkstra = new DijkstraMap();
-        dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-        rt = Radius.SQUARE;
-        this.origin = origin;
-        this.end = end;
-        this.radius = radius;
-        length =(int)Math.round(rt.radius(origin.x, origin.y, end.x, end.y));
-        reach.maxDistance = length;
-        los = new LOS(LOS.THICK);
-    }
-    public BeamAOE(Coord origin, Coord end, int radius, Radius radiusType)
-    {
-        dijkstra = new DijkstraMap();
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case OCTAHEDRON:
-            case DIAMOND:
-                dijkstra.measurement = DijkstraMap.Measurement.MANHATTAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                dijkstra.measurement = DijkstraMap.Measurement.CHEBYSHEV;
-                break;
-            default:
-                dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-                break;
-        }
-        this.origin = origin;
-        this.end = end;
-        this.radius = radius;
-        length =(int)Math.round(rt.radius(origin.x, origin.y, end.x, end.y));
-        reach.maxDistance = length;
-        los = new LOS(LOS.THICK);
-    }
-
-    public BeamAOE(Coord origin, double angle, int length)
-    {
-        dijkstra = new DijkstraMap();
-        dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-        rt = Radius.SQUARE;
-        this.origin = origin;
-        double theta = Math.toRadians(angle);
-        end = Coord.get((int) round(cos(theta) * length) + origin.x,
-                (int) round(sin(theta) * length) + origin.y);
-        this.length = length;
-        reach.maxDistance = this.length;
-        radius = 0;
-        los = new LOS(LOS.THICK);
-    }
-    public BeamAOE(Coord origin, double angle, int length, int radius)
-    {
-        dijkstra = new DijkstraMap();
-        dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-        rt = Radius.SQUARE;
-        this.origin = origin;
-        double theta = Math.toRadians(angle);
-        end = Coord.get((int) round(cos(theta) * length) + origin.x,
-                (int) round(sin(theta) * length) + origin.y);
-        this.radius = radius;
-        this.length = length;
-        reach.maxDistance = this.length;
-        los = new LOS(LOS.THICK);
-    }
-    public BeamAOE(Coord origin, double angle, int length, int radius, Radius radiusType)
-    {
-        dijkstra = new DijkstraMap();
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case OCTAHEDRON:
-            case DIAMOND:
-                dijkstra.measurement = DijkstraMap.Measurement.MANHATTAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                dijkstra.measurement = DijkstraMap.Measurement.CHEBYSHEV;
-                break;
-            default:
-                dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-                break;
-        }
-        this.origin = origin;
-        double theta = Math.toRadians(angle);
-        end = Coord.get((int) round(cos(theta) * length) + origin.x,
-                (int) round(sin(theta) * length) + origin.y);
-        this.radius = radius;
-        this.length = length;
-        reach.maxDistance = this.length;
-        los = new LOS(LOS.THICK);
-    }
-    private double[][] initDijkstra()
-    {
-        los.isReachable(dungeon, origin.x, origin.y, end.x, end.y, rt);
-        Queue<Coord> lit = los.getLastPath();
-
-        dijkstra.initialize(dungeon);
-        for(Coord p : lit)
-        {
-            dijkstra.setGoal(p);
-        }
-        if(radius == 0)
-            return dijkstra.gradientMap;
-        return dijkstra.partialScan(radius, null);
-    }
-
-    @Override
-	public Coord getOrigin() {
-        return origin;
-    }
-
-    @Override
-	public void setOrigin(Coord origin) {
-        this.origin = origin;
-        dijkstra.resetMap();
-        dijkstra.clearGoals();
-    }
-
-    @Override
-    public AimLimit getLimitType() {
-        return reach.limit;
-    }
-
-    @Override
-    public int getMinRange() {
-        return reach.minDistance;
-    }
-
-    @Override
-    public int getMaxRange() {
-        return reach.maxDistance;
-    }
-
-    @Override
-    public Radius getMetric() {
-        return reach.metric;
-    }
-
-    /**
-     * Gets the same values returned by getLimitType(), getMinRange(), getMaxRange(), and getMetric() bundled into one
-     * Reach object.
-     *
-     * @return a non-null Reach object.
-     */
-    @Override
-    public Reach getReach() {
-        return reach;
-    }
-
-    @Override
-    public void setLimitType(AimLimit limitType) {
-        reach.limit = limitType;
-
-    }
-
-    @Override
-    public void setMinRange(int minRange) {
-        reach.minDistance = minRange;
-    }
-
-    @Override
-    public void setMaxRange(int maxRange) {
-        reach.maxDistance = maxRange;
-        length = maxRange;
-
-    }
-
-    @Override
-    public void setMetric(Radius metric) {
-        reach.metric = metric;
-    }
-
-    /**
-     * Sets the same values as setLimitType(), setMinRange(), setMaxRange(), and setMetric() using one Reach object.
-     *
-     * @param reach a non-null Reach object.
-     */
-    @Override
-    public void setReach(Reach reach) {
-        if(reach != null)
-            this.reach = reach;
-    }
-
-    public Coord getEnd() {
-        return end;
-    }
-
-    public void setEnd(Coord end) {
-        if (AreaUtils.verifyReach(reach, origin, end))
-        {
-            this.end = rt.extend(origin, end, length, false, dungeon.length, dungeon[0].length);
-        }
-
-    }
-
-    public int getRadius() {
-        return radius;
-    }
-
-    public void setRadius(int radius) {
-        this.radius = radius;
-    }
-
-    public Radius getRadiusType()
-    {
-        return rt;
-    }
-    public void setRadiusType(Radius radiusType)
-    {
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case OCTAHEDRON:
-            case DIAMOND:
-                dijkstra.measurement = DijkstraMap.Measurement.MANHATTAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                dijkstra.measurement = DijkstraMap.Measurement.CHEBYSHEV;
-                break;
-            default:
-                dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-                break;
-        }
-    }
-
-    @Override
-    public void shift(Coord aim) {
-        setEnd(aim);
-    }
-
-    @Override
-    public boolean mayContainTarget(Set<Coord> targets) {
-        for (Coord p : targets)
-        {
-            if(rt.radius(origin.x, origin.y, p.x, p.y) + rt.radius(end.x, end.y, p.x, p.y) -
-                    rt.radius(origin.x, origin.y, end.x, end.y) <= 3.0 + radius)
-                return true;
-        }
-        return false;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        if(targets == null)
-            return new OrderedMap<>();
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-
-        int totalTargets = targets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        Coord[] ts = targets.toArray(new Coord[targets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t;
-
-        double[][][] compositeMap = new double[ts.length][dungeon.length][dungeon[0].length];
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-        }
-        DijkstraMap dt = new DijkstraMap(dungeon, dijkstra.measurement);
-        double[][] resMap = DungeonUtility.generateResistances(dungeon);
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = rt.extend(origin, exs[i], length, false, dungeon.length, dungeon[0].length);
-            dt.resetMap();
-            dt.clearGoals();
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (dt.gradientMap[x][y] < DijkstraMap.FLOOR || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        //t = rt.extend(origin, ts[0], length, false, dungeon.length, dungeon[0].length);
-
-        for (int i = 0; i < ts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dijkstra.measurement);
-
-            t = rt.extend(origin, ts[i], length, false, dungeon.length, dungeon[0].length);
-            dt.resetMap();
-            dt.clearGoals();
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (dt.gradientMap[x][y] < DijkstraMap.FLOOR){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][ts[i].x][ts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(ts[i]);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-        }
-        double bestQuality = 99999 * ts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long bits = 0;
-                for (int i = 0; i < ts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        bits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> priorityTargets, Set<Coord> lesserTargets, Set<Coord> requiredExclusions) {
-        if(priorityTargets == null)
-            return idealLocations(lesserTargets, requiredExclusions);
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = priorityTargets.size() + lesserTargets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        Coord[] pts = priorityTargets.toArray(new Coord[priorityTargets.size()]);
-        Coord[] lts = lesserTargets.toArray(new Coord[lesserTargets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t;// = rt.extend(origin, exs[0], length, false, dungeon.length, dungeon[0].length);
-
-        double[][][] compositeMap = new double[totalTargets][dungeon.length][dungeon[0].length];
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length],
-                dungeonPriorities = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-            Arrays.fill(dungeonPriorities[i], '#');
-        }
-        DijkstraMap dt = new DijkstraMap(dungeon, dijkstra.measurement);
-        double[][] resMap = DungeonUtility.generateResistances(dungeon);
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = rt.extend(origin, exs[i], length, false, dungeon.length, dungeon[0].length);
-            dt.resetMap();
-            dt.clearGoals();
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (dt.gradientMap[x][y] < DijkstraMap.FLOOR  || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = rt.extend(origin, pts[0], length, false, dungeon.length, dungeon[0].length);
-
-        for (int i = 0; i < pts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dijkstra.measurement);
-
-            t = rt.extend(origin, pts[i], length, false, dungeon.length, dungeon[0].length);
-            dt.resetMap();
-            dt.clearGoals();
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (dt.gradientMap[x][y] < DijkstraMap.FLOOR){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius) {
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                            dungeonPriorities[x][y] = dungeon[x][y];
-                        }
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][pts[i].x][pts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 399999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(pts[i]);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 399999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-
-        t = rt.extend(origin, lts[0], length, false, dungeon.length, dungeon[0].length);
-
-        for (int i = pts.length; i < totalTargets; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dijkstra.measurement);
-
-            t = rt.extend(origin, lts[i - pts.length], length, false, dungeon.length, dungeon[0].length);
-            dt.resetMap();
-            dt.clearGoals();
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (dt.gradientMap[x][y] < DijkstraMap.FLOOR){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][lts[i - pts.length].x][lts[i - pts.length].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++)
-                {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(lts[i - pts.length]);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!' && dungeonPriorities[x][y] != '#') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-        double bestQuality = 99999 * lts.length + 399999 * pts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long pbits = 0, lbits = 0;
-                for (int i = 0; i < pts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 399999.0 && i < 63)
-                        pbits |= 1 << i;
-                }
-                for (int i = pts.length; i < totalTargets; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        lbits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if((pbits & (1 << i)) != 0)
-                            ap.add(pts[i]);
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if ((pbits & (1 << i)) != 0) {
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                        }
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-    /*
-        @Override
-        public ArrayList<ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-            int totalTargets = targets.size() + 1;
-            int volume = (int)(rt.radius(1, 1, dungeon.length - 2, dungeon[0].length - 2) * radius * 2.1);
-            ArrayList<ArrayList<Coord>> locs = new ArrayList<ArrayList<Coord>>(totalTargets);
-            for(int i = 0; i < totalTargets; i++)
-            {
-                locs.add(new ArrayList<Coord>(volume));
-            }
-            if(totalTargets == 1)
-                return locs;
-
-            int ctr = 0;
-
-            boolean[][] tested = new boolean[dungeon.length][dungeon[0].length];
-            for (int x = 1; x < dungeon.length - 1; x += radius) {
-                for (int y = 1; y < dungeon[x].length - 1; y += radius) {
-
-                    if(mayContainTarget(requiredExclusions, x, y))
-                        continue;
-                    ctr = 0;
-                    for(Coord tgt : targets)
-                    {
-                        if(rt.radius(origin.x, origin.y, tgt.x, tgt.y) + rt.radius(end.x, end.y, tgt.x, tgt.y) -
-                            rt.radius(origin.x, origin.y, end.x, end.y) <= 3.0 + radius)
-                            ctr++;
-                    }
-                    if(ctr > 0)
-                        locs.get(totalTargets - ctr).add(Coord.get(x, y));
-                }
-            }
-            Coord it;
-            for(int t = 0; t < totalTargets - 1; t++)
-            {
-                if(locs.get(t).size() > 0) {
-                    int numPoints = locs.get(t).size();
-                    for (int i = 0; i < numPoints; i++) {
-                        it = locs.get(t).get(i);
-                        for (int x = Math.max(1, it.x - radius / 2); x < it.x + (radius + 1) / 2 && x < dungeon.length - 1; x++) {
-                            for (int y = Math.max(1, it.y - radius / 2); y <= it.y + (radius - 1) / 2 && y < dungeon[0].length - 1; y++)
-                            {
-                                if(tested[x][y])
-                                    continue;
-                                tested[x][y] = true;
-
-                                if(mayContainTarget(requiredExclusions, x, y))
-                                    continue;
-
-                                ctr = 0;
-                                for(Coord tgt : targets)
-                                {
-                                    if(rt.radius(origin.x, origin.y, tgt.x, tgt.y) + rt.radius(end.x, end.y, tgt.x, tgt.y) -
-                                            rt.radius(origin.x, origin.y, end.x, end.y) <= 3.0 + radius)
-                                        ctr++;
-                                }
-                                if(ctr > 0)
-                                    locs.get(totalTargets - ctr).add(Coord.get(x, y));
-                            }
-                        }
-                    }
-                }
-            }
-            return locs;
-        }
-    */
-    @Override
-    public void setMap(char[][] map) {
-        dungeon = map;
-        end = rt.extend(origin, end, length, false, map.length, map[0].length);
-        dijkstra.resetMap();
-        dijkstra.clearGoals();
-    }
-
-    @Override
-    public OrderedMap<Coord, Double> findArea() {
-        double[][] dmap = initDijkstra();
-        dmap[origin.x][origin.y] = DijkstraMap.DARK;
-        dijkstra.resetMap();
-        dijkstra.clearGoals();
-        return AreaUtils.dijkstraToHashMap(dmap);
-    }
-
-    /**
-     * If you use FOVCache to pre-compute FOV maps for a level, you can share the speedup from using the cache with
-     * some AOE implementations that rely on FOV. Not all implementations need to actually make use of the cache, but
-     * those that use FOV for calculations should benefit. The cache parameter this receives should have completed its
-     * calculations, which can be confirmed by calling awaitCache(). Ideally, the FOVCache will have done its initial
-     * calculations in another thread while the previous level or menu was being displayed, and awaitCache() will only
-     * be a formality.
-     *
-     * @param cache The FOVCache for the current level; can be null to stop using the cache
-     */
-
-    @GwtIncompatible
-    @Override
-    public void setCache(FOVCache cache) {
-    }
-
-}

+ 0 - 611
squidlib-util/src/main/java/squidpony/squidai/BlastAOE.java

@@ -1,611 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.annotation.GwtIncompatible;
-import squidpony.squidgrid.FOV;
-import squidpony.squidgrid.FOVCache;
-import squidpony.squidgrid.Radius;
-import squidpony.squidgrid.mapping.DungeonUtility;
-import squidpony.squidmath.Coord;
-
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.OrderedSet;
-
-import java.util.*;
-
-/**
- * An AOE type that has a center and a radius, and will blast outward and somewhat around corners/obstacles, out to
- * the distance specified by radius. You can specify the radiusType to Radius.DIAMOND for Manhattan distance,
- * RADIUS.SQUARE for Chebyshev, or RADIUS.CIRCLE for Euclidean.
- *
- * This will produce doubles for its findArea() method which are greater than 0.0 and less than or equal to 1.0.
- *
- * This class uses squidpony.squidgrid.FOV to create its area of effect.
- * Created by Tommy Ettinger on 7/13/2015.
- */
-public class BlastAOE implements AOE {
-    private FOV fov;
-    private Coord center, origin = null;
-    private int radius;
-    private double[][] map;
-    private char[][] dungeon;
-    private Radius radiusType;
-    
-    private Reach reach = new Reach(1, 1, Radius.SQUARE, null);
-
-    public BlastAOE(Coord center, int radius, Radius radiusType)
-    {
-        fov = new FOV(FOV.RIPPLE_LOOSE);
-        this.center = center;
-        this.radius = radius;
-        this.radiusType = radiusType;
-    }
-    public BlastAOE(Coord center, int radius, Radius radiusType, int minRange, int maxRange)
-    {
-        fov = new FOV(FOV.RIPPLE_LOOSE);
-        this.center = center;
-        this.radius = radius;
-        this.radiusType = radiusType;
-        reach.minDistance = minRange;
-        reach.maxDistance = maxRange;
-    }
-
-    public Coord getCenter() {
-        return center;
-    }
-
-    public void setCenter(Coord center) {
-
-        if (map != null && center.isWithin(map.length, map[0].length) &&
-                AreaUtils.verifyReach(reach, origin, center))
-        {
-            this.center = center;
-        }
-    }
-
-    public int getRadius() {
-        return radius;
-    }
-
-    public void setRadius(int radius) {
-        this.radius = radius;
-    }
-
-    public Radius getRadiusType() {
-        return radiusType;
-    }
-
-    public void setRadiusType(Radius radiusType) {
-        this.radiusType = radiusType;
-    }
-
-    @Override
-    public void shift(Coord aim) {
-        setCenter(aim);
-    }
-
-    @Override
-    public boolean mayContainTarget(Set<Coord> targets) {
-        for (Coord p : targets)
-        {
-            if(radiusType.radius(center.x, center.y, p.x, p.y) <= radius)
-                return true;
-        }
-        return false;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        if(targets == null)
-            return new OrderedMap<>();
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = targets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        if(radius == 0)
-        {
-            for(Coord p : targets)
-            {
-                ArrayList<Coord> ap = new ArrayList<>();
-                ap.add(p);
-                bestPoints.put(p, ap);
-            }
-            return bestPoints;
-        }
-        Coord[] ts = targets.toArray(new Coord[targets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[ts.length][dungeon.length][dungeon[0].length];
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-        }
-        double[][] tmpfov;
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = exs[i];
-
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (tmpfov[x][y] > 0.0 || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = ts[0];
-
-        DijkstraMap.Measurement dmm = DijkstraMap.Measurement.MANHATTAN;
-        if(radiusType == Radius.SQUARE || radiusType == Radius.CUBE) dmm = DijkstraMap.Measurement.CHEBYSHEV;
-        else if(radiusType == Radius.CIRCLE || radiusType == Radius.SPHERE) dmm = DijkstraMap.Measurement.EUCLIDEAN;
-
-        for (int i = 0; i < ts.length; i++) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-
-            t = ts[i];
-
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (tmpfov[x][y] > 0.0) ? dm.physicalMap[x][y] : DijkstraMap.WALL;
-                }
-            }
-
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (tmpfov[x][y] > 0.0){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][ts[i].x][ts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-        }
-        double bestQuality = 99999 * ts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long bits = 0;
-                for (int i = 0; i < ts.length; i++) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        bits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-                    if(ap.size() > 0)
-                    {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality) {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if ((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> priorityTargets, Set<Coord> lesserTargets, Set<Coord> requiredExclusions) {
-        if(priorityTargets == null)
-            return idealLocations(lesserTargets, requiredExclusions);
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = priorityTargets.size() + lesserTargets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        if(radius == 0)
-        {
-            for(Coord p : priorityTargets)
-            {
-                ArrayList<Coord> ap = new ArrayList<>();
-                ap.add(p);
-                bestPoints.put(p, ap);
-            }
-            return bestPoints;
-        }
-        Coord[] pts = priorityTargets.toArray(new Coord[priorityTargets.size()]);
-        Coord[] lts = lesserTargets.toArray(new Coord[lesserTargets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[totalTargets][dungeon.length][dungeon[0].length];
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length],
-                dungeonPriorities = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-            Arrays.fill(dungeonPriorities[i], '#');
-        }
-        double[][] tmpfov;
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = exs[i];
-
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (tmpfov[x][y] > 0.0 || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = pts[0];
-
-        DijkstraMap.Measurement dmm = DijkstraMap.Measurement.MANHATTAN;
-        if(radiusType == Radius.SQUARE || radiusType == Radius.CUBE) dmm = DijkstraMap.Measurement.CHEBYSHEV;
-        else if(radiusType == Radius.CIRCLE || radiusType == Radius.SPHERE) dmm = DijkstraMap.Measurement.EUCLIDEAN;
-
-        for (int i = 0; i < pts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-
-            t = pts[i];
-
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (tmpfov[x][y] > 0.0){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius) {
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                            dungeonPriorities[x][y] = dungeon[x][y];
-                        }
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][pts[i].x][pts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 399999.0);
-                }
-                continue;
-            }
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 399999.0;
-                }
-            }
-        }
-
-        t = lts[0];
-
-        for (int i = pts.length; i < totalTargets; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-
-            t = lts[i - pts.length];
-
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (tmpfov[x][y] > 0.0){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][lts[i - pts.length].x][lts[i - pts.length].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++)
-                {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!' && dungeonPriorities[x][y] != '#') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-        }
-        double bestQuality = 99999 * lts.length + 399999 * pts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long pbits = 0, lbits = 0;
-                for (int i = 0; i < pts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 399999.0 && i < 63)
-                        pbits |= 1 << i;
-                }
-                for (int i = pts.length; i < totalTargets; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        lbits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if((pbits & (1 << i)) != 0)
-                            ap.add(pts[i]);
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality) {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if ((pbits & (1 << i)) != 0) {
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                        }
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if ((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-    /*
-    @Override
-    public ArrayList<ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        int totalTargets = targets.size() + 1;
-        int maxEffect = (int)radiusType.volume2D(radius);
-        ArrayList<ArrayList<Coord>> locs = new ArrayList<ArrayList<Coord>>(totalTargets);
-
-        for(int i = 0; i < totalTargets; i++)
-        {
-            locs.add(new ArrayList<Coord>(maxEffect));
-        }
-        if(totalTargets == 1)
-            return locs;
-        int ctr = 0;
-        if(radius < 1)
-        {
-            locs.get(totalTargets - 2).addAll(targets);
-            return locs;
-        }
-
-        boolean[][] tested = new boolean[dungeon.length][dungeon[0].length];
-        for (int x = 1; x < dungeon.length - 1; x += radius) {
-            BY_POINT:
-            for (int y = 1; y < dungeon[x].length - 1; y += radius) {
-                for(Coord ex : requiredExclusions)
-                {
-                    if(radiusType.radius(x, y, ex.x, ex.y) <= radius)
-                        continue BY_POINT;
-                }
-                ctr = 0;
-                for(Coord tgt : targets)
-                {
-                    if(radiusType.radius(x, y, tgt.x, tgt.y) <= radius)
-                        ctr++;
-                }
-                if(ctr > 0)
-                    locs.get(totalTargets - ctr).add(Coord.get(x, y));
-            }
-        }
-        Coord it;
-        for(int t = 0; t < totalTargets - 1; t++)
-        {
-            if(locs.get(t).size() > 0) {
-                int numPoints = locs.get(t).size();
-                for (int i = 0; i < numPoints; i++) {
-                    it = locs.get(t).get(i);
-                    for (int x = Math.max(1, it.x - radius / 2); x < it.x + (radius + 1) / 2 && x < dungeon.length - 1; x++) {
-                        BY_POINT:
-                        for (int y = Math.max(1, it.y - radius / 2); y <= it.y + (radius - 1) / 2 && y < dungeon[0].length - 1; y++)
-                        {
-                            if(tested[x][y])
-                                continue;
-                            tested[x][y] = true;
-
-                            for(Coord ex : requiredExclusions)
-                            {
-                                if(radiusType.radius(x, y, ex.x, ex.y) <= radius)
-                                    continue BY_POINT;
-                            }
-
-                            ctr = 0;
-                            for(Coord tgt : targets)
-                            {
-                                if(radiusType.radius(x, y, tgt.x, tgt.y) <= radius)
-                                    ctr++;
-                            }
-                            if(ctr > 0)
-                                locs.get(totalTargets - ctr).add(Coord.get(x, y));
-                        }
-                    }
-                }
-            }
-        }
-        return locs;
-    }
-*/
-    @Override
-    public void setMap(char[][] map) {
-        this.map = DungeonUtility.generateResistances(map);
-        dungeon = map;
-    }
-
-    @Override
-    public OrderedMap<Coord, Double> findArea() {
-        return AreaUtils.arrayToHashMap(fov.calculateFOV(map, center.x, center.y, radius, radiusType));
-    }
-
-    @Override
-    public Coord getOrigin() {
-        return origin;
-    }
-
-    @Override
-    public void setOrigin(Coord origin) {
-        this.origin = origin;
-
-    }
-
-    @Override
-    public AimLimit getLimitType() {
-        return reach.limit;
-    }
-
-    @Override
-    public int getMinRange() {
-        return reach.minDistance;
-    }
-
-    @Override
-    public int getMaxRange() {
-        return reach.maxDistance;
-    }
-
-    @Override
-    public Radius getMetric() {
-        return reach.metric;
-    }
-
-    /**
-     * Gets the same values returned by getLimitType(), getMinRange(), getMaxRange(), and getMetric() bundled into one
-     * Reach object.
-     *
-     * @return a non-null Reach object.
-     */
-    @Override
-    public Reach getReach() {
-        return reach;
-    }
-
-    @Override
-    public void setLimitType(AimLimit limitType) {
-        reach.limit = limitType;
-
-    }
-
-    @Override
-    public void setMinRange(int minRange) {
-        reach.minDistance = minRange;
-    }
-
-    @Override
-    public void setMaxRange(int maxRange) {
-        reach.maxDistance = maxRange;
-
-    }
-
-    @Override
-    public void setMetric(Radius metric) {
-        reach.metric = metric;
-    }
-
-    /**
-     * Sets the same values as setLimitType(), setMinRange(), setMaxRange(), and setMetric() using one Reach object.
-     *
-     * @param reach a non-null Reach object.
-     */
-    @Override
-    public void setReach(Reach reach) {
-        if(reach != null)
-            this.reach = reach;
-    }
-
-    /**
-     * If you use FOVCache to pre-compute FOV maps for a level, you can share the speedup from using the cache with
-     * some AOE implementations that rely on FOV. Not all implementations need to actually make use of the cache, but
-     * those that use FOV for calculations should benefit. The cache parameter this receives should have completed its
-     * calculations, which can be confirmed by calling awaitCache(). Ideally, the FOVCache will have done its initial
-     * calculations in another thread while the previous level or menu was being displayed, and awaitCache() will only
-     * be a formality.
-     *
-     * @param cache The FOVCache for the current level; can be null to stop using the cache
-     */
-    @GwtIncompatible
-    @Override
-    public void setCache(FOVCache cache) {
-        fov = cache;
-    }
-
-}

+ 0 - 612
squidlib-util/src/main/java/squidpony/squidai/BurstAOE.java

@@ -1,612 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.annotation.GwtIncompatible;
-import squidpony.squidgrid.FOV;
-import squidpony.squidgrid.FOVCache;
-import squidpony.squidgrid.Radius;
-import squidpony.squidgrid.mapping.DungeonUtility;
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.OrderedSet;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Set;
-
-/**
- * An AOE type that has a center and a radius, and uses shadowcasting to create a burst of rays from the center, out to
- * the distance specified by radius. You can specify the RadiusType to Radius.DIAMOND for Manhattan distance,
- * RADIUS.SQUARE for Chebyshev, or RADIUS.CIRCLE for Euclidean.
- *
- * This will produce doubles for its findArea() method which are equal to 1.0.
- *
- * This class uses squidpony.squidgrid.FOV to create its area of effect.
- * Created by Tommy Ettinger on 7/13/2015.
- */
-public class BurstAOE implements AOE {
-    private FOV fov;
-    private Coord center, origin;
-    private int radius;
-    private double[][] map;
-    private char[][] dungeon;
-    private Radius radiusType;
-    private Reach reach = new Reach(1, 1, Radius.SQUARE, null);
-
-    public BurstAOE(Coord center, int radius, Radius radiusType)
-    {
-        fov = new FOV(FOV.SHADOW);
-        this.center = center;
-        this.radius = radius;
-        this.radiusType = radiusType;
-    }
-    public BurstAOE(Coord center, int radius, Radius radiusType, int minRange, int maxRange)
-    {
-        fov = new FOV(FOV.SHADOW);
-        this.center = center;
-        this.radius = radius;
-        this.radiusType = radiusType;
-        reach.minDistance = minRange;
-        reach.maxDistance = maxRange;
-    }
-
-    public Coord getCenter() {
-        return center;
-    }
-
-    public void setCenter(Coord center) {
-
-        if (map != null && center.isWithin(map.length, map[0].length) &&
-                AreaUtils.verifyReach(reach, origin, center))
-        {
-            this.center = center;
-        }
-    }
-
-    public int getRadius() {
-        return radius;
-    }
-
-    public void setRadius(int radius) {
-        this.radius = radius;
-    }
-
-    public Radius getRadiusType() {
-        return radiusType;
-    }
-
-    public void setRadiusType(Radius radiusType) {
-        this.radiusType = radiusType;
-    }
-
-    @Override
-    public void shift(Coord aim) {
-        setCenter(aim);
-    }
-
-    @Override
-    public boolean mayContainTarget(Set<Coord> targets) {
-        for (Coord p : targets)
-        {
-            if(radiusType.radius(center.x, center.y, p.x, p.y) <= radius)
-                return true;
-        }
-        return false;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        if(targets == null)
-            return new OrderedMap<>();
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = targets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        if(radius == 0)
-        {
-            for(Coord p : targets)
-            {
-                ArrayList<Coord> ap = new ArrayList<>();
-                ap.add(p);
-                bestPoints.put(p, ap);
-            }
-            return bestPoints;
-        }
-        Coord[] ts = targets.toArray(new Coord[targets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[ts.length][dungeon.length][dungeon[0].length];
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-        }
-        double[][] tmpfov;
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = exs[i];
-
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (tmpfov[x][y] > 0.0 || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = ts[0];
-
-        DijkstraMap.Measurement dmm = DijkstraMap.Measurement.MANHATTAN;
-        if(radiusType == Radius.SQUARE || radiusType == Radius.CUBE) dmm = DijkstraMap.Measurement.CHEBYSHEV;
-        else if(radiusType == Radius.CIRCLE || radiusType == Radius.SPHERE) dmm = DijkstraMap.Measurement.EUCLIDEAN;
-
-        for (int i = 0; i < ts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-
-            t = ts[i];
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (tmpfov[x][y] > 0.0) {
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][ts[i].x][ts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-        }
-        double bestQuality = 99999 * ts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long bits = 0;
-                for (int i = 0; i < ts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        bits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }                }
-                else if(qualityMap[x][y] == bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> priorityTargets, Set<Coord> lesserTargets, Set<Coord> requiredExclusions) {
-        if(priorityTargets == null)
-            return idealLocations(lesserTargets, requiredExclusions);
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = priorityTargets.size() + lesserTargets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        if(radius == 0)
-        {
-            for(Coord p : priorityTargets)
-            {
-                ArrayList<Coord> ap = new ArrayList<>();
-                ap.add(p);
-                bestPoints.put(p, ap);
-            }
-            return bestPoints;
-        }
-        Coord[] pts = priorityTargets.toArray(new Coord[priorityTargets.size()]);
-        Coord[] lts = lesserTargets.toArray(new Coord[lesserTargets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[totalTargets][dungeon.length][dungeon[0].length];
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length],
-                dungeonPriorities = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-            Arrays.fill(dungeonPriorities[i], '#');
-        }
-        double[][] tmpfov;
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = exs[i];
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (tmpfov[x][y] > 0.0 || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = pts[0];
-
-        DijkstraMap.Measurement dmm = DijkstraMap.Measurement.MANHATTAN;
-        if(radiusType == Radius.SQUARE || radiusType == Radius.CUBE) dmm = DijkstraMap.Measurement.CHEBYSHEV;
-        else if(radiusType == Radius.CIRCLE || radiusType == Radius.SPHERE) dmm = DijkstraMap.Measurement.EUCLIDEAN;
-
-        for (int i = 0; i < pts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-            t = pts[i];
-
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (tmpfov[x][y] > 0.0){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius) {
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                            dungeonPriorities[x][y] = dungeon[x][y];
-                        }
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][t.x][t.y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 399999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 399999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-
-        t = lts[0];
-
-        for (int i = pts.length; i < totalTargets; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-            t = lts[i - pts.length];
-
-            tmpfov = fov.calculateFOV(map, t.x, t.y, radius, radiusType);
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (tmpfov[x][y] > 0.0){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][t.x][t.y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++)
-                {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!' && dungeonPriorities[x][y] != '#') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-        double bestQuality = 99999 * lts.length + 399999 * pts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long pbits = 0, lbits = 0;
-                for (int i = 0; i < pts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 399999.0 && i < 63)
-                        pbits |= 1 << i;
-                }
-                for (int i = pts.length; i < totalTargets; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        lbits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if((pbits & (1 << i)) != 0)
-                            ap.add(pts[i]);
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if ((pbits & (1 << i)) != 0) {
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                        }
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-    /*
-    @Override
-    public ArrayList<ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        int totalTargets = targets.size() + 1;
-        int maxEffect = (int)radiusType.volume2D(radius);
-        ArrayList<ArrayList<Coord>> locs = new ArrayList<ArrayList<Coord>>(totalTargets);
-
-        for(int i = 0; i < totalTargets; i++)
-        {
-            locs.add(new ArrayList<Coord>(maxEffect));
-        }
-        if(totalTargets == 1)
-            return locs;
-
-        int ctr = 0;
-        if(radius < 1)
-        {
-            locs.get(totalTargets - 2).addAll(targets);
-            return locs;
-        }
-
-        boolean[][] tested = new boolean[dungeon.length][dungeon[0].length];
-        for (int x = 1; x < dungeon.length - 1; x += radius) {
-            BY_POINT:
-            for (int y = 1; y < dungeon[x].length - 1; y += radius) {
-                for(Coord ex : requiredExclusions)
-                {
-                    if(radiusType.radius(x, y, ex.x, ex.y) <= radius)
-                        continue BY_POINT;
-                }
-                ctr = 0;
-                for(Coord tgt : targets)
-                {
-                    if(radiusType.radius(x, y, tgt.x, tgt.y) <= radius)
-                        ctr++;
-                }
-                if(ctr > 0)
-                    locs.get(totalTargets - ctr).add(Coord.get(x, y));
-            }
-        }
-        Coord it;
-        for(int t = 0; t < totalTargets - 1; t++)
-        {
-            if(locs.get(t).size() > 0) {
-                int numPoints = locs.get(t).size();
-                for (int i = 0; i < numPoints; i++) {
-                    it = locs.get(t).get(i);
-                    for (int x = Math.max(1, it.x - radius / 2); x < it.x + (radius + 1) / 2 && x < dungeon.length - 1; x++) {
-                        BY_POINT:
-                        for (int y = Math.max(1, it.y - radius / 2); y <= it.y + (radius - 1) / 2 && y < dungeon[0].length - 1; y++)
-                        {
-                            if(tested[x][y])
-                                continue;
-                            tested[x][y] = true;
-
-                            for(Coord ex : requiredExclusions)
-                            {
-                                if(radiusType.radius(x, y, ex.x, ex.y) <= radius)
-                                    continue BY_POINT;
-                            }
-
-                            ctr = 0;
-                            for(Coord tgt : targets)
-                            {
-                                if(radiusType.radius(x, y, tgt.x, tgt.y) <= radius)
-                                    ctr++;
-                            }
-                            if(ctr > 0)
-                                locs.get(totalTargets - ctr).add(Coord.get(x, y));
-                        }
-                    }
-                }
-            }
-        }
-        return locs;
-    }
-*/
-    @Override
-    public void setMap(char[][] map) {
-        this.map = DungeonUtility.generateResistances(map);
-        dungeon = map;
-    }
-
-    @Override
-    public OrderedMap<Coord, Double> findArea() {
-        return AreaUtils.arrayToHashMap(fov.calculateFOV(null, center.x, center.y, radius, radiusType));
-    }
-
-
-    @Override
-    public Coord getOrigin() {
-        return origin;
-    }
-
-    @Override
-    public void setOrigin(Coord origin) {
-        this.origin = origin;
-
-    }
-
-    @Override
-    public AimLimit getLimitType() {
-        return reach.limit;
-    }
-
-    @Override
-    public int getMinRange() {
-        return reach.minDistance;
-    }
-
-    @Override
-    public int getMaxRange() {
-        return reach.maxDistance;
-    }
-
-    @Override
-    public Radius getMetric() {
-        return reach.metric;
-    }
-
-    /**
-     * Gets the same values returned by getLimitType(), getMinRange(), getMaxRange(), and getMetric() bundled into one
-     * Reach object.
-     *
-     * @return a non-null Reach object.
-     */
-    @Override
-    public Reach getReach() {
-        return reach;
-    }
-
-    @Override
-    public void setLimitType(AimLimit limitType) {
-        reach.limit = limitType;
-
-    }
-
-    @Override
-    public void setMinRange(int minRange) {
-        reach.minDistance = minRange;
-    }
-
-    @Override
-    public void setMaxRange(int maxRange) {
-        reach.maxDistance = maxRange;
-
-    }
-
-    @Override
-    public void setMetric(Radius metric) {
-        reach.metric = metric;
-    }
-
-    /**
-     * Sets the same values as setLimitType(), setMinRange(), setMaxRange(), and setMetric() using one Reach object.
-     *
-     * @param reach a non-null Reach object.
-     */
-    @Override
-    public void setReach(Reach reach) {
-        if(reach != null)
-            this.reach = reach;
-    }
-
-    /**
-     * If you use FOVCache to pre-compute FOV maps for a level, you can share the speedup from using the cache with
-     * some AOE implementations that rely on FOV. Not all implementations need to actually make use of the cache, but
-     * those that use FOV for calculations should benefit. The cache parameter this receives should have completed its
-     * calculations, which can be confirmed by calling awaitCache(). Ideally, the FOVCache will have done its initial
-     * calculations in another thread while the previous level or menu was being displayed, and awaitCache() will only
-     * be a formality.
-     *
-     * @param cache The FOVCache for the current level; can be null to stop using the cache
-     */
-    @GwtIncompatible
-    @Override
-    public void setCache(FOVCache cache) {
-        fov = cache;
-    }
-
-}

+ 0 - 751
squidlib-util/src/main/java/squidpony/squidai/CloudAOE.java

@@ -1,751 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.annotation.GwtIncompatible;
-import squidpony.squidgrid.FOVCache;
-import squidpony.squidgrid.Radius;
-import squidpony.squidgrid.Spill;
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.LightRNG;
-import squidpony.squidmath.RNG;
-
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.OrderedSet;
-
-import java.util.*;
-
-/**
- * An AOE type that has a center and a volume, and will randomly expand in all directions until it reaches volume or
- * cannot expand further. Specify the RadiusType as Radius.DIAMOND for Manhattan distance (and the best results),
- * RADIUS.SQUARE for Chebyshev, or RADIUS.CIRCLE for Euclidean. You can specify a seed for the RNG and a fresh RNG will
- * be used for all random expansion; the RNG will reset to the specified seed after each generation so the same
- * CloudAOE can be used in different places by just changing the center. You can cause the CloudAOE to not reset after
- * generating each time by using setExpanding(true) and cause it to reset after the next generation by setting it back
- * to the default of false. If expanding is true, then multiple calls to findArea with the same center and larger
- * volumes will produce more solid clumps of affected area with fewer gaps, and can be spaced out over multiple calls.
- *
- * This will produce doubles for its findArea() method which are equal to 1.0.
- *
- * This class uses squidpony.squidgrid.Spill to create its area of effect.
- * Created by Tommy Ettinger on 7/13/2015.
- */
-public class CloudAOE implements AOE {
-    private Spill spill;
-    private Coord center, origin = null;
-    private int volume;
-    private long seed;
-    private boolean expanding;
-    private Radius rt;
-    private Reach reach = new Reach(1, 1, Radius.SQUARE, null);
-    private char[][] dungeon;
-
-    public CloudAOE(Coord center, int volume, Radius radiusType)
-    {
-        LightRNG l = new LightRNG();
-        seed = l.getState();
-        spill = new Spill(new RNG(l));
-        this.center = center;
-        this.volume = volume;
-        expanding = false;
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case SPHERE:
-            case CIRCLE:
-                spill.measurement = Spill.Measurement.EUCLIDEAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                spill.measurement = Spill.Measurement.CHEBYSHEV;
-                break;
-            default:
-                spill.measurement = Spill.Measurement.MANHATTAN;
-                break;
-        }
-    }
-
-    public CloudAOE(Coord center, int volume, Radius radiusType, int minRange, int maxRange)
-    {
-        LightRNG l = new LightRNG();
-        seed = l.getState();
-        spill = new Spill(new RNG(l));
-        this.center = center;
-        this.volume = volume;
-        expanding = false;
-        rt = radiusType;
-        reach.minDistance = minRange;
-        reach.maxDistance = maxRange;
-        switch (radiusType)
-        {
-            case SPHERE:
-            case CIRCLE:
-                spill.measurement = Spill.Measurement.EUCLIDEAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                spill.measurement = Spill.Measurement.CHEBYSHEV;
-                break;
-            default:
-                spill.measurement = Spill.Measurement.MANHATTAN;
-                break;
-        }
-    }
-    public CloudAOE(Coord center, int volume, Radius radiusType, long rngSeed)
-    {
-        seed = rngSeed;
-        spill = new Spill(new RNG(new LightRNG(rngSeed)));
-        this.center = center;
-        this.volume = volume;
-        expanding = false;
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case SPHERE:
-            case CIRCLE:
-                spill.measurement = Spill.Measurement.EUCLIDEAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                spill.measurement = Spill.Measurement.CHEBYSHEV;
-                break;
-            default:
-                spill.measurement = Spill.Measurement.MANHATTAN;
-                break;
-        }
-    }
-    public CloudAOE(Coord center, int volume, Radius radiusType, long rngSeed, int minRange, int maxRange)
-    {
-        seed = rngSeed;
-        spill = new Spill(new RNG(new LightRNG(rngSeed)));
-        this.center = center;
-        this.volume = volume;
-        expanding = false;
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case SPHERE:
-            case CIRCLE:
-                spill.measurement = Spill.Measurement.EUCLIDEAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                spill.measurement = Spill.Measurement.CHEBYSHEV;
-                break;
-            default:
-                spill.measurement = Spill.Measurement.MANHATTAN;
-                break;
-        }
-        reach.minDistance = minRange;
-        reach.maxDistance = maxRange;
-    }
-
-    public Coord getCenter() {
-        return center;
-    }
-
-    public void setCenter(Coord center) {
-
-        if (dungeon != null && center.isWithin(dungeon.length, dungeon[0].length) &&
-                AreaUtils.verifyReach(reach, origin, center))
-        {
-            this.center = center;
-        }
-    }
-
-    public int getVolume() {
-        return volume;
-    }
-
-    public void setVolume(int volume) {
-        this.volume = volume;
-    }
-
-    public Radius getRadiusType() {
-        return rt;
-    }
-
-    public void setRadiusType(Radius radiusType) {
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case SPHERE:
-            case CIRCLE:
-                break;
-            case CUBE:
-            case SQUARE:
-                break;
-            default:
-                break;
-        }
-    }
-
-    @Override
-    public void shift(Coord aim) {
-        setCenter(aim);
-    }
-
-    @Override
-    public boolean mayContainTarget(Set<Coord> targets) {
-        for (Coord p : targets)
-        {
-            if(rt.radius(center.x, center.y, p.x, p.y) <= Math.sqrt(volume) * 0.75)
-                return true;
-        }
-        return false;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        if(targets == null)
-            return new OrderedMap<>();
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = targets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0 || volume <= 0)
-            return bestPoints;
-
-        if(volume == 1)
-        {
-            for(Coord p : targets)
-            {
-                ArrayList<Coord> ap = new ArrayList<>();
-                ap.add(p);
-                bestPoints.put(p, ap);
-            }
-            return bestPoints;
-        }
-        Coord[] ts = targets.toArray(new Coord[targets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[ts.length][dungeon.length][dungeon[0].length];
-
-        Spill sp;
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-        }
-
-        Coord tempPt;
-        for (int i = 0; i < exs.length; ++i) {
-            t = exs[i];
-            sp = new Spill(dungeon, spill.measurement);
-            sp.lrng.setState(seed);
-
-            sp.start(t, volume, null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (sp.spillMap[x][y] || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        DijkstraMap.Measurement dmm = DijkstraMap.Measurement.MANHATTAN;
-        if(spill.measurement == Spill.Measurement.CHEBYSHEV) dmm = DijkstraMap.Measurement.CHEBYSHEV;
-        else if(spill.measurement == Spill.Measurement.EUCLIDEAN) dmm = DijkstraMap.Measurement.EUCLIDEAN;
-
-        double radius = Math.sqrt(volume) * 0.75;
-
-        for (int i = 0; i < ts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-
-            t = ts[i];
-            sp = new Spill(dungeon, spill.measurement);
-            sp.lrng.setState(seed);
-
-            sp.start(t, volume, null);
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (sp.spillMap[x][y]){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][ts[i].x][ts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-        double bestQuality = 99999 * ts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long bits = 0;
-                for (int i = 0; i < ts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        bits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> priorityTargets, Set<Coord> lesserTargets, Set<Coord> requiredExclusions) {
-        if(priorityTargets == null)
-            return idealLocations(lesserTargets, requiredExclusions);
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-
-        int totalTargets = priorityTargets.size() + lesserTargets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0 || volume <= 0)
-            return bestPoints;
-
-        if(volume == 1)
-        {
-            for(Coord p : priorityTargets)
-            {
-                ArrayList<Coord> ap = new ArrayList<>();
-                ap.add(p);
-                bestPoints.put(p, ap);
-            }
-            return bestPoints;
-        }
-        Coord[] pts = priorityTargets.toArray(new Coord[priorityTargets.size()]);
-        Coord[] lts = lesserTargets.toArray(new Coord[lesserTargets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[totalTargets][dungeon.length][dungeon[0].length];
-        Spill sp;
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length],
-                dungeonPriorities = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-            Arrays.fill(dungeonPriorities[i], '#');
-        }
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = exs[i];
-            sp = new Spill(dungeon, spill.measurement);
-            sp.lrng.setState(seed);
-
-            sp.start(t, volume, null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (sp.spillMap[x][y] || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = pts[0];
-
-        DijkstraMap.Measurement dmm = DijkstraMap.Measurement.MANHATTAN;
-        if(spill.measurement == Spill.Measurement.CHEBYSHEV) dmm = DijkstraMap.Measurement.CHEBYSHEV;
-        else if(spill.measurement == Spill.Measurement.EUCLIDEAN) dmm = DijkstraMap.Measurement.EUCLIDEAN;
-
-        double radius = Math.sqrt(volume) * 0.75;
-
-        for (int i = 0; i < pts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-
-            t = pts[i];
-            sp = new Spill(dungeon, spill.measurement);
-            sp.lrng.setState(seed);
-
-            sp.start(t, volume, null);
-
-
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (sp.spillMap[x][y]){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius) {
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                            dungeonPriorities[x][y] = dungeon[x][y];
-                        }
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][pts[i].x][pts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 399999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 399999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-
-        t = lts[0];
-
-        for (int i = pts.length; i < totalTargets; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-
-            t = lts[i - pts.length];
-            sp = new Spill(dungeon, spill.measurement);
-            sp.lrng.setState(seed);
-
-            sp.start(t, volume, null);
-
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (sp.spillMap[x][y]){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][lts[i - pts.length].x][lts[i - pts.length].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++)
-                {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!' && dungeonPriorities[x][y] != '#') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-        double bestQuality = 99999 * lts.length + 399999 * pts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long pbits = 0, lbits = 0;
-                for (int i = 0; i < pts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 399999.0 && i < 63)
-                        pbits |= 1 << i;
-                }
-                for (int i = pts.length; i < totalTargets; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        lbits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if((pbits & (1 << i)) != 0)
-                            ap.add(pts[i]);
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if((pbits & (1 << i)) != 0)
-                            ap.add(pts[i]);
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if ((pbits & (1 << i)) != 0) {
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                        }
-                    }
-
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-
-/*
-    @Override
-    public ArrayList<ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        int totalTargets = targets.size() + 1;
-        int radius = Math.max(1, (int) (Math.sqrt(volume) * 1.5));
-        ArrayList<ArrayList<Coord>> locs = new ArrayList<ArrayList<Coord>>(totalTargets);
-
-        for(int i = 0; i < totalTargets; i++)
-        {
-            locs.add(new ArrayList<Coord>(volume));
-        }
-        if(totalTargets == 1)
-            return locs;
-        double ctr = 0;
-        if(radius < 1)
-        {
-            locs.get(totalTargets - 2).addAll(targets);
-            return locs;
-        }
-        double tempRad;
-        boolean[][] tested = new boolean[dungeon.length][dungeon[0].length];
-        for (int x = 1; x < dungeon.length - 1; x += radius) {
-            BY_POINT:
-            for (int y = 1; y < dungeon[x].length - 1; y += radius) {
-                for(Coord ex : requiredExclusions)
-                {
-                    if(rt.radius(x, y, ex.x, ex.y) <= radius * 0.75)
-                        continue BY_POINT;
-                }
-                ctr = 0;
-                for(Coord tgt : targets)
-                {
-                    tempRad = rt.radius(x, y, tgt.x, tgt.y);
-                    if(tempRad < radius)
-                        ctr += 1.0 - (tempRad / radius) * 0.5;
-                }
-                if(ctr >= 1)
-                    locs.get((int)(totalTargets - ctr)).add(Coord.get(x, y));
-            }
-        }
-        Coord it;
-        for(int t = 0; t < totalTargets - 1; t++)
-        {
-            if(locs.get(t).size() > 0) {
-                int numPoints = locs.get(t).size();
-                for (int i = 0; i < numPoints; i++) {
-                    it = locs.get(t).get(i);
-                    for (int x = Math.max(1, it.x - radius / 2); x < it.x + (radius + 1) / 2 && x < dungeon.length - 1; x++) {
-                        BY_POINT:
-                        for (int y = Math.max(1, it.y - radius / 2); y <= it.y + (radius - 1) / 2 && y < dungeon[0].length - 1; y++)
-                        {
-                            if(tested[x][y])
-                                continue;
-                            tested[x][y] = true;
-
-                            for(Coord ex : requiredExclusions)
-                            {
-                                if(rt.radius(x, y, ex.x, ex.y) <= radius * 0.75)
-                                    continue BY_POINT;
-                            }
-
-                            ctr = 0;
-                            for(Coord tgt : targets)
-                            {
-                                tempRad = rt.radius(x, y, tgt.x, tgt.y);
-                                if(tempRad < radius)
-                                    ctr += 1.0 - (tempRad / radius) * 0.5;
-                            }
-                            if(ctr >= 1)
-                                locs.get((int)(totalTargets - ctr)).add(Coord.get(x, y));
-                        }
-                    }
-                }
-            }
-        }
-        return locs;
-    }
-*/
-
-    @Override
-    public void setMap(char[][] map) {
-        spill.initialize(map);
-        dungeon = map;
-    }
-
-    @Override
-    public OrderedMap<Coord, Double> findArea() {
-        spill.start(center, volume, null);
-        OrderedMap<Coord, Double> r = AreaUtils.arrayToHashMap(spill.spillMap);
-        if(!expanding)
-        {
-            spill.reset();
-            spill.lrng.setState(seed);
-        }
-        return r;
-    }
-
-    @Override
-    public Coord getOrigin() {
-        return origin;
-    }
-
-    @Override
-    public void setOrigin(Coord origin) {
-        this.origin = origin;
-
-    }
-
-    @Override
-    public AimLimit getLimitType() {
-        return reach.limit;
-    }
-
-    @Override
-    public int getMinRange() {
-        return reach.minDistance;
-    }
-
-    @Override
-    public int getMaxRange() {
-        return reach.maxDistance;
-    }
-
-    @Override
-    public Radius getMetric() {
-        return reach.metric;
-    }
-
-    /**
-     * Gets the same values returned by getLimitType(), getMinRange(), getMaxRange(), and getMetric() bundled into one
-     * Reach object.
-     *
-     * @return a non-null Reach object.
-     */
-    @Override
-    public Reach getReach() {
-        return reach;
-    }
-
-    @Override
-    public void setLimitType(AimLimit limitType) {
-        reach.limit = limitType;
-
-    }
-
-    @Override
-    public void setMinRange(int minRange) {
-        reach.minDistance = minRange;
-    }
-
-    @Override
-    public void setMaxRange(int maxRange) {
-        reach.maxDistance = maxRange;
-
-    }
-
-    @Override
-    public void setMetric(Radius metric) {
-        reach.metric = metric;
-    }
-
-    /**
-     * Sets the same values as setLimitType(), setMinRange(), setMaxRange(), and setMetric() using one Reach object.
-     *
-     * @param reach a non-null Reach object.
-     */
-    @Override
-    public void setReach(Reach reach) {
-        if(reach != null)
-            this.reach = reach;
-    }
-
-    public boolean isExpanding() {
-        return expanding;
-    }
-
-    public void setExpanding(boolean expanding) {
-        this.expanding = expanding;
-    }
-
-    /**
-     * If you use FOVCache to pre-compute FOV maps for a level, you can share the speedup from using the cache with
-     * some AOE implementations that rely on FOV. Not all implementations need to actually make use of the cache, but
-     * those that use FOV for calculations should benefit. The cache parameter this receives should have completed its
-     * calculations, which can be confirmed by calling awaitCache(). Ideally, the FOVCache will have done its initial
-     * calculations in another thread while the previous level or menu was being displayed, and awaitCache() will only
-     * be a formality.
-     *
-     * @param cache The FOVCache for the current level; can be null to stop using the cache
-     */
-    @GwtIncompatible
-    @Override
-    public void setCache(FOVCache cache) {
-
-    }
-}

+ 0 - 642
squidlib-util/src/main/java/squidpony/squidai/ConeAOE.java

@@ -1,642 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.annotation.GwtIncompatible;
-import squidpony.squidgrid.FOV;
-import squidpony.squidgrid.FOVCache;
-import squidpony.squidgrid.Radius;
-import squidpony.squidgrid.mapping.DungeonUtility;
-import squidpony.squidmath.Coord;
-
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.OrderedSet;
-
-import java.util.*;
-
-/**
- * An AOE type that has an origin, a radius, an angle, and a span; it will blast from the origin to a length equal to
- * radius along the angle (in degrees), moving somewhat around corners/obstacles, and also spread a total of span
- * degrees around the angle (a span of 90 will affect a full quadrant, centered on angle). You can specify the
- * RadiusType to Radius.DIAMOND for Manhattan distance, RADIUS.SQUARE for Chebyshev, or RADIUS.CIRCLE for Euclidean.
- *
- * RADIUS.CIRCLE (Euclidean measurement) will produce the most real-looking cones. This will produce doubles for its
- * findArea() method which are greater than 0.0 and less than or equal to 1.0.
- *
- * This class uses squidpony.squidgrid.FOV to create its area of effect.
- * Created by Tommy Ettinger on 7/13/2015.
- */
-public class ConeAOE implements AOE {
-    private FOV fov;
-    private Coord origin;
-    private double radius, angle, span;
-    private double[][] map;
-    private char[][] dungeon;
-    private Radius radiusType;
-    private Reach reach = new Reach(1, 1, Radius.SQUARE, null);
-
-    public ConeAOE(Coord origin, Coord endCenter, double span, Radius radiusType)
-    {
-        fov = new FOV(FOV.RIPPLE_LOOSE);
-        this.origin = origin;
-        radius = radiusType.radius(origin.x, origin.y, endCenter.x, endCenter.y);
-        angle = (Math.toDegrees(Math.atan2(endCenter.y - origin.y, endCenter.x - origin.x)) % 360.0 + 360.0) % 360.0;
-//        this.startAngle = Math.abs((angle - span / 2.0) % 360.0);
-//        this.endAngle = Math.abs((angle + span / 2.0) % 360.0);
-        this.span = span;
-        this.radiusType = radiusType;
-    }
-    public ConeAOE(Coord origin, int radius, double angle, double span, Radius radiusType)
-    {
-        fov = new FOV(FOV.RIPPLE_LOOSE);
-        this.origin = origin;
-        this.radius = radius;
-//        this.startAngle = Math.abs((angle - span / 2.0) % 360.0);
-//        this.endAngle = Math.abs((angle + span / 2.0) % 360.0);
-        this.angle = angle;
-        this.span = span;
-        this.radiusType = radiusType;
-    }
-
-    @Override
-	public Coord getOrigin() {
-        return origin;
-    }
-
-    @Override
-	public void setOrigin(Coord origin) {
-        this.origin = origin;
-    }
-
-    @Override
-    public AimLimit getLimitType() {
-        return reach.limit;
-    }
-
-    @Override
-    public int getMinRange() {
-        return reach.minDistance;
-    }
-
-    @Override
-    public int getMaxRange() {
-        return reach.maxDistance;
-    }
-
-    @Override
-    public Radius getMetric() {
-        return reach.metric;
-    }
-
-    /**
-     * Gets the same values returned by getLimitType(), getMinRange(), getMaxRange(), and getMetric() bundled into one
-     * Reach object.
-     *
-     * @return a non-null Reach object.
-     */
-    @Override
-    public Reach getReach() {
-        return reach;
-    }
-
-    @Override
-    public void setLimitType(AimLimit limitType) {
-        reach.limit = limitType;
-
-    }
-
-    @Override
-    public void setMinRange(int minRange) {
-        reach.minDistance = minRange;
-    }
-
-    @Override
-    public void setMaxRange(int maxRange) {
-        reach.maxDistance = maxRange;
-
-    }
-
-    @Override
-    public void setMetric(Radius metric) {
-        reach.metric = metric;
-    }
-
-    /**
-     * Sets the same values as setLimitType(), setMinRange(), setMaxRange(), and setMetric() using one Reach object.
-     *
-     * @param reach a non-null Reach object.
-     */
-    @Override
-    public void setReach(Reach reach) {
-        if(reach != null)
-            this.reach = reach;
-    }
-
-    public double getRadius() {
-        return radius;
-    }
-
-    public void setRadius(double radius) {
-        this.radius = radius;
-    }
-
-    public double getAngle() {
-        return angle;
-    }
-
-    public void setAngle(double angle) {
-        if (reach.limit == null || reach.limit == AimLimit.FREE ||
-                (reach.limit == AimLimit.EIGHT_WAY && (int) angle % 45 == 0) ||
-                (reach.limit == AimLimit.DIAGONAL && (int) angle % 90 == 45) ||
-                (reach.limit == AimLimit.ORTHOGONAL && (int) angle % 90 == 0)) {
-            this.angle = angle;
-//            this.startAngle = Math.abs((angle - span / 2.0) % 360.0);
-//            this.endAngle = Math.abs((angle + span / 2.0) % 360.0);
-        }
-    }
-
-    public void setEndCenter(Coord endCenter) {
-//        radius = radiusType.radius(origin.x, origin.y, endCenter.x, endCenter.y);
-        if (AreaUtils.verifyLimit(reach.limit, origin, endCenter)) {
-            angle = (Math.toDegrees(Math.atan2(endCenter.y - origin.y, endCenter.x - origin.x)) % 360.0 + 360.0) % 360.0;
-//            startAngle = Math.abs((angle - span / 2.0) % 360.0);
-//            endAngle = Math.abs((angle + span / 2.0) % 360.0);
-        }
-    }
-
-    public double getSpan() {
-        return span;
-    }
-
-    public void setSpan(double span) {
-        this.span = span;
-//        this.startAngle = Math.abs((angle - span / 2.0) % 360.0);
-//        this.endAngle = Math.abs((angle + span / 2.0) % 360.0);
-    }
-
-    public Radius getRadiusType() {
-        return radiusType;
-    }
-
-    public void setRadiusType(Radius radiusType) {
-        this.radiusType = radiusType;
-    }
-
-    @Override
-    public void shift(Coord aim) {
-        setEndCenter(aim);
-    }
-
-    @Override
-    public boolean mayContainTarget(Set<Coord> targets) {
-        for (Coord p : targets) {
-            if (radiusType.radius(origin.x, origin.y, p.x, p.y) <= radius) {
-                double d = (angle - Math.toDegrees(Math.atan2(p.y - origin.y, p.x - origin.x)) % 360.0 + 360.0) % 360.0;
-                if(d > 180)
-                    d = 360 - d;
-                if(d < span / 2.0)
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        if(targets == null)
-            return new OrderedMap<>();
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = targets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        Coord[] ts = targets.toArray(new Coord[targets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[ts.length][dungeon.length][dungeon[0].length];
-        double tAngle; //, tStartAngle, tEndAngle;
-
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-        }
-        double[][] tmpfov;
-        Coord tempPt = Coord.get(0, 0);
-
-        for (int i = 0; i < exs.length; i++) {
-            t = exs[i];
-//            tRadius = radiusType.radius(origin.x, origin.y, t.x, t.y);
-            tAngle = (Math.toDegrees(Math.atan2(t.y - origin.y, t.x - origin.x)) % 360.0 + 360.0) % 360.0;
-//            tStartAngle = Math.abs((tAngle - span / 2.0) % 360.0);
-//            tEndAngle = Math.abs((tAngle + span / 2.0) % 360.0);
-            tmpfov = fov.calculateFOV(map, origin.x, origin.y, radius, radiusType, tAngle, span);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (tmpfov[x][y] > 0.0 || !AreaUtils.verifyLimit(reach.limit, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = ts[0];
-
-        DijkstraMap.Measurement dmm = DijkstraMap.Measurement.MANHATTAN;
-        if(radiusType == Radius.SQUARE || radiusType == Radius.CUBE) dmm = DijkstraMap.Measurement.CHEBYSHEV;
-        else if(radiusType == Radius.CIRCLE || radiusType == Radius.SPHERE) dmm = DijkstraMap.Measurement.EUCLIDEAN;
-
-        for (int i = 0; i < ts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-            t = ts[i];
-//            tRadius = radiusType.radius(origin.x, origin.y, t.x, t.y);
-            tAngle = (Math.toDegrees(Math.atan2(t.y - origin.y, t.x - origin.x)) % 360.0 + 360.0) % 360.0;
-//            tStartAngle = Math.abs((tAngle - span / 2.0) % 360.0);
-//            tEndAngle = Math.abs((tAngle + span / 2.0) % 360.0);
-
-            tmpfov = fov.calculateFOV(map, origin.x, origin.y, radius, radiusType, tAngle, span);
-
-
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (tmpfov[x][y] > 0.0)
-                    {
-                        compositeMap[i][x][y] = dm.physicalMap[x][y];
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][t.x][t.y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-        }
-        double bestQuality = 99999 * ts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long bits = 0;
-                for (int i = 0; i < ts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        bits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality) {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if ((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-
-            }
-        }
-
-        return bestPoints;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> priorityTargets, Set<Coord> lesserTargets, Set<Coord> requiredExclusions) {
-        if(priorityTargets == null)
-            return idealLocations(lesserTargets, requiredExclusions);
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = priorityTargets.size() + lesserTargets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        Coord[] pts = priorityTargets.toArray(new Coord[priorityTargets.size()]);
-        Coord[] lts = lesserTargets.toArray(new Coord[lesserTargets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[totalTargets][dungeon.length][dungeon[0].length];
-        double tAngle; //, tStartAngle, tEndAngle;
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length],
-                dungeonPriorities = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-            Arrays.fill(dungeonPriorities[i], '#');
-        }
-        double[][] tmpfov;
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = exs[i];
-
-            tAngle = (Math.toDegrees(Math.atan2(t.y - origin.y, t.x - origin.x)) % 360.0 + 360.0) % 360.0;
-//            tStartAngle = Math.abs((tAngle - span / 2.0) % 360.0);
-//            tEndAngle = Math.abs((tAngle + span / 2.0) % 360.0);
-            tmpfov = fov.calculateFOV(map, origin.x, origin.y, radius, radiusType, tAngle, span);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (tmpfov[x][y] > 0.0 || !AreaUtils.verifyLimit(reach.limit, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = pts[0];
-
-        DijkstraMap.Measurement dmm = DijkstraMap.Measurement.MANHATTAN;
-        if(radiusType == Radius.SQUARE || radiusType == Radius.CUBE) dmm = DijkstraMap.Measurement.CHEBYSHEV;
-        else if(radiusType == Radius.CIRCLE || radiusType == Radius.SPHERE) dmm = DijkstraMap.Measurement.EUCLIDEAN;
-
-        for (int i = 0; i < pts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-            t = pts[i];
-            tAngle = (Math.toDegrees(Math.atan2(t.y - origin.y, t.x - origin.x)) % 360.0 + 360.0) % 360.0;
-//            tStartAngle = Math.abs((tAngle - span / 2.0) % 360.0);
-//            tEndAngle = Math.abs((tAngle + span / 2.0) % 360.0);
-
-            tmpfov = fov.calculateFOV(map, origin.x, origin.y, radius, radiusType, tAngle, span);
-
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (tmpfov[x][y] > 0.0){
-                        compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        dungeonPriorities[x][y] = dungeon[x][y];
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][pts[i].x][pts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 399999.0);
-                }
-                continue;
-            }
-
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 399999.0;
-                }
-            }
-        }
-
-        t = lts[0];
-
-        for (int i = pts.length; i < totalTargets; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dmm);
-            t = lts[i - pts.length];
-            tAngle = (Math.toDegrees(Math.atan2(t.y - origin.y, t.x - origin.x)) % 360.0 + 360.0) % 360.0;
-//            tStartAngle = Math.abs((tAngle - span / 2.0) % 360.0);
-//            tEndAngle = Math.abs((tAngle + span / 2.0) % 360.0);
-
-            tmpfov = fov.calculateFOV(map, origin.x, origin.y, radius, radiusType, tAngle, span);
-
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (tmpfov[x][y] > 0.0){
-                         compositeMap[i][x][y] = dm.physicalMap[x][y];
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][lts[i - pts.length].x][lts[i - pts.length].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++)
-                {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!' && dungeonPriorities[x][y] != '#') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-        }
-        double bestQuality = 99999 * lts.length + 399999 * pts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long pbits = 0, lbits = 0;
-                for (int i = 0; i < pts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 399999.0 && i < 63)
-                        pbits |= 1 << i;
-                }
-                for (int i = pts.length; i < totalTargets; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        lbits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if((pbits & (1 << i)) != 0)
-                            ap.add(pts[i]);
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-
-                }
-                else if(qualityMap[x][y] == bestQuality) {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if ((pbits & (1 << i)) != 0) {
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                        }
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if ((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-    /*
-    @Override
-    public ArrayList<ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        int totalTargets = targets.size() + 1;
-        int maxEffect = (int)(radiusType.volume2D(radius) * Math.max(5, span) / 360.0);
-        double allowed = Math.toRadians(span / 2.0);
-        ArrayList<ArrayList<Coord>> locs = new ArrayList<ArrayList<Coord>>(totalTargets);
-
-        for(int i = 0; i < totalTargets; i++)
-        {
-            locs.add(new ArrayList<Coord>(maxEffect));
-        }
-        if(totalTargets == 1)
-            return locs;
-
-        int ctr = 0;
-        if(radius < 1)
-        {
-            locs.get(totalTargets - 2).addAll(targets);
-            return locs;
-        }
-
-        double tmpAngle, ang;
-        boolean[][] tested = new boolean[dungeon.length][dungeon[0].length];
-        for (int x = 1; x < dungeon.length - 1; x += radius) {
-            BY_POINT:
-            for (int y = 1; y < dungeon[x].length - 1; y += radius) {
-                ang = Math.atan2(y - origin.y, x - origin.x); // between -pi and pi
-
-                for(Coord ex : requiredExclusions) {
-                    if (radiusType.radius(x, y, ex.x, ex.y) <= radius) {
-                        tmpAngle = Math.abs(ang - Math.atan2(ex.y - origin.y, ex.x - origin.x));
-                        if(tmpAngle > Math.PI) tmpAngle = PI2 - tmpAngle;
-                        if(tmpAngle < allowed)
-                            continue BY_POINT;
-                    }
-                }
-                ctr = 0;
-                for(Coord tgt : targets) {
-                    if (radiusType.radius(x, y, tgt.x, tgt.y) <= radius) {
-                        tmpAngle = Math.abs(ang - Math.atan2(tgt.y - origin.y, tgt.x - origin.x));
-                        if(tmpAngle > Math.PI) tmpAngle = PI2 - tmpAngle;
-                        if(tmpAngle < allowed)
-                            ctr++;
-                    }
-                }
-                if(ctr > 0)
-                    locs.get(totalTargets - ctr).add(Coord.get(x, y));
-            }
-        }
-        Coord it;
-        for(int t = 0; t < totalTargets - 1; t++)
-        {
-            if(locs.get(t).size() > 0) {
-                int numPoints = locs.get(t).size();
-                for (int i = 0; i < numPoints; i++) {
-                    it = locs.get(t).get(i);
-                    for (int x = Math.max(1, it.x - (int)(radius) / 2); x < it.x + (radius + 1) / 2 && x < dungeon.length - 1; x++) {
-                        BY_POINT:
-                        for (int y = Math.max(1, it.y - (int)(radius) / 2); y <= it.y + (radius - 1) / 2 && y < dungeon[0].length - 1; y++)
-                        {
-                            if(tested[x][y])
-                                continue;
-                            tested[x][y] = true;
-                            ang = Math.atan2(y - origin.y, x - origin.x); // between -pi and pi
-                            for(Coord ex : requiredExclusions) {
-                                if (radiusType.radius(x, y, ex.x, ex.y) <= radius) {
-                                    tmpAngle = Math.abs(ang - Math.atan2(ex.y - origin.y, ex.x - origin.x));
-                                    if(tmpAngle > Math.PI) tmpAngle = PI2 - tmpAngle;
-                                    if(tmpAngle < allowed)
-                                        continue BY_POINT;
-                                }
-                            }
-
-                            ctr = 0;
-                            for(Coord tgt : targets) {
-                                if (radiusType.radius(x, y, tgt.x, tgt.y) <= radius) {
-                                    tmpAngle = Math.abs(ang - Math.atan2(tgt.y - origin.y, tgt.x - origin.x));
-                                    if(tmpAngle > Math.PI) tmpAngle = PI2 - tmpAngle;
-                                    if(tmpAngle < allowed)
-                                        ctr++;
-                                }
-                            }
-                            if(ctr > 0)
-                                locs.get(totalTargets - ctr).add(Coord.get(x, y));
-                        }
-                    }
-                }
-            }
-        }
-        return locs;
-    }
-*/
-    @Override
-    public void setMap(char[][] map) {
-        this.map = DungeonUtility.generateResistances(map);
-        dungeon = map;
-    }
-
-    @Override
-    public OrderedMap<Coord, Double> findArea() {
-        OrderedMap<Coord, Double> r = AreaUtils.arrayToHashMap(fov.calculateFOV(map, origin.x, origin.y, radius,
-                radiusType, angle, span));
-        r.remove(origin);
-        return r;
-    }
-
-    /**
-     * If you use FOVCache to pre-compute FOV maps for a level, you can share the speedup from using the cache with
-     * some AOE implementations that rely on FOV. Not all implementations need to actually make use of the cache, but
-     * those that use FOV for calculations should benefit. The cache parameter this receives should have completed its
-     * calculations, which can be confirmed by calling awaitCache(). Ideally, the FOVCache will have done its initial
-     * calculations in another thread while the previous level or menu was being displayed, and awaitCache() will only
-     * be a formality.
-     *
-     * @param cache The FOVCache for the current level; can be null to stop using the cache
-     */
-    @GwtIncompatible
-    @Override
-    public void setCache(FOVCache cache) {
-        fov = cache;
-    }
-
-}

Fichier diff supprimé car celui-ci est trop grand
+ 2872 - 3341
squidlib-util/src/main/java/squidpony/squidai/DijkstraMap.java


+ 0 - 723
squidlib-util/src/main/java/squidpony/squidai/LineAOE.java

@@ -1,723 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.annotation.GwtIncompatible;
-import squidpony.squidgrid.FOVCache;
-import squidpony.squidgrid.LOS;
-import squidpony.squidgrid.Radius;
-import squidpony.squidgrid.mapping.DungeonUtility;
-import squidpony.squidmath.Coord;
-
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.OrderedSet;
-
-import java.util.*;
-
-/**
- * Line Area of Effect that affects an slightly expanded (Elias) line from a given origin Coord to a given end Coord,
- * plus an optional radius of cells around the path of the line, while respecting obstacles in its path and possibly
- * stopping if obstructed. You can specify the RadiusType to Radius.DIAMOND for Manhattan distance, RADIUS.SQUARE for
- * Chebyshev, or RADIUS.CIRCLE for Euclidean.
- *
- * You may want the BeamAOE class instead of this. LineAOE travels point-to-point and does not restrict length, while
- * BeamAOE travels a specific length (and may have a radius, like LineAOE) but then stops only after the travel down the
- * length and radius has reached its end. This difference is relevant if a game has effects that have a definite
- * area measured in a rectangle or elongated pillbox shape, such as a "20-foot-wide bolt of lightning, 100 feet long."
- * BeamAOE is more suitable for that effect, while LineAOE may be more suitable for things like focused lasers that
- * pass through small (likely fleshy) obstacles but stop after hitting the aimed-at target.
- *
- * LineAOE will strike a small area behind the user and in the opposite direction of the target if the radius is
- * greater than 0. This behavior may be altered in a future version.
- *
- * This will produce doubles for its findArea() method which are equal to 1.0.
- *
- * This class uses squidpony.squidmath.Elias and squidpony.squidai.DijkstraMap to create its area of effect.
- * Created by Tommy Ettinger on 7/14/2015.
- */
-public class LineAOE implements AOE {
-    private Coord origin, end;
-    private int radius;
-    private char[][] dungeon;
-    private DijkstraMap dijkstra;
-    private Radius rt;
-    private LOS los;
-    private Reach reach = new Reach(1, 1, Radius.SQUARE, null);
-    public LineAOE(Coord origin, Coord end)
-    {
-        dijkstra = new DijkstraMap();
-        dijkstra.measurement = DijkstraMap.Measurement.CHEBYSHEV;
-        rt = Radius.SQUARE;
-        this.origin = origin;
-        this.end = end;
-        radius = 0;
-        los = new LOS(LOS.DDA);
-    }
-    public LineAOE(Coord origin, Coord end, int radius)
-    {
-        dijkstra = new DijkstraMap();
-        dijkstra.measurement = DijkstraMap.Measurement.CHEBYSHEV;
-        rt = Radius.SQUARE;
-        this.origin = origin;
-        this.end = end;
-        this.radius = radius;
-        los = new LOS(LOS.DDA);
-    }
-    public LineAOE(Coord origin, Coord end, int radius, Radius radiusType)
-    {
-        dijkstra = new DijkstraMap();
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case OCTAHEDRON:
-            case DIAMOND:
-                dijkstra.measurement = DijkstraMap.Measurement.MANHATTAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                dijkstra.measurement = DijkstraMap.Measurement.CHEBYSHEV;
-                break;
-            default:
-                dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-                break;
-        }
-        this.origin = origin;
-        this.end = end;
-        this.radius = radius;
-        los = new LOS(LOS.DDA);
-    }
-    public LineAOE(Coord origin, Coord end, int radius, Radius radiusType, int minRange, int maxRange)
-    {
-        dijkstra = new DijkstraMap();
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case OCTAHEDRON:
-            case DIAMOND:
-                dijkstra.measurement = DijkstraMap.Measurement.MANHATTAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                dijkstra.measurement = DijkstraMap.Measurement.CHEBYSHEV;
-                break;
-            default:
-                dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-                break;
-        }
-        this.origin = origin;
-        this.end = end;
-        this.radius = radius;
-        reach.minDistance = minRange;
-        reach.maxDistance = maxRange;
-        los = new LOS(LOS.DDA);
-    }
-    private double[][] initDijkstra()
-    {
-        los.isReachable(dungeon, origin.x, origin.y, end.x, end.y, rt);
-        Queue<Coord> lit = los.getLastPath();
-
-        dijkstra.initialize(dungeon);
-        for(Coord p : lit)
-        {
-            dijkstra.setGoal(p);
-        }
-        if(radius == 0)
-            return dijkstra.gradientMap;
-        return dijkstra.partialScan(radius, null);
-    }
-
-    @Override
-    public Coord getOrigin() {
-        return origin;
-    }
-
-    @Override
-    public void setOrigin(Coord origin) {
-        this.origin = origin;
-        dijkstra.resetMap();
-        dijkstra.clearGoals();
-    }
-
-    @Override
-    public AimLimit getLimitType() {
-        return reach.limit;
-    }
-
-    @Override
-    public int getMinRange() {
-        return reach.minDistance;
-    }
-
-    @Override
-    public int getMaxRange() {
-        return reach.maxDistance;
-    }
-
-    @Override
-    public Radius getMetric() {
-        return reach.metric;
-    }
-
-    /**
-     * Gets the same values returned by getLimitType(), getMinRange(), getMaxRange(), and getMetric() bundled into one
-     * Reach object.
-     *
-     * @return a non-null Reach object.
-     */
-    @Override
-    public Reach getReach() {
-        return reach;
-    }
-
-    @Override
-    public void setLimitType(AimLimit limitType) {
-        reach.limit = limitType;
-
-    }
-
-    @Override
-    public void setMinRange(int minRange) {
-        reach.minDistance = minRange;
-    }
-
-    @Override
-    public void setMaxRange(int maxRange) {
-        reach.maxDistance = maxRange;
-
-    }
-
-    @Override
-    public void setMetric(Radius metric) {
-        reach.metric = metric;
-    }
-
-    /**
-     * Sets the same values as setLimitType(), setMinRange(), setMaxRange(), and setMetric() using one Reach object.
-     *
-     * @param reach a non-null Reach object.
-     */
-    @Override
-    public void setReach(Reach reach) {
-        if(reach != null)
-            this.reach = reach;
-    }
-
-
-    public Coord getEnd() {
-        return end;
-    }
-
-    public void setEnd(Coord end) {
-        if (dungeon != null && end.isWithin(dungeon.length, dungeon[0].length) &&
-                AreaUtils.verifyReach(reach, origin, end)) {
-            this.end = end;
-            dijkstra.resetMap();
-            dijkstra.clearGoals();
-        }
-    }
-
-    public int getRadius() {
-        return radius;
-    }
-
-    public void setRadius(int radius) {
-        this.radius = radius;
-    }
-
-    public Radius getRadiusType()
-    {
-        return rt;
-    }
-    public void setRadiusType(Radius radiusType)
-    {
-        rt = radiusType;
-        switch (radiusType)
-        {
-            case OCTAHEDRON:
-            case DIAMOND:
-                dijkstra.measurement = DijkstraMap.Measurement.MANHATTAN;
-                break;
-            case CUBE:
-            case SQUARE:
-                dijkstra.measurement = DijkstraMap.Measurement.CHEBYSHEV;
-                break;
-            default:
-                dijkstra.measurement = DijkstraMap.Measurement.EUCLIDEAN;
-                break;
-        }
-    }
-
-    @Override
-    public void shift(Coord aim) {
-        setEnd(aim);
-    }
-
-    @Override
-    public boolean mayContainTarget(Set<Coord> targets) {
-        for (Coord p : targets)
-        {
-            if(rt.radius(origin.x, origin.y, p.x, p.y) + rt.radius(end.x, end.y, p.x, p.y) -
-                    rt.radius(origin.x, origin.y, end.x, end.y) <= 3.0 + radius)
-                return true;
-        }
-        return false;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        if(targets == null)
-            return new OrderedMap<>();
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = targets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        Coord[] ts = targets.toArray(new Coord[targets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[ts.length][dungeon.length][dungeon[0].length];
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-        }
-        DijkstraMap dt = new DijkstraMap(dungeon, dijkstra.measurement);
-        double[][] resMap = DungeonUtility.generateResistances(dungeon);
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = exs[i];
-            dt.resetMap();
-            dt.clearGoals();
-
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (dt.gradientMap[x][y] < DijkstraMap.FLOOR || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = ts[0];
-
-        for (int i = 0; i < ts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dijkstra.measurement);
-
-            t = ts[i];
-            dt.resetMap();
-            dt.clearGoals();
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (dt.gradientMap[x][y] < DijkstraMap.FLOOR){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][ts[i].x][ts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-        double bestQuality = 99999 * ts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long bits = 0;
-                for (int i = 0; i < ts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        bits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < ts.length && i < 63; ++i) {
-                        if((bits & (1 << i)) != 0)
-                            ap.add(ts[i]);
-                    }
-
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> priorityTargets, Set<Coord> lesserTargets, Set<Coord> requiredExclusions) {
-        if(priorityTargets == null)
-            return idealLocations(lesserTargets, requiredExclusions);
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        //requiredExclusions.remove(origin);
-        int totalTargets = priorityTargets.size() + lesserTargets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        Coord[] pts = priorityTargets.toArray(new Coord[priorityTargets.size()]);
-        Coord[] lts = lesserTargets.toArray(new Coord[lesserTargets.size()]);
-        Coord[] exs = requiredExclusions.toArray(new Coord[requiredExclusions.size()]);
-        Coord t = exs[0];
-
-        double[][][] compositeMap = new double[totalTargets][dungeon.length][dungeon[0].length];
-
-        char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length],
-                dungeonPriorities = new char[dungeon.length][dungeon[0].length];
-        for (int i = 0; i < dungeon.length; i++) {
-            System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length);
-            Arrays.fill(dungeonPriorities[i], '#');
-        }
-        DijkstraMap dt = new DijkstraMap(dungeon, dijkstra.measurement);
-        double[][] resMap = DungeonUtility.generateResistances(dungeon);
-        Coord tempPt = Coord.get(0, 0);
-        for (int i = 0; i < exs.length; ++i) {
-            t = exs[i];
-            dt.resetMap();
-            dt.clearGoals();
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    tempPt = Coord.get(x, y);
-                    dungeonCopy[x][y] = (dt.gradientMap[x][y] < DijkstraMap.FLOOR || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y];
-                }
-            }
-        }
-
-        t = pts[0];
-
-        for (int i = 0; i < pts.length; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dijkstra.measurement);
-            t = pts[i];
-            dt.resetMap();
-            dt.clearGoals();
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (dt.gradientMap[x][y] < DijkstraMap.FLOOR){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius) {
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                            dungeonPriorities[x][y] = dungeon[x][y];
-                        }
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][pts[i].x][pts[i].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++) {
-                    Arrays.fill(compositeMap[i][x], 399999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 399999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-
-        t = lts[0];
-
-        for (int i = pts.length; i < totalTargets; ++i) {
-            DijkstraMap dm = new DijkstraMap(dungeon, dijkstra.measurement);
-            t = lts[i - pts.length];
-            dt.resetMap();
-            dt.clearGoals();
-            los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt);
-            Queue<Coord> lit = los.getLastPath();
-
-            for(Coord p : lit)
-            {
-                dt.setGoal(p);
-            }
-            if(radius > 0)
-                dt.partialScan(radius, null);
-
-            double dist = 0.0;
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    if (dt.gradientMap[x][y] < DijkstraMap.FLOOR){
-                        dist = reach.metric.radius(origin.x, origin.y, x, y);
-                        if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius)
-                            compositeMap[i][x][y] = dm.physicalMap[x][y];
-                        else
-                            compositeMap[i][x][y] = DijkstraMap.WALL;
-                    }
-                    else compositeMap[i][x][y] = DijkstraMap.WALL;
-                }
-            }
-            if(compositeMap[i][lts[i - pts.length].x][lts[i - pts.length].y] > DijkstraMap.FLOOR)
-            {
-                for (int x = 0; x < dungeon.length; x++)
-                {
-                    Arrays.fill(compositeMap[i][x], 99999.0);
-                }
-                continue;
-            }
-
-
-            dm.initialize(compositeMap[i]);
-            dm.setGoal(t);
-            dm.scan(null);
-            for (int x = 0; x < dungeon.length; x++) {
-                for (int y = 0; y < dungeon[x].length; y++) {
-                    compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR  && dungeonCopy[x][y] != '!' && dungeonPriorities[x][y] != '#') ? dm.gradientMap[x][y] : 99999.0;
-                }
-            }
-            dm.resetMap();
-            dm.clearGoals();
-        }
-        double bestQuality = 99999 * lts.length + 399999 * pts.length;
-        double[][] qualityMap = new double[dungeon.length][dungeon[0].length];
-        for (int x = 0; x < qualityMap.length; x++) {
-            for (int y = 0; y < qualityMap[x].length; y++) {
-                qualityMap[x][y] = 0.0;
-                long pbits = 0, lbits = 0;
-                for (int i = 0; i < pts.length; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 399999.0 && i < 63)
-                        pbits |= 1 << i;
-                }
-                for (int i = pts.length; i < totalTargets; ++i) {
-                    qualityMap[x][y] += compositeMap[i][x][y];
-                    if(compositeMap[i][x][y] < 99999.0 && i < 63)
-                        lbits |= 1 << i;
-                }
-                if(qualityMap[x][y] < bestQuality)
-                {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if((pbits & (1 << i)) != 0)
-                            ap.add(pts[i]);
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-
-                    if(ap.size() > 0) {
-                        bestQuality = qualityMap[x][y];
-                        bestPoints.clear();
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-                else if(qualityMap[x][y] == bestQuality) {
-                    ArrayList<Coord> ap = new ArrayList<>();
-
-                    for (int i = 0; i < pts.length && i < 63; ++i) {
-                        if ((pbits & (1 << i)) != 0) {
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                            ap.add(pts[i]);
-                        }
-                    }
-                    for (int i = pts.length; i < totalTargets && i < 63; ++i) {
-                        if ((lbits & (1 << i)) != 0)
-                            ap.add(lts[i - pts.length]);
-                    }
-
-                    if (ap.size() > 0) {
-                        bestPoints.put(Coord.get(x, y), ap);
-                    }
-                }
-            }
-        }
-
-        return bestPoints;
-    }
-
-/*
-    @Override
-    public ArrayList<ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        int totalTargets = targets.size() + 1;
-        int volume = (int)(rt.radius(1, 1, dungeon.length - 2, dungeon[0].length - 2) * radius * 2.1);
-        ArrayList<ArrayList<Coord>> locs = new ArrayList<ArrayList<Coord>>(totalTargets);
-        for(int i = 0; i < totalTargets; i++)
-        {
-            locs.add(new ArrayList<Coord>(volume));
-        }
-        if(totalTargets == 1)
-            return locs;
-
-        int ctr = 0;
-
-        boolean[][] tested = new boolean[dungeon.length][dungeon[0].length];
-        for (int x = 1; x < dungeon.length - 1; x += radius) {
-            for (int y = 1; y < dungeon[x].length - 1; y += radius) {
-
-                if(mayContainTarget(requiredExclusions, x, y))
-                    continue;
-                ctr = 0;
-                for(Coord tgt : targets)
-                {
-                    if(rt.radius(origin.x, origin.y, tgt.x, tgt.y) + rt.radius(end.x, end.y, tgt.x, tgt.y) -
-                        rt.radius(origin.x, origin.y, end.x, end.y) <= 3.0 + radius)
-                        ctr++;
-                }
-                if(ctr > 0)
-                    locs.get(totalTargets - ctr).add(Coord.get(x, y));
-            }
-        }
-        Coord it;
-        for(int t = 0; t < totalTargets - 1; t++)
-        {
-            if(locs.get(t).size() > 0) {
-                int numPoints = locs.get(t).size();
-                for (int i = 0; i < numPoints; i++) {
-                    it = locs.get(t).get(i);
-                    for (int x = Math.max(1, it.x - radius / 2); x < it.x + (radius + 1) / 2 && x < dungeon.length - 1; x++) {
-                        for (int y = Math.max(1, it.y - radius / 2); y <= it.y + (radius - 1) / 2 && y < dungeon[0].length - 1; y++)
-                        {
-                            if(tested[x][y])
-                                continue;
-                            tested[x][y] = true;
-
-                            if(mayContainTarget(requiredExclusions, x, y))
-                                continue;
-
-                            ctr = 0;
-                            for(Coord tgt : targets)
-                            {
-                                if(rt.radius(origin.x, origin.y, tgt.x, tgt.y) + rt.radius(end.x, end.y, tgt.x, tgt.y) -
-                                        rt.radius(origin.x, origin.y, end.x, end.y) <= 3.0 + radius)
-                                    ctr++;
-                            }
-                            if(ctr > 0)
-                                locs.get(totalTargets - ctr).add(Coord.get(x, y));
-                        }
-                    }
-                }
-            }
-        }
-        return locs;
-    }
-*/
-    @Override
-    public void setMap(char[][] map) {
-        dungeon = map;
-        dijkstra.resetMap();
-        dijkstra.clearGoals();
-    }
-
-    @Override
-    public OrderedMap<Coord, Double> findArea() {
-        double[][] dmap = initDijkstra();
-        dmap[origin.x][origin.y] = DijkstraMap.DARK;
-        dijkstra.resetMap();
-        dijkstra.clearGoals();
-        return AreaUtils.dijkstraToHashMap(dmap);
-    }
-
-    /**
-     * If you use FOVCache to pre-compute FOV maps for a level, you can share the speedup from using the cache with
-     * some AOE implementations that rely on FOV. Not all implementations need to actually make use of the cache, but
-     * those that use FOV for calculations should benefit. The cache parameter this receives should have completed its
-     * calculations, which can be confirmed by calling awaitCache(). Ideally, the FOVCache will have done its initial
-     * calculations in another thread while the previous level or menu was being displayed, and awaitCache() will only
-     * be a formality.
-     *
-     * @param cache The FOVCache for the current level; can be null to stop using the cache
-     */
-    @GwtIncompatible
-    @Override
-    public void setCache(FOVCache cache) {
-
-    }
-}

+ 0 - 322
squidlib-util/src/main/java/squidpony/squidai/PointAOE.java

@@ -1,322 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.annotation.GwtIncompatible;
-import squidpony.squidgrid.FOVCache;
-import squidpony.squidgrid.Radius;
-import squidpony.squidmath.Coord;
-
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.OrderedSet;
-
-import java.util.ArrayList;
-import java.util.Set;
-
-/**
- * An AOE type that has a center Coord only and only affects that single Coord. Useful if you need an AOE implementation
- * for something that does not actually affect an area.
- * This will produce doubles for its findArea() method which are equal to 1.0.
- *
- * This class doesn't use any other SquidLib class to create its area of effect.
- * Created by Tommy Ettinger on 7/13/2015.
- */
-public class PointAOE implements AOE {
-    private Coord center, origin = null;
-    private int mapWidth, mapHeight;
-    private Reach reach = new Reach(1, 1, Radius.SQUARE, null);
-
-    public PointAOE(Coord center)
-    {
-        this.center = center;
-    }
-    public PointAOE(Coord center, int minRange, int maxRange)
-    {
-        this.center = center;
-        reach.minDistance = minRange;
-        reach.maxDistance = maxRange;
-    }
-
-    public Coord getCenter() {
-        return center;
-    }
-
-
-    public void setCenter(Coord center) {
-
-        if (center.isWithin(mapWidth, mapHeight) &&
-                AreaUtils.verifyReach(reach, origin, center))
-        {
-            this.center = center;
-        }
-    }
-
-    @Override
-    public void shift(Coord aim) {
-        setCenter(aim);
-    }
-
-    @Override
-    public boolean mayContainTarget(Set<Coord> targets) {
-        for (Coord p : targets)
-        {
-            if(center.x == p.x && center.y == p.y)
-                return true;
-        }
-        return false;
-    }
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        if(targets == null)
-            return new OrderedMap<>();
-
-        int totalTargets = targets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-
-        double dist = 0.0;
-        for(Coord p : targets) {
-            if (AreaUtils.verifyReach(reach, origin, p)) {
-
-                dist = reach.metric.radius(origin.x, origin.y, p.x, p.y);
-                if (dist <= reach.maxDistance && dist >= reach.minDistance) {
-                    ArrayList<Coord> ap = new ArrayList<>();
-                    ap.add(p);
-                    bestPoints.put(p, ap);
-                }
-            }
-        }
-        return bestPoints;
-    }
-
-
-    @Override
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Set<Coord> priorityTargets, Set<Coord> lesserTargets, Set<Coord> requiredExclusions) {
-        if(priorityTargets == null)
-            return idealLocations(lesserTargets, requiredExclusions);
-        if(requiredExclusions == null) requiredExclusions = new OrderedSet<>();
-
-        int totalTargets = priorityTargets.size() + lesserTargets.size();
-        OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 4);
-
-        if(totalTargets == 0)
-            return bestPoints;
-
-        double dist = 0.0;
-
-        for(Coord p : priorityTargets) {
-            if (AreaUtils.verifyReach(reach, origin, p)) {
-
-                dist = reach.metric.radius(origin.x, origin.y, p.x, p.y);
-                if (dist <= reach.maxDistance && dist >= reach.minDistance) {
-                    ArrayList<Coord> ap = new ArrayList<>();
-                    ap.add(p);
-                    ap.add(p);
-                    ap.add(p);
-                    ap.add(p);
-                    bestPoints.put(p, ap);
-                }
-            }
-        }
-        if(bestPoints.isEmpty()) {
-            for (Coord p : lesserTargets) {
-                if (AreaUtils.verifyReach(reach, origin, p)) {
-
-                    dist = reach.metric.radius(origin.x, origin.y, p.x, p.y);
-                    if (dist <= reach.maxDistance && dist >= reach.minDistance) {
-                        ArrayList<Coord> ap = new ArrayList<>();
-                        ap.add(p);
-                        bestPoints.put(p, ap);
-                    }
-                }
-            }
-        }
-        return bestPoints;
-
-    }
-
-    /*
-    @Override
-    public ArrayList<ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) {
-        int totalTargets = targets.size() + 1;
-        int maxEffect = (int)radiusType.volume2D(radius);
-        ArrayList<ArrayList<Coord>> locs = new ArrayList<ArrayList<Coord>>(totalTargets);
-
-        for(int i = 0; i < totalTargets; i++)
-        {
-            locs.add(new ArrayList<Coord>(maxEffect));
-        }
-        if(totalTargets == 1)
-            return locs;
-
-        int ctr = 0;
-        if(radius < 1)
-        {
-            locs.get(totalTargets - 2).addAll(targets);
-            return locs;
-        }
-
-        boolean[][] tested = new boolean[dungeon.length][dungeon[0].length];
-        for (int x = 1; x < dungeon.length - 1; x += radius) {
-            BY_POINT:
-            for (int y = 1; y < dungeon[x].length - 1; y += radius) {
-                for(Coord ex : requiredExclusions)
-                {
-                    if(radiusType.radius(x, y, ex.x, ex.y) <= radius)
-                        continue BY_POINT;
-                }
-                ctr = 0;
-                for(Coord tgt : targets)
-                {
-                    if(radiusType.radius(x, y, tgt.x, tgt.y) <= radius)
-                        ctr++;
-                }
-                if(ctr > 0)
-                    locs.get(totalTargets - ctr).add(Coord.get(x, y));
-            }
-        }
-        Coord it;
-        for(int t = 0; t < totalTargets - 1; t++)
-        {
-            if(locs.get(t).size() > 0) {
-                int numPoints = locs.get(t).size();
-                for (int i = 0; i < numPoints; i++) {
-                    it = locs.get(t).get(i);
-                    for (int x = Math.max(1, it.x - radius / 2); x < it.x + (radius + 1) / 2 && x < dungeon.length - 1; x++) {
-                        BY_POINT:
-                        for (int y = Math.max(1, it.y - radius / 2); y <= it.y + (radius - 1) / 2 && y < dungeon[0].length - 1; y++)
-                        {
-                            if(tested[x][y])
-                                continue;
-                            tested[x][y] = true;
-
-                            for(Coord ex : requiredExclusions)
-                            {
-                                if(radiusType.radius(x, y, ex.x, ex.y) <= radius)
-                                    continue BY_POINT;
-                            }
-
-                            ctr = 0;
-                            for(Coord tgt : targets)
-                            {
-                                if(radiusType.radius(x, y, tgt.x, tgt.y) <= radius)
-                                    ctr++;
-                            }
-                            if(ctr > 0)
-                                locs.get(totalTargets - ctr).add(Coord.get(x, y));
-                        }
-                    }
-                }
-            }
-        }
-        return locs;
-    }
-*/
-    @Override
-    public void setMap(char[][] map) {
-        if (map != null && map.length > 0) {
-            mapWidth = map.length;
-            mapHeight = map[0].length;
-        }
-    }
-
-    @Override
-    public OrderedMap<Coord, Double> findArea() {
-        OrderedMap<Coord, Double> ret = new OrderedMap<>(1);
-        ret.put(Coord.get(center.x, center.y), 1.0);
-        return ret;
-    }
-
-
-    @Override
-    public Coord getOrigin() {
-        return origin;
-    }
-
-    @Override
-    public void setOrigin(Coord origin) {
-        this.origin = origin;
-
-    }
-
-    @Override
-    public AimLimit getLimitType() {
-        return reach.limit;
-    }
-
-    @Override
-    public int getMinRange() {
-        return reach.minDistance;
-    }
-
-    @Override
-    public int getMaxRange() {
-        return reach.maxDistance;
-    }
-
-    @Override
-    public Radius getMetric() {
-        return reach.metric;
-    }
-
-    /**
-     * Gets the same values returned by getLimitType(), getMinRange(), getMaxRange(), and getMetric() bundled into one
-     * Reach object.
-     *
-     * @return a non-null Reach object.
-     */
-    @Override
-    public Reach getReach() {
-        return reach;
-    }
-
-    @Override
-    public void setLimitType(AimLimit limitType) {
-        reach.limit = limitType;
-
-    }
-
-    @Override
-    public void setMinRange(int minRange) {
-        reach.minDistance = minRange;
-    }
-
-    @Override
-    public void setMaxRange(int maxRange) {
-        reach.maxDistance = maxRange;
-
-    }
-
-    @Override
-    public void setMetric(Radius metric) {
-        reach.metric = metric;
-    }
-
-    /**
-     * Sets the same values as setLimitType(), setMinRange(), setMaxRange(), and setMetric() using one Reach object.
-     *
-     * @param reach a non-null Reach object.
-     */
-    @Override
-    public void setReach(Reach reach) {
-
-    }
-
-    /**
-     * If you use FOVCache to pre-compute FOV maps for a level, you can share the speedup from using the cache with
-     * some AOE implementations that rely on FOV. Not all implementations need to actually make use of the cache, but
-     * those that use FOV for calculations should benefit. The cache parameter this receives should have completed its
-     * calculations, which can be confirmed by calling awaitCache(). Ideally, the FOVCache will have done its initial
-     * calculations in another thread while the previous level or menu was being displayed, and awaitCache() will only
-     * be a formality.
-     *
-     * @param cache The FOVCache for the current level; can be null to stop using the cache
-     */
-    @GwtIncompatible
-    @Override
-    public void setCache(FOVCache cache) {
-
-    }
-}

+ 0 - 182
squidlib-util/src/main/java/squidpony/squidai/Technique.java

@@ -1,182 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.OrderedMap;
-
-import java.util.ArrayList;
-import java.util.Set;
-
-/**
- * A simple struct-like class that stores various public fields which describe the targeting properties of a skill,
- * spell, tech, or any other game-specific term for a targeted (typically offensive) ability we call a Technique.
- *
- * The typical usage of a Technique is:
- * <ul>
- * <li>Construct any AOE implementation the Technique would use (if the Technique affects multiple grid cells).</li>
- * <li>Construct the Technique (passing the AOE as a parameter if needed).</li>
- * <li>Call setMap() before considering the Technique if it has not been called yet, if the physical map (including
- * doors and destructible objects) has changed since setMap() was last called, or simply on every Technique every time
- * the map changes if there are few enemies with few Techniques. PERFORMING ANY SUBSEQUENT STEPS WITHOUT SETTING THE
- * MAP TO THE CURRENT ACTUAL PHYSICAL MAP WILL HAVE BAD CONSEQUENCES FOR LOGIC AND MAY CAUSE CRASHING BUGS DUE TO
- * ARRAY BOUNDS VIOLATIONS IF YOU HAVEN'T SET THE MAP ARRAY IN THE FIRST PLACE. The map should be bounded by wall chars
- * ('#'), which is done automatically by squidpony.squidgrid.mapping.DungeonGenerator .</li>
- * <li>When the Technique is being considered by an AI, call idealLocations() with the values of targets,
- * lesserTargets, and/or priorityTargets set to beings that the AI can see (likely using FOV) and wants to affect with
- * this Technique (enemies for offensive Techniques, allies for supporting ones), and requiredExclusions typically set
- * to allies for offensive Techniques that can cause friendly-fire damage, or to null for supporting ones or Techniques
- * that don't affect allies.</li>
- * <li>When an ideal location has been determined from the previous step, and the AI decides (possibly randomly, by an
- * aggression ("aggro") level tracked per-enemy, or by weights on Techniques for different situations) to use this
- * Technique on a specific target point, call apply() with the user position as a Coord and the chosen Coord, and
- * proceed to process the effects of the Technique as fitting for your game on the returned Map of Coord keys to Double
- * values that describe the amount of effect (from 0.0 for none to 1.0 for full) that Coord receives.</li>
- * </ul>
- *
- * A Technique always has an AOE implementation that it uses to determine which cells it actually affects, and
- * Techniques that do not actually affect an area use the default single-cell "Area of Effect" implementation, PointAOE.
- * You typically will need to construct the implementing class of the AOE interface in a different way for each
- * implementation; BeamAOE, LineAOE, and ConeAOE depend on the user's position, BurstAOE and BlastAOE treat radii
- * differently from BeamAOE and LineAOE, and CloudAOE has a random component that can be given a seed.
- *
- * A Technique has a String  name, which typically should be in a form that can be presented to a user, and a
- * String id, which defaults to the same value as name but can be given some value not meant for users that records
- * any additional identifying characteristics the game needs for things like comparisons.
- *
- * Created by Tommy Ettinger on 7/27/2015.
- */
-public class Technique {
-    public String name;
-    public String id;
-    public AOE aoe;
-    protected char[][] dungeon;
-    protected static final Coord DEFAULT_POINT = Coord.get(0, 0);
-
-    /**
-     * Creates a Technique that can target any adjacent single Coord, using
-     * Chebyshev (8-way square) distance.
-     */
-    public Technique() {
-        name = "Default Technique";
-        id = name;
-        aoe = new PointAOE(DEFAULT_POINT);
-    }
-
-    /**
-     * Creates a Technique that can target any adjacent single Coord,
-     * using Chebyshev (8-way square) distance.
-     * @param name An identifier that may be displayed to the user. Also used for id.
-     */
-    public Technique(String name) {
-        this.name = name;
-        id = name;
-        aoe = new PointAOE(DEFAULT_POINT);
-    }
-
-    /**
-     * Creates a Technique that can target a Coord at a range specified by the given AOE's minRange and maxRange,
-     * using a distance metric from the AOE, and use that target Coord for the given AOE.
-     * @param name An identifier that may be displayed to the user. Also used for id.
-     * @param aoe An implementation of the AOE interface; typically needs construction beforehand.
-     */
-    public Technique(String name, AOE aoe) {
-        this.name = name;
-        id = name;
-        this.aoe = aoe;
-    }
-
-
-    /**
-     * Creates a Technique that can target a Coord at a range specified by the given AOE's minRange and maxRange,
-     * using a distance metric from the AOE, and use that target Coord for the given AOE. Takes an id parameter.
-     * @param name An identifier that may be displayed to the user.
-     * @param id An identifier that should always be internal, and will probably never be shown to the user.
-     * @param aoe An implementation of the AOE interface; typically needs construction beforehand.
-     */
-    public Technique(String name, String id, AOE aoe) {
-        this.name = name;
-        this.id = id;
-        this.aoe = aoe;
-    }
-
-
-    /**
-     * VITAL: Call this method before any calls to idealLocations() or apply(), and call it again if the map changes.
-     *
-     * This simple method sets the map that this Technique can find targets in to a given char 2D array with '#' for
-     * walls and any other character (including characters for open and closed doors) treated as a floor for most
-     * purposes (certain AOE implementations may treat open and closed doors differently, specifically any that use
-     * FOV internally and can yield values other than 1.0 from their findArea() method, like BlastAOE and ConeAOE).
-     * @param map A char 2D array like one generated by squidpony.squidgrid.mapping.DungeonGenerator, with '#' for walls and bounded edges.
-     */
-    public void setMap(char[][] map)
-    {
-        dungeon = map;
-        aoe.setMap(map);
-    }
-
-    /**
-     * Get a mapping of Coord keys representing locations to apply this Technique to, to ArrayList of Coord values
-     * representing which targets (by their location) are effected by choosing that Coord. All targets with this method
-     * are valued equally, and the ideal location affects as many as possible without hitting any requiredExclusions.
-     *
-     * YOU MUST CALL setMap() with the current map status at some point before using this method, and call it again if
-     * the map changes. Failure to do so can cause serious bugs, from logic errors where monsters consider a door
-     * closed when it is open or vice versa, to an ArrayIndexOutOfBoundsException being thrown if the player moved to a
-     * differently-sized map and the Technique tries to use the previous map with coordinates from the new one.
-     *
-     * @param user The location of the user of this Technique
-     * @param targets Set of Coord of desirable targets to include in the area of this Technique, as many as possible.
-     * @param requiredExclusions Set of Coord where each value is something this Technique will really try to avoid.
-     * @return OrderedMap of Coord keys representing target points to pass to apply, to ArrayList of Coord values representing what targets' locations will be affected.
-     */
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Coord user, Set<Coord> targets, Set<Coord> requiredExclusions) {
-        aoe.setOrigin(user);
-        return aoe.idealLocations(targets, requiredExclusions);
-
-    }
-
-    /**
-     * Get a mapping of Coord keys representing locations to apply this Technique to, to ArrayList of Coord values
-     * representing which targets (by their location) are effected by choosing that Coord. This method will strongly
-     * prefer including priorityTargets in its area, especially multiple one if possible, and primarily uses
-     * lesserTargets as a tiebreaker if two locations have the same number of included priorityTargets but one has more
-     * lesserTargets in its area.
-     *
-     * YOU MUST CALL setMap() with the current map status at some point before using this method, and call it again if
-     * the map changes. Failure to do so can cause serious bugs, from logic errors where monsters consider a door
-     * closed when it is open or vice versa, to an ArrayIndexOutOfBoundsException being thrown if the player moved to a
-     * differently-sized map and the Technique tries to use the previous map with coordinates from the new one.
-     *
-     * @param user The location of the user of this Technique
-     * @param priorityTargets Set of Coord of important targets to include in the area of this Technique, preferring to target a single priorityTarget over four lesserTargets.
-     * @param lesserTargets Set of Coord of desirable targets to include in the area of this Technique, as many as possible without excluding priorityTargets.
-     * @param requiredExclusions Set of Coord where each value is something this Technique will really try to avoid.
-     * @return OrderedMap of Coord keys representing target points to pass to apply, to ArrayList of Coord values representing what targets' locations will be affected.
-     */
-    public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Coord user, Set<Coord> priorityTargets, Set<Coord> lesserTargets, Set<Coord> requiredExclusions) {
-        aoe.setOrigin(user);
-        return aoe.idealLocations(priorityTargets, lesserTargets, requiredExclusions);
-    }
-
-    /**
-     * This does one last validation of the location aimAt (checking that it is within the valid range for this
-     * Technique) before getting the area affected by the AOE targeting that cell. It considers the origin of the AOE
-     * to be the Coord parameter user, for purposes of directional limitations and for AOE implementations that need
-     * the user's location, such as ConeAOE and LineAOE.
-     *
-     * YOU MUST CALL setMap() with the current map status at some point before using this method, and call it again if
-     * the map changes. Failure to do so can cause serious bugs, from logic errors where monsters consider a door
-     * closed when it is open or vice versa, to an ArrayIndexOutOfBoundsException being thrown if the player moved to a
-     * differently-sized map and the Technique tries to use the previous map with coordinates from the new one.
-     *
-     * @param user The position of the Technique's user, x first, y second.
-     * @param aimAt A target Coord typically obtained from idealLocations that determines how to position the AOE.
-     * @return a HashMap of Coord keys to Double values from 1.0 (fully affected) to 0.0 (unaffected).
-     */
-    public OrderedMap<Coord, Double> apply(Coord user, Coord aimAt)
-    {
-        aoe.setOrigin(user);
-        aoe.shift(aimAt);
-        return aoe.findArea();
-    }
-}

+ 0 - 32
squidlib-util/src/main/java/squidpony/squidai/Threat.java

@@ -1,32 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.squidgrid.Radius;
-import squidpony.squidmath.Coord;
-
-/**
- * A small class to store the area that a creature is perceived by other creatures to threaten.
- * Created by Tommy Ettinger on 11/8/2015.
- */
-public class Threat {
-
-    public Coord position;
-    public Reach reach;
-
-    public Threat(Coord position, int maxThreatDistance) {
-        this.position = position;
-        reach = new Reach(maxThreatDistance);
-    }
-
-    public Threat(Coord position, int minThreatDistance, int maxThreatDistance) {
-        this.position = position;
-        reach = new Reach(minThreatDistance, maxThreatDistance);
-    }
-    public Threat(Coord position, int minThreatDistance, int maxThreatDistance, Radius measurement) {
-        this.position = position;
-        reach = new Reach(minThreatDistance, maxThreatDistance, measurement);
-    }
-    public Threat(Coord position, int minThreatDistance, int maxThreatDistance, Radius measurement, AimLimit limits) {
-        this.position = position;
-        reach = new Reach(minThreatDistance, maxThreatDistance, measurement, limits);
-    }
-}

+ 0 - 553
squidlib-util/src/main/java/squidpony/squidai/WaypointPathfinder.java

@@ -1,553 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.squidgrid.Direction;
-import squidpony.squidgrid.Radius;
-import squidpony.squidgrid.mapping.DungeonUtility;
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.PoissonDisk;
-import squidpony.squidmath.RNG;
-import squidpony.squidmath.StatefulRNG;
-
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.OrderedSet;
-
-import java.util.*;
-
-import static squidpony.squidmath.CoordPacker.*;
-
-/**
- * Pathfind to known connections between rooms or other "chokepoints" without needing full-map Dijkstra scans.
- * Pre-calculates a path either from or to any given chokepoint to each other chokepoint.
- * Created by Tommy Ettinger on 10/25/2015.
- */
-public class WaypointPathfinder {
-    private int width;
-    private int height;
-    private DijkstraMap dm;
-    private char[][] map;
-    private int[][] expansionMap;
-    public RNG rng;
-    private OrderedMap<Coord, OrderedMap<Coord, Edge>> waypoints;
-
-    /**
-     * Calculates and stores the doors and doors-like connections ("chokepoints") on the given map as waypoints.
-     * Will use the given Radius enum to determine how to handle DijkstraMap measurement in future pathfinding.
-     * Uses rng for all random choices, or a new unseeded RNG if the parameter is null.
-     * @param map a char[][] that stores a "complete" dungeon map, with any chars as features that pathfinding needs.
-     * @param measurement a Radius that should correspond to how you want path distance calculated.
-     * @param rng an RNG object or null (which will make this use a new RNG); will be used for all random choices
-     */
-    public WaypointPathfinder(char[][] map, Radius measurement, RNG rng)
-    {
-        if(rng == null)
-            this.rng = new StatefulRNG();
-        else
-            this.rng = rng;
-        this.map = map;
-        width = map.length;
-        height = map[0].length;
-        char[][] simplified = DungeonUtility.simplifyDungeon(map);
-        ArrayList<Coord> centers = PoissonDisk.sampleMap(simplified,
-                Math.min(width, height) * 0.4f, this.rng, '#');
-        int centerCount = centers.size();
-        expansionMap = new int[width][height];
-        waypoints = new OrderedMap<>(64);
-        dm = new DijkstraMap(simplified, DijkstraMap.Measurement.MANHATTAN);
-
-        for (Coord center : centers) {
-            dm.clearGoals();
-            dm.resetMap();
-            dm.setGoal(center);
-            dm.scan(null);
-            double current;
-            for (int i = 0; i < width; i++) {
-                for (int j = 0; j < height; j++) {
-                    current = dm.gradientMap[i][j];
-                    if (current >= DijkstraMap.FLOOR)
-                        continue;
-                    if (center.x == i && center.y == j)
-                        expansionMap[i][j]++;
-                    for (Direction dir : Direction.CARDINALS) {
-                        if (dm.gradientMap[i + dir.deltaX][j + dir.deltaY] == current + 1 ||
-                                dm.gradientMap[i + dir.deltaX][j + dir.deltaY] == current - 1)
-                            expansionMap[i][j]++;
-                    }
-                }
-            }
-        }
-
-        for (int i = 0; i < width; i++) {
-            for (int j = 0; j < height; j++) {
-                expansionMap[i][j] /= centerCount;
-            }
-        }
-
-        OrderedSet<Coord> chokes = new OrderedSet<>(128);
-        for (int i = 0; i < width; i++) {
-            ELEMENT_WISE:
-            for (int j = 0; j < height; j++) {
-                if(expansionMap[i][j] <= 0)
-                    continue;
-                int current = expansionMap[i][j];
-                boolean good = false;
-                for(Direction dir : Direction.CARDINALS) {
-                    if (chokes.contains(Coord.get(i + dir.deltaX, j + dir.deltaY)))
-                        continue ELEMENT_WISE;
-                    if (expansionMap[i + dir.deltaX][j + dir.deltaY] > 0 && expansionMap[i + dir.deltaX][j + dir.deltaY] > current + 1 ||
-                            (expansionMap[i + dir.deltaX][j + dir.deltaY] > current && expansionMap[i][j] <= 2)) {
-                        if (expansionMap[i - dir.deltaX][j - dir.deltaY] > 0 && expansionMap[i - dir.deltaX][j - dir.deltaY] >= current) {
-                            good = true;
-                        }
-                    }
-                }
-
-                if(good) {
-                    Coord chk = Coord.get(i, j);
-                    chokes.add(chk);
-                    waypoints.put(chk, new OrderedMap<Coord, Edge>());
-                }
-            }
-        }
-
-        /*
-        for (int y = 0; y < height; y++) {
-            for (int x = 0; x < width; x++) {
-                if(expansionMap[x][y] <= 0)
-                    System.out.print('#');
-                else
-                    System.out.print((char)(expansionMap[x][y] + 64));
-            }
-            System.out.println();
-        }
-
-        for (int y = 0; y < height; y++) {
-            for (int x = 0; x < width; x++) {
-                if(expansionMap[x][y] <= 0)
-                    System.out.print('#');
-                else if(chokes.contains(Coord.get(x, y)))
-                    System.out.print('@');
-                else if(centers.contains(Coord.get(x, y)))
-                    System.out.print('*');
-                else
-                    System.out.print('.');
-            }
-            System.out.println();
-        }
-*/
-
-        dm = new DijkstraMap(map, DijkstraMap.findMeasurement(measurement));
-
-        int e = 0;
-        for(Map.Entry<Coord, OrderedMap<Coord, Edge>> n : waypoints.entrySet())
-        {
-            chokes.remove(n.getKey());
-            if(chokes.isEmpty())
-                break;
-            dm.clearGoals();
-            dm.resetMap();
-            dm.setGoal(n.getKey());
-            dm.scan(null);
-            for(Coord c : chokes)
-            {
-                n.getValue().put(c, new Edge(n.getKey(), c, dm.findPathPreScanned(c), dm.gradientMap[c.x][c.y]));
-            }
-        }
-
-    }
-    /**
-     * Calculates and stores the doors and doors-like connections ("chokepoints") on the given map as waypoints.
-     * Will use the given Radius enum to determine how to handle DijkstraMap measurement in future pathfinding.
-     * Uses rng for all random choices, or a new unseeded RNG if the parameter is null.
-     * @param map a char[][] that stores a "complete" dungeon map, with any chars as features that pathfinding needs.
-     * @param measurement a Radius that should correspond to how you want path distance calculated.
-     * @param rng an RNG object or null (which will make this use a new RNG); will be used for all random choices
-     * @param thickCorridors true if most chokepoints on the map are 2 cells wide instead of 1
-     */
-    public WaypointPathfinder(char[][] map, Radius measurement, RNG rng, boolean thickCorridors)
-    {
-        if(rng == null)
-            this.rng = new StatefulRNG();
-        else
-            this.rng = rng;
-        this.map = map;
-        width = map.length;
-        height = map[0].length;
-        char[][] simplified = DungeonUtility.simplifyDungeon(map);
-        expansionMap = new int[width][height];
-        waypoints = new OrderedMap<>(64);
-        OrderedSet<Coord> chokes = new OrderedSet<>(128);
-
-        if(thickCorridors)
-        {
-            short[] floors = pack(simplified, '.'),
-                    rooms = flood(floors, retract(floors, 1, 60, 60, true), 2, false),
-                    corridors = differencePacked(floors, rooms),
-                    doors = intersectPacked(rooms, fringe(corridors, 1, 60, 60, false));
-            Coord[] apart = apartPacked(doors, 1);
-            Collections.addAll(chokes, apart);
-            for (int i = 0; i < apart.length; i++) {
-                waypoints.put(apart[i], new OrderedMap<Coord, Edge>());
-            }
-        }
-        else {
-            ArrayList<Coord> centers = PoissonDisk.sampleMap(simplified,
-                    Math.min(width, height) * 0.4f, this.rng, '#');
-            int centerCount = centers.size();
-            dm = new DijkstraMap(simplified, DijkstraMap.Measurement.MANHATTAN);
-
-            for (Coord center : centers) {
-                dm.clearGoals();
-                dm.resetMap();
-                dm.setGoal(center);
-                dm.scan(null);
-                double current;
-                for (int i = 0; i < width; i++) {
-                    for (int j = 0; j < height; j++) {
-                        current = dm.gradientMap[i][j];
-                        if (current >= DijkstraMap.FLOOR)
-                            continue;
-                        if (center.x == i && center.y == j)
-                            expansionMap[i][j]++;
-                        for (Direction dir : Direction.CARDINALS) {
-                            if (dm.gradientMap[i + dir.deltaX][j + dir.deltaY] == current + 1 ||
-                                    dm.gradientMap[i + dir.deltaX][j + dir.deltaY] == current - 1)
-                                expansionMap[i][j]++;
-                        }
-                    }
-                }
-            }
-
-            for (int i = 0; i < width; i++) {
-                for (int j = 0; j < height; j++) {
-                    expansionMap[i][j] /= centerCount;
-                }
-            }
-
-            for (int i = 0; i < width; i++) {
-                ELEMENT_WISE:
-                for (int j = 0; j < height; j++) {
-                    if (expansionMap[i][j] <= 0)
-                        continue;
-                    int current = expansionMap[i][j];
-                    boolean good = false;
-                    for (Direction dir : Direction.CARDINALS) {
-                        if (chokes.contains(Coord.get(i + dir.deltaX, j + dir.deltaY)))
-                            continue ELEMENT_WISE;
-                        if (expansionMap[i + dir.deltaX][j + dir.deltaY] > 0 && expansionMap[i + dir.deltaX][j + dir.deltaY] > current + 1 ||
-                                (expansionMap[i + dir.deltaX][j + dir.deltaY] > current && expansionMap[i][j] <= 2)) {
-                            if (expansionMap[i - dir.deltaX][j - dir.deltaY] > 0 && expansionMap[i - dir.deltaX][j - dir.deltaY] >= current) {
-                                good = true;
-                            }
-                        }
-                    }
-
-                    if (good) {
-                        Coord chk = Coord.get(i, j);
-                        chokes.add(chk);
-                        waypoints.put(chk, new OrderedMap<Coord, Edge>());
-                    }
-                }
-            }
-        }
-
-        dm = new DijkstraMap(map, DijkstraMap.findMeasurement(measurement));
-
-        int e = 0;
-        for(Map.Entry<Coord, OrderedMap<Coord, Edge>> n : waypoints.entrySet())
-        {
-            chokes.remove(n.getKey());
-            if(chokes.isEmpty())
-                break;
-            dm.clearGoals();
-            dm.resetMap();
-            dm.setGoal(n.getKey());
-            dm.scan(null);
-            for(Coord c : chokes)
-            {
-                n.getValue().put(c, new Edge(n.getKey(), c, dm.findPathPreScanned(c), dm.gradientMap[c.x][c.y]));
-            }
-        }
-
-    }
-
-    /**
-     * Calculates and stores the specified fraction of walkable points from map as waypoints. Does not perform any
-     * analysis of chokepoints and acts as a more brute-force solution when maps may be unpredictable. The lack of an
-     * analysis step may mean this could have drastically less of a penalty to startup time than the other constructors,
-     * and with the right fraction parameter (29 seems ideal), may perform better as well. Will use the given Radius
-     * enum to determine how to handle DijkstraMap measurement in future pathfinding. Uses rng for all random choices,
-     * or a new unseeded RNG if the parameter is null.
-     * <br>
-     * Remember, a fraction value of 29 works well!
-     * @param map a char[][] that stores a "complete" dungeon map, with any chars as features that pathfinding needs.
-     * @param measurement a Radius that should correspond to how you want path distance calculated.
-     * @param rng an RNG object or null (which will make this use a new RNG); will be used for all random choices
-     * @param fraction the fractional denominator of passable cells to assign as waypoints; use 29 if you aren't sure
-     */
-    public WaypointPathfinder(char[][] map, Radius measurement, RNG rng, int fraction)
-    {
-        if(rng == null)
-            this.rng = new StatefulRNG();
-        else
-            this.rng = rng;
-        this.map = map;
-        width = map.length;
-        height = map[0].length;
-        char[][] simplified = DungeonUtility.simplifyDungeon(map);
-        expansionMap = new int[width][height];
-        waypoints = new OrderedMap<>(64);
-        OrderedSet<Coord> chokes = new OrderedSet<>(128);
-
-        short[] floors = pack(simplified, '.');
-        Coord[] apart = fractionPacked(floors, fraction);
-        Collections.addAll(chokes, apart);
-        for (int i = 0; i < apart.length; i++) {
-            waypoints.put(apart[i], new OrderedMap<Coord, Edge>());
-        }
-
-        dm = new DijkstraMap(map, DijkstraMap.findMeasurement(measurement));
-
-        int e = 0;
-        for(Map.Entry<Coord, OrderedMap<Coord, Edge>> n : waypoints.entrySet())
-        {
-            chokes.remove(n.getKey());
-            if(chokes.isEmpty())
-                break;
-            dm.clearGoals();
-            dm.resetMap();
-            dm.setGoal(n.getKey());
-            dm.scan(null);
-            for(Coord c : chokes)
-            {
-                n.getValue().put(c, new Edge(n.getKey(), c, dm.findPathPreScanned(c), dm.gradientMap[c.x][c.y]));
-            }
-        }
-
-    }
-
-    /**
-     * Calculates and stores the doors and doors-like connections ("chokepoints") on the given map as waypoints.
-     * Will use the given DijkstraMap for pathfinding after construction (and during some initial calculations).
-     * The dijkstra parameter will be mutated by this class, so it should not be reused elsewhere.
-     * Uses rng for all random choices, or a new unseeded RNG if the parameter is null.
-     * @param map a char[][] that stores a "complete" dungeon map, with any chars as features that pathfinding needs
-     * @param dijkstra a DijkstraMap that will be used to find paths; may have costs but they will not be used
-     * @param rng an RNG object or null (which will make this use a new RNG); will be used for all random choices
-     */
-    public WaypointPathfinder(char[][] map, DijkstraMap dijkstra, RNG rng)
-    {
-        if(rng == null)
-            this.rng = new StatefulRNG();
-        else
-            this.rng = rng;
-        this.map = map;
-        width = map.length;
-        height = map[0].length;
-        char[][] simplified = DungeonUtility.simplifyDungeon(map);
-        ArrayList<Coord> centers = PoissonDisk.sampleMap(simplified,
-                Math.min(width, height) * 0.4f, this.rng, '#');
-        int centerCount = centers.size();
-        expansionMap = new int[width][height];
-        waypoints = new OrderedMap<>(64);
-        dm = new DijkstraMap(simplified, DijkstraMap.Measurement.MANHATTAN);
-
-        for (Coord center : centers) {
-            dm.clearGoals();
-            dm.resetMap();
-            dm.setGoal(center);
-            dm.scan(null);
-            double current;
-            for (int i = 0; i < width; i++) {
-                for (int j = 0; j < height; j++) {
-                    current = dm.gradientMap[i][j];
-                    if (current >= DijkstraMap.FLOOR)
-                        continue;
-                    if (center.x == i && center.y == j)
-                        expansionMap[i][j]++;
-                    for (Direction dir : Direction.CARDINALS) {
-                        if (dm.gradientMap[i + dir.deltaX][j + dir.deltaY] == current + 1 ||
-                                dm.gradientMap[i + dir.deltaX][j + dir.deltaY] == current - 1)
-                            expansionMap[i][j]++;
-                    }
-                }
-            }
-        }
-
-        for (int i = 0; i < width; i++) {
-            for (int j = 0; j < height; j++) {
-                expansionMap[i][j] /= centerCount;
-            }
-        }
-
-        OrderedSet<Coord> chokes = new OrderedSet<>(128);
-        for (int i = 0; i < width; i++) {
-            ELEMENT_WISE:
-            for (int j = 0; j < height; j++) {
-                if(expansionMap[i][j] <= 0)
-                    continue;
-                int current = expansionMap[i][j];
-                boolean good = false;
-                for(Direction dir : Direction.CARDINALS) {
-                    if (chokes.contains(Coord.get(i + dir.deltaX, j + dir.deltaY)))
-                        continue ELEMENT_WISE;
-                    if (expansionMap[i + dir.deltaX][j + dir.deltaY] > 0 && expansionMap[i + dir.deltaX][j + dir.deltaY] > current + 1 ||
-                            (expansionMap[i + dir.deltaX][j + dir.deltaY] > current && expansionMap[i][j] <= 2)) {
-                        if (expansionMap[i - dir.deltaX][j - dir.deltaY] > 0 && expansionMap[i - dir.deltaX][j - dir.deltaY] >= current) {
-                            good = true;
-                        }
-                    }
-                }
-                if(good) {
-                    Coord chk = Coord.get(i, j);
-                    chokes.add(chk);
-                    waypoints.put(chk, new OrderedMap<Coord, Edge>());
-                }
-            }
-        }
-        dm = dijkstra;
-        int e = 0;
-        for(Map.Entry<Coord, OrderedMap<Coord, Edge>> n : waypoints.entrySet())
-        {
-            chokes.remove(n.getKey());
-            if(chokes.isEmpty())
-                break;
-            dm.clearGoals();
-            dm.resetMap();
-            dm.setGoal(n.getKey());
-            dm.scan(null);
-            for(Coord c : chokes)
-            {
-                n.getValue().put(c, new Edge(n.getKey(), c, dm.findPathPreScanned(c), dm.gradientMap[c.x][c.y]));
-            }
-        }
-
-    }
-
-    /**
-     * Finds the appropriate one of the already-calculated, possibly-long paths this class stores to get from a waypoint
-     * to another waypoint, then quickly finds a path to get on the long path, and returns the total path. This does
-     * not need to perform any full-map scans with DijkstraMap.
-     * @param self the pathfinder's position
-     * @param approximateTarget the Coord that represents the approximate area to pathfind to; will be randomized if
-     *                          it is not walkable.
-     * @return an ArrayList of Coord that will go from a cell adjacent to self to a waypoint near approximateTarget
-     */
-    public ArrayList<Coord> getKnownPath(Coord self, Coord approximateTarget) {
-        ArrayList<Coord> near = dm.findNearestMultiple(approximateTarget, 5, waypoints.keySet());
-        Coord me = dm.findNearest(self, waypoints.keySet());
-        double bestCost = 999999.0;
-        ArrayList<Coord> path = new ArrayList<>();
-        /*if (waypoints.containsKey(me)) {
-            Edge[] ed = waypoints.get(me).values().toArray(new Edge[waypoints.get(me).size()]);
-            Arrays.sort(ed);
-            path = ed[0].path;
-        */
-        boolean reversed = false;
-        for (Coord test : near) {
-            if (waypoints.containsKey(test)) {
-                Edge ed;
-                if(waypoints.get(test).containsKey(me)) {
-                    ed = waypoints.get(test).get(me);
-                    reversed = true;
-                }
-                else if(waypoints.containsKey(me) && waypoints.get(me).containsKey(test))
-                    ed = waypoints.get(me).get(test);
-                else
-                    continue;
-                if (ed.cost < bestCost) {
-                    bestCost = ed.cost;
-                    path = new ArrayList<>(ed.path);
-                }
-            }
-        }
-        if(path.isEmpty())
-            return path;
-        if(reversed)
-            Collections.reverse(path);
-        ArrayList<Coord> getToPath = dm.findShortcutPath(self, path.toArray(new Coord[path.size()]));
-        if (getToPath.size() > 0)
-        {
-            getToPath.remove(getToPath.size() - 1);
-            getToPath.addAll(path);
-            path = getToPath;
-        }
-        return path;
-    }
-
-    /**
-     * If a creature is interrupted or obstructed on a "highway" path, it may need to travel off the path to its goal.
-     * This method gets a straight-line path back to the path to goal. It does not contain the "highway" path, only the
-     * "on-ramp" to enter the ideal path.
-     * @param currentPosition the current position of the pathfinder, which is probably not on the ideal path
-     * @param path the ideal path, probably returned by getKnownPath
-     * @return an ArrayList of Coord that go from a cell adjacent to currentPosition to a Coord on or adjacent to path.
-     */
-    public ArrayList<Coord> goBackToPath(Coord currentPosition, ArrayList<Coord> path)
-    {
-        return dm.findShortcutPath(currentPosition, path.toArray(new Coord[path.size()]));
-    }
-
-    public OrderedSet<Coord> getWaypoints()
-    {
-        return new OrderedSet<>(waypoints.keySet());
-    }
-
-    private static class Edge implements Comparable<Edge>
-    {
-        public Coord from;
-        public Coord to;
-        public ArrayList<Coord> path;
-        public double cost;
-        public Edge(Coord from, Coord to, ArrayList<Coord> path, double cost)
-        {
-            this.from = from;
-            this.to = to;
-            this.path = path;
-            this.cost = cost;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            Edge edge = (Edge) o;
-
-            if (Double.compare(edge.cost, cost) != 0) return false;
-            if (!from.equals(edge.from)) return false;
-            return to.equals(edge.to);
-
-        }
-
-        @Override
-        public int hashCode() {
-            int result;
-            long temp;
-            result = from.hashCode();
-            result = 31 * result + to.hashCode();
-            temp = Double.doubleToLongBits(cost);
-            result = 31 * result + (int) (temp ^ (temp >>> 32));
-            return result;
-        }
-
-        /**
-         * Compares this object with the specified object for order.  Returns a
-         * negative integer, zero, or a positive integer as this object is less
-         * than, equal to, or greater than the specified object.
-         *
-         * Note: this class has a natural ordering that is
-         * inconsistent with equals.
-         * @param o the object to be compared.
-         * @return a negative integer, zero, or a positive integer as this object
-         * is less than, equal to, or greater than the specified object.
-         * @throws NullPointerException if the specified object is null
-         * @throws ClassCastException   if the specified object's type prevents it
-         *                              from being compared to this object.
-         */
-        @Override
-        public int compareTo(Edge o) {
-            return (cost - o.cost > 0) ? 1 : (cost - o.cost < 0) ? -1 : 0;
-        }
-    }
-
-}

+ 0 - 210
squidlib-util/src/main/java/squidpony/squidai/ZOI.java

@@ -1,210 +0,0 @@
-package squidpony.squidai;
-
-import squidpony.squidgrid.Direction;
-import squidpony.squidgrid.Radius;
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.CoordPacker;
-import squidpony.squidmath.OrderedSet;
-import squidpony.squidmath.ShortVLA;
-
-import java.util.Collections;
-
-/**
- * Calculates the Zone of Influence, also known as Zone of Control, for different points on a map.
- * Uses CoordPacker for more efficient storage and manipulation of zones; it's recommended if you use this class to be
- * somewhat familiar with the methods for manipulating packed data in that class.
- * Created by Tommy Ettinger on 10/27/2015.
- */
-public class ZOI {
-    private char[][] map;
-    private DijkstraMap dijkstra;
-    private Coord[][] influences;
-    private short[][] packedGroups;
-    private boolean completed = false;
-    private Radius radius;
-    /**
-     * Constructs a Zone of Influence map. Takes a (quite possibly jagged) array of arrays of Coord influences, where
-     * the elements of the outer array represent different groups of influencing "factions" or groups that exert control
-     * over nearby areas, and the Coord elements of the inner array represent individual spots that are part of those
-     * groups and share influence with all Coord in the same inner array. Also takes a char[][] for a map, which can be
-     * the simplified map with only '#' for walls and '.' for floors, or the final map (with chars like '~' for deep
-     * water as well as walls and floors), and a Radius enum that will be used to determine how distance is calculated.
-     * <br>
-     * Call calculate() when you want information out of this.
-     * @param influences an outer array containing influencing groups, each an array containing Coords that influence
-     * @param map a char[][] that is used as a map; should be bounded
-     * @param measurement a Radius enum that corresponds to how distance should be measured
-     */
-    public ZOI(Coord[][] influences, char[][] map, Radius measurement) {
-        this.influences = influences;
-        packedGroups = new short[influences.length][];
-        this.map = map;
-        radius = measurement;
-        dijkstra = new DijkstraMap(map, DijkstraMap.findMeasurement(measurement));
-    }
-    /**
-     * Constructs a Zone of Influence map. Takes an arrays of Coord influences, where each Coord is treated as both a
-     * one-element group of influencing "factions" or groups that exert control over nearby areas, and the individual
-     * spot that makes up one of those groups and spreads influence. Also takes a char[][] for a map, which can be the
-     * simplified map with only '#' for walls and '.' for floors, or the final map (with chars like '~' for deep water
-     * as well as walls and floors), and a Radius enum that will be used to determine how distance is calculated.
-     * <br>
-     * Essentially, this is the same as constructing a ZOI with a Coord[][] where each inner array has only one element.
-     * <br>
-     * Call calculate() when you want information out of this.
-     * @param influences an array containing Coords that each have their own independent influence
-     * @param map a char[][] that is used as a map; should be bounded
-     * @param measurement a Radius enum that corresponds to how distance should be measured
-     * @see squidpony.squidmath.PoissonDisk for a good way to generate evenly spaced Coords that can be used here
-     */
-    public ZOI(Coord[] influences, char[][] map, Radius measurement) {
-        this.influences = new Coord[influences.length][];
-        for (int i = 0; i < influences.length; i++) {
-            this.influences[i] = new Coord[] { influences[i] };
-        }
-        packedGroups = new short[influences.length][];
-        this.map = map;
-        radius = measurement;
-        dijkstra = new DijkstraMap(map, DijkstraMap.findMeasurement(measurement));
-    }
-
-    /**
-     * Finds the zones of influence for each of the influences (inner arrays of Coord) this was constructed with, and
-     * returns them as packed data (using CoordPacker, which can also be used to unpack the data, merge zones, get
-     * shared borders, and all sorts of other tricks). This has each zone of influence overlap with its neighbors; this
-     * is useful to find borders using CoordPacker.intersectPacked(), and borders are typically between 1 and 2 cells
-     * wide. You can get a different region as packed data if you want region A without the overlapping areas it shares
-     * with region B by using {@code short[] different = CoordPacker.differencePacked(A, B)}. Merging two zones A and B
-     * can be done with {@code short[] merged = CoordPacker.unionPacked(A, B)} . You can unpack the data
-     * into a boolean[][] easily with CoordPacker.unpack(), where true is contained in the zone and false is not.
-     * The CoordPacker methods fringe(), expand(), singleRandom(), randomSample(), and randomPortion() are also
-     * potentially useful for this sort of data. You should save the short[][] for later use if you want to call
-     * nearestInfluences() in this class.
-     * <br>
-     * The first short[] in the returned short[][] will correspond to the area influenced by the first Coord[] in the
-     * nested array passed to the constructor (or the first Coord if a non-nested array was passed); the second will
-     * correspond to the second, and so on. The length of the short[][] this returns will equal the number of influence
-     * groups.
-     * @return an array of short[] storing the zones' areas; each can be used as packed data with CoordPacker
-     */
-    public short[][] calculate()
-    {
-        for (int i = 0; i < influences.length; i++) {
-            for (int j = 0; j < influences[i].length; j++) {
-                dijkstra.setGoal(influences[i][j]);
-            }
-        }
-        double[][] scannedAll = dijkstra.scan(null);
-
-        for (int i = 0; i < influences.length; i++) {
-
-            /*
-            dijkstra.clearGoals();
-            dijkstra.resetMap();
-            for (int j = 0; j < influences[i].length; j++) {
-                dijkstra.setGoal(influences[i][j]);
-            }
-            double[][] factionScanned = dijkstra.scan(null);
-            for (int y = 0; y < map[0].length; y++) {
-                for (int x = 0; x < map.length; x++) {
-                    influenced[x][y] = (scannedAll[x][y] < DijkstraMap.FLOOR) &&
-                            (factionScanned[x][y] - scannedAll[x][y] <= 1);
-                }
-            }*/
-            packedGroups[i] = CoordPacker.pack(increasing(scannedAll, influences[i]));
-        }
-        completed = true;
-        return packedGroups;
-    }
-    protected boolean[][] increasing(double[][] dm, Coord[] inf) {
-        OrderedSet<Coord> open = new OrderedSet<>(64), fresh = new OrderedSet<>(64);
-        Collections.addAll(open, inf);
-        Direction[] dirs = (radius.equals2D(Radius.DIAMOND)) ? Direction.CARDINALS : Direction.OUTWARDS;
-        boolean[][] influenced = new boolean[map.length][map[0].length];
-
-        final int width = dm.length;
-        final int height = width == 0 ? 0 : dm[0].length;
-
-        int numAssigned = open.size();
-        double diff;
-        while (numAssigned > 0) {
-            numAssigned = 0;
-            for (Coord cell : open) {
-                influenced[cell.x][cell.y] = true;
-                for (int d = 0; d < dirs.length; d++) {
-                    Coord adj = cell.translate(dirs[d].deltaX, dirs[d].deltaY);
-                    if (adj.x < 0 || adj.y < 0 || width <= adj.x || height <= adj.y)
-                    	/* Outside the map */
-                    	continue;
-                    if (!open.contains(adj) && dm[adj.x][adj.y] < DijkstraMap.FLOOR && !influenced[adj.x][adj.y]) {
-                        //h = heuristic(dirs[d]);
-                        diff = dm[adj.x][adj.y] - dm[cell.x][cell.y];
-                        if (diff <= 1.0 && diff >= 0) {
-                            fresh.add(adj);
-                            influenced[adj.x][adj.y] = true;
-                            ++numAssigned;
-                        }
-                    }
-                }
-            }
-
-            open = new OrderedSet<>(fresh);
-            fresh.clear();
-        }
-
-        return influenced;
-    }
-
-    /**
-     * Given the zones resulting from this class' calculate method and a Coord to check, finds the indices of all
-     * influencing groups in zones that have the Coord in their area, and returns all such indices as an int array.
-     * @param zones a short[][] returned by calculate; not a multi-packed short[][] from CoordPacker !
-     * @param point the Coord to test
-     * @return an int[] where each element is the index of an influencing group in zones
-     */
-    public int[] nearestInfluences(short[][] zones, Coord point)
-    {
-        ShortVLA found = new ShortVLA(4);
-        for (short i = 0; i < zones.length; i++) {
-            if(CoordPacker.queryPacked(zones[i], point.x, point.y))
-                found.add(i);
-        }
-        return found.asInts();
-    }
-    /**
-     * This can be given a Coord to check in the results of the latest calculate() call. Finds the indices of all
-     * influencing groups in zones that have the Coord in their area, and returns all such indices as an int array.
-     * @param point the Coord to test
-     * @return an int[] where each element is the index of an influencing group in zones
-     */
-    public int[] nearestInfluences(Coord point)
-    {
-        if(!completed)
-            return new int[0];
-        ShortVLA found = new ShortVLA(4);
-        for (short i = 0; i < packedGroups.length; i++) {
-            if(CoordPacker.queryPacked(packedGroups[i], point.x, point.y))
-                found.add(i);
-        }
-        return found.asInts();
-    }
-
-    /**
-     * Gets the influencing groups; ideally the result should not be changed without setting it back with setInfluences.
-     * @return influences a jagged array of Coord arrays, where the inner arrays are groups of influences
-     */
-    public Coord[][] getInfluences() {
-        return influences;
-    }
-
-    /**
-     * Changes the influencing groups. This also invalidates the last calculation for the purposes of nearestInfluences,
-     * at least for the overload that takes only a Coord.
-     * @param influences a jagged array of Coord arrays, where the inner arrays are groups of influences
-     */
-    public void setInfluences(Coord[][] influences) {
-        this.influences = influences;
-        packedGroups = new short[influences.length][];
-        completed = false;
-    }
-}

Fichier diff supprimé car celui-ci est trop grand
+ 630 - 604
squidlib-util/src/main/java/squidpony/squidgrid/LOS.java


+ 0 - 276
squidlib-util/src/main/java/squidpony/squidmath/CombinationGenerator.java

@@ -1,276 +0,0 @@
-// ============================================================================
-//   Copyright 2006-2012 Daniel W. Dyer
-//
-//   Licensed under the Apache License, Version 2.0 (the "License");
-//   you may not use this file except in compliance with the License.
-//   You may obtain a copy of the License at
-//
-//       http://www.apache.org/licenses/LICENSE-2.0
-//
-//   Unless required by applicable law or agreed to in writing, software
-//   distributed under the License is distributed on an "AS IS" BASIS,
-//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//   See the License for the specific language governing permissions and
-//   limitations under the License.
-// ============================================================================
-package squidpony.squidmath;
-
-import java.io.Serializable;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Combination generator for generating all combinations of a given size from
- * the specified set of elements.  For performance reasons, this implementation
- * is restricted to operating with set sizes and combination lengths that produce
- * no more than 2^63 different combinations.
- * <br>
- * Originally part of the <a href="http://maths.uncommons.org/">Uncommon Maths software package</a>.
- * @param <T> The type of element that the combinations are made from.
- * @author Daniel Dyer (modified from the original version written by Michael
- * Gilleland of Merriam Park Software -
- * <a href="http://www.merriampark.com/perm.htm">http://www.merriampark.com/comb.htm</a>).
- * @see PermutationGenerator
- */
-public class CombinationGenerator<T> implements Iterable<List<T>>, Serializable
-{
-    private static final long serialVersionUID = 5998145341506278361L;
-
-    private final T[] elements;
-    private final int[] combinationIndices;
-    private long remainingCombinations;
-    private long totalCombinations;
-
-    private CombinationGenerator()
-    {
-        elements = null;
-        combinationIndices = null;
-    };
-    /**
-     * Create a combination generator that generates all combinations of
-     * a specified length from the given set.
-     * @param elements The set from which to generate combinations; will be used directly (not copied)
-     * @param combinationLength The length of the combinations to be generated.
-     */
-    public CombinationGenerator(T[] elements,
-                                int combinationLength)
-    {
-        if (combinationLength > elements.length)
-        {
-            throw new IllegalArgumentException("Combination length cannot be greater than set size.");
-        }
-
-        this.elements = elements;
-        this.combinationIndices = new int[combinationLength];
-
-        BigInteger sizeFactorial = MathExtras.bigFactorial(elements.length);
-        BigInteger lengthFactorial = MathExtras.bigFactorial(combinationLength);
-        BigInteger differenceFactorial = MathExtras.bigFactorial(elements.length - combinationLength);
-        BigInteger total = sizeFactorial.divide(differenceFactorial.multiply(lengthFactorial));
-        
-        if (total.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0)
-        {
-            throw new IllegalArgumentException("Total number of combinations must not be more than 2^63."); 
-        }
-
-        totalCombinations = total.longValue();
-        reset();
-    }
-
-
-    /**
-     * Create a combination generator that generates all combinations of
-     * a specified length from the given set.
-     * @param elements The set from which to generate combinations.
-     * @param combinationLength The length of the combinations to be generated.
-     * @param filler An array of T with the same length as elements; needed because GWT can't create a generic array.
-     */
-    @SuppressWarnings("unchecked")
-    public CombinationGenerator(Collection<T> elements,
-                                int combinationLength,
-                                T[] filler)
-    {
-        this(elements.toArray(filler), combinationLength);
-    }
-
-
-    /**
-     * Reset the combination generator.
-     */
-    public final void reset()
-    {
-        for (int i = 0; i < combinationIndices.length; i++)
-        {
-            combinationIndices[i] = i;
-        }
-        remainingCombinations = totalCombinations;
-    }
-
-
-    /**
-     * @return The number of combinations not yet generated.
-     */
-    public long getRemainingCombinations()
-    {
-        return remainingCombinations;
-    }
-
-
-    /**
-     * Are there more combinations?
-     * @return true if there are more combinations available, false otherwise.
-     */
-    public boolean hasMore()
-    {
-        return remainingCombinations > 0;
-    }
-
-
-    /**
-     * @return The total number of combinations.
-     */
-    public long getTotalCombinations()
-    {
-        return totalCombinations;
-    }
-
-
-    /**
-     * Generate the next combination and return an array containing
-     * the appropriate elements.  This overloaded method allows the caller
-     * to provide an array that will be used and returned.
-     * The purpose of this is to improve performance when iterating over
-     * combinations.  This method allows a single array instance to be reused.
-     * @param destination Provides an array to use to create the
-     * combination.  The specified array must be the same length as a
-     * combination.
-     * @return The provided array now containing the elements of the combination.
-     */
-    public T[] nextCombinationAsArray(T[] destination)
-    {
-        if (destination.length != combinationIndices.length)
-        {
-            throw new IllegalArgumentException("Destination array must be the same length as combinations.");
-        }
-        generateNextCombinationIndices();
-        for (int i = 0; i < combinationIndices.length; i++)
-        {
-            destination[i] = elements[combinationIndices[i]];
-        }
-        return destination;
-    }
-
-
-    /**
-     * Generate the next combination and return a list containing the
-     * appropriate elements.
-     * @see #nextCombinationAsList(List)
-     * @return A list containing the elements that make up the next combination.
-     */
-    public List<T> nextCombinationAsList()
-    {
-        return nextCombinationAsList(new ArrayList<T>(elements.length));
-    }
-
-
-    /**
-     * Generate the next combination and return a list containing
-     * the appropriate elements.  This overloaded method allows the caller
-     * to provide a list that will be used and returned.
-     * The purpose of this is to improve performance when iterating over
-     * combinations.  If the {@link #nextCombinationAsList()} method is
-     * used it will create a new list every time.  When iterating over
-     * combinations this will result in lots of short-lived objects that
-     * have to be garbage collected.  This method allows a single list
-     * instance to be reused in such circumstances.
-     * @param destination Provides a list to use to create the
-     * combination.
-     * @return The provided list now containing the elements of the combination.
-     */
-    public List<T> nextCombinationAsList(List<T> destination)
-    {
-        generateNextCombinationIndices();
-        // Generate actual combination.
-        destination.clear();
-        for (int i : combinationIndices)
-        {
-            destination.add(elements[i]);
-        }
-        return destination;
-    }
-
-
-
-    /**
-     * Generate the indices into the elements array for the next combination. The
-     * algorithm is from Kenneth H. Rosen, Discrete Mathematics and Its Applications,
-     * 2nd edition (NY: McGraw-Hill, 1991), p. 286.
-     */
-    private void generateNextCombinationIndices()
-    {
-        if (remainingCombinations == 0)
-        {
-            throw new IllegalStateException("There are no combinations remaining.  " +
-                                            "Generator must have reset() called to continue.");
-        }
-        else if (remainingCombinations < totalCombinations)
-        {
-            int i = combinationIndices.length - 1;
-            while (combinationIndices[i] == elements.length - combinationIndices.length + i)
-            {
-                i--;
-            }
-            ++combinationIndices[i];
-            for (int j = i + 1; j < combinationIndices.length; j++)
-            {
-                combinationIndices[j] = combinationIndices[i] + j - i;
-            }
-        }
-        --remainingCombinations;
-    }
-
-
-    /**
-     * <p>Provides a read-only iterator for iterating over the combinations
-     * generated by this object.  This method is the implementation of the
-     * {@link Iterable} interface that permits instances of this class to be
-     * used with the new-style for loop.</p>
-     * <p>For example:</p>
-     * <pre>
-     * List&lt;Integer&gt; elements = Arrays.asList(1, 2, 3);
-     * CombinationGenerator&lt;Integer&gt; combinations = new CombinationGenerator(elements, 2);
-     * for (List&lt;Integer&gt; c : combinations)
-     * {
-     *     // Do something with each combination.
-     * }
-     * </pre>
-     * @return An iterator.
-     * @since 1.1
-     */
-    public Iterator<List<T>> iterator()
-    {
-        return new Iterator<List<T>>()
-        {
-            public boolean hasNext()
-            {
-                return hasMore();
-            }
-
-
-            public List<T> next()
-            {
-                return nextCombinationAsList();
-            }
-
-
-            public void remove()
-            {
-                throw new UnsupportedOperationException("Iterator does not support removal.");
-            }
-        };
-    }
-
-}

+ 0 - 153
squidlib-util/src/main/java/squidpony/squidmath/SquidID.java

@@ -1,153 +0,0 @@
-package squidpony.squidmath;
-
-import squidpony.StringKit;
-
-import java.io.Serializable;
-
-/**
- * A UUID-like identifier; not compatible with Java's standard UUID but will work on GWT.
- * <br>
- * Meant to be used as an identity type for things like SpatialMap, especially when no special game-specific logic is
- * needed for identities.
- * Created by Tommy Ettinger on 4/30/2016.
- */
-public class SquidID implements Serializable, Comparable<SquidID> {
-    private static final long serialVersionUID = 8946534790126874460L;
-    private static LongPeriodRNG rng = new LongPeriodRNG();
-    public final long low, high;
-
-    /**
-     * Constructs a new random SquidID. If you want different random IDs with every run, the defaults should be fine.
-     * If you want stable IDs to be generated, use SquidID.stabilize(), but be careful about collisions!
-     */
-    public SquidID() {
-        low = rng.nextLong();
-        high = rng.nextLong();
-    }
-
-    /**
-     * Constructs a fixed SquidID with the given low and high 64-bit longs.
-     * @param low the least-significant bits of the ID
-     * @param high the most-significant bits of the ID
-     */
-    public SquidID(long low, long high) {
-        this.low = low;
-        this.high = high;
-    }
-
-    /**
-     * Gets a new random SquidID, the same as calling the no-argument constructor.
-     * The name is for compatibility with Java's standard UUID class.
-     * @return a newly-constructed random SquidID.
-     */
-    public static SquidID randomUUID()
-    {
-        return new SquidID();
-    }
-
-    /**
-     * Makes the IDs generated after calling this repeatable, with the same IDs generated in order after this is called.
-     * This class uses a random number generator with a random seed by default to produce IDs, and properties of the
-     * LongPeriodRNG this uses make it incredibly unlikely that IDs will repeat even if the game was run for the rest
-     * of your natural lifespan. For the purposes of tests, you may want stable SquidID values to be generated, the same
-     * for every startup of the program, generating the same IDs in order. This will change the seed used internally to
-     * a constant (large) seed the first time it is called, and it should only be called at or near the start of your
-     * program, no more than once. If an ID is requested immediately after calling this method, and then this method is
-     * called again, the next ID to be generated will be identical to the previous one generated (a collision). There
-     * may be reasons you want this during testing, so there isn't any check for multiple calls to this method. If IDs
-     * can persist between runs of the game (i.e. saved in a file), using this is generally a bad idea, and the default
-     * random IDs should more than suffice.
-     * <br>
-     * You can "undo" the effects of this method with randomize(), changing the seed to a new random value.
-     * <br>
-     * Because IDs aren't likely to have gameplay significance, this uses one seed, the opening paragraph of The
-     * Wonderful Wizard of Oz, by Frank L. Baum, which is in the public domain. Changing the seed is unlikely to change
-     * the likelihood of collisions, which should be less likely than a tornado transporting you to Oz, as long as this
-     * method is called at most once per program run.
-     */
-    public static void stabilize()
-    {
-        rng.reseed(
-                "Dorothy lived in the midst of the great Kansas prairies, with Uncle Henry, who was a "+
-                        "farmer, and Aunt Em, who was the farmer's wife. Their house was small, for the "+
-                        "lumber to build it had to be carried by wagon many miles. There were four walls, "+
-                        "a floor and a roof, which made one room; and this room contained a rusty looking "+
-                        "cookstove, a cupboard for the dishes, a table, three or four chairs, and the beds."+
-                        " Uncle Henry and Aunt Em had a big bed in one corner, and Dorothy a little bed in "+
-                        "another corner. There was no garret at all, and no cellar—except a small hole dug "+
-                        "in the ground, called a cyclone cellar, where the family could go in case one of "+
-                        "those great whirlwinds arose, mighty enough to crush any building in its path. It "+
-                        "was reached by a trap door in the middle of the floor, from which a ladder led "+
-                        "down into the small, dark hole.");
-    }
-
-    /**
-     * Makes the IDs generated after calling this non-repeatable, with a random 1024-bit seed.
-     * This class uses a random number generator with a random seed by default to produce IDs, and properties of the
-     * LongPeriodRNG this uses make it incredibly unlikely that IDs will repeat even if the game was run for the rest
-     * of your natural lifespan. However, if you call stabilize(), generate some IDs, call stabilize() again, and
-     * generate some more IDs, the first, second, third, etc. IDs generated after each call will be identical -- hardly
-     * the unique ID you usually want. You can "undo" the effects of stabilize by calling this method, making the seed
-     * a new random value. This does not affect the constructor that takes two longs to produce an exact ID, nor will
-     * it change any IDs.
-     */
-    public static void randomize()
-    {
-        rng.reseed();
-    }
-
-    /**
-     * Gets the least-significant bits, also accessible by the field low.
-     * The name is for compatibility with Java's standard UUID class.
-     * @return the least-significant bits as a long
-     */
-    public long getLeastSignificantBits()
-    {
-        return low;
-    }
-
-    /**
-     * Gets the most-significant bits, also accessible by the field high.
-     * The name is for compatibility with Java's standard UUID class.
-     * @return the most-significant bits as a long
-     */
-    public long getMostSignificantBits()
-    {
-        return high;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        SquidID squidID = (SquidID) o;
-
-        if (low != squidID.low) return false;
-        return high == squidID.high;
-
-    }
-
-    @Override
-    public int hashCode() {
-        int result = (int) (low ^ (low >>> 32));
-        result = 31 * result + (int) (high ^ (high >>> 32));
-        return result;
-    }
-
-    @Override
-    public String toString()
-    {
-        return StringKit.hex(high) + '-' + StringKit.hex(low);
-    }
-
-    @Override
-    public int compareTo(SquidID o) {
-        if(o == null)
-            return 1;
-        long diff = high - o.high;
-        if(diff == 0)
-            diff = low - o.low;
-        return diff > 0 ? 1 : diff < 0 ? -1 : 0;
-    }
-}