All Downloads are FREE. Search and download functionalities are using the official Maven repository.

squidpony.squidai.AreaUtils Maven / Gradle / Ivy

Go to download

SquidLib platform-independent logic and utility code. Please refer to https://github.com/SquidPony/SquidLib .

There is a newer version: 3.0.6
Show newest version
package squidpony.squidai;

import squidpony.squidmath.Coord;
import squidpony.squidmath.OrderedMap;


/**
 * Static utilities for use in AOE and anything else that might need HashMaps of Coord keys to Double values.
 * Created by Tommy Ettinger on 7/13/2015.
 */
public class AreaUtils {
    /**
     * This takes a 2D boolean array and returns a HashMap of Coord keys to Double values, but will only use the value
     * 1.0, and only for positions in map that have as their boolean element true.
     * @param map width by height, commonly generated by FOV methods
     * @return a HashMap of Coord keys to Double values, but the only value used is 1.0
     */
    public static OrderedMap arrayToHashMap(boolean[][] map)
    {
        OrderedMap ret = new OrderedMap<>();
        for(int i = 0; i < map.length; i++)
        {
            for(int j = 0; j < map[i].length; j++)
            {
                if(map[i][j])
                    ret.put(Coord.get(i, j), 1.0);
            }
        }
        return ret;
    }

    /**
     * This takes a 2D double array called map and returns a HashMap of Coord keys to Double values, and will have a key
     * for every position in map that is greater than 0.0, with values equal to those in map.
     * @param map width by height, commonly generated by FOV methods
     * @return a HashMap of Coord keys to Double values, with values all greater than 0.0
     */
    public static OrderedMap arrayToHashMap(double[][] map)
    {
        OrderedMap ret = new OrderedMap<>();
        for(int i = 0; i < map.length; i++)
        {
            for(int j = 0; j < map[i].length; j++)
            {
                if(map[i][j] > 0.0)
                    ret.put(Coord.get(i, j), map[i][j]);
            }
        }
        return ret;
    }

    /**
     * This takes a 2D double array and returns a HashMap of Coord keys to Double values, but will only use the value
     * 1.0, and only does this if the passed double[][] has a value at that position that is greater than cutoff.
     * For example, a cutoff of 0.3 will make all elements in the 2D array that are 0.3 or less be ignored and not put
     * into the HashMap, but all elements that are greater than 0.3 will be placed in as 1.0.
     * @param map width by height, commonly generated by FOV methods
     * @param cutoff any elements greater than this will be 1.0 in the return, anything else will be ignored
     * @return a HashMap of Coord keys to Double values, but the only value used is 1.0
     */
    public static OrderedMap arrayToHashMap(double[][] map, double cutoff)
    {
        OrderedMap ret = new OrderedMap<>();
        for(int i = 0; i < map.length; i++)
        {
            for(int j = 0; j < map[i].length; j++)
            {
                if(map[i][j] > cutoff)
                    ret.put(Coord.get(i, j), 1.0);
            }
        }
        return ret;
    }

    /**
     * This takes a DijkstraMap that has already completed a scan() and returns a HashMap of Coord keys to Double
     * values, and will have a key for every position that was reached in the DijkstraMap, with 1.0 as the only value.
     * @param map a double[][] returned by a DijkstraMap running its scan()
     * @return a HashMap of Coord keys to Double values, with values of 1.0 only
     */
    public static OrderedMap dijkstraToHashMap(double[][] map)
    {
        OrderedMap ret = new OrderedMap<>();
        for(int i = 0; i < map.length; i++)
        {
            for(int j = 0; j < map[i].length; j++)
            {
                if(map[i][j] < DijkstraMap.WALL)
                    ret.put(Coord.get(i, j), 1.0);
            }
        }
        return ret;
    }

    /**
     * Checks that the given end Coord can be targeted from the given origin Coord given the directional targeting
     * rules specified by limit. If any of the arguments are null, returns true (it assumes that any limits are not
     * valid and don't restrict anything). The following AimLimit enum values for limit have the following meanings:
     *
     * 
    *
  • AimLimit.FREE makes no restrictions; it is equivalent here to passing null for limit.
  • *
  • AimLimit.EIGHT_WAY will only consider Points to be valid targets * if they are along a straight line with an angle that is a multiple of 45 degrees, relative to the positive x * axis. Essentially, this limits the points to those a queen could move to in chess.
  • *
  • AimLimit.ORTHOGONAL will cause the AOE to only consider Points to be valid targets if * they are along a straight line with an angle that is a multiple of 90 degrees, relative to the positive x * axis. Essentially, this limits the points to those a rook could move to in chess.
  • *
  • AimLimit.DIAGONAL will cause the AOE to only consider Points to be valid targets if they are along a * straight line with an angle that is 45 degrees greater than a multiple of 90 degrees, relative to the * positive x axis. Essentially, this limits the points to those a bishop could move to in chess.
  • *
* * @param limit an AimLimit enum that restricts valid points unless it is AimLimit.FREE or null * @param origin where the user is * @param end where the point we want to verify is * @return true if the point is a valid target or if the limits are invalid (non-restricting), false otherwise */ public static boolean verifyLimit(AimLimit limit, Coord origin, Coord end) { if (limit != null && origin != null && end != null) { switch (limit) { case EIGHT_WAY: if(Math.abs(end.x - origin.x) == Math.abs(end.y - origin.y) || end.x == origin.x || end.y == origin.y) { return true; } break; case DIAGONAL: if(Math.abs(end.x - origin.x) == Math.abs(end.y - origin.y)) { return true; } break; case ORTHOGONAL: if(end.x == origin.x || end.y == origin.y) { return true; } break; case FREE: return true; } return false; } return true; } /** * Checks that the given end Coord can be targeted from the given origin Coord given the complete targeting rules * specified by reach. If any of the arguments are null, returns true (it assumes that any limits are not * valid and don't restrict anything). If reach.limit is null, it treats it as equivalent to {@link AimLimit#FREE}. * Otherwise, it uses the metric, minDistance, and maxDistance from reach to calculate if end is target-able from * origin assuming an unobstructed playing field. * * @param reach a Reach object that, if non-null, gives limits for how targeting can proceed. * @param origin where the user is * @param end where the point we want to verify is * @return true if the point is a valid target or if the limits are invalid (non-restricting), false otherwise */ public static boolean verifyReach(Reach reach, Coord origin, Coord end) { if(reach == null) return true; AimLimit limit = reach.limit; if(limit == null) limit = AimLimit.FREE; if (origin != null && end != null) { switch (limit) { case EIGHT_WAY: if(Math.abs(end.x - origin.x) == Math.abs(end.y - origin.y) || end.x == origin.x || end.y == origin.y) { return reach.metric.inRange(origin.x, origin.y, end.x, end.y, reach.minDistance, reach.maxDistance); } break; case DIAGONAL: if(Math.abs(end.x - origin.x) == Math.abs(end.y - origin.y)) { return reach.metric.inRange(origin.x, origin.y, end.x, end.y, reach.minDistance, reach.maxDistance); } break; case ORTHOGONAL: if(end.x == origin.x || end.y == origin.y) { return reach.metric.inRange(origin.x, origin.y, end.x, end.y, reach.minDistance, reach.maxDistance); } break; case FREE: return reach.metric.inRange(origin.x, origin.y, end.x, end.y, reach.minDistance, reach.maxDistance); } return false; } return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy