Sunday, September 20, 2009

FiringDock: My First Competitive Robot

Task: Design and implement a single robot that can reliably beat as many of the following eight sample robots as possible: Walls, RamFire, SpinBot, Crazy, Fire, Corners, Tracker, SittingDuck.

After studying the strategies of some simple robots include in the Robocode and brainstorming some strategy to counter those sample robots, for this week I started to build my first competitive robot which called FiringDock. Click here to download.

Movement: This robot sits still and only moves 100 pixels perpendicularly to the bullet when it hit by a bullet.

Targeting: The targeting for FiringDock is similar to the TrackFire. The radar and the gun always points at the enemy.

Firing: The firing strategy for FiringDock is very simple. The FiringDock always fires when the enemy is scanned. It fires with the bullet power proportionally to the distant between the enemy and the enemy's velocity. While minimizing bullet waste and maximizing the chance to shoot the target, it fires the maximum bullet power when the target sits still or is within 300 pixels; otherwise, it fires the lower bullet power.

Sound simple, isn't it? Now let's look at which sample robots it can defeat in a 1v1 battlefield.

Corner: the FiringDock has more chance to win the Corner because the Corner does not attack until it get to the one corner of the battlefield and it only sits still there. The chance that the FiringDock gets hit by the bullet is less because it moves to a new position when getting hit by the first bullet. The FiringDock also has a more efficient firing technique for a still target.

Fire: similary to the FiringDock, the Fire only moves when it hit by a bullet. With the firing technique that always fire hard at the still object, the FiringDock always win the Fire. The FiringDock also has a better targeting technique when it moves or the target moves. It scans for the target faster when it moves or the target moves.

RamFire: the FiringDock can easily win the RamFire because the RamFire take time to turn and move closer (as it tries to ram), it only fires when it hits the enemy and it does not move away from the bullet.

SittingDuck: the firing technique of FiringDock can easily kill the SittingDuck in every battelfield.

Tracker: the FiringDock can easily kill the Tracker because the Tracker only fires when it get within 150 pixels. The FiringDock can at least reduce 1/2 or 1/3 of the Tracker's life before it opens fire.

However, the FiringDock cannot defeat the Walls, the Crazy, and the SpinBot with the same strategies because it does not include a predictive shooting algorithm for a moving target. The FiringDock lost energy in two ways: it gets hit by the enemy and it wastes the bullet. Keep pointing the gun at the target does not work for a moving target.

Lesson learned: I admit that without looking into the code of each sample robot, the FiringDock probably defeat less than the five simple robots above. Designing a real competitive robot is very challenging. Though, we have an idea of how to defeat the wall by following behind it, coding a single robot that could defeat all will not be easy without some movement pattern recognition involve. While trying different ideas to design a single robot that defeat all, another option is escaping the bullet. The constraint to this option is the lack of functionality for scanning when the enemy fires a bullet. By googling the web, I realized that we can track this by tracking the energy drop (between .1 and 3). I beleive, with some additional conditions, this could be a potential solution for surviving the Walls, SpinBot, and Crazy.

Wednesday, September 16, 2009

Review of Strategies in Sample Robots

The sample robots included in the Robocode package has a lot of potential for competitive robot. While trying to tacgle for the first robocode assignment, the only feature that missing from the sample robots is the trigonometric moving between two points. Because I like simplicity (even for a complicate problem), I really like the targeting of TrackFire. Anyway, below is the review of moving, targeting, and firing strategy of eigth sample robots.

Walls: It first turns to one of the special angles then moves to the furthest wall. The targeting of the walls is simple but efficient enough to stop before hitting on an enermy. With the "peek" variable, the robot will stop if there an enermy in front of it and it will keep firing till the enermy out of the way. If it hits the enemy in the front, moves back; otherwise moves ahead.

RamFire: The movements is straightforward. The targeting is not very efficient because the radar only turns when the robot turn. Thus, it need to rescan for a new enermy while trying to get close to the previous enemy that already moved out of the radar. It only fires on hitting at the enermy and uses the bullet power proportionally to its energy. Though, it seem to be effecient, in a real battlefield, the chance is that it could be killed before hitting on any enemy.

SpinBot: This is the extends of AdvancedRobot. Its unique feature is the circle movement by turning in a large degree with a low velocity then moving ahead. The targeting is straightforward. The firing is not energy efficient. Not only that it fires hard once scanned on a robot, it also does not track the exact location of the moving target. Thus, there's more chance that the bullet would miss the moving target.

Crazy: This is another advanced robot. The movement of this robot is seem randomized. After looking at the robot movement and the code, first I wonder what make this robot not moving a straight ahead while in the code said so. After deeply investigate some of the advanced robot function, I've realized that each of the set movement will not execute until the completion of waitFor(new TurnCompleteCondition(this)). That seem to be a pretty cool method of making a random movement. The targeting and firing is straightforward and also it does not track the exact location of the enermy. It takes longer to kill an enemy because the bullet power is low.

Fire: This robot turn "perpendicular" to the bullet before moving backward or forward 50pixels each time hitting by a bullet. Without interupting, it sits still, spins gun around and fires on the target. The gun spins around but does not follow on any enemy which is not so efficient on a tough battlefield. It uses the bullet power proportionally to its energy and the distance of enemy. It also do the best to kill enemy as fast as possible if it hit on it.

Sitting Duck: This robot sits still and keeps track of its persistency. There is no movement, firing, or targeting in this one. At least the feature of this robot is tracking robot's life into the external file.

Corners: This robot first moves to one of the corner and switch the corner if it did not do well in the previous round. Similarly to the walls robot, the corner uses "stopWhenSeeRobot" variable to be alert of any enemy in its way. Instead of rotate the gun around, this robot only rotate the gun back and forth which is sufficient enough. The ability to keep track of enemy in the field and statistisc of each round make this robot unique. Maybe we can include that feature in the design of the competitive robot. The firing is similar to Fire.

Tracker: This robot tries to move closer to its chosen target before firing. Before moving anywhere, it has to scan for an enemy and tries to move closer. The technique doesn't work for a moving robot. It rescan for the chosen target everytime after each turn. The method of finding the first target is unnecessary. We can get at least one target with just a single round (360) turn regardless of robot's position. Trying to rotate the gun to another direction should be replaced by pointing at the enemy all time. The firing is straightforward as it fires hard once getting close.

Sunday, September 13, 2009

Coding Standard in Robocode

The most important reason for using the coding standard is the effeciency in debuging code especially with the following elements of coding style:

1. Comment: a meaningful comment is very useful for understanding the method or each line of code. Accordign to The Element of Java Style, comment is summary of interface, class, or method. By having a clear comment for each method, others rather than the author of the code can easily debug the code without asking the code author. Other programmer can also identify the pitfall in the code by just comparing the code's objective and its actual functionality.

2. Naming Convention: by having a standard naming convention, programmers can identify each names quickly without going back-forth or scrolling up and down between classes. Imagine the scenario of having 10 programmers working on each class of a project using different naming convention. Some use the old naming convention (no vowel with underscore, eg. gt_rpt) for both class, interface, method, an variable. Some use mixed convention, and some use a non-meaningful name. In this case, if someone rather than the author has to debug the code, he or she will spend quite a lot of time to adapt to the new convention and try to debug the code. A mix convention also presents an integration issue which could cause a nightmare.

3. Variable scope: by specifying the class, method, or variable with the keyword 'this, public, or private' has two advantages. First, it ensures the scope of each method or class. Second, it also prevent the common method or variable name issue in different classes especially for a global variable.

Revising Robocode: I spent about two hours for reviewing the coding style in my robocode that consist of thirteen movements. After reading The Elements of Java Style and the ICS coding standard, I realized that I had violated a lot of elements in coding standard. Just to name a few, those violations include a mixing naming convention, variable scope, and comment documentation. Actually, the comment section was a bit scary for me but I was very fortunate to come across Georg's blog that I could use as a sample. Renaming some of the variable name is not so difficult since in fact this project is small and also within Eclipse you can just simply find and replace. The last thing that I did was to ensure the single task in my method and also include a descriptive comment of the method.

Finally, my personal thoughts for the coding style is the rule #1: Adhere to the style of the original seem to be valid for different language not just in Java. Despite the fact that each language has different styles and rules, each project should document the related style use within the project.

To download my improved Robocode, click here.

Tuesday, September 8, 2009

My First Robot Assignment

Click to download LNP package

Robocode is a Java-based game, created by Mathew Nelson. Digest through all the robocode resource, I found that it's very interesting that the initial purpose of the this project was to prove that we can program game in Java.

Include in my package are the following movements:

  • Movement01: The robot does absolutely nothing.
  • Movement02: The robot move forward a total of 50 pixels per turn and it reverse direction if it hits a wall.
  • Movement03: The robot move forward a total of N pixels per turn, then turn left. N is initialized to 10 and increases by 10 per turn.
  • Movement04: The robot move to the center of the battlefield and stop.
  • Movement05: The robot move to the upper left corner, then to the lower right corner, then to the upper right corner, and to the lower left corner.
  • Movement06: The robot move to the center, then move in a circle, and ending up where it started.
  • Tracking01: The robot pick one enemy to follow them.
  • Tracking02: The robot pick one enemy and follow them, but stop when it gets within 20 pixels of them.
  • Tracking03: The robot find the closest enemy each turn and move in the opposite direction by 100 pixels, then stop.
  • Firing01: The robot sit still, rotate gun, and fire when it is pointing at an enemy.
  • Firing02: The robot sit still, pick one enemy, and only fire when it is pointing at the chosen enemy.
  • Firing03: The robot sit still, rotate gun, and fire the bullet power proportionally to the distance of the enemy.
  • Firing04: The robot sit still, pick one enemy, and attempt to point the gun at the enemy all the time but does not fire.
  • It's very obvious that one of my problem was to install the Robocode. Due to the default program for any *.jar file on my computer was Eclips, the installation of robocode did not start automatically. It tooks me a while to figure out and change the default setting of *.jar file.

    After I successfully installed the Robocode, first I took a few hours to get my feet wet with all the classes, functions, movements, and events. I've read each link in 06.Robocode of this class as well as did my searching, and digging through the sample robot's code.

    I did not have any problem with movement 01 to 03 since they are just to understand the basic steps of a robot. However, I've spent a lot of time on movement 04. I tried to create a shared function for movement 04, 05, and 06 and I first started with two steps to get to a new position. It seemed to work well for movement 04; however, it got confused when the robot has to go to multiple postions in movement 05. Instead, I rewrote the function by applying some trignometry function to measure the angle between two. Below, I attached my code to calculate the angle between two points:

        public double getDegree(double x1, double y1, double x2, double y2){
            double dx = Math.abs(x1-x2);
            double dy = Math.abs(y1-y2);
            double t = dy/dx;    //tan = opp/adj
            double r = Math.atan(t);     //angle = inverse tan (in radian)
            return Math.abs(r * (180/Math.PI));     // deg = rad * 180/pi
        }
    
    

    Thus, to simply move to a new position, my robot has to:

  • turn to face the 0 or 180 (this help me adjust the robot's heading in the next step)
  • calculate the distant and angle between both positions
  • move to the new position the approximate distant

    For tracking and firing robots, the most challenging issue is to keep the gun tracking the enemy (and not turning away). For my tracking01-bot, it will follow a new enemy when it collide with a new enemy. After digesting throught some sample robots, I used the approach from TrackFire-bot to track the enemy. This approach work perfectly with all of my tracking and firing robots.

    However, I could not follow the specification for Tracking03 and Firing02. For Tracking03, I could not define "the closest enemy". I assume that the closest enemy for each turn should be the closest one in the radar angle. For Firing02, the robot sit still but the gun will follow the chosen target and keep firing until the target die. I first tried with the gun also sit still but it will take too long waiting for the target to come back again (which probably not in most cases).

    Beside the technical issue, I also had problem with the unclear specification of each movement. For example, the turn left angle for Movement03, the started point in Movement06, and rotating gun in Firing02.

    After spent most of the long weekends with this robocode assignment, I've learnt that to build a competitive robot, the following factors are very important:

  • smart fire: use the bullet power proportionally to the distant of the enermy
  • try to kill the enermy fast in each turn
  • destroy the most threaten enermy first

    I've also got some ideas from the sample robots TrackFire and RamFire which can put together to build a competitive robot.

  •