My Robot Code Kata
"Robot Code Kata" may be one of the more interesting phrases you'll read in a technical blog.
Kata is a martial arts term describing highly choreographed and practiced movements that aim to perfect form. A code kata is, similarly, an exercise in programming form. It involves purposeful and effortful study toward improving programming skills through a number of small projects.
Okay, repetitively practicing programming may not sound that interesting. Let's add Robots. Robots make everything more exciting.
Robocode is an open source game where Robots written in Java battle each other by moving, targeting, and firing upon their enemies. Simple robots are very easy to make, but a robocode champion will involve advanced algorithms for avoiding enemy fire while predicting their movements.
My Robot Code Kata consists of thirteen exercises - six in moving, three in targeting, and four in firing. None of these exercises will result in a winning robot, but the skills honed in each iteration will improve knowledge of the API and should result in better robots overall.
Kata is a martial arts term describing highly choreographed and practiced movements that aim to perfect form. A code kata is, similarly, an exercise in programming form. It involves purposeful and effortful study toward improving programming skills through a number of small projects.
Okay, repetitively practicing programming may not sound that interesting. Let's add Robots. Robots make everything more exciting.
Robocode is an open source game where Robots written in Java battle each other by moving, targeting, and firing upon their enemies. Simple robots are very easy to make, but a robocode champion will involve advanced algorithms for avoiding enemy fire while predicting their movements.
My Robot Code Kata consists of thirteen exercises - six in moving, three in targeting, and four in firing. None of these exercises will result in a winning robot, but the skills honed in each iteration will improve knowledge of the API and should result in better robots overall.
- Position01: The minimal robot. Does absolutely nothing at all.
- Position02: Move forward a total of 100 pixels per turn. When you hit a wall, reverse direction.
- Position03: Each turn, move forward a total of N pixels per turn, then turn right. N is initialized to 15, and increases by 15 per turn.
- Position04: Move to the center of the playing field, spin around in a circle, and stop.
- Position05: Move to the upper right corner. Then move to the lower left corner. Then move to the upper left corner. Then move to the lower right corner.
- Position06: Move to the center, then move in a circle with a radius of approximately 100 pixels, ending up where you started.
- Follow01: Pick one enemy and follow them.
- Follow02: Pick one enemy and follow them, but stop if your robot gets within 50 pixels of them.
- Follow03: Each turn, Find the closest enemy, and move in the opposite direction by 100 pixels, then stop.
- Boom01: Sit still. Rotate gun. When it is pointing at an enemy, fire.
- Boom02: Sit still. Pick one enemy. Only fire your gun when it is pointing at the chosen enemy.
- Boom03: Sit still. Rotate gun. When it is pointing at an enemy, use bullet power proportional to the distance of the enemy from you. The farther away the enemy, the less power your bullet should use (since far targets increase the odds that the bullet will miss).
- Boom04: Sit still. Pick one enemy and attempt to track it with your gun. In other words, try to have your gun always pointing at that enemy. Don't fire (you don't want to kill it).
As you may expect, the first three were very simple, but they ensure that the Robocode environment is set up correctly. The next three can be done simply by moving in straight lines and turning at right angles. This is how I completed them the first time through. After testing them I decided to make their movements more efficient by calculating a direct route from the robot's current position to their desired position. I created a helper method that takes in the x and y coordinates of the destination and calculates the direction relative to the robot's current direction and the distance to travel. I must credit http://www.clarku.edu/~djoyce/trig/ for reminding me about the trig functions needed to do this. I especially found the difference between tan and arctan helpful after an hour of debugging my code that used the wrong one. There is one issue here that I still need to work on. In Position05, I calculate the angle to each corner in succession. However, when going from the lower left to the upper left, the angle always results in hitting the wall early. Since the robot stops when hitting the wall, it only gets about 1/4 of the way to the upper left corner before turning around and heading toward the lower right corner. For now I am cheating my way around that by not calculating the angle on that turn and just going straight up the wall. I know the Robocode wiki has some Wall Smoothing techniques that would resolve this, so I'll have to look into them later.
The three Follow exercises didn't require any trigonometry because Robocode provides the distance and angle of enemies relative to my robot's position. The difficultly here was in either following a specific enemy or selecting the closest one in each turn. To follow a single enemy, I just keep track of the name of the first robot I see. Each time I scan a robot, I check to see if it is the same one I saw originally. If it is, I take action toward it. If not, I ignore it and continue scanning. To find the closest enemy, I scan all robots by turning my radar 360 degrees. I keep track of the distance and direction to every robot I see, and after the full scan I can easily find the closest one. I am not sure if this is the best way to accomplish these goals, but it seems to work fairly well.
The hardest exercise in the third group was the last one. I had trouble calculating the correct angle to shoot at since my robot, radar, and gun could all be pointing in different directions. I found it odd that the direction of the enemy was given relative to my robot's heading. This wasn't a problem in previous exercises when I wanted to follow the enemy, but aiming the gun and not moving the robot was more difficult. Once I got the equation right though, everything else was pretty easy to build off of the previous exercises.
This kata seemed to encourage building skills slowly. None of the exercises were overwhelming as long as the previous one had been completed. Now I'll need to use these techniques to create a few competitive robots with different strategies to see which one performs better.
I too had some trouble getting my robot into the corners for Position 05. Assuming that the (x,y) of my robot was its center (since I haven't been able to find that explicitly stated anywhere), my fix was to account for the size of my robot. The getWidth() and getHeight() methods are helpful for this.
ReplyDeleteSo rather than trying to go to (0,0), I just went to (width/2, height/2). I can now get into corners even when on a sharp entry angle. I overrode onHitWall to make sure I'm actually making it into the corner without a collision. It looks like I'm tight in the corners, so my assumption about (x,y) being the center of the bot must be correct. :)
I like your use of the word kata. The Robocode katas were definitely worth the programming effort when I took ICS 613.
ReplyDeleteIf you like katas, you should check out my Java and C katas: http://www.thetravelingcs.com/search/label/katas
They definitely beat FizzBuzz.
Thanks Zach, I figured the size of the robot in and it fixed the problem.
ReplyDelete