By David McCoy


Background

I was introduced to Robocode when a coworker decided to run weekly in-office matches. I was immediately fascinated and quickly put together a prototype bot for the competition.

The prototype helped me understand the Robocode API, but proved to be a poor overall design. PrairieWolf was my first real attempt at a competition bot, designed to take advantage of what I learned from the prototype.


Structure

PrairieWolf was designed with flexibility and extensibility in mind. Three state managers (sensors, tactical, and navigation) swap individual state classes in and out based on the circumstances. This architecture allows new logic to be added easily without impacting existing code.

PrairieWolf was designed to be too complex to be easily analyzed during combat. It attempts to find the most effective movement pattern for each opponent and remembers opponents for up to a month between encounters.

PrairieWolf's architecture is somewhat unique in that it runs in a single thread, unlike most of the leading bots. PrairieWolf was also the first bot (to my knowledge) to use a file to remember opponents between encounters.


Sensors
Sensors are responsible for radar movement and recording radar contacts.
Circular Scan (Multiple Enemies) This was originally PrairieWolf's only radar state. It provides maximum radar sweep area and the advantage of being able to monitor all opponents simultaneously. It is well suited to melee combat.
Narrow Scan (Single Enemy) This state provides a narrow side-to-side radar sweep of an opponent. I added this state to reduce the time delay between radar contacts during one-on-one combat. I tried to use a sweep narrow enough to provide timely radar contacts yet wide enough that PrairieWolf wasn't likely to lose it's target.


Tactical
Tactical is responsible for choosing targets, determining shot power, calculating firing angles, and firing once the turret is in position.
I have thus far devoted very little time to tactical. I believe evading enemy fire is ultimately much more important than the number of hits scored on the enemy.
Target Nearest Enemy (Multiple Enemies) This state originally always targeted the nearest enemy - this tended to attract the attention of too many other bots at once. I later modified this state to only switch targets if the active target was destroyed, the active target moved out of optimal firing distance, or if another bot became disabled.
The firing algorithm is very primitive, plotting target movement using only the target's current speed and a rough approximation of the target's rate of turn.
Simple Predictive (Single Enemy) This is roughly equivalent to the Target Nearest Enemy state, but with the target switching logic removed for speed.


Navigation
Navigation is responsible for picking the best possible movement pattern for the circumstances. Different classes of pattern are used depending on the number of enemies within view.
Corners (Multiple Enemies) Attempts to stay as close to the walls as possible, while attempting to avoid other bots. This was one of the first states I had planned, yet one of the last I implemented. Ultimately, it proved to be the best melee state for most situations. PrairieWolf utilizes this state exclusively on battlefields of 1000x1000 or less.
Evade (Multiple Enemies) Every successful bot seems to utilize (at least to some degree) an anti-gravity algorithm. I decided PrairieWolf should be no different. In addition to distance, PrairieWolf also factors the other bots' bearings in to this calculation. While this was once PrairieWolf's mainstay for melee combat, it is now only used on battlefields larger than 1000x1000.
Perimeter (Multiple Enemies) This was an early attempt at keeping PrairieWolf out of the fray. It is basically an extension of the Evade state, factoring in the center of the battlefield as an additional evade point. It seemed like a good idea at the time, but proved somewhat less effective than planned.
Weave (Multiple Enemies) This was PrairieWolf's original all-purpose movement state. The plan was to navigate in graceful half-circles, reversing at the end of each arc. This state was removed after it became clear the only thing it was good for was racking up unbelievable ram damage.
Cautious Approach (Single Enemy) Sometimes the best defense is a good offense, but using a head-on approach often makes a bot cannon fodder. This state attempts to resolve this problem by approaching the enemy in side-to-side arcs.
Dodge (Single Enemy) This was PrairieWolf's first single-fight state. It started as a back-and-forth pattern very similar to (though not half as graceful or effective as) the pattern used by MadHatter. I later changed this state to use an anti-gravity algorithm designed specifically for a single enemy.
Finisher (Single Enemy) Impressed with Wolverine's very classy finishing move for disabled opponents, I decided PrairieWolf needed a finishing move as well. I spent considerable time designing and implementing a special state to do a little dance before finishing off disabled opponents. However, after watching several bots come back to win after a still-active bullet hit PrairieWolf in mid-dance, I decided showing off was best left to those who could actually pull it off. ;-)
Opposing Orbit (Single Enemy) Being somewhat mathematically challenged, I quickly realized my opponents were likely to have much more elegant one-on-one movement strategies than PrairieWolf. This state is my attempt at using an opponent's strength against them - it keeps PrairieWolf in an opposing orbit around the center of the battlefield from it's opponent. Simple, but very effective against some bots.
Orbit Enemy (Single Enemy) This is the mainstay of PrairieWolf's one-on-one navigation. It keeps PrairieWolf in an orbit around it's opponent, moving only when shot at or when the opponent gets too close.
Reflection (Single Enemy) Another one of my early states that seemed like a good idea at the time, but didn't quite pan out. The plan was for PrairieWolf to mirror it's opponent's movements; using the opponent's own movement strategy against them. In reality it made PrairieWolf fumble around clumsily and run in to the walls a lot.
Search (No Enemies Visible) I despise bots that hide away, refusing to engage any opponents until the fighting dies down and all the other bots are badly damaged. This state is my attempt at keeping PrairieWolf from falling in to that category - it puts PrairieWolf in a circular search pattern around the center of the battlefield whenever all contact is lost with other bots.


What's Next?

PrairieWolf is far from finished. I have planned several additional movement states in addition to a complete rework of the sensor and navigation systems. I may also add a separate pattern analyzer if I start getting lost turn events using PrairieWolf's current single-threaded architecture.