package voidious.test; import robocode.*; import robocode.util.Utils; import java.awt.geom.*; import robocode.RobocodeFileWriter; /** * 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 double _timeSinceVChange = 0; private static int _enemyVelocity; private static String _enemyName = ""; 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: RaikoMicro's gun, by Jamougha // http://robowiki.net?RaikoMicro //////////////////////////////////////////////////////// Wave w; addCustomEvent(w = new Wave()); _enemyLocation = project((_myLocation = new Point2D.Double(getX(), getY())), _enemyAbsoluteBearing, _lastDistance = e.getDistance()); double power = 3; w.distanceTraveled = 0; double enemyLatVel; _lastGunOrientation = sign(enemyLatVel = (e.getVelocity())*Math.sin(e.getHeadingRadians() - _enemyAbsoluteBearing)); _timeSinceVChange++; int newVelocity, accel; accel = 1; if (_enemyVelocity != (newVelocity = (int)(Math.abs(enemyLatVel)))) { _timeSinceVChange = 0; accel = 2; if (_enemyVelocity > newVelocity) { accel = 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; } } 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 = (long)_timeSinceVChange; w.wallDistance = wallDistance; w.accel = accel; w.sourceLocation = _myLocation; w.directAngle = _enemyAbsoluteBearing; setTurnGunRightRadians(Utils.normalRelativeAngle(_enemyAbsoluteBearing - getGunHeadingRadians() + ((_lastGunOrientation*maxEscapeAngle)*((Math.random() * 2) - 1)) )); if (setFireBullet(3) != null) { w.firing = true; } } 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 += round(w.distance, 1) + " : "; output += round(w.wallDistance, 3) + " : "; output += round(w.relativeHeading, 4) + "\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 + ".txt").exists()) { x++; } RobocodeFileWriter writer = new RobocodeFileWriter( getDataFile(_enemyName + "." + x + ".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; int accel; double velocity, distance, latVel, wallDistance, relativeHeading; 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) <= (distanceTraveled+=bulletVelocity) + (.5*bulletVelocity)) { WaveRecorder.logHit(this, WaveRecorder._enemyLocation, getRoundNum()); return true; } return false; } } }