Robocode Lab: PartsBot

Or: using interfaces and inner classes

You may find the following information useful. These are links to Sun's online Java tutorials.

Specifications

Write an interface called RobotPart and three classes that implement it called Radar, Gun, and Tank.

All of these interfaces / implementing classes will be written inside an AdvancedRobot called PartsBot, making them all inner classes.

The RobotPart Interface

Declare an interface called RobotPart. It should have two method stubs: init() and move().

The Radar Class

Write a class called Radar that implements the RobotPart interface. You will need to override both of the interface's methods.

Additional convenience methods: As we discussed, you must override all the methods in interfaces that you implement, but you can certainly add additional methods if you want. In the test harness below I've added shouldTrack() and wasTracking() methods.

The Gun Class

Next, write a class called Gun that also implements the RobotPart interface. As before, you will need to override both of the interface's methods.

The Tank Class

Lastly, write a class called Tank that also implements the RobotPart interface. If you haven't figured it out already, you will need to override both of the interface's methods in this class too.

Test Harness

To test the various parts you wrote, you can start with the following skeleton code:

public class PartsBot extends AdvancedRobot {

	private AdvancedEnemyBot enemy = new AdvancedEnemyBot();

	RobotPart[] parts = new RobotPart[3]; // make three parts
	final static int RADAR = 0;
	final static int GUN = 1;
	final static int TANK = 2;

	public void run() {

		parts[RADAR] = new Radar();
		parts[GUN] = new Gun();
		parts[TANK] = new Tank();

		// initialize each part
		for (int i = 0; i < parts.length; i++) {
			// behold, the magic of polymorphism
			parts[i].init();
		}

		// iterate through each part, moving them as we go
		for (int i = 0; true; i = (i + 1) % parts.length) {
			// polymorphism galore!
			parts[i].move();
			if (i == 0) execute();
		}
	}

	public void onScannedRobot(ScannedRobotEvent e) {
		Radar radar = (Radar)parts[RADAR];
		if (radar.shouldTrack(e)) enemy.update(e, this);
	}

	public void onRobotDeath(RobotDeathEvent e) {
		Radar radar = (Radar)parts[RADAR];
		if (radar.wasTracking(e)) enemy.reset();
	}   

	// ... put normalizeBearing and absoluteBearing methods here

	// ...  declare the RobotPart interface and classes that implement it here
	// They will be _inner_ classes.

}

Link to starter file that contains previous test harness: PartsBot.java.

I'll show you a demo that uses this test harness in class.

Note that you can use all the outer class' methods and variables - including private members - inside the inner classes. Thus, you can make calls to setTurnRight() or setFire() without any qualifiers. You can also use the enemy variable in the inner classes as you normally would inside any of the outter class' methods.

Questions and Answers

Help! It won't compile!

The EnemyBot Q & A answers this.

What if I don't like any of the stock colors?

Then make your own. You can do it quite easily with the three-argument constructor of the Color class, like so:

  setColors(new Color(250, 13, 73), Color.green, Color.yellow);
Note that in the above example I'm using a custom color for the tank, and stock colors for the gun and radar. You can make them all custom, all stock, or mix-n-match. Your choice.

I'm getting lots of "symbol not found" errors

A common problem with this lab is mismatched curly braces. This happens a lot because you have so many inner classes, nested for loops, etc. The very best way to prevent this problem is to use proper indenting. For those of you who have eschewed proper indentation, dismissing it as just unfounded anal-retentiveness, this lab will painfully teach you the follies of your misguided and erroneous opinions.

How do I show you this lab working?

Using the above test harness, you can show me a robot zooming around the screen using all the parts you wrote.

What do you want me to turn in?

The PartsBot.java file with your name, the lab # and the course # at the top of the page in comments.

What's up with all those screwy .class files that were generated?

Glad you asked. This lab will illustrate how the Java compiler generates .class files for inner classes by concatenating the outer class name with the inner class name, putting a dollar sign ($) between them.

Will you pleeease show me the code for the shouldTrack() and wasTracking() methods?

Oh, fine. Here. Put these methods in the Radar class.

boolean shouldTrack(ScannedRobotEvent e) {
	// track if we have no enemy, the one we found is significantly
	// closer, or we scanned the one we've been tracking.
	return (enemy.none() || e.getDistance() < enemy.getDistance() - 70 ||
			e.getName().equals(enemy.getName()));
}

boolean wasTracking(RobotDeathEvent e) {
	return (e.getName().equals(enemy.getName()));
}