Robocode Homework: OutputBot

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

Specifications

Write (or modify an existing) bot that prints information about the robot it's tracking to a file. It should also output predictive targeting information to help you debug it.

Detail

You will probably want to modify an existing bot that you've written to date, rather than start over from scratch. The notes in this lab make this assumption.

  1. Create two new private class variables inside your robot: a PrintStream (call it ps) and a NumberFormat (call it f).
  2. Near the top of your run() method, before the while (true) loop, set up the NumberFormat object like so:
    1. Construct it, not with a constructor, but by calling the static getNumberInstance method like so:
      f = NumberFormat.getNumberInstance();
    2. Set the maximum number of decimal places you want to have shown by calling the setMaximumFractionDigits() method. (Hint: pass it a small number like, oh say, 1 or 2.)
  3. Just after you set up the NumberFormat class, set up the output file like so:
    1. Get a reference to the data file you can use by calling getDataFile() like so:
      File file = getDataFile("output.dat");
    2. Construct a new RobocodeFileOutputStream, passing it the reference to the data file you just got, and pass the new RobocodeFileOutputStream to the constructor for a new PrintStream. (This is the "nested constructors" thing we talked about in class.) Store the new PrintStream in the 'ps' class variable you declared earlier.

      Note #1: Do not re-declare a local 'ps' var inside run(), it will create oodles of problems.

      Note #2: You will need to handle the exception that could be thrown when constructing the new PrintStream by using a try..catch statement.

  4. Down in your doGun() method (or wherever you're doing your targeting) use the PrintStream object to print output to your file. Here's an example to get you started:
    	ps.println("Tracking: " + enemy.getName() + " at (x,y) (" + 
    		f.format(enemy.getX()) + ", " + f.format(enemy.getY()) + ")");
    	
  5. You will need to close your output stream when the round is over. There are two ways the round can end for you: your bot dies, or your bot wins. To handle both of these, please ovverride both the onWin and onDeath methods and put the following code in there:
    	if (ps != null) ps.close();
    	

Sample Output

Here's an example of the kind of output I'm looking for. You might output a little bit more or a little bit less, but I'm expecting something along these lines.

Tracking: sample.Fire at (x,y) (384.1, 53.2)
  firePower = 2.1, bulletSpeed = 13.7, time = 13
  futureX = 384.1, futureY = 53.2, absDeg = 97.3, turn = 2.4

Tracking: sample.Fire at (x,y) (384.1, 53.2)
  firePower = 2.1, bulletSpeed = 13.7, time = 13
  futureX = 384.1, futureY = 53.2, absDeg = 99.7, turn = 2.4

Tracking: sample.Fire at (x,y) (384.1, 53.2)
  firePower = 2.1, bulletSpeed = 13.7, time = 13
  futureX = 384.1, futureY = 53.2, absDeg = 102.1, turn = 2.4

Tracking: sample.RamFire at (x,y) (181.4, 197)
  firePower = 3, bulletSpeed = 11, time = 9
  futureX = 181.4, futureY = 197, absDeg = 344.2, turn = -117.9

Tracking: sample.RamFire at (x,y) (181.4, 197)
  firePower = 3, bulletSpeed = 11, time = 9
  futureX = 181.4, futureY = 197, absDeg = 341, turn = -97.1

...

Questions and Answers

Do I derive this bot from Robot or AdvancedRobot?

AdvancedRobot for sure. The Robot class does not let you write to an output file.

I'm getting a lot of "Cannot resolve symbol" errors.

Are you importing all the right packages? You'll need these two to get the file IO and NumberFormat classes respectively:

import java.io.*;
import java.text.NumberFormat;

Where do I put this file?

Put it in the c:\robocode\robots\[initials] directory with your other robots.

You do need to print it up and give me a copy, though.

So, where the heck do I find this output file?

In the c:\robocode\robots\[initials]\[robotname].data directory.

Why do I have to use the NumberFormat thinger?

No one is making you use it, but here's what the output looks like if you don't:

Tracking: sample.TrackFire at (x,y) (559.5203855902, 254.8100637962)
  firePower = 3, bulletSpeed = 11, time = 6
  futureX = 559.5203855902, futureY = 254.8100637962, absDeg = 308.3014154079, turn = 3.1290191007

Given the choice, I think you might prefer something more like:

Tracking: sample.Fire at (x,y) (384.1, 53.2)
  firePower = 2, bulletSpeed = 14, time = 14
  futureX = 384.1, futureY = 53.2, absDeg = 79.8, turn = -1.5

Can I print debug output for more than just the targeting?

Of course, be my guest. The whole point here is to show you guys how you can dump debug noise to a file for postmortem analysis.

How do I show you this working?

Show me your robot running around the screen and bring up his output in a text editor.

What do you want me to turn in?

A printout of the code for the outputting robot with your name, the course number (etc.) at the top of the page in comments.

What's the deal with the AccessControlException it keeps throwing?

You have discovered a bug in the 1.4.2 JDK. There was a bug report posted to Sun and they've issued the following workaround: just start the JVM with this command-line parameter: -Dsun.io.useCanonCaches=false. IOW, start Robocode like so:

java -Dsun.io.useCanonCaches=false -Xmx256M -jar robocode.jar

That will fix the problem and you will be able to run your OutputBot without it constantly throwing those exceptions.

To fix this once and for good, edit the robocode.bat (or robocode.sh file on Linux) and make sure it looks like the line above.

Credit where it's due: I found this solution on the Robocode Repository right here.