Jeremy Rayner on java and other stuff.

All | AudioDrama | Fun | Java | Life

LNE - my Robot strategist
Posted on 16 Mar 2004
... or how I applied the Strategy (315) pattern to Robocode.

download source code for this article (3Kb)

Taking the event based methods of AdvancedRobot into a Strategy interface

public interface Strategy {
    public void preRun();
    public void run();
    public void onBulletHit(BulletHitEvent event);
    public void onBulletHitBullet(BulletHitBulletEvent event);
    public void onBulletMissed(BulletMissedEvent event);
    public void onCustomEvent(CustomEvent e);
    public void onDeath(DeathEvent event);
    public void onHitByBullet(HitByBulletEvent event);
    public void onHitRobot(HitRobotEvent event);
    public void onHitWall(HitWallEvent event);
    public void onRobotDeath(RobotDeathEvent event);
    public void onScannedRobot(ScannedRobotEvent event);
    public void onWin(WinEvent event);
}

Then providing a simple adapter with a default implementation of each event method
public class StrategyAdapter implements Strategy {
    public void preRun() {}
    public void run() {}
    public void onBulletHit(BulletHitEvent event) {}
    public void onBulletHitBullet(BulletHitBulletEvent event) {}
    public void onBulletMissed(BulletMissedEvent event) {}
    public void onCustomEvent(CustomEvent e) {}
    public void onDeath(DeathEvent event) {}
    public void onHitByBullet(HitByBulletEvent event) {}
    public void onHitRobot(HitRobotEvent event) {}
    public void onHitWall(HitWallEvent event) {}
    public void onRobotDeath(RobotDeathEvent event) {}
    public void onScannedRobot(ScannedRobotEvent event) {}
    public void onWin(WinEvent event) {}
}

All this means that I could take an existing robot, and turn him into a strategic advisor. In the example below the sample WallRobot has been adapted into a strategist, simply by passing in a reference to the real robot that is in the arena, the WallStrategy can advise what action to take on any of the events it cares to override. So this means coding a strategy is just like coding a real robot, but you call i.turnLeft() instead of the implied super.turnLeft().
public class WallStrategy extends StrategyAdapter {
    private Robot i;
    private boolean peek;
    private double moveAmount;
    
    public WallStrategy(Robot robot) {
        this.i = robot;
    }
    
    public void preRun() {
        moveAmount = Math.max(
i.getBattleFieldWidth(),
 i.getBattleFieldHeight
());
        peek = false;
        i.turnLeft(i.getHeading() 90);
        i.ahead(moveAmount);
        peek = true;
        i.turnGunRight(90);
        i.turnRight(90);
    }
    
    public void run() {
        peek = true;
        i.ahead(moveAmount);
        peek = false;
        i.turnRight(90);
    }
    
    public void onHitRobot(HitRobotEvent e) {
        if (e.getBearing() > -90 && e.getBearing() 90) {
            i.back(100);
        else {
            i.ahead(100);
        }
    }
    
    public void onScannedRobot(ScannedRobotEvent e) {
        i.fire(2);
        if (peek) {
            i.scan();
        }
    }
}

All of this comes together in my robot LNE (Lenny), which uses the strategy above, but more importantly, when Lenny realises that the strategy is not working, he automatically changes strategy. (I think Lenny could grow into something beautiful...)
public class LNE extends AdvancedRobot implements Strategy {
    protected int current = 0;
    protected Strategy[] strategy = new Strategy[] {
                  new TagAlongStrategy(this)
                  new TrackFireStrategy(this),
    };
    
    public void run() {
        while (true) {
            int currentAtStartOfOuterWhileLoop = current;

            strategy[current].preRun();
            while (current == currentAtStartOfOuterWhileLoop) {
                strategy[current].run();
            }
        }
    }
    
    public void onBulletHit(BulletHitEvent e) {
        strategy[current].onBulletHit(e);
    }
    
    ...

    public void onHitByBullet(HitByBulletEvent e) {
        strategy[current].onHitByBullet(e);
        changeStrategy();
    }

    public void onWin(WinEvent e) {
        turnGunRight(36000);
    }

    private void changeStrategy() {
        clearAllEvents();
        current++;
        if (current == strategy.length) {
            current = 0;
        }
    }
}

Just a shame it didn't win :-)

16 Mar 2004 |

 

 
March 2004
SunMonTueWedThuFriSat
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Prev | Today | Next

rss:subscribe (All)



What I'm reading
my feed aggregator ->box
on my mobile

My websites
London Java Meetups
Elite in Java
megg
Blogmento
Jez's Photos
Fantasy Stock Market
Cool Saxophonist
Doctor Who Audios
Pisces Audios

Other Blogs
Mike Cannon-Brookes
James Strachan
Joe Walnes
Sam Dalton
Simon Brown
Cameron Purdy
Mike Roberts
Erik C. Thauvin
John Martin
Manfred Riem

B5 d++ t++ k s+ u- f
i+ o+ x-- e+ l- c--

powered by blogmento