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