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