[Home]ARAMtocles

Robo Home | Changes | Preferences | AllPages

Showing revision 8

ARAMtocles

By GrubbmGait and PEZ

What is it?

A MicroBot. The result of using Aristocles's gun on the mean RamBot GrubbmThree

It can be found here: http://www.robocoderepository.com/BotDetail.jsp?id=2864

Code

RWPCL applies.

package wiki.micro;
import robocode.*;
import robocode.util.Utils;
import java.awt.Color;
import java.awt.geom.*;
/**
 * ARAMtocles - ramming with GuessFactors
 * Gunnery of Aristocles by PEZ
 * rest of GrubbmThree by GrubbmGait (but that turns out to be very little)
 * RWPCL applies
 *
 * Revision information:
 * v0.1 20060213 Initial version, shrunk GrubbmThree and GF-gun of Aristocles.
 *               No tuning of segmentation. 726 bytes
 * v0.2 20060213 Added reverse wall segmentation. Lowered the granularity in general to 
 *               accomodate to the short learning times ramming gives you. 732 bytes
 *
 */
public class ARAMtocles extends AdvancedRobot
{
    static Rectangle2D.Double fireField;	// the shootable battlefield


    static final double MAX_DISTANCE = 300;
    static final double MAX_BULLET_POWER = 3.0;
    static final double BULLET_POWER = 1.9;
    static final double WALL_MARGIN = 18;

    static final int DISTANCE_INDEXES = 3;
    static final int VELOCITY_INDEXES = 5;
    static final int LAST_VELOCITY_INDEXES = 5;
    static final int WALL_INDEXES = 3;
    static final int DECCEL_TIME_INDEXES = 5;
    static final int AIM_FACTORS = 33;
    static final int MIDDLE_FACTOR = (AIM_FACTORS - 1) / 2;

    static Point2D enemyLocation;
    static double enemyVelocity;
    static int timeSinceDeccel;
    static double bearingDirection;
    static double enemyDistance;
    static int[][][][][][][] aimFactors = new int[DISTANCE_INDEXES][VELOCITY_INDEXES][LAST_VELOCITY_INDEXES][DECCEL_TIME_INDEXES][WALL_INDEXES][WALL_INDEXES][AIM_FACTORS];

    /**
     * run: ARAMtocles default behavior
     */
    public void run() {

	setColors( Color.red, Color.blue, Color.yellow);

	fireField = new Rectangle2D.Double( WALL_MARGIN, WALL_MARGIN, getBattleFieldWidth() - WALL_MARGIN * 2, getBattleFieldHeight() - WALL_MARGIN * 2);

	// Let gun and radar move independently
	setAdjustGunForRobotTurn( true);
	setAdjustRadarForGunTurn( true);

	// mainloop
	do {
	    turnRadarRight( Double.NEGATIVE_INFINITY);
	} while(true);
    }

    /**
     * onScannedRobot: What to do when you see another robot
     */
    public void onScannedRobot(ScannedRobotEvent e) {

	double tmpbearing = getHeadingRadians() + e.getBearingRadians();
	double turnAngle;

	// Lock target with radar
	setTurnRadarRightRadians( 2.2 * Utils.normalRelativeAngle( tmpbearing - getRadarHeadingRadians()));

	// perform Aristocles targeting
	Wave wave = new Wave();
	double enemyAbsoluteBearing = getHeadingRadians() + e.getBearingRadians();
	enemyLocation = project(wave.wGunLocation = new Point2D.Double(getX(), getY()), enemyAbsoluteBearing, enemyDistance = e.getDistance());

	int lastVelocityIndex = (int)Math.abs(enemyVelocity) / 2;
	int velocityIndex = (int)Math.abs((enemyVelocity = e.getVelocity()) / 2);
	if (velocityIndex < lastVelocityIndex) {
	    timeSinceDeccel = 0;
	}

	if (enemyVelocity != 0) {
	    bearingDirection = enemyVelocity * Math.sin(e.getHeadingRadians() - enemyAbsoluteBearing) > 0 ?
		0.7 / (double)MIDDLE_FACTOR : -0.7 / (double)MIDDLE_FACTOR;
	}
	wave.wBearingDirection = bearingDirection;

	int distanceIndex = (int)Math.min(DISTANCE_INDEXES - 1, enemyDistance / (MAX_DISTANCE / DISTANCE_INDEXES));
	wave.wBulletPower = enemyDistance > 120 ? BULLET_POWER : MAX_BULLET_POWER;

	wave.wAimFactors = aimFactors[distanceIndex][velocityIndex][lastVelocityIndex][Math.min(DECCEL_TIME_INDEXES - 4, timeSinceDeccel++ / 13)]
	    [wallIndex(wave, 1)][wallIndex(wave, -1)];

	wave.wBearing = enemyAbsoluteBearing;

	int mostVisited = MIDDLE_FACTOR, i = AIM_FACTORS;
	do  {
	    if (wave.wAimFactors[--i] > wave.wAimFactors[mostVisited]) {
		mostVisited = i;
	    }
	} while (i > 0);
	// end of Aristocles gun

	// Turn gun (still Aristocles, but keep tmpbearing for movement)
	tmpbearing = enemyAbsoluteBearing + wave.wBearingDirection * (mostVisited - MIDDLE_FACTOR);
        setTurnGunRightRadians( Utils.normalRelativeAngle( tmpbearing - getGunHeadingRadians()));

	// Aristocles
	setFire(wave.wBulletPower);
	if (getEnergy() >= 0) {
	    addCustomEvent(wave);
	}
	// GT: Move towards target
	turnAngle = Utils.normalRelativeAngle( tmpbearing - getHeadingRadians());
	setTurnRightRadians( Math.atan( Math.tan( turnAngle)));
	setAhead( Double.POSITIVE_INFINITY * Math.cos( turnAngle));

	// Helps in melee to lock onto nearest target.
	//		clearAllEvents();
    }


    /**
     * onWin: Show my private victory dance
     */
    public void onWin(WinEvent e)
    {
	//Victory dance	
	setTurnGunRight( Double.POSITIVE_INFINITY);
	setTurnRadarLeft( Double.POSITIVE_INFINITY);
	setTurnRight(10);
	ahead(10);
	waitFor(new RadarTurnCompleteCondition(this));
    }


    // Aristocles: helperfunctions and so
    static double bulletVelocity(double power) {
	return 20 - 3 * power;
    }

    static Point2D project(Point2D sourceLocation, double angle, double length) {
	return new Point2D.Double(sourceLocation.getX() + Math.sin(angle) * length,
		sourceLocation.getY() + Math.cos(angle) * length);
    }

    static double absoluteBearing(Point2D source, Point2D target) {
	return Math.atan2(target.getX() - source.getX(), target.getY() - source.getY());
    }

    static int wallIndex(Wave wave, double direction) {
	int wallIndex = 0;
	do {
	    wallIndex++;
	} while (wallIndex < (WALL_INDEXES) &&
	    fireField.contains(project(wave.wGunLocation, wave.wBearing + direction * wave.wBearingDirection * (double)(wallIndex * 7.5), enemyDistance)));
	return wallIndex - 1;
    }

    class Wave extends Condition {
	double wBulletPower;
	Point2D wGunLocation;
	double wBearing;
	double wBearingDirection;
	int[] wAimFactors;
	double wDistance;

	public boolean test() {
	    if ((wDistance += bulletVelocity(wBulletPower)) > wGunLocation.distance(enemyLocation) - 18) {
		try {
		    wAimFactors[(int)Math.round(((Utils.normalRelativeAngle(absoluteBearing(wGunLocation, enemyLocation) - wBearing)) /
				wBearingDirection) + MIDDLE_FACTOR)]++;
		}
		catch (Exception e) {
		}
		removeCustomEvent(this);
	    }
	    return false;
	}
    }
}

Comments

Grub, I've tried to tune the segmentations some. Mainly it was about narrowing down the distance segmentation and also using less granularity. (There's not much time to learn during a ram fight.) I also added a reverse wall segmentation, which I am not sure it helps much now that I have watched a few fights with this bot. But anyway. Can you pack this up and release on the rumble for test? -- PEZ

Its up, lets see if can do some more damage. -- GrubbmGait

Again it doesn't look too promising. It could be something is buggy with the gun now, but probably it just means the gun just isn't cut for dealing with the extreme fast learning needed here. And at those fighting distances the circular targeting might just be better than bothering with stats. -- PEZ

I think you are right, each battle only lasts between 100 and 200 ticks, so there is almost no time for learning. I expected ARAMtocles to be an improvement against the better anti-rammers as running away seems quite predictable, but it seems that that can not compensate the lesser performance in the first rounds. -- GrubbmGait

This is a bit dissapointing, but I can't make this work even with low segmentation it seems. Poor ARAM seems to be a poor rammer compared to its ancestor and cousin. I say we remove it from the rumble until we have some more ideas on how to make it work. -- PEZ

PEZ, maybe an advancing velocity segment would be useful in this bot? It seems that a rammer might create exploitable behaviour in that dimension (since the enemy will most likely be moving away from you). Just a thought. --wcsv

It might. But to me it looks like most of the fight is carried at point blank. And then the circular prediction is 100% right while even one wrong guess from the learning gun will lower performance. (I've seen ARAMtocles miss while it looks to be ramming the opponent... The guns start heated so during the time it takes for the rammer to close in it can't fire anyway. Mayvbe I even should consider using linear or circular predictions in CassiusClay when I know I am dealing with a rammer. -- PEZ


Robo Home | Changes | Preferences | AllPages
Edit revision 8 of this page | View other revisions | View current revision
Edited February 14, 2006 10:25 EST by PEZ (diff)
Search: