[Home]PugilistGL/Code

Robo Home | PugilistGL | Changes | Preferences | AllPages

Source code for PugilistGL

Never mind that all classes are suffixed "GL". It was the quickest way I could get this version to compile in the same source directory as Pugilist...

package pez.mini;
import robocode.*;
import robocode.util.Utils;
import java.util.*;
import java.awt.geom.*;
import java.awt.Color;

import robocode.robocodeGL.*; // GL
import robocode.robocodeGL.system.*; // GL

// This code is released under the RoboWiki Public Code Licence (RWPCL), datailed on:
// http://robowiki.net/?RWPCL
//
// PugilistGL, by PEZ. RobocodeGL version of Pugilist 1.3.1
// http://robowiki.net/?PugilistGL
//
// Ideas and concepts are often my own, but i have borrowed from many places too. Quite often from Jamougha and Kawigi.
//
// $Id: PugilistGL.java,v 1.31 2004/03/10 11:16:26 peter Exp $

public class PugilistGL extends AdvancedRobot {
    static final double BOT_WIDTH = 36;
    static final double MAX_VELOCITY = 8;

    static final double BATTLE_FIELD_WIDTH = 800;
    static final double BATTLE_FIELD_HEIGHT = 600;
    static final double MAX_WALL_SMOOTH_TRIES = 100;
    static final double WALL_MARGIN = 18;
    static final Rectangle2D fieldRectangle = new Rectangle2D.Double(WALL_MARGIN, WALL_MARGIN,
	    BATTLE_FIELD_WIDTH - WALL_MARGIN * 2, BATTLE_FIELD_HEIGHT - WALL_MARGIN * 2);

    static final double MAX_DISTANCE = 900;
    static final double MAX_BULLET_TRAVEL_TIME = 80;
    static final double MAX_BULLET_POWER = 3.0;
    static final double BULLET_POWER = 2.3;

    static final int FACTORS = 27;
    static final int MIDDLE_FACTOR = (FACTORS - 1) / 2;
    static final int DISTANCE_INDEXES = 5;
    static final int VELOCITY_INDEXES = 5;
    static final int LAST_VELOCITY_INDEXES = 5;
    static final int WALL_INDEXES = 2;
    static final int DECCEL_TIME_INDEXES = 6;
    static final int BULLET_POWER_INDEXES = 5;


    static Point2D robotLocation = new Point2D.Double();
    static Point2D enemyLocation = new Point2D.Double();
    static double enemyDistance;
    static int distanceIndex;
    static double enemyVelocity;
    double enemyEnergy;
    static int enemyTimeSinceDeccel;
    static double enemyBearingDirection = 0.75;
    static int[][][][][][] aimFactors = new int[DISTANCE_INDEXES][VELOCITY_INDEXES][LAST_VELOCITY_INDEXES][DECCEL_TIME_INDEXES][WALL_INDEXES][FACTORS];

    static double enemyFirePower = 2.5;
    static double robotBearingDirection = 1;
    //static int[][][][][] moveFactors = new int[DISTANCE_INDEXES][BULLET_POWER_INDEXES][WALL_INDEXES][VELOCITY_INDEXES][FACTORS];
    static int[][][][] moveFactors = new int[DISTANCE_INDEXES][BULLET_POWER_INDEXES][WALL_INDEXES][FACTORS];
    static EnemyWaveGL passingWave;
    static double visitsForward;
    static double visitsReverse;
    static double orbitDirection = 1;
    long nextDirectionChangeTime;

    public void run() {
	setAdjustRadarForGunTurn(true);
	setAdjustGunForRobotTurn(true);

	passingWave = null;

	do {
	    turnRadarRightRadians(Double.POSITIVE_INFINITY); 
	} while (true);
    }

    public void onScannedRobot(ScannedRobotEvent e) {
	WaveGL wave = new WaveGL();
	wave.robot = this;
	EnemyWaveGL ew = new EnemyWaveGL();
	ew.robot = this;
	ew.gunLocation = new Point2D.Double(enemyLocation.getX(), enemyLocation.getY());
	ew.startBearing = ew.gunBearing(robotLocation);

	double enemyDeltaEnergy = enemyEnergy - e.getEnergy();
	if (enemyDeltaEnergy > 0 && enemyDeltaEnergy <= 3.0) {
	    enemyFirePower = enemyDeltaEnergy;
	    ew.surfable = true;
	}
	enemyEnergy = e.getEnergy();
	ew.bulletVelocity = bulletVelocity(enemyFirePower);

	robotBearingDirection = sign(getVelocity() * Math.sin(getHeadingRadians() - ew.startBearing));
	ew.bearingDirection = robotBearingDirection / (double)MIDDLE_FACTOR;

	ew.visits = moveFactors[distanceIndex = (int)(enemyDistance / (MAX_DISTANCE / DISTANCE_INDEXES))]
	    [(int)(enemyFirePower / 0.65)]
	    [fieldRectangle.contains(project(enemyLocation, ew.startBearing + ew.bearingDirection * 15, enemyDistance)) ? 0 : 1]
	    //[(int)(Math.abs(robotVelocity) / 2)]
	    ;
	ew.targetLocation = robotLocation;

	robotLocation.setLocation(new Point2D.Double(getX(), getY()));
	double enemyAbsoluteBearing = getHeadingRadians() + e.getBearingRadians();
	enemyLocation.setLocation(project(wave.gunLocation = new Point2D.Double(getX(), getY()), enemyAbsoluteBearing, enemyDistance));
	wave.targetLocation = enemyLocation;
	enemyDistance = e.getDistance();

	ew.advance(2);
	addCustomEvent(ew);

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

	//double bulletPower = MAX_BULLET_POWER; // TargetingChallenge
	double bulletPower = Math.min(enemyEnergy / 4, distanceIndex > 2 ? BULLET_POWER : MAX_BULLET_POWER);
	wave.bulletVelocity = bulletVelocity(bulletPower);

	if (enemyVelocity != 0) {
	    enemyBearingDirection = 0.75 * sign(enemyVelocity * Math.sin(e.getHeadingRadians() - enemyAbsoluteBearing));
	}
	wave.bearingDirection = enemyBearingDirection / (double)MIDDLE_FACTOR;

	wave.visits = aimFactors[distanceIndex][velocityIndex][lastVelocityIndex][Math.min(5, enemyTimeSinceDeccel++ / 13)]
	    [fieldRectangle.contains(project(wave.gunLocation, enemyAbsoluteBearing + wave.bearingDirection * 13, enemyDistance)) ? 1 : 0];

	wave.startBearing = enemyAbsoluteBearing;

	setTurnGunRightRadians(Utils.normalRelativeAngle(enemyAbsoluteBearing - getGunHeadingRadians() +
		    wave.bearingDirection * (wave.mostVisited() - MIDDLE_FACTOR)));

	if (getEnergy() >= BULLET_POWER) {
	    setFire(bulletPower);
	    addCustomEvent(wave);
	}
	// </gun>

	if (getTime() > nextDirectionChangeTime) {
	    if (visitsReverse < visitsForward) {
		orbitDirection = -robotBearingDirection;
		nextDirectionChangeTime = getTime() + 2;
	    }
	    else {
		orbitDirection = robotBearingDirection;
	    }
	}
	Point2D destination = wallSmoothedDestination(enemyLocation, robotLocation, orbitDirection * 0.4, 1.2);
	// Jamougha's cool way
	double angle;
	setAhead(Math.cos(angle = wave.gunBearing(destination) - getHeadingRadians()) * 100);
	setTurnRightRadians(Math.tan(angle));

	setTurnRadarRightRadians(Utils.normalRelativeAngle(enemyAbsoluteBearing - getRadarHeadingRadians()) * 2);

	visitsForward = visitsReverse = 0;

	if (ew.surfable) { // GL
	    ew.grapher = new WaveGrapherGL(ew); // GL
	} // GL
    }

    public void onHitByBullet(HitByBulletEvent e) {
	EnemyWaveGL wave = passingWave;
	if (wave != null) {
	    wave.registerVisits(1000);
	}
    }

    static Point2D wallSmoothedDestination(Point2D orbitLocation, Point2D satelliteLocation,
					    double deltaBearing, double distanceFactor) {
	Point2D destination = null;
	double direction = -1;
	double wallSmoothTries;
	do {
	    direction = -direction;
	    wallSmoothTries = 0;
	    while (!fieldRectangle.contains(destination =
			project(orbitLocation,
			    absoluteBearing(orbitLocation, satelliteLocation) + deltaBearing * direction,
			    robotLocation.distance(orbitLocation) * (distanceFactor - wallSmoothTries / 100))) && wallSmoothTries < MAX_WALL_SMOOTH_TRIES) {
		wallSmoothTries++;
	    }
	} while (wallSmoothTries > 35 + distanceIndex * 10 && direction > 0);
	return destination;
    }

    static void updateDirectionStats(EnemyWaveGL wave) {
	Point2D destination;
	double timeToImpact = wave.distanceToTarget() / wave.bulletVelocity - 1; // I don't want to do the subtraction part...
	destination = wallSmoothedDestination(enemyLocation, robotLocation,
		-wave.deltaBearing(Math.max(2, timeToImpact - 8 + distanceIndex) * MAX_VELOCITY * robotBearingDirection), 1.1);
	visitsReverse += wave.smoothedVisits(destination);
	wave.grapher.drawReverseDestination(destination, wave.smoothedVisits(destination)); // GL

	destination = wallSmoothedDestination(enemyLocation, robotLocation, wave.deltaBearing(timeToImpact * MAX_VELOCITY * robotBearingDirection), 1.1);
	visitsForward += wave.smoothedVisits(destination);
	wave.grapher.drawForwardDestination(destination, wave.smoothedVisits(destination)); // GL
    }

    static double bulletVelocity(double bulletPower) {
	return 20 - 3 * bulletPower;
    }

    static double maxEscapeAngle(double bulletVelocity) {
	return Math.asin(MAX_VELOCITY / bulletVelocity);
    }

    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 sign(double v) {
        return v < 0 ? -1 : 1;
    }

    static double minMax(double v, double min, double max) {
	return Math.max(min, Math.min(max, v));
    }
}

class WaveGL extends Condition {
    PugilistGL robot;
    double bulletVelocity;
    Point2D gunLocation;
    Point2D targetLocation;
    double startBearing;
    double bearingDirection;
    int[] visits;
    double distanceFromGun;

    public boolean test() {
	advance(1);
	if (passing(-18)) {
	    if (robot.getOthers() > 0) {
		registerVisits(1);
	    }
	    robot.removeCustomEvent(this);
	}
	return false;
    }

    public boolean passing(double distanceOffset) {
	return distanceFromGun > gunLocation.distance(targetLocation) + distanceOffset;
    }

    void advance(int ticks) {
	distanceFromGun += ticks * bulletVelocity;
    }

    int visitingIndex(Point2D target) {
	return (int)PugilistGL.minMax(
	    Math.round(((Utils.normalRelativeAngle(gunBearing(target) - startBearing)) / bearingDirection) + PugilistGL.MIDDLE_FACTOR), 0 , PugilistGL.FACTORS - 1);
    }

    void registerVisits(int count) {
	try {
	    visits[visitingIndex(targetLocation)] += count;
	}
	catch (ArrayIndexOutOfBoundsException e) {
	}
    }

    double gunBearing(Point2D target) {
	return PugilistGL.absoluteBearing(gunLocation, target);
    }

    double currentBearing() {
	return gunBearing(targetLocation);
    }

    double distanceToTarget() {
	return gunLocation.distance(targetLocation) - distanceFromGun;
    }

    double shootingDistance() {
	return gunLocation.distance(targetLocation);
    }

    int mostVisited() {
	int mostVisited = PugilistGL.MIDDLE_FACTOR, i = PugilistGL.FACTORS - 1;
	do  {
	    if (visits[--i] > visits[mostVisited]) {
		mostVisited = i;
	    }
	} while (i > 0);
	return mostVisited;
    }

    double smoothedVisits(Point2D destination) {
	return smoothedVisits(visitingIndex(destination));
    }

    double smoothedVisits(int index) {
	double smoothed = 0;
	int i = 0;
	do {
	    smoothed += (double)visits[i] / Math.sqrt((double)(Math.abs(index - i) + 1.0));
	    i++;
	} while (i < PugilistGL.FACTORS);
	return smoothed / Math.pow(distanceToTarget() / bulletVelocity, 1.3);
    }

    double deltaBearing(double distance) {
	return (distance / shootingDistance());
    }
}

class EnemyWaveGL extends WaveGL {
    WaveGrapherGL grapher; // GL

    boolean surfable;

    public boolean test() {
	advance(1);
	if (passing(-18)) {
	    registerVisits(1);
	    surfable = false;
	    PugilistGL.passingWave = this;
	}
	if (passing(18)) {
	    if (grapher != null) { // GL
		grapher.remove(); // GL
	    } // GL
	    robot.removeCustomEvent(this);
	}
	else if (surfable) {
	    PugilistGL.updateDirectionStats(this);
	}
	if (grapher != null) { // GL
	    grapher.drawWave(); // GL
	} // GL
	return false;
    }
}

/* GL */
class WaveGrapherGL {
    static GLRenderer renderer = GLRenderer.getInstance();
    static int counter = 0;
    String id;
    WaveGL wave;
    PointGL[] dots;
    PointGL reverseDestination = new PointGL();
    PointGL forwardDestination = new PointGL();
    LabelGL reverseLabel = new LabelGL("");
    LabelGL forwardLabel = new LabelGL("");
    
    WaveGrapherGL(WaveGL wave) {
	this.id = "" + counter++;
	this.wave = wave;
	this.dots = new PointGL[wave.visits.length];
	for (int i = 0; i < dots.length; i++) {
	    dots[i] = new PointGL();
	    if (i == PugilistGL.MIDDLE_FACTOR) {
		dots[i].addLabel(new LabelGL(id));
	    }
	    renderer.addRenderElement(dots[i]);
	}
	reverseDestination.addLabel(reverseLabel);
	reverseDestination.setColor(Color.RED);
	reverseDestination.setSize(15);
	reverseDestination.setPosition(-100, -100);
	forwardDestination.addLabel(forwardLabel);
	forwardDestination.setColor(Color.GREEN);
	forwardDestination.setSize(15);
	forwardDestination.setPosition(-100, -100);
	renderer.addRenderElement(reverseDestination);
	renderer.addRenderElement(forwardDestination);
    }

    void drawWave() {
	//remove();
	float totalVisits = 0;
	for (int i = 0; i < wave.visits.length; i++) {
	    totalVisits += wave.smoothedVisits(i);
	}
	for (int i = 0; i < dots.length; i++) {
	    Point2D dot = PugilistGL.project(wave.gunLocation,
					  wave.startBearing + wave.bearingDirection * (i - PugilistGL.MIDDLE_FACTOR),
					  wave.distanceFromGun);
	    dots[i].setPosition(dot.getX(), dot.getY());
	    dots[i].setColor(Color.BLUE);
	    dots[i].setSize(100f * (float)wave.smoothedVisits(i) / totalVisits);
	}
    }

    void drawDestination(PointGL destination, LabelGL label, Point2D coords, double value) {
	destination.setPosition(coords.getX(), coords.getY());
	label.setString(id + " : " + (int)value);
    }

    void drawReverseDestination(Point2D coords, double value) {
	drawDestination(reverseDestination, reverseLabel, coords, value);
    }

    void drawForwardDestination(Point2D coords, double value) {
	drawDestination(forwardDestination, forwardLabel, coords, value);
    }

    void remove() {
	for (int i = 0; i < dots.length; i++) {
	    dots[i].remove();
	}
	reverseDestination.remove();
	forwardDestination.remove();
    }
}
/* GL */


Robo Home | PugilistGL | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited March 10, 2004 21:42 EST by PEZ (diff)
Search: