/**
* RRobotState.java
*/
package epgy.util;
import java.util.Comparator;
import robocode.ScannedRobotEvent;
import robocode.util.Utils;
/**
* This class represents the state of a robot at a given point in time. The EPGYRobotState is used mainly
* to store past states, and can be useful in referencing a past state of the enemy.
* @author Matthew Chun-Lum
*/
public class EPGYRobotState {
/**
* The location of the robot for this state
*/
public EPGYPoint location;
/**
* The absolute bearing in radians to the robot for this state
*/
public double absoluteBearing;
/**
* The velocity for the robot
*/
public double velocity;
/**
* The lateral velocity is the the enemy velocity
* that is perpendicular to the absolute bearing
*/
public double lateralVelocity;
/**
* The advancing velocity is the enemy velocity
* towards your direction
*/
public double advancingVelocity;
/**
* The change in velocity from the last state
*/
public double deltaV;
/**
* The heading in radians
*/
public double heading;
/**
* The change in heading in radians
*/
public double deltaH;
/**
* The distance from your robot for this state
*/
public double distance;
/**
* The time in ticks since the robot changed velocity
*/
public double timeSinceVelocityChange;
/**
* The time in ticks since the root changed directions
*/
public double timeSinceDirectionChange;
/**
* The time in ticks since the robot stopped
*/
public double timeSinceStop;
/**
* The energy of the robot
*/
public double energy;
/**
* {@code true} if the robot is accelerating
*/
public boolean accelerating;
/**
* {@code true} if the robot is breaking
*/
public boolean breaking;
/**
* {@code 1} for clockwise and {@code -1} for counter clockwise relative to your position
*/
public int directionTraveling;
/**
* Default constructor
*/
public EPGYRobotState() {}
/**
* Constructor for our states
* @param robot
*/
public EPGYRobotState(EPGYBot robot) {
EPGYRobotState lastState = robot.getCurrentState();
this.location = new EPGYPoint(robot.getX(), robot.getY());
this.absoluteBearing = 0;
this.velocity = robot.getVelocity();
this.lateralVelocity = 0;
this.advancingVelocity = 0;
this.deltaV = lastState == null ? 0 : velocity - lastState.velocity;
this.accelerating = deltaV > 0;
this.breaking = !accelerating;
this.heading = robot.getHeadingRadians();
this.deltaH = lastState == null ? 0 : heading - lastState.heading;
this.distance = 0;
this.timeSinceVelocityChange = deltaV != 0 || lastState == null ? 0 : lastState.timeSinceVelocityChange + 1;
this.directionTraveling = velocity == 0 ? 0 :
Math.sin(heading - absoluteBearing) * velocity < 0 ? -1 :
1;
this.timeSinceDirectionChange = lastState == null || lastState.directionTraveling != directionTraveling ? 0 :
lastState.timeSinceDirectionChange + 1;
this.timeSinceStop = velocity == 0 || lastState == null ? 0 : lastState.timeSinceStop + 1;
this.energy = robot.getEnergy();
}
/**
* Constructor for enemy states
* @param enemy
* @param e
*/
public EPGYRobotState(EPGYBot bot, EPGYEnemyRobot robot, ScannedRobotEvent e) {
EPGYBot reference = bot;
if(reference == null) {
return;
} else {
EPGYRobotState lastState = robot.getCurrentState();
this.absoluteBearing = Utils.normalAbsoluteAngle(reference.getHeadingRadians() + e.getBearingRadians());
this.location = EPGYUtil.project(reference.getLocation(), absoluteBearing, e.getDistance());
this.velocity = e.getVelocity();
this.heading = e.getHeadingRadians();
this.lateralVelocity = velocity * Math.sin(heading - absoluteBearing);
this.advancingVelocity = velocity * -1 * Math.cos(heading - absoluteBearing);
this.deltaV = lastState == null ? 0 : velocity - lastState.velocity;
this.accelerating = deltaV > 0;
this.breaking = !accelerating;
this.deltaH = lastState == null ? 0 : heading - lastState.heading;
this.distance = e.getDistance();
this.timeSinceVelocityChange = deltaV != 0 || lastState == null ? 0 : lastState.timeSinceVelocityChange + 1;
this.directionTraveling = lateralVelocity >= 0 ? 1 : -1;
this.timeSinceDirectionChange = lastState == null || lastState.directionTraveling != directionTraveling ? 0 :
lastState.timeSinceDirectionChange + 1;
this.timeSinceStop = velocity == 0 || lastState == null ? 0 : lastState.timeSinceStop + 1;
this.energy = e.getEnergy();
}
}
/**
* Standard constructor
* @param location
* @param absoluteBearing
* @param velocity
* @param lateralVelocity
* @param advancingVelocity
* @param deltaV
* @param heading
* @param deltaH
* @param distance
* @param distanceFromWall
* @param timeSinceVelocityChange
* @param timeSinceDirectionChange
* @param timeSinceStop
* @param energy
* @param directionTraveling
*/
public EPGYRobotState(EPGYPoint location, double absoluteBearing,
double velocity, double lateralVelocity, double advancingVelocity,
double deltaV, double heading, double deltaH, double distance,
double timeSinceVelocityChange,
double timeSinceDirectionChange, double timeSinceStop,
double energy, int directionTraveling) {
this.location = location.getCopy();
this.absoluteBearing = absoluteBearing;
this.velocity = velocity;
this.lateralVelocity = lateralVelocity;
this.advancingVelocity = advancingVelocity;
this.deltaV = deltaV;
this.heading = heading;
this.deltaH = deltaH;
this.distance = distance;
this.timeSinceVelocityChange = timeSinceVelocityChange;
this.timeSinceDirectionChange = timeSinceDirectionChange;
this.timeSinceStop = timeSinceStop;
this.energy = energy;
this.directionTraveling = directionTraveling;
this.accelerating = deltaV > 0;
this.breaking = deltaV < 0;
}
/**
* Copy constructor
* @param state
*/
public EPGYRobotState(EPGYRobotState state) {
this(state.location,
state.absoluteBearing,
state.velocity,
state.lateralVelocity,
state.advancingVelocity,
state.deltaV,
state.heading,
state.deltaH,
state.distance,
state.timeSinceVelocityChange,
state.timeSinceDirectionChange,
state.timeSinceStop,
state.energy,
state.directionTraveling);
}
/**
* Will return a copy of the passed state
* @return a copy of the current state
*/
public EPGYRobotState getCopy() {
return new EPGYRobotState(this);
}
}