This source code is also included in the bot jar file: http://www.robocoderepository.com/Controller.jsp?submitAction=downloadClass&id=1744
package pez.mini;
import robocode.*;
import robocode.util.Utils;
import java.awt.geom.*;
import java.awt.Color;
import java.util.*;
import java.util.zip.*;
import java.io.*;
// VertiLeach, by PEZ. Stays close to you and follows your vertical movements
//
// This code is released under the RoboWiki Public Code Licence (RWPCL), datailed on:
// http://robowiki.dyndns.org/?RWPCL
//
// Code home page: http://robowiki.dyndns.org/?VertiLeach/Code
//
// $Id: VertiLeach.java,v 1.5 2003/10/26 14:32:37 peter Exp $
public class VertiLeach extends AdvancedRobot {
private static final double MAX_VELOCITY = 8;
private static final double DEFAULT_DISTANCE = 300;
private static final double DEFAULT_BULLET_POWER = 3.0;
private static final double WALL_MARGIN = 50;
private static final int MAX_FACTOR_VISITS = 255;
private static final int DIRECTION_SEGMENTS = 3;
private static final int VERTICAL_SEGMENTS = 11;
private static final int AIM_FACTORS = 17;
private static Point2D robotLocation = new Point2D.Double();
private static Point2D oldRobotLocation = new Point2D.Double();
private static Point2D oldEnemyLocation = new Point2D.Double();
private static Point2D enemyLocation = new Point2D.Double();
private static Rectangle2D fieldRectangle;
private static double robotEnergy;
private static String enemyName = "";
private static double enemyDistance;
private static double enemyEnergy;
private static double enemyAbsoluteBearing;
private static double maxEnemyBearing;
private static double deltaBearing;
private static double yOffset;
private static int[][][] aimFactors;
private int[] currentAimFactors;
private Point2D robotDestination = null;
private boolean shouldRam;
public void run() {
fieldRectangle = new Rectangle2D.Double(0, 0 , getBattleFieldWidth(), getBattleFieldHeight());
setColors(Color.red.darker().darker(), Color.green.darker().darker(), Color.gray.darker().darker());
setAdjustGunForRobotTurn(true);
setAdjustRadarForGunTurn(true);
do {
turnRadarRightRadians(Double.POSITIVE_INFINITY);
} while (true);
}
public void onScannedRobot(ScannedRobotEvent e) {
if (enemyName == "") {
enemyName = e.getName();
restoreFactors();
}
oldRobotLocation.setLocation(robotLocation);
robotLocation.setLocation(getX(), getY());
enemyAbsoluteBearing = getHeadingRadians() + e.getBearingRadians();
enemyDistance = e.getDistance();
oldEnemyLocation.setLocation(enemyLocation);
toLocation(enemyAbsoluteBearing, enemyDistance, robotLocation, enemyLocation);
double delta = enemyEnergy - e.getEnergy();
if (delta >= 0.1 && delta <= 3.0) {
yOffset = 150 * Math.random() - 75;
}
enemyEnergy = e.getEnergy();
robotEnergy = getEnergy();
shouldRam = enemyEnergy == 0 || (enemyEnergy < 0.3 && robotEnergy > enemyEnergy * 11);
move();
deltaBearing = Utils.normalRelativeAngle(absoluteBearing(oldRobotLocation, enemyLocation) -
absoluteBearing(oldRobotLocation, oldEnemyLocation));
double bulletPower = Math.min(robotEnergy / 5, Math.min(enemyEnergy / 4, DEFAULT_BULLET_POWER));
maxEnemyBearing = Math.abs(Math.asin(MAX_VELOCITY / (bulletVelocity(bulletPower))));
currentAimFactors = aimFactors[aimDirectionSegment()]
[Math.min((int)(enemyLocation.getY() / (getBattleFieldHeight() / VERTICAL_SEGMENTS)), VERTICAL_SEGMENTS - 1)];
setTurnGunRightRadians(Utils.normalRelativeAngle(
enemyAbsoluteBearing + maxEnemyBearing * sign(deltaBearing) * mostVisitedFactor() - getGunHeadingRadians()));
if (!shouldRam && (robotEnergy > 1.5 || enemyDistance < 200)) {
if (setFireBullet(bulletPower) != null && bulletPower > 0.9) {
addCustomEvent(new Wave(bulletVelocity(bulletPower)));
}
}
setTurnRadarRightRadians(Utils.normalRelativeAngle(enemyAbsoluteBearing - getRadarHeadingRadians()) * 2);
}
public void onWin(WinEvent e) {
saveFactors();
}
public void onDeath(DeathEvent e) {
saveFactors();
}
private void move() {
double X = enemyLocation.getX() + sign(getX() - enemyLocation.getX()) * (shouldRam ? 0 : DEFAULT_DISTANCE);;
robotDestination = new Point2D.Double(X, enemyLocation.getY() + yOffset);
translateInsideField(robotDestination, WALL_MARGIN);
goTo(robotDestination);
}
void goTo(Point2D destination) {
double angle = Utils.normalRelativeAngle(absoluteBearing(robotLocation, destination) - getHeadingRadians());
int direction = 1;
if (Math.abs(angle) > Math.PI / 2) {
angle += Math.acos(direction = -1);
}
setTurnRightRadians(Utils.normalRelativeAngle(angle));
setAhead(robotLocation.distance(destination) * direction);
}
double mostVisitedFactor() {
int mostVisited = (AIM_FACTORS - 1) / 2;
for (int i = 0; i < AIM_FACTORS; i++) {
if (currentAimFactors[i] > currentAimFactors[mostVisited]) {
mostVisited = i;
}
}
return (mostVisited - (AIM_FACTORS - 1D) / 2D) / ((AIM_FACTORS - 1D) / 2D);
}
void registerFactorVisit(int[] factors, int index) {
if (factors[index] < MAX_FACTOR_VISITS) {
factors[index]++;
}
else {
decrementOtherFactors(factors, index);
}
}
void decrementOtherFactors(int[] factors, int index) {
for (int i = 0, numFactors = factors.length; i < numFactors; i++) {
if (i != index && factors[i] > 0) {
factors[i]--;
}
}
}
private int aimDirectionSegment() {
double delta = enemyLocation.getY() - oldEnemyLocation.getY();
if (delta < 0) {
return 0;
}
else if (delta > 0) {
return 2;
}
return 1;
}
private void translateInsideField(Point2D point, double margin) {
point.setLocation(Math.max(margin, Math.min(fieldRectangle.getWidth() - margin, point.getX())),
Math.max(margin, Math.min(fieldRectangle.getHeight() - margin, point.getY())));
}
private double bulletVelocity(double power) {
return 20 - 3 * power;
}
private int sign(double v) {
return v > 0 ? 1 : -1;
}
private void toLocation(double angle, double length, Point2D sourceLocation, Point2D targetLocation) {
targetLocation.setLocation(sourceLocation.getX() + Math.sin(angle) * length,
sourceLocation.getY() + Math.cos(angle) * length);
}
private double absoluteBearing(Point2D source, Point2D target) {
return Math.atan2(target.getX() - source.getX(), target.getY() - source.getY());
}
void restoreFactors() {
try {
ZipInputStream zipin = new ZipInputStream(new
FileInputStream(getDataFile(enemyName + ".zip")));
zipin.getNextEntry();
ObjectInputStream in = new ObjectInputStream(zipin);
aimFactors = (int[][][])in.readObject();
in.close();
}
catch (Exception e) {
aimFactors = new int[DIRECTION_SEGMENTS][VERTICAL_SEGMENTS][AIM_FACTORS];
}
}
void saveFactors() {
try {
ZipOutputStream zipout = new ZipOutputStream(new RobocodeFileOutputStream(getDataFile(enemyName + ".zip")));
zipout.putNextEntry(new ZipEntry("aimFactors"));
ObjectOutputStream out = new ObjectOutputStream(zipout);
out.writeObject(aimFactors);
out.flush();
zipout.closeEntry();
out.close();
}
catch (IOException e) {
}
}
class Wave extends Condition {
private long wTime;
private double bulletVelocity;
private double bearingDelta;
private Point2D oldRLocation = new Point2D.Double();
private Point2D oldELocation = new Point2D.Double();
private double maxBearing;
int[] wAimFactors;
public Wave(double bulletVelocity) {
this.wTime = getTime();
this.bulletVelocity = bulletVelocity;
this.bearingDelta = deltaBearing;
this.oldRLocation.setLocation(robotLocation);
this.oldELocation.setLocation(enemyLocation);
this.maxBearing = maxEnemyBearing;
this.wAimFactors = currentAimFactors;
}
public boolean test() {
if (bulletVelocity * (getTime() - wTime) > oldRLocation.distance(enemyLocation) - 10) {
double bearingDiff = Utils.normalRelativeAngle(absoluteBearing(oldRLocation, enemyLocation) -
absoluteBearing(oldRLocation, oldELocation));
registerFactorVisit(wAimFactors, (int)Math.round(Math.max(0D, Math.min(AIM_FACTORS - 1D,
((sign(bearingDelta) * bearingDiff) / maxBearing) * (AIM_FACTORS - 1D) / 2D + (AIM_FACTORS - 1D) / 2D))));
removeCustomEvent(this);
}
return false;
}
}
}