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; } }