[Home]VertiLeach/Code

Robo Home | VertiLeach | Changes | Preferences | AllPages

Difference (from prior author revision) (minor diff)

Changed: 1c1,6
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.

Changed: 17c22
// http://robowiki.dyndns.org/?RWPCL
// http://robowiki.net/?RWPCL

Changed: 19c24
// Code home page: http://robowiki.dyndns.org/?VertiLeach/Code
// Code home page: http://robowiki.net/?VertiLeach/Code

Changed: 21c26
// $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 $

Changed: 26c31
private static final double DEFAULT_BULLET_POWER = 3.0;
private static final double DEFAULT_BULLET_POWER = 2.8;

Removed: 28d32
private static final int MAX_FACTOR_VISITS = 255;

Changed: 30,31c34,35
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;

Changed: 33,34c37,38
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();

Removed: 36d39
private static Rectangle2D fieldRectangle;

Added: 41a45,47
private static double enemyY;
private static double enemyYNormal;
private static double lastEnemyYNormal?;

Added: 43a50
private static int bearingDirection;

Added: 44a52
private static double midY;

Added: 45a54,55
private static double bulletPower = DEFAULT_BULLET_POWER;
private static int mostVisited;

Removed: 47,48d56
private Point2D robotDestination = null;
private boolean shouldRam;

Removed: 51d58
fieldRectangle = new Rectangle2D.Double(0, 0 , getBattleFieldWidth?(), getBattleFieldHeight?());

Added: 54a62
midY = getBattleFieldHeight?() / 2;

Changed: 66c74
oldRobotLocation?.setLocation(robotLocation);
lastRobotLocation?.setLocation(robotLocation);

Changed: 70c78
oldEnemyLocation?.setLocation(enemyLocation);
lastEnemyLocation?.setLocation(enemyLocation);

Changed: 73,75c81,93
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);
}

Removed: 79,86d96
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))));

Changed: 88,89c98,99
currentAimFactors? = aimFactors[aimDirectionSegment?()]
[Math.min((int)(enemyLocation.getY() / (getBattleFieldHeight?() / VERTICAL_SEGMENTS)), VERTICAL_SEGMENTS - 1)];
if (getTime() > 8) {
move();

Changed: 91,98c101,121
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());
}
}

Changed: 112,114c135,147
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;
}
}

Changed: 120,124c153,155
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);

Added: 127a159,162
int side() {
return sign(getX() - enemyLocation.getX());
}


Changed: 129c164
int mostVisited = (AIM_FACTORS - 1) / 2;
mostVisited = (AIM_FACTORS - 1) / 2;

Changed: 135c170
return (mostVisited - (AIM_FACTORS - 1D) / 2D) / ((AIM_FACTORS - 1D) / 2D);
return ((mostVisited + 0.5) / AIM_FACTORS) * 2 - 1;

Changed: 139,144c174,188
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]++;
}

Changed: 147,152c191,193
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;

Changed: 156,157c197,198
double delta = enemyLocation.getY() - oldEnemyLocation?.getY();
if (delta < 0) {
double yDelta = enemyYNormal - lastEnemyYNormal?;
if (yDelta < 0) {

Changed: 160c201
else if (delta > 0) {
else if (yDelta > 0) {

Changed: 167,168c208,209
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())));

Changed: 191c232
FileInputStream?(getDataFile?(enemyName + ".zip")));
FileInputStream?(getDataFile?(enemyName)));

Changed: 204c245
ZipOutputStream? zipout = new ZipOutputStream?(new RobocodeFileOutputStream?(getDataFile?(enemyName + ".zip")));
ZipOutputStream? zipout = new ZipOutputStream?(new RobocodeFileOutputStream?(getDataFile?(enemyName)));

Changed: 218,222c259,264
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?;

Changed: 225c267
public Wave(double bulletVelocity) {
public Wave() {

Changed: 227,231c269,273
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?;

Added: 232a275
this.wBearingDirection? = bearingDirection;

Changed: 236,240c279,283
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));

Changed: 248c291

Comments, suggestions and questions are welcome



Comments, suggestions and questions are welcome




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:

  1. It's from a top-10 class bot in RoboRumble@Home (and top-2 class in the MiniBots class)
  2. It uses a simple GuessFactorTargeting gun
  3. 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.

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

Comments, suggestions and questions are welcome


Robo Home | VertiLeach | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited December 19, 2003 13:48 EST by PEZ (diff)
Search: