Darkcanuck/VelocityTest
Jump to navigation
Jump to search
Some basic code to test 1.7.1.3's updated getNewVelocity() method.
The main class:
import robocode.Rules;
public class VelocityTest {
private static Commands currentCommands = new Commands();
public static void main(String[] args) {
// init
System.out.println("\nDarkcanuck's VelocityTest\n");
if (!args[0].equals("all")) {
testCase(Double.valueOf(args[0]), Double.valueOf(args[1]));
} else {
testCase(0, 6);
}
}
public static void testCase(double velocity, double distance) {
double newvel = velocity;
double newdist = distance;
int tick = 0;
System.out.println("Starting velocity=" + velocity + " distance=" + distance);
while ((Math.abs(newvel)>0.00001) || (Math.abs(newdist)>0.00001)) {
newvel = getNewVelocity(newvel, newdist);
newdist -= newvel;
tick++;
System.out.println(" " + tick + " velocity=" + newvel + " remain=" + newdist);
}
System.out.println("\n");
}
private static double getNewVelocity(double velocity, double distance) {
// If the distance is negative, then change it to be positive and change the sign of the input velocity and the result
if (distance < 0) {
return -getNewVelocity(-velocity, -distance);
}
double newVelocity;
// Get the speed, which is always positive (because it is a scalar)
final double speed = Math.abs(velocity);
// Check if we are decelerating, i.e. if the velocity is negative.
// Note that if the speed is too high due to a new max. velocity, we must also decelerate.
if (velocity < 0 || speed > currentCommands.getMaxVelocity()) {
// If the velocity is negative, we are decelerating
newVelocity = speed - Rules.DECELERATION;
// Check if we are going from deceleration into acceleration
if (newVelocity < 0) {
// If we have decelerated to velocity = 0, then the remaining time must be used for acceleration
double decelTime = speed / Rules.DECELERATION;
double accelTime = (1 - decelTime);
// New velocity (v) = d / t, where time = 1 (i.e. 1 turn). Hence, v = d / 1 => v = d
// However, the new velocity must be limited by the max. velocity
newVelocity = Math.min(currentCommands.getMaxVelocity(),
Math.min(Rules.DECELERATION * decelTime * decelTime + Rules.ACCELERATION * accelTime * accelTime,
distance));
// Note: We change the sign here due to the sign check later when returning the result
velocity *= -1;
}
} else {
// Else, we are not decelerating, but might need to start doing so due to the remaining distance
// Deceleration time (t) is calculated by: v = a * t => t = v / a
final double decelTime = speed / Rules.DECELERATION;
// Deceleration time (d) is calculated by: d = 1/2 a * t^2 + v0 * t + t
// Adding the extra 't' (in the end) is special for Robocode, and v0 is the starting velocity = 0
final double decelDist = 0.5 * Rules.DECELERATION * decelTime * decelTime + decelTime;
// Check if we should start decelerating
if (distance <= decelDist) {
// If the distance < max. deceleration distance, we must decelerate so we hit a distance = 0
// Calculate time left for deceleration to distance = 0
double time = distance / (decelTime + 1); // 1 is added here due to the extra 't' for Robocode
// New velocity (v) = a * t, i.e. deceleration * time, but not greater than the current speed
if (time <= 1) {
// When there is only one turn left (t <= 1), we set the speed to match the remaining distance
newVelocity = Math.max(speed - Rules.DECELERATION, distance);
} else {
// New velocity (v) = a * t, i.e. deceleration * time
newVelocity = time * Rules.DECELERATION;
if (speed < newVelocity) {
// If the speed is less that the new velocity we just calculated, then use the old speed instead
newVelocity = speed;
} else if (speed - newVelocity > Rules.DECELERATION) {
// The deceleration must not exceed the max. deceleration.
// Hence, we limit the velocity to the speed minus the max. deceleration.
newVelocity = speed - Rules.DECELERATION;
}
}
} else {
// Else, we need to accelerate, but only to max. velocity
newVelocity = Math.min(speed + Rules.ACCELERATION, currentCommands.getMaxVelocity());
}
}
// Return the new velocity with the correct sign. We have been working with the speed, which is always positive
return (velocity < 0) ? -newVelocity : newVelocity;
}
}
And a support class for setting the max velocity:
import robocode.Rules;
public class Commands {
private static double maxVelocity = Rules.MAX_VELOCITY;
public static double getMaxVelocity() { return maxVelocity; }
public static void setMaxVelocity(double maxVel) { maxVelocity = maxVel; }
}