FuturePosition
Jump to navigation
Jump to search
Precise Prediction code by Albert, used by many Wave Surfers.
The parameters are like follows:
- steps - number of ticks you want to predict.
- b - is your robot. Just use "this".
- maxVel and maxTurnRate - the maximum velocity and turn rate allowed. Use them only if you have used setMaxVelocity() or setMaxTurnRate()
package apv; import java.awt.geom.Point2D; import java.util.Vector; import robocode.util.*; import robocode.*; public class MovSim { private double systemMaxTurnRate = Math.toRadians(10.0); private double systemMaxVelocity = 8.0; private double maxBraking = 2.0; private double maxAcceleration = 1.0; public double defaultMaxTurnRate = 10.0; public double defaultMaxVelocity = 8.0; public MovSim() {}; public MovSimStat[] futurePos(int steps, AdvancedRobot b) { return futurePos(steps, b, defaultMaxVelocity, defaultMaxTurnRate); } public MovSimStat[] futurePos(int steps, AdvancedRobot b, double maxVel, double maxTurnRate) { return futurePos(steps, b.getX(), b.getY(), b.getVelocity(), maxVel, b.getHeadingRadians(), b.getDistanceRemaining(), b.getTurnRemainingRadians(), maxTurnRate, b.getBattleFieldWidth(), b.getBattleFieldHeight()); } private MovSimStat[] futurePos(int steps, double x, double y, double velocity, double maxVelocity, double heading, double distanceRemaining, double angleToTurn, double maxTurnRate, double battleFieldW, double battleFieldH) { //maxTurnRate in degrees MovSimStat[] pos = new MovSimStat[steps]; double acceleration = 0; boolean slowingDown = false; double moveDirection; maxTurnRate = Math.toRadians(maxTurnRate); if (distanceRemaining == 0) moveDirection = 0; else if (distanceRemaining < 0.0) moveDirection = -1; else moveDirection = 1; //heading, accel, velocity, distance for (int i=0; i<steps; i++) { //heading double lastHeading = heading; double turnRate = Math.min(maxTurnRate, ((0.4 + 0.6 * (1.0 - (Math.abs(velocity) / systemMaxVelocity))) * systemMaxTurnRate)); if (angleToTurn > 0.0) { if (angleToTurn < turnRate) { heading += angleToTurn; angleToTurn = 0.0; } else { heading += turnRate; angleToTurn -= turnRate; } } else if (angleToTurn < 0.0) { if (angleToTurn > -turnRate) { heading += angleToTurn; angleToTurn = 0.0; } else { heading -= turnRate; angleToTurn += turnRate; } } heading = Utils.normalAbsoluteAngle(heading); //movement if (distanceRemaining != 0.0 || velocity != 0.0) { //lastX = x; lastY = y; if (!slowingDown && moveDirection == 0) { slowingDown = true; if (velocity > 0.0) moveDirection = 1; else if (velocity < 0.0) moveDirection = -1; else moveDirection = 0; } double desiredDistanceRemaining = distanceRemaining; if (slowingDown) { if (moveDirection == 1 && distanceRemaining < 0.0) desiredDistanceRemaining = 0.0; else if (moveDirection == -1 && distanceRemaining > 1.0) desiredDistanceRemaining = 0.0; } double slowDownVelocity = (double) (int) (maxBraking / 2.0 * ((Math.sqrt(4.0 * Math.abs(desiredDistanceRemaining)+ 1.0)) - 1.0)); if (moveDirection == -1) slowDownVelocity = -slowDownVelocity; if (!slowingDown) { if (moveDirection == 1) { if (velocity < 0.0) acceleration = maxBraking; else acceleration = maxAcceleration; if (velocity + acceleration > slowDownVelocity) slowingDown = true; } else if (moveDirection == -1) { if (velocity > 0.0) acceleration = -maxBraking; else acceleration = -maxAcceleration; if (velocity + acceleration < slowDownVelocity) slowingDown = true; } } if (slowingDown) { if (distanceRemaining != 0.0 && Math.abs(velocity) <= maxBraking && Math.abs(distanceRemaining) <= maxBraking) slowDownVelocity = distanceRemaining; double perfectAccel = slowDownVelocity - velocity; if (perfectAccel > maxBraking) perfectAccel = maxBraking; else if (perfectAccel < -maxBraking) perfectAccel = -maxBraking; acceleration = perfectAccel; } if (velocity > maxVelocity || velocity < -maxVelocity) acceleration = 0.0; velocity += acceleration; if (velocity > maxVelocity) velocity -= Math.min(maxBraking, velocity - maxVelocity); if (velocity < -maxVelocity) velocity += Math.min(maxBraking, -velocity - maxVelocity); double dx = velocity * Math.sin(heading); double dy = velocity * Math.cos(heading); x += dx; y += dy; //boolean updateBounds = false; //if (dx != 0.0 || dy != 0.0) updateBounds = true; if (slowingDown && velocity == 0.0) { distanceRemaining = 0.0; moveDirection = 0; slowingDown = false; acceleration = 0.0; } //if (updateBounds) updateBoundingBox(); distanceRemaining -= velocity; if (x<18 || y<18 || x>battleFieldW-18 || y>battleFieldH-18) { distanceRemaining = 0; angleToTurn = 0; velocity = 0; moveDirection = 0; x = Math.max(18,Math.min(battleFieldW-18,x)); y = Math.max(18,Math.min(battleFieldH-18,y)); } } //add position pos[i] = new MovSimStat(x,y,velocity,heading,Utils.normalRelativeAngle(heading-lastHeading)); } return pos; } }
package apv; public class MovSimStat { public double x; public double y; public double v; public double h; public double w; public MovSimStat(double x, double y, double v, double h, double w) { this.x = x; this.y = y; this.v = v; this.h = h; this.w = w; } }