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