/** * Util.java */ package rampancy_old.util; import java.awt.geom.Point2D; import rampancy_old.util.kdTree.KDDistanceFunction; import robocode.AdvancedRobot; import robocode.util.Utils; import java.util.*; /** * This class contains utility methods used by Durandal * @author Matthew Chun-Lum * */ public abstract class Util { /** * Credit: Voidious * Handles movement in an efficient manner. * @param robot * @param goAngle * @param dist */ public static void setBackAsFront(AdvancedRobot robot, double goAngle, double dist) { double angle = Utils.normalRelativeAngle(goAngle - robot.getHeadingRadians()); if (Math.abs(angle) > (Math.PI/2)) { if (angle < 0) { robot.setTurnRightRadians(Math.PI + angle); } else { robot.setTurnLeftRadians(Math.PI - angle); } robot.setBack(dist); } else { if (angle < 0) { robot.setTurnLeftRadians(-1*angle); } else { robot.setTurnRightRadians(angle); } robot.setAhead(dist); } } public static double computeDensity(List<Double> distances, double h) { double factor = 1.0 / (distances.size() * h); double k_factor = 1.0 / Math.sqrt(Math.PI * 2); double sigma = 0; for(int i = 0; i < distances.size(); i++) sigma += Math.exp(-0.5 * Math.pow(distances.get(i) / h, 2)); return sigma * factor * k_factor; } /** * Rounds the specified value to the passed float precision * @param value * @param precision * @return the rounded value */ public static double roundToPrecision(double value, int precision) { int temp = (int) Math.round((value * Math.max(1, Math.pow(10, precision)))); return ((double) temp) / Math.pow(10, precision); } /** * Scales a given value to fall within the given min and max values * @param min * @param max * @param minExpected * @param maxExpected * @param value * @return */ public static double scaleToRange(double min, double max, double minExpected, double maxExpected, double value) { return scaleToRange(min, max, minExpected, maxExpected, value, 0); } /** * Scales a given value to fall within the given min and max values * @param min * @param max * @param minExpected * @param maxExpected * @param value * @param offset * @return */ public static double scaleToRange(double min, double max, double minExpected, double maxExpected, double value, double offset) { double scaleRange = max - min; double valueRange = maxExpected - minExpected; double percentDiff = scaleRange / valueRange; return Util.limit(min, (value + offset) * percentDiff, max); } /** * Determines if the passed value is within the range * @param min * @param max * @param value * @return */ public static boolean inRange(double min, double max, double value) { return (value >= min && value <= max); } /** * Computes the rolling average * @param value * @param newEntry * @param n * @param weighting * @return */ public static double rollingAvg(double value, double newEntry, double n, double weighting ) { return (value * n + newEntry * weighting)/(n + weighting); } /** * @param values * @return the lowest value from the list of values */ public static double lowest(double[] values) { double lowest = values[0]; for(int i = 1; i < values.length; i++) if(lowest > values[i]) lowest = values[i]; return lowest; } /** * Limits the passed value to the range between the passed max * and min values * @param min * @param value * @param max * @return the limited value */ public static double limit(double min, double value, double max) { return Math.max(min, Math.min(value, max)); } /** * Computes the absolute bearing from the source to the target * @param source * @param target * @return the absolute bearing in radians */ public static double computeAbsoluteBearing(Point2D.Double source, Point2D.Double target) { return Math.atan2(target.x - source.x, target.y - source.y); } /** * Determines the velocity of a bullet given its power * @param bulletPower * @return the velocity of the bullet */ public static double computeBulletVelocity(double bulletPower) { return (20.0 - (3.0 * bulletPower)); } /** * Determines the max escape angle given velocity * @param velocity * @return the max escape angle */ public static double computeMaxEscapeAngle(double velocity) { return Math.asin(8.0 / velocity); } /** * Determines if the enemy is advancing (mainly to counter ram bots) * @param absoluteBearing * @param enemyHeading * @param deltaHeading * @param velocity * @return {@code true} if the enemy is advancing */ public static boolean isAdvancing(double absoluteBearing, double enemyHeading, double deltaHeading, double velocity) { if(inRange(-Constants.RAM_TOLERANCE, Constants.RAM_TOLERANCE, Math.abs(enemyHeading - absoluteBearing) - Math.PI)) { return (Math.abs(deltaHeading) < Constants.DELTA_TOLERANCE && velocity > 1); } return false; } /** * Returns 1 or -1 given the passed value * @param d * @return */ public static int nonZeroSign(double d) { if (d < 0) { return -1; } return 1; } /** * Projects a point location given distance and angle */ public static Point2D.Double project(Point2D.Double source, double angle, double length) { double x = source.x + Math.sin(angle) * length; double y = source.y + Math.cos(angle) * length; return new Point2D.Double(x, y); } }