Parcourir la source

Remove stuff I don't use

smelc il y a 7 ans
Parent
commit
688faf151b

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

@@ -2552,218 +2552,6 @@ public class DijkstraMap implements Serializable {
         return new ArrayList<>(path);
         return new ArrayList<>(path);
     }
     }
 
 
-    /**
-     * Scans the dungeon using DijkstraMap.scan with the listed goals and start point, and returns a list
-     * of Coord positions (using the current measurement) needed to get closer to a goal, where goals are
-     * considered valid if they are at a valid range for the given Technique to hit at least one target
-     * and ideal if that Technique can affect as many targets as possible from a cell that can be moved
-     * to with at most movelength steps.
-     * <p/>
-     * The return value of this method is the path to get to a location to attack, but on its own it
-     * does not tell the user how to perform the attack.  It does set the targetMap 2D Coord array field
-     * so that if your position at the end of the returned path is non-null in targetMap, it will be
-     * a Coord that can be used as a target position for Technique.apply() . If your position at the end
-     * of the returned path is null, then an ideal attack position was not reachable by the path.
-     * <p/>
-     * This needs a char[][] dungeon as an argument because DijkstraMap does not always have a char[][]
-     * version of the map available to it, and certain AOE implementations that a Technique uses may
-     * need a char[][] specifically to determine what they affect.
-     * <p/>
-     * The maximum length of the returned list is given by moveLength; if moving the full length of
-     * the list would place the mover in a position shared by one of the positions in allies
-     * (which is typically filled with friendly units that can be passed through in multi-tile-
-     * movement scenarios, and is also used considered an undesirable thing to affect for the Technique),
-     * it will recalculate a move so that it does not pass into that cell.
-     * <p/>
-     * The keys in impassable should be the positions of enemies and obstacles that cannot be moved
-     * through, and will be ignored if there is a target overlapping one.
-     * <br>
-     * This caches its result in a member field, path, which can be fetched after finding a path and will change with
-     * each call to a pathfinding method.
-     *
-     * @param moveLength the maximum distance to try to pathfind out to; if a spot to use a Technique can be found
-     *                   while moving no more than this distance, then the targetMap field in this object will have a
-     *                   target Coord that is ideal for the given Technique at the x, y indices corresponding to the
-     *                   last Coord in the returned path.
-     * @param tech       a Technique that we will try to find an ideal place to use, and/or a path toward that place.
-     * @param dungeon    a char 2D array with '#' for walls.
-     * @param cache      a FOVCache that has completed its calculations, and will be used for LOS and Technique work, may be null
-     * @param impassable locations of enemies or mobile hazards/obstacles that aren't in the map as walls
-     * @param allies     called onlyPassable in other methods, here it also represents allies for Technique things
-     * @param start      the Coord the pathfinder starts at.
-     * @param targets    a Set of Coord, not an array of Coord or variable argument list as in other methods.
-     * @return an ArrayList of Coord that represents a path to travel to get to an ideal place to use tech. Copy of path.
-     */
-    @GwtIncompatible
-    public ArrayList<Coord> findTechniquePath(int moveLength, Technique tech, char[][] dungeon, FOVCache cache,
-                                              Set<Coord> impassable, Set<Coord> allies, Coord start, Set<Coord> targets) {
-        if (!initialized) return null;
-        tech.setMap(dungeon);
-        if (cache != null)
-            tech.aoe.setCache(cache);
-        double[][] resMap = new double[width][height];
-        double[][] worthMap = new double[width][height];
-        double[][] userDistanceMap;
-        double paidLength = 0.0;
-
-        OrderedSet<Coord> friends;
-
-
-        for (int x = 0; x < width; x++) {
-            for (int y = 0; y < height; y++) {
-                resMap[x][y] = (physicalMap[x][y] == WALL) ? 1.0 : 0.0;
-                targetMap[x][y] = null;
-            }
-        }
-
-        path.clear();
-        if (targets == null || targets.size() == 0)
-            return new ArrayList<>(path);
-        OrderedSet<Coord> impassable2;
-        if (impassable == null)
-            impassable2 = new OrderedSet<>();
-        else
-            impassable2 = new OrderedSet<>(impassable);
-
-        if (allies == null)
-            friends = new OrderedSet<>();
-        else {
-            friends = new OrderedSet<>(allies);
-            friends.remove(start);
-        }
-
-        resetMap();
-        setGoal(start);
-        userDistanceMap = scan(impassable2);
-        clearGoals();
-        resetMap();
-        for (Coord goal : targets) {
-            setGoal(goal.x, goal.y);
-        }
-        if (goals.isEmpty())
-            return new ArrayList<>(path);
-
-        Measurement mess = measurement;
-        /*
-        if(measurement == Measurement.EUCLIDEAN)
-        {
-            measurement = Measurement.CHEBYSHEV;
-        }
-        */
-        scan(impassable2);
-        clearGoals();
-
-        Coord tempPt = Coord.get(0, 0);
-        OrderedMap<Coord, ArrayList<Coord>> ideal;
-        // generate an array of the single best location to attack when you are in a given cell.
-        for (int x = 0; x < width; x++) {
-            CELL:
-            for (int y = 0; y < height; y++) {
-                tempPt = Coord.get(x, y);
-                if (gradientMap[x][y] == WALL || gradientMap[x][y] == DARK || userDistanceMap[x][y] > moveLength * 2.0)
-                    continue;
-                if (gradientMap[x][y] >= tech.aoe.getMinRange() && gradientMap[x][y] <= tech.aoe.getMaxRange()) {
-                    for (Coord tgt : targets) {
-                        if (cache == null || cache.queryLOS(x, y, tgt.x, tgt.y)) {
-                            ideal = tech.idealLocations(tempPt, targets, friends);
-                            if (!ideal.isEmpty()) {
-                                targetMap[x][y] = ideal.keyAt(0);
-                                worthMap[x][y] = ideal.getAt(0).size();
-                                setGoal(x, y);
-                                gradientMap[x][y] = 0;
-                            }
-                            continue CELL;
-                        }
-                    }
-                    gradientMap[x][y] = FLOOR;
-                } else
-                    gradientMap[x][y] = FLOOR;
-            }
-        }
-        scan(impassable2);
-
-        double currentDistance = gradientMap[start.x][start.y];
-        if (currentDistance <= moveLength) {
-            int[] g_arr = goals.keySet().toIntArray();
-            Coord dec;
-
-            goals.clear();
-            setGoal(start);
-            scan(impassable2);
-            goals.clear();
-            gradientMap[start.x][start.y] = moveLength;
-
-            for (int g : g_arr) {
-                dec = Coord.decode(g);
-                if (gradientMap[dec.x][dec.y] <= moveLength && worthMap[dec.x][dec.y] > 0) {
-                    goals.put(g, 0.0 - worthMap[dec.x][dec.y]);
-                }
-            }
-            resetMap();
-           /* for(Coord g : goals.keySet())
-            {
-                gradientMap[g.x][g.y] = 0.0 - worthMap[g.x][g.y];
-            }*/
-            scan(impassable2);
-
-        }
-
-        measurement = mess;
-
-        Coord currentPos = Coord.get(start.x, start.y);
-        while (true) {
-            if (frustration > 500) {
-                path.clear();
-                break;
-            }
-            double best = gradientMap[currentPos.x][currentPos.y];
-            final Direction[] dirs = appendDirToShuffle(rng);
-            int choice = rng.nextInt(measurement.directionCount() + 1);
-
-            for (int d = 0; d <= measurement.directionCount(); d++) {
-                Coord pt = Coord.get(currentPos.x + dirs[d].deltaX, currentPos.y + dirs[d].deltaY);
-                if (gradientMap[pt.x][pt.y] < best && !impassable2.contains(pt)) {
-                    if (dirs[choice] == Direction.NONE || !path.contains(pt)) {
-                        best = gradientMap[pt.x][pt.y];
-                        choice = d;
-                    }
-                }
-            }
-            if (best >= gradientMap[currentPos.x][currentPos.y]) {
-                if (friends.contains(currentPos)) {
-                    closed.put(currentPos.encode(), WALL);
-                    impassable2.add(currentPos);
-                    return findTechniquePath(moveLength, tech, dungeon, cache, impassable2,
-                            friends, start, targets);
-                }
-                break;
-            }
-            if (best > gradientMap[start.x][start.y] || physicalMap[currentPos.x + dirs[choice].deltaX][currentPos.y + dirs[choice].deltaY] > FLOOR) {
-                path.clear();
-                break;
-            }
-            currentPos = currentPos.translate(dirs[choice].deltaX, dirs[choice].deltaY);
-            path.add(currentPos);
-            paidLength += costMap[currentPos.x][currentPos.y];
-            frustration++;
-            if (paidLength > moveLength - 1.0) {
-                if (friends.contains(currentPos)) {
-                    closed.put(currentPos.encode(), WALL);
-                    impassable2.add(currentPos);
-                    return findTechniquePath(moveLength, tech, dungeon, cache, impassable2,
-                            friends, start, targets);
-                }
-                break;
-            }
-//            if(gradientMap[currentPos.x][currentPos.y] == 0)
-//                break;
-        }
-        frustration = 0;
-        goals.clear();
-        return new ArrayList<>(path);
-    }
-
-
     private double cachedLongerPaths = 1.2;
     private double cachedLongerPaths = 1.2;
     private Set<Coord> cachedImpassable = new OrderedSet<>();
     private Set<Coord> cachedImpassable = new OrderedSet<>();
     private Coord[] cachedFearSources;
     private Coord[] cachedFearSources;

+ 0 - 469
squidlib-util/src/main/java/squidpony/squidgrid/SoundMap.java

@@ -1,469 +0,0 @@
-package squidpony.squidgrid;
-
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.LightRNG;
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.RNG;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * This class is used to determine when a sound is audible on a map and at what positions.
- * Created by Tommy Ettinger on 4/4/2015.
- */
-public class SoundMap
-{
-    /**
-     * The type of heuristic to use. Note that EUCLIDEAN is not an option here because it would only affect paths, and
-     * there is no path-finding functionality in this class.
-     */
-    public enum Measurement {
-
-        /**
-         * The distance it takes when only the four primary directions can be
-         * moved in. The default.
-         */
-        MANHATTAN,
-        /**
-         * The distance it takes when diagonal movement costs the same as
-         * cardinal movement.
-         */
-        CHEBYSHEV
-    }
-
-    /**
-     * This affects how sound travels on diagonal directions vs. orthogonal directions. MANHATTAN should form a diamond
-     * shape on a featureless map, while CHEBYSHEV will form a square.
-     */
-    public Measurement measurement = Measurement.MANHATTAN;
-
-
-    /**
-     * Stores which parts of the map are accessible and which are not. Should not be changed unless the actual physical
-     * terrain has changed. You should call initialize() with a new map instead of changing this directly.
-     */
-    public double[][] physicalMap;
-    /**
-     * The frequently-changing values that are often the point of using this class; cells producing sound will have a
-     * value greater than 0, cells that cannot possibly be reached by a sound will have a value of exactly 0, and walls
-     * will have a value equal to the WALL constant (a negative number).
-     */
-    public double[][] gradientMap;
-    /**
-     * Height of the map. Exciting stuff. Don't change this, instead call initialize().
-     */
-    public int height;
-    /**
-     * Width of the map. Exciting stuff. Don't change this, instead call initialize().
-     */
-    public int width;
-    /**
-     * The latest results of findAlerted(), with Coord keys representing the positions of creatures that were alerted
-     * and Double values representing how loud the sound was when it reached them.
-     */
-    public OrderedMap<Coord, Double> alerted = new OrderedMap<>();
-    /**
-     * Cells with no sound are always marked with 0.
-     */
-    public static final double SILENT = 0.0;
-    /**
-     * Walls, which are solid no-entry cells, are marked with a significant negative number equal to -999500.0 .
-     */
-    public static final double WALL = -999500.0;
-    /**
-     * Sources of sound on the map; keys are positions, values are how loud the noise is (10.0 should spread 10 cells
-     * away, with diminishing values assigned to further positions).
-     */
-    public OrderedMap<Coord, Double> sounds;
-    private OrderedMap<Coord, Double> fresh;
-    /**
-     * The RNG used to decide which one of multiple equally-short paths to take.
-     */
-    public RNG rng;
-
-    private boolean initialized = false;
-    /**
-     * Construct a SoundMap without a level to actually scan. If you use this constructor, you must call an
-     * initialize() method before using this class.
-     */
-    public SoundMap() {
-        rng = new RNG(new LightRNG());
-        alerted = new OrderedMap<>();
-        fresh = new OrderedMap<>();
-        sounds = new OrderedMap<>();
-    }
-
-    /**
-     * Construct a SoundMap without a level to actually scan. This constructor allows you to specify an RNG before it is
-     * used. If you use this constructor, you must call an initialize() method before using this class.
-     */
-    public SoundMap(RNG random) {
-        rng = random;
-        alerted = new OrderedMap<>();
-        fresh = new OrderedMap<>();
-        sounds = new OrderedMap<>();
-    }
-
-    /**
-     * Used to construct a SoundMap from the output of another. Any sounds will need to be assigned again.
-     * @param level
-     */
-    public SoundMap(final double[][] level) {
-        rng = new RNG(new LightRNG());
-        alerted = new OrderedMap<>();
-        fresh = new OrderedMap<>();
-        sounds = new OrderedMap<>();
-        initialize(level);
-    }
-    /**
-     * Used to construct a DijkstraMap from the output of another, specifying a distance calculation.
-     * @param level
-     * @param measurement
-     */
-    public SoundMap(final double[][] level, Measurement measurement) {
-        rng = new RNG(new LightRNG());
-        this.measurement = measurement;
-        alerted = new OrderedMap<>();
-        fresh = new OrderedMap<>();
-        sounds = new OrderedMap<>();
-        initialize(level);
-    }
-
-    /**
-     * Constructor meant to take a char[][] returned by DungeonGen.generate(), or any other
-     * char[][] where '#' means a wall and anything else is a walkable tile. If you only have
-     * a map that uses box-drawing characters, use DungeonUtility.linesToHashes() to get a
-     * map that can be used here.
-     *
-     * @param level
-     */
-    public SoundMap(final char[][] level) {
-        rng = new RNG(new LightRNG());
-        alerted = new OrderedMap<>();
-        fresh = new OrderedMap<>();
-        sounds = new OrderedMap<>();
-        initialize(level);
-    }
-    /**
-     * Constructor meant to take a char[][] returned by DungeonGen.generate(), or any other
-     * char[][] where one char means a wall and anything else is a walkable tile. If you only have
-     * a map that uses box-drawing characters, use DungeonUtility.linesToHashes() to get a
-     * map that can be used here. You can specify the character used for walls.
-     *
-     * @param level
-     */
-    public SoundMap(final char[][] level, char alternateWall) {
-        rng = new RNG(new LightRNG());
-        alerted = new OrderedMap<>();
-        fresh = new OrderedMap<>();
-        sounds = new OrderedMap<>();
-        initialize(level, alternateWall);
-    }
-
-    /**
-     * Constructor meant to take a char[][] returned by DungeonGen.generate(), or any other
-     * char[][] where '#' means a wall and anything else is a walkable tile. If you only have
-     * a map that uses box-drawing characters, use DungeonUtility.linesToHashes() to get a
-     * map that can be used here. This constructor specifies a distance measurement.
-     *
-     * @param level
-     * @param measurement
-     */
-    public SoundMap(final char[][] level, Measurement measurement) {
-        rng = new RNG(new LightRNG());
-        this.measurement = measurement;
-        alerted = new OrderedMap<>();
-        fresh = new OrderedMap<>();
-        sounds = new OrderedMap<>();
-        initialize(level);
-    }
-
-    /**
-     * Used to initialize or re-initialize a SoundMap that needs a new PhysicalMap because it either wasn't given
-     * one when it was constructed, or because the contents of the terrain have changed permanently.
-     * @param level
-     * @return
-     */
-    public SoundMap initialize(final double[][] level) {
-        width = level.length;
-        height = level[0].length;
-        gradientMap = new double[width][height];
-        physicalMap = new double[width][height];
-        for (int y = 0; y < height; y++) {
-            for (int x = 0; x < width; x++) {
-                gradientMap[x][y] = level[x][y];
-                physicalMap[x][y] = level[x][y];
-            }
-        }
-        initialized = true;
-        return this;
-    }
-
-    /**
-     * Used to initialize or re-initialize a SoundMap that needs a new PhysicalMap because it either wasn't given
-     * one when it was constructed, or because the contents of the terrain have changed permanently.
-     * @param level
-     * @return
-     */
-    public SoundMap initialize(final char[][] level) {
-        width = level.length;
-        height = level[0].length;
-        gradientMap = new double[width][height];
-        physicalMap = new double[width][height];
-        for (int y = 0; y < height; y++) {
-            for (int x = 0; x < width; x++) {
-                double t = (level[x][y] == '#') ? WALL : SILENT;
-                gradientMap[x][y] = t;
-                physicalMap[x][y] = t;
-            }
-        }
-        initialized = true;
-        return this;
-    }
-
-    /**
-     * Used to initialize or re-initialize a SoundMap that needs a new PhysicalMap because it either wasn't given
-     * one when it was constructed, or because the contents of the terrain have changed permanently. This
-     * initialize() method allows you to specify an alternate wall char other than the default character, '#' .
-     * @param level
-     * @param alternateWall
-     * @return
-     */
-    public SoundMap initialize(final char[][] level, char alternateWall) {
-        width = level.length;
-        height = level[0].length;
-        gradientMap = new double[width][height];
-        physicalMap = new double[width][height];
-        for (int y = 0; y < height; y++) {
-            for (int x = 0; x < width; x++) {
-                double t = (level[x][y] == alternateWall) ? WALL : SILENT;
-                gradientMap[x][y] = t;
-                physicalMap[x][y] = t;
-            }
-        }
-        initialized = true;
-        return this;
-    }
-
-    /**
-     * Resets the gradientMap to its original value from physicalMap. Does not remove sounds (they will still affect
-     * scan() normally).
-     */
-    public void resetMap() {
-            if(!initialized) return;
-        for (int y = 0; y < height; y++) {
-            for (int x = 0; x < width; x++) {
-                gradientMap[x][y] = physicalMap[x][y];
-            }
-        }
-    }
-
-    /**
-     * Resets this SoundMap to a state with no sounds, no alerted creatures, and no changes made to gradientMap
-     * relative to physicalMap.
-     */
-    public void reset() {
-        resetMap();
-        alerted.clear();
-        fresh.clear();
-        sounds.clear();
-    }
-
-    /**
-     * Marks a cell as producing a sound with the given loudness; this can be placed on a wall or unreachable area,
-     * but that may cause the sound to be un-hear-able. A sound emanating from a cell on one side of a 2-cell-thick
-     * wall will only radiate sound on one side, which can be used for certain effects. A sound emanating from a cell
-     * in a 1-cell-thick wall will radiate on both sides.
-     * @param x
-     * @param y
-     * @param loudness The number of cells the sound should spread away using the current measurement.
-     */
-    public void setSound(int x, int y, double loudness) {
-        if(!initialized) return;
-        Coord pt = Coord.get(x, y);
-        if(sounds.containsKey(pt) && sounds.get(pt) >= loudness)
-            return;
-        sounds.put(pt, loudness);
-    }
-
-    /**
-     * Marks a cell as producing a sound with the given loudness; this can be placed on a wall or unreachable area,
-     * but that may cause the sound to be un-hear-able. A sound emanating from a cell on one side of a 2-cell-thick
-     * wall will only radiate sound on one side, which can be used for certain effects. A sound emanating from a cell
-     * in a 1-cell-thick wall will radiate on both sides.
-     * @param pt
-     * @param loudness The number of cells the sound should spread away using the current measurement.
-     */
-    public void setSound(Coord pt, double loudness) {
-        if(!initialized) return;
-        if(sounds.containsKey(pt) && sounds.get(pt) >= loudness)
-            return;
-        sounds.put(pt, loudness);
-    }
-
-    /**
-     * If a sound is being produced at a given (x, y) location, this removes it.
-     * @param x
-     * @param y
-     */
-    public void removeSound(int x, int y) {
-        if(!initialized) return;
-        Coord pt = Coord.get(x, y);
-        if(sounds.containsKey(pt))
-            sounds.remove(pt);
-    }
-
-    /**
-     * If a sound is being produced at a given location (a Coord), this removes it.
-     * @param pt
-     */
-    public void removeSound(Coord pt) {
-        if(!initialized) return;
-        if(sounds.containsKey(pt))
-            sounds.remove(pt);
-    }
-
-    /**
-     * Marks a specific cell in gradientMap as a wall, which makes sounds potentially unable to pass through it.
-     * @param x
-     * @param y
-     */
-    public void setOccupied(int x, int y) {
-        if(!initialized) return;
-        gradientMap[x][y] = WALL;
-    }
-
-    /**
-     * Reverts a cell to the value stored in the original state of the level as known by physicalMap.
-     * @param x
-     * @param y
-     */
-    public void resetCell(int x, int y) {
-        if(!initialized) return;
-        gradientMap[x][y] = physicalMap[x][y];
-    }
-
-    /**
-     * Reverts a cell to the value stored in the original state of the level as known by physicalMap.
-     * @param pt
-     */
-    public void resetCell(Coord pt) {
-        if(!initialized) return;
-        gradientMap[pt.x][pt.y] = physicalMap[pt.x][pt.y];
-    }
-
-    /**
-     * Used to remove all sounds.
-     */
-    public void clearSounds() {
-        if(!initialized) return;
-        sounds.clear();
-    }
-
-    protected void setFresh(int x, int y, double counter) {
-        if(!initialized) return;
-        gradientMap[x][y] = counter;
-        fresh.put(Coord.get(x, y), counter);
-    }
-
-    protected void setFresh(final Coord pt, double counter) {
-        if(!initialized) return;
-        gradientMap[pt.x][pt.y] = counter;
-        fresh.put(Coord.get(pt.x, pt.y), counter);
-    }
-
-    /**
-     * Recalculate the sound map and return it. Cells that were marked as goals with setSound will have
-     * a value greater than 0 (higher numbers are louder sounds), the cells adjacent to sounds will have a value 1 less
-     * than the loudest adjacent cell, and cells progressively further from sounds will have a value equal to the
-     * loudness of the nearest sound minus the distance from it, to a minimum of 0. The exceptions are walls,
-     * which will have a value defined by the WALL constant in this class. Like sound itself, the sound map
-     * allows some passage through walls; specifically, 1 cell thick of wall can be passed through, with reduced
-     * loudness, before the fill cannot go further. This uses the current measurement.
-     *
-     * @return A 2D double[width][height] using the width and height of what this knows about the physical map.
-     */
-    public double[][] scan() {
-        if(!initialized) return null;
-
-        for (Map.Entry<Coord, Double> entry : sounds.entrySet()) {
-            gradientMap[entry.getKey().x][entry.getKey().y] = entry.getValue();
-            if(fresh.containsKey(entry.getKey()) && fresh.get(entry.getKey()) > entry.getValue())
-            {
-            }
-            else
-            {
-                fresh.put(entry.getKey(), entry.getValue());
-            }
-
-        }
-        int numAssigned = fresh.size();
-
-        Direction[] dirs = (measurement == Measurement.MANHATTAN) ? Direction.CARDINALS : Direction.OUTWARDS;
-
-        while (numAssigned > 0) {
-            numAssigned = 0;
-            OrderedMap<Coord, Double> fresh2 = new OrderedMap<>(fresh.size());
-            fresh2.putAll(fresh);
-            fresh.clear();
-
-            for (Map.Entry<Coord, Double> cell : fresh2.entrySet()) {
-                if(cell.getValue() <= 1) //We shouldn't assign values lower than 1.
-                    continue;
-                for (int d = 0; d < dirs.length; d++) {
-                    Coord adj = cell.getKey().translate(dirs[d].deltaX, dirs[d].deltaY);
-                    if(adj.x < 0 || adj.x >= width || adj.y < 0 || adj.y >= height)
-                        continue;
-                    if(physicalMap[cell.getKey().x][cell.getKey().y] == WALL && physicalMap[adj.x][adj.y] == WALL)
-                        continue;
-                    if (gradientMap[cell.getKey().x][cell.getKey().y] > gradientMap[adj.x][adj.y] + 1) {
-                        double v = cell.getValue() - 1 - ((physicalMap[adj.x][adj.y] == WALL) ? 1 : 0);
-                        if (v > 0) {
-                            gradientMap[adj.x][adj.y] = v;
-                            fresh.put(Coord.get(adj.x, adj.y), v);
-                            ++numAssigned;
-                        }
-                    }
-                }
-            }
-        }
-
-        for (int y = 0; y < height; y++) {
-            for (int x = 0; x < width; x++) {
-                if (physicalMap[x][y] == WALL) {
-                    gradientMap[x][y] = WALL;
-                }
-            }
-        }
-
-        return gradientMap;
-    }
-
-    /**
-     * Scans the dungeon using SoundMap.scan, adding any positions in extraSounds to the group of known sounds before
-     * scanning.  The creatures passed to this function as a Set of Points will have the loudness of all sounds at
-     * their position put as the value in alerted corresponding to their Coord position.
-     *
-     * @param creatures
-     * @param extraSounds
-     * @return
-     */
-    public OrderedMap<Coord, Double> findAlerted(Set<Coord> creatures, Map<Coord, Double> extraSounds) {
-        if(!initialized) return null;
-        alerted = new OrderedMap<>(creatures.size());
-
-        resetMap();
-        for (Map.Entry<Coord, Double> sound : extraSounds.entrySet()) {
-            setSound(sound.getKey(), sound.getValue());
-        }
-        scan();
-        for(Coord critter : creatures)
-        {
-            if(critter.x < 0 || critter.x >= width || critter.y < 0 || critter.y >= height)
-                continue;
-            alerted.put(Coord.get(critter.x, critter.y), gradientMap[critter.x][critter.y]);
-        }
-        return alerted;
-    }
-}

+ 0 - 894
squidlib-util/src/main/java/squidpony/squidgrid/SpatialMap.java

@@ -1,894 +0,0 @@
-package squidpony.squidgrid;
-
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.OrderedMap;
-import squidpony.squidmath.OrderedSet;
-import squidpony.squidmath.RNG;
-
-import java.util.*;
-
-/**
- * A data structure that seems to be re-implemented often for games, this associates Coord positions and generic I
- * identities with generic E elements. You can get an element from a SpatialMap with either an identity or a position,
- * change the position of an element without changing its value or identity, modify an element given its identity and
- * a new value, and perform analogues to most of the features of the Map interface, though this does not implement Map
- * because it essentially has two key types and one value type. You can also iterate through the values in insertion
- * order, where insertion order should be stable even when elements are moved or modified (the relevant key is the
- * identity, which is never changed in this class). Uses two OrderedMap fields internally.
- * Created by Tommy Ettinger on 1/2/2016.
- */
-public class SpatialMap<I, E> implements Iterable<E> {
-
-    public static class SpatialTriple<I,E>
-    {
-        public Coord position;
-        public I id;
-        public E element;
-
-        public SpatialTriple()
-        {
-            position = Coord.get(0,0);
-            id = null;
-            element = null;
-        }
-        public SpatialTriple(Coord position, I id, E element) {
-            this.position = position;
-            this.id = id;
-            this.element = element;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-
-            SpatialTriple<?, ?> that = (SpatialTriple<?, ?>) o;
-
-            if (position != null ? !position.equals(that.position) : that.position != null) return false;
-            if (id != null ? !id.equals(that.id) : that.id != null) return false;
-            return element != null ? element.equals(that.element) : that.element == null;
-
-        }
-
-        @Override
-        public int hashCode() {
-            int result = position != null ? position.hashCode() : 0;
-            result = 31 * result + (id != null ? id.hashCode() : 0);
-            result = 31 * result + (element != null ? element.hashCode() : 0);
-            return result;
-        }
-    }
-
-    protected OrderedMap<I, SpatialTriple<I, E>> itemMapping;
-    protected OrderedMap<Coord, SpatialTriple<I, E>> positionMapping;
-
-    /**
-     * Constructs a SpatialMap with capacity 32.
-     */
-    public SpatialMap()
-    {
-        itemMapping = new OrderedMap<>(32);
-        positionMapping = new OrderedMap<>(32);
-    }
-
-    /**
-     * Constructs a SpatialMap with the given capacity
-     * @param capacity the capacity for each of the internal OrderedMaps
-     */
-    public SpatialMap(int capacity)
-    {
-        itemMapping = new OrderedMap<>(capacity);
-        positionMapping = new OrderedMap<>(capacity);
-    }
-
-    /**
-     * Constructs a SpatialMap given arrays of Coord, identity, and element; all 3 arrays should have the same length,
-     * since this will use only up to the minimum length of these arrays for how many it adds. Each unique id will be
-     * added with the corresponding element at the corresponding Coord position if that position is not already filled.
-     * @param coords a starting array of Coord positions; indices here correspond to the other parameters
-     * @param ids a starting array of identities; indices here correspond to the other parameters
-     * @param elements a starting array of elements; indices here correspond to the other parameters
-     */
-    public SpatialMap(Coord[] coords, I[] ids, E[] elements)
-    {
-        itemMapping = new OrderedMap<>(
-                Math.min(coords.length, Math.min(ids.length, elements.length)));
-        positionMapping = new OrderedMap<>(
-                Math.min(coords.length, Math.min(ids.length, elements.length)));
-
-        for (int i = 0; i < coords.length && i < ids.length && i < elements.length; i++) {
-            add(coords[i], ids[i], elements[i]);
-        }
-    }
-
-    /**
-     * Constructs a SpatialMap given collections of Coord, identity, and element; all 3 collections should have the same
-     * length, since this will use only up to the minimum length of these collections for how many it adds. Each unique
-     * id will be added with the corresponding element at the corresponding Coord position if that position is not
-     * already filled.
-     * @param coords a starting collection of Coord positions; indices here correspond to the other parameters
-     * @param ids a starting collection of identities; indices here correspond to the other parameters
-     * @param elements a starting collection of elements; indices here correspond to the other parameters
-     */
-    public SpatialMap(Collection<Coord> coords, Collection<I> ids, Collection<E> elements)
-    {
-        itemMapping = new OrderedMap<>(
-                Math.min(coords.size(), Math.min(ids.size(), elements.size())));
-        positionMapping = new OrderedMap<>(
-                Math.min(coords.size(), Math.min(ids.size(), elements.size())));
-        if(itemMapping.size() <= 0)
-            return;
-        Iterator<Coord> cs = coords.iterator();
-        Iterator<I> is = ids.iterator();
-        Iterator<E> es = elements.iterator();
-        Coord c = cs.next();
-        I i = is.next();
-        E e = es.next();
-        for (; cs.hasNext() && is.hasNext() && es.hasNext(); c = cs.next(), i = is.next(), e = es.next()) {
-            add(c, i, e);
-        }
-    }
-
-    /**
-     * Adds a new element with the given identity and Coord position. If the position is already occupied by an element
-     * in this data structure, does nothing. If the identity is already used, this also does nothing. If the identity
-     * and position are both unused, this adds element to the data structure.
-     * <br>
-     * You should strongly avoid calling remove() and add() to change an element; prefer modify() and move().
-     * @param coord the Coord position to place the element at; should be empty
-     * @param id the identity to associate the element with; should be unused
-     * @param element the element to add
-     */
-    public void add(Coord coord, I id, E element)
-    {
-        if(itemMapping.containsKey(id))
-            return;
-        if(!positionMapping.containsKey(coord))
-        {
-            SpatialTriple<I, E> triple = new SpatialTriple<>(coord, id, element);
-            itemMapping.put(id, triple);
-            positionMapping.put(coord, triple);
-        }
-    }
-
-    /**
-     * Inserts a new element with the given identity and Coord position, potentially overwriting an existing element.
-     * <br>
-     * If you want to alter an existing element, use modify() or move().
-     * @param coord the Coord position to place the element at; should be empty
-     * @param id the identity to associate the element with; should be unused
-     * @param element the element to add
-     */
-    public void put(Coord coord, I id, E element)
-    {
-        SpatialTriple<I, E> triple = new SpatialTriple<>(coord, id, element);
-        itemMapping.remove(id);
-        positionMapping.remove(coord);
-        itemMapping.put(id, triple);
-        positionMapping.put(coord, triple);
-    }
-
-    /**
-     * Inserts a SpatialTriple into this SpatialMap without changing it, potentially overwriting an existing element.
-     * SpatialTriple objects can be obtained by the triples() or tripleIterator() methods, and can also be constructed
-     * on their own.
-     * <br>
-     * If you want to alter an existing element, use modify() or move().
-     * @param triple a SpatialTriple (an inner class of SpatialMap) with the same type parameters as this class
-     */
-    public void put(SpatialTriple<I, E> triple)
-    {
-        itemMapping.remove(triple.id);
-        positionMapping.remove(triple.position);
-        itemMapping.put(triple.id, triple);
-        positionMapping.put(triple.position, triple);
-    }
-
-    /**
-     * Changes the element's value associated with id. The key id should exist before calling this; if there is no
-     * matching id, this returns null.
-     * @param id the identity of the element to modify
-     * @param newValue the element value to replace the previous element with.
-     * @return the previous element value associated with id
-     */
-    public E modify(I id, E newValue)
-    {
-        SpatialTriple<I, E> gotten = itemMapping.get(id);
-        if(gotten != null) {
-            E previous = gotten.element;
-            gotten.element = newValue;
-            return previous;
-        }
-        return null;
-    }
-    /**
-     * Changes the element's value associated with pos. The key pos should exist before calling this; if there is no
-     * matching position, this returns null.
-     * @param pos the position of the element to modify
-     * @param newValue the element value to replace the previous element with.
-     * @return the previous element value associated with id
-     */
-    public E positionalModify(Coord pos, E newValue)
-    {
-        SpatialTriple<I, E> gotten = positionMapping.get(pos);
-        if(gotten != null) {
-            E previous = gotten.element;
-            gotten.element = newValue;
-            return previous;
-        }
-        return null;
-    }
-
-    /**
-     * Move an element from one position to another; moves whatever is at the Coord position previous to the new Coord
-     * position target. The element will not be present at its original position if target is unoccupied, but nothing
-     * will change if target is occupied.
-     * @param previous the starting Coord position of an element to move
-     * @param target the Coord position to move the element to
-     * @return the moved element if movement was successful or null otherwise
-     */
-    public E move(Coord previous, Coord target)
-    {
-        if(positionMapping.containsKey(previous) && !positionMapping.containsKey(target)) {
-            SpatialTriple<I, E> gotten = positionMapping.remove(previous);
-            gotten.position = target;
-            positionMapping.put(target, gotten);
-            return gotten.element;
-        }
-        return null;
-    }
-
-    /**
-     * Move an element, picked by its identity, to a new Coord position. Finds the element using only the id, and does
-     * not need the previous position. The target position must be empty for this to move successfully, and the id must
-     * exist in this data structure for this to move anything.
-     * @param id the identity of the element to move
-     * @param target the Coord position to move the element to
-     * @return the moved element if movement was successful or null otherwise
-     */
-    public E move(I id, Coord target)
-    {
-        if(itemMapping.containsKey(id) && !positionMapping.containsKey(target)) {
-            SpatialTriple<I, E> gotten = itemMapping.get(id);
-            positionMapping.remove(gotten.position);
-            gotten.position = target;
-            positionMapping.put(target, gotten);
-            return gotten.element;
-        }
-        return null;
-    }
-
-    /**
-     * Removes the element at the given position from all storage in this data structure.
-     * <br>
-     * You should strongly avoid calling remove() and add() to change an element; prefer modify() and move().
-     * @param coord the position of the element to remove
-     * @return the value of the element that was removed or null if nothing was present at the position
-     */
-    public E remove(Coord coord)
-    {
-        SpatialTriple<I, E> gotten = positionMapping.remove(coord);
-        if(gotten != null) {
-            itemMapping.remove(gotten.id);
-            return gotten.element;
-        }
-        return null;
-    }
-    /**
-     * Removes the element with the given identity from all storage in this data structure.
-     * <br>
-     * You should strongly avoid calling remove() and add() to change an element; prefer modify() and move().
-     * @param id the identity of the element to remove
-     * @return the value of the element that was removed or null if nothing was present at the position
-     */
-    public E remove(I id)
-    {
-        SpatialTriple<I, E> gotten = itemMapping.remove(id);
-        if(gotten != null) {
-            positionMapping.remove(gotten.position);
-            return gotten.element;
-        }
-        return null;
-    }
-
-    /**
-     * Checks whether this contains the given element. Slower than containsKey and containsPosition (linear time).
-     * @param o an Object that should be an element if you expect this to possibly return true
-     * @return true if o is contained as an element in this data structure
-     */
-    public boolean containsValue(Object o)
-    {
-        if(o == null)
-        {
-            for(SpatialTriple<I,E> v : itemMapping.values())
-            {
-                if(v != null && v.element == null)
-                    return true;
-            }
-        }
-        else {
-            for (SpatialTriple<I, E> v : itemMapping.values()) {
-                if (v != null && v.element != null && v.element.equals(o))
-                    return true;
-            }
-        }
-        return false;
-    }
-    /**
-     * Checks whether this contains the given identity key.
-     * @param o an Object that should be of the generic I type if you expect this to possibly return true
-     * @return true if o is an identity key that can be used with this data structure
-     */
-    public boolean containsKey(Object o)
-    {
-        return itemMapping.containsKey(o);
-    }
-    /**
-     * Checks whether this contains anything at the given position.
-     * @param o an Object that should be a Coord if you expect this to possibly return true
-     * @return true if o is a Coord that is associated with some element in this data structure
-     */
-    public boolean containsPosition(Object o)
-    {
-        return positionMapping.containsKey(o);
-    }
-
-    /**
-     * Gets the element at the given Coord position.
-     * @param c the position to get an element from
-     * @return the element if it exists or null otherwise
-     */
-    public E get(Coord c)
-    {
-        SpatialTriple<I, E> gotten = positionMapping.get(c);
-        if(gotten != null)
-            return gotten.element;
-        return null;
-    }
-
-    /**
-     * Gets the element with the given identity.
-     * @param i the identity of the element to get
-     * @return the element if it exists or null otherwise
-     */
-    public E get(I i)
-    {
-        SpatialTriple<I, E> gotten = itemMapping.get(i);
-        if(gotten != null)
-            return gotten.element;
-        return null;
-    }
-
-    /**
-     * Gets the position of the element with the given identity.
-     * @param i the identity of the element to get a position from
-     * @return the position of the element if it exists or null otherwise
-     */
-    public Coord getPosition(I i)
-    {
-        SpatialTriple<I, E> gotten = itemMapping.get(i);
-        if(gotten != null)
-            return gotten.position;
-        return null;
-    }
-
-    /**
-     * Gets the identity of the element at the given Coord position.
-     * @param c the position to get an identity from
-     * @return the identity of the element if it exists at the given position or null otherwise
-     */
-    public I getIdentity(Coord c)
-    {
-        SpatialTriple<I, E> gotten = positionMapping.get(c);
-        if(gotten != null)
-            return gotten.id;
-        return null;
-    }
-
-    /**
-     * Get a Set of all positions used for values in this data structure, returning a OrderedSet (defensively copying
-     * the key set used internally) for its stable iteration order.
-     * @return a OrderedSet of Coord corresponding to the positions present in this data structure.
-     */
-    public OrderedSet<Coord> positions()
-    {
-        return new OrderedSet<>(positionMapping.keySet());
-    }
-    /**
-     * Get a Set of all identities used for values in this data structure, returning a OrderedSet (defensively
-     * copying the key set used internally) for its stable iteration order.
-     * @return a OrderedSet of I corresponding to the identities present in this data structure.
-     */
-    public OrderedSet<I> identities()
-    {
-        return new OrderedSet<>(itemMapping.keySet());
-    }
-
-    /**
-     * Gets all data stored in this as a collection of values similar to Map.Entry, but containing a Coord, I, and E
-     * value for each entry, in insertion order. The type is SpatialTriple, defined in a nested class.
-     * @return a Collection of SpatialTriple of I, E
-     */
-    public Collection<SpatialTriple<I, E>> triples()
-    {
-        return itemMapping.values();
-    }
-
-    /**
-     * Given an Iterable (such as a List, Set, or other Collection) of Coord, gets all elements in this SpatialMap that
-     * share a position with one of the Coord objects in positions and returns them as an ArrayList of elements.
-     * @param positions an Iterable (such as a List or Set) of Coord
-     * @return an ArrayList, possibly empty, of elements that share a position with a Coord in positions
-     */
-    public ArrayList<E> getManyPositions(Iterable<Coord> positions)
-    {
-        ArrayList<E> gotten = new ArrayList<>();
-        SpatialTriple<I, E> ie;
-        for(Coord p : positions)
-        {
-            if((ie = positionMapping.get(p)) != null)
-                gotten.add(ie.element);
-        }
-        return gotten;
-    }
-
-    /**
-     * Given an Iterable (such as a List, Set, or other Collection) of I, gets all elements in this SpatialMap that
-     * share an identity with one of the I objects in identities and returns them as an ArrayList of elements.
-     * @param identities an Iterable (such as a List or Set) of I
-     * @return an ArrayList, possibly empty, of elements that share an Identity with an I in identities
-     */
-    public ArrayList<E> getManyIdentities(Iterable<I> identities)
-    {
-        ArrayList<E> gotten = new ArrayList<>();
-        SpatialTriple<I, E> ie;
-        for(I i : identities)
-        {
-            if((ie = itemMapping.get(i)) != null)
-                gotten.add(ie.element);
-        }
-        return gotten;
-    }
-
-    /**
-     * Given an array of Coord, gets all elements in this SpatialMap that share a position with one of the Coord objects
-     * in positions and returns them as an ArrayList of elements.
-     * @param positions an array of Coord
-     * @return an ArrayList, possibly empty, of elements that share a position with a Coord in positions
-     */
-    public ArrayList<E> getManyPositions(Coord[] positions)
-    {
-        ArrayList<E> gotten = new ArrayList<>(positions.length);
-        SpatialTriple<I, E> ie;
-        for(Coord p : positions)
-        {
-            if((ie = positionMapping.get(p)) != null)
-                gotten.add(ie.element);
-        }
-        return gotten;
-    }
-    /**
-     * Given an array of I, gets all elements in this SpatialMap that share an identity with one of the I objects in
-     * identities and returns them as an ArrayList of elements.
-     * @param identities an array of I
-     * @return an ArrayList, possibly empty, of elements that share an Identity with an I in identities
-     */
-    public ArrayList<E> getManyIdentities(I[] identities)
-    {
-        ArrayList<E> gotten = new ArrayList<>(identities.length);
-        SpatialTriple<I, E> ie;
-        for(I i : identities)
-        {
-            if((ie = itemMapping.get(i)) != null)
-                gotten.add(ie.element);
-        }
-        return gotten;
-    }
-
-    public E randomElement(RNG rng)
-    {
-        if(itemMapping.isEmpty())
-            return null;
-        return itemMapping.randomValue(rng).element;
-    }
-
-    public Coord randomPosition(RNG rng)
-    {
-        if(positionMapping.isEmpty())
-            return null;
-        return positionMapping.randomKey(rng);
-    }
-    public I randomIdentity(RNG rng)
-    {
-        if(itemMapping.isEmpty())
-            return null;
-        return itemMapping.randomKey(rng);
-    }
-
-    public SpatialTriple<I, E> randomEntry(RNG rng)
-    {
-        if(itemMapping.isEmpty())
-            return null;
-        return itemMapping.randomValue(rng);
-    }
-
-    /**
-     * Given the size and position of a rectangular area, creates a new SpatialMap from this one that refers only to the
-     * subsection of this SpatialMap shared with the rectangular area. Will not include any elements from this
-     * SpatialMap with positions beyond the bounds of the given rectangular area, and will include all elements from
-     * this that are in the area.
-     * @param x the minimum x-coordinate of the rectangular area
-     * @param y the minimum y-coordinate of the rectangular area
-     * @param width the total width of the rectangular area
-     * @param height the total height of the rectangular area
-     * @return a new SpatialMap that refers to a subsection of this one
-     */
-    public SpatialMap<I, E> rectangleSection(int x, int y, int width, int height)
-    {
-        SpatialMap<I, E> next = new SpatialMap<>(positionMapping.size());
-        Coord tmp;
-        for(SpatialTriple<I, E> ie : positionMapping.values())
-        {
-            tmp = ie.position;
-            if(tmp.x >= x && tmp.y >= y && tmp.x + width > x && tmp.y + height > y)
-                next.put(ie);
-        }
-        return next;
-    }
-
-    /**
-     * Given the center position, Radius to determine measurement, and maximum distance from the center, creates a new
-     * SpatialMap from this one that refers only to the subsection of this SpatialMap shared with the area within the
-     * given distance from the center as measured by measurement. Will not include any elements from this SpatialMap
-     * with positions beyond the bounds of the given area, and will include all elements from this that are in the area.
-     * @param x the center x-coordinate of the area
-     * @param y the center y-coordinate of the area
-     * @param measurement a Radius enum, such as Radius.CIRCLE or Radius.DIAMOND, that calculates distance
-     * @param distance the maximum distance from the center to include in the area
-     * @return a new SpatialMap that refers to a subsection of this one
-     */
-    public SpatialMap<I, E> radiusSection(int x, int y, Radius measurement, int distance)
-    {
-        SpatialMap<I, E> next = new SpatialMap<>(positionMapping.size());
-        Coord tmp;
-        for(SpatialTriple<I, E> ie : positionMapping.values())
-        {
-            tmp = ie.position;
-            if(measurement.inRange(x, y, tmp.x, tmp.y, 0, distance))
-                next.put(ie);
-        }
-        return next;
-    }
-
-    /**
-     * Given the center position and maximum distance from the center, creates a new SpatialMap from this one that
-     * refers only to the subsection of this SpatialMap shared with the area within the given distance from the center,
-     * measured with Euclidean distance to produce a circle shape. Will not include any elements from this SpatialMap
-     * with positions beyond the bounds of the given area, and will include all elements from this that are in the area.
-     * @param x the center x-coordinate of the area
-     * @param y the center y-coordinate of the area
-     * @param radius the maximum distance from the center to include in the area, using Euclidean distance
-     * @return a new SpatialMap that refers to a subsection of this one
-     */
-    public SpatialMap<I, E> circleSection(int x, int y, int radius)
-    {
-        return radiusSection(x, y, Radius.CIRCLE, radius);
-    }
-
-    public void clear()
-    {
-        itemMapping.clear();
-        positionMapping.clear();
-    }
-    public boolean isEmpty()
-    {
-        return itemMapping.isEmpty();
-    }
-    public int size()
-    {
-        return itemMapping.size();
-    }
-    public Object[] toArray()
-    {
-        Object[] contents = itemMapping.values().toArray();
-        for (int i = 0; i < contents.length; i++) {
-            contents[i] = ((SpatialTriple<?,?>)contents[i]).element;
-        }
-        return contents;
-    }
-
-    /**
-     * Replaces the contents of the given array with the elements this holds, in insertion order, until either this
-     * data structure or the array has been exhausted.
-     * @param a the array to replace; should usually have the same length as this data structure's size.
-     * @return an array of elements that should be the same as the changed array originally passed as a parameter.
-     */
-    public E[] toArray(E[] a)
-    {
-        Collection<SpatialTriple<I,E>> contents = itemMapping.values();
-        int i = 0;
-        for (SpatialTriple<I,E> triple : contents) {
-            if(i < a.length)
-                a[i] = triple.element;
-            else
-                break;
-            i++;
-        }
-        return a;
-    }
-
-    /**
-     * Iterates through values in insertion order.
-     * @return an Iterator of generic type E
-     */
-    @Override
-    public Iterator<E> iterator()
-    {
-        final Iterator<SpatialTriple<I, E>> it = itemMapping.values().iterator();
-        return new Iterator<E>() {
-            @Override
-            public boolean hasNext() {
-                return it.hasNext();
-            }
-
-            @Override
-            public E next() {
-                SpatialTriple<I,E> triple = it.next();
-                if(triple != null)
-                    return triple.element;
-                return null;
-            }
-
-            @Override
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
-    }
-
-    /**
-     * Iterates through values similar to Map.Entry, but containing a Coord, I, and E value for each entry, in insertion
-     * order. The type is SpatialTriple, defined in a nested class.
-     * @return an Iterator of SpatialTriple of I, E
-     */
-    public Iterator<SpatialTriple<I, E>> tripleIterator()
-    {
-        return itemMapping.values().iterator();
-    }
-    /**
-     * Iterates through positions in insertion order; has less predictable iteration order than the other iterators.
-     * @return an Iterator of Coord
-     */
-    public Iterator<Coord> positionIterator()
-    {
-        return positionMapping.keySet().iterator();
-    }
-    /**
-     * Iterates through identity keys in insertion order.
-     * @return an Iterator of generic type I
-     */
-    public Iterator<I> identityIterator()
-    {
-        return itemMapping.keySet().iterator();
-    }
-
-    /**
-     * Iterates through positions in a rectangular region (starting at a minimum of x, y and extending to the specified
-     * width and height) in left-to-right, then top-to-bottom order (the same as reading a page of text).
-     * Any Coords this returns should be viable arguments to get() if you want a corresponding element.
-     * @return an Iterator of Coord
-     */
-    public Iterator<Coord> rectanglePositionIterator(int x, int y, int width, int height)
-    {
-        return new RectangularIterator(x, y, width, height);
-    }
-
-    /**
-     * Iterates through positions in a region defined by a Radius (starting at a minimum of x - distance, y - distance
-     * and extending to x + distance, y + distance but skipping any positions where the Radius considers a position
-     * further from x, y than distance) in left-to-right, then top-to-bottom order (the same as reading a page of text).
-     * You can use Radius.SQUARE to make a square region (which could also be made with rectanglePositionIterator()),
-     * Radius.DIAMOND to make a, well, diamond-shaped region, or Radius.CIRCLE to make a circle (which could also be
-     * made with circlePositionIterator).
-     * Any Coords this returns should be viable arguments to get() if you want a corresponding element.
-     * @return an Iterator of Coord
-     */
-    public Iterator<Coord> radiusPositionIterator(int x, int y, Radius measurement, int distance)
-    {
-        return new RadiusIterator(x, y, measurement, distance);
-    }
-    /**
-     * Iterates through positions in a circular region (starting at a minimum of x - distance, y - distance and
-     * extending to x + distance, y + distance but skipping any positions where the Euclidean distance from x,y to the
-     * position is more than distance) in left-to-right, then top-to-bottom order (the same as reading a page of text).
-     * Any Coords this returns should be viable arguments to get() if you want a corresponding element.
-     * @return an Iterator of Coord
-     */
-    public Iterator<Coord> circlePositionIterator(int x, int y, int distance)
-    {
-        return new RadiusIterator(x, y, Radius.CIRCLE, distance);
-    }
-
-    private class RectangularIterator implements Iterator<Coord>
-    {
-        int x, y, width, height, idx,
-                poolWidth = Coord.getCacheWidth(), poolHeight = Coord.getCacheHeight();
-        Set<Coord> positions;
-        Coord temp;
-        RectangularIterator(int x, int y, int width, int height)
-        {
-            this.x = x;
-            this.y = y;
-            this.width = width;
-            this.height = height;
-            idx = -1;
-            positions = positionMapping.keySet();
-        }
-
-        @Override
-        public boolean hasNext() {
-            if (idx < width * height - 1) {
-                Coord t2;
-                int n = idx;
-                do {
-                    n = findNext(n);
-                    if (idx < 0)
-                        return n >= 0;
-                    else {
-                        if(x + n % width >= 0 && x + n % width < poolWidth
-                                && y + n / width >= 0 && y + n / width < poolHeight)
-                            t2 = Coord.get(x + n % width, y + n / width);
-                        else t2 = Coord.get(-1, -1);
-                    }
-                } while (!positions.contains(t2));
-				/* Not done && has next */
-                return n >= 0;
-            }
-            return false;
-        }
-
-
-        @Override
-        public Coord next() {
-            do {
-                idx = findNext(idx);
-                if (idx < 0)
-                    throw new NoSuchElementException();
-                if(x + idx % width >= 0 && x + idx % width < poolWidth
-                        && y + idx / width >= 0 && y + idx / width < poolHeight)
-                    temp = Coord.get(x + idx % width, y + idx / width);
-                else temp = Coord.get(-1, -1);
-            } while (!positions.contains(temp));
-            return temp;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-        private int findNext(final int idx) {
-            if (idx < 0) {
-				/* First iteration */
-                return 0;
-            } else {
-                if (idx >= width * height - 1)
-                {
-					/* Done iterating */
-                    return -1;
-                } else {
-                    return idx + 1;
-                }
-            }
-        }
-    }
-
-    private class RadiusIterator implements Iterator<Coord>
-    {
-        int x, y, width, height, distance, idx,
-                poolWidth = Coord.getCacheWidth(), poolHeight = Coord.getCacheHeight();
-        Set<Coord> positions;
-        Coord temp;
-        Radius measurement;
-        RadiusIterator(int x, int y, Radius measurement, int distance)
-        {
-            this.x = x;
-            this.y = y;
-            width = 1 + distance * 2;
-            height = 1 + distance * 2;
-            this.distance = distance;
-            this.measurement = measurement;
-            idx = -1;
-            positions = positionMapping.keySet();
-        }
-
-        @Override
-        public boolean hasNext() {
-            if (idx < width * height - 1) {
-                Coord t2;
-                int n = idx;
-                do {
-                    n = findNext(n);
-                    if (idx < 0)
-                        return n >= 0;
-                    else {
-                        if(x - distance + n % width >= 0 && x - distance + n % width < poolWidth
-                                && y - distance + n / width >= 0 && y - distance + n / width < poolHeight &&
-                                measurement.radius(x, y,
-                                        x - distance + n % width, y - distance + n / width) <= distance)
-                            t2 = Coord.get(x - distance + n % width, y - distance + n / width);
-                        else t2 = Coord.get(-1, -1);
-                    }
-                } while (!positions.contains(t2));
-				/* Not done && has next */
-                return n >= 0;
-            }
-            return false;
-        }
-
-
-        @Override
-        public Coord next() {
-            do {
-                idx = findNext(idx);
-                if (idx < 0)
-                    throw new NoSuchElementException();
-                if(x - distance + idx % width >= 0 && x - distance + idx % width < poolWidth
-                        && y - distance + idx / width >= 0 && y - distance + idx / width < poolHeight &&
-                        measurement.radius(x, y,
-                                x - distance + idx % width, y - distance + idx / width) <= distance)
-                    temp = Coord.get(x - distance + idx % width, y - distance + idx / width);
-                else temp = Coord.get(-1, -1);
-            } while (!positions.contains(temp));
-            return temp;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-        private int findNext(final int idx) {
-            if (idx < 0) {
-				/* First iteration */
-                return 0;
-            } else {
-                if (idx >= width * height - 1)
-                {
-					/* Done iterating */
-                    return -1;
-                } else {
-                    return idx + 1;
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        SpatialMap<?, ?> that = (SpatialMap<?, ?>) o;
-
-        if (itemMapping != null ? !itemMapping.equals(that.itemMapping) : that.itemMapping != null) return false;
-        return positionMapping != null ? positionMapping.equals(that.positionMapping) : that.positionMapping == null;
-
-    }
-
-    @Override
-    public int hashCode() {
-        int result = itemMapping != null ? itemMapping.hashCode() : 0;
-        result = 31 * result + (positionMapping != null ? positionMapping.hashCode() : 0);
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "SpatialMap{" +
-                "itemMapping=" + itemMapping +
-                ", positionMapping=" + positionMapping +
-                '}';
-    }
-
-}

+ 0 - 247
squidlib-util/src/main/java/squidpony/squidgrid/Splash.java

@@ -1,247 +0,0 @@
-package squidpony.squidgrid;
-
-import squidpony.squidgrid.mapping.DungeonUtility;
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.RNG;
-
-import java.util.*;
-
-/**
- * A alternative to {@link Spill}, whose purpose is to have a simpler API. You
- * can specify the characters that are impassable (in other words: that should
- * not be spilled on) using {@link #addImpassableChar(char)} and
- * {@link #removeImpassableChar(char)}. By default the set of impassable characters
- * is {@code '#'}.
- * 
- * @author smelC
- * 
- * @see Spill An alternative implementation of spilling.
- */
-public class Splash {
-
-	private static Splash splashCache = null;
-	private static int splashHash = -1;
-	protected final Set<Character> impassable;
-
-	/**
-	 * A fresh instance, whose only impassable character is '#'.
-	 */
-	public Splash() {
-		this.impassable = new HashSet<>();
-		/* The default */
-		addImpassableChar('#');
-	}
-	/**
-	 * A fresh instance, adding the chars in blocked to the set of impassable characters,
-	 * then also adding '#' if it isn't present. You can remove '#' with
-	 * {@link #removeImpassableChar(char)} if you use '#' to mean something non-blocking.
-	 */
-	public Splash(Set<Character> blocked) {
-		this.impassable = new HashSet<>(blocked);
-		/* The default */
-		addImpassableChar('#');
-	}
-
-	/**
-	 * Adds {@code c} to the set of impassable characters.
-	 * 
-	 * @param c
-	 *            The character to add.
-	 */
-	public void addImpassableChar(char c) {
-		this.impassable.add(c);
-	}
-
-	/**
-	 * Removes {@code c} from the set of impassable characters.
-	 * 
-	 * @param c
-	 *            The character to remove.
-	 * @return Whether it was in there.
-	 */
-	public boolean removeImpassableChar(char c) {
-		return this.impassable.remove(c);
-	}
-
-	/**
-	 * @param rng used to randomize the floodfill
-	 * @param level char 2D array with x, y indices for the dungeon/map level
-	 * @param start
-	 *            Where the spill should start. It should be passable, otherwise
-	 *            an empty list gets returned. Consider using
-	 *            {@link DungeonUtility#getRandomCell(RNG, char[][], Set, int)}
-	 *            to find it.
-	 * @param volume
-	 *            The number of cells to spill on.
-	 * @param drunks
-	 *            The ratio of drunks to use to make the splash more realistic.
-	 *            Like for dungeon generation, if greater than 0, drunk walkers
-	 *            will remove the splash's margins, to make it more realistic.
-	 *            You don't need that if you're doing a splash that is bounded
-	 *            by walls, because the fill will be realistic. If you're doing
-	 *            a splash that isn't bounded, use that for its borders not to
-	 *            be too square.
-	 * 
-	 *            <p>
-	 *            Useful values are 0, 1, and 2. Giving more will likely yield
-	 *            an empty result, on any decent map sizes.
-	 *            </p>
-	 * @return The spill. It is a list of coordinates (containing {@code start})
-	 *         valid in {@code level} that are all adjacent and whose symbol is
-	 *         passable. If non-empty, this is guaranteed to be an
-	 *         {@link ArrayList}.
-	 */
-	public List<Coord> spill(RNG rng, char[][] level, Coord start, int volume, int drunks) {
-		if (!DungeonUtility.inLevel(level, start) || !passable(level[start.x][start.y]))
-			return Collections.emptyList();
-
-		final List<Coord> result = new ArrayList<>(volume);
-
-		Direction[] dirs = new Direction[Direction.OUTWARDS.length];
-
-		final LinkedList<Coord> toTry = new LinkedList<>();
-		toTry.add(start);
-		final Set<Coord> trieds = new HashSet<>();
-
-		while (!toTry.isEmpty()) {
-			assert result.size() < volume;
-			final Coord current = toTry.removeFirst();
-			assert DungeonUtility.inLevel(level, current);
-			assert passable(level[current.x][current.y]);
-			if (trieds.contains(current))
-				continue;
-			trieds.add(current);
-			/*
-			 * Here it holds that either 'current == start' or there's a Coord
-			 * in 'result' that is adjacent to 'current'.
-			 */
-			result.add(current);
-			if (result.size() == volume)
-				/* We're done */
-				break;
-			/* Now prepare data for next iterations */
-			/* Randomize directions */
-			dirs = rng.shuffle(Direction.OUTWARDS, dirs);
-			for (Direction d : dirs) {
-				final Coord next = current.translate(d);
-				if (DungeonUtility.inLevel(level, next) && !trieds.contains(next)
-						&& passable(level[next.x][next.y]))
-					/* A valid cell for trying to be spilled on */
-					toTry.add(next);
-			}
-		}
-
-		if (0 < drunks)
-			drunkinize(rng, level, result, DungeonUtility.border(result, null), drunks);
-
-		return result;
-	}
-
-	/**
-	 * @param rng
-	 * @param map
-	 *            The map on which {@code zone} is a pool
-	 * @param zone
-	 *            The zone to shrink
-	 * @param border
-	 *            {@code zone}'s border
-	 * @param drunks
-	 *            The number of drunken walkers to consider
-	 */
-	protected void drunkinize(RNG rng, char[][] map, List<Coord> zone, List<Coord> border, int drunks) {
-		if (drunks == 0)
-			return;
-
-		final int sz = zone.size();
-		final int nb = (sz / 10) * drunks;
-		if (nb == 0)
-			return;
-
-		assert !border.isEmpty();
-		for (int j = 0; j < nb && !zone.isEmpty(); j++) {
-			drunkinize0(rng, zone, border, drunks);
-			if (border.isEmpty() || zone.isEmpty())
-				return;
-		}
-	}
-
-	protected boolean passable(char c) {
-		return !impassable.contains(c);
-	}
-
-	/**
-	 * Removes a circle from {@code zone}, by taking the circle's center in
-	 * {@code zone} 's border: {@code border}.
-	 * 
-	 * @param border
-	 *            {@code result}'s border.
-	 */
-	private void drunkinize0(RNG rng, List<Coord> zone, List<Coord> border, int nb) {
-		assert !border.isEmpty();
-		assert !zone.isEmpty();
-
-		final int width = rng.nextInt(nb) + 1;
-		final int height = rng.nextInt(nb) + 1;
-		final int radius = Math.max(1, Math.round(nb * Math.min(width, height)));
-		final Coord center = rng.getRandomElement(border);
-		zone.remove(center);
-		for (int dx = -radius; dx <= radius; ++dx) {
-			final int high = (int) Math.floor(Math.sqrt(radius * radius - dx * dx));
-			for (int dy = -high; dy <= high; ++dy) {
-				final Coord c = center.translate(dx, dy);
-				zone.remove(c);
-				if (zone.isEmpty())
-					return;
-			}
-		}
-	}
-
-	/**
-	 * @param rng
-	 *            used to randomize the floodfill
-	 * @param level
-	 *            char 2D array with x, y indices for the dungeon/map level
-	 * @param start
-	 *            Where the spill should start. It should be passable, otherwise
-	 *            an empty list gets returned. Consider using
-	 *            {@link DungeonUtility#getRandomCell(RNG, char[][], Set, int)}
-	 *            to find it.
-	 * @param volume
-	 *            The number of cells to spill on.
-	 * @param impassable the set of chars on the level that block the spill, such
-	 *                   as walls or maybe other spilled things (oil and water).
-	 *                   May be null, which makes this treat '#' as impassable.
-	 * @param drunks
-	 *            The ratio of drunks to use to make the splash more realistic.
-	 *            Like for dungeon generation, if greater than 0, drunk walkers
-	 *            will remove the splash's margins, to make it more realistic.
-	 *            You don't need that if you're doing a splash that is bounded
-	 *            by walls, because the fill will be realistic. If you're doing
-	 *            a splash that isn't bounded, use that for its borders not to
-	 *            be too square.
-	 * 
-	 *            <p>
-	 *            Useful values are 0, 1, and 2. Giving more will likely yield
-	 *            an empty result, on any decent map sizes.
-	 *            </p>
-	 * @return The spill. It is a list of coordinates (containing {@code start})
-	 *         valid in {@code level} that are all adjacent and whose symbol is
-	 *         passable. If non-empty, this is guaranteed to be an
-	 *         {@link ArrayList}.
-	 */
-	public static List<Coord> spill(RNG rng, char[][] level, Coord start, int volume, Set<Character> impassable, int drunks)
-	{
-		Set<Character> blocked;
-		if(impassable == null)
-			blocked = new HashSet<>(2);
-		else
-			blocked = impassable;
-		if(splashCache == null || blocked.hashCode() != splashHash)
-		{
-			splashHash = blocked.hashCode();
-			splashCache = new Splash(blocked);
-		}
-		return splashCache.spill(rng, level, start, volume, drunks);
-	}
-
-}