PluggableRobot/Source
Jump to navigation
Jump to search
Below is the source for PluggableRobot. Pillage to your heart's content. PluggableRobot is released under the RoboWiki Limited Public Code License.
Contents
Canvas.java
/* * PluggableRobot, by Robert J. Walker * Home page: http://robowiki.net/w/index.php?title=PluggableRobot * This software is made available under the RoboWiki Limited Public Code * License (RWLPCL). The full text of the license may be found at: * http://robowiki.net/w/index.php?title=RWLPCL */ package rjw.pluggablerobot; import java.awt.*; import java.awt.geom.Point2D; import robocode.AdvancedRobot; /** * A convenience wrapper around Graphics2D which provides the following * features: * * - Accepts doubles for many arguments which are ints in Graphics2D * - getCenter(), getHeight() and getWidth() * - drawCircle(), fillCircle() * * @author Robert J. Walker */ public class Canvas { private Graphics2D _g; private double _width; private double _height; private Point2D.Double _center; Canvas(AdvancedRobot bot) { _g = bot.getGraphics(); _width = bot.getBattleFieldWidth(); _height = bot.getBattleFieldHeight(); _center = new Point2D.Double(_width / 2, _height / 2); } /** * @see java awt.Graphics2D.clearRect(int, int, int, int) */ public void clearRect(double x, double y, double width, double height) { _g.clearRect(i(x), i(y), i(width), i(height)); } /** * @see java awt.Graphics2D.clip(java.awt.Shape) */ public void clip(Shape shape) { _g.clip(shape); } /** * @see java awt.Graphics2D.clipRect(int, int, int, int) */ public void clipRect(double x, double y, double width, double height) { _g.clipRect(i(x), i(y), i(width), i(height)); } /** * @see java awt.Graphics2D.copyArea(int, int, int, int, int, int) */ public void copyArea(double x, double y, double width, double height, double dx, double dy) { _g.copyArea(i(x), i(y), i(width), i(height), i(dx), i(dy)); } /** * @see java awt.Graphics2D.draw(java.awt.Shape) */ public void draw(Shape shape) { _g.draw(shape); } /** * @see java awt.Graphics2D.drawArc(int, int, int, int, int, int) */ public void drawArc(double x, double y, double width, double height, double startAngle, double arcAngle) { _g.drawArc(i(x), i(y), i(width), i(height), i(startAngle), i(arcAngle)); } /** * Convenience method for drawing a circle, given the center coordinates and * radius. */ public void drawCircle(double x, double y, double r) { int d = i(r * 2); _g.drawOval(i(x - r), i(y - r), d, d); } /** * @see java awt.Graphics2D.drawLine(int, int, int, int) */ public void drawLine(double x1, double y1, double x2, double y2) { _g.drawLine(i(x1), i(y1), i(x2), i(y2)); } /** * @see java awt.Graphics2D.drawOval(int, int, int, int) */ public void drawOval(double x, double y, double width, double height) { _g.drawOval(i(x), i(y), i(width), i(height)); } /** * @see java awt.Graphics2D.drawRect(int, int, int, int) */ public void drawRect(double x, double y, double width, double height) { _g.drawRect(i(x), i(y), i(width), i(height)); } /** * @see java awt.Graphics2D.drawRoundRect(int, int, int, int, int, int) */ public void drawRoundRect(double x, double y, double width, double height, double arcWidth, double arcHeight) { _g.drawRoundRect(i(x), i(y), i(width), i(height), i(arcWidth), i(arcHeight)); } /** * @see java awt.Graphics2D.drawString(String, float, float) */ public void drawString(String str, double x, double y) { _g.drawString(str, (float) x, (float) y); } /** * @see java awt.Graphics2D.fill(java.awt.Shape) */ public void fill(Shape shape) { _g.fill(shape); } /** * @see java awt.Graphics2D.fillArc(int, int, int, int, int, int) */ public void fillArc(double x, double y, double width, double height, double startAngle, double arcAngle) { _g.fillArc(i(x), i(y), i(width), i(height), i(startAngle), i(arcAngle)); } /** * Convenience method for filling a circle, given the center coordinates and * radius. */ public void fillCircle(double x, double y, double r) { int d = i(r * 2); _g.fillOval(i(x - r), i(y - r), d, d); } /** * @see java awt.Graphics2D.fillOval(int, int, int, int) */ public void fillOval(double x, double y, double width, double height) { _g.fillOval(i(x), i(y), i(width), i(height)); } /** * @see java awt.Graphics2D.fillRect(int, int, int, int) */ public void fillRect(double x, double y, double width, double height) { _g.fillRect(i(x), i(y), i(width), i(height)); } /** * @see java awt.Graphics2D.fillRoundRect(int, int, int, int, int, int) */ public void fillRoundRect(double x, double y, double width, double height, double arcWidth, double arcHeight) { _g.fillRoundRect(i(x), i(y), i(width), i(height), i(arcWidth), i(arcHeight)); } /** * @see java awt.Graphics2D.getBackground() */ public Color getBackground() { return _g.getBackground(); } /** * Returns a Point2D located at the center of the canvas. */ public Point2D.Double getCenter() { return _center; } /** * @see java awt.Graphics2D.getClip() */ public Shape getClip() { return _g.getClip(); } /** * @see java awt.Graphics2D.getClipBounds() */ public Rectangle getClipBounds() { return _g.getClipBounds(); } /** * @see java awt.Graphics2D.getClipBounds(java.awt.Rectangle) */ public Rectangle getClipBounds(Rectangle r) { return _g.getClipBounds(r); } /** * @see java awt.Graphics2D.getColor() */ public Color getColor() { return _g.getColor(); } /** * @see java awt.Graphics2D.getDeviceConfiguration() */ public GraphicsConfiguration getDeviceConfiguration() { return _g.getDeviceConfiguration(); } /** * Returns a reference to the actual Graphics2D object wrapped by the * Canvas. */ public Graphics2D getGraphics() { return _g; } /** * Returns the canvas's height. */ public double getHeight() { return _height; } /** * @see java awt.Graphics2D.getPaint() */ public Paint getPaint() { return _g.getPaint(); } /** * @see java awt.Graphics2D.getStroke() */ public Stroke getStroke() { return _g.getStroke(); } /** * Returns the canvas's width. */ public double getWidth() { return _width; } /** * @see java awt.Graphics2D.hit(java.awt.Rectangle, java.awt.Shape, boolean) */ public boolean hit(Rectangle rect, Shape s, boolean onStroke) { return _g.hit(rect, s, onStroke); } /** * @see java awt.Graphics2D.hitClip(int, int, int, int) */ public boolean hitClip(double x, double y, double width, double height) { return _g.hitClip(i(x), i(y), i(width), i(height)); } /** * @see java awt.Graphics2D.setBackground(java.awt.Color) */ public void setBackground(Color color) { _g.setBackground(color); } /** * @see java awt.Graphics2D.setClip(int, int, int, int) */ public void setClip(double x, double y, double width, double height) { _g.setClip(i(x), i(y), i(width), i(height)); } /** * @see java awt.Graphics2D.setClip(java.awt.Shape) */ public void setClip(Shape clip) { _g.setClip(clip); } /** * @see java awt.Graphics2D.setColor(java.awt.Color) */ public void setColor(Color c) { _g.setColor(c); } /** * @see java awt.Graphics2D.setPaint(java.awt.Paint) */ public void setPaint(Paint paint) { _g.setPaint(paint); } /** * @see java awt.Graphics2D.setStroke(java.awt.Stroke) */ public void setStroke(Stroke stroke) { _g.setStroke(stroke); } /** * Rounds a double to the nearest integer and returns it as an int. */ private static int i(double d) { return (int) Math.round(d); } }
Component.java
/* * PluggableRobot, by Robert J. Walker * Home page: http://robowiki.net/w/index.php?title=PluggableRobot * This software is made available under the RoboWiki Limited Public Code * License (RWLPCL). The full text of the license may be found at: * http://robowiki.net/w/index.php?title=RWLPCL */ package rjw.pluggablerobot; /** * Components encapsulate the main combat behavior of the robot into pluggable * modules. Any code that actually sets an action for the robot (moving, * turning, rotating the turret or radar, etc.) should be done in the go() * method. Components should NEVER call any blocking methods; PluggableRobot * will call execute() automatically when all components have had a chance to * act. * @author Robert J. Walker */ public interface Component { /** * Asks this Component to execute any actions that it wants to take this * turn. PluggableRobot will call this method once per turn for each * registered Component. Don't put any blocking calls in here; * PluggableRobot will call execute() for you automatically after calling * go() on each Component. */ public abstract void go(); }
EventListener.java
/* * PluggableRobot, by Robert J. Walker * Home page: http://robowiki.net/w/index.php?title=PluggableRobot * This software is made available under the RoboWiki Limited Public Code * License (RWLPCL). The full text of the license may be found at: * http://robowiki.net/w/index.php?title=RWLPCL */ package rjw.pluggablerobot; import robocode.*; /** * Event listener interfaces. Objects that wish to be notified of events must * extend one or more of these subinterfaces and register themselves with * PluggableRobot at the start of the round via the registerListener() method. * @author Robert J. Walker */ public interface EventListener { public interface BattleEnded extends EventListener { /** * Called by the ListenerDelegate when the battle ends. */ public void notifyBattleEnded(BattleEndedEvent event); } public interface BulletHitBullet extends EventListener { /** * Called by the ListenerDelegate when a bullet fired by your robot has * hit another bullet. */ public void notifyBulletHitBullet(BulletHitBulletEvent event); } public interface BulletHit extends EventListener { /** * Called by the ListenerDelegate when a bullet fired by your robot has * hit another robot. */ public void notifyBulletHit(BulletHitEvent event); } public interface BulletMissed extends EventListener { /** * Called by the ListenerDelegate when a bullet fired by your robot has * hit a wall. */ public void notifyBulletMissed(BulletMissedEvent event); } public interface Death extends EventListener { /** * Called by the ListenerDelegate when your robot has been destroyed. */ public void notifyDeath(DeathEvent event); } public interface HitByBullet extends EventListener { /** * Called by the ListenerDelegate when your robot has been hit by an * enemy bullet. */ public void notifyHitByBullet(HitByBulletEvent event); } public interface HitRobot extends EventListener { /** * Called by the ListenerDelegate when your robot has collided with * another robot. */ public void notifyHitRobot(HitRobotEvent event); } public interface HitWall extends EventListener { /** * Called by the ListenerDelegate when your robot has collided with a * wall. */ public void notifyHitWall(HitWallEvent event); } public interface RobotDeath extends EventListener { /** * Called by the ListenerDelegate when an enemy robot has been * destroyed. */ public void notifyRobotDeath(RobotDeathEvent event); } public interface ScannedRobot extends EventListener { /** * Called by the ListenerDelegate when your radar has swept over an * enemy robot. */ public void notifyScannedRobot(ScannedRobotEvent event); } public interface SkippedTurn extends EventListener { /** * Called by the ListenerDelegate when your robot has skipped a turn. */ public void notifySkippedTurn(SkippedTurnEvent event); } public interface Status extends EventListener { /** * Called by the ListenerDelegate every turn with a robot status update. */ public void notifyStatus(StatusEvent event); } public interface Win extends EventListener { /** * Called by the ListenerDelegate when all robots besides yours have * been destroyed. */ public void notifyWin(WinEvent event); } // Internal event listeners /** * An EventListener used only by the Hud to inform it of KeyPressedEvents * so that it handle requests to toggle layers. */ interface _KeyPressed extends EventListener { /** * Notifies the Hud that a key was pressed. */ public void notifyKeyPressed(KeyPressedEvent event); } /** * An EventListener used only by the ListenerDelegate to inform it of * PaintEvents. The ListenerDelegate registers with itself as being * interested in this event. This is the connection point for * PluggableRobot's debug graphics harness. */ interface _Paint extends EventListener { /** * Notifies the ListenerDelegate that a PaintEvent has been received. */ public void notifyPaint(PaintEvent event); } }
Hud.java
/* * PluggableRobot, by Robert J. Walker * Home page: http://robowiki.net/w/index.php?title=PluggableRobot * This software is made available under the RoboWiki Limited Public Code * License (RWLPCL). The full text of the license may be found at: * http://robowiki.net/w/index.php?title=RWLPCL */ package rjw.pluggablerobot; import java.util.ArrayList; import rjw.pluggablerobot.EventListener._KeyPressed; import robocode.AdvancedRobot; import robocode.KeyPressedEvent; /** * The Hud is responsible for drawing debug graphics. The Hud has multiple * layers, each of which can be enabled or disabled independently through a key * binding. Any object which is interested in contributing to the Hud must * register itself with PluggableRobot, declaring which layer it wishes to paint * on. Layers are painted in the order in which they were declared, and * individual painters are invoked in the order that they were registered for * that layer. * * Concept based on previous work by Nfwu and David Alves: * http://robowiki.net/w/index.php?title=User:Nfwu/Painter * * @author Robert J. Walker */ public class Hud implements _KeyPressed { private Canvas _canvas; private ArrayList<Layer> _layers = new ArrayList<Layer>(); public Hud(AdvancedRobot bot) { _canvas = new Canvas(bot); } /** * Constructs a new Layer with the given name and bound to the indicated * key. The enabled argument determines whether or not the layer should * be on or off by default. */ public void createLayer(int key, String name, boolean enabled) { Layer layer = new Layer(key, name, enabled); _layers.add(layer); } /** * Registers a painter with the layer bound to the given key. */ public void registerPainter(int key, Painter painter) { for (Layer layer : _layers) { if (layer.getKey() == key) { layer.addPainter(painter); return; } } throw new IllegalArgumentException("No layer bound to that key!"); } /** * Notifes the Hud that a key was pressed, and toggles the corresponding * layer, if it exists. */ @Override public void notifyKeyPressed(KeyPressedEvent event) { Layer layer = getLayer(event.getSourceEvent().getKeyCode()); if (layer != null) { layer.toggle(); } } /** * Called by PluggableRobot when it's time to paint the Hud. */ void paint(long tick) { for (Layer layer : _layers) { layer.paint(_canvas, tick); } } /** * Returns the layer bound to the given key. */ private Layer getLayer(int key) { for (Layer layer : _layers) { if (layer.getKey() == key) { return layer; } } return null; } /** * Objects which implement the Painter interface and are registered * PluggableRobot will get their paint() methods called when it is time for * them to paint. Note that any one object that implements Painter may only * paint on one layer of the Hud. */ public interface Painter { /** * Notifies the Painter that it's time to paint, and provides it with a * Canvas object to paint with. */ public void paint(Canvas canvas, long tick); } /** * A single Hud layer, responsible for painting itself by calling the * Painters that which to paint on it. */ private static class Layer { private int _key; private String _name; private boolean _enabled; private ArrayList<Painter> _painters = new ArrayList<Painter>(); /** * Constructs a new Layer with the given name and bound to the indicated * key. The enabled argument determines whether or not the layer should * be on or off by default. */ Layer(int key, String name, boolean enabled) { _key = key; _name = name; _enabled = enabled; } /** * Returns the key to which this Layer is bound. */ int getKey() { return _key; } /** * Returns this Layer's name. */ String getName() { return _name; } /** * Adds a new Painter to this Layer. */ void addPainter(Painter painter) { _painters.add(painter); } /** * Returns whether or not this Layer is enabled. */ boolean isEnabled() { return _enabled; } /** * Toggles this Layer between being enabled and disabled. */ void toggle() { _enabled = !_enabled; } /** * Notifies the Painter that it's time to paint, and provides it with a * Canvas object to paint with. */ void paint(Canvas canvas, long tick) { if (!_enabled) { return; } for (Painter painter : _painters) { painter.paint(canvas, tick); } } } }
ListenerDelegate.java
/* * PluggableRobot, by Robert J. Walker * Home page: http://robowiki.net/w/index.php?title=PluggableRobot * This software is made available under the RoboWiki Limited Public Code * License (RWLPCL). The full text of the license may be found at: * http://robowiki.net/w/index.php?title=RWLPCL */ package rjw.pluggablerobot; import java.util.*; import robocode.*; /** * Class that manages all the event listeners for a PluggableRobot and delegates * events to the appropriate EventListeners. Unlike the default Robocode * behavior, events are doled out first by listener (first registered, first * notified), then by the order of the listener interfaces declared on the * listener implementation. This allows each component to get notified of events * in any order it likes, regardless of event priorities or the order used by * other components. * * PaintEvents are handled differently; they are captured and held until all * EventListeners have been notified and Components have acted, so that as much * information as possible is available for debug painting. * * @author Robert J. Walker */ public class ListenerDelegate implements EventListener._Paint { private static HashMap<Class, Invoker> _invokers; // Build the invoker map, so we can look up invokers by listener class static { _invokers = new HashMap<Class, Invoker>(); // interal paint event listener _invokers.put(_Paint.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof PaintEvent; } protected void invoke(EventListener listener, Event event) { ((_Paint) listener).notifyPaint((PaintEvent) event); } }); // interal key pressed event listener _invokers.put(_KeyPressed.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof KeyPressedEvent; } protected void invoke(EventListener listener, Event event) { ((_KeyPressed) listener).notifyKeyPressed( (KeyPressedEvent) event ); } }); // battle ended _invokers.put(EventListener.BattleEnded.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof BattleEndedEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.BattleEnded) listener).notifyBattleEnded( (BattleEndedEvent) event ); } }); // bullet hit _invokers.put(EventListener.BulletHit.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof BulletHitEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.BulletHit) listener).notifyBulletHit( (BulletHitEvent) event ); } }); // bullet hit bullet _invokers.put(EventListener.BulletHitBullet.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof BulletHitBulletEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.BulletHitBullet) listener) .notifyBulletHitBullet((BulletHitBulletEvent) event); } }); // bullet missed _invokers.put(EventListener.BulletMissed.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof BulletMissedEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.BulletMissed) listener).notifyBulletMissed( (BulletMissedEvent) event ); } }); // death _invokers.put(EventListener.Death.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof DeathEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.Death) listener).notifyDeath( (DeathEvent) event ); } }); // hit by bullet _invokers.put(EventListener.HitByBullet.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof HitByBulletEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.HitByBullet) listener).notifyHitByBullet( (HitByBulletEvent) event ); } }); // hit robot _invokers.put(EventListener.HitRobot.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof HitRobotEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.HitRobot) listener).notifyHitRobot( (HitRobotEvent) event ); } }); // hit wall _invokers.put(EventListener.HitWall.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof HitWallEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.HitWall) listener).notifyHitWall( (HitWallEvent) event ); } }); // robot death _invokers.put(EventListener.RobotDeath.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof RobotDeathEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.RobotDeath) listener).notifyRobotDeath( (RobotDeathEvent) event ); } }); // scanned robot _invokers.put(EventListener.ScannedRobot.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof ScannedRobotEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.ScannedRobot) listener).notifyScannedRobot( (ScannedRobotEvent) event ); } }); // skipped turn _invokers.put(EventListener.SkippedTurn.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof SkippedTurnEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.SkippedTurn) listener).notifySkippedTurn( (SkippedTurnEvent) event ); } }); // status _invokers.put(EventListener.Status.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof StatusEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.Status) listener).notifyStatus( (StatusEvent) event ); } }); // win _invokers.put(EventListener.Win.class, new Invoker() { protected boolean consumesEvent(Event event) { return event instanceof WinEvent; } protected void invoke(EventListener listener, Event event) { ((EventListener.Win) listener).notifyWin((WinEvent) event); } }); } private ArrayList<EventListener> _listeners = new ArrayList<EventListener>(); private PaintEvent _lastPaintEvent = null; public ListenerDelegate() { register(this); // register itself for the PaintEvent } /** * Register a new EventListener. */ public void register(EventListener listener) { _listeners.add(listener); } /** * Hand out event notifications to the EventListeners. */ public void processEvents(List<Event> events) { // Notify listeners in the order they were registered for (EventListener listener : _listeners) { Class[] interfaces = listener.getClass().getInterfaces(); // Iterate the interfaces on each listener for (Class iface : interfaces) { // Skip if interface does not descend from EventListener if (!EventListener.class.isAssignableFrom(iface)) { continue; } // Get the invoker for this interface Invoker invoker = _invokers.get(iface); // Find the events this invoker consumes for (Event event : events) { // Skip if listener isn't interested in this kind of event if (!invoker.consumesEvent(event)) { continue; } // Notify the listener invoker.invoke(listener, event); } } } } /** * Called by a special internal EventListener to handle PaintEvents. */ @Override public void notifyPaint(PaintEvent event) { _lastPaintEvent = event; } /** * Returns the most recently received PaintEvent, or null if no PaintEvent * has been received. */ public PaintEvent getLastPaintEvent() { return _lastPaintEvent; } /** * An object that knows about a Robocode Event class and how to invoke its * corresponding EventListener. */ private static abstract class Invoker { protected abstract boolean consumesEvent(Event event); /** * Invokes the given EventListener, passing in a Robocode Event object. */ protected abstract void invoke(EventListener listener, Event event); } }
Math2.java
/* * PluggableRobot, by Robert J. Walker * Home page: http://robowiki.net/w/index.php?title=PluggableRobot * This software is made available under the RoboWiki Limited Public Code * License (RWLPCL). The full text of the license may be found at: * http://robowiki.net/w/index.php?title=RWLPCL */ package rjw.pluggablerobot; import java.awt.geom.Point2D; import java.util.Random; import robocode.util.Utils; /** * Math utility class. Note that trig functions are reversed in order to provide * correct results for the Robocode coordinate system. * * @author Robert J. Walker */ public final class Math2 { public static final double PI_OVER_2 = Math.PI / 2; private static final Random random = new Random(); private Math2() { } /** * Returns a random int between the min and max arguments, inclusive. */ public static int randomInteger(int min, int max) { return random.nextInt(max - min + 1) + min; } /** * If value is less than min, returns min. If value is greater than max, * returns max. Otherwise, returns value. */ public static double limit(double min, double value, double max) { return Math.max(min, Math.min(value, max)); } /** * Adds the X and Y components of the given Point2D.Double objects and * returns a new Point2D.Double object with the result. */ public static Point2D.Double add(Point2D.Double point1, Point2D.Double point2) { return new Point2D.Double(point1.x + point2.x, point1.y + point2.y); } /** * Subtracts the X and Y components of the second given Point2D.Double * object from those of the first and returns a new Point2D.Double object * with the result. */ public static Point2D.Double subtract(Point2D.Double point1, Point2D.Double point2) { return new Point2D.Double(point1.x - point2.x, point1.y - point2.y); } /** * Returns the absolute bearing in radians from the given origin point to * the given target point. */ public static double getAbsoluteTargetBearing(Point2D.Double origin, Point2D.Double target) { return Utils.normalAbsoluteAngle(Math.atan2(target.x - origin.x, target.y - origin.y)); } /** * Returns a Point2D.Double object indicating the relative position of an * object at the given angle (in radians) and distance from the origin. */ public static Point2D.Double getRelativePosition(double angle, double distance) { double dx = distance * Math.sin(angle); double dy = distance * Math.cos(angle); return new Point2D.Double(dx, dy); } /** * Returns a Point2D.Double object indicating the position of an object at * the given angle (in radians) and distance from the given origin point. */ public static Point2D.Double getAbsolutePosition(Point2D.Double origin, double angle, double distance) { double x = origin.x + distance * Math.sin(angle); double y = origin.y + distance * Math.cos(angle); return new Point2D.Double(x, y); } /** * Converts degrees to radians. */ public static double degToRad(double degrees) { return Math.toRadians(degrees); } /** * Converts radians to degrees. */ public static double radToDeg(double radians) { return Math.toDegrees(radians); } }
PluggableRobot.java
/* * PluggableRobot, by Robert J. Walker * Home page: http://robowiki.net/w/index.php?title=PluggableRobot * This software is made available under the RoboWiki Limited Public Code * License (RWLPCL). The full text of the license may be found at: * http://robowiki.net/w/index.php?title=RWLPCL */ package rjw.pluggablerobot; import java.awt.Graphics2D; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.geom.Point2D; import java.util.ArrayList; import rjw.pluggablerobot.Hud.Painter; import robocode.*; /** * An abstract robot class that provides a pluggable architecture, sophisticated * event management and advanced debug graphics handling. * * @author Robert Walker */ public abstract class PluggableRobot extends AdvancedRobot { private static boolean _battleInitialized = false; private static Point2D.Double _center; private ListenerDelegate _listenerDelegate; private ArrayList<Component> _components = new ArrayList<Component>(); private Hud _hud; public PluggableRobot() { _listenerDelegate = new ListenerDelegate(); } /** * PluggableRobot's main execution loop. Rather that implementing run() in * your own robot, you will register listeners, components and painters in * the initRound() method, and those objects will handle your robot's combat * logic. This allows you to more easily separate concerns into separate * objects, and replace parts to change robot behavior. */ @Override public final void run() { // Initialize battle (at start of first round only) if (!_battleInitialized) { _center = new Point2D.Double(getWidth() / 2, getHeight() / 2); initBattle(); _battleInitialized = true; } // Mechanism for capturing all events and handing them to the // ListenerDelegate. addCustomEvent(new Condition("eventManager") { public boolean test() { PluggableRobot.this.handleEvents(); return false; } }); // Initialize the Hud _hud = new Hud(this); registerListener(_hud); // Allow robot to initialize its parts initRound(); // Main loop while (true) { // Let each component act for (Component component : _components) { component.go(); } // Handle painting PaintEvent pe = _listenerDelegate.getLastPaintEvent(); if (pe != null && pe.getTime() == getTime()) { _hud.paint(getTime()); } execute(); } } /** * Returns a Point2D object located at the exact center of the battlefield. */ public Point2D.Double getCenter() { return _center; } /** * Called by PluggableRobot at the start of a battle. Your implementation of * this method should perform whatever operations you wish to handle at the * start of a battle, such as setting tank colors and initializing memory * objects that will persist between rounds. */ protected abstract void initBattle(); /** * Called by PluggableRobot at the start of each round. Your implementation * of this method should create Hud layers, register your robot's * EventListeners, Components and Painters, and perform any other operations * you wish to handle at the start of a round. */ protected abstract void initRound(); /** * Registers an EventListener. Registration lasts until the end of the round * and enables the listener to receive event notifications. */ protected final void registerListener(EventListener listener) { _listenerDelegate.register(listener); } /** * Registers a Component. Registration lasts until the end of the round and * enables the Component to be notified when it is time to act. */ protected void registerComponent(Component component) { _components.add(component); } /** * Constructs a new Hud layer with the given name and bound to the indicated * key. The enabled argument determines whether or not the layer should * be on or off by default. */ protected void createLayer(int key, String name, boolean enabled) { _hud.createLayer(key, name, enabled); } /** * Registers a Painter and binds it to the layer corresponding to the given * key. Registration lasts until the end of the round and enables the * Painter to draw on a Hud layer when it's time to paint. */ protected void registerPainter(int key, Painter painter) { _hud.registerPainter(key, painter); } /** * Called by a custom event registered by PluggableRobot. This method hands * the event list to the ListenerDelegate, which will in turn notify the * EventListeners in the desired order. */ private void handleEvents() { _listenerDelegate.processEvents(getAllEvents()); clearAllEvents(); } /* * Since we've got our own event handling mechanism, we don't want to use * the existing one, so make these methods final. */ @Override public final void onBattleEnded(BattleEndedEvent event) { } @Override public final void onBulletHit(BulletHitEvent event) { } @Override public final void onBulletHitBullet(BulletHitBulletEvent event) { } @Override public final void onBulletMissed(BulletMissedEvent event) { } @Override public final void onCustomEvent(CustomEvent event) { } @Override public final void onDeath(DeathEvent event) { } @Override public final void onHitByBullet(HitByBulletEvent event) { } @Override public final void onHitRobot(HitRobotEvent event) { } @Override public final void onHitWall(HitWallEvent event) { } @Override public final void onKeyPressed(KeyEvent e) { } @Override public final void onKeyReleased(KeyEvent e) { } @Override public final void onKeyTyped(KeyEvent e) { } @Override public final void onMouseClicked(MouseEvent e) { } @Override public final void onMouseDragged(MouseEvent e) { } @Override public final void onMouseEntered(MouseEvent e) { } @Override public final void onMouseExited(MouseEvent e) { } @Override public final void onMouseMoved(MouseEvent e) { } @Override public final void onMousePressed(MouseEvent e) { } @Override public final void onMouseReleased(MouseEvent e) { } @Override public final void onMouseWheelMoved(MouseWheelEvent e) { } @Override public final void onPaint(Graphics2D g) { } @Override public final void onRobotDeath(RobotDeathEvent event) { } @Override public final void onScannedRobot(ScannedRobotEvent event) { } @Override public final void onSkippedTurn(SkippedTurnEvent event) { } @Override public final void onStatus(StatusEvent e) { } @Override public final void onWin(WinEvent event) { } }