Gouldingi/Code
Jump to navigation
Jump to search
- Gouldingi Sub-pages:
- Gouldingi - Version History - Code - Archived Talk 20030814
The full source code of a bot that for a second was #6 on Eternal Rumble One on One. For the moment it's #11.
- Code size: 1442
package pez.mini;
import robocode.*;
import java.awt.geom.*;
import java.awt.Color;
import java.util.*;
// Gouldingi, by PEZ. Small, hard to catch and sharp teeth.
//
// Gouldingi is open source under GPL-like conditions. Meaning you can use
// the code. Meaning you should feel obliged to share any improvements you do
// to the code. Meaning you must release your bots code if you directly use this
// code.
//
// Home page of this bot is: http://robowiki.dyndns.org/?Gouldingi
// The code should be available there and it is also the place for you to share any
// code improvements.
//
// $Id: Gouldingi.java,v 1.9 2003/04/18 10:08:30 peter Exp $
public class Gouldingi extends AdvancedRobot {
private static Point2D location = new Point2D.Double();
private static Point2D oldLocation = new Point2D.Double();
private static Point2D enemyLocation = new Point2D.Double();
private static Point2D oldEnemyLocation = new Point2D.Double();
private static Rectangle2D fieldRectangle;
private static double guessedHeading;
private static double enemyDistance;
private static double enemyEnergy;
private static double absoluteBearing;
private static double deltaBearing;
private static double meanOffsetFactor;
private static double meanAimFactorLeft;
private static double meanAimFactorStraight;
private static double meanAimFactorRight;
private static double velocity;
public void run() {
fieldRectangle = new Rectangle2D.Double(0, 0 , getBattleFieldWidth(), getBattleFieldHeight());
setColors(Color.gray, Color.yellow, Color.black);
setAdjustGunForRobotTurn(true);
setAdjustRadarForGunTurn(true);
turnRadarRightRadians(Double.POSITIVE_INFINITY);
while (true) {
if (Math.random() < 0.05) {
velocity = Math.min(8, Math.random() * 24);
}
setMaxVelocity(Math.abs(getTurnRemaining()) > 45 ? 0.1 : velocity);
if (getOthers() == 0) {
moveRandomly();
}
execute();
}
}
public void onScannedRobot(ScannedRobotEvent e) {
oldLocation.setLocation(location);
location.setLocation(getX(), getY());
oldEnemyLocation.setLocation(enemyLocation);
absoluteBearing = getHeading() + e.getBearing();
enemyEnergy = e.getEnergy();
enemyDistance = e.getDistance();
toLocation(absoluteBearing, enemyDistance, location, enemyLocation);
deltaBearing = normalRelativeAngle(absoluteBearing(oldLocation, enemyLocation) -
absoluteBearing(oldLocation, oldEnemyLocation));
aimGun();
moveRandomly();
if (enemyEnergy > 0 && (getEnergy() > 0.2 || enemyDistance < 150)) {
Bullet bullet = setFireBullet(bulletPower(enemyEnergy));
if (bullet != null) {
addCustomEvent(new CheckUpdateFactors(bullet));
}
}
setTurnRadarLeftRadians(getRadarTurnRemaining());
}
private void moveRandomly() {
if (Math.abs(getDistanceRemaining()) < Math.random() * 50) {
Point2D dLocation = new Point2D.Double();
double relativeAngle = -36 + 72 * Math.random();
double distanceExtra = 3;
double angle = absoluteBearing + 180 + relativeAngle;
if (isCornered() || enemyDistance > 600) {
distanceExtra = -1;
}
if (enemyEnergy == 0 && getOthers() == 1) {
distanceExtra = -10;
}
distanceExtra *= Math.abs(relativeAngle);
toLocation(angle, enemyDistance + distanceExtra, enemyLocation, dLocation);
if (!fieldRectangle.contains(dLocation)) {
angle = absoluteBearing + 180 - relativeAngle;
toLocation(angle, enemyDistance + distanceExtra, enemyLocation, dLocation);
}
translateInsideField(dLocation, 35);
goTo(dLocation);
}
}
private double bulletPower(double enemyEnergy) {
double power = 3;
power = Math.min(enemyEnergy / 4, power);
power = Math.min(getEnergy() / 3, power);
return power;
}
private void aimGun() {
double guessedDistance = location.distance(enemyLocation);
double meanAimFactor = meanAimFactorStraight;
if (deltaBearing < -0.3) {
meanAimFactor = meanAimFactorLeft;
}
else if (deltaBearing > 0.3) {
meanAimFactor = meanAimFactorRight;
}
guessedHeading = absoluteBearing(location, enemyLocation);
if (Math.abs(deltaBearing) > 0.05) {
guessedHeading += deltaBearing * meanAimFactor;
}
else {
guessedHeading += meanOffsetFactor;
}
Point2D impactLocation = new Point2D.Double();
toLocation(guessedHeading, guessedDistance, location, impactLocation);
translateInsideField(impactLocation, 1);
guessedHeading = absoluteBearing(location, impactLocation);
setTurnGunRight(normalRelativeAngle(guessedHeading - getGunHeading()));
}
private void goTo(Point2D point) {
double distance = location.distance(point);
double angle = normalRelativeAngle(absoluteBearing(location, point) - getHeading());
if (Math.abs(angle) > 90) {
distance *= -1;
if (angle > 0) {
angle -= 180;
}
else {
angle += 180;
}
}
setTurnRight(angle);
setAhead(distance);
}
private boolean isCornered() {
double m = 100;
double mnX = m;
double mnY = m;
double mxX = fieldRectangle.getWidth() - m;
double mxY = fieldRectangle.getHeight() - m;
double x = location.getX();
double y = location.getY();
return ((x < mnX && (y < mnY || y > mxY)) || (x > mxX && (y < mnY || y > mxY)));
}
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 void toLocation(double angle, double length, Point2D sourceLocation, Point2D targetLocation) {
targetLocation.setLocation(sourceLocation.getX() + Math.sin(Math.toRadians(angle)) * length,
sourceLocation.getY() + Math.cos(Math.toRadians(angle)) * length);
}
private double absoluteBearing(Point2D source, Point2D target) {
return Math.toDegrees(Math.atan2(target.getX() - source.getX(), target.getY() - source.getY()));
}
private double normalRelativeAngle(double angle) {
angle = Math.toRadians(angle);
return Math.toDegrees(Math.atan2(Math.sin(angle), Math.cos(angle)));
}
public double rollingAvg(double value, double newEntry, double n, double weighting ) {
return (value * n + newEntry * weighting)/(n + weighting);
}
class CheckUpdateFactors extends Condition {
private long time;
private double bulletVelocity;
private double bulletPower;
private double bearingDelta;
private Point2D oldRLocation = new Point2D.Double();
private Point2D oldELocation = new Point2D.Double();
private double oldBearing;
public CheckUpdateFactors(Bullet bullet) {
this.time = getTime();
this.bulletVelocity = bullet.getVelocity();
this.bulletPower = bullet.getPower();
this.bearingDelta = deltaBearing;
this.oldRLocation.setLocation(location);
this.oldELocation.setLocation(enemyLocation);
this.oldBearing = absoluteBearing(oldRLocation, oldELocation);
}
public boolean test() {
if (bulletVelocity * (getTime() - time) > oldRLocation.distance(enemyLocation) - 10) {
double impactBearing = absoluteBearing(oldRLocation, enemyLocation);
double bearingDiff = normalRelativeAngle(impactBearing - oldBearing);
meanOffsetFactor = rollingAvg(meanOffsetFactor, bearingDiff, 20, bulletPower);
if (Math.abs(bearingDelta) > 0.05) {
double factor = bearingDiff / bearingDelta;
if (bearingDelta < -0.3) {
meanAimFactorLeft = rollingAvg(meanAimFactorLeft, factor, 75, bulletPower);
}
else if (bearingDelta > 0.3) {
meanAimFactorRight = rollingAvg(meanAimFactorRight, factor, 75, bulletPower);
}
else {
meanAimFactorStraight = rollingAvg(meanAimFactorStraight, factor, 75, bulletPower);
}
}
removeCustomEvent(this);
}
return false;
}
}
}