/* * ModdedBot.java * by: Vuen * * Last edited on November 7, 2003 */ package mod; import robocode.*; import java.util.Vector; import java.util.Iterator; /* This is the robot template for creating a Robocode mod. Robots playing your * mod should extend this rather than AdvancedRobot; you can then add any * functionality you like. */ public class ModdedBot extends AdvancedRobot { //These are private variables that hold needed info private boolean isInit; private Vector events; //Holds all robot events private Vector eventsfake; //Holds fake events before they are added to events vector /* This is the initialization method of your robot. It gets called at the * start of every round. The robot usually can perform a few calculations * before this is called, but you should not have to worry; if you would * like this to be guaranteed to be called before the robot does something, * an example of this is below. */ private void init() { if (isInit) return; isInit = true; super.addCustomEvent(new Condition("ModdedBot", 99) {public boolean test() {events(); return false;}}); eventsfake = new Vector(); //Add any code you would like that initializes your mod in here. } /* Suppose we would like to guarantee that the robot be initialized before * the robot uses getHeading(): */ public double getHeading() { init(); return super.getHeading(); } /* You can delete this example method if you like. */ /* This method handles the events in the robot. Whatever you would like the * mod to do upon receiving an event, do it here. Do NOT override the * onBla(BlaEvent) methods. */ private void events() { if (events != null) events.clear(); events = super.getAllEvents(); eventsfake.clear(); super.clearAllEvents(); Iterator i = events.iterator(); while (i.hasNext()) { Event event = (Event)i.next(); //This is where we handle the events we want to handle. //This contains sample code to remove certain scans, and // to catch robot deaths. Remove the below sample code when // you create your mod. if (event instanceof ScannedRobotEvent) { //Suppose we would like to disallow a robot from scanning a ScoreBot: ScannedRobotEvent scan = (ScannedRobotEvent)event; if (scan.getName().indexOf("ScoreBot") > -1) i.remove(); //remove the event from the events vector //it is now impossible for the robot to receive ScoreBot scans. } else if (event instanceof BulletMissedEvent) { //Suppose we want to do something when a bullet goes offscreen: BulletMissedEvent miss = (BulletMissedEvent)event; //do stuff using this event //Note that the robot will still receive this event even if we used it. } else if (event instanceof BulletHitEvent) { //Suppose we want to generate a RobotDeathEvent instead of a // BulletHitEvent when the enemy's bullet hits another robot BulletHitEvent hit = (BulletHitEvent)event; //create new RobotDeathEvent and add to fakes eventsfake.add(new RobotDeathEvent(hit.getName())); //remove the BulletHitEvent i.remove(); //The robot will now receive a RobotDeathEvemt instead of a // BulletHitEvent; the robot will not be able to tell the // difference between the real RobotDeathEvents and the ones // created by the mod. } } /**Here you can create any fake events you would like. You can also * make your own event classes, or make event classes that extend * some of the events that already exist. I suggest you package custom * event classes in the same package as your ModdedBot. Whatever events * you create, add them to the eventsfake Vector when you want them to * be sent to the robot. */ events.addAll(eventsfake); eventsfake.clear(); } /* This event parses the events and calls the proper event handlers.*/ private void dump() { if (events == null) return; for (int i = 0; i < events.size(); i++) { //If you have created any of your own custom event classes, add them // here BEFORE the rest of the events get parsed, and change the // next line to else if so that any events you have extended won't // fire twice. //If you haven't created any custom event classes, you don't need // to modify this method. if (events.get(i) instanceof ScannedRobotEvent) onScannedRobot((ScannedRobotEvent)events.get(i)); else if (events.get(i) instanceof RobotDeathEvent) onRobotDeath((RobotDeathEvent)events.get(i)); else if (events.get(i) instanceof HitRobotEvent) onHitRobot((HitRobotEvent)events.get(i)); else if (events.get(i) instanceof HitWallEvent) onHitWall((HitWallEvent)events.get(i)); else if (events.get(i) instanceof HitByBulletEvent) onHitByBullet((HitByBulletEvent)events.get(i)); else if (events.get(i) instanceof BulletHitEvent) onBulletHit((BulletHitEvent)events.get(i)); else if (events.get(i) instanceof BulletMissedEvent) onBulletMissed((BulletMissedEvent)events.get(i)); else if (events.get(i) instanceof BulletHitBulletEvent) onBulletHitBullet((BulletHitBulletEvent)events.get(i)); else if (events.get(i) instanceof CustomEvent) onCustomEvent((CustomEvent)events.get(i)); else if (events.get(i) instanceof SkippedTurnEvent) onSkippedTurn((SkippedTurnEvent)events.get(i)); else if (events.get(i) instanceof WinEvent) onWin((WinEvent)events.get(i)); else if (events.get(i) instanceof DeathEvent) onDeath((DeathEvent)events.get(i)); else printError("Unknown Event!! This event is unhandled: " + events.get(i).getClass().getName()); } events.clear(); events = null; } /* This is your go method. This is always called at the end of every tick, * after the robot has performed its actions. */ private void go() { init(); //Put anything you would like your mod to do each tick in here. } /* The following chunk of methods provides the functionality of all the * getXXXEvents methods in the robot. Since we parse the events manually, * we have to rebuild these methods to allow the extending robot to use * them. If you have any custom event classes, you should add a * getXXXEvents for your class to provide the robot with this function. * Note that if you extend any of the existing events, they will NOT be * returned by the getXXXEvents method of the class they extend; you can * modify the parseEvents method to provide this functionality if you want. * * If you have not created any custom event classes, you do not need to * modify this code. */ public Vector getAllEvents() {return events;} public void clearAllEvents() {events.clear(); events = null;} public Vector getScannedRobotEvents() {return parseEvents("robocode.ScannedRobotEvent");} public Vector getRobotDeathEvents() {return parseEvents("robocode.RobotDeathEvent");} public Vector getHitRobotEvents() {return parseEvents("robocode.HitRobotEvent");} public Vector getHitWallEvents() {return parseEvents("robocode.HitWallEvent");} public Vector getHitByBulletEvents() {return parseEvents("robocode.HitByBulletEvent");} public Vector getBulletHitEvents() {return parseEvents("robocode.BulletHitEvent");} public Vector getBulletMissedEvents() {return parseEvents("robocode.BulletMissedEvent");} public Vector getBulletHitBulletEvents() {return parseEvents("robocode.BulletHitBulletEvent");} private Vector parseEvents(String type) { Vector newevents = new Vector(); for (int i = 0; i < events.size(); i++) {if (events.get(i).getClass().getName().equals(type)) newevents.add(events.get(i));} return newevents; } public void addCustomEvent(Condition condition) { init(); //make sure our condition is first super.addCustomEvent(condition); } /* Here's the fun part: you can now add any mod methods to the robot you * want! Suppose the robot has a powerup, and we want it to return the time * remaining on the powerup: */ private long powerUpTime; public long getPowerUpTime() { return powerUpTime; } /* You can see here that you can add to your mod any method you could * possibly want the extending robot to call. Note that for methods like * this, you would put in the go() method the code to handle the amount * of time remaining on the powerup. */ //This is just a debugger method; it will call whenever an error occurs // within the mod. You can call this or remove this or do whatever you want // with it; debug your mod however you like. private void printError(String text) { System.out.println("[" + getTime() + "] Mod Error! " + text); } /* The following block of code is what allows the extending robot to use * any blocking calls they wish, and still allow the mod to get a go() * every tick. You should not need to modify any of the below code, unless * you want to prevent the robot from performing any of these actions. */ public void execute() { go(); super.execute(); dump(); } public void doNothing() {execute();} public void scan() { go(); super.scan(); dump(); } public void fire(double power) { go(); super.fire(power); dump(); } public Bullet fireBullet(double power) { go(); Bullet bullet = super.fireBullet(power); dump(); return bullet; } public void ahead(double distance) { setAhead(distance); while (getDistanceRemaining() > 0) { scan(); } } public void back(double distance) {ahead(-distance);} public void turnRightRadians(double angle) { setTurnLeftRadians(angle); while (getTurnRemaining() != 0) { scan(); } } public void turnLeftRadians(double angle) {turnRightRadians(-angle);} public void turnRight(double angle) {turnRightRadians(Math.toRadians(angle));} public void turnLeft(double angle) {turnRight(-angle);} public void turnGunRightRadians(double angle) { setTurnGunRightRadians(angle); while (getGunTurnRemaining() != 0) { scan(); } } public void turnGunLeftRadians(double angle) {turnGunRightRadians(-angle);} public void turnGunRight(double angle) {turnGunRightRadians(Math.toRadians(angle));} public void turnGunLeft(double angle) {turnGunRight(-angle);} public void turnRadarRightRadians(double angle) { setTurnRadarRightRadians(angle); while (getRadarTurnRemaining() != 0) { scan(); } } public void turnRadarLeftRadians(double angle) {turnRadarRightRadians(-angle);} public void turnRadarRight(double angle) {turnRadarRightRadians(Math.toRadians(angle));} public void turnRadarLeft(double angle) {turnRadarRight(-angle);} }