Thursday, September 29, 2011

Ant 型 (Kata)


In this exciting week, I've had the opportunity to learn and work with the Ant Build System-- a software tool for automating software build processes. Although I've "used" build systems before, they were only IDE-integrated ones (such as MSBuild in Microsoft Visual Studio), and as such, I did not have to even know that such pieces of code existed. However, with all of its capabilities, it is crucial to actually write code using build system tools, so that when you want to release code to others, everything is neat and complete.

Since my primary focus for now is Java, the build system of choice is Apache Ant, which despite its somewhat not-so-pleasant name, stands for Another Neat Tool. And it is! Ant is quite nice to programmers, although it can get rather complicated at times. It comes packed with feature after feature, so it did seem overwhelming at first. In fact, it is still a little overwhelming to me, but just because of the sheer amount of capabilities that it has. But just like Robocode, I carried out the learning process of Ant through a series of programming martial arts, called Katas.


The 8 Ant Katas that I practiced were:
  1. Ant Hello World- Start from ground zero-- write a script that uses the <echo> task to print out Hello World.
  2. Ant Immutable Properties- Understand the immutability of properties-- create a script that sets a property to one value, and then attempts to change it by assigning it another value. Printing out the value of the property returns the initial value, demonstrating immutability.
  3. Ant Dependencies- Understand the use of the "depends" attribute by creating several targets that have different dependencies, and see in what order the targets end up executing. Also, understand what happens when the dependencies are cyclic (they depend on each other in an infinite loop).
  4. Hello Ant Compilation- Learn how to compile Java code using Ant-- create a script that uses <javac> to compile a simple HelloAnt.java file.
  5. Hello Ant Execution- Run Java code using Ant-- create a script that first compiles Java code (using dependencies and the compiler script from Kata 4), and executes the HelloAnt program, which prints "Hello Ant" to the console.
  6. Hello Ant Documentation- Generate JavaDoc documentation-- create a script that first compiles the HelloAnt program and then generates the JavaDocs for it using the <javadoc> task.
  7. Cleaning Hello Ant- Implement a cleaning task-- add a "clean" target to the compile script that deletes the "build/" directory that stores the .class files and JavaDocs.
  8. Packaging Hello Ant- Zip up the project so it can be shipped out-- create a script that uses the <zip> task to package the project into a zip file.
It was difficult to get started with writing the first couple of scripts because of the "unfamiliar territory" that I was in. However, as I got used to the different attributes and properties and just the overall structure of the scripts, things became much easier. To anyone wanting to start using Ant, I would recommend getting familiar the Ant Manual when implementing tasks. At first, I used this just to copy the examples, but many of them contain more complex features which are not necessary to learn at this moment, so definitely learn how the manual works, especially the Parameters table which lists and explains all the attributes, and even tells you whether it is required or not. I wish I had realized this earlier!


The most difficult part of these Katas was managing the directories to and from which files were to be compiled, run, generated, and packaged (for Katas 4-6 and 8). I frequently got an error message reporting that "<ProjectDirectory>/src could not be found", even though I had set up the properties correctly in the compile script. I resolved these errors by explicitly specifying the "basedir" property at the top of the script with the project declaration. Prior to this, I had thought that since it was specified in another dependency script, this would not have to be set, just like how properties need not be set again. I am not sure if this is the correct way to solve this issue, but it averted the crises that I had, so perhaps this is indeed the solution. I shall look into this more, and in the meanwhile hopefully I can learn more of the Ant features!

Tuesday, September 20, 2011

Let's Get Ready to Robocode!

About a week-and-a-half ago, I took my first peek at the Robocode project. "What is Robocode?", you may ask?-- well in a nutshell it is an open-source project started by Matthew Nelson of IBM in 2001. It was originally intended as an educational game designed to help budding programmers learn java, but eventually grew to become a worldwide programming sensation with fierce competitions-- and not to mention competitors who have tweaked their code to becoming virtually unstoppable.

After downloading the libraries, source code, and other essential components, I ran the program with a couple of sample robots-- just to get a feel for what the interface was like. I was flung back in my seat as I saw little tank-like robots fixing their aim on each other, rapidly firing their guns, ramming into each other, and whizzing around the perimeter of the screen. "How in the world am I ever going to create that?!", I exclaimed in my head when the mayhem was over just a few seconds later. Over the course of a week, I created 13 robots, starting from the bare-bones minimum and slowly working my way up, trying out and adding on different features.

The descriptions of the 13 robots are as follows:
  1. Position 01: Doesn't do anything; just watches the action in front of it.
  2. Position 02: Moves forward 100 pixels each turn, reversing direction if it hits a wall.
  3. Position 03: Moves forward N pixels each turn and then turn right. N starts at 15 and increases by 15 each turn.
  4. Position 04: Moves to the center of the playing field, spins around in a circle, and stops.
  5. Position 05: Moves to the corners in the following order: top-right, bottom-left, top-left, and bottom-right.
  6. Position 06: Moves to the center, then travels in a circle of approximately 100 pixels, ending up where the circular traversal started.
  7. Follow 01: Picks an enemy and follows it around.
  8. Follow 02: Picks an enemy and follows it around, but stops if it gets within 50 pixels of it.
  9. Follow 03: Finds the nearest enemy each turn and moves 100 pixels in the opposite direction.
  10. Boom 01: Sits still, rotates its gun, and fires when it is pointing at an enemy.
  11. Boom 02: Sits still, picks an enemy, and fires only when the gun is pointing at that enemy.
  12. Boom 03: Sits still, rotates its gun, and shoots when it is pointing at an enemy. Bullet power is weaker the farther away the enemy is.
  13. Boom 04: Sits still, picks one enemy and tracks it with its gun, keeping it pointed at the enemy but not firing.
What I Learned
Since most of the methods used were implemented through the Robocode API, I did not learn new Java concepts through this experience. I did, however, brush up on some skills that have gotten rusty-- especially in the Math class. Some of the Position robots required the use of trigonometric calculations to get to the right places on the field, but since I have not used these functions in quite some time, it took a little trial and error before the ball got fully rolling.

Difficulties Encountered
By far the biggest difficulty was getting adjusted to the whole Robocode environment. Figuring out how to even run something took some prodding around, because the run() method acts as the main method, instead of main(). Also, calling methods such as ahead(), scan(), and fire() seemed awkward at first, since in Java programming we typically don't see methods that are called just by themselves like this; they usually follow some sort of class or object (like System.out.println() or object.someMethod(). This made getting accustomed to Robocode coding quite difficult. Finally, another substantial difficulty was utilizing the bearings and headings properties correctly, and getting used to them. In mathematics and science, we're used to measuring angles starting at zero on the right side of the x-axis (between quadrants I and IV). In Robocode, however, angle zero lies in the positive side of the y-axis (between quadrants I and II). Headings are measured with this latter system, so in order to calculate angles using trigonometry in the conventional perspective, we have to adjust the values to reflect the Robocode coordinates. This was very confusing and frustrating indeed, but once the solution to one Robot was completed (and worked), then applying it and altering it for other Robots was significantly easier.

Robocode Robot Behaviors

Trying to balance simplicity with robustness proved to be very difficult, especially for the Position05 and Position06 robots. In order for Position05 to get to most of the corners, calculations are useful for setting the angle and distance to travel, but calculating the angle is not required when traversing from the bottom-left corner to the top-left corner, since it is just traveling "upward". Thus it is trivial to point the robot at angle zero and just traverse the height of the field. However, this is a naïve implementation, since bumping into another robot or missing the bottom-left corner due to the entry angle will cause the robot to move upward even though that is not the direction of the top-left corner.
As for Position06, it was difficult to implement the movement of the robot in a circle. At first, I had it move in a hexagonal path instead, since it seemed much more straight-forward to get the robot to move in that shape versus a circle. Eventually, however, I was able to get the robot to move in a circle (or close to one), although it took a significantly longer time.

The only robot that I could not get working entirely correctly is Boom02. It seems to only fire at the tracked enemy only when it is within a certain distance from the enemy:

Fig. 1- Boom02 vs. Walls vs. SpinBot. Boom02 is temperamental as to when it wants to fire.

Ideas for Building a Competitive Robot
As far as I can think of for now, there are only two strategies for a robot in Robocode: assault and evasion. Since there is no way to "defend" oneself, a robot can either be on the offensive, or try to dodge enemy attacks (since firing lowers one's own energy). I will not reveal which route I shall be taking in my creation of a competitive robot, but it will most likely include a lot of movement, in order to increase the chances of evading shots.

Thoughts on Code Katas
This project demonstrated the practice of code kata-- separating practice from profession. Since I started with simple tasks and progressed through more advanced territory all the while being in a "practice environment" (as this is not the true competition), I was able to hone my skills before diving into the actual competition, rather than being stuck with them during it. This is an extremely wise way of practicing software engineering, and produces much higher-quality software when it comes to the live development project.