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("Darkcanuck's VelocityTest\n\n");
testCase(Double.valueOf(args[0]), Double.valueOf(args[1]));
}
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 + "\n");
while (newdist > 0.0) {
newvel = getNewVelocity(newvel, newdist);
newdist -= newvel;
tick++;
System.out.println(" " + tick + " velocity=" + newvel + " remain=" + newdist+"\n");
}
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
if (velocity < 0) {
// 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
newVelocity = 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. Perhaps we should decelerate? If not, we should accelerate instead
// 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 = 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 are accelerating
newVelocity = speed + Rules.ACCELERATION;
}
}
// 0 <= velocity <= max. velocity
newVelocity = Math.min(currentCommands.getMaxVelocity(), Math.abs(newVelocity));
// 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; }
}