|
Source code for VertiLeach V 0.3, released under the RoboWiki Public Code Licence (RWPCL). |
|
Source code for VertiLeach V 0.3.3, released under the RoboWiki Public Code Licence (RWPCL). There are a couple of things that might be interesting with this code: # It's from a top-10 class bot in RoboRumble@Home (and top-2 class in the MiniBots class) # It uses a simple GuessFactorTargeting gun # Rather few lines of code. Even if it has some improvements to ask for in terms of clarity, it isn't as obfuscated as some minibot code out there. |
|
// http://robowiki.dyndns.org/?RWPCL |
|
// http://robowiki.net/?RWPCL |
|
// Code home page: http://robowiki.dyndns.org/?VertiLeach/Code |
|
// Code home page: http://robowiki.net/?VertiLeach/Code |
|
// $Id: VertiLeach.java,v 1.5 2003/10/26 14:32:37 peter Exp $ |
|
// $Id: VertiLeach.java,v 1.9 2003/12/19 00:43:56 peter Exp $ |
|
private static final double DEFAULT_BULLET_POWER = 3.0; |
|
private static final double DEFAULT_BULLET_POWER = 2.8; |
|
private static final int MAX_FACTOR_VISITS = 255; |
|
private static final int VERTICAL_SEGMENTS = 11; private static final int AIM_FACTORS = 17; |
|
private static final int VERTICAL_SEGMENTS = 9; private static final int AIM_FACTORS = 23; |
|
private static Point2D oldRobotLocation? = new Point2D.Double(); private static Point2D oldEnemyLocation? = new Point2D.Double(); |
|
private static Point2D lastRobotLocation? = new Point2D.Double(); private static Point2D lastEnemyLocation? = new Point2D.Double(); |
|
private static Rectangle2D fieldRectangle; |
|
private static double enemyY; private static double enemyYNormal; private static double lastEnemyYNormal?; |
|
private static int bearingDirection; |
|
private static double midY; |
|
private static double bulletPower = DEFAULT_BULLET_POWER; private static int mostVisited; |
|
private Point2D robotDestination = null; private boolean shouldRam; |
|
fieldRectangle = new Rectangle2D.Double(0, 0 , getBattleFieldWidth?(), getBattleFieldHeight?()); |
|
midY = getBattleFieldHeight?() / 2; |
|
oldRobotLocation?.setLocation(robotLocation); |
|
lastRobotLocation?.setLocation(robotLocation); |
|
oldEnemyLocation?.setLocation(enemyLocation); |
|
lastEnemyLocation?.setLocation(enemyLocation); |
|
double delta = enemyEnergy - e.getEnergy(); if (delta >= 0.1 && delta <= 3.0) { yOffset = 150 * Math.random() - 75; |
|
lastEnemyYNormal? = enemyYNormal; enemyYNormal = enemyY = enemyLocation.getY(); if (enemyY > midY) { enemyYNormal = midY - (enemyY - midY); } double eDelta = enemyEnergy - e.getEnergy(); if (eDelta >= 0.1 && eDelta <= 3.0) { double maxOffset = 175 + (DEFAULT_DISTANCE - Math.min(DEFAULT_DISTANCE, enemyDistance)); yOffset = 2 * maxOffset * Math.random() - maxOffset; if (aimVerticalSegment?() < 1) { yOffset *= 0.5 * Math.abs(yOffset) * sign(midY - enemyY); } |
|
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)]; |
|
if (getTime() > 8) { move(); |
|
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))); } } |
|
deltaBearing = Utils.normalRelativeAngle(absoluteBearing(lastRobotLocation?, enemyLocation) - absoluteBearing(lastRobotLocation?, lastEnemyLocation?)); if (deltaBearing < 0) { bearingDirection = -1; } else if (deltaBearing > 0) { bearingDirection = 1; } bulletPower = (enemyDistance < 2 * DEFAULT_DISTANCE / 3) ? 3.0 : DEFAULT_BULLET_POWER; bulletPower = Math.min(robotEnergy / 5, Math.min(enemyEnergy / 4, bulletPower)); maxEnemyBearing? = Math.abs(Math.asin(MAX_VELOCITY / (bulletVelocity(bulletPower)))); currentAimFactors? = aimFactors[aimDirectionSegment?()][aimVerticalSegment?()]; setTurnGunRightRadians?(Utils.normalRelativeAngle( enemyAbsoluteBearing? + maxEnemyBearing? * bearingDirection * mostVisitedFactor?() - getGunHeadingRadians?())); if (setFireBullet(bulletPower) != null && bulletPower == DEFAULT_BULLET_POWER) { addCustomEvent(new Wave()); } } |
|
double X = enemyLocation.getX() + sign(getX() - enemyLocation.getX()) * (shouldRam ? 0 : DEFAULT_DISTANCE);; robotDestination = new Point2D.Double(X, enemyLocation.getY() + yOffset); translateInsideField?(robotDestination, WALL_MARGIN); |
|
Point2D robotDestination = null; double direction = 1; for (int i = 0; i < 2; i++) { double X = enemyLocation.getX() + direction * side() * DEFAULT_DISTANCE; robotDestination = new Point2D.Double(X, enemyLocation.getY() + yOffset); translateInsideField?(robotDestination, WALL_MARGIN); if (Math.abs(X - robotDestination.getX()) < 100) { break; } else { direction *= -1; } } |
|
int direction = 1; if (Math.abs(angle) > Math.PI / 2) { angle += Math.acos(direction = -1); } setTurnRightRadians?(Utils.normalRelativeAngle(angle)); |
|
double turnAngle = Math.atan(Math.tan(angle)); int direction = angle == turnAngle ? 1 : - 1; setTurnRightRadians?(turnAngle); |
|
int side() { return sign(getX() - enemyLocation.getX()); } |
|
int mostVisited = (AIM_FACTORS - 1) / 2; |
|
mostVisited = (AIM_FACTORS - 1) / 2; |
|
return (mostVisited - (AIM_FACTORS - 1D) / 2D) / ((AIM_FACTORS - 1D) / 2D); |
|
return ((mostVisited + 0.5) / AIM_FACTORS) * 2 - 1; |
|
if (factors[index] < MAX_FACTOR_VISITS) { factors[index]++; } else { decrementOtherFactors?(factors, index); } |
|
index = Math.min(Math.max(0, index), AIM_FACTORS - 1); if (factors[mostVisited] > 100) { for (int i = 0; i < AIM_FACTORS; i++) { if (factors[i] > 1) { factors[i] -= 2; } } } factors[index] += 2; if (index < AIM_FACTORS - 1) { factors[index + 1]++; } if (index > 0) { factors[index - 1]++; } |
|
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 aimVerticalSegment?() { int segment = Math.min((int)(enemyYNormal / (midY / VERTICAL_SEGMENTS)), VERTICAL_SEGMENTS - 1); return segment; |
|
double delta = enemyLocation.getY() - oldEnemyLocation?.getY(); if (delta < 0) { |
|
double yDelta = enemyYNormal - lastEnemyYNormal?; if (yDelta < 0) { |
|
else if (delta > 0) { |
|
else if (yDelta > 0) { |
|
point.setLocation(Math.max(margin, Math.min(fieldRectangle.getWidth() - margin, point.getX())), Math.max(margin, Math.min(fieldRectangle.getHeight() - margin, point.getY()))); |
|
point.setLocation(Math.max(margin, Math.min(getBattleFieldWidth?() - margin, point.getX())), Math.max(margin, Math.min(getBattleFieldHeight?() - margin, point.getY()))); |
|
FileInputStream?(getDataFile?(enemyName + ".zip"))); |
|
FileInputStream?(getDataFile?(enemyName))); |
|
ZipOutputStream? zipout = new ZipOutputStream?(new RobocodeFileOutputStream?(getDataFile?(enemyName + ".zip"))); |
|
ZipOutputStream? zipout = new ZipOutputStream?(new RobocodeFileOutputStream?(getDataFile?(enemyName))); |
|
private double bulletVelocity; private double bearingDelta; private Point2D oldRLocation = new Point2D.Double(); private Point2D oldELocation = new Point2D.Double(); private double maxBearing; |
|
private double wBulletVelocity?; private double wBearingDelta?; private Point2D wRobotLocation? = new Point2D.Double(); private Point2D wEnemyLocation? = new Point2D.Double(); private int wBearingDirection?; private double wMaxBearing?; |
|
public Wave(double bulletVelocity) { |
|
public Wave() { |
|
this.bulletVelocity = bulletVelocity; this.bearingDelta = deltaBearing; this.oldRLocation.setLocation(robotLocation); this.oldELocation.setLocation(enemyLocation); this.maxBearing = maxEnemyBearing?; |
|
this.wBulletVelocity? = bulletVelocity(bulletPower); this.wBearingDelta? = deltaBearing; this.wRobotLocation?.setLocation(robotLocation); this.wEnemyLocation?.setLocation(enemyLocation); this.wMaxBearing? = maxEnemyBearing?; |
|
this.wBearingDirection? = bearingDirection; |
|
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)))); |
|
if (wBulletVelocity? * (getTime() - wTime) > wRobotLocation?.distance(enemyLocation) - 10) { double bearingDiff = Utils.normalRelativeAngle(absoluteBearing(wRobotLocation?, enemyLocation) - absoluteBearing(wRobotLocation?, wEnemyLocation?)); registerFactorVisit?(wAimFactors?, (int)Math.round(((((wBearingDirection? * bearingDiff) / wMaxBearing?) + 1) / 2) * wAimFactors?.length)); |
Comments, suggestions and questions are welcome |
Comments, suggestions and questions are welcome |
There are a couple of things that might be interesting with this code:
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.net/?RWPCL
//
// Code home page: http://robowiki.net/?VertiLeach/Code
//
// $Id: VertiLeach.java,v 1.9 2003/12/19 00:43:56 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 = 2.8;
private static final double WALL_MARGIN = 50;
private static final int DIRECTION_SEGMENTS = 3;
private static final int VERTICAL_SEGMENTS = 9;
private static final int AIM_FACTORS = 23;
private static Point2D robotLocation = new Point2D.Double();
private static Point2D lastRobotLocation = new Point2D.Double();
private static Point2D lastEnemyLocation = new Point2D.Double();
private static Point2D enemyLocation = new Point2D.Double();
private static double robotEnergy;
private static String enemyName = "";
private static double enemyDistance;
private static double enemyEnergy;
private static double enemyAbsoluteBearing;
private static double enemyY;
private static double enemyYNormal;
private static double lastEnemyYNormal;
private static double maxEnemyBearing;
private static double deltaBearing;
private static int bearingDirection;
private static double yOffset;
private static double midY;
private static int[][][] aimFactors;
private static double bulletPower = DEFAULT_BULLET_POWER;
private static int mostVisited;
private int[] currentAimFactors;
public void run() {
setColors(Color.red.darker().darker(), Color.green.darker().darker(), Color.gray.darker().darker());
setAdjustGunForRobotTurn(true);
setAdjustRadarForGunTurn(true);
midY = getBattleFieldHeight() / 2;
do {
turnRadarRightRadians(Double.POSITIVE_INFINITY);
} while (true);
}
public void onScannedRobot(ScannedRobotEvent e) {
if (enemyName == "") {
enemyName = e.getName();
restoreFactors();
}
lastRobotLocation.setLocation(robotLocation);
robotLocation.setLocation(getX(), getY());
enemyAbsoluteBearing = getHeadingRadians() + e.getBearingRadians();
enemyDistance = e.getDistance();
lastEnemyLocation.setLocation(enemyLocation);
toLocation(enemyAbsoluteBearing, enemyDistance, robotLocation, enemyLocation);
lastEnemyYNormal = enemyYNormal;
enemyYNormal = enemyY = enemyLocation.getY();
if (enemyY > midY) {
enemyYNormal = midY - (enemyY - midY);
}
double eDelta = enemyEnergy - e.getEnergy();
if (eDelta >= 0.1 && eDelta <= 3.0) {
double maxOffset = 175 + (DEFAULT_DISTANCE - Math.min(DEFAULT_DISTANCE, enemyDistance));
yOffset = 2 * maxOffset * Math.random() - maxOffset;
if (aimVerticalSegment() < 1) {
yOffset *= 0.5 * Math.abs(yOffset) * sign(midY - enemyY);
}
}
enemyEnergy = e.getEnergy();
robotEnergy = getEnergy();
if (getTime() > 8) {
move();
deltaBearing = Utils.normalRelativeAngle(absoluteBearing(lastRobotLocation, enemyLocation) -
absoluteBearing(lastRobotLocation, lastEnemyLocation));
if (deltaBearing < 0) {
bearingDirection = -1;
}
else if (deltaBearing > 0) {
bearingDirection = 1;
}
bulletPower = (enemyDistance < 2 * DEFAULT_DISTANCE / 3) ? 3.0 : DEFAULT_BULLET_POWER;
bulletPower = Math.min(robotEnergy / 5, Math.min(enemyEnergy / 4, bulletPower));
maxEnemyBearing = Math.abs(Math.asin(MAX_VELOCITY / (bulletVelocity(bulletPower))));
currentAimFactors = aimFactors[aimDirectionSegment()][aimVerticalSegment()];
setTurnGunRightRadians(Utils.normalRelativeAngle(
enemyAbsoluteBearing + maxEnemyBearing * bearingDirection * mostVisitedFactor() - getGunHeadingRadians()));
if (setFireBullet(bulletPower) != null && bulletPower == DEFAULT_BULLET_POWER) {
addCustomEvent(new Wave());
}
}
setTurnRadarRightRadians(Utils.normalRelativeAngle(enemyAbsoluteBearing - getRadarHeadingRadians()) * 2);
}
public void onWin(WinEvent e) {
saveFactors();
}
public void onDeath(DeathEvent e) {
saveFactors();
}
private void move() {
Point2D robotDestination = null;
double direction = 1;
for (int i = 0; i < 2; i++) {
double X = enemyLocation.getX() + direction * side() * DEFAULT_DISTANCE;
robotDestination = new Point2D.Double(X, enemyLocation.getY() + yOffset);
translateInsideField(robotDestination, WALL_MARGIN);
if (Math.abs(X - robotDestination.getX()) < 100) {
break;
}
else {
direction *= -1;
}
}
goTo(robotDestination);
}
void goTo(Point2D destination) {
double angle = Utils.normalRelativeAngle(absoluteBearing(robotLocation, destination) - getHeadingRadians());
double turnAngle = Math.atan(Math.tan(angle));
int direction = angle == turnAngle ? 1 : - 1;
setTurnRightRadians(turnAngle);
setAhead(robotLocation.distance(destination) * direction);
}
int side() {
return sign(getX() - enemyLocation.getX());
}
double mostVisitedFactor() {
mostVisited = (AIM_FACTORS - 1) / 2;
for (int i = 0; i < AIM_FACTORS; i++) {
if (currentAimFactors[i] > currentAimFactors[mostVisited]) {
mostVisited = i;
}
}
return ((mostVisited + 0.5) / AIM_FACTORS) * 2 - 1;
}
void registerFactorVisit(int[] factors, int index) {
index = Math.min(Math.max(0, index), AIM_FACTORS - 1);
if (factors[mostVisited] > 100) {
for (int i = 0; i < AIM_FACTORS; i++) {
if (factors[i] > 1) {
factors[i] -= 2;
}
}
}
factors[index] += 2;
if (index < AIM_FACTORS - 1) {
factors[index + 1]++;
}
if (index > 0) {
factors[index - 1]++;
}
}
private int aimVerticalSegment() {
int segment = Math.min((int)(enemyYNormal / (midY / VERTICAL_SEGMENTS)), VERTICAL_SEGMENTS - 1);
return segment;
}
private int aimDirectionSegment() {
double yDelta = enemyYNormal - lastEnemyYNormal;
if (yDelta < 0) {
return 0;
}
else if (yDelta > 0) {
return 2;
}
return 1;
}
private void translateInsideField(Point2D point, double margin) {
point.setLocation(Math.max(margin, Math.min(getBattleFieldWidth() - margin, point.getX())),
Math.max(margin, Math.min(getBattleFieldHeight() - 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)));
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)));
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 wBulletVelocity;
private double wBearingDelta;
private Point2D wRobotLocation = new Point2D.Double();
private Point2D wEnemyLocation = new Point2D.Double();
private int wBearingDirection;
private double wMaxBearing;
int[] wAimFactors;
public Wave() {
this.wTime = getTime();
this.wBulletVelocity = bulletVelocity(bulletPower);
this.wBearingDelta = deltaBearing;
this.wRobotLocation.setLocation(robotLocation);
this.wEnemyLocation.setLocation(enemyLocation);
this.wMaxBearing = maxEnemyBearing;
this.wAimFactors = currentAimFactors;
this.wBearingDirection = bearingDirection;
}
public boolean test() {
if (wBulletVelocity * (getTime() - wTime) > wRobotLocation.distance(enemyLocation) - 10) {
double bearingDiff = Utils.normalRelativeAngle(absoluteBearing(wRobotLocation, enemyLocation) -
absoluteBearing(wRobotLocation, wEnemyLocation));
registerFactorVisit(wAimFactors, (int)Math.round(((((wBearingDirection * bearingDiff) /
wMaxBearing) + 1) / 2) * wAimFactors.length));
removeCustomEvent(this);
}
return false;
}
}
}