Here are some general 'milestones' that were important (to me) along the way:
- Develop a debugging system. Be able to print some text as you go and some all at once at the end. Steal someone's file writing code and make it a debugging option.
- Predict what your bot's position, heading, and velocity will be next turn based on this turn's instructions.
- Develop a crude movement style.
- Develop a crude wall avoidance algorithm.
- Develop a crude enemy scan data structure.
- Review some basic trigonometry.
- Make your turret lock on to your enemy's position. Test it in all 4 quadrants.
- Make your radar lock on to your enemy's position, sweeping 22.5 degrees to either side of it.
- Fire your gun straight ahead and hit a sitting target.
- Predict where your enemy's position will be if he keeps going straight ahead at his present speed for n turns.
- Determine if a bullet fired now could hit the target at turn n, limited to 11.0~19.7 distance/tick (min/max bullet velocity).
- Hit your target using linear projection.
- Adjust your prediction slightly to account for your bullet not actually firing until after you and your target have been moved one tick.
- Improve your enemy scan data structure to include one additional scan history.
- Predict where your enemy's position will be if he keeps changing heading at the same rate at his present speed for n turns.
- Hit your target using circular projection.
You should now be able to beat all sample robots.
I put debugging first because it's that important. Some things I did that you may want to implement:
- a line item display that goes to the console
- a 'self-debug' mechanism that you can send to the console or a file, depending on the level of output you need at present (too much to the console in a turn gets truncated)
- an exception mechanism for formatting and persisting exceptions thrown (which could be handy when running blind like in the roborumble)
- a 'String trim( double )' method for displaying doubles truncated to significant digits
- most of my classes have a 'public void debug()' method that formats debugging information (i.e. member field values) and sends it to the 'self-debugging' mechanism. It makes displaying debug information a breeze. I just tell objects to debug themselves.
-- Martin Alan Pedersen
Q: How does firing at an opponent work?
A: Letís start with a basic example: Turn 29, you instruct your gun to turn x degrees / radians. Turn 30, you instruct your gun to fire. Turn 31, your gun fires.
Now letís give some context to all of that. The instruction to fire is processed before the instructions to move or turn your gun. This means that you cannot aim and fire in the same turn, so you must aim one turn and fire the next. Your tank will also move once before firing (the same turn you are aiming). Your opponent will also be moving while you are aiming, possibly changing speed and heading. Your data will always be one turn old between deciding where to shoot and shooting.
Second illustration: In turn 29, you receive a ScannedRobotEvent, and use the data to determine the enemy robotís position. Afterward, using your movement strategy, you determine where your own robot should go and what position it will be in turn 30 as a result of movement instructions. Analyzing your opponents position and behavior, you decide what bullet power to use and angle to fire at from your future (Turn 30) position. To conclude turn 29, you tell the AdvancedRobot super class to set the throttle (Ahead) and adjust the tankís chassis, gun, and radar headings, concluding with the execute() blocking call.
In turn 30, you receive another ScannedRobotEvent, decide where to move, and how to aim (since you may as well keep aiming to keep your gun close to where it will need to be when you can fire again). To conclude turn 30, in addition to the previous instructions, you call setFire with the bullet power chosen in Turn 29.
On the server side of Turn 31 (before you are returned control of your robot), the new bullet is fired from your cool gun and travels one bulletVelocity (translated from bulletPower) length, and all other bullets are also moved. Then all bot position and chassis heading changes are processed. Then guns are rotated, and finally radars, resulting in ScannedRobotEvents for Turn 31.
-- Martin Alan Pedersen
[Along the lines of debugging, I would also add a couple key things from my experiences:
Try RobocodeGL or RobocodeSG Use the graphical features now built into Robocode ... Being able to draw on the screen can make debugging a LOT easier than it is when you're just reading a bunch of numbers from the console and piecing together what they mean.
- Test methods and modules, even at the most basic level. Robocode can get addictive! If you're trying to push something out, you might think, "this is so simple, it _obviously_ works, so I won't test it." These bugs can be very hard to find, too, and may ruin an otherwise well-designed system. It reminds me of a quote by Steve McConnell?: "It's hard enough to find an error in your code when you're looking for it; it's even harder when you've assumed your code is error-free."