Last time, I introduced the idea of building an F# robot for Robocode. The second iteration contains some improvements:
You may recall me saying that the first version of this robot could be defeated by a wall. While trying to implement this feature, it became clear that firepower
didn’t represent enough state for the BetaFish robot to care about. There were a number of intermediate versions between last post’s code and the above, as I experimented with created a class to encapsulate state.
While trying to use multiple classes, I was stymied for a time by Visual Studio. In an F# project, it wasn’t clear to me how to spread my solution over multiple source files. I couldn’t reference my other classes. I discovered that in a functional language, it’s necessary to order the source files to resolve dependencies, so that items do not depend on other items that are compiled afterward. It turned out that the classes I wanted to use came after the main class in alphabetical order. In Visual Studio, you can reorder source files in an F# project by right-clicking the source file in Source Explorer and moving it up or down.
After a number of iterations, I discarded that secondary class in favor of a discriminated union, which I called ActionType
. Conceptually, a discriminated union is kind of like a generic C# enumeration, but of course much more useful. For example, notice that the Evade
and Attack
elements take a float
argument, whereas the others don’t. And pattern matching provides a more robust way to examine the contents of an ActionType
than C# enumeration’s ever would. To accomplish this in C#, you’d need a hierarchy of classes.**
**
The Run
method has become more sophisticated also, now matching against the AttackType
instead of just a scalar value. Notice that I’m able to name the union type’s argument inline, such as in the case of Evade
’s bearing
. This is a feature of pattern matching, not discriminated unions, as you can see with strength
in the OnBulletHit
event handler.
**
NOTE: While this code looks more impressive, it actually stinks in battle. If you try this robot, you’ll find that once BetaFish engages the enemy, the robot freezes in battle as soon as it’s hit, twitching until it is annihilated. Can you see why? The next article in the series contains the answer.