Parcourir la source

Delete stuff I don't use

smelc il y a 7 ans
Parent
commit
4e14c06f9f

+ 43 - 43
squidlib-util/src/main/java/squidpony/panel/IColoredString.java

@@ -1,8 +1,11 @@
 package squidpony.panel;
 
-import squidpony.annotation.Beta;
-
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
 
 /**
  * A {@link String} divided in chunks of different colors. Use the
@@ -13,7 +16,6 @@ import java.util.*;
  * @param <T>
  *            The type of colors;
  */
-@Beta
 public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 
 	/**
@@ -93,7 +95,7 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 	 * 
 	 * @param color
 	 */
-	void setColor(/*@Nullable*/ T color);
+	void setColor(/* @Nullable */ T color);
 
 	/**
 	 * Deletes all content after index {@code len} (if any).
@@ -111,16 +113,16 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 	 * @param width
 	 *            A positive integer
 	 * @return {@code this} split in pieces that would fit in a display with
-	 *         {@code width} columns (if all words in {@code this} are smaller
-	 *         or equal in length to {@code width}, otherwise wrapping will fail
-	 *         for these words).
+	 *         {@code width} columns (if all words in {@code this} are smaller or
+	 *         equal in length to {@code width}, otherwise wrapping will fail for
+	 *         these words).
 	 */
 	List<IColoredString<T>> wrap(int width);
 
 	/**
-	 * This method does NOT guarantee that the result's length is {@code width}.
-	 * It is impossible to do correct justifying if {@code this}'s length is
-	 * greater than {@code width} or if {@code this} has no space character.
+	 * This method does NOT guarantee that the result's length is {@code width}. It
+	 * is impossible to do correct justifying if {@code this}'s length is greater
+	 * than {@code width} or if {@code this} has no space character.
 	 * 
 	 * @param width
 	 * @return A variant of {@code this} where spaces have been introduced
@@ -168,9 +170,12 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 	String present();
 
 	/**
-	 * Given some way of converting from a T value to an in-line markup tag, returns a string representation of
-	 * this IColoredString with in-line markup representing colors.
-	 * @param markup an IMarkup implementation
+	 * Given some way of converting from a T value to an in-line markup tag, returns
+	 * a string representation of this IColoredString with in-line markup
+	 * representing colors.
+	 * 
+	 * @param markup
+	 *            an IMarkup implementation
 	 * @return a String with markup inserted inside.
 	 */
 	String presentWithMarkup(IMarkup<T> markup);
@@ -209,8 +214,7 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 		}
 
 		/**
-		 * A static constructor, to avoid having to write {@code <T>} in the
-		 * caller.
+		 * A static constructor, to avoid having to write {@code <T>} in the caller.
 		 * 
 		 * @return {@code new Impl(s, t)}.
 		 */
@@ -229,8 +233,7 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 		}
 
 		/**
-		 * A static constructor, to avoid having to write {@code <T>} in the
-		 * caller.
+		 * A static constructor, to avoid having to write {@code <T>} in the caller.
 		 * 
 		 * @return {@code new Impl(s, t)}.
 		 */
@@ -246,9 +249,8 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 
 		/**
 		 * @param one
-		 * @param two 
-		 * @return Whether {@code one} represents the same content as
-		 *         {@code two}.
+		 * @param two
+		 * @return Whether {@code one} represents the same content as {@code two}.
 		 */
 		/*
 		 * Method could be smarter, i.e. return true more often, by doing some
@@ -423,8 +425,8 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 			final List<IColoredString<T>> result = new ArrayList<>();
 			if (isEmpty()) {
 				/*
-				 * Catch this case early on, as empty lines are eaten below (see
-				 * code after the while). Checking emptyness is cheap anyway.
+				 * Catch this case early on, as empty lines are eaten below (see code after the
+				 * while). Checking emptyness is cheap anyway.
 				 */
 				result.add(this);
 				return result;
@@ -441,8 +443,7 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 				for (int i = 0; i < split.length; i++) {
 					if (i == split.length - 1 && bucket.endsWith(" "))
 						/*
-						 * Do not loose trailing space that got eaten by
-						 * 'bucket.split'.
+						 * Do not loose trailing space that got eaten by 'bucket.split'.
 						 */
 						split[i] = split[i] + " ";
 					final String chunk = split[i];
@@ -451,9 +452,8 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 					if (curlen + chunklen + (addLeadingSpace ? 1 : 0) <= width) {
 						if (addLeadingSpace) {
 							/*
-							 * Do not forget space on which chunk got split. If
-							 * the space is offscreen, it's harmless, hence not
-							 * checking it.
+							 * Do not forget space on which chunk got split. If the space is offscreen, it's
+							 * harmless, hence not checking it.
 							 */
 							current.append(' ', null);
 							curlen++;
@@ -479,8 +479,7 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 							curlen = chunklen;
 						} else {
 							/*
-							 * This word is too long. Adding it and preparing a
-							 * new line immediately.
+							 * This word is too long. Adding it and preparing a new line immediately.
 							 */
 							/* Add */
 							result.add(new Impl<>(chunk, color));
@@ -503,17 +502,15 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 
 		@Override
 		/*
-		 * smelC: not the cutest result (we should add spaces both from the left
-		 * and the right, instead of just from the left), but better than
-		 * nothing.
+		 * smelC: not the cutest result (we should add spaces both from the left and the
+		 * right, instead of just from the left), but better than nothing.
 		 */
 		public IColoredString<T> justify(int width) {
 			int length = length();
 
 			if (width <= length)
 				/*
-				 * If width==length, we're good. If width<length, we cannot
-				 * adjust
+				 * If width==length, we're good. If width<length, we cannot adjust
 				 */
 				return this;
 
@@ -582,8 +579,8 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 				int localRest = localDiff - (nb * localNbSpaces);
 				if (localRest == 0 && 0 < totalRest) {
 					/*
-					 * Take one for the group. This avoids flushing all spaces
-					 * needed in the 'last hope' cases below.
+					 * Take one for the group. This avoids flushing all spaces needed in the 'last
+					 * hope' cases below.
 					 */
 					localRest = 1;
 				}
@@ -710,10 +707,14 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 				result.append(fragment.text);
 			return result.toString();
 		}
+
 		/**
-		 * Given some way of converting from a T value to an in-line markup tag, returns a string representation of
-		 * this IColoredString with in-line markup representing colors.
-		 * @param markup an IMarkup implementation
+		 * Given some way of converting from a T value to an in-line markup tag, returns
+		 * a string representation of this IColoredString with in-line markup
+		 * representing colors.
+		 * 
+		 * @param markup
+		 *            an IMarkup implementation
 		 * @return a String with markup inserted inside.
 		 */
 		@Override
@@ -721,13 +722,12 @@ public interface IColoredString<T> extends Iterable<IColoredString.Bucket<T>> {
 			final StringBuilder result = new StringBuilder();
 			boolean open = false;
 			for (Bucket<T> fragment : fragments) {
-				if(fragment.color != null) {
+				if (fragment.color != null) {
 					if (open)
 						result.append(markup.closeMarkup());
 					result.append(markup.getMarkup(fragment.color));
 					open = true;
-				}
-				else {
+				} else {
 					if (open)
 						result.append(markup.closeMarkup());
 					open = false;

+ 0 - 298
squidlib-util/src/main/java/squidpony/panel/ICombinedPanel.java

@@ -1,298 +0,0 @@
-package squidpony.panel;
-
-import squidpony.IColorCenter;
-import squidpony.annotation.Beta;
-
-/**
- * The combination of two panels, one to color the background, the other to
- * write characters on the foreground.
- * 
- * <p>
- * <ul>
- * <li>
- * There is a very generic implementation in this file: {@link Impl} that you
- * should use if you're combining generic things.
- * </li>
- * <li>
- * There is a libgdx-{@code Group} based implementation that offers more
- * features and that you should likely use if you're a new user (in
- * squidlib-gdx).
- * </li>
- * </ul>
- * 
- * @author smelC
- * 
- * @param <T>
- *            The type of colors.
- */
-@Beta
-public interface ICombinedPanel<T> {
-
-	/**
-	 * Puts the character {@code c} at {@code (x, y)}.
-	 * 
-	 * @param x
-	 * @param y
-	 * @param c
-	 */
-	void putFG(int x, int y, char c);
-
-	/**
-	 * Puts the character {@code c} at {@code (x, y)} with some {@code color}.
-	 * 
-	 * @param x
-	 * @param y
-	 * @param c
-	 * @param color
-	 */
-	void putFG(int x, int y, char c, T color);
-
-	/**
-	 * Puts the given string horizontally with the first character at the given
-	 * offset.
-	 *
-	 * Does not word wrap. Characters that are not renderable (due to being at
-	 * negative offsets or offsets greater than the grid size) will not be shown
-	 * but will not cause any malfunctions.
-	 *
-	 * @param x
-	 *            the x coordinate of the first character
-	 * @param y
-	 *            the y coordinate of the first character
-	 * @param string
-	 *            the characters to be displayed
-	 * @param color
-	 *            the color to draw the characters
-	 */
-	void putFG(int x, int y, String string, T color);
-
-	/**
-	 * Puts the given string horizontally with the first character at the given
-	 * offset.
-	 *
-	 * Does not word wrap. Characters that are not renderable (due to being at
-	 * negative offsets or offsets greater than the grid size) will not be shown
-	 * but will not cause any malfunctions.
-	 *
-	 * @param x
-	 *            the x coordinate of the first character
-	 * @param y
-	 *            the y coordinate of the first character
-	 * @param cs
-	 *            the text to be displayed, with its color.
-	 */
-	void putFG(int x, int y, IColoredString<T> cs);
-
-	/**
-	 * Puts the color {@code c} at {@code (x, y)}.
-	 * 
-	 * @param x
-	 * @param y
-	 * @param color
-	 */
-	void putBG(int x, int y, T color);
-
-	/**
-	 * Puts {@code c} at (x, y), using {@code fgc} for {@code c} and {@code bgc}
-	 * for the background.
-	 */
-	void put(int x, int y, char c, T bgc, T fgc);
-
-    /**
-     * Put {@code cs} at (x,y) using {@code bgc} for the background.
-     */
-	void put(int x, int y, T bgc, IColoredString<T> cs);
-
-	/**
-	 * Put {@code cs} at (x,y) using {@code bgc} for the background and
-	 * {@code fgc} for the foreground.
-	 */
-	void put(int x, int y, String s, T bgc, T fgc);
-
-	/**
-	 * @param what
-	 * 			  What to fill
-	 * @param color
-	 *            The color to put within this panel.
-	 */
-	void fill(What what, T color);
-
-	/**
-	 * @return Returns true if there are animations running when this method is
-	 *         called.
-	 */
-	boolean hasActiveAnimations();
-
-	/**
-	 * Changes the underlying {@link IColorCenter}.
-	 * 
-	 * @param icc
-	 */
-	void setColorCenter(IColorCenter<T> icc);
-
-	/**
-	 * What to fill
-	 * 
-	 * @author smelC
-	 */
-	enum What {
-		BG,
-		FG,
-		BG_AND_FG;
-
-		/**
-		 * @return {@code true} if {@code this} contains the background.
-		 */
-		public boolean hasBG() {
-			switch (this) {
-			case BG:
-			case BG_AND_FG:
-				return true;
-			case FG:
-				return false;
-			}
-			throw new IllegalStateException("Unmatched value: " + this);
-		}
-
-		/**
-		 * @return {@code true} if {@code this} contains the foreground.
-		 */
-		public boolean hasFG() {
-			switch (this) {
-			case FG:
-			case BG_AND_FG:
-				return true;
-			case BG:
-				return false;
-			}
-			throw new IllegalStateException("Unmatched value: " + this);
-		}
-	}
-
-	/**
-	 * A generic implementation of {@link ICombinedPanel}. Useful to combine
-	 * things. If you're a new user, you likely would prefer the more specific
-	 * implementation using libGDX, GroupCombinedPanel, instead.
-	 * 
-	 * @author smelC
-	 * 
-	 * @param <T>
-	 *            The type of colors.
-	 */
-	@Beta
-	class Impl<T> implements ICombinedPanel<T> {
-
-		protected final ISquidPanel<T> bg;
-		protected final ISquidPanel<T> fg;
-
-		protected final int width;
-		protected final int height;
-
-		/**
-		 * @param bg
-		 *            The backing background panel.
-		 * @param fg
-		 *            The backing foreground panel.
-		 * @param width
-		 *            The width of this panel, used for {@link #fillBG(Object)}
-		 *            (so that it fills within {@code [0, width)}).
-		 * @param height
-		 *            The height of this panel, used for {@link #fillBG(Object)}
-		 *            (so that it fills within {@code [0, height)}).
-		 * @throws IllegalStateException
-		 *             In various cases of errors regarding sizes of panels.
-		 */
-		public Impl(ISquidPanel<T> bg, ISquidPanel<T> fg, int width, int height) {
-			if (bg.gridWidth() != fg.gridWidth())
-				throw new IllegalStateException(
-						"Cannot build a combined panel with backers of different widths");
-			if (bg.gridHeight() != fg.gridHeight())
-				throw new IllegalStateException(
-						"Cannot build a combined panel with backers of different heights");
-
-			this.bg = bg;
-			this.fg = fg;
-			if (width < 0)
-				throw new IllegalStateException("Cannot create a panel with a negative width");
-			this.width = width;
-			if (height < 0)
-				throw new IllegalStateException("Cannot create a panel with a negative height");
-			this.height = height;
-		}
-
-		@Override
-		public void putFG(int x, int y, char c) {
-			fg.put(x, y, c);
-		}
-
-		@Override
-		public void putFG(int x, int y, char c, T color) {
-			fg.put(x, y, c, color);
-		}
-
-		@Override
-		public void putFG(int x, int y, String string, T foreground) {
-			fg.put(x, y, string, foreground);
-		}
-
-		@Override
-		public void putFG(int x, int y, IColoredString<T> cs) {
-			fg.put(x, y, cs);
-		}
-
-		@Override
-		public void putBG(int x, int y, T color) {
-			bg.put(x, y, color);
-		}
-
-		@Override
-		public void put(int x, int y, char c, T bgc, T fgc) {
-			bg.put(x, y, bgc);
-			fg.put(x, y, c, fgc);
-		}
-
-		@Override
-		public void put(int x, int y, T bgc, IColoredString<T> cs) {
-			final int l = cs.length();
-			for (int i = x; i < l && i < width; i++)
-				bg.put(i, y, bgc);
-			fg.put(x, y, cs);
-		}
-
-		@Override
-		public void put(int x, int y, String s, T bgc, T fgc) {
-			final int l = s.length();
-			for (int i = x; i < l && i < width; i++)
-				bg.put(i, y, bgc);
-			fg.put(x, y, s, fgc);
-		}
-
-		@Override
-		public void fill(What what, T color) {
-			/* Nope, not Doom's Big Fucking Gun */
-			final boolean bfg = what.hasFG();
-			final boolean bbg = what.hasBG();
-			for (int x = 0; x < width; x++) {
-				for (int y = 0; y < height; y++) {
-					if (bfg)
-						putFG(x, y, ' ', color);
-					if (bbg)
-						putBG(x, y, color);
-				}
-			}
-		}
-
-		@Override
-		public boolean hasActiveAnimations() {
-			return bg.hasActiveAnimations() || fg.hasActiveAnimations();
-		}
-
-		@Override
-		public void setColorCenter(IColorCenter<T> icc) {
-			bg.setColorCenter(icc);
-			fg.setColorCenter(icc);
-		}
-
-	}
-
-}

+ 10 - 17
squidlib-util/src/main/java/squidpony/panel/ISquidPanel.java

@@ -1,7 +1,6 @@
 package squidpony.panel;
 
 import squidpony.IColorCenter;
-import squidpony.annotation.Beta;
 
 /**
  * The abstraction of {@code SquidPanel}s, to abstract from the UI
@@ -12,11 +11,7 @@ import squidpony.annotation.Beta;
  * 
  * @param <T>
  *            The type of colors
- * 
- * @see ICombinedPanel The combination of two panels, one for the background,
- *      one for the foreground; a frequent use case in roguelikes.
  */
-@Beta
 public interface ISquidPanel<T> {
 
 	/**
@@ -43,8 +38,8 @@ public interface ISquidPanel<T> {
 	 * offset.
 	 *
 	 * Does not word wrap. Characters that are not renderable (due to being at
-	 * negative offsets or offsets greater than the grid size) will not be shown
-	 * but will not cause any malfunctions.
+	 * negative offsets or offsets greater than the grid size) will not be shown but
+	 * will not cause any malfunctions.
 	 *
 	 * @param xOffset
 	 *            the x coordinate of the first character
@@ -62,8 +57,8 @@ public interface ISquidPanel<T> {
 	 * offset, using the colors that {@code cs} provides.
 	 *
 	 * Does not word wrap. Characters that are not renderable (due to being at
-	 * negative offsets or offsets greater than the grid size) will not be shown
-	 * but will not cause any malfunctions.
+	 * negative offsets or offsets greater than the grid size) will not be shown but
+	 * will not cause any malfunctions.
 	 *
 	 * @param xOffset
 	 *            the x coordinate of the first character
@@ -134,9 +129,8 @@ public interface ISquidPanel<T> {
 
 	/**
 	 * @return The default foreground color (if none was set with
-	 *         {@link #setDefaultForeground(Object)}), or the last color set
-	 *         with {@link #setDefaultForeground(Object)}. Cannot be
-	 *         {@code null}.
+	 *         {@link #setDefaultForeground(Object)}), or the last color set with
+	 *         {@link #setDefaultForeground(Object)}. Cannot be {@code null}.
 	 */
 	T getDefaultForegroundColor();
 
@@ -149,11 +143,10 @@ public interface ISquidPanel<T> {
 	ISquidPanel<T> setColorCenter(IColorCenter<T> icc);
 
 	/**
-	 * @return The panel doing the real job, i.e. an instance of
-	 *         {@code SquidPanel}. The type of colors is unspecified, as some
-	 *         clients have forwarding instances of this class that hides that
-	 *         the type of color of the backer differs from the type of color in
-	 *         {@code this}.
+	 * @return The panel doing the real job, i.e. an instance of {@code SquidPanel}.
+	 *         The type of colors is unspecified, as some clients have forwarding
+	 *         instances of this class that hides that the type of color of the
+	 *         backer differs from the type of color in {@code this}.
 	 * 
 	 *         <p>
 	 *         Can be {@code this} itself.

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 2302
squidlib-util/src/main/java/squidpony/squidai/CustomDijkstraMap.java


+ 0 - 500
squidlib-util/src/main/java/squidpony/squidgrid/mapping/ClassicRogueMapGenerator.java

@@ -1,500 +0,0 @@
-package squidpony.squidgrid.mapping;
-
-
-import squidpony.squidgrid.Direction;
-import squidpony.squidmath.Coord;
-import squidpony.squidmath.RNG;
-
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Creates a dungeon in the style of the original Rogue game. It will always
- * make a grid style of rooms where there are a certain number horizontally and
- * vertically and it will link them only next to each other.
- *
- * This dungeon generator is based on a port of the rot.js version.
- *
- * @author hyakugei
- * @author Eben Howard - http://squidpony.com - howard@squidpony.com
- */
-public class ClassicRogueMapGenerator {
-
-    /**
-     * Holds the information needed to track rooms in the classic rogue
-     * generation algorithm.
-     */
-    private class ClassicRogueRoom {
-
-        private int x, y, width, height, cellx, celly;
-        private final List<ClassicRogueRoom> connections = new LinkedList<>();
-
-        ClassicRogueRoom(int x, int y, int width, int height, int cellx, int celly) {
-            this.x = x;
-            this.y = y;
-            this.width = width;
-            this.height = height;
-            this.cellx = cellx;
-            this.celly = celly;
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 5;
-            hash = 89 * hash + cellx;
-            hash = 89 * hash + celly;
-            return hash;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final ClassicRogueRoom other = (ClassicRogueRoom) obj;
-            if (cellx != other.cellx) {
-                return false;
-            }
-            return celly == other.celly;
-        }
-    }
-
-    private RNG rng;
-
-    private int horizontalRooms, verticalRooms, dungeonWidth, dungeonHeight,
-            minRoomWidth, maxRoomWidth, minRoomHeight, maxRoomHeight;
-    private ClassicRogueRoom[][] rooms;
-    private Terrain[][] map;
-
-    /**
-     * Initializes the generator to turn out random dungeons within the specific
-     * parameters.
-     *
-     * Will size down the room width and height parameters if needed to ensure
-     * the desired number of rooms will fit both horizontally and vertically.
-     *
-     * @param horizontalRooms How many rooms will be made horizontally
-     * @param verticalRooms How many rooms will be made vertically
-     * @param dungeonWidth How wide the total dungeon will be
-     * @param dungeonHeight How high the total dungeon will be
-     * @param minRoomWidth The minimum width a room can be
-     * @param maxRoomWidth The maximum width a room can be
-     * @param minRoomHeight The minimum height a room can be
-     * @param maxRoomHeight The maximum height a room can be
-     */
-    public ClassicRogueMapGenerator(int horizontalRooms, int verticalRooms, int dungeonWidth, int dungeonHeight,
-                                    int minRoomWidth, int maxRoomWidth, int minRoomHeight, int maxRoomHeight) {
-        this(horizontalRooms, verticalRooms, dungeonWidth, dungeonHeight, minRoomWidth, maxRoomWidth, minRoomHeight, maxRoomHeight, new RNG());
-    }
-
-    /**
-     * Initializes the generator to turn out random dungeons within the specific
-     * parameters.
-     *
-     * Will size down the room width and height parameters if needed to ensure
-     * the desired number of rooms will fit both horizontally and vertically.
-     *
-     * @param horizontalRooms How many rooms will be made horizontally
-     * @param verticalRooms How many rooms will be made vertically
-     * @param dungeonWidth How wide the total dungeon will be
-     * @param dungeonHeight How high the total dungeon will be
-     * @param minRoomWidth The minimum width a room can be
-     * @param maxRoomWidth The maximum width a room can be
-     * @param minRoomHeight The minimum height a room can be
-     * @param maxRoomHeight The maximum height a room can be
-     */
-    public ClassicRogueMapGenerator(int horizontalRooms, int verticalRooms, int dungeonWidth, int dungeonHeight,
-                                    int minRoomWidth, int maxRoomWidth, int minRoomHeight, int maxRoomHeight, RNG rng)
-    {
-        this.rng = rng;
-        this.horizontalRooms = horizontalRooms;
-        this.verticalRooms = verticalRooms;
-        this.dungeonWidth = dungeonWidth;
-        this.dungeonHeight = dungeonHeight;
-        this.minRoomWidth = minRoomWidth;
-        this.maxRoomWidth = maxRoomWidth;
-        this.minRoomHeight = minRoomHeight;
-        this.maxRoomHeight = maxRoomHeight;
-
-        sanitizeRoomDimensions();
-    }
-
-    private void sanitizeRoomDimensions() {
-        int test = (dungeonWidth - 3 * horizontalRooms) / horizontalRooms;//have to leave space for hallways
-        maxRoomWidth = Math.min(test, maxRoomWidth);
-        minRoomWidth = Math.max(minRoomWidth, 2);
-        minRoomWidth = Math.min(minRoomWidth, maxRoomWidth);
-
-        test = (dungeonHeight - 3 * verticalRooms) / verticalRooms;//have to leave space for hallways
-        maxRoomHeight = Math.min(test, maxRoomHeight);
-        minRoomHeight = Math.max(minRoomHeight, 2);
-        minRoomHeight = Math.min(minRoomHeight, maxRoomHeight);
-    }
-
-    /**
-     * Builds and returns a map in the Classic Rogue style.
-     * <br>
-     * Only includes rooms, corridors and doors.
-     * <br>
-     * There is also a generate method that produces a 2D char array, which may be more suitable.
-     * @return a 2D array of Terrain objects
-     */
-    public Terrain[][] create() {
-        initRooms();
-        connectRooms();
-        connectUnconnectedRooms();
-        fullyConnect();
-        createRooms();
-        createCorridors();
-        return map;
-    }
-    /**
-     * Builds and returns a map in the Classic Rogue style, returned as a 2D char array.
-     *
-     * Only includes rooms ('.' for floor and '#' for walls), corridors (using the same chars as rooms) and doors ('+'
-     * for closed doors, does not generate open doors).
-     * <br>
-     * There is also a create method that produces a 2D array of Terrain objects, which could (maybe) be what you want.
-     * More methods in SquidLib expect char 2D arrays than Terrain anything, particularly in DungeonUtility.
-     * @return a 2D char array version of the map
-     */
-    public char[][] generate()
-    {
-        create();
-        if(map.length <= 0)
-            return new char[0][0];
-        char[][] gen = new char[map.length][map[0].length];
-        for (int x = 0; x < map.length; x++) {
-            for (int y = 0; y < map[x].length; y++) {
-                gen[x][y] = map[x][y].symbol();
-            }
-        }
-        return gen;
-    }
-
-    private void initRooms() {
-        rooms = new ClassicRogueRoom[horizontalRooms][verticalRooms];
-        map = new Terrain[dungeonWidth][dungeonHeight];
-        for (int x = 0; x < horizontalRooms; x++) {
-            for (int y = 0; y < verticalRooms; y++) {
-                rooms[x][y] = new ClassicRogueRoom(0, 0, 0, 0, x, y);
-            }
-        }
-        for (int x = 0; x < dungeonWidth; x++) {
-            for (int y = 0; y < dungeonHeight; y++) {
-                map[x][y] = Terrain.WALL;
-            }
-        }
-    }
-
-    private void connectRooms() {
-        List<ClassicRogueRoom> unconnected = new LinkedList<>();
-        for (int x = 0; x < horizontalRooms; x++) {
-            for (int y = 0; y < verticalRooms; y++) {
-                unconnected.add(rooms[x][y]);
-            }
-        }
-        unconnected = rng.shuffle(unconnected);
-
-        Direction[]  dirToCheck = new Direction[4];
-        for (ClassicRogueRoom room : unconnected) {
-            rng.shuffle(Direction.CARDINALS, dirToCheck);
-            for (Direction dir : dirToCheck) {
-                int nextX = room.x + dir.deltaX;
-                int nextY = room.y + dir.deltaY;
-                if (nextX < 0 || nextX >= horizontalRooms || nextY < 0 || nextY >= verticalRooms) {
-                    continue;
-                }
-                ClassicRogueRoom otherRoom = rooms[nextX][nextY];
-
-                if (room.connections.contains(otherRoom)) {
-                    break;//already connected to this room
-                }
-
-                if (!otherRoom.connections.isEmpty()) {
-                    room.connections.add(otherRoom);
-                    break;
-                }
-            }
-        }
-    }
-
-    private void connectUnconnectedRooms() {
-        for (int x = 0; x < horizontalRooms; x++) {
-            for (int y = 0; y < verticalRooms; y++) {
-                ClassicRogueRoom room = rooms[x][y];
-
-                if (room.connections.isEmpty()) {
-                    List<Direction> dirToCheck = Arrays.asList(Direction.CARDINALS);
-                    dirToCheck = rng.shuffle(dirToCheck);
-
-                    boolean validRoom = false;
-                    ClassicRogueRoom otherRoom = null;
-
-                    do {
-                        Direction dir = dirToCheck.remove(0);
-
-                        int nextX = x + dir.deltaX;
-                        if (nextX < 0 || nextX >= horizontalRooms) {
-                            continue;
-                        }
-                        int nextY = y + dir.deltaY;
-                        if (nextY < 0 || nextY >= verticalRooms) {
-                            continue;
-                        }
-
-                        otherRoom = rooms[nextX][nextY];
-                        validRoom = true;
-
-                        if (otherRoom.connections.contains(room)) {
-                            validRoom = false;
-                        }
-                        else {
-                            break;
-                        }
-                    } while (!dirToCheck.isEmpty());
-
-                    if (validRoom) {
-                        room.connections.add(otherRoom);
-                    }
-                }
-            }
-        }
-    }
-
-    private void fullyConnect() {
-        boolean allGood;
-        do {
-            LinkedList<ClassicRogueRoom> deq = new LinkedList<>();
-            for (int x = 0; x < horizontalRooms; x++) {
-                for (int y = 0; y < verticalRooms; y++) {
-                    deq.offer(rooms[x][y]);
-                }
-            }
-            LinkedList<ClassicRogueRoom> connected = new LinkedList<>();
-            connected.add(deq.removeFirst());
-            boolean changed = true;
-            testing:
-            while (changed) {
-                changed = false;
-                for (ClassicRogueRoom test : deq) {
-                    for (ClassicRogueRoom r : connected) {
-                        if (test.connections.contains(r) || r.connections.contains(test)) {
-                            connected.offer(test);
-                            deq.remove(test);
-                            changed = true;
-                            continue testing;
-                        }
-                    }
-                }
-            }
-
-            allGood = true;
-            if (!deq.isEmpty()) {
-                testing:
-                for (ClassicRogueRoom room : deq) {
-                    for (Direction dir : Direction.CARDINALS) {
-                        int x = room.cellx + dir.deltaX;
-                        int y = room.celly + dir.deltaY;
-                        if (x >= 0 && y >= 0 && x < horizontalRooms && y < verticalRooms) {
-                            ClassicRogueRoom otherRoom = rooms[x][y];
-                            if (connected.contains(otherRoom)) {
-                                room.connections.add(otherRoom);
-                                allGood = false;
-                                break testing;
-                            }
-                        }
-                    }
-                }
-            }
-
-        } while (!allGood);
-    }
-
-    private void createRooms() {
-        int cwp = dungeonWidth / horizontalRooms;
-        int chp = dungeonHeight / verticalRooms;
-
-        ClassicRogueRoom otherRoom;
-
-        for (int x = 0; x < horizontalRooms; x++) {
-            for (int y = 0; y < verticalRooms; y++) {
-                int sx = cwp * x;
-                int sy = chp * y;
-
-                sx = Math.max(sx, 2);
-                sy = Math.max(sy, 2);
-
-                int roomw = rng.between(minRoomWidth, maxRoomWidth + 1);
-                int roomh = rng.between(minRoomHeight, maxRoomHeight + 1);
-
-                if (y > 0) {
-                    otherRoom = rooms[x][y - 1];
-                    while (sy - (otherRoom.y + otherRoom.height) < 3) {
-                        sy++;
-                    }
-                }
-
-                if (x > 0) {
-                    otherRoom = rooms[x - 1][y];
-                    while (sx - (otherRoom.x + otherRoom.width) < 3) {
-                        sx++;
-                    }
-                }
-
-                int sxOffset = Math.round(rng.nextInt(cwp - roomw) / 2);
-                int syOffset = Math.round(rng.nextInt(chp - roomh) / 2);
-
-                while (sx + sxOffset + roomw >= dungeonWidth) {
-                    if (sxOffset > 0) {
-                        sxOffset--;
-                    } else {
-                        roomw--;
-                    }
-                }
-                while (sy + syOffset + roomh >= dungeonHeight) {
-                    if (syOffset > 0) {
-                        syOffset--;
-                    } else {
-                        roomh--;
-                    }
-                }
-
-                sx += sxOffset;
-                sy += syOffset;
-
-                ClassicRogueRoom r = rooms[x][y];
-                r.x = sx;
-                r.y = sy;
-                r.width = roomw;
-                r.height = roomh;
-
-                for (int xx = sx; xx < sx + roomw; xx++) {
-                    for (int yy = sy; yy < sy + roomh; yy++) {
-                        map[xx][yy] = Terrain.FLOOR;
-                    }
-                }
-            }
-        }
-    }
-
-    private Coord randomWallPosition(ClassicRogueRoom room, Direction dir) {
-        int x, y;
-        Coord p = null;
-
-        switch (dir) {
-            case LEFT:
-                y = rng.between(room.y + 1, room.y + room.height);
-                x = room.x - 1;
-                map[x][y] = Terrain.CLOSED_DOOR;
-                p = Coord.get(x - 1, y);
-                break;
-            case RIGHT:
-                y = rng.between(room.y + 1, room.y + room.height);
-                x = room.x + room.width;
-                map[x][y] = Terrain.CLOSED_DOOR;
-                p = Coord.get(x + 1, y);
-                break;
-            case UP:
-                x = rng.between(room.x + 1, room.x + room.width);
-                y = room.y - 1;
-                map[x][y] = Terrain.CLOSED_DOOR;
-                p = Coord.get(x, y - 1);
-                break;
-            case DOWN:
-                x = rng.between(room.x + 1, room.x + room.width);
-                y = room.y + room.height;
-                map[x][y] = Terrain.CLOSED_DOOR;
-                p = Coord.get(x, y + 1);
-                break;
-        case NONE:
-        	break;
-		case DOWN_LEFT:
-		case DOWN_RIGHT:
-		case UP_LEFT:
-		case UP_RIGHT:
-			throw new IllegalStateException("There should only be cardinal positions here");
-        }
-
-        return p;
-    }
-
-    /**
-     * Draws a corridor between the two points with a zig-zag in between.
-     *
-     * @param start
-     * @param end
-     */
-    private void digPath(Coord start, Coord end) {
-        int xOffset = end.x - start.x;
-        int yOffset = end.y - start.y;
-        int xpos = start.x;
-        int ypos = start.y;
-
-        List<Magnitude> moves = new LinkedList<>();
-
-        int xAbs = Math.abs(xOffset);
-        int yAbs = Math.abs(yOffset);
-
-        double firstHalf = rng.nextDouble();
-        double secondHalf = 1 - firstHalf;
-
-        Direction xDir = xOffset < 0 ? Direction.LEFT : Direction.RIGHT;
-        Direction yDir = yOffset > 0 ? Direction.DOWN : Direction.UP;
-
-        if (xAbs < yAbs) {
-            int tempDist = (int) Math.ceil(yAbs * firstHalf);
-            moves.add(new Magnitude(yDir, tempDist));
-            moves.add(new Magnitude(xDir, xAbs));
-            tempDist = (int) Math.floor(yAbs * secondHalf);
-            moves.add(new Magnitude(yDir, tempDist));
-        } else {
-            int tempDist = (int) Math.ceil(xAbs * firstHalf);
-            moves.add(new Magnitude(xDir, tempDist));
-            moves.add(new Magnitude(yDir, yAbs));
-            tempDist = (int) Math.floor(xAbs * secondHalf);
-            moves.add(new Magnitude(xDir, tempDist));
-        }
-
-        map[xpos][ypos] = Terrain.FLOOR;
-
-        while (!moves.isEmpty()) {
-            Magnitude move = moves.remove(0);
-            Direction dir = move.dir;
-            int dist = move.distance;
-            while (dist > 0) {
-                xpos += dir.deltaX;
-                ypos += dir.deltaY;
-                map[xpos][ypos] = Terrain.FLOOR;
-                dist--;
-            }
-        }
-    }
-
-    private void createCorridors() {
-        for (int x = 0; x < horizontalRooms; x++) {
-            for (int y = 0; y < verticalRooms; y++) {
-                ClassicRogueRoom room = rooms[x][y];
-                for (ClassicRogueRoom otherRoom : room.connections) {
-                    Direction dir = Direction.getCardinalDirection(otherRoom.cellx - room.cellx, otherRoom.celly - room.celly);
-                    digPath(randomWallPosition(room, dir), randomWallPosition(otherRoom, dir.opposite()));
-                }
-            }
-        }
-    }
-
-    private class Magnitude {
-
-        public Direction dir;
-        public int distance;
-
-        public Magnitude(Direction dir, int distance) {
-            this.dir = dir;
-            this.distance = distance;
-        }
-    }
-}

+ 0 - 68
squidlib-util/src/main/java/squidpony/squidgrid/mapping/Terrain.java

@@ -1,68 +0,0 @@
-package squidpony.squidgrid.mapping;
-
-import squidpony.annotation.Beta;
-
-/**
- * A base class for cell level features common to roguelike dungeons.
- *
- *
- * @author Eben Howard - http://squidpony.com - howard@squidpony.com
- */
-@Beta
-public class Terrain {
-
-    public static final Terrain FLOOR = new Terrain('.', 0),
-            WALL = new Terrain('#', 1),
-            CLOSED_DOOR = new Terrain('+', 2),
-            OPEN_DOOR = new Terrain('/', 2),
-            EMPTY_SPACE = new Terrain('_', 30),
-            LIQUID = new Terrain('~', 26),
-            ENTRANCE = new Terrain('<', 34),
-            EXIT = new Terrain('>', 38);
-    private final char symbol;
-    private final int color;
-
-    private Terrain(char symbol, int colorIndex) {
-        this.symbol = symbol;
-        color = colorIndex;
-    }
-
-    /**
-     * Returns the character representation for this terrain. This is meant to
-     * be for display purposes and should not be used to check for equality
-     * since multiple different terrains may return the same symbol.
-     *
-     * @return
-     */
-    public char symbol() {
-        return symbol;
-    }
-
-    /**
-     * Returns the color for this terrain.
-     *
-     * @return
-     */
-    public int colorIndex() {
-        return color;
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 7;
-        hash = 83 * hash + symbol;
-        return hash;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final Terrain other = (Terrain) obj;
-        return symbol == other.symbol;
-    }
-}

Fichier diff supprimé car celui-ci est trop grand
+ 6049 - 5442
squidlib-util/src/main/java/squidpony/squidmath/CoordPacker.java


+ 0 - 149
squidlib-util/src/main/java/squidpony/squidmath/GapShuffler.java

@@ -1,149 +0,0 @@
-package squidpony.squidmath;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-
-/**
- * Meant to take a fixed-size set of items and produce a shuffled stream of them such that an element is never chosen in
- * quick succession; that is, there should always be a gap between the same item's occurrences. This is an Iterable of
- * T, not a Collection, because it can iterate without stopping, infinitely, unless you break out of a foreach loop that
- * iterates through one of these, or call the iterator's next() method only a limited number of times. Collections have
- * a size that can be checked, but Iterables can be infinite (and in this case, this one is).
- * Created by Tommy Ettinger on 5/21/2016.
- * @param <T> the type of items to iterate over; ideally, the items are unique
- */
-public class GapShuffler<T> implements Iterator<T>, Iterable<T>, Serializable {
-    private static final long serialVersionUID = 1277543974688106290L;
-    public RNG rng;
-    private ArrayList<T> elements;
-    private int size, index;
-    private int[][] indexSections;
-    private GapShuffler() {}
-
-    /**
-     * Constructor that takes any Collection of T, shuffles it with an unseeded RNG, and can then iterate infinitely
-     * through mostly-random shuffles of the given collection. These shuffles are spaced so that a single element should
-     * always have a large amount of "gap" in order between one appearance and the next. It helps to keep the appearance
-     * of a gap if every item in elements is unique, but that is not necessary and does not affect how this works.
-     * @param elements a Collection of T that will not be modified
-     */
-    public GapShuffler(Collection<T> elements)
-    {
-        rng = new RNG(new LongPeriodRNG());
-        this.elements = rng.shuffle(elements);
-        size = this.elements.size();
-        double sz2 = size;
-        index = 0;
-        int portionSize = Math.min(20, Math.max(1, size / 2));
-        int minSection = Math.min(5, size / 2 + 1);
-        while (size % portionSize < minSection && portionSize > 2)
-            portionSize--;
-        indexSections = new int[(int)Math.ceil(sz2 / portionSize)][];
-        for (int i = 0; i < indexSections.length - 1; i++) {
-            indexSections[i] = PermutationGenerator.decodePermutation(
-                    rng.nextLong(PermutationGenerator.getTotalPermutations(portionSize)), portionSize, i * portionSize);
-            sz2 -= portionSize;
-        }
-        indexSections[indexSections.length - 1] = PermutationGenerator.decodePermutation(
-                rng.nextLong(PermutationGenerator.getTotalPermutations((int)sz2)),
-                (int)sz2, (indexSections.length - 1) * portionSize);
-    }
-
-    /**
-     * Constructor that takes any Collection of T, shuffles it with the given RNG, and can then iterate infinitely
-     * through mostly-random shuffles of the given collection. These shuffles are spaced so that a single element should
-     * always have a large amount of "gap" in order between one appearance and the next. It helps to keep the appearance
-     * of a gap if every item in elements is unique, but that is not necessary and does not affect how this works. The
-     * rng parameter is copied so externally using it won't change the order this produces its values; the rng field is
-     * used whenever the iterator needs to re-shuffle the internal ordering of elements. I suggest that the RNG should
-     * use LongPeriodRNG as its RandomnessSource, since it is in general a good choice for shuffling, but since this
-     * class mostly delegates its unique-shuffling code to PermutationGenerator and looks up at most 20 elements'
-     * permutation at once (allowing it to use a single random long to generate the permutation), there probably won't
-     * be problems if you use any other RandomnessSource.
-     * @param elements a Collection of T that will not be modified
-     * @param rng an RNG that can be pre-seeded; will be copied and not used directly
-     */
-    public GapShuffler(Collection<T> elements, RNG rng)
-    {
-        this.rng = rng.copy();
-        this.elements = rng.shuffle(elements);
-        size = this.elements.size();
-        double sz2 = size;
-        index = 0;
-        int portionSize = Math.min(20, Math.max(1, size / 2));
-        int minSection = Math.min(5, size / 2 + 1);
-        while (size % portionSize < minSection && portionSize > 2)
-            portionSize--;
-        indexSections = new int[(int)Math.ceil(sz2 / portionSize)][];
-        for (int i = 0; i < indexSections.length - 1; i++) {
-            indexSections[i] = PermutationGenerator.decodePermutation(
-                    rng.nextLong(PermutationGenerator.getTotalPermutations(portionSize)), portionSize, i * portionSize);
-            sz2 -= portionSize;
-        }
-        indexSections[indexSections.length - 1] = PermutationGenerator.decodePermutation(
-                rng.nextLong(PermutationGenerator.getTotalPermutations((int)sz2)),
-                (int)sz2, (indexSections.length - 1) * portionSize);
-    }
-
-    /**
-     * Gets the next element of the infinite sequence of T this shuffles through. This class can be used as an
-     * Iterator or Iterable of type T.
-     * @return the next element in the infinite sequence
-     */
-    public T next() {
-        if(index >= size)
-        {
-            index = 0;
-            int build = 0, inner, rotated;
-            for (int i = 0; i < indexSections.length; i++) {
-                if(indexSections.length <= 2)
-                    rotated = (indexSections.length + 2 - i) % indexSections.length;
-                else
-                    rotated = (indexSections.length + 1 - i) % indexSections.length;
-                inner = indexSections[rotated].length;
-                indexSections[rotated] =
-                        PermutationGenerator.decodePermutation(
-                                rng.nextLong(PermutationGenerator.getTotalPermutations(inner)),
-                                inner,
-                                build);
-                build += inner;
-            }
-        }
-        int ilen = indexSections[0].length, ii = index / ilen, ij = index - ilen * ii;
-        ++index;
-        return elements.get(indexSections[ii][ij]);
-    }
-    /**
-     * Returns {@code true} if the iteration has more elements.
-     * This is always the case for GapShuffler.
-     *
-     * @return {@code true} always
-     */
-    @Override
-    public boolean hasNext() {
-        return true;
-    }
-    /**
-     * Not supported.
-     *
-     * @throws UnsupportedOperationException always throws this exception
-     */
-    @Override
-    public void remove() {
-        throw new UnsupportedOperationException("remove() is not supported");
-    }
-
-    /**
-     * Returns an <b>infinite</b> iterator over elements of type {@code T}; the returned iterator is this object.
-     * You should be prepared to break out of any for loops that use this once you've gotten enough elements!
-     * The remove() method is not supported by this iterator and hasNext() will always return true.
-     *
-     * @return an infinite Iterator over elements of type T.
-     */
-    @Override
-    public Iterator<T> iterator() {
-        return this;
-    }
-}

+ 0 - 266
squidlib-util/src/main/java/squidpony/squidmath/IsaacRNG.java

@@ -1,266 +0,0 @@
-/**
- ------------------------------------------------------------------------------
- Rand.java: By Bob Jenkins.  My random number generator, ISAAC.
- rand.init() -- initialize
- rand.val()  -- get a random value
- MODIFIED:
- 960327: Creation (addition of randinit, really)
- 970719: use context, not global variables, for internal state
- 980224: Translate to Java
- ------------------------------------------------------------------------------
- */
-
-package squidpony.squidmath;
-
-/**
- * This is a port of the public domain Isaac64 (cryptographic) random number generator to Java.
- * It is a RandomnessSource here, so it should generally be used to make an RNG, which has more features.
- * IsaacRNG is slower than the non-cryptographic RNGs in SquidLib, but much faster than cryptographic RNGs
- * that need SecureRandom, and it's compatible with GWT and Android to boot!
- * Created by Tommy Ettinger on 8/1/2016.
- */
-
-public class IsaacRNG implements RandomnessSource {
-    static final int SIZEL = 8;              /* log of size of results[] and mem[] */
-    static final int SIZE = 256;               /* size of results[] and mem[] */
-    static final int MASK = 255<<2;            /* for pseudorandom lookup */
-    private int count;                           /* count through the results in results[] */
-    long results[];                                /* the results given to the user */
-    private long mem[];                                   /* the internal state */
-    private long a;                                              /* accumulator */
-    private long b;                                          /* the last result */
-    private long c;              /* counter, guarantees cycle is at least 2^^72 */
-
-
-    /**
-     * Constructs an IsaacRNG with no seed; this will produce one sequence of numbers as if the seed were 0
-     * (which it essentially is, though passing 0 to the constructor that takes a long will produce a different
-     * sequence) instead of what the other RandomnessSources do (initialize with a low-quality random number
-     * from Math.random()).
-     */
-    public IsaacRNG() {
-        mem = new long[SIZE];
-        results = new long[SIZE];
-        init(false);
-    }
-
-
-    /**
-     * Constructs an IsaacRNG with the given seed, which should be a rather large array of long values.
-     * You should try to make seed a long[256], but smaller arrays will be tolerated without error.
-     * Arrays larger than 256 items will only have the first 256 used.
-     * @param seed an array of longs to use as a seed; ideally it should be 256 individual longs
-     */
-    public IsaacRNG(long seed[]) {
-        mem = new long[SIZE];
-        results = new long[SIZE];
-        if(seed == null)
-            init(false);
-        else {
-            System.arraycopy(seed, 0, results, 0, Math.min(256, seed.length));
-            init(true);
-        }
-    }
-
-    /**
-     * Constructs an IsaacRNG with its state filled by the value of seed, run through the LightRNG algorithm.
-     * @param seed any long; will have equal influence on all bits of state
-     */
-    public IsaacRNG(long seed) {
-        mem = new long[SIZE];
-        results = new long[SIZE];
-        long z;
-        for (int i = 0; i < 256; i++) {
-            z = seed += 0x9E3779B97F4A7C15L;
-            z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
-            z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
-            results[i] = z ^ (z >>> 31);
-        }
-        init(true);
-    }
-
-    /**
-     * Constructs an IsaacRNG with its state filled by repeated hashing of seed.
-     * @param seed a String that should be exceptionally long to get the best results.
-     */
-    public IsaacRNG(String seed) {
-        mem = new long[SIZE];
-        results = new long[SIZE];
-        if(seed == null)
-            init(false);
-        else {
-            char[] chars = seed.toCharArray();
-            int slen = seed.length(), i = 0;
-            for (; i < 256 && i < slen; i++) {
-                results[i] = CrossHash.hash64(chars, i, slen);
-            }
-            for (; i < 256; i++) {
-                results[i] = CrossHash.hash64(results);
-            }
-            init(true);
-        }
-    }
-
-    private IsaacRNG(IsaacRNG other)
-    {
-        this(other.results);
-    }
-
-    /**
-     *  Generates 256 results to be used by later calls to next() or nextLong().
-     *  This is a fast (not small) implementation.
-     *  */
-    public final void regen() {
-        int i, j;
-        long x, y;
-
-        b += ++c;
-        for (i=0, j=128; i<128;) {
-            x = mem[i];
-            a ^= a<<21;
-            a += mem[j++];
-            mem[i] = y = mem[(int)(x&MASK)>>3] + a + b;
-            results[i++] = b = mem[(int)((y>>8)&MASK)>>3] + x;
-
-            x = mem[i];
-            a ^= a>>>5;
-            a += mem[j++];
-            mem[i] = y = mem[(int)(x&MASK)>>3] + a + b;
-            results[i++] = b = mem[(int)((y>>8)&MASK)>>3] + x;
-
-            x = mem[i];
-            a ^= a<<12;
-            a += mem[j++];
-            mem[i] = y = mem[(int)(x&MASK)>>3] + a + b;
-            results[i++] = b = mem[(int)((y>>8)&MASK)>>3] + x;
-
-            x = mem[i];
-            a ^= a>>>33;
-            a += mem[j++];
-            mem[i] = y = mem[(int)(x&MASK)>>3] + a + b;
-            results[i++] = b = mem[(int)((y>>8)&MASK)>>3] + x;
-        }
-
-        for (j=0; j<128;) {
-            x = mem[i];
-            a ^= a<<21;
-            a += mem[j++];
-            mem[i] = y = mem[(int)(x&MASK)>>3] + a + b;
-            results[i++] = b = mem[(int)((y>>8)&MASK)>>3] + x;
-
-            x = mem[i];
-            a ^= a>>>5;
-            a += mem[j++];
-            mem[i] = y = mem[(int)(x&MASK)>>3] + a + b;
-            results[i++] = b = mem[(int)((y>>8)&MASK)>>3] + x;
-
-            x = mem[i];
-            a ^= a<<12;
-            a += mem[j++];
-            mem[i] = y = mem[(int)(x&MASK)>>3] + a + b;
-            results[i++] = b = mem[(int)((y>>8)&MASK)>>3] + x;
-
-            x = mem[i];
-            a ^= a>>>33;
-            a += mem[j++];
-            mem[i] = y = mem[(int)(x&MASK)>>3] + a + b;
-            results[i++] = b = mem[(int)((y>>8)&MASK)>>3] + x;
-        }
-    }
-
-
-    /**
-     * Initializes this IsaacRNG; typically used from the constructor but can be called externally.
-     * @param flag if true, use data from seed; if false, initializes this to unseeded random state
-     */
-    public final void init(boolean flag) {
-        int i;
-        long a,b,c,d,e,f,g,h;
-        a=b=c=d=e=f=g=h=0x9e3779b97f4a7c13L;                        /* the golden ratio */
-
-        for (i=0; i<4; ++i) {
-            a-=e; f^=h>>>9;  h+=a;
-            b-=f; g^=a<<9;  a+=b;
-            c-=g; h^=b>>>23; b+=c;
-            d-=h; a^=c<<15; c+=d;
-            e-=a; b^=d>>>14; d+=e;
-            f-=b; c^=e<<20; e+=f;
-            g-=c; d^=f>>>17; f+=g;
-            h-=d; e^=g<<14; g+=h;
-            /*
-            a^=b<<11;  d+=a; b+=c;
-            b^=c>>>3;  e+=b; c+=d;
-            c^=d<<8;   f+=c; d+=e;
-            d^=e>>>16; g+=d; e+=f;
-            e^=f<<10;  h+=e; f+=g;
-            f^=g>>>4;  a+=f; g+=h;
-            g^=h<<8;   b+=g; h+=a;
-            h^=a>>>9;  c+=h; a+=b;
-            */
-        }
-
-        for (i=0; i<256; i+=8) {              /* fill in mem[] with messy stuff */
-            if (flag) {
-                a+= results[i  ]; b+= results[i+1]; c+= results[i+2]; d+= results[i+3];
-                e+= results[i+4]; f+= results[i+5]; g+= results[i+6]; h+= results[i+7];
-            }
-            a-=e; f^=h>>>9;  h+=a;
-            b-=f; g^=a<<9;  a+=b;
-            c-=g; h^=b>>>23; b+=c;
-            d-=h; a^=c<<15; c+=d;
-            e-=a; b^=d>>>14; d+=e;
-            f-=b; c^=e<<20; e+=f;
-            g-=c; d^=f>>>17; f+=g;
-            h-=d; e^=g<<14; g+=h;
-            mem[i  ]=a; mem[i+1]=b; mem[i+2]=c; mem[i+3]=d;
-            mem[i+4]=e; mem[i+5]=f; mem[i+6]=g; mem[i+7]=h;
-        }
-
-        if (flag) {           /* second pass makes all of seed affect all of mem */
-            for (i=0; i<256; i+=8) {
-                a+=mem[i  ]; b+=mem[i+1]; c+=mem[i+2]; d+=mem[i+3];
-                e+=mem[i+4]; f+=mem[i+5]; g+=mem[i+6]; h+=mem[i+7];
-                a-=e; f^=h>>>9;  h+=a;
-                b-=f; g^=a<<9;  a+=b;
-                c-=g; h^=b>>>23; b+=c;
-                d-=h; a^=c<<15; c+=d;
-                e-=a; b^=d>>>14; d+=e;
-                f-=b; c^=e<<20; e+=f;
-                g-=c; d^=f>>>17; f+=g;
-                h-=d; e^=g<<14; g+=h;
-                mem[i  ]=a; mem[i+1]=b; mem[i+2]=c; mem[i+3]=d;
-                mem[i+4]=e; mem[i+5]=f; mem[i+6]=g; mem[i+7]=h;
-            }
-        }
-
-        regen();
-        count = 256;
-    }
-
-
-    @Override
-    public final long nextLong() {
-        if (0 == count--) {
-            regen();
-            count = 255;
-        }
-        return results[count];
-    }
-
-    @Override
-    public int next( int bits ) {
-        //return (int)( nextLong() >>> (64 - bits) );
-        return (int)( nextLong() & ( 1L << bits ) - 1 );
-    }
-
-    /**
-     * Produces another RandomnessSource, but the new one will not produce the same data as this one.
-     * This is meant to be a "more-secure" generator, so this helps reduce the ability to guess future
-     * results from a given sequence of output.
-     * @return another RandomnessSource with the same implementation but no guarantees as to generation
-     */
-    @Override
-    public RandomnessSource copy() {
-        return new IsaacRNG(results);
-    }
-}

+ 0 - 493
squidlib-util/src/main/java/squidpony/squidmath/MultiKey.java

@@ -1,493 +0,0 @@
-package squidpony.squidmath;
-
-import squidpony.annotation.Beta;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.SortedSet;
-
-/**
- * An ordered multi-directional "map" that keeps 1 or more keysets organized so you can look up one key given a key in
- * another keyset, and do the same for the indices of keys. Does not have generic type parameters, which is needed
- * because we handle arbitrary counts of keysets, and each keyset could have its own type. You can use most of the
- * normal Map methods here, though they often need an int as their first argument, {@code which}, that specifies which
- * keyset the method applies to. For example, {@link #contains(int, Object)} checks for the presence of the second
- * parameter in the keyset specified by the first parameter. Adding items to a MultiKey uses {@link #put(Object...)},
- * and that does not take a {@code which} parameter because it needs to add an item to every keyset to succeed, and will
- * do nothing if the array or varargs passed to it has a different length than the {@link #keyCount} of the MultiKey.
- * Created by Tommy Ettinger on 10/23/2016.
- */
-@Beta
-@SuppressWarnings("unchecked")
-public class MultiKey {
-    public final int keyCount;
-    Arrangement[] keys;
-
-    /**
-     * Constructs an empty MultiKey.
-     */
-    public MultiKey()
-    {
-        this(3, 16, 0.5f);
-    }
-
-    /**
-     * Constructs a MultiKey with the expected number of indices to hold (the number of items in each keyset is always
-     * the same, and this will be more efficient if expected is greater than that number).
-     * @param expected how many items this should be ready to hold; can resize if needed
-     */
-    public MultiKey(int keyCount, int expected)
-    {
-        this(keyCount, expected, 0.5f);
-    }
-
-    /**
-     * Constructs a MultiKey with the expected number of indices to hold (the number of items in each keyset is always
-     * the same, and this will be more efficient if expected is greater than that number) and the load factor to use,
-     * between 0.1f and 0.8f usually (using load factors higher than 0.8f can cause problems).
-     * @param expected the amount of indices (the number of items in each keyset is always the same) this should hold
-     * @param f the load factor, probably between 0.1f and 0.8f
-     */
-    public MultiKey(int keyCount, int expected, float f)
-    {
-        this.keyCount = keyCount;
-        keys = new Arrangement[keyCount];
-        for (int i = 0; i < keyCount; i++) {
-            keys[i] = new Arrangement(expected, f);
-        }
-    }
-
-    /**
-     * Constructs a MultiKey from a Collection of Iterables that will be processed in tandem, adding a unique item from
-     * each keyset in keysets if and only if it can also add a unique item from all other keysets, otherwise skipping
-     * that iteration in each Iterable.
-     * @param keysets a Collection of Iterable data structures, each containing items that should all be unique
-     */
-    public MultiKey(Collection<Iterable> keysets) {
-        if (keysets == null) {
-            keyCount = 0;
-            keys = new Arrangement[0];
-        } else {
-            keyCount = keysets.size();
-            keys = new Arrangement[keyCount];
-            for (int i = 0; i < keyCount; i++) {
-                keys[i] = new Arrangement();
-            }
-            putAll(keysets);
-        }
-    }
-
-    public MultiKey(MultiKey other)
-    {
-        if(other == null)
-        {
-            keyCount = 0;
-            keys = new Arrangement[0];
-        }
-        else
-        {
-            keyCount = other.keyCount;
-            keys = new Arrangement[keyCount];
-            for (int i = 0; i < keyCount; i++) {
-                keys[i] = new Arrangement(other.keys[i]);
-            }
-        }
-    }
-
-    public MultiKey(Arrangement[] keysets)
-    {
-        if(keysets == null)
-        {
-            keyCount = 0;
-            keys = new Arrangement[0];
-        }
-        else
-        {
-            keyCount = keysets.length;
-            keys = new Arrangement[keyCount];
-            int minLength = Integer.MAX_VALUE;
-            for (int k = 0; k < keyCount; k++) {
-                if(keysets[k] == null)
-                    return;
-                minLength = Math.min(minLength, keysets[k].size);
-            }
-            for (int k = 0; k < keyCount; k++) {
-                keys[k] = keysets[k].take(minLength);
-            }
-        }
-    }
-    /**
-     * Returns true if this contains key in the keyset specified by which.
-     * @param which which keyset to check in
-     * @param key the key to check the presence of
-     * @return true if key is present in the keyset at which; false otherwise
-     */
-    public boolean contains(int which, Object key) {
-        if(which >= 0 && which < keyCount)
-            return keys[which].containsKey(key);
-        return false;
-    }
-
-    /**
-     * Returns true if index is between 0 (inclusive) and {@link #size()} (exclusive), or false otherwise.
-     * @param index the index to check
-     * @return true if index is a valid index in the ordering of this MultiKey
-     */
-    public boolean containsIndex(int index) {
-        if(keyCount > 0) return keys[0].containsValue(index);
-        return false;
-    }
-
-    /**
-     * Given an index of a keyset (which) and an Object key, finds the position in the ordering that key has in the
-     * keyset at which, or -1 if key is not present.
-     * <br>
-     * Unlike {@link java.util.List#indexOf(Object)}, this runs in constant time.
-     * @param which which keyset to check in
-     * @param key the key to find the position of
-     * @return the int index of key in the ordering, or -1 if it is not present
-     */
-    public int indexOf(int which, Object key)
-    {
-        if(which >= 0 && which < keyCount)
-            return keys[which].getInt(key);
-        return -1;
-    }
-
-    /**
-     * Given an index of a keyset (which) and an int index, finds the associated key in the keyset specified by which
-     * (using index as a point in the ordering).
-     * @param which which keyset to get from
-     * @param index an int index into this MultiKey
-     * @return the key (in the keyset found by which) with index for its position in the ordering, or null if index or which was invalid
-     */
-    public Object getAt(int which, int index)
-    {
-        if(which >= 0 && which < keyCount)
-            return keys[which].keyAt(index);
-        return null;
-    }
-
-    /**
-     * Given an int index, finds the associated keys at all keysets (using index as a point in the ordering) and returns
-     * them as a newly-allocated Object array.
-     * @param index an int index into this MultiKey
-     * @return the array of keys with index for their position in the ordering, or an array of null if index was invalid
-     * @see #getAllAt(int, Object[]) getAllAt can avoid allocating a new array each time
-     */
-    public Object[] getAllAt(int index) {
-        Object[] os = new Object[keyCount];
-        for (int i = 0; i < keyCount; i++) {
-            os[i] = keys[i].keyAt(index);
-        }
-        return os;
-    }
-
-    /**
-     * Given an int index and an Object array to reuse, finds the associated keys at all keysets (using index as a point
-     * in the ordering) and fills into with those keys, up to keyCount items.
-     * @param index an int index into this MultiKey
-     * @param into an Object array to reuse and fill with items; will be returned as-is if smaller than keyCount
-     * @return the array of keys with index for their position in the ordering, or an array of null if index was invalid
-     */
-    public Object[] getAllAt(int index, Object[] into) {
-        if (into != null && into.length >= keyCount) {
-            for (int i = 0; i < keyCount; i++) {
-                into[i] = keys[i].keyAt(index);
-            }
-        }
-        return into;
-    }
-
-    /**
-     * Given an index of the keyset to look up a key in (lookingUp), an index of the keyset to get from (getting), and
-     * an Object key to look up (key), finds the Object key in the keyset specified by getting that is associated with
-     * key in the keyset specified by lookingUp. key and the returned value will be at the same point in the ordering.
-     * @param lookingUp which keyset to look up the {@code key} parameter in
-     * @param getting which keyset to get a value from
-     * @param key an object to use as a key, which should be the right type for the keyset at lookingUp
-     * @return the object from getting's keyset that is associated with key, or null if key was not present
-     */
-    public Object getFrom(int lookingUp, int getting, Object key)
-    {
-        if(lookingUp >= 0 && lookingUp < keyCount && getting >= 0 && getting < keyCount)
-            return keys[getting].keyAt(keys[lookingUp].getInt(key));
-        return null;
-    }
-
-    /**
-     * Gets a random key from the keyset specified by which using the given RNG.
-     * @param which which keyset to get a random key from
-     * @param random generates a random index to get a key with
-     * @return a randomly chosen key from the keyset specified, or null if this is empty
-     */
-    public Object randomKey(int which, RNG random)
-    {
-        if(which >= 0 && which < keyCount)
-            return keys[which].randomKey(random);
-        return null;
-    }
-    /**
-     * Gets a random key from a random keyset in this MultiKey using the given RNG.
-     * @param random generates a random keyset index and random item index, to get a random key
-     * @return a randomly chosen Object key from possibly any keyset in this, or null if this is empty
-     */
-    public Object randomKey(RNG random)
-    {
-        if(keyCount > 0)
-            return keys[random.nextIntHasty(keyCount)].randomKey(random);
-        return null;
-    }
-
-    /**
-     * In the keyset specified by {@code which}, changes an existing key, {@code past}, to another key, {@code future},
-     * if past exists in that keyset and future does not yet exist in that keyset. This will retain past's point in the
-     * ordering for future, so the associated other key(s) will still be associated in the same way.
-     * @param which which keyset to alter the items in
-     * @param past a key, that must exist in the keyset specified by which, and will be changed
-     * @param future a key, that cannot currently exist in the keyset specified by which, but will if this succeeds
-     * @return this for chaining
-     */
-    public MultiKey alter(int which, Object past, Object future)
-    {
-        if(which >= 0 && which < keyCount && keys[which].containsKey(past) && !keys[which].containsKey(future))
-            keys[which].alter(past, future);
-        return this;
-    }
-    /**
-     * In the keyset specified by {@code which}, changes the key at {@code index} to another key, {@code future}, if
-     * index is valid and future does not yet exist in that keyset. The position in the ordering for future will be the
-     * same as index, and the same as the key this replaced, if this succeeds, so the other key(s) at that position will
-     * still be associated in the same way.
-     * @param which which keyset to alter the items in
-     * @param index a position in the ordering to change; must be at least 0 and less than {@link #size()}
-     * @param future a key, that cannot currently exist in the keyset specified by which, but will if this succeeds
-     * @return this for chaining
-     */
-    public MultiKey alterAt(int which, int index, Object future)
-    {
-        if(which >= 0 && which < keyCount && !keys[which].containsKey(future) && index >= 0 && index < keys[which].size)
-            keys[which].alter(keys[which].keyAt(index), future);
-        return this;
-    }
-
-    /**
-     * Adds a key to each keyset at the same point in the ordering (the end) of this MultiKey. The length of k must
-     * match the keyCount of this MultiKey, and the nth item in k will go into the nth keyset. No item in k can be
-     * present in the matching keyset in this before this is called. If you want to change or update an existing key,
-     * use {@link #alter(int, Object, Object)} or {@link #alterAt(int, int, Object)}.
-     * @param k an array or varargs of keys to add after the last index of this MultiKey; length must equal keyCount
-     * @return true if this collection changed as a result of this call
-     */
-    public boolean put(Object... k)
-    {
-        if(k != null && keyCount > 0 && k.length == keyCount) {
-            for (int i = 0; i < keyCount; i++) {
-                if(keys[i].containsKey(k[i]))
-                    return false;
-            }
-            for (int i = 0; i < keyCount; i++) {
-                keys[i].add(k[i]);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Goes through all Iterable items in {@code k} and adds their unique items into their corresponding keyset at the
-     * end. If an item from the nth Iterable is already present in the nth keyset in this when this would add one, this
-     * will not put any keys at that point in the iteration order, and will place the next unique group of items it
-     * finds in the arguments at that position instead.
-     * @param k a Collection of Iterable s of keys to add to their respective keysets; should all be unique (like a Set)
-     * @return true if this collection changed as a result of this call
-     */
-    public boolean putAll(Collection<Iterable> k)
-    {
-        if(k == null || k.size() != keyCount) return false;
-        boolean changed = false;
-        Iterator[] its = new Iterator[keyCount];
-        int idx = 0;
-        for (Iterable it : k) {
-            its[idx++] = it.iterator();
-        }
-        Object[] os = new Object[keyCount];
-        while (true)
-        {
-            for (int i = 0; i < keyCount; i++) {
-                if(!its[i].hasNext())
-                    return changed;
-                os[i] = its[i].next();
-            }
-            changed = put(os) || changed;
-        }
-    }
-    /**
-     * Puts all unique keys in {@code other} into this MultiKey, respecting other's ordering. If a key in other is
-     * already present when this would add one, this will not put the keys at that point in the iteration
-     * order, and will place the next unique items it finds in other at that position instead.
-     * @param other another MultiKey collection with the same keyCount
-     * @return true if this collection changed as a result of this call
-     */
-    public boolean putAll(MultiKey other)
-    {
-        if(other == null || other.keyCount != keyCount) return false;
-        boolean changed = false;
-        int sz = other.size();
-        Object[] os = new Object[keyCount];
-        for (int i = 0; i < sz; i++) {
-            changed = put(other.getAllAt(i, os)) || changed;
-        }
-        return changed;
-    }
-
-    /**
-     * Adds a key to each keyset at the given index in the ordering of this MultiKey. The length of k must
-     * match the keyCount of this MultiKey, and the nth item in k will go into the nth keyset. No item in k can be
-     * present in the matching keyset in this before this is called. If you want to change or update an existing key,
-     * use {@link #alter(int, Object, Object)} or {@link #alterAt(int, int, Object)}.
-     * @param k an array or varargs of keys to add after the last index of this MultiKey; length must equal keyCount
-     * @return true if this collection changed as a result of this call
-     */
-    public boolean putAt(int index, Object... k)
-    {
-        if(k != null && keyCount > 0 && k.length == keyCount) {
-            for (int i = 0; i < keyCount; i++) {
-                if(keys[i].containsKey(k[i]))
-                    return false;
-            }
-            for (int i = 0; i < keyCount; i++) {
-                keys[i].addAt(index, k[i]);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Removes a given Object key from the keyset specified by which, if {@code removing} exists in that keyset, and
-     * also removes any keys associated with its point in the ordering.
-     * @param which which keyset to remove the item from; if {@code removing} isn't in that keyset, this does nothing
-     * @param removing the key to remove
-     * @return this for chaining
-     */
-    public MultiKey remove(int which, Object removing)
-    {
-        if(which >= 0 && which < keyCount) {
-            int i = keys[which].removeInt(removing);
-            if(i >= 0) {
-                for (int j = 0; j < keyCount; j++) {
-                    if(j != which)
-                        keys[j].removeAt(i);
-                }
-            }
-        }
-        return this;
-    }
-
-    /**
-     * Removes a given point in the ordering, if {@code index} is at least 0 and less than {@link #size()}.
-     * @param index the position in the ordering to remove
-     * @return this for chaining
-     */
-    public MultiKey removeAt(int index)
-    {
-        if(index >= 0 && keyCount > 0 && index < keys[0].size) {
-            for (int i = 0; i < keyCount; i++) {
-                keys[i].removeAt(index);
-            }
-        }
-        return this;
-    }
-
-    /**
-     * Reorders this MultiKey using {@code ordering}, which have the same length as this MultiKey's {@link #size()}
-     * and can be generated with {@link squidpony.GwtCompatibility#range(int)} (which, if applied, would produce no
-     * change to the current ordering), {@link RNG#randomOrdering(int)} (which gives a random ordering, and if
-     * applied immediately would be the same as calling {@link #shuffle(RNG)}), or made in some other way. If you
-     * already have an ordering and want to make a different ordering that can undo the change, you can use
-     * {@link squidpony.GwtCompatibility#invertOrdering(int[])} called on the original ordering.
-     * @param ordering an int array or vararg that should contain each int from 0 to {@link #size()} (or less)
-     * @return this for chaining
-     */
-    public MultiKey reorder(int... ordering)
-    {
-        if(ordering != null) {
-            for (int i = 0; i < keyCount; i++) {
-                keys[i].reorder(ordering);
-            }
-        }
-        return this;
-    }
-
-    /**
-     * Generates a random ordering with rng and applies the same ordering to all kinds of keys this has; they will
-     * maintain their current association to other keys but their ordering/indices will change.
-     * @param rng an RNG to produce the random ordering this will use
-     * @return this for chaining
-     */
-    public MultiKey shuffle(RNG rng)
-    {
-        if(keyCount > 0) {
-            int[] ordering = rng.randomOrdering(keys[0].size);
-            for (int i = 0; i < keyCount; i++) {
-                keys[i].reorder(ordering);
-            }
-        }
-        return this;
-    }
-
-    /**
-     * Creates a new iterator over the keys this holds in the keyset specified by which. This can be problematic for
-     * garbage collection if called very frequently; it may be better to access items by index (which also lets you
-     * access other keys associated with that index) using {@link #getAt(int, int)} in a for(int i=0...) loop.
-     * @return a newly-created iterator over this MultiKey's keys in the specified keyset
-     */
-    public Iterator iterator(int which)
-    {
-        if(which >= 0 && which < keyCount)
-            return keys[which].iterator();
-        return null;
-    }
-
-    /**
-     * Gets and caches the keys in the keyset specified by which as a Collection that implements SortedSet (and so also
-     * implements Set).
-     * @param which which keyset to get as a separate value
-     * @return the keys from the keyset specified by which, as a SortedSet
-     */
-    public SortedSet getSet(int which) {
-        if(which >= 0 && which < keyCount)
-            return keys[which].keySet();
-        return null;
-    }
-
-    /**
-     * To be called sparingly, since this allocates a new OrderedSet instead of reusing one.
-     * @param which which keyset to get as a separate value
-     * @return the keys from the keyset specified by which, as an OrderedSet
-     */
-    public OrderedSet getOrderedSet(int which) {
-        if(which >= 0 && which < keyCount)
-            return keys[which].keysAsOrderedSet();
-        return null;
-
-    }
-
-    public int keyCount() {
-        return keyCount;
-    }
-    public int valueCount() {
-        return 0;
-    }
-
-    public int size() {
-        return (keyCount > 0) ? keys[0].size : 0;
-    }
-
-    public boolean isEmpty()
-    {
-        return keyCount > 0 && keys[0].size > 0;
-    }
-
-}

+ 0 - 141
squidlib-util/src/main/java/squidpony/squidmath/NeuralParticle.java

@@ -1,141 +0,0 @@
-package squidpony.squidmath;
-
-
-import squidpony.annotation.Beta;
-
-import java.io.Serializable;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Creates a field of particles that tend to form a neuron image type
- * distribution. The distribution tends to reach towards the largest area of
- * empty space, but features many nice branches and curls as well.
- *
- * If no points are added before the populate method is run, the center of the
- * area is chosen as the single pre-populated point.
- *
- * Based on work by Nolithius
- *
- * http://www.nolithius.com/game-development/neural-particle-deposition
- *
- * Source code is available on GitHub:
- * https://github.com/Nolithius/neural-particle as well as Google Code
- * (now archived): http://code.google.com/p/neural-particle/
- *
- * @author @author Eben Howard - http://squidpony.com - howard@squidpony.com
- */
-@Beta
-public class NeuralParticle implements Serializable{
-    private static final long serialVersionUID = -3742942580678517149L;
-
-    private final RNG rng;
-    private final int maxDistance, minDistance, width, height;
-    private final LinkedList<Coord> distribution = new LinkedList<>();
-
-    public NeuralParticle(int width, int height, int maxDistance, RNG rng) {
-        this.rng = rng;
-        this.maxDistance = maxDistance;
-        this.width = width;
-        this.height = height;
-        minDistance = 1;
-    }
-
-    /**
-     * Populates the field with given number of points.
-     *
-     * @param quantity the number of points to insert
-     */
-    public void populate(int quantity) {
-        for (int i = 0; i < quantity; i++) {
-            add(createPoint());
-        }
-    }
-
-    /**
-     * Returns a list of the current distribution.
-     *
-     * @return the distribution as a List of Coord
-     */
-    public List<Coord> asList() {
-        return new LinkedList<>(distribution);
-    }
-
-    /**
-     * Returns an integer mapping of the current distribution.
-     *
-     * @param scale the value that active points will hold
-     * @return a 2D int array, with all elements equal to either 0 or scale
-     */
-    public int[][] asIntMap(int scale) {
-        int ret[][] = new int[width][height];
-        for (Coord p : distribution) {
-            ret[p.x][p.y] = scale;
-        }
-        return ret;
-    }
-
-    /**
-     * Adds a single specific point to the distribution.
-     *
-     * @param point the Coord, also called a pip here, to insert
-     */
-    public void add(Coord point) {
-        distribution.add(point);
-    }
-
-    /**
-     * Creates a pip that falls within the required distance from the current
-     * distribution. Does not add the pip to the distribution.
-     *
-     * @return the created pip
-     */
-    public Coord createPoint() {
-        Coord randomPoint = randomPoint();
-        Coord nearestPoint = nearestPoint(randomPoint);
-        double pointDistance = randomPoint.distance(nearestPoint);
-        // Too close, toss
-        while (pointDistance < minDistance) {
-            randomPoint = randomPoint();
-            nearestPoint = nearestPoint(randomPoint);
-            pointDistance = randomPoint.distance(nearestPoint);
-        }
-        // Adjust if we're too far
-        if (pointDistance > maxDistance) {
-            // Calculate unit vector
-            double unitX = (randomPoint.x - nearestPoint.x) / pointDistance;
-            double unitY = (randomPoint.y - nearestPoint.y) / pointDistance;
-            randomPoint = Coord.get( (int) (rng.between(minDistance, maxDistance + 1) * unitX + nearestPoint.x)
-                                   , (int) (rng.between(minDistance, maxDistance + 1) * unitY + nearestPoint.y));
-        }
-        return randomPoint;
-    }
-
-    private Coord nearestPoint(Coord point) {
-        if (distribution.isEmpty()) {
-            Coord center = Coord.get(width / 2, height / 2);
-            distribution.add(center);
-            return center;
-        }
-
-        Coord nearestPoint = distribution.getFirst();
-        double nearestDistance = point.distance(nearestPoint);
-        for (Coord candidatePoint : distribution) {
-            double candidateDistance = point.distance(candidatePoint);
-            if (candidateDistance > 0 && candidateDistance <= maxDistance) {
-                return candidatePoint;
-            }
-
-            if (candidateDistance < nearestDistance) {
-                nearestPoint = candidatePoint;
-                nearestDistance = candidateDistance;
-            }
-        }
-        return nearestPoint;
-    }
-
-    private Coord randomPoint() {
-        return Coord.get(rng.nextInt(width), rng.nextInt(height));
-    }
-
-}

+ 0 - 87
squidlib-util/src/main/java/squidpony/squidmath/OrthoLine.java

@@ -1,87 +0,0 @@
-package squidpony.squidmath;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * A simple line-drawing algorithm that only takes orthogonal steps; may be useful for LOS in games that use Manhattan
- * distances for measurements.
- * Algorithm is from http://www.redblobgames.com/grids/line-drawing.html#stepping , thanks Amit!
- * Created by Tommy Ettinger on 1/10/2016.
- */
-public class OrthoLine {
-    /**
-     * Draws a line from (startX, startY) to (endX, endY) using only N/S/E/W movement. Returns a List of Coord in order.
-     *
-     * @param startX x of starting point
-     * @param startY y of starting point
-     * @param endX   x of ending point
-     * @param endY   y of ending point
-     * @return List of Coord, including (startX, startY) and (endX, endY) and all points walked between
-     */
-    public static List<Coord> line(int startX, int startY, int endX, int endY) {
-        int dx = endX - startX, dy = endY - startY, nx = Math.abs(dx), ny = Math.abs(dy);
-        int signX = (dx > 0) ? 1 : -1, signY = (dy > 0) ? 1 : -1, workX = startX, workY = startY;
-        LinkedList<Coord> drawn = new LinkedList<>();
-        drawn.add(Coord.get(startX, startY));
-        for (int ix = 0, iy = 0; ix < nx || iy < ny; ) {
-            if ((0.5f + ix) / nx < (0.5 + iy) / ny) {
-                workX += signX;
-                ix++;
-            } else {
-                workY += signY;
-                iy++;
-            }
-            drawn.add(Coord.get(workX, workY));
-        }
-        return drawn;
-    }
-
-    /**
-     * Draws a line from start to end using only N/S/E/W movement. Returns a List of Coord in order.
-     * @param start starting point
-     * @param end ending point
-     * @return List of Coord, including start and end and all points walked between
-     */
-    public static List<Coord> line(Coord start, Coord end)
-    {
-        return line(start.x, start.y, end.x, end.y);
-    }
-    /**
-     * Draws a line from (startX, startY) to (endX, endY) using only N/S/E/W movement. Returns an array of Coord in order.
-     *
-     * @param startX x of starting point
-     * @param startY y of starting point
-     * @param endX   x of ending point
-     * @param endY   y of ending point
-     * @return array of Coord, including (startX, startY) and (endX, endY) and all points walked between
-     */
-    public static Coord[] line_(int startX, int startY, int endX, int endY) {
-        int dx = endX - startX, dy = endY - startY, nx = Math.abs(dx), ny = Math.abs(dy);
-        int signX = (dx > 0) ? 1 : -1, signY = (dy > 0) ? 1 : -1, workX = startX, workY = startY;
-        Coord[] drawn = new Coord[nx + ny + 1];
-        drawn[0] = Coord.get(startX, startY);
-        for (int i = 1, ix = 0, iy = 0; ix < nx || iy < ny; i++) {
-            if ((0.5f + ix) / nx < (0.5 + iy) / ny) {
-                workX += signX;
-                ix++;
-            } else {
-                workY += signY;
-                iy++;
-            }
-            drawn[i] = Coord.get(workX, workY);
-        }
-        return drawn;
-    }
-
-    /**
-     * Draws a line from start to end using only N/S/E/W movement. Returns a List of Coord in order.
-     * @param start starting point
-     * @param end ending point
-     * @return List of Coord, including start and end and all points walked between
-     */
-    public static Coord[] line_(Coord start, Coord end)
-    {
-        return line_(start.x, start.y, end.x, end.y);
-    }
-}

+ 0 - 765
squidlib-util/src/main/java/squidpony/squidmath/PermutationGenerator.java

@@ -1,765 +0,0 @@
-// ============================================================================
-//   Copyright 2006-2012 Daniel W. Dyer
-//
-//   Licensed under the Apache License, Version 2.0 (the "License");
-//   you may not use this file except in compliance with the License.
-//   You may obtain a copy of the License at
-//
-//       http://www.apache.org/licenses/LICENSE-2.0
-//
-//   Unless required by applicable law or agreed to in writing, software
-//   distributed under the License is distributed on an "AS IS" BASIS,
-//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//   See the License for the specific language governing permissions and
-//   limitations under the License.
-// ============================================================================
-package squidpony.squidmath;
-
-import java.io.Serializable;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Permutation generator for generating all permutations for all sets up to
- * 20 elements in size.  While 20 may seem a low limit, bear in mind that
- * the number of permutations of a set of size n is n!  For a set of 21
- * items, the number of permutations is bigger than can be stored in Java's
- * 64-bit long integer data type.  Therefore it seems unlikely that you
- * could ever generate, let alone process, all of the permutations in a
- * reasonable time frame.  For this reason the implementation is optimised for
- * sets of size 20 or less (this affords better performance by allowing primitive
- * numeric types to be used for calculations rather than
- * {@link java.math.BigInteger}).
- * <br>
- * Originally part of the <a href="http://maths.uncommons.org/">Uncommon Maths software package</a>.
- * @param <T> The type of element that the permutation will consist of.
- * @author Daniel Dyer (modified from the original version written by Michael
- * Gilleland of Merriam Park Software -
- * <a href="http://www.merriampark.com/perm.htm">http://www.merriampark.com/perm.htm</a>).
- * @see CombinationGenerator
- */
-public class PermutationGenerator<T> implements Iterable<List<T>>, Serializable
-{
-    private static final long serialVersionUID = 514276118639629743L;
-
-    private final T[] elements;
-    private final int[] permutationIndices;
-    private long remainingPermutations;
-    private long totalPermutations;
-
-
-    /**
-     * Permutation generator that generates all possible orderings of
-     * the elements in the specified set.
-     * @param elements The elements to permute; will be modified, so this should be copied beforehand
-     */
-    public PermutationGenerator(T[] elements)
-    {
-        if (elements.length > 20)
-        {
-            throw new IllegalArgumentException("Size must be less than or equal to 20.");
-        }
-        this.elements = elements;
-        permutationIndices = new int[elements.length];
-        totalPermutations = MathExtras.factorial(elements.length);
-        reset();
-    }
-
-
-    /**
-     * Permutation generator that generates all possible orderings of
-     * the elements in the specified set.
-     * @param elements The elements to permute.
-     * @param filler An array of T with the same length as elements; needed because GWT can't create a generic array.
-     */
-    @SuppressWarnings("unchecked")
-    public PermutationGenerator(Collection<T> elements, T[] filler)
-    {
-        this(elements.toArray(filler));
-    }
-
-
-    /**
-     * Resets the generator state.
-     */
-    public final void reset()
-    {
-        for (int i = 0; i < permutationIndices.length; i++)
-        {
-            permutationIndices[i] = i;
-        }
-        remainingPermutations = totalPermutations;
-    }
-
-
-    /**
-     * Returns the number of permutations not yet generated.
-     * @return The number of unique permutations still to be generated.
-     */
-    public long getRemainingPermutations()
-    {
-        return remainingPermutations;
-    }
-
-
-    /**
-     * Returns the total number of unique permutations that can be
-     * generated for the given set of elements.
-     * @return The total number of permutations.
-     */
-    public long getTotalPermutations()
-    {
-        return totalPermutations;
-    }
-
-    /**
-     * Returns the total number of unique permutations that can be
-     * generated for the given count of permute-able elements.
-     * Typically used with the static methods of this class that
-     * find permutation indices.
-     * @param count the number of elements (typically indices) you want to find a permutation of
-     * @return The total number of permutations.
-     */
-    public static long getTotalPermutations(int count)
-    {
-        return MathExtras.factorial(count);
-    }
-
-
-    /**
-     * Returns the total number of unique permutations that can be
-     * generated for the given count of permute-able elements.
-     * Typically used with the static methods of this class that
-     * find permutation indices and involve BigInteger values.
-     * @param count the number of elements (typically indices) you want to find a permutation of
-     * @return The total number of permutations.
-     */
-    public static BigInteger getBigTotalPermutations(int count)
-    {
-        return MathExtras.bigFactorial(count);
-    }
-
-
-    /**
-     * Are there more permutations that have not yet been returned?
-     * @return true if there are more permutations, false otherwise.
-     */
-    public boolean hasMore()
-    {
-        return remainingPermutations > 0;
-    }
-
-
-    /**
-     * Generate the next permutation and return an array containing
-     * the elements in the appropriate order.  This overloaded method
-     * allows the caller to provide an array that will be used and returned.
-     * The purpose of this is to improve performance when iterating over
-     * permutations. This method allows a single array instance to be reused.
-     * @param destination Provides an array to use to create the
-     * permutation.  The specified array must be the same length as a
-     * permutation.  This is the array that will be returned, once
-     * it has been filled with the elements in the appropriate order.
-     * @return The next permutation as an array.
-     */
-    public T[] nextPermutationAsArray(T[] destination)
-    {
-        if (destination.length != elements.length)
-        {
-            throw new IllegalArgumentException("Destination array must be the same length as permutations.");
-        }
-        generateNextPermutationIndices();
-        // Generate actual permutation.
-        for (int i = 0; i < permutationIndices.length; i++)
-        {
-            destination[i] = elements[permutationIndices[i]];
-        }
-        return destination;
-    }
-
-
-    /**
-     * Generate the next permutation and return a list containing
-     * the elements in the appropriate order.
-     * @see #nextPermutationAsList(List)
-     * @return The next permutation as a list.
-     */
-    public List<T> nextPermutationAsList()
-    {
-        List<T> permutation = new ArrayList<T>(elements.length);
-        return nextPermutationAsList(permutation);
-    }
-
-
-    /**
-     * Generate the next permutation and return a list containing
-     * the elements in the appropriate order.  This overloaded method
-     * allows the caller to provide a list that will be used and returned.
-     * The purpose of this is to improve performance when iterating over
-     * permutations.  If the {@link #nextPermutationAsList()} method is
-     * used it will create a new list every time.  When iterating over
-     * permutations this will result in lots of short-lived objects that
-     * have to be garbage collected.  This method allows a single list
-     * instance to be reused in such circumstances.
-     * @param destination Provides a list to use to create the
-     * permutation.  This is the list that will be returned, once
-     * it has been filled with the elements in the appropriate order.
-     * @return The next permutation as a list.
-     */
-    public List<T> nextPermutationAsList(List<T> destination)
-    {
-        generateNextPermutationIndices();
-        // Generate actual permutation.
-        destination.clear();
-        for (int i : permutationIndices)
-        {
-            destination.add(elements[i]);
-        }
-        return destination;
-    }
-
-    /**
-     * Generate the indices into the elements array for the next permutation.  The
-     * algorithm is from Kenneth H. Rosen, Discrete Mathematics and its Applications,
-     * 2nd edition (NY: McGraw-Hill, 1991), p. 284)
-     */
-    private void generateNextPermutationIndices()
-    {
-        if (remainingPermutations == 0)
-        {
-            throw new IllegalStateException("There are no permutations remaining.  " +
-                                            "Generator must be reset to continue using.");
-        }
-        else if (remainingPermutations < totalPermutations)
-        {
-            // Find largest index j with permutationIndices[j] < permutationIndices[j + 1]
-            int j = permutationIndices.length - 2;
-            while (permutationIndices[j] > permutationIndices[j + 1])
-            {
-                j--;
-            }
-
-            // Find index k such that permutationIndices[k] is smallest integer greater than
-            // permutationIndices[j] to the right of permutationIndices[j].
-            int k = permutationIndices.length - 1;
-            while (permutationIndices[j] > permutationIndices[k])
-            {
-                k--;
-            }
-
-            // Interchange permutation indices.
-            int temp = permutationIndices[k];
-            permutationIndices[k] = permutationIndices[j];
-            permutationIndices[j] = temp;
-
-            // Put tail end of permutation after jth position in increasing order.
-            int r = permutationIndices.length - 1;
-            int s = j + 1;
-
-            while (r > s)
-            {
-                temp = permutationIndices[s];
-                permutationIndices[s] = permutationIndices[r];
-                permutationIndices[r] = temp;
-                r--;
-                s++;
-            }
-        }
-        --remainingPermutations;
-    }
-
-    private int[] getPermutationShift(T[] perm) {
-        int[] sh = new int[perm.length];
-        boolean[] taken = new boolean[perm.length];
-
-        for (int i = 0; i < perm.length - 1; i++) {
-            int ctr = -1;
-            for (int j = 0; j < perm.length; j++) {
-                if (!taken[j])
-                    ctr++;
-                if (perm[j] == elements[i]) {
-                    taken[j] = true;
-                    sh[i] = ctr;
-                    break;
-                }
-            }
-        }
-        return sh;
-    }
-
-    private int[] getPermutationShift(List<T> perm) {
-        int length = perm.size();
-        int[] sh = new int[length];
-        boolean[] taken = new boolean[length];
-
-        for (int i = 0; i < length - 1; i++) {
-            int ctr = -1;
-            for (int j = 0; j < length; j++) {
-                if (!taken[j])
-                    ctr++;
-                if (perm.get(j) == elements[i]) {
-                    taken[j] = true;
-                    sh[i] = ctr;
-                    break;
-                }
-            }
-        }
-        return sh;
-    }
-
-    /**
-     * Given an array of T that constitutes a permutation of the elements this was constructed with, finds the specific
-     * index of the permutation given a factoradic numbering scheme (not used by the rest of this class, except the
-     * decodePermutation() method). The index can be passed to decodePermutation to reproduce the permutation passed to
-     * this, or modified and then passed to decodePermutation(). Determines equality by identity, not by .equals(), so
-     * that equivalent values that have different references/identities can appear in the permuted elements.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param perm an array of T that must be a valid permutation of this object's elements
-     * @return an encoded number that can be used to reconstruct the permutation when passed to decodePermutation()
-     */
-    public long encodePermutation(T[] perm)
-    {
-        long e = 0;
-        if(perm == null || perm.length != elements.length)
-            return e;
-        int[] shift = getPermutationShift(perm);
-        for (int i = 1; i < shift.length; i++) {
-            e += shift[i] * MathExtras.factorialsStart[i];
-        }
-        return e;
-    }
-
-    /**
-     * Given a List of T that constitutes a permutation of the elements this was constructed with, finds the specific
-     * index of the permutation given a factoradic numbering scheme (not used by the rest of this class, except the
-     * decodePermutation() method). The index can be passed to decodePermutation to reproduce the permutation passed to
-     * this, or modified and then passed to decodePermutation(). Determines equality by identity, not by .equals(), so
-     * that equivalent values that have different references/identities can appear in the permuted elements.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param perm a List of T that must be a valid permutation of this object's elements
-     * @return an encoded number that can be used to reconstruct the permutation when passed to decodePermutation()
-     */
-    public long encodePermutation(List<T> perm)
-    {
-        long e = 0;
-        if(perm == null || perm.size() != elements.length)
-            return e;
-        int[] shift = getPermutationShift(perm);
-        for (int i = 1; i < shift.length; i++) {
-            e += shift[i] * MathExtras.factorialsStart[i];
-        }
-        return e;
-    }
-
-    private int[] factoradicDecode(long e)
-    {
-        int[] sequence = new int[elements.length];
-        int base = 2;
-
-        for (int k = 1; k < elements.length; k++)
-        {
-            sequence[elements.length - 1 - k] = (int)(e % base);
-            e /= base;
-
-            base++;
-        }
-        return sequence;
-    }
-
-    /**
-     * Given a long between 0 and the total number of permutations possible (see getTotalPermutations() for how to access
-     * this) and an array of T with the same length as the elements this was constructed with, fills the array with the
-     * permutation described by the long as a special (factoradic) index into the possible permutations. You can get an
-     * index for a specific permutation with encodePermutation() or by generating a random number between 0 and
-     * getTotalPermutations(), if you want it randomly.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param encoded the index encoded as a long
-     * @param destination an array of T that must have equivalent length to the elements this was constructed with
-     * @return the looked-up permutation, which is the same value destination will be assigned
-     */
-    public T[] decodePermutation(long encoded, T[] destination)
-    {
-        if(destination == null)
-            return null;
-        encoded %= totalPermutations;
-        int[] sequence = factoradicDecode(encoded);
-        //char[] list = new char[] { 'a', 'b', 'c', 'd', 'e' }; //change for elements
-
-        //char[] permuted = new char[n]; //change for destination
-        boolean[] set = new boolean[elements.length];
-
-        for (int i = 0; i < elements.length; i++)
-        {
-            int s = sequence[i];
-            int remainingPosition = 0;
-            int index;
-
-            // Find the s'th position in the permuted list that has not been set yet.
-            for (index = 0; index < elements.length; index++)
-            {
-                if (!set[index])
-                {
-                    if (remainingPosition == s)
-                        break;
-
-                    remainingPosition++;
-                }
-            }
-
-            destination[index] = elements[i];
-            set[index] = true;
-        }
-        return destination;
-    }
-
-    /**
-     * Given a long between 0 and the total number of permutations possible (see getTotalPermutations() for how to access
-     * this), creates a List filled with the permutation described by the long as a special (factoradic) index into the
-     * possible permutations. You can get an index for a specific permutation with encodePermutation() or by generating a
-     * random number between 0 and getTotalPermutations(), if you want it randomly.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param encoded the index encoded as a long
-     * @return a List of T that corresponds to the permutation at the encoded index
-     */
-    public List<T> decodePermutation(long encoded)
-    {
-        ArrayList<T> list = new ArrayList<T>(elements.length);
-        Collections.addAll(list, elements);
-        return decodePermutation(encoded, list);
-    }
-
-    /**
-     * Given a long between 0 and the total number of permutations possible (see getTotalPermutations() for how to access
-     * this) and a List of T with the same length as the elements this was constructed with, fills the List with the
-     * permutation described by the long as a special (factoradic) index into the possible permutations. You can get an
-     * index for a specific permutation with encodePermutation() or by generating a random number between 0 and
-     * getTotalPermutations(), if you want it randomly.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param encoded the index encoded as a long
-     * @param destination a List of T that must have equivalent size to the elements this was constructed with
-     * @return the looked-up permutation, which is the same value destination will be assigned
-     */
-    public List<T> decodePermutation(long encoded, List<T> destination)
-    {
-        if(destination == null)
-            return null;
-        encoded %= totalPermutations;
-        int[] sequence = factoradicDecode(encoded);
-        //char[] list = new char[] { 'a', 'b', 'c', 'd', 'e' }; //change for elements
-
-        //char[] permuted = new char[n]; //change for destination
-        boolean[] set = new boolean[elements.length];
-
-        for (int i = 0; i < elements.length; i++)
-        {
-            int s = sequence[i];
-            int remainingPosition = 0;
-            int index;
-
-            // Find the s'th position in the permuted list that has not been set yet.
-            for (index = 0; index < elements.length; index++)
-            {
-                if (!set[index])
-                {
-                    if (remainingPosition == s)
-                        break;
-
-                    remainingPosition++;
-                }
-            }
-
-            destination.set(index, elements[i]);
-            set[index] = true;
-        }
-        return destination;
-    }
-    /**
-     * <p>Provides a read-only iterator for iterating over the permutations
-     * generated by this object.  This method is the implementation of the
-     * {@link Iterable} interface that permits instances of this class to be
-     * used with the new-style for loop.</p>
-     * <p>For example:</p>
-     * <pre>
-     * List&lt;Integer&gt; elements = Arrays.asList(1, 2, 3);
-     * PermutationGenerator&lt;Integer&gt; permutations = new PermutationGenerator(elements);
-     * for (List&lt;Integer&gt; p : permutations)
-     * {
-     *     // Do something with each permutation.
-     * }
-     * </pre>
-     * @return An iterator.
-     * @since 1.1
-     */
-    public Iterator<List<T>> iterator()
-    {
-        return new Iterator<List<T>>()
-        {
-            public boolean hasNext()
-            {
-                return hasMore();
-            }
-
-
-            public List<T> next()
-            {
-                return nextPermutationAsList();
-            }
-
-
-            public void remove()
-            {
-                throw new UnsupportedOperationException("Iterator does not support removal.");
-            }
-        };
-    }
-
-
-    private static int[] getPermutationShift(int[] perm) {
-        int[] sh = new int[perm.length];
-        boolean[] taken = new boolean[perm.length];
-
-        for (int i = 0; i < perm.length - 1; i++) {
-            int ctr = -1;
-            for (int j = 0; j < perm.length; j++) {
-                if (!taken[j])
-                    ctr++;
-                if (perm[j] == i) {
-                    taken[j] = true;
-                    sh[i] = ctr;
-                    break;
-                }
-            }
-        }
-        return sh;
-    }
-    /**
-     * Given an array of int that constitutes a permutation of indices, where no element in perm is repeated and all
-     * ints are less than perm.length, finds the specific index of the permutation given a factoradic numbering scheme
-     * (not used by the rest of this class, except the decodePermutation() method). The index can be passed to
-     * decodePermutation to reproduce the index permutation passed to this, or modified and then passed to
-     * decodePermutation().
-     * <br>
-     * If perm is more than 20 items in length, you should use {@link #encodeBigPermutation} instead.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param perm an array of int that is a permutation of the range from 0 (inclusive) to perm.length (exclusive, must be no more than 20)
-     * @return an encoded number that can be used to reconstruct the permutation when passed to decodePermutation()
-     */
-    public static long encodePermutation(int[] perm)
-    {
-        long e = 0;
-        if(perm == null || perm.length <= 0)
-            return e;
-        int[] shift = getPermutationShift(perm);
-        for (int i = 1; i < shift.length; i++) {
-            e += shift[i] * MathExtras.factorialsStart[i];
-        }
-        return e;
-    }
-
-    /**
-     * Given an array of int that constitutes a permutation of indices, where no element in perm is repeated and all
-     * ints are less than perm.length, finds the specific index of the permutation given a factoradic numbering scheme
-     * (not used by the rest of this class, except the decodePermutation() method). The index can be passed to
-     * decodePermutation to reproduce the index permutation passed to this, or modified and then passed to
-     * decodePermutation().
-     * <br>
-     * If perm is 20 items or less in length, you can use {@link #encodePermutation} instead to get a 64-bit encoding.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param perm an array of int that is a permutation of the range from 0 (inclusive) to perm.length (exclusive)
-     * @return an encoded number that can be used to reconstruct the permutation when passed to decodePermutation()
-     */
-    public static BigInteger encodeBigPermutation(int[] perm)
-    {
-        BigInteger e = BigInteger.ZERO;
-        if(perm == null || perm.length <= 0)
-            return e;
-        int[] shift = getPermutationShift(perm);
-        for (int i = 1; i < shift.length; i++) {
-            e = e.add(MathExtras.bigFactorial(i).multiply(BigInteger.valueOf(shift[i])));
-        }
-        return e;
-    }
-
-
-    private static int[] factoradicDecode(long e, int count)
-    {
-        int[] sequence = new int[count];
-        int base = 2;
-
-        for (int k = 1; k < count; k++)
-        {
-            sequence[count - 1 - k] = (int)(e % base);
-            e /= base;
-
-            base++;
-        }
-        return sequence;
-    }
-
-    private static int[] factoradicDecode(BigInteger e, int count)
-    {
-        int[] sequence = new int[count];
-        BigInteger base = BigInteger.valueOf(2);
-
-        for (int k = 1; k < count; k++)
-        {
-            sequence[count - 1 - k] = e.mod(base).intValue();
-            e = e.divide(base);
-
-            base = base.add(BigInteger.ONE);
-        }
-        return sequence;
-    }
-
-    /**
-     * Given a long between 0 and the total number of permutations possible (see getTotalPermutations() for how to access
-     * this) and an int count of how many indices to find a permutation of, returns an array with the permutation
-     * of the indices described by the long as a special (factoradic) index into the possible permutations. You can get
-     * an index for a specific permutation with encodePermutation() or by generating a random number between 0 and
-     * getTotalPermutations(), if you want it randomly.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param encoded the index encoded as a long
-     * @param count an int between 1 and 20, inclusive, that will be the size of the returned array
-     * @return the looked-up permutation as an int array with length equal to count
-     */
-    public static int[] decodePermutation(long encoded, int count)
-    {
-        if(count <= 0)
-            return new int[0];
-        encoded %= MathExtras.factorial(count);
-        int[] sequence = factoradicDecode(encoded, count), destination = new int[count];
-        //char[] list = new char[] { 'a', 'b', 'c', 'd', 'e' }; //change for elements
-
-        //char[] permuted = new char[n]; //change for destination
-        boolean[] set = new boolean[count];
-
-        for (int i = 0; i < count; i++)
-        {
-            int s = sequence[i];
-            int remainingPosition = 0;
-            int index;
-
-            // Find the s'th position in the permuted list that has not been set yet.
-            for (index = 0; index < count; index++)
-            {
-                if (!set[index])
-                {
-                    if (remainingPosition == s)
-                        break;
-
-                    remainingPosition++;
-                }
-            }
-
-            destination[index] = i;
-            set[index] = true;
-        }
-        return destination;
-    }
-
-    /**
-     * Given a long between 0 and the total number of permutations possible (see getBigTotalPermutations() for how to
-     * access this) and an int count of how many indices to find a permutation of, returns an array with the permutation
-     * of the indices described by the long as a special (factoradic) index into the possible permutations. You can get
-     * an index for a specific permutation with encodeBigPermutation() or by generating a random number between 0 and
-     * getBigTotalPermutations(), if you want it randomly.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param encoded the index encoded as a BigInteger
-     * @param count a positive int that will be the size of the returned array
-     * @return the looked-up permutation as an int array with length equal to count
-     */
-    public static int[] decodePermutation(BigInteger encoded, int count)
-    {
-        if(count <= 0)
-            return new int[0];
-        BigInteger enc = encoded.mod(MathExtras.bigFactorial(count));
-        int[] sequence = factoradicDecode(enc, count), destination = new int[count];
-        //char[] list = new char[] { 'a', 'b', 'c', 'd', 'e' }; //change for elements
-
-        //char[] permuted = new char[n]; //change for destination
-        boolean[] set = new boolean[count];
-
-        for (int i = 0; i < count; i++)
-        {
-            int s = sequence[i];
-            int remainingPosition = 0;
-            int index;
-
-            // Find the s'th position in the permuted list that has not been set yet.
-            for (index = 0; index < count; index++)
-            {
-                if (!set[index])
-                {
-                    if (remainingPosition == s)
-                        break;
-
-                    remainingPosition++;
-                }
-            }
-
-            destination[index] = i;
-            set[index] = true;
-        }
-        return destination;
-    }
-
-    /**
-     * Given a long between 0 and the total number of permutations possible (see getTotalPermutations() for how to access
-     * this) and an int count of how many indices to find a permutation of, returns an array with the permutation
-     * of the indices described by the long as a special (factoradic) index into the possible permutations. You can get
-     * an index for a specific permutation with encodePermutation() or by generating a random number between 0 and
-     * getTotalPermutations(), if you want it randomly. This variant adds an int to each item in the returned array,
-     * which may be useful if generating indices that don't start at 0.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param encoded the index encoded as a long
-     * @param count an int between 1 and 20, inclusive, that will be the size of the returned array
-     * @param add an int to add to each item of the permutation
-     * @return the looked-up permutation as an int array with length equal to count
-     */
-    public static int[] decodePermutation(long encoded, int count, int add)
-    {
-        int[] p = decodePermutation(encoded, count);
-        for (int i = 0; i < p.length; i++) {
-            p[i] += add;
-        }
-        return p;
-    }
-
-    /**
-     * Given a long between 0 and the total number of permutations possible (see getBigTotalPermutations() for how to
-     * access this) and an int count of how many indices to find a permutation of, returns an array with the permutation
-     * of the indices described by the long as a special (factoradic) index into the possible permutations. You can get
-     * an index for a specific permutation with encodeBigPermutation() or by generating a random number between 0 and
-     * getBigTotalPermutations(), if you want it randomly. This variant adds an int to each item in the returned array,
-     * which may be useful if generating indices that don't start at 0.
-     * <br>
-     * Credit goes to user Joren on StackOverflow, http://stackoverflow.com/a/1506337
-     * @param encoded the index encoded as a BigInteger
-     * @param count a positive int that will be the size of the returned array
-     * @param add an int to add to each item of the permutation
-     * @return the looked-up permutation as an int array with length equal to count
-     */
-    public static int[] decodePermutation(BigInteger encoded, int count, int add)
-    {
-        int[] p = decodePermutation(encoded, count);
-        for (int i = 0; i < p.length; i++) {
-            p[i] += add;
-        }
-        return p;
-    }
-
-}

+ 0 - 341
squidlib-util/src/main/java/squidpony/squidmath/PermutedRNG.java

@@ -1,341 +0,0 @@
-/*
- * Ported to Java from the PCG library. Its copyright header follows:
- *
- * PCG Random Number Generation for C++
- *
- * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * For additional information about the PCG random number generation scheme,
- * including its license and other licensing options, visit
- *
- *     http://www.pcg-random.org
- */
-package squidpony.squidmath;
-
-import squidpony.StringKit;
-
-/**
- * This is a RandomnessSource in the PCG-Random family. It performs pseudo-
- * random modifications to the output based on the techniques from the
- * Permuted Congruential Generators created by M.E. O'Neill.
- * Specifically, this variant is:
- * RXS M XS -- random xorshift, mcg multiply, fixed xorshift
- *
- * The most statistically powerful generator, but all those steps
- * make it slower than some of the others.
- *
- * Because it's usually used in contexts where the state type and the
- * result type are the same, it is a permutation and is thus invert-able.
- * We thus provide a (protected) function to invert it.
- * <br>
- * Even though benchmarks on similar programs in C would lead you to
- * believe this should be somewhat faster than LightRNG, benchmarking
- * with JMH seems to show LightRNG being between 2 and 3 times faster
- * than PermutedRNG, and both drastically faster than java.util.Random .
- * @author Melissa E. O'Neill (Go HMC!)
- * @author Tommy Ettinger
- */
-public class PermutedRNG implements RandomnessSource, StatefulRandomness
-{
-	/** 2 raised to the 53, - 1. */
-    private static final long DOUBLE_MASK = ( 1L << 53 ) - 1;
-    /** 2 raised to the -53. */
-    private static final double NORM_53 = 1. / ( 1L << 53 );
-    /** 2 raised to the 24, -1. */
-    private static final long FLOAT_MASK = ( 1L << 24 ) - 1;
-    /** 2 raised to the -24. */
-    private static final double NORM_24 = 1. / ( 1L << 24 );
-    /**
-     * The state can be seeded with any value.
-     */
-    public long state;
-
-	private static final long serialVersionUID = 3637443966125527620L;
-
-    /** Creates a new generator seeded using Math.random. */
-    public PermutedRNG() {
-        this((long)Math.floor(Math.random() * Long.MAX_VALUE));
-    }
-
-    public PermutedRNG(final long seed) {
-        state = (seed + 1442695040888963407L) * 6364136223846793005L + 1442695040888963407L;
-    }
-
-    @Override
-    public int next( int bits ) {
-        return (int)( nextLong() & ( 1L << bits ) - 1 );
-    }
-
-
-    /**
-     * From the PCG-Random source:
-     * XorShifts are invert-able, but they are something of a pain to invert.
-     * This function backs them out.
-     * @param n a XorShift-ed value
-     * @param bits the number of bits we still need to invert, not constant
-     * @param shift the crazy one; the wild-card; it's some weird value every time it's used
-     * @return a long that inverts the shift done to n
-     */
-    private static long unxorshift(long n, int bits, int shift)
-    {
-        if (2*shift >= bits) {
-            return n ^ (n >>> shift);
-        }
-        long lowmask1 = (1L << (bits - shift*2)) - 1;
-        long highmask1 = ~lowmask1;
-        long top1 = n;
-        long bottom1 = n & lowmask1;
-        top1 ^= top1 >>> shift;
-        top1 &= highmask1;
-        n = top1 | bottom1;
-        long lowmask2 = (1L << (bits - shift)) - 1;
-        long bottom2 = n & lowmask2;
-        bottom2 = unxorshift(bottom2, bits - shift, shift);
-        bottom2 &= lowmask1;
-        return top1 | bottom2;
-    }
-
-    /**
-     * Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
-     * Calls nextLong() exactly one time.
-     * @return any int, all 32 bits are random
-     */
-    public int nextInt() {
-        return (int)nextLong();
-    }
-    /**
-     * Can return any long, positive or negative, of any size permissible in a 64-bit signed integer.
-     *
-     * @return any long, all 64 bits are random
-     */
-    @Override
-    public long nextLong()
-    {
-        // increment  = 1442695040888963407L;
-        // multiplier = 6364136223846793005L;
-
-        long p = state;
-        p ^= p >>> (5 + (p >>> 59));
-        p *= -5840758589994634535L;
-        state = state * 6364136223846793005L + 1442695040888963407L;
-        return p ^ (p >>> 43);
-    }
-
-    /**
-     * Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the
-     * copy, both will generate the same sequence of random numbers from the point copy() was called. This just need to
-     * copy the state so it isn't shared, usually, and produce a new value with the same exact state.
-     *
-     * @return a copy of this RandomnessSource
-     */
-    @Override
-    public RandomnessSource copy() {
-        PermutedRNG next = new PermutedRNG(state);
-        next.setState(state);
-        return next;
-    }
-
-    public static long permute(long p)
-    {
-        p ^= p >>> (5 + (p >>> 59));
-        p *= -5840758589994634535L;
-        return p ^ (p >>> 43);
-
-    }
-
-    protected static long invert(long internal)
-    {
-        internal = unxorshift(internal, 64, 43);
-        internal *= -3437190434928431767L;
-        return unxorshift(internal, 64, 5 + (int)(internal >>> 59));
-    }
-
-    /**
-     * Exclusive on the upper bound n.  The lower bound is 0.
-     * Will call nextLong() with no arguments at least 1 time, possibly more.
-     * @param n the upper bound; should be positive
-     * @return a random int less than n and at least equal to 0
-     */
-    public int nextInt( final int n ) {
-        if ( n <= 0 ) return 0;
-        int threshold = (0x7fffffff - n + 1) % n;
-        for (;;) {
-            int bits = (int)(nextLong() & 0x7fffffff);
-            if (bits >= threshold)
-                return bits % n;
-        }
-    }
-
-    /**
-     * Inclusive lower, exclusive upper.
-     * Will call nextLong() with no arguments at least 1 time, possibly more.
-     * @param lower the lower bound, inclusive, can be positive or negative
-     * @param upper the upper bound, exclusive, should be positive, must be greater than lower
-     * @return a random int at least equal to lower and less than upper
-     */
-    public int nextInt( final int lower, final int upper ) {
-        if ( upper - lower <= 0 ) throw new IllegalArgumentException();
-        return lower + nextInt(upper - lower);
-    }
-
-    /**
-     * Exclusive on the upper bound n. The lower bound is 0.
-     *
-     * Will call nextLong() with no arguments at least 1 time, possibly more.
-     * @param n the upper bound; should be positive
-     * @return a random long less than n
-     */
-    public long nextLong( final long n ) {
-        if ( n <= 0 ) return 0;
-        long threshold = (0x7fffffffffffffffL - n + 1) % n;
-        for (;;) {
-            long bits = nextLong() & 0x7fffffffffffffffL;
-            if (bits >= threshold)
-                return bits % n;
-        }
-    }
-
-    /**
-     * Exclusive on the upper bound n. The lower bound is 0.
-     *
-     * Will call nextLong() at least 1 time, possibly more.
-     * @param lower the lower bound, inclusive, can be positive or negative
-     * @param upper the upper bound, exclusive, should be positive, must be greater than lower
-     * @return a random long at least equal to lower and less than upper
-     */
-    public long nextLong( final long lower, final long upper ) {
-        if ( upper - lower <= 0 ) return 0;
-        return lower + nextLong(upper - lower);
-    }
-
-    /**
-     * Gets a uniform random double in the range [0.0,1.0)
-     *
-     * Calls nextLong() exactly one time.
-     *
-     * @return a random double at least equal to 0.0 and less than 1.0
-     */
-    public double nextDouble() {
-        return ( nextLong() & DOUBLE_MASK ) * NORM_53;
-    }
-
-    /**
-     * Gets a uniform random double in the range [0.0,outer) given a positive parameter outer. If outer
-     * is negative, it will be the (exclusive) lower bound and 0.0 will be the (inclusive) upper bound.
-     *
-     * Calls nextLong() exactly one time.
-     *
-     *  @param outer the exclusive outer bound, can be negative
-     * @return a random double between 0.0 (inclusive) and outer (exclusive)
-     */
-    public double nextDouble(final double outer) {
-        return nextDouble() * outer;
-    }
-
-    /**
-     * Gets a uniform random float in the range [0.0,1.0)
-     *
-     * Calls nextLong() exactly one time.
-     *
-     * @return a random float at least equal to 0.0f and less than 1.0f
-     */
-    public float nextFloat() {
-        return (float)( ( nextLong() & FLOAT_MASK ) * NORM_24 );
-    }
-
-    /**
-     * Gets a random value, true or false.
-     * Calls nextLong() once.
-     * @return a random true or false value.
-     */
-    public boolean nextBoolean() {
-        return ( nextLong() & 1L ) != 0L;
-    }
-
-    /**
-     * Given a byte array as a parameter, this will fill the array with random bytes (modifying it
-     * in-place). Calls nextLong() {@code Math.ceil(bytes.length / 8.0)} times.
-     * @param bytes a byte array that will have its contents overwritten with random bytes.
-     */
-    public void nextBytes( final byte[] bytes ) {
-        int i = bytes.length, n = 0;
-        while( i != 0 ) {
-            n = Math.min(i, 8 );
-            for ( long bits = nextLong(); n-- != 0; bits >>>= 8 ) bytes[ --i ] = (byte)bits;
-        }
-    }
-
-
-    /**
-     * Sets the seed of this generator (which is also the current state).
-     * @param seed the seed to use for this PermutedRNG, as if it was constructed with this seed.
-     */
-    public void setSeed( final long seed ) {
-        state = seed;
-    }
-    /**
-     * Sets the seed (also the current state) of this generator.
-     * @param seed the seed to use for this PermutedRNG, as if it was constructed with this seed.
-     */
-    @Override
-	public void setState( final long seed ) {
-        state = seed;
-    }
-    /**
-     * Gets the current state of this generator.
-     * @return the current seed of this PermutedRNG, changed once per call to nextLong()
-     */
-    @Override
-	public long getState( ) {
-        return state;
-    }
-
-    /**
-     * Advances or rolls back the PermutedRNG's state without actually generating numbers. Skip forward
-     * or backward a number of steps specified by advance, where a step is equal to one call to nextLong().
-     * @param advance Number of future generations to skip past. Can be negative to backtrack.
-     * @return the state after skipping.
-     */
-    public long skip(long advance)
-    {
-        // The method used here is based on Brown, "Random Number Generation
-        // with Arbitrary Stride,", Transactions of the American Nuclear
-        // Society (Nov. 1994).  The algorithm is very similar to fast
-        // exponentiation.
-        //
-        // Even though advance is a signed long, it is treated as unsigned, effectively, for the purposes
-        // of how many iterations it goes through (at most 63 for forwards, 64 for "backwards").
-        if(advance == 0)
-            return state;
-        long acc_mult = 1, acc_plus = 0, cur_mult = 6364136223846793005L, cur_plus = 1442695040888963407L;
-
-        do {
-            if ((advance & 1L) != 0L) {
-                acc_mult *= cur_mult;
-                acc_plus = acc_plus*cur_mult + cur_plus;
-            }
-            cur_plus = (cur_mult+1L)*cur_plus;
-            cur_mult *= cur_mult;
-            advance >>>= 1;
-        }while (advance > 0L);
-        return acc_mult * state + acc_plus;
-    }
-
-    @Override
-    public String toString() {
-        return "PermutedRNG with state 0x" + StringKit.hex(state) + 'L';
-    }
-
-}

+ 0 - 106
squidlib-util/src/main/java/squidpony/squidmath/ProbabilityTable.java

@@ -1,106 +0,0 @@
-package squidpony.squidmath;
-
-import squidpony.annotation.Beta;
-
-import java.io.Serializable;
-import java.util.SortedSet;
-
-/**
- * A generic method of holding a probability table to determine weighted random
- * outcomes.
- *
- * The weights do not need to add up to any particular value, they will be
- * normalized when choosing a random entry.
- *
- * @author Eben Howard - http://squidpony.com - howard@squidpony.com
- *
- * @param <T> The type of object to be held in the table
- */
-@Beta
-public class ProbabilityTable<T> implements Serializable {
-    private static final long serialVersionUID = -1307656083434154736L;
-    private final OrderedMap<T, Integer> table;
-    private RNG rng;
-    private int total;
-
-    /**
-     * Creates a new probability table.
-     */
-    public ProbabilityTable() {
-        this(new StatefulRNG());
-    }
-
-    /**
-     * Creates a new probability table with the provided source of randomness
-     * used.
-     *
-     * @param rng the source of randomness
-     */
-    public ProbabilityTable(RNG rng) {
-        this.rng = rng;
-        table = new OrderedMap<>();
-        total = 0;
-    }
-
-    /**
-     * Returns an object randomly based on assigned weights.
-     *
-     * Returns null if no elements have been put in the table.
-     *
-     * @return the chosen object or null
-     */
-    public T random() {
-        if (table.isEmpty()) {
-            return null;
-        }
-        int index = rng.nextInt(total);
-        for (T t : table.keySet()) {
-            index -= table.get(t);
-            if (index < 0) {
-                return t;
-            }
-        }
-        return null;//something went wrong, shouldn't have been able to get all the way through without finding an item
-    }
-
-    /**
-     * Adds the given item to the table.
-     *
-     * Weight must be greater than 0.
-     *
-     * @param item the object to be added
-     * @param weight the weight to be given to the added object
-     */
-    public void add(T item, int weight) {
-        Integer i = table.get(item);
-        if (i == null) {
-            i = weight;
-        } else {
-            i += weight;
-        }
-        table.put(item, i);
-        total += weight;
-    }
-
-    /**
-     * Returns the weight of the item if the item is in the table. Returns zero
-     * of the item is not in the table.
-     *
-     * @param item the item searched for
-     * @return the weight of the item, or zero
-     */
-    public int weight(T item) {
-        Integer i = table.get(item);
-        return i == null ? 0 : i;
-    }
-
-    /**
-     * Provides a set of the items in this table, without reference to their
-     * weight.
-     *
-     * @return a "sorted" set of all items stored, really sorted in insertion order
-     */
-    public SortedSet<T> items() {
-        return table.keySet();
-    }
-}

+ 0 - 354
squidlib-util/src/main/java/squidpony/squidmath/Region.java

@@ -1,354 +0,0 @@
-package squidpony.squidmath;
-
-import squidpony.squidgrid.mapping.DungeonUtility;
-
-import java.io.Serializable;
-import java.util.AbstractList;
-import java.util.Collection;
-
-import static squidpony.squidmath.CoordPacker.*;
-/**
- * Represents an area or series of areas as one logical unit, and allows iterating over or altering that unit.
- * This can be useful for getting an iterable data structure from a FOV map, Dijkstra map, or just a map from a dungeon
- * generator. It can also work with some shapes (circles and rectangles).
- * Regions must be no larger than 256x256 (actually, the Coords in them should fit in that), even if Coord has had its
- * expandPool() method called. This is because CoordPacker relies on that maximum size to significantly improve
- * efficiency, and this is really just a convenience class wrapping CoordPacker to avoid some of its complexity.
- * More features are likely to be ported into Region as they are added to CoordPacker.
- * Created by Tommy Ettinger on 5/12/2016.
- */
-public class Region extends AbstractList<Coord> implements Serializable{
-
-    private static final long serialVersionUID = 4015272367863327093L;
-
-    protected short[] raw;
-    protected Coord[] coords;
-    private boolean dirty;
-
-    /**
-     * A constructor for a Region that takes a 2D double array, usually the kind produced by FOV, and stores only Coord
-     * positions that correspond to values greater than 0.0 (actually, greater than epsilon, which here is 0.0001).
-     * This won't behave as-expected if you give it a double[][] that DijkstraMap produces; there's a different
-     * constructor for that purpose.
-     * @param fovMap a 2D double array as produced by FOV
-     */
-    public Region(double[][] fovMap)
-    {
-        this(pack(fovMap));
-    }
-
-    /**
-     * A constructor for a Region that takes a 2D double array, usually produced by DijkstraMap, and a maximum value,
-     * and stores only Coord positions that correspond to values no greater than maximum.
-     * This won't behave as-expected if you give it a double[][] that FOV produces; there's a different
-     * constructor for that purpose.
-     * @param dijkstraMap a 2D double array as produced by DijkstraMap
-     * @param maximum the highest value that a position can have in dijkstraMap and still be given a Coord in this
-     */
-    public Region(double[][] dijkstraMap, double maximum)
-    {
-        this(pack(dijkstraMap, maximum));
-    }
-
-    /**
-     * A constructor for a Region that takes a 2D char array, the kind produced by most map/dungeon generators in this
-     * library, and a vararg or array of char that will have their Coord positions used where those chars appear in map.
-     * This is optimized for the common case of a single char in using if you only want to, for example, store '.' to
-     * make a Region of floors, or '#' for walls.
-     * @param map a 2D char array that is usually the kind returned by a dungeon or map generator
-     * @param using an array or vararg of char that will have their Coords used where they appear in map
-     */
-    public Region(char[][] map, char... using)
-    {
-        this(pack(map, using));
-    }
-
-    /**
-     * A constructor for a Region that takes an array or vararg of Coord and encodes all of them in the Region.
-     * @param points an array or vararg of Coord that will be stored in this Region, none can be null
-     */
-    public Region(Coord... points)
-    {
-        this(packSeveral(points));
-    }
-    /**
-     * A constructor for a Region that takes a Collection of Coord, such as a List or Set, and encodes all of them in
-     * the Region.
-     * @param points a Collection of Coord that will be stored in this Region, none can be null
-     */
-    public Region(Collection<Coord> points)
-    {
-        this(packSeveral(points));
-    }
-
-    /**
-     * A constructor that copies another Region so this Region will have the same contents. If the other Region is
-     * "dirty", this won't perform "cleanup" on it, but will ensure that this Region is "clean" at creation.
-     * None of the reference types in other will be used directly in this Region, so changes made to this Region won't
-     * be reflected in other.
-     * @param other another Region to copy into this one
-     */
-    public Region(Region other)
-    {
-        raw = new short[other.raw.length];
-        System.arraycopy(other.raw, 0, raw, 0, raw.length);
-        if(other.dirty)
-        {
-            coords = allPacked(raw);
-        }
-        else
-        {
-            coords = new Coord[other.coords.length];
-            System.arraycopy(other.coords, 0, coords, 0, coords.length);
-        }
-        dirty = false;
-
-    }
-
-    /**
-     * A constructor for a circular Region (possibly truncated at the edges) with a Coord center, an int radius, and a
-     * maximum width and height that the Coords in this Region will not exceed.
-     * @param center the center of the circular Region
-     * @param circleRadius the radius as an int
-     * @param mapWidth one more than the maximum x-position of any Coord this will contain
-     * @param mapHeight one more than the maximum y-position of any Coord this will contain
-     */
-    public Region(Coord center, int circleRadius, int mapWidth, int mapHeight)
-    {
-        this(circle(center, circleRadius, mapWidth, mapHeight));
-    }
-
-    /**
-     * A constructor for a rectangular Region that stores Coords for the area from (minX,minY) at the minimum corner to
-     * (width + minX - 1, height + minY - 1) at the maximum corner. All parameters should be non-negative and less than
-     * 256, and height and width will be reduced if a Coord in the rectangle would extend to 256 in either dimension.
-     * This doesn't take two Coords as parameters because that would be confusing with the constructor that takes a
-     * vararg or array of Coord for its parameters.
-     * @param minX lowest x-coordinate in the rectangle; should be between 0 and 255
-     * @param minY lowest y-coordinate in the rectangle; should be between 0 and 255
-     * @param width total width of the rectangle; must be non-negative
-     * @param height total height of the rectangle; must be non-negative
-     */
-    public Region(int minX, int minY, int width, int height)
-    {
-        this(rectangle(minX, minY, width, height));
-    }
-    /**
-     * A constructor for a Region that takes a specifically-formatted short array (packed data), as produced by
-     * CoordPacker or sometimes other classes, like RegionMap or RoomFinder. If you don't have such data, the other
-     * constructors are recommended instead.
-     * <br>
-     * Note: arrays of Hilbert indices are occasionally returned in CoordPacker as a different kind of short array, but
-     * those methods are always noted as such and those short arrays won't make sense if passed to this constructor.
-     * They may result in a technically-valid Region with random-seeming contents. In general, if a method in
-     * CoordPacker returns a short array (most of them do), but the name contains Hilbert, it may return the wrong kind
-     * (an array of Hilbert indices is wrong, packed data is right); check the documentation for that method.
-     * @param packedData a short array as produced by CoordPacker (usually), or sometimes RoomFinder or RegionMap
-     */
-    public Region(short[] packedData)
-    {
-        raw = new short[packedData.length];
-        System.arraycopy(packedData, 0, raw, 0, packedData.length);
-        coords = allPacked(raw);
-        dirty = false;
-    }
-
-    /**
-     * Gets a single random Coord from this using the given RNG (which can be seeded); returns null if this is empty.
-     * @param rng the source of random numbers used to get a random Coord from this Region
-     * @return a random Coord in this Region, or null if this is empty
-     */
-    public Coord getRandomCoord(RNG rng)
-    {
-        if(CoordPacker.isEmpty(raw))
-            return null;
-        return singleRandom(raw, rng);
-    }
-
-    /**
-     * Takes this region and walks through its Coords in chunks with length equal to separation, creating a new Region
-     * where one Coord in each chunk is kept and the others are discarded.
-     * @param separation an int where higher numbers mean there will be more distance between Coords, and fewer total
-     * @return a new Region made of the separated Coords
-     */
-    public Region separated(int separation)
-    {
-        return new Region(fractionPacked(raw, separation));
-    }
-
-    /**
-     * Takes this region and walks through its Coords in chunks with length equal to separation, creating a new Region
-     * where one randomly-chosen Coord in each chunk is kept and the others are discarded.
-     * @param separation an int where higher numbers mean there will be more distance between Coords, and fewer total
-     * @param rng the source of random numbers used to randomize Coords used, removing any noticeable pattern
-     * @return a new Region made of the separated Coords
-     */
-    public Region randomSeparated(int separation, RNG rng)
-    {
-        return new Region(CoordPacker.randomSeparated(raw, separation, rng));
-    }
-
-    /**
-     * Gets a representation of this Region as a 2D boolean array with the given width and height. If this contains a
-     * Coord with x and y less than width and height, that position will be true in the 2D array this returns, otherwise
-     * it will be false.
-     * @param width the width of the 2D array to return
-     * @param height the height of the 2D array to return
-     * @return a 2D boolean array where present Coords in this Region will be true, and everything else will be false
-     */
-    public boolean[][] toBooleanArray(int width, int height)
-    {
-        return CoordPacker.unpack(raw, width, height);
-    }
-
-    /**
-     * Gets a representation of this Region as a 2D char array with the given width and height, using on to represent
-     * present Coords and off to represent absent ones. If this contains a Coord with x and y less than width and
-     * height, that position will be equal to on in the 2D array this returns, otherwise it will be equal to off.
-     * @param width the width of the 2D array to return
-     * @param height the height of the 2D array to return
-     * @param on the char to use when a Coord is present in this Region
-     * @param off the char to use where no Coord is present in this Region
-     * @return a 2D char array where present Coords in this Region will be on, and everything else will be off
-     */
-    public char[][] toCharArray(int width, int height, char on, char off)
-    {
-        return CoordPacker.unpackChar(raw, width, height, on, off);
-    }
-
-    /**
-     * Gets the Coord stored at the given index in this Region, or null if index is out of bounds.
-     * The ordering this class uses may seem unusual, but it is predictable, using the pattern a Hilbert Curve takes to
-     * wind through a 256x256 space (at its maximum). Any two given Coords will always have the same before-after
-     * relationship, regardless of other Coords in the Region. A Region is a dense data structure, like a List or array,
-     * so valid indices shouldn't ever return null.
-     * @param index the index into this Region to get a Coord at; should be less than size() and non-negative.
-     * @return the Coord this Region holds at index, if index is valid; otherwise null
-     */
-    @Override
-    public Coord get(int index) {
-        if(dirty)
-        {
-            coords = allPacked(raw);
-            dirty = false;
-        }
-        if(index >= 0 && index < coords.length)
-            return coords[index];
-        return null;
-    }
-
-    /**
-     * Gets the size of this Region as measured in Coords stored.
-     * Performs "cleanup" if the Region is "dirty," even though this doesn't specifically request a Coord. As such, it
-     * may take longer than a call to size() might be expected to, but only just after a "dirtying" method was called.
-     * @return the number of Coords stored in this Region.
-     */
-    @Override
-    public int size() {
-        if(dirty)
-        {
-            coords = allPacked(raw);
-            dirty = false;
-        }
-        return coords.length;
-    }
-
-    /**
-     * Returns true if there are no Coords in this Region, or false otherwise. Can be more efficient than checking if
-     * size() is greater than 0 because it doesn't depend on the "dirty or clean" state, and can quickly check.
-     * @return
-     */
-    @Override
-    public boolean isEmpty() {
-        return CoordPacker.isEmpty(raw);
-    }
-
-    /**
-     * Adds a Coord to this Region, returning false if the Coord is null or already included in this, or true otherwise.
-     * Causes the Region to be considered "dirty", which will make anything that gets a Coord from this to perform some
-     * "cleanup" on the Coords this holds when a Coord is requested. You can perform multiple "dirtying" operations in
-     * succession without needing more "cleanups" than the one when a Coord is next requested.
-     * @param coord a Coord to add to this region
-     * @return true if the Coord was added and was not already present; false if the Coord as null or already present
-     */
-    @Override
-    public boolean add(Coord coord) {
-        if(coord == null || queryPacked(raw, coord.x, coord.y))
-            return false;
-        raw = insertPacked(raw, coord.x, coord.y);
-        dirty = true;
-        return true;
-    }
-
-    /**
-     * Gets a direct reference to this Region's "raw packed data"; don't modify it unless you know what you're doing!
-     * It's fine to pass this to methods in CoordPacker, since essentially all of those methods won't modify packed data
-     * given as arguments.
-     * @return the raw packed data this class uses; should not be modified carelessly
-     */
-    public short[] getRaw() {
-        return raw;
-    }
-
-    /**
-     * Sets the "raw packed data" to the given short array, as generated by CoordPacker or some parts of RegionMap.
-     * This hopefully won't need to be consumed too much externally, but is an important bridge between this and
-     * CoordPacker's API, which deals mostly with these special short arrays.
-     * Causes the Region to be considered "dirty", which will make anything that gets a Coord from this to perform some
-     * "cleanup" on the Coords this holds when a Coord is requested. You can perform multiple "dirtying" operations in
-     * succession without needing more "cleanups" than the one when a Coord is next requested.
-     * @param raw a short array of packed data; has a very specific format and should usually not be made manually
-     */
-    public void setRaw(short[] raw) {
-        this.raw = raw;
-        dirty = true;
-    }
-
-    /**
-     * Gets the Coords contained in this as an array, a direct reference that does permit modifying the Coords in your
-     * own code without altering "dirty/clean" status. This method does "cleanup" in itself if necessary, but once the
-     * Coords are returned you can change them at-will. The Coords may not reflect changes made by this object if it
-     * creates a new Coord array, as it often does.
-     * @return the Coords contained in this Region as an array
-     */
-    public Coord[] getCoords() {
-        if(dirty)
-        {
-            coords = allPacked(raw);
-            dirty = false;
-        }
-        return coords;
-    }
-
-    /**
-     * Changes this Region to include the given Coords and disregard its previous contents. If any elements of coords
-     * are null, this Region will hold no Coords (a sort of escape hatch to avoid throwing an exception, since all other
-     * methods in this class fail on null entries without potentially crashing a program).
-     * @param coords an array or vararg of Coord that will be used as the entirety of this Region
-     */
-    public void setCoords(Coord... coords) {
-        if (coords == null)
-            return;
-        raw = packSeveral(coords);
-        if (raw == ALL_WALL) {
-            this.coords = new Coord[0];
-            dirty = false;
-        } else {
-            this.coords = new Coord[coords.length];
-            System.arraycopy(coords, 0, this.coords, 0, coords.length);
-            dirty = false;
-        }
-    }
-
-    /**
-     * Prints this Region to System.out as a grid of chars with the given width and height, using '.' for Coords this
-     * contains and '#' for empty space. Consider using toCharArray() instead if you need more customization for what
-     * you want printed.
-     * @param width the width in chars of the grid to print
-     * @param height the height in chars of the grid to print
-     */
-    public void debugPrint(int width, int height)
-    {
-        DungeonUtility.debugPrint(toCharArray(width, height, '.', '#'));
-    }
-}

+ 0 - 883
squidlib-util/src/main/java/squidpony/squidmath/RegionMap.java

@@ -1,883 +0,0 @@
-/*******************************************************************************
- * Copyright 2011 See AUTHORS file.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- ******************************************************************************/
-
-package squidpony.squidmath;
-
-import java.io.Serializable;
-import java.util.*;
-
-/** An unordered map of regions (specifically, packed data from CoordPacker or something that uses it, like FOVCache or
- * ZOI, as short arrays) to values of a generic type. Regions can overlap, and you can technically store the same set of
- * points as two or more different keys by appending 0 multiple times, which doesn't change the cells encoded in a short
- * array of packed data but does cause it to be hashed differently and thus not over-write the previous region in this
- * RegionMap. Overlapping areas can be useful, since this provides a way to find all values associated with regions
- * containing a given point using the method allAt(), in a way that is similar to a multimap data structure.
- * <br>
- * Normal Java Maps aren't meant to use primitive arrays as keys, in part because they are mutable and in part because
- * the equals() method on an array isn't exactly correct for this purpose. Here, we have the collection specialized for
- * short[] keys (which still should not be mutated!), use Arrays.equals() for comparing equality, and use
- * CrossHash.hash() for hashing short arrays efficiently.
- * <br>
- * Ported from LibGDX (original class was ObjectMap) by Tommy Ettinger on 1/25/2016.
- * @author Nathan Sweet
- * @author Tommy Ettinger
- */
-public class RegionMap<V> implements Iterable<RegionMap.Entry<V>>, Serializable {
-    private static final long serialVersionUID = -6026166931953522091L;
-    private static final int PRIME1 = 0xbe1f14b1;
-    private static final int PRIME2 = 0xb4b82e39;
-    private static final int PRIME3 = 0xced1c241;
-    private LightRNG lrng = new LightRNG(0xbadfad);
-    public int size;
-
-    short[][] keyTable;
-    V[] valueTable;
-    int capacity, stashSize;
-
-    private float loadFactor;
-    private int hashShift, mask, threshold;
-    private int stashCapacity;
-    private int pushIterations;
-
-    private Entries<V> entries1, entries2;
-    private Values<V> values1, values2;
-    private Keys keys1, keys2;
-
-    /** Creates a new map with an initial capacity of 51 and a load factor of 0.8. */
-    public RegionMap () {
-        this(51, 0.8f);
-    }
-
-    /** Creates a new map with a load factor of 0.8.
-     * @param initialCapacity If not a power of two, it is increased to the next nearest power of two. */
-    public RegionMap (int initialCapacity) {
-        this(initialCapacity, 0.8f);
-    }
-
-    /** Creates a new map with the specified initial capacity and load factor. This map will hold initialCapacity items before
-     * growing the backing table.
-     * @param initialCapacity If not a power of two, it is increased to the next nearest power of two. */
-    @SuppressWarnings("unchecked")
-    public RegionMap (int initialCapacity, float loadFactor) {
-        if (initialCapacity < 0) throw new IllegalArgumentException("initialCapacity must be >= 0: " + initialCapacity);
-        initialCapacity = nextPowerOfTwo((int)Math.ceil(initialCapacity / loadFactor));
-        if (initialCapacity > 1 << 30) throw new IllegalArgumentException("initialCapacity is too large: " + initialCapacity);
-        capacity = initialCapacity;
-
-        if (loadFactor <= 0) throw new IllegalArgumentException("loadFactor must be > 0: " + loadFactor);
-        this.loadFactor = loadFactor;
-
-        threshold = (int)(capacity * loadFactor);
-        mask = capacity - 1;
-        hashShift = 31 - Integer.numberOfTrailingZeros(capacity);
-        stashCapacity = Math.max(3, (int)Math.ceil(Math.log(capacity)) * 2);
-        pushIterations = Math.max(Math.min(capacity, 8), (int)Math.sqrt(capacity) / 8);
-
-        keyTable = new short[capacity + stashCapacity][];
-        valueTable = (V[])new Object[keyTable.length];
-    }
-
-    /** Creates a new map identical to the specified map. */
-    public RegionMap (RegionMap<? extends V> map) {
-        this(map.capacity, map.loadFactor);
-        stashSize = map.stashSize;
-        System.arraycopy(map.keyTable, 0, keyTable, 0, map.keyTable.length);
-        System.arraycopy(map.valueTable, 0, valueTable, 0, map.valueTable.length);
-        size = map.size;
-    }
-
-    /** Returns the old value associated with the specified key, or null. */
-    public V put (short[] key, V value) {
-        if (key == null) throw new IllegalArgumentException("key cannot be null.");
-        return put_internal(key, value);
-    }
-
-    private V put_internal (short[] key, V value) {
-        short[][] keyTable = this.keyTable;
-
-        // Check for existing keys.
-        int hashCode = CrossHash.hash(key);
-        int index1 = hashCode & mask;
-        short[] key1 = keyTable[index1];
-        if (Arrays.equals(key, key1)) {
-            V oldValue = valueTable[index1];
-            valueTable[index1] = value;
-            return oldValue;
-        }
-
-        int index2 = hash2(hashCode);
-        short[] key2 = keyTable[index2];
-        if (Arrays.equals(key, key2)) {
-            V oldValue = valueTable[index2];
-            valueTable[index2] = value;
-            return oldValue;
-        }
-
-        int index3 = hash3(hashCode);
-        short[] key3 = keyTable[index3];
-        if (Arrays.equals(key, key3)) {
-            V oldValue = valueTable[index3];
-            valueTable[index3] = value;
-            return oldValue;
-        }
-
-        // Update key in the stash.
-        for (int i = capacity, n = i + stashSize; i < n; i++) {
-            if (Arrays.equals(key, keyTable[i])) {
-                V oldValue = valueTable[i];
-                valueTable[i] = value;
-                return oldValue;
-            }
-        }
-
-        // Check for empty buckets.
-        if (key1 == null) {
-            keyTable[index1] = key;
-            valueTable[index1] = value;
-            if (size++ >= threshold) resize(capacity << 1);
-            return null;
-        }
-
-        if (key2 == null) {
-            keyTable[index2] = key;
-            valueTable[index2] = value;
-            if (size++ >= threshold) resize(capacity << 1);
-            return null;
-        }
-
-        if (key3 == null) {
-            keyTable[index3] = key;
-            valueTable[index3] = value;
-            if (size++ >= threshold) resize(capacity << 1);
-            return null;
-        }
-
-        push(key, value, index1, key1, index2, key2, index3, key3);
-        return null;
-    }
-
-    public void putAll (RegionMap<V> map) {
-        ensureCapacity(map.size);
-        for (Entry<V> entry : map)
-            put(entry.key, entry.value);
-    }
-
-    /** Skips checks for existing keys. */
-    private void putResize (short[] key, V value) {
-        // Check for empty buckets.
-        int hashCode = CrossHash.hash(key);
-        int index1 = hashCode & mask;
-        short[] key1 = keyTable[index1];
-        if (key1 == null) {
-            keyTable[index1] = key;
-            valueTable[index1] = value;
-            if (size++ >= threshold) resize(capacity << 1);
-            return;
-        }
-
-        int index2 = hash2(hashCode);
-        short[] key2 = keyTable[index2];
-        if (key2 == null) {
-            keyTable[index2] = key;
-            valueTable[index2] = value;
-            if (size++ >= threshold) resize(capacity << 1);
-            return;
-        }
-
-        int index3 = hash3(hashCode);
-        short[] key3 = keyTable[index3];
-        if (key3 == null) {
-            keyTable[index3] = key;
-            valueTable[index3] = value;
-            if (size++ >= threshold) resize(capacity << 1);
-            return;
-        }
-
-        push(key, value, index1, key1, index2, key2, index3, key3);
-    }
-
-    private void push (short[] insertKey, V insertValue, int index1, short[] key1, int index2, short[] key2, int index3, short[] key3) {
-        short[][] keyTable = this.keyTable;
-        V[] valueTable = this.valueTable;
-        int mask = this.mask;
-
-        // Push keys until an empty bucket is found.
-        short[] evictedKey;
-        V evictedValue;
-        int i = 0, pushIterations = this.pushIterations;
-        do {
-            // Replace the key and value for one of the hashes.
-            switch (lrng.nextInt(2)) {
-                case 0:
-                    evictedKey = key1;
-                    evictedValue = valueTable[index1];
-                    keyTable[index1] = insertKey;
-                    valueTable[index1] = insertValue;
-                    break;
-                case 1:
-                    evictedKey = key2;
-                    evictedValue = valueTable[index2];
-                    keyTable[index2] = insertKey;
-                    valueTable[index2] = insertValue;
-                    break;
-                default:
-                    evictedKey = key3;
-                    evictedValue = valueTable[index3];
-                    keyTable[index3] = insertKey;
-                    valueTable[index3] = insertValue;
-                    break;
-            }
-
-            // If the evicted key hashes to an empty bucket, put it there and stop.
-            int hashCode = CrossHash.hash(evictedKey);
-            index1 = hashCode & mask;
-            key1 = keyTable[index1];
-            if (key1 == null) {
-                keyTable[index1] = evictedKey;
-                valueTable[index1] = evictedValue;
-                if (size++ >= threshold) resize(capacity << 1);
-                return;
-            }
-
-            index2 = hash2(hashCode);
-            key2 = keyTable[index2];
-            if (key2 == null) {
-                keyTable[index2] = evictedKey;
-                valueTable[index2] = evictedValue;
-                if (size++ >= threshold) resize(capacity << 1);
-                return;
-            }
-
-            index3 = hash3(hashCode);
-            key3 = keyTable[index3];
-            if (key3 == null) {
-                keyTable[index3] = evictedKey;
-                valueTable[index3] = evictedValue;
-                if (size++ >= threshold) resize(capacity << 1);
-                return;
-            }
-
-            if (++i == pushIterations) break;
-
-            insertKey = evictedKey;
-            insertValue = evictedValue;
-        } while (true);
-
-        putStash(evictedKey, evictedValue);
-    }
-
-    private void putStash (short[] key, V value) {
-        if (stashSize == stashCapacity) {
-            // Too many pushes occurred and the stash is full, increase the table size.
-            resize(capacity << 1);
-            put_internal(key, value);
-            return;
-        }
-        // Store key in the stash.
-        int index = capacity + stashSize;
-        keyTable[index] = key;
-        valueTable[index] = value;
-        stashSize++;
-        size++;
-    }
-
-    public V get (short[] key) {
-        int hashCode = CrossHash.hash(key);
-        int index = hashCode & mask;
-        if (!Arrays.equals(key, keyTable[index])) {
-            index = hash2(hashCode);
-            if (!Arrays.equals(key, keyTable[index])) {
-                index = hash3(hashCode);
-                if (!Arrays.equals(key, keyTable[index])) return getStash(key);
-            }
-        }
-        return valueTable[index];
-    }
-
-    private V getStash (short[] key) {
-        short[][] keyTable = this.keyTable;
-        for (int i = capacity, n = i + stashSize; i < n; i++)
-            if (Arrays.equals(key, keyTable[i])) return valueTable[i];
-        return null;
-    }
-
-    /** Returns the value for the specified key, or the default value if the key is not in the map. */
-    public V get (short[] key, V defaultValue) {
-        int hashCode = CrossHash.hash(key);
-        int index = hashCode & mask;
-        if (!Arrays.equals(key, keyTable[index])) {
-            index = hash2(hashCode);
-            if (!Arrays.equals(key, keyTable[index])) {
-                index = hash3(hashCode);
-                if (!Arrays.equals(key, keyTable[index])) return getStash(key, defaultValue);
-            }
-        }
-        return valueTable[index];
-    }
-
-    private V getStash (short[] key, V defaultValue) {
-        short[][] keyTable = this.keyTable;
-        for (int i = capacity, n = i + stashSize; i < n; i++)
-            if (Arrays.equals(key, keyTable[i])) return valueTable[i];
-        return defaultValue;
-    }
-
-    /**
-     * Gets a List of all values associated with regions containing a given x,y point.
-     * @param x the x coordinate of the point in question
-     * @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 OrderedSet<V> allAt(int x, int y)
-    {
-        OrderedSet<V> found = new OrderedSet<>(capacity);
-        OrderedSet<short[]> regions = CoordPacker.findManyPacked(x, y, keyTable);
-        for(short[] region : regions)
-        {
-            found.add(get(region));
-        }
-        return found;
-    }
-
-    /**
-     * Checks if a region, stored as packed data (possibly from CoordPacker or this class) overlaps with regions stored
-     * in this object as keys. Returns true if there is any overlap, false otherwise
-     * @param region the packed region to check for overlap with regions this stores values for
-     * @return true if the region overlaps at all, false otherwise
-     */
-    public boolean containsRegion(short[] region)
-    {
-        return CoordPacker.regionsContain(region, keyTable);
-    }
-    /**
-     * Gets a List of all regions containing a given x,y point.
-     * @param x the x coordinate of the point in question
-     * @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 OrderedSet<short[]> regionsContaining(int x, int y)
-    {
-        return CoordPacker.findManyPacked(x, y, keyTable);
-    }
-
-    public V remove (short[] key) {
-        int hashCode = CrossHash.hash(key);
-        int index = hashCode & mask;
-        if (Arrays.equals(key, keyTable[index])) {
-            keyTable[index] = null;
-            V oldValue = valueTable[index];
-            valueTable[index] = null;
-            size--;
-            return oldValue;
-        }
-
-        index = hash2(hashCode);
-        if (Arrays.equals(key, keyTable[index])) {
-            keyTable[index] = null;
-            V oldValue = valueTable[index];
-            valueTable[index] = null;
-            size--;
-            return oldValue;
-        }
-
-        index = hash3(hashCode);
-        if (Arrays.equals(key, keyTable[index])) {
-            keyTable[index] = null;
-            V oldValue = valueTable[index];
-            valueTable[index] = null;
-            size--;
-            return oldValue;
-        }
-
-        return removeStash(key);
-    }
-
-    V removeStash (short[] key) {
-        short[][] keyTable = this.keyTable;
-        for (int i = capacity, n = i + stashSize; i < n; i++) {
-            if (Arrays.equals(key, keyTable[i])) {
-                V oldValue = valueTable[i];
-                removeStashIndex(i);
-                size--;
-                return oldValue;
-            }
-        }
-        return null;
-    }
-
-    void removeStashIndex (int index) {
-        // If the removed location was not last, move the last tuple to the removed location.
-        stashSize--;
-        int lastIndex = capacity + stashSize;
-        if (index < lastIndex) {
-            keyTable[index] = keyTable[lastIndex];
-            valueTable[index] = valueTable[lastIndex];
-            valueTable[lastIndex] = null;
-        } else
-            valueTable[index] = null;
-    }
-
-    /** Reduces the size of the backing arrays to be the specified capacity or less. If the capacity is already less, nothing is
-     * done. If the map contains more items than the specified capacity, the next highest power of two capacity is used instead. */
-    public void shrink (int maximumCapacity) {
-        if (maximumCapacity < 0) throw new IllegalArgumentException("maximumCapacity must be >= 0: " + maximumCapacity);
-        if (size > maximumCapacity) maximumCapacity = size;
-        if (capacity <= maximumCapacity) return;
-        maximumCapacity = nextPowerOfTwo(maximumCapacity);
-        resize(maximumCapacity);
-    }
-
-    /** Clears the map and reduces the size of the backing arrays to be the specified capacity if they are larger. */
-    public void clear (int maximumCapacity) {
-        if (capacity <= maximumCapacity) {
-            clear();
-            return;
-        }
-        size = 0;
-        resize(maximumCapacity);
-    }
-
-    public void clear () {
-        if (size == 0) return;
-        short[][] keyTable = this.keyTable;
-        V[] valueTable = this.valueTable;
-        for (int i = capacity + stashSize; i-- > 0;) {
-            keyTable[i] = null;
-            valueTable[i] = null;
-        }
-        size = 0;
-        stashSize = 0;
-    }
-
-    /** Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may
-     * be an expensive operation.
-     * @param identity If true, uses == to compare the specified value with values in the map. If false, uses
-     *           {@link #equals(Object)}. */
-    public boolean containsValue (Object value, boolean identity) {
-        V[] valueTable = this.valueTable;
-        if (value == null) {
-            short[][] keyTable = this.keyTable;
-            for (int i = capacity + stashSize; i-- > 0;)
-                if (keyTable[i] != null && valueTable[i] == null) return true;
-        } else if (identity) {
-            for (int i = capacity + stashSize; i-- > 0;)
-                if (valueTable[i] == value) return true;
-        } else {
-            for (int i = capacity + stashSize; i-- > 0;)
-                if (value.equals(valueTable[i])) return true;
-        }
-        return false;
-    }
-
-    public boolean containsKey (short[] key) {
-        int hashCode = CrossHash.hash(key);
-        int index = hashCode & mask;
-        if (!Arrays.equals(key, keyTable[index])) {
-            index = hash2(hashCode);
-            if (!Arrays.equals(key, keyTable[index])) {
-                index = hash3(hashCode);
-                if (!Arrays.equals(key, keyTable[index])) return containsKeyStash(key);
-            }
-        }
-        return true;
-    }
-
-    private boolean containsKeyStash (short[] key) {
-        short[][] keyTable = this.keyTable;
-        for (int i = capacity, n = i + stashSize; i < n; i++)
-            if (Arrays.equals(key, keyTable[i])) return true;
-        return false;
-    }
-
-    /** Returns the key for the specified value, or null if it is not in the map. Note this traverses the entire map and compares
-     * every value, which may be an expensive operation.
-     * @param identity If true, uses == to compare the specified value with values in the map. If false, uses
-     *           {@link #equals(Object)}. */
-    public short[] findKey (Object value, boolean identity) {
-        V[] valueTable = this.valueTable;
-        if (value == null) {
-            short[][] keyTable = this.keyTable;
-            for (int i = capacity + stashSize; i-- > 0;)
-                if (keyTable[i] != null && valueTable[i] == null) return keyTable[i];
-        } else if (identity) {
-            for (int i = capacity + stashSize; i-- > 0;)
-                if (valueTable[i] == value) return keyTable[i];
-        } else {
-            for (int i = capacity + stashSize; i-- > 0;)
-                if (value.equals(valueTable[i])) return keyTable[i];
-        }
-        return null;
-    }
-
-    /** Increases the size of the backing array to accommodate the specified number of additional items. Useful before adding many
-     * items to avoid multiple backing array resizes. */
-    public void ensureCapacity (int additionalCapacity) {
-        int sizeNeeded = size + additionalCapacity;
-        if (sizeNeeded >= threshold) resize(nextPowerOfTwo((int)Math.ceil(sizeNeeded / loadFactor)));
-    }
-
-    @SuppressWarnings("unchecked")
-    private void resize (int newSize) {
-        int oldEndIndex = capacity + stashSize;
-
-        capacity = newSize;
-        threshold = (int)(newSize * loadFactor);
-        mask = newSize - 1;
-        hashShift = 31 - Integer.numberOfTrailingZeros(newSize);
-        stashCapacity = Math.max(3, (int)Math.ceil(Math.log(newSize)) * 2);
-        pushIterations = Math.max(Math.min(newSize, 8), (int)Math.sqrt(newSize) / 8);
-
-        short[][] oldKeyTable = keyTable;
-        V[] oldValueTable = valueTable;
-
-        keyTable = new short[newSize + stashCapacity][];
-        valueTable = (V[])new Object[newSize + stashCapacity];
-
-        int oldSize = size;
-        size = 0;
-        stashSize = 0;
-        if (oldSize > 0) {
-            for (int i = 0; i < oldEndIndex; i++) {
-                short[] key = oldKeyTable[i];
-                if (key != null) putResize(key, oldValueTable[i]);
-            }
-        }
-    }
-
-    private int hash2 (int h) {
-        h *= PRIME2;
-        return (h ^ h >>> hashShift) & mask;
-    }
-
-    private int hash3 (int h) {
-        h *= PRIME3;
-        return (h ^ h >>> hashShift) & mask;
-    }
-
-    public int hashCode () {
-        int h = 0;
-        short[][] keyTable = this.keyTable;
-        V[] valueTable = this.valueTable;
-        for (int i = 0, n = capacity + stashSize; i < n; i++) {
-            short[] key = keyTable[i];
-            if (key != null) {
-                h += CrossHash.hash(key) * 31;
-
-                V value = valueTable[i];
-                if (value != null) {
-                    h += value.hashCode();
-                }
-            }
-        }
-        return h;
-    }
-
-    @SuppressWarnings("unchecked")
-    public boolean equals (Object obj) {
-        if (obj == this) return true;
-        if (!(obj instanceof RegionMap)) return false;
-        RegionMap<V> other = (RegionMap<V>)obj;
-        if (other.size != size) return false;
-        short[][] keyTable = this.keyTable;
-        V[] valueTable = this.valueTable;
-        for (int i = 0, n = capacity + stashSize; i < n; i++) {
-            short[] key = keyTable[i];
-            if (key != null) {
-                V value = valueTable[i];
-                if (value == null) {
-                    if (!other.containsKey(key) || other.get(key) != null) {
-                        return false;
-                    }
-                } else {
-                    if (!value.equals(other.get(key))) {
-                        return false;
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-    public String toString (String separator) {
-        return toString(separator, false);
-    }
-
-    @Override
-	public String toString () {
-        return toString(", ", true);
-    }
-
-    private String toString (String separator, boolean braces) {
-        if (size == 0) return braces ? "{}" : "";
-        StringBuilder buffer = new StringBuilder(32);
-        if (braces) buffer.append('{');
-        short[][] keyTable = this.keyTable;
-        V[] valueTable = this.valueTable;
-        int i = keyTable.length;
-        while (i-- > 0) {
-            short[] key = keyTable[i];
-            if (key == null) continue;
-            buffer.append("Packed Region:");
-            buffer.append(CoordPacker.encodeASCII(key));
-            buffer.append('=');
-            buffer.append(valueTable[i]);
-            break;
-        }
-        while (i-- > 0) {
-            short[] key = keyTable[i];
-            if (key == null) continue;
-            buffer.append(separator);
-            buffer.append("Packed Region:");
-            buffer.append(CoordPacker.encodeASCII(key));
-            buffer.append('=');
-            buffer.append(valueTable[i]);
-        }
-        if (braces) buffer.append('}');
-        return buffer.toString();
-    }
-    private static int nextPowerOfTwo(int n)
-    {
-        int highest = Integer.highestOneBit(n);
-        return  (highest == Integer.lowestOneBit(n)) ? highest : highest << 1;
-    }
-    @Override
-	public Entries<V> iterator () {
-        return entries();
-    }
-
-    /** Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is returned each
-     * time this method is called. Use the {@link Entries} constructor for nested or multithreaded iteration. */
-    public Entries<V> entries () {
-        if (entries1 == null) {
-            entries1 = new Entries<>(this);
-            entries2 = new Entries<>(this);
-        }
-        if (!entries1.valid) {
-            entries1.reset();
-            entries1.valid = true;
-            entries2.valid = false;
-            return entries1;
-        }
-        entries2.reset();
-        entries2.valid = true;
-        entries1.valid = false;
-        return entries2;
-    }
-
-    /** Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is returned each
-     * time this method is called. Use the {@link Values} constructor for nested or multithreaded iteration. */
-    public Values<V> values () {
-        if (values1 == null) {
-            values1 = new Values<>(this);
-            values2 = new Values<>(this);
-        }
-        if (!values1.valid) {
-            values1.reset();
-            values1.valid = true;
-            values2.valid = false;
-            return values1;
-        }
-        values2.reset();
-        values2.valid = true;
-        values1.valid = false;
-        return values2;
-    }
-
-    /** Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is returned each
-     * time this method is called. Use the {@link Keys} constructor for nested or multithreaded iteration. */
-    public Keys keys () {
-        if (keys1 == null) {
-            keys1 = new Keys(this);
-            keys2 = new Keys(this);
-        }
-        if (!keys1.valid) {
-            keys1.reset();
-            keys1.valid = true;
-            keys2.valid = false;
-            return keys1;
-        }
-        keys2.reset();
-        keys2.valid = true;
-        keys1.valid = false;
-        return keys2;
-    }
-
-    public static class Entry<V> {
-        public short[] key;
-        public V value;
-
-        @Override
-		public String toString () {
-            return "Packed Region:" + CoordPacker.encodeASCII(key) + "=" + value;
-        }
-    }
-
-    private abstract static class MapIterator<V, I> implements Iterable<I>, Iterator<I> {
-        public boolean hasNext;
-
-        final RegionMap<V> map;
-        int nextIndex, currentIndex;
-        boolean valid = true;
-
-        public MapIterator (RegionMap<V> map) {
-            this.map = map;
-            reset();
-        }
-
-        public void reset () {
-            currentIndex = -1;
-            nextIndex = -1;
-            findNextIndex();
-        }
-
-        void findNextIndex () {
-            hasNext = false;
-            short[][] keyTable = map.keyTable;
-            for (int n = map.capacity + map.stashSize; ++nextIndex < n;) {
-                if (keyTable[nextIndex] != null) {
-                    hasNext = true;
-                    break;
-                }
-            }
-        }
-
-        @Override
-		public void remove () {
-            if (currentIndex < 0) throw new IllegalStateException("next must be called before remove.");
-            if (currentIndex >= map.capacity) {
-                map.removeStashIndex(currentIndex);
-                nextIndex = currentIndex - 1;
-                findNextIndex();
-            } else {
-                map.keyTable[currentIndex] = null;
-                map.valueTable[currentIndex] = null;
-            }
-            currentIndex = -1;
-            map.size--;
-        }
-    }
-
-    public static class Entries<V> extends MapIterator<V, Entry<V>> {
-        Entry<V> entry = new Entry<>();
-
-        public Entries (RegionMap<V> map) {
-            super(map);
-        }
-
-        /** Note the same entry instance is returned each time this method is called. */
-        @Override
-		public Entry<V> next () {
-            if (!hasNext) throw new NoSuchElementException();
-            if (!valid) throw new RuntimeException("#iterator() cannot be used nested.");
-            short[][] keyTable = map.keyTable;
-            entry.key = keyTable[nextIndex];
-            entry.value = map.valueTable[nextIndex];
-            currentIndex = nextIndex;
-            findNextIndex();
-            return entry;
-        }
-
-        @Override
-		public boolean hasNext () {
-            if (!valid) throw new RuntimeException("#iterator() cannot be used nested.");
-            return hasNext;
-        }
-
-        @Override
-		public Entries<V> iterator () {
-            return this;
-        }
-    }
-
-    public static class Values<V> extends MapIterator<V, V> {
-        public Values (RegionMap<V> map) {
-            super(map);
-        }
-
-        @Override
-		public boolean hasNext () {
-            if (!valid) throw new RuntimeException("#iterator() cannot be used nested.");
-            return hasNext;
-        }
-
-        @Override
-		public V next () {
-            if (!hasNext) throw new NoSuchElementException();
-            if (!valid) throw new RuntimeException("#iterator() cannot be used nested.");
-            V value = map.valueTable[nextIndex];
-            currentIndex = nextIndex;
-            findNextIndex();
-            return value;
-        }
-
-        @Override
-		public Values<V> iterator () {
-            return this;
-        }
-
-        /** Returns a new list containing the remaining values. */
-        public List<V> toList () {
-            return toList(new ArrayList<V>(map.size));
-        }
-
-        /** Adds the remaining values to the specified list. */
-        public List<V> toList (List<V> list) {
-            while (hasNext)
-                list.add(next());
-            return list;
-        }
-    }
-
-    public static class Keys extends MapIterator<Object, short[]> {
-        @SuppressWarnings("unchecked")
-        public Keys (RegionMap<?> map) {
-            super((RegionMap<Object>) map);
-        }
-
-        @Override
-		public boolean hasNext () {
-            if (!valid) throw new RuntimeException("#iterator() cannot be used nested.");
-            return hasNext;
-        }
-
-        @Override
-		public short[] next () {
-            if (!hasNext) throw new NoSuchElementException();
-            if (!valid) throw new RuntimeException("#iterator() cannot be used nested.");
-            short[] key = map.keyTable[nextIndex];
-            currentIndex = nextIndex;
-            findNextIndex();
-            return key;
-        }
-
-        @Override
-		public Keys iterator () {
-            return this;
-        }
-
-        /** Returns a new list containing the remaining keys. */
-        public List<short[]> toList() {
-            return toList(new ArrayList<short[]>(map.size));
-        }
-
-        /** Adds the remaining keys to the array. */
-        public List<short[]> toList(List<short[]> list) {
-            while (hasNext)
-                list.add(next());
-            return list;
-        }
-    }
-}

+ 0 - 165
squidlib-util/src/main/java/squidpony/squidmath/WobblyLine.java

@@ -1,165 +0,0 @@
-package squidpony.squidmath;
-
-import squidpony.squidgrid.Direction;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A drunkard's-walk-like algorithm for line drawing "wobbly" paths.
- * The line() methods here use an RNG (and will make their own if they don't take one as a parameter) to make a choice
- * between orthogonal directions to travel in. Because they can go around the target instead of straight to it, they
- * also need a width and height for the map so they don't wander over the edge. You can also pass a weight to one of the
- * line() methods, which affects how straight the wobbly path will be (1.0 being just about perfectly straight, 0.5
- * being very chaotic, and less than 0.5 being almost unrecognizable as a path).
- * <br>
- * Based on Michael Patraw's C code, used for cave carving in his map generator. http://mpatraw.github.io/libdrunkard/
- * Created by Tommy Ettinger on 1/10/2016.
- */
-public class WobblyLine {
-    private WobblyLine(){}
-    /**
-     * Draws a line from (startX, startY) to (endX, endY) using the Drunkard's Walk algorithm. Returns a List of Coord
-     * in order.
-     * <br>
-     * Equivalent to calling {@code line(startX, startY, endX, endY, width, height, 0.75, new RNG())} .
-     * @param startX x of starting point
-     * @param startY y of starting point
-     * @param endX   x of ending point
-     * @param endY   y of ending point
-     * @param width maximum map width
-     * @param height maximum map height
-     * @return List of Coord, including (startX, startY) and (endX, endY) and all points walked between
-     */
-    public static List<Coord> line(int startX, int startY, int endX, int endY, int width, int height) {
-        return line(startX, startY, endX, endY, width, height, 0.75, new RNG());
-    }
-    /**
-     * Draws a line from (startX, startY) to (endX, endY) using the Drunkard's Walk algorithm. Returns a List of Coord
-     * in order.
-     * @param startX x of starting point
-     * @param startY y of starting point
-     * @param endX   x of ending point
-     * @param endY   y of ending point
-     * @param width maximum map width
-     * @param height maximum map height
-     * @param weight between 0.5 and 1.0, usually. 0.6 makes very random walks, 0.9 is almost a straight line.
-     * @param rng the random number generator to use
-     * @return List of Coord, including (startX, startY) and (endX, endY) and all points walked between
-     */
-    public static List<Coord> line(int startX, int startY, int endX, int endY,
-                                   int width, int height, double weight, RNG rng) {
-        List<Coord> pts = new ArrayList<>();
-        Coord start = Coord.get(startX, startY);
-        Direction dir;
-        do {
-            pts.add(start);
-            dir = stepWobbly(start.x, start.y, endX, endY, weight, width, height, rng);
-            start = start.translate(dir);
-            if(start.x < 1 || start.y < 1 || start.x >= width - 1 || start.y >= height - 1)
-                break;
-        }while (dir != Direction.NONE);
-        return pts;
-    }
-
-    /**
-     * Internal use. Drunkard's walk algorithm, single step. Based on Michael Patraw's C code, used for cave carving.
-     * http://mpatraw.github.io/libdrunkard/
-     * @param currentX the x coordinate of the current point
-     * @param currentY the y coordinate of the current point
-     * @param targetX the x coordinate of the point to wobble towards
-     * @param targetY the y coordinate of the point to wobble towards
-     * @param weight between 0.5 and 1.0, usually. 0.6 makes very random walks, 0.9 is almost a straight line.
-     * @param width maximum map width
-     * @param height maximum map height
-     * @param rng the random number generator to use
-     * @return a Direction, either UP, DOWN, LEFT, or RIGHT if we should move, or NONE if we have reached our target
-     */
-    private static Direction stepWobbly(int currentX, int currentY, int targetX, int targetY, double weight,
-                                        int width, int height, RNG rng)
-    {
-        int dx = targetX - currentX;
-        int dy = targetY - currentY;
-
-        if (dx >  1) dx = 1;
-        if (dx < -1) dx = -1;
-        if (dy >  1) dy = 1;
-        if (dy < -1) dy = -1;
-
-        double r = rng.nextDouble();
-        Direction dir;
-        if (dx == 0 && dy == 0)
-        {
-            return Direction.NONE;
-        }
-        else if (dx == 0 || dy == 0)
-        {
-            int dx2 = (dx == 0) ? dx : dy, dy2 = (dx == 0) ? dy : dx;
-            if (r >= (weight * 0.5))
-            {
-                r -= weight * 0.5;
-                if (r < weight * (1.0 / 6) + (1 - weight) * (1.0 / 3))
-                {
-                    dx2 = -1;
-                    dy2 = 0;
-                }
-                else if (r < weight * (2.0 / 6) + (1 - weight) * (2.0 / 3))
-                {
-                    dx2 = 1;
-                    dy2 = 0;
-                }
-                else
-                {
-                    dx2 = 0;
-                    dy2 *= -1;
-                }
-            }
-            dir = Direction.getCardinalDirection(dx2, -dy2);
-
-        }
-        else
-        {
-            if (r < weight * 0.5)
-            {
-                dy = 0;
-            }
-            else if (r < weight)
-            {
-                dx = 0;
-            }
-            else if (r < weight + (1 - weight) * 0.5)
-            {
-                dx *= -1;
-                dy = 0;
-            }
-            else
-            {
-                dx = 0;
-                dy *= -1;
-            }
-            dir = Direction.getCardinalDirection(dx, -dy);
-        }
-        if(currentX + dir.deltaX <= 0 || currentX + dir.deltaX >= width - 1) {
-            if (currentY < targetY) dir = Direction.DOWN;
-            else if (currentY > targetY) dir = Direction.UP;
-        }
-        else if(currentY + dir.deltaY <= 0 || currentY + dir.deltaY >= height - 1) {
-            if (currentX < targetX) dir = Direction.RIGHT;
-            else if (currentX > targetX) dir = Direction.LEFT;
-        }
-        return dir;
-    }
-
-    /**
-     * Draws a line from start to end using the Drunkard's Walk algorithm. Returns a List of Coord in order.
-     * @param start starting point
-     * @param end ending point
-     * @param width maximum map width
-     * @param height maximum map height
-     * @return List of Coord, including start and end and all points walked between
-     */
-    public static List<Coord> line(Coord start, Coord end, int width, int height)
-    {
-        return line(start.x, start.y, end.x, end.y, width, height);
-    }
-}