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 */