001package squidpony.squidmath;
002
003import squidpony.squidgrid.Direction;
004
005import java.io.Serializable;
006
007/**
008 * A 2D coordinate with (constant) x and y fields. Coord objects are immutable; a single pool of Coord values, with
009 * x and y each ranging from -3 to 255, is shared by all users of Coord. This pool helps reduce pressure on the
010 * garbage collector when many Coord values would have been created for some purpose and quickly discarded; instead
011 * of creating a new Coord with a constructor, you use the static method {@link #get(int, int)}, which retrieves an
012 * already-existing Coord from the pool if possible, and always returns a usable Coord.
013 * <br>
014 * The Coord class is a fundamental part of SquidLib; any class that uses positions on a grid makes use of it here.
015 * It finds usage naturally in classes throughout {@link squidpony.squidgrid}, with {@link squidpony.squidgrid.zone}
016 * providing an abstraction around groups of Coord and {@link squidpony.squidgrid.iterator} providing various ways to
017 * iterate through the Coords that make up a larger shape. In this package, {@link squidpony.squidmath}, a few classes
018 * should be pointed out. {@link CoordPacker} is a class with all static methods that provides various ways to compress
019 * the memory usage of regions made of many Coord values (and can be constructed in other ways but still provide Coords
020 * later), but since Coords don't use much memory anyway, the real use of the class is for manipulating the shapes and
021 * sizes of the regions those Coords are part of. {@link GreasedRegion} has similar functionality to CoordPacker, but
022 * where CoordPacker is purely static, taking and returning regions as encoded, usually-low-memory-cost arrays of
023 * {@code short} that it considers immutable, a GreasedRegion is a mutable object that allows the same region-altering
024 * techniques to be applied in-place in a way that is relatively (very) low-time-cost. If deciding between the two,
025 * GreasedRegion should usually be preferred, and CoordPacker cannot actually be used when storing regions in larger
026 * than a 256x256 space (usually when the Coord pool has been expanded; see below); GreasedRegion can store potentially
027 * large positions.
028 * <br>
029 * More on the Coord pool used by this class:  Coords can't always be retrieved from the pool; Coord.get constructs a
030 * new Coord if one of x or y is unusually large (greater than 255) or too negative (below -3). The upper limit of 255
031 * is not a hard rule; you can increase the limit on the pool by calling {@link #expandPoolTo(int, int)} or
032 * {@link #expandPool(int, int)}, which cause more memory to be spent initially on storing Coords but can save memory
033 * or ease GC pressure over the long term by preventing duplicate Coords from being created many times. The pool can
034 * never shrink because allowing that would cause completely unpredictable results if existing Coords were in use, or
035 * could easily cause crashes on Android after resuming an application that had previously shrunken the pool due to
036 * platform quirks. Long story short, you should only expand the pool size when your game needs a larger set of 2D
037 * points it will commonly use, and in most cases you shouldn't need to change it at all.
038 * 
039 * Created by Tommy Ettinger on 8/12/2015.
040 */
041public class Coord implements Serializable {
042    private static final long serialVersionUID = 300L;
043
044        /** The x-coordinate. */
045        public final int x;
046
047        /** The y-coordinate (the ordinate) */
048        public final int y;
049
050    protected Coord()
051    {
052        this(0, 0);
053    }
054    protected Coord(final int x, final int y)
055    {
056        this.x = x;
057        this.y = y;
058    }
059    public static Coord get(final int x, final int y)
060    {
061        if(x >= -3 && y >= -3 && x < POOL.length - 3 && y < POOL[x + 3].length - 3)
062            return POOL[x + 3][y + 3];
063        else return new Coord(x, y);
064    }
065
066        /**
067     * Gets the angle in degrees to go between two Coords.
068     * When only x is different and {@code to.x} is greater than {@code from.x}, this returns 0.
069     * When only y is different and {@code to.y} is greater than {@code from.y}, this returns 90.
070     * When only x is different and {@code to.x} is less than {@code from.x}, this returns 180.
071     * When only y is different and {@code to.y} is less than {@code from.y}, this returns 270.
072     * In cases between these, the angle is between those values; it cannot be 360 but it can be very close. This never
073     * returns a negative angle. Keep in mind, "up" depends on how your code orients the y-axis, and SquidLib generally
074     * defaults to positive y going toward the bottom of the screen, like how later lines in a paragraph are further
075     * down on the page.
076     * <br>
077     * As a compatibility note, before SquidLib 3.0.0 stable, this used an odd rotation of the normal degrees where 0
078     * degrees were used when {@code to.y} was greater than {@code from.y} and x was equal. Because that typically runs
079     * counter to expectations from actual math, the behavior was changed. 
080         * @param from the starting Coord to measure from
081         * @param to the ending Coord to measure to
082         * @return The degree from {@code from} to {@code to}; 0 is up
083         */
084        public static double degrees(final Coord from, final Coord to) {
085                return NumberTools.atan2_(to.y - from.y, to.x - from.x) * 360.0;
086        }
087
088    /**
089     * Provided for compatibility with earlier code that used the AWT Point API.
090     * @return this Coord, without changes
091     */
092    public Coord getLocation()
093    {
094        return this;
095    }
096
097    /**
098     * Takes this Coord, adds x to its x and y to its y, and returns the Coord at that position.
099     * @param x the amount of x distance to move
100     * @param y the amount of y distance to move
101     * @return a Coord (usually cached and not a new instance) that has been moved the specified distance
102     */
103    public Coord translate(final int x, final int y)
104    {
105        return get(this.x + x, this.y + y);
106    }
107    /**
108     * Takes this Coord, adds x to its x and y to its y, limiting x from 0 to width and limiting y from 0 to height,
109     * and returns the Coord at that position.
110     * @param x the amount of x distance to move
111     * @param y the amount of y distance to move
112     * @param width one higher than the maximum x value this can use; typically the length of an array
113     * @param height one higher than the maximum y value this can use; typically the length of an array
114     * @return a Coord (usually cached and not a new instance) that has been moved the specified distance
115     */
116    public Coord translateCapped(final int x, final int y, final int width, final int height)
117    {
118        return get(Math.min(Math.max(0, this.x + x), width - 1), Math.min(Math.max(0, this.y + y), height - 1));
119    }
120
121    /**
122     * Separately combines the x and y positions of this Coord and other, producing a different Coord as their "sum."
123     * @param other another Coord
124     * @return a Coord (usually cached and not a new instance) with {@code x = this.x + other.x; y = this.y + other.y}
125     */
126    public Coord add(final Coord other)
127    {
128        return get(x + other.x, y + other.y);
129    }
130
131    /**
132     * Separately adds the x and y positions of this Coord to operand, producing a different Coord as their
133     * "sum."
134     * @param operand a value to add each of x and y to
135     * @return a Coord (usually cached and not a new instance) with {@code x = this.x + operand; y = this.y + operand}
136     */
137    public Coord add(final int operand)
138    {
139        return get(x + operand, y + operand);
140    }
141
142    /**
143     * Separately adds the x and y positions of this Coord to operand, rounding to the nearest int for each of x
144     * and y and producing a different Coord as their "sum."
145     * @param operand a value to add each of x and y to
146     * @return a Coord (usually cached and not a new instance) with {@code x = this.x + operand; y = this.y +
147     *          operand}, with both x and y rounded accordingly
148     */
149    public Coord add(final double operand)
150    {
151        return get((int)Math.round(x + operand), (int)Math.round(y + operand));
152    }
153
154    /**
155     * Separately subtracts the x and y positions of other from this Coord, producing a different Coord as their
156     * "difference."
157     * @param other another Coord
158     * @return a Coord (usually cached and not a new instance) with {@code x = this.x - other.x; y = this.y - other.y}
159     */
160    public Coord subtract(final Coord other)
161    {
162        return get(x - other.x, y - other.y);
163    }
164
165    /**
166     * Separately subtracts operand from the x and y positions of this Coord, producing a different Coord as their
167     * "difference."
168     * @param operand a value to subtract from each of x and y
169     * @return a Coord (usually cached and not a new instance) with {@code x = this.x - operand; y = this.y - operand}
170     */
171    public Coord subtract(final int operand)
172    {
173        return get(x - operand, y - operand);
174    }
175
176    /**
177     * Separately subtracts operand from the x and y positions of this Coord, rounding to the nearest int for each of x
178     * and y and producing a different Coord as their "difference."
179     * @param operand a value to subtract from each of x and y
180     * @return a Coord (usually cached and not a new instance) with {@code x = this.x - operand; y = this.y -
181     *          operand}, with both x and y rounded accordingly
182     */
183    public Coord subtract(final double operand)
184    {
185        return get((int)Math.round(x - operand), (int)Math.round(y - operand));
186    }
187    /**
188     * Separately multiplies the x and y positions of other from this Coord, producing a different Coord as their
189     * "product."
190     * @param other another Coord
191     * @return a Coord (usually cached and not a new instance) with {@code x = this.x * other.x; y = this.y * other.y}
192     */
193    public Coord multiply(final Coord other)
194    {
195        return get(x * other.x, y * other.y);
196    }
197    /**
198     * Separately multiplies the x and y positions of this Coord by operand, producing a different Coord as their
199     * "product."
200     * @param operand a value to multiply each of x and y by
201     * @return a Coord (usually cached and not a new instance) with {@code x = this.x * operand; y = this.y * operand}
202     */
203    public Coord multiply(final int operand)
204    {
205        return get(x * operand, y * operand);
206    }
207
208    /**
209     * Separately multiplies the x and y positions of this Coord by operand, rounding to the nearest int for each of x
210     * and y and producing a different Coord as their "product."
211     * @param operand a value to multiply each of x and y by
212     * @return a Coord (usually cached and not a new instance) with {@code x = this.x * operand; y = this.y *
213     *          operand}, with both x and y rounded accordingly
214     */
215    public Coord multiply(final double operand)
216    {
217        return get((int)Math.round(x * operand), (int)Math.round(y * operand));
218    }
219
220    /**
221     * Separately divides the x and y positions of this Coord by other, producing a different Coord as their
222     * "quotient." If other has 0 for x or y, this will throw an exception, as dividing by 0 is expected to do.
223     * @param other another Coord
224     * @return a Coord (usually cached and not a new instance) with {@code x = this.x / other.x; y = this.y / other.y}
225     */
226    public Coord divide(final Coord other)
227    {
228        return get(x / other.x, y / other.y);
229    }
230    /**
231     * Separately divides the x and y positions of this Coord by operand, producing a different Coord as their
232     * "quotient." If operand is 0, this will throw an exception, as dividing by 0 is expected to do.
233     * @param operand a value to divide each of x and y by
234     * @return a Coord (usually cached and not a new instance) with {@code x = this.x / operand; y = this.y / operand}
235     */
236    public Coord divide(final int operand)
237    {
238        return get(x / operand, y / operand);
239    }
240
241    /**
242     * Separately divides the x and y positions of this Coord by operand, flooring to a lower int for each of x and
243     * y and producing a different Coord as their "quotient." If operand is 0.0, expect strange results (infinity and
244     * NaN are both possibilities).
245     * @param operand a value to divide each of x and y by
246     * @return a Coord (usually cached and not a new instance) with {@code x = this.x / operand; y = this.y /
247     *          operand}, with both x and y rounded accordingly
248     */
249    public Coord divide(final double operand)
250    {
251        return get((int)(x / operand), (int)(y / operand));
252    }
253
254    /**
255     * Separately divides the x and y positions of this Coord by operand, rounding to the nearest int for each of x and
256     * y and producing a different Coord as their "quotient." If operand is 0.0, expect strange results (infinity and
257     * NaN are both possibilities).
258     * @param operand a value to divide each of x and y by
259     * @return a Coord (usually cached and not a new instance) with {@code x = this.x / operand; y = this.y /
260     *          operand}, with both x and y rounded accordingly
261     */
262    public Coord divideRounding(final double operand)
263    {
264        return get((int)Math.round(x / operand), (int)Math.round(y / operand));
265    }
266
267    /**
268     * Separately averages the x and y positions of this Coord with other, producing a different Coord as their
269     * "midpoint."
270     * @param other another Coord
271     * @return a Coord (usually cached and not a new instance) halfway between this and other, rounded nearest.
272     */
273    public Coord average(final Coord other)
274    {
275        return get(Math.round((x + other.x) / 2.0f), Math.round((y + other.y) / 2.0f));
276    }
277        /**
278         * @param d
279         *            A non-{@code null} direction.
280         * @return The coordinate obtained by applying {@code d} on {@code this}.
281         */
282        public Coord translate(final Direction d) {
283                return Coord.get(x + d.deltaX, y + d.deltaY);
284        }
285
286        /**
287         * @param i
288         * @return {@code (x*i,y*i)}.
289         */
290        public Coord scale(final int i) {
291                return Coord.get(x * i, y * i);
292        }
293
294        /**
295         * @param i
296         * @return {@code (x*i,y*j)}.
297         */
298        public Coord scale(final int i, final int j) {
299                return Coord.get(x * i, y * j);
300        }
301
302    public double distance(final double x2, final double y2)
303    {
304        return Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y));
305    }
306    public double distance(final Coord co)
307    {
308        return Math.sqrt((co.x - x) * (co.x - x) + (co.y - y) * (co.y - y));
309    }
310    public double distanceSq(final double x2, final double y2)
311    {
312        return (x2 - x) * (x2 - x) + (y2 - y) * (y2 - y);
313    }
314    public double distanceSq(final Coord co) { return (co.x - x) * (co.x - x) + (co.y - y) * (co.y - y); }
315
316    /**
317     * Gets a Coord based off this instance but with odd values for x and/or y decreased to the nearest even number.
318     * May be useful for thin-wall maps as produced by {@link squidpony.squidgrid.mapping.ThinDungeonGenerator} and used
319     * with {@link squidpony.squidgrid.Adjacency.ThinWallAdjacency}.
320     * @return a Coord (probably from the pool) with even x and even y, changing (decrementing) only if they are odd
321     */
322    public Coord makeEven()
323    {
324        return get(x & -2, y & -2);
325    }
326
327    /**
328     * Gets a Coord based off this instance but with even values for x and/or y increased to the nearest odd number.
329     * May be useful for thin-wall maps as produced by {@link squidpony.squidgrid.mapping.ThinDungeonGenerator} and used
330     * with {@link squidpony.squidgrid.Adjacency.ThinWallAdjacency}.
331     * @return a Coord (probably from the pool) with odd x and odd y, changing (incrementing) only if they are even
332     */
333    public Coord makeOdd() {
334        return get(x | 1, y | 1);
335    }
336
337        /**
338         * @param c
339         * @return Whether {@code this} is adjacent to {@code c}. Not that a cell is
340         *         not adjacent to itself with this method.
341         */
342        public boolean isAdjacent(final Coord c) {
343                switch (Math.abs(x - c.x)) {
344                case 0:
345                        return Math.abs(y - c.y) == 1;
346                case 1:
347                        return y == c.y || Math.abs(y - c.y) == 1;
348                default:
349                        return false;
350                }
351        }
352
353        /**
354     * Gets the {@link Direction} needed to get to {@code target} from this; typically this is more useful when target
355     * and this are adjacent (by {@link #isAdjacent(Coord)}) since that should make it possible to go to target.
356     * <br>
357     * Internally, this delegates to {@link Direction#toGoTo(Coord, Coord)}, and some code may prefer using the method
358     * in Direction instead of this one. Earlier versions of this code only worked for adjacent Coords, which seemed
359     * like an unnecessary limitation since Direction's version worked for any arguments.
360         * @param target a non-null {@link Coord}
361         * @return the direction to go from {@code this} to {@code target}
362         */
363        public Direction toGoTo(final Coord target) {
364            return Direction.toGoTo(this, target);
365        }
366
367    /**
368     * Returns true if x is between 0 (inclusive) and width (exclusive) and y is between 0 (inclusive) and height
369     * (exclusive), false otherwise.
370     * @param width the upper limit on x to check, exclusive
371     * @param height the upper limit on y to check, exclusive
372     * @return true if this Coord is within the limits of width and height and has non-negative x and y
373     */
374    public boolean isWithin(final int width, final int height)
375    {
376        return x >= 0 && y >= 0 && x < width && y < height;
377    }
378    /**
379     * Returns true if x is between minX (inclusive) and maxX (exclusive) and y is between minY (inclusive) and maxY
380     * (exclusive), false otherwise.
381     * @param minX the lower limit on x to check, inclusive
382     * @param minY the lower limit on y to check, inclusive
383     * @param maxX the upper limit on x to check, exclusive
384     * @param maxY the upper limit on y to check, exclusive
385     * @return true if this Coord is within the limits of the given parameters
386     */
387    public boolean isWithinRectangle(int minX, int minY, int maxX, int maxY)
388    {
389        return x >= minX && y >= minY && x < maxX && y < maxY;
390    }
391    public int getX() {
392        return x;
393    }
394
395    public Coord setX(final int x) {
396        return get(x, y);
397    }
398
399    public int getY() {
400        return y;
401    }
402
403    public Coord setY(final int y) {
404        return get(x, y);
405    }
406
407    @Override
408    public String toString()
409    {
410        return "(" + x + "," + y + ")";
411    }
412
413    /**
414     * Gets the hash code for this Coord; does not use the standard "auto-complete" style of hash that most IDEs will
415     * generate, but instead uses a highly-specific technique based on the Rosenberg-Strong pairing function, a Gray
416     * code, and two XLCG steps at the end. It manages to get extremely low collision rates under many circumstances,
417     * and very frequently manages to avoid colliding on more than 25% of Coords (making the load factor of most
418     * hash-based collections fine at a default of 0.75) while often having 0 collisions with some data sets.
419     * It does much better when Coords are in the default pooled range of -3 or greater.
420     * <br>
421     * This gets slightly better collision rates than previous versions used by SquidLib, around 4% across a wide
422     * variety of rectangular areas (most earlier hashes got about-5%-range collision rates, and using
423     * {@link java.util.Objects#hash(Object...)} gives more than a 75% collision rate). The previous version, which is
424     * still available as {@link #cantorHashCode(int, int)}, has slightly better results when used for seeding
425     * procedural generation based on a Coord (a reasonable usage of this method), but both this hash code and the
426     * Cantor-based one have excellent randomness in the upper bits of the hash (so if you use a hashCode() result as a
427     * whole int, then it should be pretty good as a seed). The method before the Cantor-based one,
428     * {@link #xoroHashCode(int, int)} was structured a little like xoroshiro ({@link XoRoRNG} uses the 64-bit version
429     * of xoroshiro), and while it had pretty low collision rates (low 5% range), its hash codes changed bits in large
430     * checkerboard patterns, leaving heavy square-shaped biases in generated results.
431     * <br>
432     * This changed at least 7 times in SquidLib's history. In general, you shouldn't rely on hashCodes to stay the
433     * same across platforms and versions, whether for the JDK or this library. SquidLib (tries to) never depend on the
434     * unpredictable ordering of some hash-based collections like HashSet and HashMap, instead using its own
435     * {@link OrderedSet} and {@link OrderedMap}; if you use the ordered kinds, then the only things that matter about
436     * this hash code are that it's fast (it's fast enough), it's cross-platform compatible (this version avoids using
437     * long values, which are slow on GWT, and is carefully written to behave the same on GWT as desktop) and that it
438     * doesn't collide often (which is now much more accurate than in earlier versions of this method).
439     * @see #rosenbergStrongHashCode(int, int) A static method that gets the same result as this method without involving a Coord
440     * @return an int that should, for most different Coord values, be significantly different from the other hash codes
441     */
442    @Override
443    public int hashCode() {
444        //// for Coord, since it can be as low as -3, and Rosenberg-Strong works only for positive integers
445        final int x = this.x + 3;
446        final int y = this.y + 3;
447        //// Rosenberg-Strong pairing function; has excellent traits for keeping the hash gap-less while the
448        //// inputs fit inside a square, and is still good for rectangles.
449        final int n = (x >= y ? x * (x + 2) - y : y * y + x);
450        //// Gray code, XLCG, XLCG (ending on a XOR to stay within int range on GWT).
451        //// The Gray code moves bits around just a little, but keeps the same power-of-two upper bound.
452        //// the XLCGs together only really randomize the upper bits; they don't change the lower bit at all.
453        //// (recall from RNG class that an XLCG is a XOR by a constant, then a multiply by a constant, where
454        //// the XOR constant, mod 8, is 5, while the multiplier, mod 8, is 3; the order can be reversed too.)
455        //// ending on a XOR helps mostly for GWT.
456        return ((n ^ n >>> 1) * 0x9E373 ^ 0xD1B54A35) * 0x125493 ^ 0x91E10DA5;
457    }
458
459    /**
460     * A static version of an earlier {@link #hashCode()} method of this class, taking x and y as parameters instead of
461     * requiring a Coord object. Like the earlier hashCode() method, this involves the close-to-optimal mathematical
462     * Cantor pairing function to distribute x and y without overlap until they get very large. Cantor's pairing
463     * function can be written simply as {@code ((x + y) * (x + y + 1)) / 2 + y}; it produces sequential results for a
464     * sequence of positive points traveling in diagonal stripes away from the origin. The finalization steps this
465     * performs improve the randomness of the lower bits, but also worsen collision rates; most cases involving Coords
466     * will see lower collision rates from {@link #rosenbergStrongHashCode(int, int)}, but more random results from this
467     * method.
468     * @param x the x coordinate of the "imaginary Coord" to hash
469     * @param y the y coordinate of the "imaginary Coord" to hash
470     * @return the equivalent to the hashCode() of an "imaginary Coord"
471     */
472    public static int cantorHashCode(int x, int y) {
473        x ^= x >> 31;
474        y ^= y >> 31;
475        y += ((x + y) * (x + y + 1) >> 1);
476        y ^= y >>> 1 ^ y >>> 6;
477        return (y ^ (y << 15 | y >>> 17) ^ (y << 23 | y >>> 9)) * 0x125493 ^ 0xD1B54A35;
478    }
479    /**
480     * A static version of the current {@link #hashCode()} method of this class, taking x and y as parameters instead of
481     * requiring a Coord object. Like the current hashCode() method, this involves the close-to-optimal mathematical
482     * Rosenberg-Strong pairing function to distribute x and y without overlap until they get very large. The
483     * Rosenberg-Strong pairing function can be written simply as {@code ((x >= y) ? x * (x + 2) - y : y * y + x)}; it
484     * produces sequential results for a sequence of positive points traveling in square "shells" away from the origin.
485     * <a href="https://hbfs.wordpress.com/2018/08/07/moeud-deux/">the algorithm is discussed more here</a>; the only
486     * changes this makes are adding 3 to x and y (to account for the minimum of -3 in most cases for a Coord), and some
487     * finalizing steps that help randomize the upper bits of the hash code (the lower bits are quite non-random because
488     * they can't permit any gaps while optimizing collision rates).
489     * @param x the x coordinate of the "imaginary Coord" to hash
490     * @param y the y coordinate of the "imaginary Coord" to hash
491     * @return the equivalent to the hashCode() of an "imaginary Coord"
492     */
493    public static int rosenbergStrongHashCode(int x, int y) {
494        //// for Coord, since it can be as low as -3, and Rosenberg-Strong works only for positive integers
495        x += 3;
496        y += 3;
497        //// Rosenberg-Strong pairing function; has excellent traits for keeping the hash gap-less while the
498        //// inputs fit inside a square, and is still good for rectangles.
499        final int n = (x >= y ? x * (x + 2) - y : y * y + x);
500        //// Gray code, XLCG, XLCG (ending on a XOR to stay within int range on GWT).
501        //// The Gray code moves bits around just a little, but keeps the same power-of-two upper bound.
502        //// the XLCGs together only really randomize the upper bits; they don't change the lower bit at all.
503        //// (recall from RNG class that an XLCG is a XOR by a constant, then a multiply by a constant, where
504        //// the XOR constant, mod 8, is 5, while the multiplier, mod 8, is 3; the order can be reversed too.)
505        //// ending on a XOR helps mostly for GWT.
506        return ((n ^ n >>> 1) * 0x9E373 ^ 0xD1B54A35) * 0x125493 ^ 0x91E10DA5;
507    }
508    /**
509     * An earlier hashCode() implementation used by this class, now standalone in case you want to replicate the results
510     * of the older code. This uses only bitwise operations, which tend to be fairly fast on all platforms, and when
511     * used in a collection it has comparable collision rates to the current hashCode() method (very, very low rates),
512     * but if used for procedural generation it's simply terrible, with large blocks of nearby x,y points having
513     * identical values for several bits and all changes happening in a repetitive checkerboard pattern. It is
514     * structured very similarly to {@link XoRoRNG} and {@link Lathe32RNG} in particular, but using only bitwise math.
515     * @param x the x coordinate of the "imaginary Coord" to hash
516     * @param y the y coordinate of the "imaginary Coord" to hash
517     * @return the equivalent to the hashCode() of an "imaginary Coord"
518     */
519    public static int xoroHashCode(final int x, final int y) {
520        int r = x ^ y;
521        r ^= (x << 13 | x >>> 19) ^ (r << 5) ^ (r << 28 | r >>> 4);
522        r = x ^ (r << 11 | r >>> 21);
523        return r ^ (r << 25 | r >>> 7);
524    }
525
526    /**
527     * Something like hashCode(), but reversible with {@code Coord.decode()}. Works for Coords between roughly -256 and
528     * 32000 in each of x and y, but will probably only decode to pooled Coords if x and y are both between -3 and 255
529     * (inclusive for both).
530     * @return an int as a unique code for this Coord
531     */
532    public int encode()
533    {
534        return ((x + 256) << 16) ^ (y + 256);
535    }
536
537    /**
538     * An alternative to getting a Coord with Coord.get() only to encode() it as the next step. This doesn't create a
539     * Coord in the middle step. Can be decoded with Coord.decode() to get the (x,y) Coord.
540     * @param x the x position to encode
541     * @param y the y position to encode
542     * @return the coded int that a Coord at (x,y) would produce with encode()
543     */
544    public static int pureEncode(final int x, final int y)
545    {
546        return ((x + 256) << 16) ^ (y + 256);
547    }
548    /**
549     * This can take an int produced by {@code someCoord.encode()} and get the original Coord back out of it. It
550     * works for all pooled Coords where the pool hasn't been expanded past about 32,000 in either dimension. It even
551     * works for Coords with negative x or y as well, if they are no lower than -256 in either dimension. This will
552     * almost certainly fail (producing a gibberish Coord that probably won't be pooled) on hashes produced by any other
553     * class, including subclasses of Coord.
554     * @param code an encoded int from a Coord, but not a subclass of Coord
555     * @return the Coord that gave hash as its hashCode()
556     */
557    public static Coord decode(final int code)
558    {
559        return get((code >>> 16) - 256, (code & 0xFFFF) - 256);
560    }
561
562    @Override
563    public boolean equals(Object o) {
564        if (o instanceof Coord) {
565            Coord other = (Coord) o;
566            return x == other.x && y == other.y;
567        } else {
568            return false;
569        }
570    }
571    private static Coord[][] POOL = new Coord[259][259];
572    static {
573        int width = POOL.length, height = POOL[0].length;
574        for (int i = 0; i < width; i++) {
575            for (int j = 0; j < height; j++) {
576                POOL[i][j] = new Coord(i - 3, j - 3);
577            }
578        }
579    }
580
581    /**
582     * Gets the width of the pool used as a cache for Coords, not including negative Coords.
583     * Unless expandPool() has been called, this should be 256.
584     * Useful for finding the upper (exclusive) bound for x values that can be used efficiently in Coords.
585     * Requesting a Coord with a x greater than or equal to this value will result in a new Coord being allocated and
586     * not cached, which may cause problems with code that expects the normal reference equality of Coords to be upheld
587     * and in extreme cases may require more time garbage collecting than is normally necessary.
588     * @return the width of the Coord cache, disregarding negative Coords
589     */
590    public static int getCacheWidth()
591    {
592        return POOL.length - 3;
593    }
594
595    /**
596     * Gets the height of the pool used as a cache for Coords, not including negative Coords.
597     * Unless expandPool() has been called, this should be 256.
598     * Useful for finding the upper (exclusive) bound for y values that can be used efficiently in Coords.
599     * Requesting a Coord with a y greater than or equal to this value will result in a new Coord being allocated and
600     * not cached, which may cause problems with code that expects the normal reference equality of Coords to be upheld
601     * and in extreme cases may require more time garbage collecting than is normally necessary.
602     * @return the height of the Coord cache, disregarding negative Coords
603     */
604    public static int getCacheHeight()
605    {
606        return POOL[0].length - 3;
607    }
608
609    /**
610     * Enlarges the pool of cached Coords to the given width and height, and doesn't change
611     * a dimension if it would be reduced in size.
612     * Cached Coord values will be reused by Coord.get instead of re-allocated each time.
613     * The default pool allows Coords with x and y each between -3 and 255, inclusive, to
614     * be cached, and is considered to have width and height of 256 to begin with. Giving a
615     * width greater than 256 will allow Coords with x greater than 255 to be cached;
616     * likewise for height. If width or height is smaller than the current cache width or
617     * height, that dimension will not change, but the other still may if it is valid. You
618     * cannot shrink the pool size.
619     * @param width the new width for the pool of cached Coords; will be ignored if smaller than the current width
620     * @param height the new height for the pool of cached Coords; will be ignored if smaller than the current height
621     */
622    public static void expandPoolTo(final int width, final int height)
623    {
624        expandPool(Math.max(0, width + 3 - POOL.length), Math.max(0, height + 3 - POOL[0].length));
625    }
626
627    /**
628     * Enlarges the pool of cached Coords by the given amount of expansion for x and y.
629     * Cached Coord values will be reused by Coord.get instead of re-allocated each time.
630     * The default pool allows Coords with x and y each between -3 and 255, inclusive, to
631     * be cached, and this can increase the size in the positive direction. If either
632     * xIncrease or yIncrease is negative, this method returns immediately and does nothing
633     * else; the same is true of both arguments are zero. You cannot shrink the pool size.
634     * @param xIncrease the amount to increase cache's width by
635     * @param yIncrease the amount to increase cache's height by
636     */
637    public static void expandPool(final int xIncrease, final int yIncrease)
638    {
639        if(xIncrease < 0 || yIncrease < 0 || (xIncrease | yIncrease) == 0 )
640            return;
641        int width = POOL.length, height = POOL[0].length;
642        Coord[][] POOL2 = new Coord[width + xIncrease][height + yIncrease];
643        for (int i = 0; i < width; i++) {
644            POOL2[i] = new Coord[height + yIncrease];
645            System.arraycopy(POOL[i], 0, POOL2[i], 0, height);
646            for (int j = 0; j < height + yIncrease; j++) {
647                if(POOL2[i][j] == null) POOL2[i][j] = new Coord(i - 3, j - 3);
648            }
649        }
650        for (int i = width; i < width + xIncrease; i++) {
651            POOL2[i] = new Coord[height + yIncrease];
652            for (int j = 0; j < height + yIncrease; j++) {
653                POOL2[i][j] = new Coord(i - 3, j - 3);
654            }
655        }
656        POOL = POOL2;
657    }
658
659    public Coord interpolate(Coord end, float amountTraveled) {
660        return Coord.get(x + Math.round((end.x - x) * amountTraveled),
661                y + Math.round((end.y - y) * amountTraveled));
662    }
663}