diff --git a/squidlib-performance/src/main/java/squidpony/performance/DijkstraBenchmark.java b/squidlib-performance/src/main/java/squidpony/performance/DijkstraBenchmark.java index a3fb56ec5d..0053751e93 100644 --- a/squidlib-performance/src/main/java/squidpony/performance/DijkstraBenchmark.java +++ b/squidlib-performance/src/main/java/squidpony/performance/DijkstraBenchmark.java @@ -51,7 +51,7 @@ public class DijkstraBenchmark { - public static final int DIMENSION = 60, PATH_LENGTH = (DIMENSION - 2) * (DIMENSION - 2); + public static final int DIMENSION = 100, PATH_LENGTH = (DIMENSION - 2) * (DIMENSION - 2); public static DungeonGenerator dungeonGen = new DungeonGenerator(DIMENSION, DIMENSION, new StatefulRNG(0x1337BEEFDEAL)); public static SerpentMapGenerator serpent = new SerpentMapGenerator(DIMENSION, DIMENSION, diff --git a/squidlib-performance/src/main/java/squidpony/performance/alternate/DijkstraMap.java b/squidlib-performance/src/main/java/squidpony/performance/alternate/DijkstraMap.java index 491c6fc388..6273b094a1 100644 --- a/squidlib-performance/src/main/java/squidpony/performance/alternate/DijkstraMap.java +++ b/squidlib-performance/src/main/java/squidpony/performance/alternate/DijkstraMap.java @@ -2,7 +2,6 @@ import squidpony.GwtCompatibility; import squidpony.annotation.GwtIncompatible; -import squidpony.squidai.Technique; import squidpony.squidai.Threat; import squidpony.squidgrid.*; import squidpony.squidmath.*; @@ -1476,215 +1475,215 @@ public ArrayList findAttackPath(int moveLength, int minPreferredRange, in 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. - *
- * 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. - *
- * 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. - *
- * 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. - *
- * 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. - *
- * 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 los a squidgrid.LOS object if the preferred range should try to stay in line of sight, or null if LoS - * should be disregarded. - * @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. - */ - public ArrayList findTechniquePath(int moveLength, Technique tech, char[][] dungeon, LOS los, - Set impassable, Set allies, Coord start, Set targets) { - if (!initialized) return null; - tech.setMap(dungeon); - double[][] resMap = new double[width][height]; - double[][] worthMap = new double[width][height]; - double[][] userDistanceMap; - double paidLength = 0.0; - - LinkedHashSet 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); - LinkedHashSet impassable2; - if (impassable == null) - impassable2 = new LinkedHashSet<>(); - else - impassable2 = new LinkedHashSet<>(impassable); - - if (allies == null) - friends = new LinkedHashSet<>(); - else { - friends = new LinkedHashSet<>(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); - LinkedHashMap> 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 (los == null || los.isReachable(resMap, x, y, tgt.x, tgt.y)) { - ideal = tech.idealLocations(tempPt, targets, friends); - // this is weird but it saves the trouble of getting the iterator and checking hasNext() . - for (Map.Entry> ip : ideal.entrySet()) { - targetMap[x][y] = ip.getKey(); - worthMap[x][y] = ip.getValue().size(); - setGoal(x, y); - gradientMap[x][y] = 0; - break; - } - continue CELL; - } - } - gradientMap[x][y] = FLOOR; - } else - gradientMap[x][y] = FLOOR; - } - } - scan(impassable2); - - double currentDistance = gradientMap[start.x][start.y]; - if (currentDistance <= moveLength) { - Coord[] g_arr = new Coord[goals.size()]; - g_arr = goals.keySet().toArray(g_arr); - - goals.clear(); - setGoal(start); - scan(impassable2); - goals.clear(); - gradientMap[start.x][start.y] = moveLength; - - for (Coord g : g_arr) { - if (gradientMap[g.x][g.y] <= moveLength && worthMap[g.x][g.y] > 0) { - goals.put(g, 0.0 - worthMap[g.x][g.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 = appendDir(shuffleDirs(rng), Direction.NONE); - int choice = rng.nextInt(dirs.length); - - for (int d = 0; d < dirs.length; d++) { - Coord pt = Coord.get(currentPos.x + dirs[d].deltaX, currentPos.y + dirs[d].deltaY); - if (gradientMap[pt.x][pt.y] < best) { - 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, WALL); - impassable2.add(currentPos); - return findTechniquePath(moveLength, tech, dungeon, los, 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, WALL); - impassable2.add(currentPos); - return findTechniquePath(moveLength, tech, dungeon, los, impassable2, - friends, start, targets); - } - break; - } -// if(gradientMap[currentPos.x][currentPos.y] == 0) +// /** +// * 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. +// *
+// * 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. +// *
+// * 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. +// *
+// * 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. +// *
+// * 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. +// *
+// * 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 los a squidgrid.LOS object if the preferred range should try to stay in line of sight, or null if LoS +// * should be disregarded. +// * @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. +// */ +// public ArrayList findTechniquePath(int moveLength, Technique tech, char[][] dungeon, LOS los, +// Set impassable, Set allies, Coord start, Set targets) { +// if (!initialized) return null; +// tech.setMap(dungeon); +// double[][] resMap = new double[width][height]; +// double[][] worthMap = new double[width][height]; +// double[][] userDistanceMap; +// double paidLength = 0.0; +// +// LinkedHashSet 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); +// LinkedHashSet impassable2; +// if (impassable == null) +// impassable2 = new LinkedHashSet<>(); +// else +// impassable2 = new LinkedHashSet<>(impassable); +// +// if (allies == null) +// friends = new LinkedHashSet<>(); +// else { +// friends = new LinkedHashSet<>(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); +// LinkedHashMap> 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 (los == null || los.isReachable(resMap, x, y, tgt.x, tgt.y)) { +// ideal = tech.idealLocations(tempPt, targets, friends); +// // this is weird but it saves the trouble of getting the iterator and checking hasNext() . +// for (Map.Entry> ip : ideal.entrySet()) { +// targetMap[x][y] = ip.getKey(); +// worthMap[x][y] = ip.getValue().size(); +// setGoal(x, y); +// gradientMap[x][y] = 0; +// break; +// } +// continue CELL; +// } +// } +// gradientMap[x][y] = FLOOR; +// } else +// gradientMap[x][y] = FLOOR; +// } +// } +// scan(impassable2); +// +// double currentDistance = gradientMap[start.x][start.y]; +// if (currentDistance <= moveLength) { +// Coord[] g_arr = new Coord[goals.size()]; +// g_arr = goals.keySet().toArray(g_arr); +// +// goals.clear(); +// setGoal(start); +// scan(impassable2); +// goals.clear(); +// gradientMap[start.x][start.y] = moveLength; +// +// for (Coord g : g_arr) { +// if (gradientMap[g.x][g.y] <= moveLength && worthMap[g.x][g.y] > 0) { +// goals.put(g, 0.0 - worthMap[g.x][g.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; - } - frustration = 0; - goals.clear(); - return new ArrayList<>(path); - } +// } +// double best = gradientMap[currentPos.x][currentPos.y]; +// final Direction[] dirs = appendDir(shuffleDirs(rng), Direction.NONE); +// int choice = rng.nextInt(dirs.length); +// +// for (int d = 0; d < dirs.length; d++) { +// Coord pt = Coord.get(currentPos.x + dirs[d].deltaX, currentPos.y + dirs[d].deltaY); +// if (gradientMap[pt.x][pt.y] < best) { +// 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, WALL); +// impassable2.add(currentPos); +// return findTechniquePath(moveLength, tech, dungeon, los, 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, WALL); +// impassable2.add(currentPos); +// return findTechniquePath(moveLength, tech, dungeon, los, impassable2, +// friends, start, targets); +// } +// break; +// } +//// if(gradientMap[currentPos.x][currentPos.y] == 0) +//// break; +// } +// frustration = 0; +// goals.clear(); +// return new ArrayList<>(path); +// } /** @@ -2460,217 +2459,217 @@ public ArrayList findCoveredAttackPath(int moveLength, int minPreferredRa 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. - *

- * 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. - *

- * 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. - *

- * 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. - *

- * 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. - *
- * 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 findTechniquePath(int moveLength, Technique tech, char[][] dungeon, FOVCache cache, - Set impassable, Set allies, Coord start, Set 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; - - LinkedHashSet 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); - LinkedHashSet impassable2; - if (impassable == null) - impassable2 = new LinkedHashSet<>(); - else - impassable2 = new LinkedHashSet<>(impassable); - - if (allies == null) - friends = new LinkedHashSet<>(); - else { - friends = new LinkedHashSet<>(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); - LinkedHashMap> 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); - // this is weird but it saves the trouble of getting the iterator and checking hasNext() . - for (Map.Entry> ip : ideal.entrySet()) { - targetMap[x][y] = ip.getKey(); - worthMap[x][y] = ip.getValue().size(); - setGoal(x, y); - gradientMap[x][y] = 0; - break; - } - continue CELL; - } - } - gradientMap[x][y] = FLOOR; - } else - gradientMap[x][y] = FLOOR; - } - } - scan(impassable2); - - double currentDistance = gradientMap[start.x][start.y]; - if (currentDistance <= moveLength) { - Coord[] g_arr = new Coord[goals.size()]; - g_arr = goals.keySet().toArray(g_arr); - - goals.clear(); - setGoal(start); - scan(impassable2); - goals.clear(); - gradientMap[start.x][start.y] = moveLength; - - for (Coord g : g_arr) { - if (gradientMap[g.x][g.y] <= moveLength && worthMap[g.x][g.y] > 0) { - goals.put(g, 0.0 - worthMap[g.x][g.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 = appendDir(shuffleDirs(rng), Direction.NONE); - int choice = rng.nextInt(dirs.length); - - for (int d = 0; d < dirs.length; d++) { - Coord pt = Coord.get(currentPos.x + dirs[d].deltaX, currentPos.y + dirs[d].deltaY); - if (gradientMap[pt.x][pt.y] < best) { - 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, 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, WALL); - impassable2.add(currentPos); - return findTechniquePath(moveLength, tech, dungeon, cache, impassable2, - friends, start, targets); - } - break; - } -// if(gradientMap[currentPos.x][currentPos.y] == 0) +// /** +// * 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. +// *

+// * 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. +// *

+// * 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. +// *

+// * 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. +// *

+// * 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. +// *
+// * 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 findTechniquePath(int moveLength, Technique tech, char[][] dungeon, FOVCache cache, +// Set impassable, Set allies, Coord start, Set 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; +// +// LinkedHashSet 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); +// LinkedHashSet impassable2; +// if (impassable == null) +// impassable2 = new LinkedHashSet<>(); +// else +// impassable2 = new LinkedHashSet<>(impassable); +// +// if (allies == null) +// friends = new LinkedHashSet<>(); +// else { +// friends = new LinkedHashSet<>(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); +// LinkedHashMap> 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); +// // this is weird but it saves the trouble of getting the iterator and checking hasNext() . +// for (Map.Entry> ip : ideal.entrySet()) { +// targetMap[x][y] = ip.getKey(); +// worthMap[x][y] = ip.getValue().size(); +// setGoal(x, y); +// gradientMap[x][y] = 0; +// break; +// } +// continue CELL; +// } +// } +// gradientMap[x][y] = FLOOR; +// } else +// gradientMap[x][y] = FLOOR; +// } +// } +// scan(impassable2); +// +// double currentDistance = gradientMap[start.x][start.y]; +// if (currentDistance <= moveLength) { +// Coord[] g_arr = new Coord[goals.size()]; +// g_arr = goals.keySet().toArray(g_arr); +// +// goals.clear(); +// setGoal(start); +// scan(impassable2); +// goals.clear(); +// gradientMap[start.x][start.y] = moveLength; +// +// for (Coord g : g_arr) { +// if (gradientMap[g.x][g.y] <= moveLength && worthMap[g.x][g.y] > 0) { +// goals.put(g, 0.0 - worthMap[g.x][g.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; - } - frustration = 0; - goals.clear(); - return new ArrayList<>(path); - } +// } +// double best = gradientMap[currentPos.x][currentPos.y]; +// final Direction[] dirs = appendDir(shuffleDirs(rng), Direction.NONE); +// int choice = rng.nextInt(dirs.length); +// +// for (int d = 0; d < dirs.length; d++) { +// Coord pt = Coord.get(currentPos.x + dirs[d].deltaX, currentPos.y + dirs[d].deltaY); +// if (gradientMap[pt.x][pt.y] < best) { +// 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, 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, 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; diff --git a/squidlib-util/src/main/java/squidpony/FakeLanguageGen.java b/squidlib-util/src/main/java/squidpony/FakeLanguageGen.java index 9b3ca4eba8..ba0fdcfaab 100644 --- a/squidlib-util/src/main/java/squidpony/FakeLanguageGen.java +++ b/squidlib-util/src/main/java/squidpony/FakeLanguageGen.java @@ -1670,12 +1670,12 @@ public String word(RNG rng, boolean capitalize) { StringBuilder sb = new StringBuilder(20); double syllableChance = rng.nextDouble(totalSyllableFrequency); int syllables = 1, i = 0; - for (Map.Entry kv : syllableFrequencies.entrySet()) { - if (syllableChance < kv.getValue()) { - syllables = kv.getKey(); + for (IntDoubleOrderedMap.MapEntry kv : syllableFrequencies.mapEntrySet()) { + if (syllableChance < kv.getDoubleValue()) { + syllables = kv.getIntKey(); break; } else - syllableChance -= kv.getValue(); + syllableChance -= kv.getDoubleValue(); } if (rng.nextDouble() < vowelStartFrequency) { sb.append(rng.getRandomElement(openingVowels)); diff --git a/squidlib-util/src/main/java/squidpony/LanguageCipher.java b/squidlib-util/src/main/java/squidpony/LanguageCipher.java index 0138cc4857..012b8e87aa 100644 --- a/squidlib-util/src/main/java/squidpony/LanguageCipher.java +++ b/squidlib-util/src/main/java/squidpony/LanguageCipher.java @@ -46,7 +46,7 @@ public class LanguageCipher implements Serializable{ */ public FakeLanguageGen language; private StatefulRNG rng; - // not a LinkedHashMap because this should never be need a random element to be requested + // not an OrderedMap because this should never be need a random element to be requested /** * The mapping of lower-case word keys to lower-case word values, where keys are in the source language and values * are generated by language. diff --git a/squidlib-util/src/main/java/squidpony/MonsterGen.java b/squidlib-util/src/main/java/squidpony/MonsterGen.java index 2c410b8cf7..64e9db8050 100644 --- a/squidlib-util/src/main/java/squidpony/MonsterGen.java +++ b/squidlib-util/src/main/java/squidpony/MonsterGen.java @@ -1,8 +1,6 @@ package squidpony; -import squidpony.squidmath.CrossHash; -import squidpony.squidmath.RNG; -import squidpony.squidmath.StatefulRNG; +import squidpony.squidmath.*; import java.util.*; @@ -40,8 +38,8 @@ public class MonsterGen { */ public static class Chimera { - public LinkedHashMap> parts; - public LinkedHashSet unsaidAdjectives, wholeAdjectives, powerAdjectives, powerPhrases; + public OrderedMap> parts; + public OrderedSet unsaidAdjectives, wholeAdjectives, powerAdjectives, powerPhrases; public String name, mainForm, unknown; /** @@ -57,13 +55,13 @@ public Chimera(String name, Chimera other) mainForm = unknown; else mainForm = other.name; - parts = new LinkedHashMap<>(other.parts); + parts = new OrderedMap<>(other.parts); List oldParts = new ArrayList<>(parts.remove(mainForm)); parts.put(name, oldParts); - unsaidAdjectives = new LinkedHashSet<>(other.unsaidAdjectives); - wholeAdjectives = new LinkedHashSet<>(other.wholeAdjectives); - powerAdjectives = new LinkedHashSet<>(other.powerAdjectives); - powerPhrases = new LinkedHashSet<>(other.powerPhrases); + unsaidAdjectives = new OrderedSet<>(other.unsaidAdjectives); + wholeAdjectives = new OrderedSet<>(other.wholeAdjectives); + powerAdjectives = new OrderedSet<>(other.powerAdjectives); + powerPhrases = new OrderedSet<>(other.powerPhrases); } /** @@ -100,11 +98,11 @@ public Chimera(String name, String unknown, String... terms) mainForm = unknown; else mainForm = name; - parts = new LinkedHashMap<>(); - unsaidAdjectives = new LinkedHashSet<>(); - wholeAdjectives = new LinkedHashSet<>(); - powerAdjectives = new LinkedHashSet<>(); - powerPhrases = new LinkedHashSet<>(); + parts = new OrderedMap<>(); + unsaidAdjectives = new OrderedSet<>(); + wholeAdjectives = new OrderedSet<>(); + powerAdjectives = new OrderedSet<>(); + powerPhrases = new OrderedSet<>(); ArrayList selfParts = new ArrayList<>(); int t = 0; for (; t < terms.length; t++) { @@ -183,11 +181,11 @@ public Chimera(String name, String unknown, Collection parts, Collection mainForm = unknown; else mainForm = name; - this.parts = new LinkedHashMap>(); - unsaidAdjectives = new LinkedHashSet(unsaid); - wholeAdjectives = new LinkedHashSet(whole); - powerAdjectives = new LinkedHashSet(powerAdj); - powerPhrases = new LinkedHashSet(powerPhr); + this.parts = new OrderedMap>(); + unsaidAdjectives = new OrderedSet(unsaid); + wholeAdjectives = new OrderedSet(whole); + powerAdjectives = new OrderedSet(powerAdj); + powerPhrases = new OrderedSet(powerPhr); ArrayList selfParts = new ArrayList(parts); this.parts.put(name, selfParts); } @@ -205,7 +203,7 @@ public String present(boolean capitalize) else sb.append('a'); int i = 0; - LinkedHashSet allAdjectives = new LinkedHashSet<>(wholeAdjectives); + OrderedSet allAdjectives = new OrderedSet<>(wholeAdjectives); if(unknown != null) allAdjectives.addAll(unsaidAdjectives); allAdjectives.addAll(powerAdjectives); @@ -288,7 +286,7 @@ public String presentVisible(boolean capitalize) sb.append('a'); int i = 0; - LinkedHashSet allAdjectives = new LinkedHashSet<>(wholeAdjectives); + OrderedSet allAdjectives = new OrderedSet<>(wholeAdjectives); if(unknown != null) allAdjectives.addAll(unsaidAdjectives); for(String adj : allAdjectives) diff --git a/squidlib-util/src/main/java/squidpony/squidai/AOE.java b/squidlib-util/src/main/java/squidpony/squidai/AOE.java index 4130a348cf..1aedeaf7f5 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/AOE.java +++ b/squidlib-util/src/main/java/squidpony/squidai/AOE.java @@ -4,9 +4,9 @@ import squidpony.squidgrid.FOVCache; import squidpony.squidgrid.Radius; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.Set; /** @@ -37,7 +37,7 @@ public interface AOE { boolean mayContainTarget(Set targets); /** - * Returns a LinkedHashMap of Coord keys and ArrayList of Coord values, where each Coord key is an ideal location to + * 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 @@ -54,9 +54,9 @@ public interface AOE { * 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 LinkedHashMap 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. + * @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. */ - LinkedHashMap> idealLocations(Set targets, Set requiredExclusions); + OrderedMap> idealLocations(Set targets, Set requiredExclusions); /** * A variant of idealLocations that takes two groups of desirable targets, and will rate locations by how many @@ -69,9 +69,9 @@ public interface AOE { * @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 LinkedHashMap 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. + * @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. */ - LinkedHashMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions); + OrderedMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions); /** * This must be called before any other methods, and takes a char[][] with '#' for walls, anything else for floors. @@ -86,12 +86,12 @@ public interface AOE { * the map. The map must be bounded by walls, which DungeonGenerator does automatically and other generators can * easily add with two loops. * - * This returns a HashMap of Coord keys to Double values; if a cell is 100% affected by the AOE then the value + * 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 a HashMap of Coord keys to Double values from 1.0 (fully affected) to 0.0 (unaffected). + * @return an OrderedMap of Coord keys to Double values from 1.0 (fully affected) to 0.0 (unaffected). */ - LinkedHashMap findArea(); + OrderedMap findArea(); /** * Get the position from which the AOE originates, which may be related to the location of the AOE's effect, as for diff --git a/squidlib-util/src/main/java/squidpony/squidai/AreaUtils.java b/squidlib-util/src/main/java/squidpony/squidai/AreaUtils.java index 1352183d69..46e7672149 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/AreaUtils.java +++ b/squidlib-util/src/main/java/squidpony/squidai/AreaUtils.java @@ -1,8 +1,8 @@ package squidpony.squidai; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; -import java.util.LinkedHashMap; /** * Static utilities for use in AOE and anything else that might need HashMaps of Coord keys to Double values. @@ -15,9 +15,9 @@ public class AreaUtils { * @param map width by height, commonly generated by FOV methods * @return a HashMap of Coord keys to Double values, but the only value used is 1.0 */ - public static LinkedHashMap arrayToHashMap(boolean[][] map) + public static OrderedMap arrayToHashMap(boolean[][] map) { - LinkedHashMap ret = new LinkedHashMap<>(); + OrderedMap ret = new OrderedMap<>(); for(int i = 0; i < map.length; i++) { for(int j = 0; j < map[i].length; j++) @@ -35,9 +35,9 @@ public static LinkedHashMap arrayToHashMap(boolean[][] map) * @param map width by height, commonly generated by FOV methods * @return a HashMap of Coord keys to Double values, with values all greater than 0.0 */ - public static LinkedHashMap arrayToHashMap(double[][] map) + public static OrderedMap arrayToHashMap(double[][] map) { - LinkedHashMap ret = new LinkedHashMap<>(); + OrderedMap ret = new OrderedMap<>(); for(int i = 0; i < map.length; i++) { for(int j = 0; j < map[i].length; j++) @@ -58,9 +58,9 @@ public static LinkedHashMap arrayToHashMap(double[][] map) * @param cutoff any elements greater than this will be 1.0 in the return, anything else will be ignored * @return a HashMap of Coord keys to Double values, but the only value used is 1.0 */ - public static LinkedHashMap arrayToHashMap(double[][] map, double cutoff) + public static OrderedMap arrayToHashMap(double[][] map, double cutoff) { - LinkedHashMap ret = new LinkedHashMap<>(); + OrderedMap ret = new OrderedMap<>(); for(int i = 0; i < map.length; i++) { for(int j = 0; j < map[i].length; j++) @@ -78,9 +78,9 @@ public static LinkedHashMap arrayToHashMap(double[][] map, double * @param map a double[][] returned by a DijkstraMap running its scan() * @return a HashMap of Coord keys to Double values, with values of 1.0 only */ - public static LinkedHashMap dijkstraToHashMap(double[][] map) + public static OrderedMap dijkstraToHashMap(double[][] map) { - LinkedHashMap ret = new LinkedHashMap<>(); + OrderedMap ret = new OrderedMap<>(); for(int i = 0; i < map.length; i++) { for(int j = 0; j < map[i].length; j++) diff --git a/squidlib-util/src/main/java/squidpony/squidai/BeamAOE.java b/squidlib-util/src/main/java/squidpony/squidai/BeamAOE.java index b456dd8e10..08013d4d0f 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/BeamAOE.java +++ b/squidlib-util/src/main/java/squidpony/squidai/BeamAOE.java @@ -6,8 +6,13 @@ import squidpony.squidgrid.Radius; import squidpony.squidgrid.mapping.DungeonUtility; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; +import squidpony.squidmath.OrderedSet; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Queue; +import java.util.Set; import static java.lang.Math.*; @@ -302,15 +307,15 @@ public boolean mayContainTarget(Set targets) { } @Override - public LinkedHashMap> idealLocations(Set targets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set targets, Set requiredExclusions) { if(targets == null) - return new LinkedHashMap<>(); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + return new OrderedMap<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = targets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -447,14 +452,14 @@ else if(qualityMap[x][y] == bestQuality) } @Override - public LinkedHashMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { if(priorityTargets == null) return idealLocations(lesserTargets, requiredExclusions); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = priorityTargets.size() + lesserTargets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -742,7 +747,7 @@ public void setMap(char[][] map) { } @Override - public LinkedHashMap findArea() { + public OrderedMap findArea() { double[][] dmap = initDijkstra(); dmap[origin.x][origin.y] = DijkstraMap.DARK; dijkstra.resetMap(); diff --git a/squidlib-util/src/main/java/squidpony/squidai/BlastAOE.java b/squidlib-util/src/main/java/squidpony/squidai/BlastAOE.java index 4a5f367cb6..f56b7b8e77 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/BlastAOE.java +++ b/squidlib-util/src/main/java/squidpony/squidai/BlastAOE.java @@ -7,6 +7,9 @@ import squidpony.squidgrid.mapping.DungeonUtility; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; +import squidpony.squidmath.OrderedSet; + import java.util.*; /** @@ -91,14 +94,14 @@ public boolean mayContainTarget(Set targets) { } @Override - public LinkedHashMap> idealLocations(Set targets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set targets, Set requiredExclusions) { if(targets == null) - return new LinkedHashMap<>(); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + return new OrderedMap<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = targets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -233,14 +236,14 @@ else if(qualityMap[x][y] == bestQuality) { } @Override - public LinkedHashMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { if(priorityTargets == null) return idealLocations(lesserTargets, requiredExclusions); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = priorityTargets.size() + lesserTargets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -510,7 +513,7 @@ public void setMap(char[][] map) { } @Override - public LinkedHashMap findArea() { + public OrderedMap findArea() { return AreaUtils.arrayToHashMap(fov.calculateFOV(map, center.x, center.y, radius, radiusType)); } diff --git a/squidlib-util/src/main/java/squidpony/squidai/BurstAOE.java b/squidlib-util/src/main/java/squidpony/squidai/BurstAOE.java index a8fc85ee77..1b63a16aa5 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/BurstAOE.java +++ b/squidlib-util/src/main/java/squidpony/squidai/BurstAOE.java @@ -6,8 +6,12 @@ import squidpony.squidgrid.Radius; import squidpony.squidgrid.mapping.DungeonUtility; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; +import squidpony.squidmath.OrderedSet; -import java.util.*; +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 @@ -90,14 +94,14 @@ public boolean mayContainTarget(Set targets) { } @Override - public LinkedHashMap> idealLocations(Set targets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set targets, Set requiredExclusions) { if(targets == null) - return new LinkedHashMap<>(); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + return new OrderedMap<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = targets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -225,14 +229,14 @@ else if(qualityMap[x][y] == bestQuality) @Override - public LinkedHashMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { if(priorityTargets == null) return idealLocations(lesserTargets, requiredExclusions); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = priorityTargets.size() + lesserTargets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -509,7 +513,7 @@ public void setMap(char[][] map) { } @Override - public LinkedHashMap findArea() { + public OrderedMap findArea() { return AreaUtils.arrayToHashMap(fov.calculateFOV(null, center.x, center.y, radius, radiusType)); } diff --git a/squidlib-util/src/main/java/squidpony/squidai/CloudAOE.java b/squidlib-util/src/main/java/squidpony/squidai/CloudAOE.java index e00c41cdab..04c06e9b5f 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/CloudAOE.java +++ b/squidlib-util/src/main/java/squidpony/squidai/CloudAOE.java @@ -8,6 +8,9 @@ import squidpony.squidmath.LightRNG; import squidpony.squidmath.RNG; +import squidpony.squidmath.OrderedMap; +import squidpony.squidmath.OrderedSet; + import java.util.*; /** @@ -191,14 +194,14 @@ public boolean mayContainTarget(Set targets) { } @Override - public LinkedHashMap> idealLocations(Set targets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set targets, Set requiredExclusions) { if(targets == null) - return new LinkedHashMap<>(); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + return new OrderedMap<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = targets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0 || volume <= 0) return bestPoints; @@ -334,15 +337,15 @@ else if(qualityMap[x][y] == bestQuality) } @Override - public LinkedHashMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { if(priorityTargets == null) return idealLocations(lesserTargets, requiredExclusions); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = priorityTargets.size() + lesserTargets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0 || volume <= 0) return bestPoints; @@ -636,9 +639,9 @@ public void setMap(char[][] map) { } @Override - public LinkedHashMap findArea() { + public OrderedMap findArea() { spill.start(center, volume, null); - LinkedHashMap r = AreaUtils.arrayToHashMap(spill.spillMap); + OrderedMap r = AreaUtils.arrayToHashMap(spill.spillMap); if(!expanding) { spill.reset(); diff --git a/squidlib-util/src/main/java/squidpony/squidai/ConeAOE.java b/squidlib-util/src/main/java/squidpony/squidai/ConeAOE.java index 4e0a701402..317999322e 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/ConeAOE.java +++ b/squidlib-util/src/main/java/squidpony/squidai/ConeAOE.java @@ -7,6 +7,9 @@ import squidpony.squidgrid.mapping.DungeonUtility; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; +import squidpony.squidmath.OrderedSet; + import java.util.*; /** @@ -197,14 +200,14 @@ public boolean mayContainTarget(Set targets) { } @Override - public LinkedHashMap> idealLocations(Set targets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set targets, Set requiredExclusions) { if(targets == null) - return new LinkedHashMap<>(); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + return new OrderedMap<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = targets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -327,14 +330,14 @@ else if(qualityMap[x][y] == bestQuality) { } @Override - public LinkedHashMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { if(priorityTargets == null) return idealLocations(lesserTargets, requiredExclusions); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = priorityTargets.size() + lesserTargets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -613,8 +616,8 @@ public void setMap(char[][] map) { } @Override - public LinkedHashMap findArea() { - LinkedHashMap r = AreaUtils.arrayToHashMap(fov.calculateFOV(map, origin.x, origin.y, radius, + public OrderedMap findArea() { + OrderedMap r = AreaUtils.arrayToHashMap(fov.calculateFOV(map, origin.x, origin.y, radius, radiusType, angle, span)); r.remove(origin); return r; diff --git a/squidlib-util/src/main/java/squidpony/squidai/DijkstraMap.java b/squidlib-util/src/main/java/squidpony/squidai/DijkstraMap.java index 214737f6b5..07bc7ed167 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/DijkstraMap.java +++ b/squidlib-util/src/main/java/squidpony/squidai/DijkstraMap.java @@ -737,7 +737,7 @@ public double[][] relax(Coord... saferPoints) { public double[][] scan(Set impassable) { if (!initialized) return null; if (impassable == null) - impassable = new LinkedHashSet<>(); + impassable = new OrderedSet<>(); IntDoubleOrderedMap blocking = new IntDoubleOrderedMap(impassable.size()); for (Coord pt : impassable) { blocking.put(pt.encode(), WALL); @@ -829,7 +829,7 @@ else if (gradientMap[x][y] < currentLowest) { public double[][] partialScan(int limit, Set impassable) { if (!initialized) return null; if (impassable == null) - impassable = new LinkedHashSet<>(); + impassable = new OrderedSet<>(); IntDoubleOrderedMap blocking = new IntDoubleOrderedMap(impassable.size()); for (Coord pt : impassable) { blocking.put(pt.encode(), WALL); @@ -992,7 +992,7 @@ public Coord findNearest(Coord start, Set targets) { * @return the Coord that it found first. */ public Coord findNearest(Coord start, Coord... targets) { - LinkedHashSet tgts = new LinkedHashSet<>(targets.length); + OrderedSet tgts = new OrderedSet<>(targets.length); Collections.addAll(tgts, targets); return findNearest(start, tgts); } @@ -1148,7 +1148,7 @@ public ArrayList findNearestMultiple(Coord start, int limit, Set t public double[][] scan(Set impassable, int size) { if (!initialized) return null; if (impassable == null) - impassable = new LinkedHashSet<>(); + impassable = new OrderedSet<>(); IntDoubleOrderedMap blocking = new IntDoubleOrderedMap(impassable.size()); for (Coord pt : impassable) { blocking.put(pt.encode(), WALL); @@ -1288,13 +1288,13 @@ public ArrayList findPath(int length, Set impassable, Set onlyPassable, Coord start, Coord... targets) { if (!initialized) return null; path.clear(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet<>(); + onlyPassable = new OrderedSet<>(); resetMap(); for (Coord goal : targets) { @@ -1418,13 +1418,13 @@ public ArrayList findAttackPath(int moveLength, int minPreferredRange, in } } path.clear(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet<>(); + onlyPassable = new OrderedSet<>(); resetMap(); for (Coord goal : targets) { @@ -1562,7 +1562,7 @@ public ArrayList findTechniquePath(int moveLength, Technique tech, char[] double[][] userDistanceMap; double paidLength = 0.0; - LinkedHashSet friends; + OrderedSet friends; for (int x = 0; x < width; x++) { @@ -1575,16 +1575,16 @@ public ArrayList findTechniquePath(int moveLength, Technique tech, char[] path.clear(); if (targets == null || targets.size() == 0) return new ArrayList<>(path); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (allies == null) - friends = new LinkedHashSet<>(); + friends = new OrderedSet<>(); else { - friends = new LinkedHashSet<>(allies); + friends = new OrderedSet<>(allies); friends.remove(start); } @@ -1610,7 +1610,7 @@ public ArrayList findTechniquePath(int moveLength, Technique tech, char[] clearGoals(); Coord tempPt = Coord.get(0, 0); - LinkedHashMap> ideal; + OrderedMap> 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: @@ -1622,13 +1622,11 @@ public ArrayList findTechniquePath(int moveLength, Technique tech, char[] for (Coord tgt : targets) { if (los == null || los.isReachable(resMap, x, y, tgt.x, tgt.y)) { ideal = tech.idealLocations(tempPt, targets, friends); - // this is weird but it saves the trouble of getting the iterator and checking hasNext() . - for (Map.Entry> ip : ideal.entrySet()) { - targetMap[x][y] = ip.getKey(); - worthMap[x][y] = ip.getValue().size(); + if (!ideal.isEmpty()) { + targetMap[x][y] = ideal.keyAt(0); + worthMap[x][y] = ideal.getAt(0).size(); setGoal(x, y); gradientMap[x][y] = 0; - break; } continue CELL; } @@ -1783,13 +1781,13 @@ public ArrayList findAttackPath(int moveLength, int minPreferredRange, in if (maxPreferredRange < minPreferredRange) maxPreferredRange = minPreferredRange; path.clear(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet<>(); + onlyPassable = new OrderedSet<>(); resetMap(); for (Coord goal : targets) { @@ -1910,7 +1908,7 @@ public ArrayList findAttackPath(int moveLength, int minPreferredRange, in */ public ArrayList findCoveredAttackPath(int moveLength, int minPreferredRange, int maxPreferredRange, double coverPreference, Set impassable, - Set onlyPassable, List threats, Coord start, + Set onlyPassable, Iterable threats, Coord start, Coord... targets) { if (!initialized) return null; @@ -1926,13 +1924,13 @@ public ArrayList findCoveredAttackPath(int moveLength, int minPreferredRa path = new ArrayList(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet(); + impassable2 = new OrderedSet(); else - impassable2 = new LinkedHashSet(impassable); + impassable2 = new OrderedSet(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet(); + onlyPassable = new OrderedSet(); resetMap(); for (Coord goal : targets) { @@ -2116,7 +2114,7 @@ public ArrayList findCoveredAttackPath(int moveLength, int preferredRange */ public ArrayList findCoveredAttackPath(int moveLength, int minPreferredRange, int maxPreferredRange, double coverPreference, FOV fov, boolean seekDistantGoals, Set impassable, - Set onlyPassable, List threats, Coord start, + Set onlyPassable, Iterable threats, Coord start, Coord... targets) { if (!initialized) return null; if(fov == null) { @@ -2135,13 +2133,13 @@ public ArrayList findCoveredAttackPath(int moveLength, int minPreferredRa path = new ArrayList(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet(); + impassable2 = new OrderedSet(); else - impassable2 = new LinkedHashSet(impassable); + impassable2 = new OrderedSet(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet(); + onlyPassable = new OrderedSet(); resetMap(); for (Coord goal : targets) { @@ -2364,13 +2362,13 @@ public ArrayList findCoveredAttackPath(int moveLength, int minPreferredRa } path.clear(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet<>(); + onlyPassable = new OrderedSet<>(); resetMap(); for (Coord goal : targets) { @@ -2548,7 +2546,7 @@ public ArrayList findTechniquePath(int moveLength, Technique tech, char[] double[][] userDistanceMap; double paidLength = 0.0; - LinkedHashSet friends; + OrderedSet friends; for (int x = 0; x < width; x++) { @@ -2561,16 +2559,16 @@ public ArrayList findTechniquePath(int moveLength, Technique tech, char[] path.clear(); if (targets == null || targets.size() == 0) return new ArrayList<>(path); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (allies == null) - friends = new LinkedHashSet<>(); + friends = new OrderedSet<>(); else { - friends = new LinkedHashSet<>(allies); + friends = new OrderedSet<>(allies); friends.remove(start); } @@ -2596,7 +2594,7 @@ public ArrayList findTechniquePath(int moveLength, Technique tech, char[] clearGoals(); Coord tempPt = Coord.get(0, 0); - LinkedHashMap> ideal; + OrderedMap> 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: @@ -2608,13 +2606,11 @@ public ArrayList findTechniquePath(int moveLength, Technique tech, char[] for (Coord tgt : targets) { if (cache == null || cache.queryLOS(x, y, tgt.x, tgt.y)) { ideal = tech.idealLocations(tempPt, targets, friends); - // this is weird but it saves the trouble of getting the iterator and checking hasNext() . - for (Map.Entry> ip : ideal.entrySet()) { - targetMap[x][y] = ip.getKey(); - worthMap[x][y] = ip.getValue().size(); + if (!ideal.isEmpty()) { + targetMap[x][y] = ideal.keyAt(0); + worthMap[x][y] = ideal.getAt(0).size(); setGoal(x, y); gradientMap[x][y] = 0; - break; } continue CELL; } @@ -2709,7 +2705,7 @@ public ArrayList findTechniquePath(int moveLength, Technique tech, char[] private double cachedLongerPaths = 1.2; - private Set cachedImpassable = new LinkedHashSet<>(); + private Set cachedImpassable = new OrderedSet<>(); private Coord[] cachedFearSources; private double[][] cachedFleeMap; private int cachedSize = 1; @@ -2744,14 +2740,14 @@ public ArrayList findFleePath(int length, double preferLongerPaths, Set onlyPassable, Coord start, Coord... fearSources) { if (!initialized) return null; path.clear(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet<>(); + onlyPassable = new OrderedSet<>(); if (fearSources == null || fearSources.length < 1) { path.clear(); return new ArrayList<>(path); @@ -2761,7 +2757,7 @@ public ArrayList findFleePath(int length, double preferLongerPaths, Set(impassable2); + cachedImpassable = new OrderedSet<>(impassable2); cachedFearSources = GwtCompatibility.cloneCoords(fearSources); cachedSize = 1; resetMap(); @@ -2857,14 +2853,14 @@ public ArrayList findPathLarge(int size, int length, Set impassabl Set onlyPassable, Coord start, Coord... targets) { if (!initialized) return null; path.clear(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet<>(); + onlyPassable = new OrderedSet<>(); resetMap(); for (Coord goal : targets) { @@ -2962,14 +2958,14 @@ public ArrayList findAttackPathLarge(int size, int moveLength, int prefer } } path.clear(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet<>(); + onlyPassable = new OrderedSet<>(); resetMap(); for (Coord goal : targets) { @@ -3100,14 +3096,14 @@ public ArrayList findAttackPathLarge(int size, int moveLength, int minPre } } path.clear(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet<>(); + onlyPassable = new OrderedSet<>(); resetMap(); for (Coord goal : targets) { @@ -3230,14 +3226,14 @@ public ArrayList findFleePathLarge(int size, int length, double preferLon Set onlyPassable, Coord start, Coord... fearSources) { if (!initialized) return null; path.clear(); - LinkedHashSet impassable2; + OrderedSet impassable2; if (impassable == null) - impassable2 = new LinkedHashSet<>(); + impassable2 = new OrderedSet<>(); else - impassable2 = new LinkedHashSet<>(impassable); + impassable2 = new OrderedSet<>(impassable); if (onlyPassable == null) - onlyPassable = new LinkedHashSet<>(); + onlyPassable = new OrderedSet<>(); if (fearSources == null || fearSources.length < 1) { path.clear(); return new ArrayList<>(path); @@ -3247,7 +3243,7 @@ public ArrayList findFleePathLarge(int size, int length, double preferLon gradientMap = cachedFleeMap; } else { cachedLongerPaths = preferLongerPaths; - cachedImpassable = new LinkedHashSet<>(impassable2); + cachedImpassable = new OrderedSet<>(impassable2); cachedFearSources = GwtCompatibility.cloneCoords(fearSources); cachedSize = size; resetMap(); @@ -3367,17 +3363,17 @@ public ArrayList findPathPreScanned(Coord target) { } /** - * A simple limited flood-fill that returns a LinkedHashMap of Coord keys to the Double values in the DijkstraMap, only + * A simple limited flood-fill that returns a OrderedMap of Coord keys to the Double values in the DijkstraMap, only * calculating out to a number of steps determined by limit. This can be useful if you need many flood-fills and * don't need a large area for each, or if you want to have an effect spread to a certain number of cells away. * * @param radius the number of steps to take outward from each starting position. * @param starts a vararg group of Points to step outward from; this often will only need to be one Coord. - * @return A LinkedHashMap of Coord keys to Double values; the starts are included in this with the value 0.0. + * @return A OrderedMap of Coord keys to Double values; the starts are included in this with the value 0.0. */ - public LinkedHashMap floodFill(int radius, Coord... starts) { + public Map floodFill(int radius, Coord... starts) { if (!initialized) return null; - LinkedHashMap fill = new LinkedHashMap<>(); + OrderedMap fill = new OrderedMap<>(); resetMap(); for (Coord goal : starts) { diff --git a/squidlib-util/src/main/java/squidpony/squidai/LineAOE.java b/squidlib-util/src/main/java/squidpony/squidai/LineAOE.java index 842437e987..8aba513df7 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/LineAOE.java +++ b/squidlib-util/src/main/java/squidpony/squidai/LineAOE.java @@ -7,6 +7,9 @@ import squidpony.squidgrid.mapping.DungeonUtility; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; +import squidpony.squidmath.OrderedSet; + import java.util.*; /** @@ -259,14 +262,14 @@ public boolean mayContainTarget(Set targets) { } @Override - public LinkedHashMap> idealLocations(Set targets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set targets, Set requiredExclusions) { if(targets == null) - return new LinkedHashMap<>(); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + return new OrderedMap<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = targets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -404,14 +407,14 @@ else if(qualityMap[x][y] == bestQuality) } @Override - public LinkedHashMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { if(priorityTargets == null) return idealLocations(lesserTargets, requiredExclusions); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); //requiredExclusions.remove(origin); int totalTargets = priorityTargets.size() + lesserTargets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 8); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 8); if(totalTargets == 0) return bestPoints; @@ -694,7 +697,7 @@ public void setMap(char[][] map) { } @Override - public LinkedHashMap findArea() { + public OrderedMap findArea() { double[][] dmap = initDijkstra(); dmap[origin.x][origin.y] = DijkstraMap.DARK; dijkstra.resetMap(); diff --git a/squidlib-util/src/main/java/squidpony/squidai/PointAOE.java b/squidlib-util/src/main/java/squidpony/squidai/PointAOE.java index d6ea9b8471..07b5cf6094 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/PointAOE.java +++ b/squidlib-util/src/main/java/squidpony/squidai/PointAOE.java @@ -5,9 +5,10 @@ import squidpony.squidgrid.Radius; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; +import squidpony.squidmath.OrderedSet; + import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.Set; /** @@ -64,12 +65,12 @@ public boolean mayContainTarget(Set targets) { } @Override - public LinkedHashMap> idealLocations(Set targets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set targets, Set requiredExclusions) { if(targets == null) - return new LinkedHashMap<>(); + return new OrderedMap<>(); int totalTargets = targets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets); if(totalTargets == 0) return bestPoints; @@ -92,13 +93,13 @@ public LinkedHashMap> idealLocations(Set targets, @Override - public LinkedHashMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { + public OrderedMap> idealLocations(Set priorityTargets, Set lesserTargets, Set requiredExclusions) { if(priorityTargets == null) return idealLocations(lesserTargets, requiredExclusions); - if(requiredExclusions == null) requiredExclusions = new LinkedHashSet<>(); + if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); int totalTargets = priorityTargets.size() + lesserTargets.size(); - LinkedHashMap> bestPoints = new LinkedHashMap<>(totalTargets * 4); + OrderedMap> bestPoints = new OrderedMap<>(totalTargets * 4); if(totalTargets == 0) return bestPoints; @@ -222,8 +223,8 @@ public void setMap(char[][] map) { } @Override - public LinkedHashMap findArea() { - LinkedHashMap ret = new LinkedHashMap<>(1); + public OrderedMap findArea() { + OrderedMap ret = new OrderedMap<>(1); ret.put(Coord.get(center.x, center.y), 1.0); return ret; } diff --git a/squidlib-util/src/main/java/squidpony/squidai/Technique.java b/squidlib-util/src/main/java/squidpony/squidai/Technique.java index b7e84e4229..4da1cd9c88 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/Technique.java +++ b/squidlib-util/src/main/java/squidpony/squidai/Technique.java @@ -1,9 +1,9 @@ package squidpony.squidai; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.Set; /** @@ -127,9 +127,9 @@ public void setMap(char[][] map) * @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 LinkedHashMap of Coord keys representing target points to pass to apply, to ArrayList of Coord values representing what targets' locations will be affected. + * @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 LinkedHashMap> idealLocations(Coord user, Set targets, Set requiredExclusions) { + public OrderedMap> idealLocations(Coord user, Set targets, Set requiredExclusions) { aoe.setOrigin(user); return aoe.idealLocations(targets, requiredExclusions); @@ -151,9 +151,9 @@ public LinkedHashMap> idealLocations(Coord user, Set> idealLocations(Coord user, Set priorityTargets, Set lesserTargets, Set requiredExclusions) { + public OrderedMap> idealLocations(Coord user, Set priorityTargets, Set lesserTargets, Set requiredExclusions) { aoe.setOrigin(user); return aoe.idealLocations(priorityTargets, lesserTargets, requiredExclusions); } @@ -173,7 +173,7 @@ public LinkedHashMap> idealLocations(Coord user, Set apply(Coord user, Coord aimAt) + public OrderedMap apply(Coord user, Coord aimAt) { aoe.setOrigin(user); aoe.shift(aimAt); diff --git a/squidlib-util/src/main/java/squidpony/squidai/WaypointPathfinder.java b/squidlib-util/src/main/java/squidpony/squidai/WaypointPathfinder.java index e366a742ad..7d7e4e8a41 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/WaypointPathfinder.java +++ b/squidlib-util/src/main/java/squidpony/squidai/WaypointPathfinder.java @@ -8,6 +8,9 @@ import squidpony.squidmath.RNG; import squidpony.squidmath.StatefulRNG; +import squidpony.squidmath.OrderedMap; +import squidpony.squidmath.OrderedSet; + import java.util.*; import static squidpony.squidmath.CoordPacker.*; @@ -24,7 +27,7 @@ public class WaypointPathfinder { private char[][] map; private int[][] expansionMap; public RNG rng; - private LinkedHashMap> waypoints; + private OrderedMap> waypoints; /** * Calculates and stores the doors and doors-like connections ("chokepoints") on the given map as waypoints. @@ -48,7 +51,7 @@ public WaypointPathfinder(char[][] map, Radius measurement, RNG rng) Math.min(width, height) * 0.4f, this.rng, '#'); int centerCount = centers.size(); expansionMap = new int[width][height]; - waypoints = new LinkedHashMap<>(64); + waypoints = new OrderedMap<>(64); dm = new DijkstraMap(simplified, DijkstraMap.Measurement.MANHATTAN); for (Coord center : centers) { @@ -79,7 +82,7 @@ public WaypointPathfinder(char[][] map, Radius measurement, RNG rng) } } - LinkedHashSet chokes = new LinkedHashSet<>(128); + OrderedSet chokes = new OrderedSet<>(128); for (int i = 0; i < width; i++) { ELEMENT_WISE: for (int j = 0; j < height; j++) { @@ -101,7 +104,7 @@ public WaypointPathfinder(char[][] map, Radius measurement, RNG rng) if(good) { Coord chk = Coord.get(i, j); chokes.add(chk); - waypoints.put(chk, new LinkedHashMap()); + waypoints.put(chk, new OrderedMap()); } } } @@ -135,7 +138,7 @@ else if(centers.contains(Coord.get(x, y))) dm = new DijkstraMap(map, DijkstraMap.findMeasurement(measurement)); int e = 0; - for(Map.Entry> n : waypoints.entrySet()) + for(Map.Entry> n : waypoints.entrySet()) { chokes.remove(n.getKey()); if(chokes.isEmpty()) @@ -171,8 +174,8 @@ public WaypointPathfinder(char[][] map, Radius measurement, RNG rng, boolean thi height = map[0].length; char[][] simplified = DungeonUtility.simplifyDungeon(map); expansionMap = new int[width][height]; - waypoints = new LinkedHashMap<>(64); - LinkedHashSet chokes = new LinkedHashSet<>(128); + waypoints = new OrderedMap<>(64); + OrderedSet chokes = new OrderedSet<>(128); if(thickCorridors) { @@ -183,7 +186,7 @@ public WaypointPathfinder(char[][] map, Radius measurement, RNG rng, boolean thi Coord[] apart = apartPacked(doors, 1); Collections.addAll(chokes, apart); for (int i = 0; i < apart.length; i++) { - waypoints.put(apart[i], new LinkedHashMap()); + waypoints.put(apart[i], new OrderedMap()); } } else { @@ -241,7 +244,7 @@ public WaypointPathfinder(char[][] map, Radius measurement, RNG rng, boolean thi if (good) { Coord chk = Coord.get(i, j); chokes.add(chk); - waypoints.put(chk, new LinkedHashMap()); + waypoints.put(chk, new OrderedMap()); } } } @@ -250,7 +253,7 @@ public WaypointPathfinder(char[][] map, Radius measurement, RNG rng, boolean thi dm = new DijkstraMap(map, DijkstraMap.findMeasurement(measurement)); int e = 0; - for(Map.Entry> n : waypoints.entrySet()) + for(Map.Entry> n : waypoints.entrySet()) { chokes.remove(n.getKey()); if(chokes.isEmpty()) @@ -292,20 +295,20 @@ public WaypointPathfinder(char[][] map, Radius measurement, RNG rng, int fractio height = map[0].length; char[][] simplified = DungeonUtility.simplifyDungeon(map); expansionMap = new int[width][height]; - waypoints = new LinkedHashMap<>(64); - LinkedHashSet chokes = new LinkedHashSet<>(128); + waypoints = new OrderedMap<>(64); + OrderedSet 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 LinkedHashMap()); + waypoints.put(apart[i], new OrderedMap()); } dm = new DijkstraMap(map, DijkstraMap.findMeasurement(measurement)); int e = 0; - for(Map.Entry> n : waypoints.entrySet()) + for(Map.Entry> n : waypoints.entrySet()) { chokes.remove(n.getKey()); if(chokes.isEmpty()) @@ -345,7 +348,7 @@ public WaypointPathfinder(char[][] map, DijkstraMap dijkstra, RNG rng) Math.min(width, height) * 0.4f, this.rng, '#'); int centerCount = centers.size(); expansionMap = new int[width][height]; - waypoints = new LinkedHashMap<>(64); + waypoints = new OrderedMap<>(64); dm = new DijkstraMap(simplified, DijkstraMap.Measurement.MANHATTAN); for (Coord center : centers) { @@ -376,7 +379,7 @@ public WaypointPathfinder(char[][] map, DijkstraMap dijkstra, RNG rng) } } - LinkedHashSet chokes = new LinkedHashSet<>(128); + OrderedSet chokes = new OrderedSet<>(128); for (int i = 0; i < width; i++) { ELEMENT_WISE: for (int j = 0; j < height; j++) { @@ -397,13 +400,13 @@ public WaypointPathfinder(char[][] map, DijkstraMap dijkstra, RNG rng) if(good) { Coord chk = Coord.get(i, j); chokes.add(chk); - waypoints.put(chk, new LinkedHashMap()); + waypoints.put(chk, new OrderedMap()); } } } dm = dijkstra; int e = 0; - for(Map.Entry> n : waypoints.entrySet()) + for(Map.Entry> n : waypoints.entrySet()) { chokes.remove(n.getKey()); if(chokes.isEmpty()) @@ -484,9 +487,9 @@ public ArrayList goBackToPath(Coord currentPosition, ArrayList pat return dm.findShortcutPath(currentPosition, path.toArray(new Coord[path.size()])); } - public LinkedHashSet getWaypoints() + public OrderedSet getWaypoints() { - return new LinkedHashSet<>(waypoints.keySet()); + return new OrderedSet<>(waypoints.keySet()); } private static class Edge implements Comparable diff --git a/squidlib-util/src/main/java/squidpony/squidai/ZOI.java b/squidlib-util/src/main/java/squidpony/squidai/ZOI.java index d3fa1b3aa1..db0aa8072a 100644 --- a/squidlib-util/src/main/java/squidpony/squidai/ZOI.java +++ b/squidlib-util/src/main/java/squidpony/squidai/ZOI.java @@ -4,9 +4,10 @@ import squidpony.squidgrid.Radius; import squidpony.squidmath.Coord; import squidpony.squidmath.CoordPacker; +import squidpony.squidmath.OrderedSet; import squidpony.squidmath.ShortVLA; -import java.util.*; +import java.util.Collections; /** * Calculates the Zone of Influence, also known as Zone of Control, for different points on a map. @@ -116,7 +117,7 @@ public short[][] calculate() return packedGroups; } protected boolean[][] increasing(double[][] dm, Coord[] inf) { - LinkedHashSet open = new LinkedHashSet<>(64), fresh = new LinkedHashSet<>(64); + OrderedSet 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]; @@ -147,7 +148,7 @@ protected boolean[][] increasing(double[][] dm, Coord[] inf) { } } - open = new LinkedHashSet<>(fresh); + open = new OrderedSet<>(fresh); fresh.clear(); } diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/DetailedMimic.java b/squidlib-util/src/main/java/squidpony/squidgrid/DetailedMimic.java index b24269cadc..d5a2ac58dc 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/DetailedMimic.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/DetailedMimic.java @@ -12,11 +12,10 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of import squidpony.GwtCompatibility; import squidpony.squidgrid.mapping.AestheticDifference; +import squidpony.squidmath.IntDoubleOrderedMap; +import squidpony.squidmath.OrderedSet; import squidpony.squidmath.RNG; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; - /** * Similar to MimicFill, this class can be used to imitate the style of an existing piece of data, but this works on * more than just booleans; it can produce similar styles of texture (its original use in SynTex), of map, of item @@ -71,7 +70,7 @@ private void analysis(int[] bitmap, int width, int height, int K, int N, boolean { int area = width * height; analyzed = new int[area][]; - LinkedHashSet points = new LinkedHashSet<>(area); + OrderedSet points = new OrderedSet<>(area); for (int i = 0; i < area; i++) points.add(i); double[] similarities = new double[area * area]; @@ -82,7 +81,7 @@ private void analysis(int[] bitmap, int width, int height, int K, int N, boolean for (int i = 0; i < area; i++) { analyzed[i] = new int[K]; - LinkedHashSet copy = new LinkedHashSet<>(points); + OrderedSet copy = new OrderedSet<>(points); analyzed[i][0] = i; copy.remove(i); @@ -117,7 +116,7 @@ private int[] coherentSynthesis(int[] sample, int SW, int SH, int[][] sets, int for (int i = 0; i < OW * OH; i++) { int x = i % OW, y = i / OW; - LinkedHashMap candidates = new LinkedHashMap(); + IntDoubleOrderedMap candidates = new IntDoubleOrderedMap(); GwtCompatibility.insert2D(cleanMask, mask, 0, 0); for (int dy = -1; dy <= 1; dy++){ @@ -240,15 +239,11 @@ private static int weightedRandom(double[] array, double r) return 0; } - private static int weightedRandom(LinkedHashMap dic, double r) { - Integer[] ints = new Integer[dic.size()]; + private static int weightedRandom(IntDoubleOrderedMap dic, double r) { + int[] ints = new int[dic.size()]; double[] doubles = new double[dic.size()]; dic.keySet().toArray(ints); - int i = 0; - for(Double d : dic.values()) - { - doubles[i++] = d; - } + dic.values().toArray(doubles); return ints[weightedRandom(doubles, r)]; } } \ No newline at end of file diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/FOVCache.java b/squidlib-util/src/main/java/squidpony/squidgrid/FOVCache.java index 64f648d8f2..cb1f53c133 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/FOVCache.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/FOVCache.java @@ -3,6 +3,7 @@ import squidpony.annotation.GwtIncompatible; import squidpony.squidgrid.mapping.DungeonUtility; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; import squidpony.squidmath.ShortVLA; import java.util.*; @@ -101,7 +102,7 @@ public class FOVCache extends FOV{ protected final int NUM_THREADS; private ExecutorService executor; protected double fovPermissiveness; - protected LinkedHashMap lights; + protected OrderedMap lights; protected Coord[] lightSources; protected int[] lightBrightnesses; private double[][] levels; @@ -143,7 +144,7 @@ public FOVCache(char[][] map, int maxRadius, Radius radiusKind) decay = 1.0 / maxRadius; this.radiusKind = radiusKind; fovPermissiveness = 0.9; - lights = new LinkedHashMap<>(); + lights = new OrderedMap<>(); cache = new short[mapLimit][][]; tmpCache = new short[mapLimit][][]; losCache = new short[mapLimit][]; @@ -212,7 +213,7 @@ public FOVCache(char[][] map, int maxRadius, int maxLOSRadius, Radius radiusKind decay = 1.0 / maxRadius; this.radiusKind = radiusKind; fovPermissiveness = 0.9; - lights = new LinkedHashMap<>(); + lights = new OrderedMap<>(); cache = new short[mapLimit][][]; tmpCache = new short[mapLimit][][]; losCache = new short[mapLimit][]; @@ -284,7 +285,7 @@ public FOVCache(char[][] map, int maxRadius, int maxLOSRadius, Radius radiusKind decay = 1.0 / maxRadius; this.radiusKind = radiusKind; fovPermissiveness = 0.9; - this.lights = new LinkedHashMap<>(lights); + this.lights = new OrderedMap<>(lights); cache = new short[mapLimit][][]; tmpCache = new short[mapLimit][][]; losCache = new short[mapLimit][]; diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/LOS.java b/squidlib-util/src/main/java/squidpony/squidgrid/LOS.java index 4b0f8c560f..9ec71a35f8 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/LOS.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/LOS.java @@ -166,8 +166,7 @@ public boolean isReachable(double[][] resistanceMap, int startx, int starty, int return bresenhamReachable(radiusStrategy); case ELIAS: throw new IllegalStateException("Elias LOS is Gwt Incompatible"); - /* FIXME Find a way around that */ - // Required to compile with GWT: + // Comment required to compile with GWT: // return eliasReachable(radiusStrategy); case RAY: return rayReachable(radiusStrategy); @@ -339,7 +338,7 @@ private boolean ddaReachable(Radius radiusStrategy) { private boolean thickReachable(Radius radiusStrategy) { lastPath = new LinkedList<>(); double dist = radiusStrategy.radius(startx, starty, targetx, targety), decay = 1 / dist; - LinkedHashSet visited = new LinkedHashSet<>((int) dist + 3); + OrderedSet visited = new OrderedSet<>((int) dist + 3); List> paths = new ArrayList<>(4); /* // actual corners paths.add(DDALine.line(startx, starty, targetx, targety, 0, 0)); @@ -387,7 +386,7 @@ private boolean thickReachable(Radius radiusStrategy) { private boolean brushReachable(Radius radiusStrategy, int spread) { lastPath = new LinkedList<>(); double dist = radiusStrategy.radius(startx, starty, targetx, targety) + spread * 2, decay = 1 / dist; - LinkedHashSet visited = new LinkedHashSet<>((int) (dist + 3) * spread); + OrderedSet visited = new OrderedSet<>((int) (dist + 3) * spread); List> paths = new ArrayList<>((int) (radiusStrategy.volume2D(spread) * 1.25)); int length = 0; List currentPath; diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/MultiSpill.java b/squidlib-util/src/main/java/squidpony/squidgrid/MultiSpill.java index 360608067a..70eeabb077 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/MultiSpill.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/MultiSpill.java @@ -2,13 +2,13 @@ import squidpony.squidgrid.Spill.Measurement; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedSet; import squidpony.squidmath.RNG; import squidpony.squidmath.StatefulRNG; import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -66,7 +66,7 @@ public class MultiSpill { * are reached on all sides and the Spill has no more room to fill. */ public int filled = 0; - private ArrayList> fresh; + private ArrayList> fresh; /** * The StatefulRNG used to decide how to randomly fill a space; can have its state set and read. */ @@ -308,7 +308,7 @@ protected void setFresh(int idx, int x, int y) { protected void setFresh(int idx, final Coord pt) { if(!initialized) return; - for(LinkedHashSet f : fresh) + for(OrderedSet f : fresh) { if(f.contains(pt)) return; @@ -337,7 +337,7 @@ protected void setFresh(int idx, final Coord pt) { public ArrayList> start(List entries, int volume, Set impassable) { if(!initialized) return null; if(impassable == null) - impassable = new LinkedHashSet<>(); + impassable = new OrderedSet<>(); if(volume < 0) volume = Integer.MAX_VALUE; ArrayList spillers = new ArrayList<>(entries); @@ -345,7 +345,7 @@ public ArrayList> start(List entries, int volume, Set(128)); - fresh.add(new LinkedHashSet(128)); + fresh.add(new OrderedSet(128)); Coord c = spillers.get(i); spillMap[c.x][c.y] = i; @@ -366,7 +366,7 @@ public ArrayList> start(List entries, int volume, Set currentFresh = fresh.get(i); + OrderedSet currentFresh = fresh.get(i); if(currentFresh.isEmpty()) continue; else @@ -416,10 +416,10 @@ public ArrayList> start(List entries, int volume, Set> start(LinkedHashMap entries, int volume, Set impassable) { + public ArrayList> start(Map entries, int volume, Set impassable) { if(!initialized) return null; if(impassable == null) - impassable = new LinkedHashSet<>(); + impassable = new OrderedSet<>(); if(volume < 0) volume = Integer.MAX_VALUE; ArrayList spillers0 = new ArrayList<>(entries.keySet()), @@ -430,7 +430,7 @@ public ArrayList> start(LinkedHashMap entries, i fresh.clear(); for (short i = 0, ctr = 0; i < spillers0.size(); i++, ctr++) { spreadPattern.add(new ArrayList(128)); - fresh.add(new LinkedHashSet(128)); + fresh.add(new OrderedSet(128)); Coord c = spillers0.get(i); spillers.add(c); biases.add(biases0.get(i)); @@ -456,7 +456,7 @@ public ArrayList> start(LinkedHashMap entries, i while (hasFresh && filled < volume) { hasFresh = false; for (short i = 0; i < spillers.size() && filled < volume; i++) { - LinkedHashSet currentFresh = fresh.get(i); + OrderedSet currentFresh = fresh.get(i); if(currentFresh.isEmpty()) continue; else diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/Radius.java b/squidlib-util/src/main/java/squidpony/squidgrid/Radius.java index f705dd05ab..b18a69f6c7 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/Radius.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/Radius.java @@ -2,9 +2,9 @@ import squidpony.squidmath.Coord; import squidpony.squidmath.Coord3D; +import squidpony.squidmath.OrderedSet; import squidpony.squidmath.RNG; -import java.util.LinkedHashSet; import java.util.Set; /** @@ -229,7 +229,7 @@ private int clamp(int n, int min, int max) public Set perimeter(Coord center, int radiusLength, boolean surpassEdges, int width, int height) { - LinkedHashSet rim = new LinkedHashSet<>(4 * radiusLength); + OrderedSet rim = new OrderedSet<>(4 * radiusLength); if(!surpassEdges && (center.x < 0 || center.x >= width || center.y < 0 || center.y > height)) return rim; if(radiusLength < 1) { @@ -445,7 +445,7 @@ else if(x < y) public Set pointsInside(Coord center, int radiusLength, boolean surpassEdges, int width, int height) { - LinkedHashSet contents = new LinkedHashSet((int)Math.ceil(volume2D(radiusLength))); + OrderedSet contents = new OrderedSet((int)Math.ceil(volume2D(radiusLength))); if(!surpassEdges && (center.x < 0 || center.x >= width || center.y < 0 || center.y >= height)) return contents; if(radiusLength < 1) { @@ -510,7 +510,7 @@ public Set pointsInside(Coord center, int radiusLength, boolean surpassEd public Set expand(int distance, int width, int height, Iterable points) { Set around = pointsInside(Coord.get(distance, distance), distance, false, width, height), - expanded = new LinkedHashSet<>(around.size() * 16); + expanded = new OrderedSet<>(around.size() * 16); int tx, ty; for(Coord pt : points) { diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/SoundMap.java b/squidlib-util/src/main/java/squidpony/squidgrid/SoundMap.java index a3474475d7..e8a0aa5660 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/SoundMap.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/SoundMap.java @@ -2,9 +2,9 @@ import squidpony.squidmath.Coord; import squidpony.squidmath.LightRNG; +import squidpony.squidmath.OrderedMap; import squidpony.squidmath.RNG; -import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -62,7 +62,7 @@ public enum Measurement { * 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 HashMap alerted = new HashMap<>(); + public OrderedMap alerted = new OrderedMap<>(); /** * Cells with no sound are always marked with 0. */ @@ -75,8 +75,8 @@ public enum Measurement { * 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 HashMap sounds; - private HashMap fresh; + public OrderedMap sounds; + private OrderedMap fresh; /** * The RNG used to decide which one of multiple equally-short paths to take. */ @@ -89,9 +89,9 @@ public enum Measurement { */ public SoundMap() { rng = new RNG(new LightRNG()); - alerted = new HashMap<>(); - fresh = new HashMap<>(); - sounds = new HashMap<>(); + alerted = new OrderedMap<>(); + fresh = new OrderedMap<>(); + sounds = new OrderedMap<>(); } /** @@ -100,9 +100,9 @@ public SoundMap() { */ public SoundMap(RNG random) { rng = random; - alerted = new HashMap<>(); - fresh = new HashMap<>(); - sounds = new HashMap<>(); + alerted = new OrderedMap<>(); + fresh = new OrderedMap<>(); + sounds = new OrderedMap<>(); } /** @@ -111,9 +111,9 @@ public SoundMap(RNG random) { */ public SoundMap(final double[][] level) { rng = new RNG(new LightRNG()); - alerted = new HashMap<>(); - fresh = new HashMap<>(); - sounds = new HashMap<>(); + alerted = new OrderedMap<>(); + fresh = new OrderedMap<>(); + sounds = new OrderedMap<>(); initialize(level); } /** @@ -124,9 +124,9 @@ public SoundMap(final double[][] level) { public SoundMap(final double[][] level, Measurement measurement) { rng = new RNG(new LightRNG()); this.measurement = measurement; - alerted = new HashMap<>(); - fresh = new HashMap<>(); - sounds = new HashMap<>(); + alerted = new OrderedMap<>(); + fresh = new OrderedMap<>(); + sounds = new OrderedMap<>(); initialize(level); } @@ -140,9 +140,9 @@ public SoundMap(final double[][] level, Measurement measurement) { */ public SoundMap(final char[][] level) { rng = new RNG(new LightRNG()); - alerted = new HashMap<>(); - fresh = new HashMap<>(); - sounds = new HashMap<>(); + alerted = new OrderedMap<>(); + fresh = new OrderedMap<>(); + sounds = new OrderedMap<>(); initialize(level); } /** @@ -155,9 +155,9 @@ public SoundMap(final char[][] level) { */ public SoundMap(final char[][] level, char alternateWall) { rng = new RNG(new LightRNG()); - alerted = new HashMap<>(); - fresh = new HashMap<>(); - sounds = new HashMap<>(); + alerted = new OrderedMap<>(); + fresh = new OrderedMap<>(); + sounds = new OrderedMap<>(); initialize(level, alternateWall); } @@ -173,9 +173,9 @@ public SoundMap(final char[][] level, char alternateWall) { public SoundMap(final char[][] level, Measurement measurement) { rng = new RNG(new LightRNG()); this.measurement = measurement; - alerted = new HashMap<>(); - fresh = new HashMap<>(); - sounds = new HashMap<>(); + alerted = new OrderedMap<>(); + fresh = new OrderedMap<>(); + sounds = new OrderedMap<>(); initialize(level); } @@ -404,7 +404,7 @@ public double[][] scan() { while (numAssigned > 0) { numAssigned = 0; - HashMap fresh2 = new HashMap<>(fresh.size()); + OrderedMap fresh2 = new OrderedMap<>(fresh.size()); fresh2.putAll(fresh); fresh.clear(); @@ -449,9 +449,9 @@ public double[][] scan() { * @param extraSounds * @return */ - public HashMap findAlerted(Set creatures, Map extraSounds) { + public OrderedMap findAlerted(Set creatures, Map extraSounds) { if(!initialized) return null; - alerted = new HashMap<>(creatures.size()); + alerted = new OrderedMap<>(creatures.size()); resetMap(); for (Map.Entry sound : extraSounds.entrySet()) { diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/SpatialMap.java b/squidlib-util/src/main/java/squidpony/squidgrid/SpatialMap.java index 7c7165a2f7..56a0920217 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/SpatialMap.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/SpatialMap.java @@ -1,6 +1,8 @@ package squidpony.squidgrid; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedMap; +import squidpony.squidmath.OrderedSet; import java.util.*; @@ -11,7 +13,7 @@ * 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 LinkedHashMap fields internally. + * identity, which is never changed in this class). Uses two OrderedMap fields internally. * Created by Tommy Ettinger on 1/2/2016. */ public class SpatialMap implements Iterable { @@ -56,26 +58,26 @@ public int hashCode() { } } - protected LinkedHashMap> itemMapping; - protected LinkedHashMap> positionMapping; + protected OrderedMap> itemMapping; + protected OrderedMap> positionMapping; /** * Constructs a SpatialMap with capacity 32. */ public SpatialMap() { - itemMapping = new LinkedHashMap<>(32); - positionMapping = new LinkedHashMap<>(32); + itemMapping = new OrderedMap<>(32); + positionMapping = new OrderedMap<>(32); } /** * Constructs a SpatialMap with the given capacity - * @param capacity the capacity for each of the internal LinkedHashMaps + * @param capacity the capacity for each of the internal OrderedMaps */ public SpatialMap(int capacity) { - itemMapping = new LinkedHashMap<>(capacity); - positionMapping = new LinkedHashMap<>(capacity); + itemMapping = new OrderedMap<>(capacity); + positionMapping = new OrderedMap<>(capacity); } /** @@ -88,9 +90,9 @@ public SpatialMap(int capacity) */ public SpatialMap(Coord[] coords, I[] ids, E[] elements) { - itemMapping = new LinkedHashMap<>( + itemMapping = new OrderedMap<>( Math.min(coords.length, Math.min(ids.length, elements.length))); - positionMapping = new LinkedHashMap<>( + 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++) { @@ -109,9 +111,9 @@ public SpatialMap(Coord[] coords, I[] ids, E[] elements) */ public SpatialMap(Collection coords, Collection ids, Collection elements) { - itemMapping = new LinkedHashMap<>( + itemMapping = new OrderedMap<>( Math.min(coords.size(), Math.min(ids.size(), elements.size()))); - positionMapping = new LinkedHashMap<>( + positionMapping = new OrderedMap<>( Math.min(coords.size(), Math.min(ids.size(), elements.size()))); if(itemMapping.size() <= 0) return; @@ -383,22 +385,22 @@ public I getIdentity(Coord c) } /** - * Get a Set of all positions used for values in this data structure, returning a LinkedHashSet (defensively copying + * 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 LinkedHashSet of Coord corresponding to the positions present in this data structure. + * @return a OrderedSet of Coord corresponding to the positions present in this data structure. */ - public LinkedHashSet positions() + public OrderedSet positions() { - return new LinkedHashSet<>(positionMapping.keySet()); + return new OrderedSet<>(positionMapping.keySet()); } /** - * Get a Set of all identities used for values in this data structure, returning a LinkedHashSet (defensively + * 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 LinkedHashSet of I corresponding to the identities present in this data structure. + * @return a OrderedSet of I corresponding to the identities present in this data structure. */ - public LinkedHashSet identities() + public OrderedSet identities() { - return new LinkedHashSet<>(itemMapping.keySet()); + return new OrderedSet<>(itemMapping.keySet()); } /** diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/Spill.java b/squidlib-util/src/main/java/squidpony/squidgrid/Spill.java index a5f2ff8db4..482cbd9046 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/Spill.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/Spill.java @@ -1,12 +1,8 @@ package squidpony.squidgrid; -import squidpony.squidmath.Coord; -import squidpony.squidmath.LightRNG; -import squidpony.squidmath.RNG; -import squidpony.squidmath.StatefulRNG; +import squidpony.squidmath.*; import java.util.ArrayList; -import java.util.LinkedHashSet; import java.util.Set; /** * A randomized flood-fill implementation that can be used for level generation (e.g. filling ponds and lakes), for @@ -79,7 +75,7 @@ public enum Measurement { * are reached on all sides and the Spill has no more room to fill. */ public int filled = 0; - private LinkedHashSet fresh; + private OrderedSet fresh; /** * The RNG used to decide which one of multiple equally-short paths to take. */ @@ -98,7 +94,7 @@ public Spill() { lrng = new LightRNG(); rng = new StatefulRNG(lrng); - fresh = new LinkedHashSet<>(); + fresh = new OrderedSet<>(); } /** * Construct a Spill without a level to actually scan. This constructor allows you to specify an RNG, but the actual @@ -111,7 +107,7 @@ public Spill(RNG random) { lrng = new LightRNG(random.nextLong()); rng = new StatefulRNG(lrng); - fresh = new LinkedHashSet<>(); + fresh = new OrderedSet<>(); } /** @@ -125,7 +121,7 @@ public Spill(LightRNG random) { lrng = random; rng = new StatefulRNG(lrng); - fresh = new LinkedHashSet<>(); + fresh = new OrderedSet<>(); } /** @@ -245,7 +241,7 @@ public Spill(final char[][] level, Measurement measurement, LightRNG random) { * @return */ public Spill initialize(final boolean[][] level) { - fresh = new LinkedHashSet<>(); + fresh = new OrderedSet<>(); width = level.length; height = level[0].length; spillMap = new boolean[width][height]; @@ -268,7 +264,7 @@ public Spill initialize(final boolean[][] level) { * @return */ public Spill initialize(final char[][] level) { - fresh = new LinkedHashSet<>(); + fresh = new OrderedSet<>(); width = level.length; height = level[0].length; spillMap = new boolean[width][height]; @@ -293,7 +289,7 @@ public Spill initialize(final char[][] level) { * @return */ public Spill initialize(final char[][] level, char alternateWall) { - fresh = new LinkedHashSet<>(); + fresh = new OrderedSet<>(); width = level.length; height = level[0].length; spillMap = new boolean[width][height]; @@ -378,7 +374,7 @@ protected void setFresh(final Coord pt) { public ArrayList start(Coord entry, int volume, Set impassable) { if(!initialized) return null; if(impassable == null) - impassable = new LinkedHashSet<>(); + impassable = new OrderedSet<>(); if(!physicalMap[entry.x][entry.y] || impassable.contains(entry)) return null; spreadPattern = new ArrayList<>(volume); diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/DungeonGenerator.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/DungeonGenerator.java index 70189cdc0d..f2631ff4df 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/DungeonGenerator.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/DungeonGenerator.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.EnumMap; -import java.util.LinkedHashSet; import static squidpony.squidmath.CoordPacker.*; @@ -326,7 +325,7 @@ public DungeonGenerator clearEffects() return this; } - protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord pt) + protected OrderedSet removeAdjacent(OrderedSet coll, Coord pt) { for(Coord temp : new Coord[]{Coord.get(pt.x + 1, pt.y), Coord.get(pt.x - 1, pt.y), Coord.get(pt.x, pt.y + 1), Coord.get(pt.x, pt.y - 1)}) @@ -337,7 +336,7 @@ protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord p return coll; } - protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord pt1, Coord pt2) + protected OrderedSet removeAdjacent(OrderedSet coll, Coord pt1, Coord pt2) { for(Coord temp : new Coord[]{Coord.get(pt1.x + 1, pt1.y), Coord.get(pt1.x - 1, pt1.y), @@ -352,9 +351,9 @@ protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord p return coll; } - protected LinkedHashSet viableDoorways(boolean doubleDoors, char[][] map) + protected OrderedSet viableDoorways(boolean doubleDoors, char[][] map) { - LinkedHashSet doors = new LinkedHashSet<>(); + OrderedSet doors = new OrderedSet<>(); for(int x = 1; x < map.length - 1; x++) { for (int y = 1; y < map[x].length - 1; y++) { if(map[x][y] == '#') @@ -544,8 +543,8 @@ public char[][] generateRespectingStairs(char[][] baseDungeon) { private char[][] innerGenerate(char[][] map) { - LinkedHashSet doorways; - LinkedHashSet hazards = new LinkedHashSet<>(); + OrderedSet doorways; + OrderedSet hazards = new OrderedSet<>(); Coord temp; boolean doubleDoors = false; int floorCount = DungeonUtility.countCells(map, '.'), @@ -582,7 +581,7 @@ private char[][] innerGenerate(char[][] map) doorways = viableDoorways(doubleDoors, map); - LinkedHashSet obstacles = new LinkedHashSet<>(doorways.size() * doorFill / 100); + OrderedSet obstacles = new OrderedSet<>(doorways.size() * doorFill / 100); if(doorFill > 0) { int total = doorways.size() * doorFill / 100; diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/LanesMapGenerator.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/LanesMapGenerator.java index b8acc6fe9e..a0cb93c7af 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/LanesMapGenerator.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/LanesMapGenerator.java @@ -1,12 +1,8 @@ package squidpony.squidgrid.mapping; -import squidpony.squidmath.Coord; -import squidpony.squidmath.CoordPacker; -import squidpony.squidmath.DDALine; -import squidpony.squidmath.RNG; +import squidpony.squidmath.*; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; /** @@ -116,7 +112,7 @@ public LanesMapGenerator(int width, int height, RNG rng, int lanes) } - LinkedHashMap> connections = new LinkedHashMap<>(80); + OrderedMap> connections = new OrderedMap<>(80); Coord temp, t; int m = random.nextInt(32), r = random.between(8, 24); temp = CoordPacker.hilbertToCoord(m); diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/LegacyDungeonGenerator.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/LegacyDungeonGenerator.java index 3316b3b9ee..0ee6abcab4 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/LegacyDungeonGenerator.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/LegacyDungeonGenerator.java @@ -5,14 +5,9 @@ import squidpony.squidgrid.Spill; import squidpony.squidgrid.mapping.styled.DungeonBoneGen; import squidpony.squidgrid.mapping.styled.TilesetType; -import squidpony.squidmath.Coord; -import squidpony.squidmath.CoordPacker; -import squidpony.squidmath.PoissonDisk; -import squidpony.squidmath.RNG; +import squidpony.squidmath.*; import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import static squidpony.squidmath.CoordPacker.*; @@ -269,17 +264,17 @@ public DungeonGenerator clearEffects() { } @Override - protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord pt) { + protected OrderedSet removeAdjacent(OrderedSet coll, Coord pt) { return super.removeAdjacent(coll, pt); } @Override - protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord pt1, Coord pt2) { + protected OrderedSet removeAdjacent(OrderedSet coll, Coord pt1, Coord pt2) { return super.removeAdjacent(coll, pt1, pt2); } @Override - protected LinkedHashSet viableDoorways(boolean doubleDoors, char[][] map) { + protected OrderedSet viableDoorways(boolean doubleDoors, char[][] map) { return super.viableDoorways(doubleDoors, map); } @@ -415,9 +410,9 @@ public char[][] generateRespectingStairs(char[][] baseDungeon) { private char[][] innerGenerate(char[][] map) { - LinkedHashSet floors = new LinkedHashSet<>(); - LinkedHashSet doorways; - LinkedHashSet hazards = new LinkedHashSet<>(); + OrderedSet floors = new OrderedSet<>(); + OrderedSet doorways; + OrderedSet hazards = new OrderedSet<>(); Coord temp; boolean doubleDoors = false; int doorFill = 0; @@ -460,7 +455,7 @@ private char[][] innerGenerate(char[][] map) floorRate -= waterRate + grassRate; doorways = viableDoorways(doubleDoors, map); - LinkedHashSet obstacles = new LinkedHashSet<>(doorways.size() * doorFill / 100); + OrderedSet obstacles = new OrderedSet<>(doorways.size() * doorFill / 100); if(doorFill > 0) { int total = doorways.size() * doorFill / 100; @@ -528,7 +523,7 @@ private char[][] innerGenerate(char[][] map) } MultiSpill ms = new MultiSpill(map, Spill.Measurement.MANHATTAN, rng); - LinkedHashMap fillers = new LinkedHashMap<>(128); + OrderedMap fillers = new OrderedMap<>(128); ArrayList dots = PoissonDisk.sampleMap(map, Math.min(width, height) / 8f, rng, '#', '+', '/','<', '>'); for (int i = 0; i < dots.size(); i++) { switch (i % 3) { @@ -629,9 +624,9 @@ private char[][] innerGenerate(char[][] map) private char[][] innerGenerateOld(char[][] map) { - LinkedHashSet floors = new LinkedHashSet<>(); - LinkedHashSet doorways; - LinkedHashSet hazards = new LinkedHashSet<>(); + OrderedSet floors = new OrderedSet<>(); + OrderedSet doorways; + OrderedSet hazards = new OrderedSet<>(); Coord temp; boolean doubleDoors = false; int doorFill = 0; @@ -663,7 +658,7 @@ private char[][] innerGenerateOld(char[][] map) doorways = viableDoorways(doubleDoors, map); - LinkedHashSet obstacles = new LinkedHashSet<>(doorways.size() * doorFill / 100); + OrderedSet obstacles = new OrderedSet<>(doorways.size() * doorFill / 100); if(doorFill > 0) { int total = doorways.size() * doorFill / 100; diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/ModularMapGenerator.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/ModularMapGenerator.java index f9289d2cb3..6a4d814413 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/ModularMapGenerator.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/ModularMapGenerator.java @@ -27,8 +27,8 @@ public class ModularMapGenerator { protected int[][] environment = null; //public RegionMap layout, modules, inverseModules; public RegionMap layout; - public LinkedHashMap> modules; - public LinkedHashMap displacement; + public OrderedMap> modules; + public OrderedMap displacement; private void putModule(short[] module) { char[][] unp = CoordPacker.unpackChar(module, '.', '#'); @@ -60,12 +60,12 @@ private void initModules() { layout = new RegionMap<>(64); //modules = new RegionMap<>(64); //inverseModules = new RegionMap<>(64); - modules = new LinkedHashMap<>(64); + modules = new OrderedMap<>(64); for (int i = 1; i <= 64; i <<= 1) { ArrayList mms = new ArrayList<>(16); modules.put(i, mms); } - displacement = new LinkedHashMap<>(64); + displacement = new OrderedMap<>(64); float multiplier = 1;//(float) Math.sqrt(Math.max(1f, Math.min(width, height) / 24f)); putRectangle(2, 2, multiplier); putRectangle(3, 3, multiplier); @@ -144,7 +144,7 @@ public ModularMapGenerator(ModularMapGenerator copying) { map = GwtCompatibility.copy2D(copying.map); environment = GwtCompatibility.copy2D(copying.environment); layout = new RegionMap<>(copying.layout); - modules = new LinkedHashMap<>(copying.modules); + modules = new OrderedMap<>(copying.modules); } /** diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/Placement.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/Placement.java index 14c96524fd..e6c621061b 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/Placement.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/Placement.java @@ -3,9 +3,7 @@ import squidpony.squidgrid.FOV; import squidpony.squidgrid.Radius; import squidpony.squidmath.Coord; - -import java.util.Collections; -import java.util.LinkedHashSet; +import squidpony.squidmath.OrderedSet; import static squidpony.squidmath.CoordPacker.*; @@ -24,9 +22,9 @@ public class Placement { private short[] allRooms = ALL_WALL, allCaves = ALL_WALL, allCorridors = ALL_WALL, allFloors = ALL_WALL, nonRoom; - private LinkedHashSet> alongStraightWalls = null, + private OrderedSet> alongStraightWalls = null, corners = null, centers = null; - private LinkedHashSet hidingPlaces = null; + private OrderedSet hidingPlaces = null; private Placement() { @@ -63,16 +61,16 @@ public Placement(RoomFinder finder) } /** - * Gets a LinkedHashSet of LinkedHashSet of Coord, where each inner LinkedHashSet of Coord refers to a placement + * Gets an OrderedSet of OrderedSet of Coord, where each inner OrderedSet of Coord refers to a placement * region along a straight wall with length 3 or more, not including corners. Each Coord refers to a single cell * along the straight wall. This could be useful for placing weapon racks in armories, chalkboards in schoolrooms * (tutorial missions, perhaps?), or even large paintings/murals in palaces. * @return a set of sets of Coord where each set of Coord is a wall's viable placement for long things along it */ - public LinkedHashSet> getAlongStraightWalls() { + public OrderedSet> getAlongStraightWalls() { if(alongStraightWalls == null) { - alongStraightWalls = new LinkedHashSet<>(32); + alongStraightWalls = new OrderedSet<>(32); short[] working; for(short[] region : finder.rooms.keys()) { working = @@ -92,16 +90,16 @@ public LinkedHashSet> getAlongStraightWalls() { } /** - * Gets a LinkedHashSet of LinkedHashSet of Coord, where each inner LinkedHashSet of Coord refers to a room's + * Gets an OrderedSet of OrderedSet of Coord, where each inner OrderedSet of Coord refers to a room's * corners, and each Coord is one of those corners. There are more uses for corner placement than I can list. This * doesn't always identify all corners, since it only finds ones in rooms, and a cave too close to a corner can * cause that corner to be ignored. * @return a set of sets of Coord where each set of Coord is a room's corners */ - public LinkedHashSet> getCorners() { + public OrderedSet> getCorners() { if(corners == null) { - corners = new LinkedHashSet<>(32); + corners = new OrderedSet<>(32); short[] working; for(short[] region : finder.rooms.keys()) { working = @@ -114,7 +112,7 @@ public LinkedHashSet> getCorners() { nonRoom); for(Coord c : allPacked(working)) { - LinkedHashSet lhs = new LinkedHashSet(); + OrderedSet lhs = new OrderedSet(); lhs.add(c); corners.add(lhs); } @@ -124,7 +122,7 @@ public LinkedHashSet> getCorners() { return corners; } /** - * Gets a LinkedHashSet of LinkedHashSet of Coord, where each inner LinkedHashSet of Coord refers to a room's cells + * Gets an OrderedSet of OrderedSet of Coord, where each inner OrderedSet of Coord refers to a room's cells * that are furthest from the walls, and each Coord is one of those central positions. There are many uses for this, * like finding a position to place a throne or shrine in a large room where it should be visible from all around. * This doesn't always identify all centers, since it only finds ones in rooms, and it can also find multiple @@ -132,10 +130,10 @@ public LinkedHashSet> getCorners() { * find a 1x5 column as the centers of that room). * @return a set of sets of Coord where each set of Coord contains a room's cells that are furthest from the walls. */ - public LinkedHashSet> getCenters() { + public OrderedSet> getCenters() { if(centers == null) { - centers = new LinkedHashSet<>(32); + centers = new OrderedSet<>(32); short[] working, working2; for(short[] region : finder.rooms.keys()) { @@ -162,16 +160,16 @@ public LinkedHashSet> getCenters() { } /** - * Gets a LinkedHashSet of Coord, where each Coord is hidden (using the given radiusStrategy and range for FOV + * Gets an OrderedSet of Coord, where each Coord is hidden (using the given radiusStrategy and range for FOV * calculations) from any doorways or similar narrow choke-points where a character might be easily ambushed. If * multiple choke-points can see a cell (using shadow-casting FOV, which is asymmetrical), then the cell is very * unlikely to be included in the returned Coords, but if a cell is visible from one or no choke-points and is far * enough away, then it is more likely to be included. * @param radiusStrategy a Radius object that will be used to determine visibility. * @param range the minimum distance things are expected to hide at; often related to player FOV range - * @return a set of Coord where each Coord is either far away from or is concealed from a door-like area + * @return a Set of Coord where each Coord is either far away from or is concealed from a door-like area */ - public LinkedHashSet getHidingPlaces(Radius radiusStrategy, int range) { + public OrderedSet getHidingPlaces(Radius radiusStrategy, int range) { if(hidingPlaces == null) { double[][] composite = new double[finder.width][finder.height], @@ -193,10 +191,8 @@ public LinkedHashSet getHidingPlaces(Radius radiusStrategy, int range) { return hidingPlaces; } - private static LinkedHashSet arrayToSet(Coord[] arr) + private static OrderedSet arrayToSet(Coord[] arr) { - LinkedHashSet lhs = new LinkedHashSet<>(arr.length); - Collections.addAll(lhs, arr); - return lhs; + return new OrderedSet (arr); } } diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/RoomFinder.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/RoomFinder.java index 36a79283c9..0cfe7b9c97 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/RoomFinder.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/RoomFinder.java @@ -2,11 +2,11 @@ import squidpony.GwtCompatibility; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedSet; import squidpony.squidmath.RegionMap; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashSet; import java.util.List; import static squidpony.squidmath.CoordPacker.*; @@ -370,7 +370,7 @@ public static char[][] merge(ArrayList regions, int width, int height) */ public char[][] regionAt(int x, int y) { - LinkedHashSet regions = rooms.regionsContaining(x, y); + OrderedSet regions = rooms.regionsContaining(x, y); regions.addAll(corridors.regionsContaining(x, y)); regions.addAll(caves.regionsContaining(x, y)); short[] found; @@ -390,7 +390,7 @@ public char[][] regionAt(int x, int y) */ public char[][] regionsNear(int x, int y) { - LinkedHashSet regions = rooms.regionsContaining(x, y); + OrderedSet regions = rooms.regionsContaining(x, y); regions.addAll(corridors.regionsContaining(x, y)); regions.addAll(caves.regionsContaining(x, y)); short[] found; @@ -399,7 +399,7 @@ public char[][] regionsNear(int x, int y) else { found = GwtCompatibility.first(regions); - LinkedHashSet> near = rooms.allAt(x, y); + OrderedSet> near = rooms.allAt(x, y); for (List links : near) { for(short[] n : links) { @@ -434,7 +434,7 @@ public char[][] regionsNear(int x, int y) public ArrayList regionsConnected(int x, int y) { ArrayList regions = new ArrayList<>(10); - LinkedHashSet> near = rooms.allAt(x, y); + OrderedSet> near = rooms.allAt(x, y); for (List links : near) { for(short[] n : links) { diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SectionDungeonGenerator.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SectionDungeonGenerator.java index ed0fc0e50b..81a39ee761 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SectionDungeonGenerator.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SectionDungeonGenerator.java @@ -564,7 +564,7 @@ public SectionDungeonGenerator clearEffects() return this; } - protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord pt) + protected OrderedSet removeAdjacent(OrderedSet coll, Coord pt) { for(Coord temp : new Coord[]{Coord.get(pt.x + 1, pt.y), Coord.get(pt.x - 1, pt.y), Coord.get(pt.x, pt.y + 1), Coord.get(pt.x, pt.y - 1)}) @@ -575,7 +575,7 @@ protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord p return coll; } - protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord pt1, Coord pt2) + protected OrderedSet removeAdjacent(OrderedSet coll, Coord pt1, Coord pt2) { for(Coord temp : new Coord[]{Coord.get(pt1.x + 1, pt1.y), Coord.get(pt1.x - 1, pt1.y), @@ -589,11 +589,11 @@ protected LinkedHashSet removeAdjacent(LinkedHashSet coll, Coord p return coll; } - protected LinkedHashSet removeNearby(LinkedHashSet coll, char[][] disallowed) + protected OrderedSet removeNearby(OrderedSet coll, char[][] disallowed) { if(coll == null || disallowed == null || disallowed.length == 0 || disallowed[0].length == 0) - return new LinkedHashSet<>(); - LinkedHashSet next = new LinkedHashSet<>(coll.size()); + return new OrderedSet<>(); + OrderedSet next = new OrderedSet<>(coll.size()); int width = disallowed.length, height = disallowed[0].length; COORD_WISE: for(Coord c : coll) @@ -612,10 +612,10 @@ protected LinkedHashSet removeNearby(LinkedHashSet coll, char[][] } - protected LinkedHashSet viableDoorways(boolean doubleDoors, char[][] map, char[][] allCaves, + protected OrderedSet viableDoorways(boolean doubleDoors, char[][] map, char[][] allCaves, char[][] allCorridors) { - LinkedHashSet doors = new LinkedHashSet<>(); + OrderedSet doors = new OrderedSet<>(); for(int x = 1; x < map.length - 1; x++) { for (int y = 1; y < map[x].length - 1; y++) { if(map[x][y] == '#' || allCorridors[x][y] != '#') @@ -917,7 +917,7 @@ private char[][] makeDoors(ArrayList rooms, ArrayList corrid map = RoomFinder.merge(fused, width, height); - LinkedHashSet doorways = viableDoorways(doubleDoors, map, allCaves, allCorridors); + OrderedSet doorways = viableDoorways(doubleDoors, map, allCaves, allCorridors); int total = doorways.size() * doorFill / 100; @@ -1063,7 +1063,7 @@ else if (shallow[x][y]) private char[][] innerGenerate(char[][] map, EnumMap fx) { - LinkedHashSet hazards = new LinkedHashSet<>(); + OrderedSet hazards = new OrderedSet<>(); int floorCount = DungeonUtility.countCells(map, '.'), doorFill = 0, waterFill = 0, diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SerpentDeepMapGenerator.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SerpentDeepMapGenerator.java index bfa96cea3e..4b3cfef2b6 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SerpentDeepMapGenerator.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SerpentDeepMapGenerator.java @@ -1,12 +1,8 @@ package squidpony.squidgrid.mapping; -import squidpony.squidmath.Coord; -import squidpony.squidmath.CoordPacker; -import squidpony.squidmath.RNG; +import squidpony.squidmath.*; import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; /** @@ -24,7 +20,7 @@ public class SerpentDeepMapGenerator { private MixedGenerator[] mix; private int[] columns, rows; private int width, height, depth; - private ArrayList> linksUp,linksDown; + private ArrayList> linksUp,linksDown; private RNG random; /** @@ -79,8 +75,8 @@ public SerpentDeepMapGenerator(int width, int height, int depth, RNG rng, double linksUp = new ArrayList<>(depth); linksDown = new ArrayList<>(depth); for (int i = 0; i < depth; i++) { - linksUp.add(new LinkedHashSet(80)); - linksDown.add(new LinkedHashSet(80)); + linksUp.add(new OrderedSet(80)); + linksDown.add(new OrderedSet(80)); } int csum = 0, rsum = 0; long b = 3; @@ -106,9 +102,9 @@ public SerpentDeepMapGenerator(int width, int height, int depth, RNG rng, double rows[i] += rs3; } - List>> connections = new ArrayList<>(depth); + List>> connections = new ArrayList<>(depth); for (int i = 0; i < depth; i++) { - connections.add(new LinkedHashMap>(80)); + connections.add(new OrderedMap>(80)); } int m = random.nextInt(0x800 * numLayers); int x = CoordPacker.getXMoore3D(m, numLayers), y = CoordPacker.getYMoore3D(m, numLayers), @@ -340,14 +336,14 @@ public char[][][] generate() floors[i] = CoordPacker.pack(dungeon[i], '.'); } //using actual dungeon space per layer, not row/column 3D grid space - ArrayList> ups = new ArrayList<>(depth), + ArrayList> ups = new ArrayList<>(depth), downs = new ArrayList<>(depth); for (int i = 0; i < depth; i++) { - ups.add(new LinkedHashSet(40)); - downs.add(new LinkedHashSet(40)); - LinkedHashSet above = null; + ups.add(new OrderedSet(40)); + downs.add(new OrderedSet(40)); + OrderedSet above = null; if (i > 0) { - above = new LinkedHashSet<>(linksDown.get(i - 1)); + above = new OrderedSet<>(linksDown.get(i - 1)); if(above.size() == 0) continue; Coord higher = random.getRandomElement(above.toArray(new Coord[above.size()])); @@ -375,7 +371,7 @@ public char[][][] generate() } for (int i = 0; i < depth; i++) { - LinkedHashMap used = new LinkedHashMap<>(128); + OrderedMap used = new OrderedMap<>(128); for(Coord up : ups.get(i)) { Integer count = used.get(up); diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SerpentMapGenerator.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SerpentMapGenerator.java index e680b5208a..3aa831e388 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SerpentMapGenerator.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SerpentMapGenerator.java @@ -1,12 +1,8 @@ package squidpony.squidgrid.mapping; -import squidpony.squidmath.Coord; -import squidpony.squidmath.CoordPacker; -import squidpony.squidmath.OrthoLine; -import squidpony.squidmath.RNG; +import squidpony.squidmath.*; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; /** @@ -173,7 +169,7 @@ public SerpentMapGenerator(int width, int height, RNG rng, double branchingChanc rows[i] += rs3; } - LinkedHashMap> connections = new LinkedHashMap<>(80); + OrderedMap> connections = new OrderedMap<>(80); Coord temp, t; int m = random.nextInt(64), r = random.between(4, 12); temp = CoordPacker.mooreToCoord(m); diff --git a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SymmetryDungeonGenerator.java b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SymmetryDungeonGenerator.java index fd65a1f5ce..66cf4c776d 100644 --- a/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SymmetryDungeonGenerator.java +++ b/squidlib-util/src/main/java/squidpony/squidgrid/mapping/SymmetryDungeonGenerator.java @@ -1,10 +1,11 @@ package squidpony.squidgrid.mapping; -import squidpony.squidmath.Coord; -import squidpony.squidmath.PoissonDisk; -import squidpony.squidmath.RNG; +import squidpony.squidmath.*; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * A variant on {@link MixedGenerator} that creates bi-radially symmetric maps (basically a yin-yang shape). Useful for @@ -15,7 +16,7 @@ */ public class SymmetryDungeonGenerator extends MixedGenerator { - public static LinkedHashMap> removeSomeOverlap(int width, int height, List sequence) + public static OrderedMap> removeSomeOverlap(int width, int height, List sequence) { List s2 = new ArrayList<>(sequence.size()); for(Coord c : sequence) @@ -25,9 +26,9 @@ public static LinkedHashMap> removeSomeOverlap(int width, int } return listToMap(s2); } - public static LinkedHashMap> removeSomeOverlap(int width, int height, Map> connections) { - LinkedHashMap> lhm2 = new LinkedHashMap<>(connections.size()); - Set keyset = connections.keySet(), newkeys = new LinkedHashSet<>(connections.size()); + public static OrderedMap> removeSomeOverlap(int width, int height, Map> connections) { + OrderedMap> lhm2 = new OrderedMap<>(connections.size()); + Set keyset = connections.keySet(), newkeys = new OrderedSet<>(connections.size()); for (Coord c : keyset) { if (c.x * 1.0 / width + c.y * 1.0 / height <= 1.0) { newkeys.add(c); @@ -100,7 +101,7 @@ public SymmetryDungeonGenerator(int width, int height, RNG rng, List sequ * @param connections a Map of Coord keys to arrays of Coord to connect to next; shouldn't connect both ways * @see SerpentMapGenerator a class that uses this technique */ - public SymmetryDungeonGenerator(int width, int height, RNG rng, LinkedHashMap> connections) { + public SymmetryDungeonGenerator(int width, int height, RNG rng, OrderedMap> connections) { this(width, height, rng, connections, 0.8f); } @@ -119,13 +120,13 @@ public SymmetryDungeonGenerator(int width, int height, RNG rng, LinkedHashMap> connections, float roomSizeMultiplier) { + public SymmetryDungeonGenerator(int width, int height, RNG rng, OrderedMap> connections, float roomSizeMultiplier) { super(width, height, rng, crossConnect(width, height, connections), roomSizeMultiplier); } - protected static LinkedHashMap> listToMap(List sequence) + protected static OrderedMap> listToMap(List sequence) { - LinkedHashMap> conns = new LinkedHashMap<>(sequence.size() - 1); + OrderedMap> conns = new OrderedMap<>(sequence.size() - 1); for (int i = 0; i < sequence.size() - 1; i++) { Coord c1 = sequence.get(i), c2 = sequence.get(i+1); List cs = new ArrayList<>(1); @@ -135,9 +136,9 @@ protected static LinkedHashMap> listToMap(List sequenc return conns; } - protected static LinkedHashMap> crossConnect(int width, int height, Map> connections) + protected static OrderedMap> crossConnect(int width, int height, Map> connections) { - LinkedHashMap> conns = new LinkedHashMap<>(connections.size()); + OrderedMap> conns = new OrderedMap<>(connections.size()); for(Map.Entry> entry : connections.entrySet()) { conns.put(entry.getKey(), new ArrayList<>(entry.getValue())); diff --git a/squidlib-util/src/main/java/squidpony/squidmath/CoordPacker.java b/squidlib-util/src/main/java/squidpony/squidmath/CoordPacker.java index c4e8a2c181..05ceb04b41 100644 --- a/squidlib-util/src/main/java/squidpony/squidmath/CoordPacker.java +++ b/squidlib-util/src/main/java/squidpony/squidmath/CoordPacker.java @@ -9,7 +9,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.LinkedHashSet; /** @@ -1627,9 +1626,9 @@ public static boolean queryPackedHilbert(short[] packed, short hilbert) * returned by packMulti(); null elements in packed will be skipped. * @return an ArrayList of all packed arrays that store true at the given x,y location. */ - public static LinkedHashSet findManyPacked(int x, int y, short[] ... packed) + public static OrderedSet findManyPacked(int x, int y, short[] ... packed) { - LinkedHashSet packs = new LinkedHashSet<>(packed.length); + OrderedSet packs = new OrderedSet<>(packed.length); int hilbertDistance = posToHilbert(x, y); for (int a = 0; a < packed.length; a++) { if(packed[a] == null) continue; @@ -1658,7 +1657,7 @@ public static LinkedHashSet findManyPacked(int x, int y, short[] ... pa */ public static boolean regionsContain(short[] checking, short[] ... packed) { - LinkedHashSet packs = new LinkedHashSet<>(packed.length); + OrderedSet packs = new OrderedSet<>(packed.length); for (int a = 0; a < packed.length; a++) { if(packed[a] == null) continue; int total = 0; diff --git a/squidlib-util/src/main/java/squidpony/squidmath/MathExtras.java b/squidlib-util/src/main/java/squidpony/squidmath/MathExtras.java index d80ff413f3..af7aca8aa0 100644 --- a/squidlib-util/src/main/java/squidpony/squidmath/MathExtras.java +++ b/squidlib-util/src/main/java/squidpony/squidmath/MathExtras.java @@ -16,7 +16,6 @@ package squidpony.squidmath; import java.math.BigInteger; -import java.util.LinkedHashMap; /** * Mathematical operations not provided by {@link Math java.lang.Math}. @@ -36,8 +35,8 @@ public final class MathExtras 6227020800L, 87178291200L, 1307674368000L, 20922789888000L, 355687428096000L, 6402373705728000L, 121645100408832000L, 2432902008176640000L }; - private static final LinkedHashMap BIG_FACTORIALS - = new LinkedHashMap(); + private static final OrderedMap BIG_FACTORIALS + = new OrderedMap(); private MathExtras() diff --git a/squidlib-util/src/main/java/squidpony/squidmath/PoissonDisk.java b/squidlib-util/src/main/java/squidpony/squidmath/PoissonDisk.java index fc5a5da55b..bac20b42cd 100644 --- a/squidlib-util/src/main/java/squidpony/squidmath/PoissonDisk.java +++ b/squidlib-util/src/main/java/squidpony/squidmath/PoissonDisk.java @@ -5,7 +5,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.LinkedHashSet; /** * This provides a Uniform Poisson Disk Sampling technique that can be used to generate random points that have a @@ -121,7 +120,7 @@ private static ArrayList sample(Coord minPosition, Coord maxPosition, flo int gridHeight = (int)(dimensions.y / cellSize) + 1; Coord[][] grid = new Coord[gridWidth][gridHeight]; ArrayList activePoints = new ArrayList<>(); - LinkedHashSet points = new LinkedHashSet<>(128); + OrderedSet points = new OrderedSet<>(128); //add first point boolean added = false; @@ -223,7 +222,7 @@ public static ArrayList sampleMap(Coord minPosition, Coord maxPosition, c int gridHeight = (int) (dimensions.y / cellSize) + 1; Coord[][] grid = new Coord[gridWidth][gridHeight]; ArrayList activePoints = new ArrayList<>(); - LinkedHashSet points = new LinkedHashSet<>(128); + OrderedSet points = new OrderedSet<>(128); //add first point diff --git a/squidlib-util/src/main/java/squidpony/squidmath/ProbabilityTable.java b/squidlib-util/src/main/java/squidpony/squidmath/ProbabilityTable.java index a74445c1d3..4a1c7e2861 100644 --- a/squidlib-util/src/main/java/squidpony/squidmath/ProbabilityTable.java +++ b/squidlib-util/src/main/java/squidpony/squidmath/ProbabilityTable.java @@ -3,8 +3,7 @@ import squidpony.annotation.Beta; import java.io.Serializable; -import java.util.HashMap; -import java.util.Set; +import java.util.SortedSet; /** * A generic method of holding a probability table to determine weighted random @@ -20,9 +19,9 @@ @Beta public class ProbabilityTable implements Serializable { private static final long serialVersionUID = -1307656083434154736L; - private final HashMap table = new HashMap<>(); + private final OrderedMap table; private RNG rng; - private int total = 0; + private int total; /** * Creates a new probability table. @@ -39,6 +38,8 @@ public ProbabilityTable() { */ public ProbabilityTable(RNG rng) { this.rng = rng; + table = new OrderedMap<>(); + total = 0; } /** @@ -97,9 +98,9 @@ public int weight(T item) { * Provides a set of the items in this table, without reference to their * weight. * - * @return a set of all items stored + * @return a "sorted" set of all items stored, really sorted in insertion order */ - public Set items() { + public SortedSet items() { return table.keySet(); } } diff --git a/squidlib-util/src/main/java/squidpony/squidmath/RandomBias.java b/squidlib-util/src/main/java/squidpony/squidmath/RandomBias.java index ac46599afc..8213304e16 100644 --- a/squidlib-util/src/main/java/squidpony/squidmath/RandomBias.java +++ b/squidlib-util/src/main/java/squidpony/squidmath/RandomBias.java @@ -1,7 +1,6 @@ package squidpony.squidmath; import java.io.Serializable; -import java.util.LinkedHashMap; import java.util.Map; /** @@ -35,7 +34,7 @@ * Created by Tommy Ettinger on 3/20/2016. */ public class RandomBias implements Serializable { - private LinkedHashMap biases; + private OrderedMap biases; public RNG rng; public int distribution = EXP_TRI; @@ -97,13 +96,13 @@ public class RandomBias implements Serializable { public RandomBias() { - biases = new LinkedHashMap<>(32); + biases = new OrderedMap<>(32); rng = new RNG(); } public RandomBias(RNG rng) { this.rng = rng; - biases = new LinkedHashMap<>(32); + biases = new OrderedMap<>(32); } public RandomBias(RNG rng, Map mapping) { @@ -113,9 +112,9 @@ public RandomBias(RNG rng, Map mapping, int distribution) { this.rng = rng; this.distribution = distribution; if (mapping == null) { - biases = new LinkedHashMap<>(32); + biases = new OrderedMap<>(32); } else { - biases = new LinkedHashMap<>(mapping.size()); + biases = new OrderedMap<>(mapping.size()); double exp; for (Map.Entry kv : mapping.entrySet()) { exp = kv.getValue(); diff --git a/squidlib-util/src/main/java/squidpony/squidmath/RegionMap.java b/squidlib-util/src/main/java/squidpony/squidmath/RegionMap.java index 8faa6b3b0b..cae086e83e 100644 --- a/squidlib-util/src/main/java/squidpony/squidmath/RegionMap.java +++ b/squidlib-util/src/main/java/squidpony/squidmath/RegionMap.java @@ -341,10 +341,10 @@ private V getStash (short[] key, V defaultValue) { * @param y the y coordinate of the point in question * @return an ArrayList of all V values corresponding to regions containing the given x,y point. */ - public LinkedHashSet allAt(int x, int y) + public OrderedSet allAt(int x, int y) { - LinkedHashSet found = new LinkedHashSet<>(capacity); - LinkedHashSet regions = CoordPacker.findManyPacked(x, y, keyTable); + OrderedSet found = new OrderedSet<>(capacity); + OrderedSet regions = CoordPacker.findManyPacked(x, y, keyTable); for(short[] region : regions) { found.add(get(region)); @@ -368,7 +368,7 @@ public boolean containsRegion(short[] region) * @param y the y coordinate of the point in question * @return an ArrayList of all regions in this data structure containing the given x,y point. */ - public LinkedHashSet regionsContaining(int x, int y) + public OrderedSet regionsContaining(int x, int y) { return CoordPacker.findManyPacked(x, y, keyTable); } diff --git a/squidlib-util/src/test/java/squidpony/examples/DungeonGeneratorTest.java b/squidlib-util/src/test/java/squidpony/examples/DungeonGeneratorTest.java index be636b3698..8ba0d9cd0b 100644 --- a/squidlib-util/src/test/java/squidpony/examples/DungeonGeneratorTest.java +++ b/squidlib-util/src/test/java/squidpony/examples/DungeonGeneratorTest.java @@ -169,7 +169,7 @@ public static void main( String[] args ) } */ /* - for(LinkedHashSet lhs : sdg.placement.getAlongStraightWalls()) + for(OrderedSet lhs : sdg.placement.getAlongStraightWalls()) { for(Coord c : lhs) { @@ -177,7 +177,7 @@ public static void main( String[] args ) } } - for(LinkedHashSet lhs : sdg.placement.getCorners()) + for(OrderedSet lhs : sdg.placement.getCorners()) { for(Coord c : lhs) { @@ -185,7 +185,7 @@ public static void main( String[] args ) } } - for(LinkedHashSet lhs : sdg.placement.getCenters()) + for(OrderedSet lhs : sdg.placement.getCenters()) { for(Coord c : lhs) { diff --git a/squidlib-util/src/test/java/squidpony/examples/FOVTest.java b/squidlib-util/src/test/java/squidpony/examples/FOVTest.java index 115d164c76..bd34620bc6 100644 --- a/squidlib-util/src/test/java/squidpony/examples/FOVTest.java +++ b/squidlib-util/src/test/java/squidpony/examples/FOVTest.java @@ -6,10 +6,10 @@ import squidpony.squidgrid.mapping.DungeonUtility; import squidpony.squidgrid.mapping.OrganicMapGenerator; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedSet; import squidpony.squidmath.StatefulRNG; import java.util.ArrayList; -import java.util.LinkedHashSet; /** * Created by Tommy Ettinger on 5/13/2016. @@ -39,7 +39,7 @@ public static void main(String[] args) { short[] floors = DungeonUtility.packedFloors(dungeon); Coord pt = dungeonGenerator.utility.randomCell(floors); Coord start = pt; - LinkedHashSet points = new LinkedHashSet<>(20); + OrderedSet points = new OrderedSet<>(20); double[][] losMap = fov.calculateLOSMap(resMap, pt.x, pt.y); for (int i = 0; i < 20; i++) { points.add(pt); diff --git a/squidlib-util/src/test/java/squidpony/examples/SpillTest.java b/squidlib-util/src/test/java/squidpony/examples/SpillTest.java index d5fc66cf3f..648b957f00 100644 --- a/squidlib-util/src/test/java/squidpony/examples/SpillTest.java +++ b/squidlib-util/src/test/java/squidpony/examples/SpillTest.java @@ -4,15 +4,11 @@ import squidpony.squidgrid.Spill; import squidpony.squidgrid.mapping.DungeonGenerator; import squidpony.squidgrid.mapping.DungeonUtility; -import squidpony.squidmath.Coord; -import squidpony.squidmath.CoordPacker; -import squidpony.squidmath.LightRNG; -import squidpony.squidmath.RNG; +import squidpony.squidmath.*; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -import java.util.LinkedHashMap; /** * A test for the randomized flood-fill in the Spill class. This runs the Spill twice from the same starting position, @@ -69,7 +65,7 @@ public static void main(String[] args) { System.out.println(dg); short[] valid = CoordPacker.pack(dun, '.'); - LinkedHashMap entries = new LinkedHashMap<>(16); + OrderedMap entries = new OrderedMap<>(16); ArrayList section = CoordPacker.randomPortion(valid, 16, rng); for (int i = 0; i < 4; i++) { entries.put(section.get(i * 4 ), 1.0); diff --git a/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/SquidLayers.java b/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/SquidLayers.java index 5cc0106920..97b5b182ef 100644 --- a/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/SquidLayers.java +++ b/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/SquidLayers.java @@ -1632,7 +1632,7 @@ public AnimatedEntity animateActor(int x, int y, TextureRegion tr, boolean doubl return animateActor(x, y, tr, Color.WHITE, doubleWidth, stretch); } - public LinkedHashSet getAnimatedEntities(int layer) { + public Set getAnimatedEntities(int layer) { SquidPanel p = foregroundPanel; switch (layer) { case 0: @@ -1648,7 +1648,7 @@ public LinkedHashSet getAnimatedEntities(int layer) { return p.getAnimatedEntities(); } - public LinkedHashSet getAnimatedEntities() { + public Set getAnimatedEntities() { return foregroundPanel.getAnimatedEntities(); } diff --git a/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/SquidPanel.java b/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/SquidPanel.java index fd0963fc05..5dab468733 100644 --- a/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/SquidPanel.java +++ b/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/SquidPanel.java @@ -14,9 +14,13 @@ import squidpony.panel.ISquidPanel; import squidpony.squidgrid.Direction; import squidpony.squidmath.Coord; +import squidpony.squidmath.OrderedSet; import squidpony.squidmath.StatefulRNG; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; /** * Displays text and images in a grid pattern. Supports basic animations. @@ -42,7 +46,7 @@ public class SquidPanel extends Group implements ISquidPanel { protected Color lightingColor = SColor.WHITE; protected final TextCellFactory textFactory; protected float xOffset, yOffset; - protected LinkedHashSet animatedEntities; + protected OrderedSet animatedEntities; protected boolean distanceField = false; /** @@ -147,7 +151,7 @@ public SquidPanel(int gridWidth, int gridHeight, TextCellFactory factory, IColor this.xOffset = xOffset; this.yOffset = yOffset; setSize(w, h); - animatedEntities = new LinkedHashSet<>(); + animatedEntities = new OrderedSet<>(); } /** @@ -1312,7 +1316,7 @@ public boolean hasActiveAnimations() { return animationCount != 0; } - public LinkedHashSet getAnimatedEntities() { + public Set getAnimatedEntities() { return animatedEntities; } diff --git a/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/TextCellFactory.java b/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/TextCellFactory.java index 873f770695..08484dbd65 100644 --- a/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/TextCellFactory.java +++ b/squidlib/src/main/java/squidpony/squidgrid/gui/gdx/TextCellFactory.java @@ -17,6 +17,7 @@ import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Disposable; import squidpony.IColorCenter; +import squidpony.squidmath.OrderedMap; import java.util.*; @@ -67,7 +68,7 @@ public class TextCellFactory implements Disposable { protected float smoothingMultiplier = 1f; protected float descent, lineHeight; private Label.LabelStyle style; - protected java.util.LinkedHashMap swap = new LinkedHashMap<>(32); + protected OrderedMap swap = new OrderedMap<>(32); /** @@ -101,7 +102,7 @@ public TextCellFactory copy() next.bmpFont = new BitmapFont(new BitmapFont.BitmapFontData(bmpFont.getData().getFontFile(), false), bmpFont.getRegions(), bmpFont.usesIntegerPositions()); next.block = block; - next.swap = new LinkedHashMap<>(swap); + next.swap = new OrderedMap<>(swap); next.distanceField = distanceField; next.distanceFieldScaleX = distanceFieldScaleX; next.distanceFieldScaleY = distanceFieldScaleY; @@ -1363,7 +1364,7 @@ public TextCellFactory removeSwap(char find) /** * Gets the current mapping of "swaps", or replacement pairs, to replace keys requested for drawing with their - * values in the LinkedHashMap. + * values in the OrderedMap. *
* This can be useful when you want to use certain defaults in squidlib-util's dungeon generation, like '~' for deep * water, but not others, like ',' for shallow water, and would rather have a glyph of your choice replace something @@ -1373,7 +1374,7 @@ public TextCellFactory removeSwap(char find) * swapping, like a top-down char-based map, and elements that should not, like those that display normal text. * @return the mapping of replacement pairs */ - public LinkedHashMap getAllSwaps() { + public OrderedMap getAllSwaps() { return swap; } @@ -1390,7 +1391,7 @@ public LinkedHashMap getAllSwaps() { * @return this for chaining */ public TextCellFactory setAllSwaps(Map swaps) { - this.swap = new LinkedHashMap<>(swaps.size()); + this.swap = new OrderedMap<>(swaps.size()); for(Map.Entry kv : swaps.entrySet()) { if(!kv.getKey().startsWith("\0")) diff --git a/squidlib/src/test/java/squidpony/gdx/examples/CoveredPathDemo.java b/squidlib/src/test/java/squidpony/gdx/examples/CoveredPathDemo.java index 625fea3e3a..2e99361d2c 100644 --- a/squidlib/src/test/java/squidpony/gdx/examples/CoveredPathDemo.java +++ b/squidlib/src/test/java/squidpony/gdx/examples/CoveredPathDemo.java @@ -16,10 +16,7 @@ import squidpony.squidgrid.mapping.DungeonGenerator; import squidpony.squidgrid.mapping.DungeonUtility; import squidpony.squidgrid.mapping.SerpentMapGenerator; -import squidpony.squidmath.Coord; -import squidpony.squidmath.CoordPacker; -import squidpony.squidmath.LightRNG; -import squidpony.squidmath.RNG; +import squidpony.squidmath.*; import java.util.*; @@ -58,8 +55,8 @@ public Creature(AnimatedEntity ae, int hp, DijkstraMap dijkstraMap) private SquidInput input; private static final Color bgColor = SColor.DARK_SLATE_GRAY; private ArrayList teamRed, teamBlue; - private LinkedHashSet redPlaces, bluePlaces; - private List redThreats, blueThreats; + private OrderedSet redPlaces, bluePlaces; + private OrderedSet redThreats, blueThreats; private DijkstraMap getToRed, getToBlue; private Stage stage; private int framesWithoutAnimation = 0, moveLength = 6; @@ -103,11 +100,11 @@ public void create () { teamRed = new ArrayList<>(numMonsters); teamBlue = new ArrayList<>(numMonsters); - redPlaces = new LinkedHashSet<>(numMonsters); - bluePlaces = new LinkedHashSet<>(numMonsters); + redPlaces = new OrderedSet<>(numMonsters); + bluePlaces = new OrderedSet<>(numMonsters); - redThreats = new ArrayList<>(numMonsters); - blueThreats = new ArrayList<>(numMonsters); + redThreats = new OrderedSet<>(numMonsters); + blueThreats = new OrderedSet<>(numMonsters); for(int i = 0; i < numMonsters; i++) { Coord monPos = dungeonGen.utility.randomCell(placement); @@ -176,7 +173,7 @@ private void startMove(int idx) { DijkstraMap whichDijkstra = null; Technique whichTech; Set whichFoes, whichAllies; - List whichThreats; + OrderedSet whichThreats; AnimatedEntity ae = null; int health = 0; Coord user = null; @@ -263,22 +260,11 @@ private boolean checkOverlap(AnimatedEntity ae, int x, int y) } return false; } - - private LinkedHashMap convertThreats(List ts) - { - LinkedHashMap numbered = new LinkedHashMap<>(); - int i = 0; - for (Threat t : ts) - { - numbered.put(i, t); - i++; - } - return numbered; - } + private void postMove(int idx) { int i = 0, myMax, myMin; - LinkedHashSet whichFoes, whichAllies, visibleTargets = new LinkedHashSet<>(8); + OrderedSet whichFoes, whichAllies, visibleTargets = new OrderedSet<>(8); AnimatedEntity ae = null; int health = 0; Coord user = null; @@ -286,14 +272,14 @@ private void postMove(int idx) { ArrayList previous = null; Color whichTint = Color.WHITE; ArrayList whichEnemyTeam; - LinkedHashMap myThreats, enemyThreats; + OrderedSet myThreats, enemyThreats; if (blueTurn) { whichFoes = redPlaces; whichAllies = bluePlaces; whichTint = Color.CYAN; whichEnemyTeam = teamRed; - myThreats = convertThreats(blueThreats); - enemyThreats = convertThreats(redThreats); + myThreats = blueThreats; + enemyThreats = redThreats; myMin = 3; myMax = 5; Creature entry = teamBlue.get(idx); @@ -307,8 +293,8 @@ private void postMove(int idx) { whichAllies = redPlaces; whichTint = Color.RED; whichEnemyTeam = teamBlue; - myThreats = convertThreats(redThreats); - enemyThreats = convertThreats(blueThreats); + myThreats = redThreats; + enemyThreats = blueThreats; myMin = 0; myMax = 1; @@ -360,8 +346,10 @@ private void postMove(int idx) { } ix++; } - if (successfulKill >= 0) { - Coord deadPos = enemyThreats.remove(successfulKill).position; + if (successfulKill >= 0 && successfulKill < enemyThreats.size()) { + Threat succ = enemyThreats.getAt(successfulKill); + enemyThreats.remove(succ); + Coord deadPos = succ.position; AnimatedEntity deadAE = whichEnemyTeam.get(successfulKill).entity; display.removeAnimatedEntity(deadAE); whichFoes.remove(deadPos); diff --git a/squidlib/src/test/java/squidpony/gdx/examples/EverythingDemo.java b/squidlib/src/test/java/squidpony/gdx/examples/EverythingDemo.java index 9649f7689b..a308a12825 100644 --- a/squidlib/src/test/java/squidpony/gdx/examples/EverythingDemo.java +++ b/squidlib/src/test/java/squidpony/gdx/examples/EverythingDemo.java @@ -25,10 +25,10 @@ import squidpony.squidgrid.mapping.MixedGenerator; import squidpony.squidmath.Coord; import squidpony.squidmath.CoordPacker; +import squidpony.squidmath.OrderedSet; import squidpony.squidmath.StatefulRNG; import java.util.ArrayList; -import java.util.LinkedHashSet; import java.util.List; public class EverythingDemo extends ApplicationAdapter { @@ -506,7 +506,7 @@ private void postMove() // this is an important piece of DijkstraMap usage; the argument is a Set of Points for squares that // temporarily cannot be moved through (not walls, which are automatically known because the map char[][] // was passed to the DijkstraMap constructor, but things like moving creatures and objects). - LinkedHashSet monplaces = monsters.positions(); + OrderedSet monplaces = monsters.positions(); pathMap = getToPlayer.scan(monplaces); diff --git a/squidlib/src/test/java/squidpony/gdx/examples/SquidAIDemo.java b/squidlib/src/test/java/squidpony/gdx/examples/SquidAIDemo.java index fae55eb42a..d7f5ece620 100644 --- a/squidlib/src/test/java/squidpony/gdx/examples/SquidAIDemo.java +++ b/squidlib/src/test/java/squidpony/gdx/examples/SquidAIDemo.java @@ -16,10 +16,7 @@ import squidpony.squidgrid.mapping.DungeonGenerator; import squidpony.squidgrid.mapping.DungeonUtility; import squidpony.squidgrid.mapping.styled.TilesetType; -import squidpony.squidmath.Coord; -import squidpony.squidmath.CoordPacker; -import squidpony.squidmath.LightRNG; -import squidpony.squidmath.RNG; +import squidpony.squidmath.*; import java.util.*; @@ -42,8 +39,8 @@ private enum Phase {MOVE_ANIM, ATTACK_ANIM} private SquidInput input; private static final Color bgColor = SColor.DARK_SLATE_GRAY; - private LinkedHashMap teamRed, teamBlue; - private LinkedHashSet redPlaces, bluePlaces; + private OrderedMap teamRed, teamBlue; + private OrderedSet redPlaces, bluePlaces; private Technique redCone, redCloud, blueBlast, blueBeam; private DijkstraMap getToRed, getToBlue; private Stage stage; @@ -80,11 +77,11 @@ public void create () { short[] placement = CoordPacker.pack(bareDungeon, '.'); - teamRed = new LinkedHashMap<>(numMonsters); - teamBlue = new LinkedHashMap<>(numMonsters); + teamRed = new OrderedMap<>(numMonsters); + teamBlue = new OrderedMap<>(numMonsters); - redPlaces = new LinkedHashSet<>(numMonsters); - bluePlaces = new LinkedHashSet<>(numMonsters); + redPlaces = new OrderedSet<>(numMonsters); + bluePlaces = new OrderedSet<>(numMonsters); for(int i = 0; i < numMonsters; i++) { Coord monPos = dungeonGen.utility.randomCell(placement); @@ -213,7 +210,7 @@ private void startMove(int idx) { int i = 0; DijkstraMap whichDijkstra; Technique whichTech; - Set whichFoes, whichAllies = new LinkedHashSet<>(8); + Set whichFoes, whichAllies = new OrderedSet<>(8); AnimatedEntity ae = null; int health = 0; Coord user = null; @@ -309,13 +306,13 @@ private void postMove(int idx) { int i = 0; Technique whichTech; - Set whichFoes, whichAllies, visibleTargets = new LinkedHashSet<>(8); + Set whichFoes, whichAllies, visibleTargets = new OrderedSet<>(8); AnimatedEntity ae = null; int health = 0; Coord user = null; Color whichTint = Color.WHITE; - LinkedHashMap whichEnemyTeam = null; - LinkedHashMap effects = null; + OrderedMap whichEnemyTeam = null; + OrderedMap effects = null; if (blueTurn) { whichTech = (idx % 2 == 0) ? blueBeam : blueBlast; whichFoes = redPlaces; @@ -358,7 +355,7 @@ private void postMove(int idx) { } } - LinkedHashMap> ideal = whichTech.idealLocations(user, visibleTargets, whichAllies); + OrderedMap> ideal = whichTech.idealLocations(user, visibleTargets, whichAllies); Coord targetCell = null; targetCell = GwtCompatibility.first(ideal.keySet());