LuminariousDuo/Code
Jump to navigation
Jump to search
- LuminariousDuo Sub-pages:
- LuminariousDuo - Version History - Code
This is the code for LuminariousDuo 1.0591. The teammate just extends Luminarious with no changes.
package voidious.team;
import robocode.*;
import robocode.util.Utils;
import java.util.HashMap;
import java.util.ArrayList;
import java.awt.geom.Point2D;
import java.awt.Color;
import java.io.Serializable;
import java.util.Random;
public class Luminarious extends TeamRobot {
protected static final double RADAR_TRACK_AMOUNT = Math.PI/4;
protected static Point2D.Double _myLocation;
protected static HashMap _enemyLocationsByName = new HashMap();
protected static Point2D.Double _teammateLocation;
protected ArrayList _recentLocations;
protected static Random _rand = new Random();
protected String _lastEnemySeen;
protected static long _scanReversalTick;
protected static int _radarDirection = 1;
protected static double _radarRangeTracker;
protected static double _lastRadarRangeTracker;
protected static java.awt.geom.Rectangle2D.Double _fieldRect;
protected int _teammatesAlive = 1;
/* For now, we are assuming our enemies will use the same or similar
* movement, which is probably pretty likely.
*/
protected static final double WAVE_BULLET_POWER = 1.9;
protected static final double WAVE_BULLET_VELOCITY = 14.3;
protected static final double WAVE_MAX_ESCAPE_ANGLE = 0.62;
protected static double _bulletPower;
static final int GF_ZERO = 18;
static final int GF_ONE = 36;
static long[][][][][] _gunStats = new long[2][3][4][5][GF_ONE+1];
protected double _targetDistance = Double.POSITIVE_INFINITY;
protected static String _targetName = "";
protected static double _randomDirChangeAmount;
protected long _timeSinceDirChangeCounter;
protected static double _lastHeading;
protected static double _enemyAbsoluteBearing;
protected static int _lastGunOrientation;
protected static double _lastDistance;
protected static double _lastBulletPower = 1;
protected static int _resumeRadarDirection = 1;
protected static boolean _tempRadarLock = false;
public void run() {
_fieldRect = new java.awt.geom.Rectangle2D.Double(30, 30,
getBattleFieldWidth() - 60, getBattleFieldHeight() - 60);
_recentLocations = new ArrayList();
setAdjustGunForRobotTurn(true);
setAdjustRadarForGunTurn(true);
setColors(Color.black, Color.black, new Color(80, 150, 80));
do {
try {
broadcastMessage(new LuminariLocation(getX(), getY()));;
} catch (Exception ex) { }
setTurnRadarRightRadians(RADAR_TRACK_AMOUNT * _radarDirection);
_radarRangeTracker += RADAR_TRACK_AMOUNT;
if (Math.abs(getGunTurnRemaining()) < 4) {
if (setFireBullet(_bulletPower) != null) {
_radarDirection = _resumeRadarDirection;
_tempRadarLock = false;
}
}
move();
execute();
} while (true);
}
public void onScannedRobot(ScannedRobotEvent e) {
String eName = e.getName();
double eDistance = _lastDistance = e.getDistance();
double eEnergy = e.getEnergy();
double eVelocity = e.getVelocity();
if (isTeammate(eName)) { return; }
////////////////////////////////////////////////
// General data stuff
////////////////////////////////////////////////
_enemyAbsoluteBearing = e.getBearingRadians() + getHeadingRadians();
double enemyLatVel = (e.getVelocity()) *
Math.sin(e.getHeadingRadians() - _enemyAbsoluteBearing);
if (!_enemyLocationsByName.containsKey(eName)) {
_enemyLocationsByName.put(eName, new EnemyData());
}
EnemyData eData = (EnemyData)_enemyLocationsByName.get(eName);
eData.name = eName;
eData.setLocation(project(_myLocation, _enemyAbsoluteBearing, eDistance));
double absSinRelativeHeading =
Math.abs(Math.sin(e.getHeadingRadians() - _enemyAbsoluteBearing));
eData.energy = eEnergy;
eData.heading = e.getHeadingRadians();
eData.velocity = eVelocity;
////////////////////////////////////////////////
// Radar
////////////////////////////////////////////////
if (_lastEnemySeen == null) {
_lastEnemySeen = eName;
}
if (getOthers() - _teammatesAlive == 1) {
_resumeRadarDirection = (_radarDirection *= -1);
} else if (
getGunHeat() <= (Math.min(Math.PI, _lastRadarRangeTracker) / 5) /
RADAR_TRACK_AMOUNT && _targetName.equals(eName)) {
_radarDirection *= -1;
if (!_tempRadarLock) {
_resumeRadarDirection = _radarDirection;
if (_radarRangeTracker > Math.PI) {
_resumeRadarDirection *= -1;
}
}
_tempRadarLock = true;
_radarRangeTracker = 0;
} else if (!_lastEnemySeen.equals(eName)) {
if (_radarRangeTracker <= Math.PI &&
_scanReversalTick != e.getTime()) {
_scanReversalTick = e.getTime();
_radarDirection *= -1;
_lastRadarRangeTracker = _radarRangeTracker;
}
_radarRangeTracker = 0;
}
_lastEnemySeen = eName;
////////////////////////////////////////////////
// Gun wave creation
////////////////////////////////////////////////
MicroWave w;
addCustomEvent(w = new MicroWave());
w.targetName = eName;
w.sourceLocation = _myLocation;
w.directAngle = _enemyAbsoluteBearing;
w.orientation = _lastGunOrientation = sign((eVelocity)
* Math.sin(e.getHeadingRadians() - _enemyAbsoluteBearing));
w.waveGuessFactors =
_gunStats[gunWallDistance(0.38591195687) ? 1 : 0]
[(int)Math.min(2, 3 * Math.asin(absSinRelativeHeading) / (Math.PI / 2))]
[(int)(eDistance / 275)][(int)((Math.abs(enemyLatVel)+1) / 2)];
////////////////////////////////////////////////
// Target selection and actual firing.
////////////////////////////////////////////////
if (eDistance < _targetDistance || _targetName.equals(eName)) {
_targetName = eName;
_targetDistance = eDistance;
}
if (!_targetName.equals(eName)) {
return;
}
int bestGF = GF_ZERO;
double bestGFRank = 0;
for (int x = 0; x < GF_ONE; x++) {
if (w.waveGuessFactors[x] > bestGFRank) {
bestGFRank = w.waveGuessFactors[x];
bestGF = x;
}
}
_bulletPower = 1.9;
if (eDistance > 750) {
_bulletPower = 1.59;
}
if (eDistance < 300) {
_bulletPower = 2.39;
}
if (eDistance < 150) {
_bulletPower = 3;
}
if ((getEnergy() < eEnergy && _teammatesAlive == 0) ||
(getEnergy() < 25)) {
_bulletPower = Math.min(_bulletPower,
1.9 - Math.max(0, (35 - getEnergy()) / 18));
}
setTurnGunRightRadians(Utils.normalRelativeAngle(
_enemyAbsoluteBearing - getGunHeadingRadians() +
(e.getEnergy() > 0 ?
(w.orientation
* (maxEscapeAngle(bulletVelocity(_bulletPower)) / GF_ZERO)
* (bestGF - GF_ZERO)) : 0)));
}
public void onMessageReceived(MessageEvent e) {
LuminariLocation loc = (LuminariLocation)e.getMessage();
_teammateLocation = new Point2D.Double(loc.x, loc.y);
}
public void onRobotDeath(RobotDeathEvent e) {
String eName = e.getName();
if (isTeammate(eName)) {
_teammatesAlive--;
}
if (_targetName.equals(eName)) {
_targetName = "";
_targetDistance = Double.POSITIVE_INFINITY;
}
_enemyLocationsByName.remove(eName);
}
public void onHitByBullet(HitByBulletEvent e) {
_lastBulletPower = e.getPower();
}
public void onHitWall(HitWallEvent e) {
_timeSinceDirChangeCounter = 0;
}
protected void move() {
_myLocation = new Point2D.Double(getX(), getY());
if (Math.random() > 0.9) {
_recentLocations.add(0, _myLocation);
}
double bestRisk = Double.POSITIVE_INFINITY;
double bestAngle = 0;
double currentHeading =
getHeadingRadians() + (getVelocity() < 0?Math.PI:0);
Object[] enemies =
(_enemyLocationsByName.values().toArray());
if (Math.abs(Utils.normalRelativeAngle(currentHeading - _lastHeading))
< Math.PI / 3) {
_timeSinceDirChangeCounter++;
} else {
_timeSinceDirChangeCounter = 0;
_randomDirChangeAmount =
Math.max(4, 2 * Math.random() * Math.random()
* (_targetDistance) / bulletVelocity(_lastBulletPower));
}
for (double x = 0; x < 2; x += .04) {
double testAngle = x * Math.PI;
Point2D.Double testPoint = project(_myLocation, testAngle,
50 + Math.random() * 200);
if (_fieldRect.contains(testPoint)) {
double testRisk = 0;
double[] enemyBearings = new double[2];
for (int y = 0; y < enemies.length; y++) {
EnemyData eData = ((EnemyData)enemies[y]);
double bearingToTeammate =
absoluteBearing(eData, _teammateLocation);
double bearingToMe = enemyBearings[y] =
absoluteBearing(eData, testPoint);
double distSquaredToEnemy =
testPoint.distanceSq(eData);
// double distSquaredTeammateToEnemy =
// _teammateLocation.distanceSq(eData);
testRisk +=
((limit(0.1, (eData.energy / getEnergy()), 2)
/ distSquaredToEnemy)
+ ((2 * _teammatesAlive)
/ testPoint.distanceSq(_teammateLocation))
)
// * (_teammatesAlive == 0?1:(
// (Math.max(1, distSquaredToEnemy / distSquaredTeammateToEnemy))))
* (1 + square(Math.cos(absoluteBearing(
_myLocation, eData) - testAngle)))
// * (2 + square(Math.sin(absoluteBearing(
// testPoint, eData) - eData.heading)))
* (_teammatesAlive==0?1:(1 +
square(Math.cos(bearingToTeammate - bearingToMe))))
;
}
try {
if (getOthers() - _teammatesAlive == 2) {
testRisk *= (1 + square(Math.sin(enemyBearings[0]
- enemyBearings[1])));
}
} catch (Exception e) { }
if (Math.abs(Utils.normalRelativeAngle(currentHeading
- testAngle)) < (Math.PI / 3)) {
if (_timeSinceDirChangeCounter > _randomDirChangeAmount) {
testRisk *= 10;
} else {
testRisk /= 2;
}
}
try {
for (int z = 0; z < Math.min(6, _recentLocations.size()); z++) {
testRisk *= (1 + (((1000) - (100 * z))
/ (testPoint.distanceSq(
(Point2D.Double)_recentLocations.get(z)))));
}
} catch (Exception e) { }
if (testRisk < bestRisk) {
bestRisk = testRisk;
bestAngle = x * Math.PI;
}
}
}
_lastHeading = currentHeading;
moveWithBackAsFront(bestAngle);
}
// CREDIT: code by Iiley,
// http://robowiki.net?BackAsFront
void moveWithBackAsFront(double bearing) {
double angle = Utils.normalRelativeAngle(bearing - getHeadingRadians());
double turnAngle;
setTurnRightRadians(turnAngle = Math.atan(Math.tan(angle)));
setAhead((angle == turnAngle) ? 100 : -100);
}
protected static Point2D.Double project(Point2D.Double sourceLocation,
double angle, double length) {
return new Point2D.Double(sourceLocation.x + Math.sin(angle) * length,
sourceLocation.y + Math.cos(angle) * length);
}
private static double absoluteBearing(Point2D.Double source, Point2D.Double target) {
return Math.atan2(target.x - source.x, target.y - source.y);
}
static int sign(double d) {
if (d >= 0) return 1;
return-1;
}
static double square(double d) {
return d * d;
}
private static double maxEscapeAngle(double velocity) {
return Math.asin(8.0/velocity);
}
protected static double bulletVelocity(double power) {
return (20.0 - (3.0*power));
}
protected static double limit(double min, double value, double max) {
return Math.max(min, Math.min(value, max));
}
protected static boolean gunWallDistance(double wallDistance) {
return _fieldRect.contains(project(_myLocation, _enemyAbsoluteBearing
+ (_lastGunOrientation*wallDistance), _lastDistance));
}
protected static double pythago(double x, double y) {
return Math.sqrt(square(x) + square(y));
}
class MicroWave extends Condition {
String targetName;
Point2D.Double sourceLocation;
long[] waveGuessFactors;
double bulletVelocity, directAngle, distance;
int orientation;
public boolean test(){
try {
Point2D.Double enemyLocation =
((EnemyData)_enemyLocationsByName.get(targetName));
if ((enemyLocation).distance(sourceLocation)
<= (distance+=WAVE_BULLET_VELOCITY) + (WAVE_BULLET_VELOCITY/2)) {
try {
double guessFactor = (Utils.normalRelativeAngle(
absoluteBearing(sourceLocation, enemyLocation)
- directAngle) * orientation) / WAVE_MAX_ESCAPE_ANGLE;
int guessFactorIndex = (int)((guessFactor * GF_ZERO) + GF_ZERO);
waveGuessFactors[guessFactorIndex]++;
} catch (Exception e) { }
removeCustomEvent(this);
}
} catch (Exception e) { }
return false;
}
}
}
class EnemyData extends Point2D.Double {
String name;
double energy, velocity, heading;
}
class LuminariLocation implements Serializable {
public double x;
public double y;
public LuminariLocation(double newX, double newY) {
x = newX;
y = newY;
}
}