A few weeks ago, I wrote about the marvelous little virtual minions that I created through the wonder that is Robocode. Now, one might have presumed that my robots were mere results of simple exercises no more exemplary of a battle worthy digital tank than a twig is of a shady oak tree. However, if one were to have thought that, then one would have failed to overlook that when thirteen twigs are combined, they would most definitely create something greater! Such as a branch perhaps?
To be certain, the general goal of this new endeavor was to create a robot that would compete among its peers in the virtual arenas in all of their 40 by 40 pixels of glory. In my efforts to accomplish this goal, I forged together a chimera of my previous iterations of single-function robots to create a single entity armed with the three basic principles of a Robocode robot: Movement, Targeting and Firing. Additionally, as any good robot knows, its primary edict in life is the Three Laws of Robotics. Now, if you will all recall from our previous discussion of the Three Laws of Robotics, the first two laws don't really factor much into Robocode robots. Thus, the ThirdRobotLaw robot was conceived, with its utmost priority being the protection of its own life.
ThirdRobotLaw, or TRL as I've come to know the little bugger as, was designed with a focus on survival. As such, it was determined that the strategy for its movement would be to minimize opportunities to be hit by its opponents. What this entails is that first we had to reduce the potential angles of attack by enemies. Hugging a wall, as it turns out, was an obvious choice since it immediately reduced a fourth of the cardinal directions from which bullets could come from. Upon the battle starting, TRL picks either the West or East wall to run towards in a true coward's fashion by determining which wall is closer. Upon reaching a wall, TRL changes to one of two modes depending on the number of enemies left on the battlefield. The first mode, if there are more than one enemies remaining is to randomly choose a direction between North and South and glide towards it at a random interval. The idea behind this mode is that if the enemy of TRL's enemy is the enemy of that other guy. TRL deviously hides along the wall and shuffles along at random and hopes that its enemies kill each other off. However, when the battlefield participants dwindle down to but one opponent, TRL will then adopt the only strategy available to a coward in that situation: eat or be eaten. At this point, TRL goes into turret mode and ceases to randomly glide around in a desperate effort to not die. It is also important to note that even in turret mode, if TRL is hit by bullets multiple times, it will try to glide away at random again in an effort to avoid bullets again. Conversely, if TRL is missing too often, it will try to move away from its current wall in an effort to get more aggressive.
Prior to reaching turret mode, TRL does not really engage in any sort of robot targetting. When it finally does begin to track enemies, there should only be one enemy left and thus, no real illusion of choice as far as who to prioritize. Using a modified version of the TrackFire sample robot's tracking mechanism, TRL sits in place and tracks the closest enemy. The closest enemy, in this case, also happens to be the only enemy.
When in turret mode, whenever TRL scans a robot and its guns are ready to fire, it will do so. However, based upon how far its enemy is, TRL will scaled back the bullet power in order to conserve energy since greater distances usually means a higher likelihood of missing. Yet, in order to compensate for robots who also act as stationary turrets, if TRL is able to connect on several consecutive shots, it was switch its guns to fire maximum power bullets under the assumption that either the other robot is stationary or our tracking is doing a decent enough job of keeping our gun lined up.
Here are the results of TRL's 1v1 attempts against the sample Robocode robots:
Vs. Walls: 0 wins, 10 losses (an absolute massacre)
Vs. RamFire: 0 wins, 10 losses (yet another massacre)
Vs. SpinBot: 1 win, 9 losses (slight improvement, but otherwise utter defeat)
Vs. Fire: 2 wins, 8 losses (still yet a bit better)
Vs. Crazy: 5 wins, 5 losses (two random robots producing 50/50 results)
Vs. Tracker: 7 wins, 3 losses (a bit more positive news)
Vs. Corners: 10 wins, 0 losses (unfortunately this was TRL's primary sparring partner)
Vs. SittingDuck: 10 wins, 0 losses (anything less here would be unacceptable)
On a whole, versus sample robots, TRL does not fare well in 1v1 situations, winning only 35 out of its 80 battles, 10 of which were against SittingDuck. While it would be most gratifying for me to report that in group battles, for which TRL was designed for, it performed admirably and conquered the field of battle by watching others die in front of its radar that was simply not the case. In fact, depending on the types of robots it faced in battle, it was often the first robot to die, especially when the other robot specialized in wall movements as well, forcing TRL to leave its sanctuary. The silver lining is that in the absence of these types of robots, TRL was rarely the first robot to die, and occasionally nabbed the first place in a round by virtues of janitorial prowess (i.e. finishing off the last enemy who has already no doubt sustained heavy damages). In retrospect, it might have been prudent for TRL's random wall sanctuary to include the North and South walls to avoid being pigeonholed by certain wall riding robots. Additionally, rather than turning its body to glide up and down, it may have been simpler and faster to simply make use of the back() functions available to all Robocode robots.
In testing TRL, I knew that its 1v1 prowess would be limited at best and so its acceptance tests consisted of generally weaker sample robots like SittingDuck and Corners. I also made the decision that I did not particularly care if TRL could beat non-SittingDuck opponents 100% of the time and that a better-than-half average was sufficient. In testing its movements, I made sure that its two primary controlled movements were implemented correctly. That is to say that TRL always necessarily arrived at either the East or West wall in each round without fail, and that against a stationary target, it too was stationary. Finally, I tested that TRL's bullet power was indeed scaling based upon its intended algorithm and that upon successfully hitting a target consecutively, it would then increase its bullet power to maximum.
If nothing else, this project has taught me one thing: an idea might sound good but until it manifests and is tested, there truly no way to know. Even in hindsight, I feel like the design of the strategy to evade at random until everyone else is dead is a sound one. Albeit there are kinks and unexpected behaviors that were unforeseen in the design of the robot, but overall the tactic still seems good, even if the execution in practice yields poor results. However, rather than focusing on the weaknesses and shortcomings of the robot, the most important thing that I took away from creating ThirdRobotLaw was actually the development process. From the Java coding standards to the automatic quality assurance tools, I learned more about the process than robocode development. It was simply nothing short of amazing how much more polished my project appeared in the end when I made use of Ant in conjunction with Checkstyle, PMD and FindBugs. Certainly, having more tools at my disposal as a developer now and having gained familiarity with how to take advantage of said tools, I would probably have approached this project a little differently. In particular, I would have been testing my robot along side JUnit from start to finish, making sure that each behavior was working as intended before moving on and tacking on more features. One of the biggest mistakes I made in this project is a mistake that often extends to students and possibly developers all over the world in that I started to write my robot as soon as I had a design in mind. I then proceeded to write big portions of functionality that intertwined with one another all at once rather than keeping them as separate modules which can then be tested on a per module basis as well. Ultimately, the failures led to a disappointing survival rate for a robot whose namesake is, in and of itself, an instruction for absolute survival. As a TRL's designer, I express my regrets here and now, and apologize to my loyal fans for TRL's many flaws. However, as a more seasoned Robocode developer now, I can promise you without a guilty conscience that version 2.0 of our robots will better than ever! Maybe by then it will be able to win 36 out of 80 rounds...
No comments:
Post a Comment