001package squidpony.squidai;
002
003import squidpony.squidgrid.Radius;
004
005import java.io.Serializable;
006
007/**
008 * A struct-like class that holds information about targeting rules for actions or other effects that reach from one
009 * square into another one, with certain potential restrictions.
010 *
011 * @see squidpony.squidai.AreaUtils AreaUtils and its verifyReach method may be useful with this
012 * Created by Tommy Ettinger on 12/17/2015.
013 */
014public class Reach implements Serializable  {
015    private static final long serialVersionUID = 1L;
016
017    /**
018     * The minimum distance in cells that this Reach can target.
019     * Distance will be measured using the {@code metric} field.
020     */
021    public int minDistance;
022
023    /**
024     * The maximum distance in cells that this Reach can target.
025     * Distance will be measured using the {@code metric} field.
026     */
027    public int maxDistance;
028    /**
029     * An AimLimit enum that may be used to determine limitations to targeting cells; defaults to FREE (no limits other
030     * than those from distance), but can also be set to ORTHOGONAL (rook move in chess), DIAGONAL (bishop move in
031     * chess), EIGHT_WAY (queen or king move in chess), or null (which usually)
032     */
033    public AimLimit limit;
034    /**
035     * Determines how distance will be measured. SQUARE or CUBE correspond to 8-way or Chebyshev movement, DIAMOND or
036     * OCTAHEDRON correspond to 4-way or Manhattan movement, and CIRCLE or SPHERE correspond to Euclidean movement.
037     */
038    public Radius metric;
039
040    /**
041     * Constructs a Reach with all fields given default values; maxDistance is set to 1, minDistance is set to 0, limit
042     * is set to AimLimit.FREE, and metric is set to Radius.SQUARE (8-way movement).
043     */
044    public Reach() {
045        minDistance = 0;
046        maxDistance = 1;
047        limit = AimLimit.FREE;
048        metric = Radius.SQUARE;
049    }
050
051    /**
052     * Constructs a Reach with the specified maxDistance, to a minimum of 0. Other fields are given default values;
053     * minDistance is set to 0, limit is set to AimLimit.FREE, and metric is set to Radius.SQUARE (8-way movement).
054     * @param maxDistance the longest distance in cells this Reach can target; will be set to 0 if negative
055     */
056    public Reach(int maxDistance) {
057        minDistance = 0;
058        this.maxDistance = Math.max(maxDistance, 0);
059        limit = AimLimit.FREE;
060        metric = Radius.SQUARE;
061    }
062
063    /**
064     * Constructs a Reach with the specified minDistance, to a minimum of 0, and maxDistance, to a minimum equal to
065     * minDistance (after factoring in any change to meet the minimum of 0). Other fields are given default values;
066     * limit is set to AimLimit.FREE, and metric is set to Radius.SQUARE (8-way movement).
067     * @param minDistance the shortest distance in cells this Reach can target; will be set to 0 if negative
068     * @param maxDistance the longest distance in cells this Reach can target; will be set to the final value of
069     *                    minDistance if it is lower than the calculated minDistance
070     */
071    public Reach(int minDistance, int maxDistance) {
072        this.minDistance = Math.max(minDistance, 0);
073        this.maxDistance = Math.max(this.minDistance, maxDistance);
074        limit = AimLimit.FREE;
075        metric = Radius.SQUARE;
076    }
077
078    /**
079     * Constructs a Reach with the specified minDistance, to a minimum of 0, maxDistance, to a minimum equal to
080     * minDistance (after factoring in any change to meet the minimum of 0), and distance calculation metric as a Radius
081     * enum. Other than that, limit is set to AimLimit.FREE.
082     * @param minDistance the shortest distance in cells this Reach can target; will be set to 0 if negative
083     * @param maxDistance the longest distance in cells this Reach can target; will be set to the final value of
084     *                    minDistance if it is lower than the calculated minDistance
085     * @param metric a Radius enum that determines how distance will be calculated
086     */
087    public Reach(int minDistance, int maxDistance, Radius metric) {
088        this.minDistance = Math.max(minDistance, 0);
089        this.maxDistance = Math.max(this.minDistance, maxDistance);
090        limit = AimLimit.FREE;
091        this.metric = metric;
092    }
093
094    /**
095     * Constructs a Reach with the specified minDistance, to a minimum of 0, maxDistance, to a minimum equal to
096     * minDistance (after factoring in any change to meet the minimum of 0), and distance calculation metric as a Radius
097     * enum. Other than that, limit is set to AimLimit.FREE.
098     * @param minDistance the shortest distance in cells this Reach can target; will be set to 0 if negative
099     * @param maxDistance the longest distance in cells this Reach can target; will be set to the final value of
100     *                    minDistance if it is lower than the calculated minDistance
101     * @param metric a Radius enum that determines how distance will be calculated
102     * @param limit an AimLimit enum that can be used to limit targeting to specific angles, or not at all (if null or
103     *              equal to AimLimit.FREE)
104     */
105    public Reach(int minDistance, int maxDistance, Radius metric, AimLimit limit) {
106        this.minDistance = Math.max(minDistance, 0);
107        this.maxDistance = Math.max(this.minDistance, maxDistance);
108        this.limit = limit;
109        this.metric = metric;
110    }
111}