Difference between revisions of "CassiusClay/Butterfly"
(migrating from old wiki) |
RednaxelaBot (talk | contribs) m (Using <syntaxhighlight>.) |
||
Line 39: | Line 39: | ||
Here's the implementing code ([[RWPCL]]): | Here's the implementing code ([[RWPCL]]): | ||
− | < | + | <syntaxhighlight> |
Move waveImpactLocation(MovementWave closest, double direction, double maxVelocity) { | Move waveImpactLocation(MovementWave closest, double direction, double maxVelocity) { | ||
double currentDirection = robotOrbitDirection(closest.gunBearing(robotLocation)); | double currentDirection = robotOrbitDirection(closest.gunBearing(robotLocation)); | ||
Line 64: | Line 64: | ||
return new Move(impactLocation, smoothed.smoothing, smoothed.wantedEvasion, smoothed.oldDistance, impactLocation.distance(enemyLocation)); | return new Move(impactLocation, smoothed.smoothing, smoothed.wantedEvasion, smoothed.oldDistance, impactLocation.distance(enemyLocation)); | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
The BackAsFront functions there looks like so: | The BackAsFront functions there looks like so: | ||
− | < | + | <syntaxhighlight> |
public static double backAsFrontTurn(double newHeading, double oldHeading) { | public static double backAsFrontTurn(double newHeading, double oldHeading) { | ||
return Math.tan(newHeading - oldHeading); | return Math.tan(newHeading - oldHeading); | ||
Line 75: | Line 75: | ||
return sign(Math.cos(newHeading - oldHeading)); | return sign(Math.cos(newHeading - oldHeading)); | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
It's the same functions I use to move my bot around [[Jamougha]] style: | It's the same functions I use to move my bot around [[Jamougha]] style: | ||
− | < | + | <syntaxhighlight> |
double newHeading = PUtils.absoluteBearing(robotLocation, destination); | double newHeading = PUtils.absoluteBearing(robotLocation, destination); | ||
double oldHeading = robot.getHeadingRadians(); | double oldHeading = robot.getHeadingRadians(); | ||
robot.setAhead(PUtils.backAsFrontDirection(newHeading, oldHeading) * 50); | robot.setAhead(PUtils.backAsFrontDirection(newHeading, oldHeading) * 50); | ||
robot.setTurnRightRadians(PUtils.backAsFrontTurn(newHeading, oldHeading)); | robot.setTurnRightRadians(PUtils.backAsFrontTurn(newHeading, oldHeading)); | ||
− | </ | + | </syntaxhighlight> |
[[Category:Movement Implementations]] | [[Category:Movement Implementations]] |
Revision as of 09:22, 1 July 2010
Butterfly by PEZ - The CassiusClay (pluggable) movement
Butterfly is all about WaveSurfing. It's the result of letting the Pugilist movement grow out of its MiniBot constraints. The design is pretty simple:
- Every scan create an EnemyWave
- If the enemy fired the tick before then mark the wave as "surfable"
- If a bullet hits my bot then
- Find the wave that is in the passing
- Find out what GuessFactor we were hit on
- Update the stat buffers with this knowledge
- Every scan:
- check where (what guess factor) we would impact with the closest surfable wave were we to:
- move fully forward
- move fully reverse
- hit the breaks
- For each wave in the air
- Examine how often we've been hit in each of these destination options compared to all other guess factors
- Weigh together the results of all surfable waves with the closest one being the most important
- Go for the option where we've been hit the least (or where it seems the least dangerous to move)
- check where (what guess factor) we would impact with the closest surfable wave were we to:
Simple enough, huh? One of those steps is a bit complicated though - step 2.1. It involves predicting our own movement some ticks in the future. This can be done in many ways. Pugilist does it in a pretty sloppy manner. CassiusClay is a bit more precise. In fact as of version 1.9.9.00g (g for gamma, my first test version) not only considers how fast CC can accelerate/deccelerate. It also tries to take into account the maximum turn angle it can do at a given velocity. Here's the scheme for the predictor:
Inputs
- The closest "surfable" EnemyWave
- The desired orbit direction
- The desired target velocity (between 0 and 8 inclusive)
Action
- Grab the current heading
- Grab the current velocity (relative to the desired orbit direction)
- Do
- Calculate a WallSmoothed position in the desired orbit direction
- Calculate absolute bearing to this position
- Adjust the velocity according to Robocode physics (aiming for the target velocity)
- Calculate how much we would need to turn the bot to get the right heading
- Adjust our virtual heading while considering BackAsFront and the maximum turn rate at the current virtual velocity
- Calculate the position of the bot 1 tick into the future using the new virtual heading and velocity
- Advance the wave 1 tick into the future
- Until the wave impacts with the predicted bot position
Here's the implementing code (RWPCL):
Move waveImpactLocation(MovementWave closest, double direction, double maxVelocity) {
double currentDirection = robotOrbitDirection(closest.gunBearing(robotLocation));
double v = Math.abs(robot.getVelocity()) * PUtils.sign(direction);
double h = robot.getHeadingRadians();
Point2D orbitCenter = orbitCenter(closest);
Point2D impactLocation = new Point2D.Double(robot.getX(), robot.getY());
Move smoothed;
int time = 0;
do {
smoothed = wallSmoothedDestination(impactLocation, orbitCenter, currentDirection * direction);
double wantedHeading = PUtils.absoluteBearing(impactLocation, smoothed.location);
h += PUtils.backAsFrontDirection(wantedHeading, h) < 0 ? Math.PI : 0.0;
if (v < maxVelocity) {
v = Math.min(maxVelocity, v + (v < 0 ? 2 : 1));
}
else {
v = Math.max(maxVelocity, v - 2);
}
double maxTurn = Math.toRadians(MAX_TURN_RATE - 0.75 * Math.abs(v));
h += PUtils.minMax(PUtils.backAsFrontTurn(wantedHeading, h), -maxTurn, maxTurn);
impactLocation = PUtils.project(impactLocation, h, v);
} while (closest.distanceFromTarget(impactLocation, time++) > 18);
return new Move(impactLocation, smoothed.smoothing, smoothed.wantedEvasion, smoothed.oldDistance, impactLocation.distance(enemyLocation));
}
The BackAsFront functions there looks like so:
public static double backAsFrontTurn(double newHeading, double oldHeading) {
return Math.tan(newHeading - oldHeading);
}
public static double backAsFrontDirection(double newHeading, double oldHeading) {
return sign(Math.cos(newHeading - oldHeading));
}
It's the same functions I use to move my bot around Jamougha style:
double newHeading = PUtils.absoluteBearing(robotLocation, destination);
double oldHeading = robot.getHeadingRadians();
robot.setAhead(PUtils.backAsFrontDirection(newHeading, oldHeading) * 50);
robot.setTurnRightRadians(PUtils.backAsFrontTurn(newHeading, oldHeading));