package voidious.test; import robocode.*; import robocode.util.Utils; import java.awt.geom.*; import robocode.RobocodeFileWriter; import java.util.ArrayList; /** * WaveRecorder.java * * Some GuessFactorTargeting analysis by Voidious. * * This code is open source, released under the RoboWiki Public Code License: * http://robowiki.net/cgi-bin/robowiki?RWPCL */ public class WaveRecorder extends AdvancedRobot { public static Point2D.Double _myLocation; public static Point2D.Double _enemyLocation; private static double _enemyAbsoluteBearing; private static int _lastGunOrientation; private static double _lastDistance; private long _timeSinceVChange = 0; private long _timeSinceZeroVelocity = 0; private long _timeSinceMaxVelocity = 0; private static int _enemyVelocity; private static String _enemyName = ""; private Wave _lastWave = null; private ArrayList _enemyPositions = new ArrayList(); private static java.awt.geom.Rectangle2D.Double _fieldRect = new java.awt.geom.Rectangle2D.Double(18, 18, 764, 564); private static String _waveLog = ""; private static String _roundWaveLog = ""; public void run() { _roundWaveLog = ""; setAdjustGunForRobotTurn(true); setAdjustRadarForGunTurn(true); do { turnRadarRightRadians(Double.POSITIVE_INFINITY); } while (true); } public void onScannedRobot(ScannedRobotEvent e) { _enemyName = e.getName(); setTurnRadarRightRadians(Utils.normalRelativeAngle((_enemyAbsoluteBearing = getHeadingRadians() + e.getBearingRadians()) - getRadarHeadingRadians()) * 2); //////////////////////////////////////////////////////// // CREDIT: Jamougha and PEZ for event based waves. //////////////////////////////////////////////////////// Wave w; addCustomEvent(w = new Wave()); _enemyLocation = project((_myLocation = new Point2D.Double(getX(), getY())), _enemyAbsoluteBearing, _lastDistance = e.getDistance()); _enemyPositions.add(_enemyLocation); double distanceLastEightTicks = _enemyLocation.distance( ((Point2D.Double)_enemyPositions.get( Math.max(0, _enemyPositions.size() - 9)))); double distanceLastFifteenTicks = _enemyLocation.distance( ((Point2D.Double)_enemyPositions.get( Math.max(0, _enemyPositions.size() - 16)))); double distanceLastTwentyFiveTicks = _enemyLocation.distance( ((Point2D.Double)_enemyPositions.get( Math.max(0, _enemyPositions.size() - 26)))); double power = 3; w.distanceTraveled = 0; double enemyLatVel; _lastGunOrientation = sign(enemyLatVel = (e.getVelocity())*Math.sin(e.getHeadingRadians() - _enemyAbsoluteBearing)); _timeSinceVChange++; _timeSinceZeroVelocity++; _timeSinceMaxVelocity++; int newVelocity, accel; accel = 1; if (_enemyVelocity != (newVelocity = (int)(Math.abs(enemyLatVel)))) { _timeSinceVChange = 0; accel = 2; if (_enemyVelocity > newVelocity) { accel = 0; } } if (Math.abs(e.getVelocity()) <= 1) { _timeSinceZeroVelocity = 0; } if (Math.abs(e.getVelocity()) > 7) { _timeSinceMaxVelocity = 0; } _enemyVelocity = newVelocity; double maxEscapeAngle = Math.asin(8D/(20 - (3 * power))); double wallDistance = 3; for (double d = 0; d < 3; d += 0.01) { if (!gunWallDistance(d * maxEscapeAngle)) { wallDistance = d; break; } } double reverseWallDistance = 3; for (double d = 0; d < 3; d += 0.01) { if (!gunWallDistance(-d * maxEscapeAngle)) { reverseWallDistance = d; break; } } w.bulletVelocity = (20 - (3 * power)); w.orientation = _lastGunOrientation; w.velocity = Math.abs(e.getVelocity()); w.relativeHeading = Utils.normalAbsoluteAngle(e.getHeadingRadians() + (e.getVelocity() < 0?Math.PI:0) - _enemyAbsoluteBearing); if (w.relativeHeading > Math.PI) { w.relativeHeading = ((2 * Math.PI) - w.relativeHeading); } w.latVel = Math.abs(enemyLatVel); w.distance = _lastDistance; w.timeSinceVChange = _timeSinceVChange; w.timeSinceZeroVelocity = _timeSinceZeroVelocity; w.timeSinceMaxVelocity = _timeSinceMaxVelocity; w.wallDistance = wallDistance; w.reverseWallDistance = reverseWallDistance; w.accel = accel; w.distanceLastEightTicks = distanceLastEightTicks; w.distanceLastFifteenTicks = distanceLastFifteenTicks; w.distanceLastTwentyFiveTicks = distanceLastTwentyFiveTicks; w.fireTime = getTime() + 1; w.sourceLocation = _myLocation; w.directAngle = _enemyAbsoluteBearing; setTurnGunRightRadians(Utils.normalRelativeAngle(_enemyAbsoluteBearing - getGunHeadingRadians() + ((_lastGunOrientation*maxEscapeAngle)*((Math.random() * 2) - 1)) )); if (setFireBullet(3) != null) { if (_lastWave != null) { _lastWave.firing = true; } } _lastWave = w; } public void onCustomEvent(CustomEvent e) { removeCustomEvent(e.getCondition()); } private static double getGuessFactor(Wave w, Point2D.Double botLocation) { return (Utils.normalRelativeAngle( w.absoluteBearing(botLocation) - w.directAngle) * w.orientation) / Math.asin(8D/w.bulletVelocity); } public static void logHit(Wave w, Point2D.Double targetLocation, int roundNum) { String output = ""; output += roundNum + " : "; output += (w.firing?1:0) + " : "; output += w.orientation + " : "; output += round(getGuessFactor(w, targetLocation), 5) + " : "; output += round(w.velocity, 2) + " : "; output += round(w.latVel, 2) + " : "; output += w.accel + " : "; output += w.timeSinceVChange + " : "; output += w.timeSinceZeroVelocity + " : "; output += w.timeSinceMaxVelocity + " : "; output += round(w.distance, 1) + " : "; output += round(w.wallDistance, 3) + " : "; output += round(w.reverseWallDistance, 3) + " : "; output += round(w.relativeHeading, 4) + " : "; output += round(w.distanceLastEightTicks, 1) + " : "; output += round(w.distanceLastFifteenTicks, 1) + " : "; output += round(w.distanceLastTwentyFiveTicks, 1) + "\n"; _roundWaveLog += output; } public void onWin(WinEvent e) { roundOver(); } public void onDeath(DeathEvent e) { roundOver(); } public void roundOver() { _waveLog += _roundWaveLog; if (getRoundNum() == getNumRounds() - 1) { try { int x = 0; while (x < 1000 && getDataFile(_enemyName + "." + x + ".w2.txt").exists()) { x++; } RobocodeFileWriter writer = new RobocodeFileWriter( getDataFile(_enemyName + "." + x + ".w2.txt")); writer.write(_waveLog); writer.close(); } catch (Exception e) { } } } /* private static double limit(double min, double value, double max) { return Math.max(min, Math.min(value, max)); } */ // CREDIT: ganked from CassiusClay, by PEZ // http://robowiki.net?CassiusClay private 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 int sign(double d) { if (d < 0) { return -1; } return 1; } private static double round(double d, int i) { long powerTen = 1; for (int x = 0; x < i; x++) { powerTen *= 10; } return ((double)Math.round(d * powerTen)) / powerTen; } private static boolean gunWallDistance(double wallDistance) { return _fieldRect.contains(project(_myLocation, _enemyAbsoluteBearing + (_lastGunOrientation*wallDistance), _lastDistance)); } class Wave extends Condition { Point2D.Double sourceLocation; double bulletVelocity, directAngle, distanceTraveled; int orientation, weight, roundNum; long timeSinceVChange, timeSinceZeroVelocity, timeSinceMaxVelocity, fireTime; int accel; double velocity, distance, latVel, wallDistance, reverseWallDistance, relativeHeading; double distanceLastEightTicks, distanceLastFifteenTicks, distanceLastTwentyFiveTicks; boolean firing = false; public double distanceToPoint(Point2D.Double p) { return sourceLocation.distance(p); } public double absoluteBearing(Point2D.Double target) { return Math.atan2(target.x - sourceLocation.x, target.y - sourceLocation.y); } public boolean test() { if (distanceToPoint(WaveRecorder._enemyLocation) <= (getTime() - fireTime + 1.5) * bulletVelocity) { WaveRecorder.logHit(this, WaveRecorder._enemyLocation, getRoundNum()); return true; } return false; } } }