Pages

Thursday, September 16, 2010

Competitive Robot: WallSpin

Overview
For this assignment we were given the task of creating a competitive robot that only extends the Robot class. I approached this assignment by analyzing which of the sample robots did best, and then chose to combine the two strategies that I thought worked best. The prior Robocode assignment was a warm up to get us ready for making our competitive robot, and seeing how I used a few strategies that I had learned from that assignment, I would say it was a great warm up.

In the following sections I will explain what approach I took when designing my competitive robot. I will also go into the advantages and disadvantages that my strategy presents.

Design
Movement is one the strong points for my robot, since it combines the wall strategy with a move and spin strategy. WallSpin starts off by moving to the top wall, it then continues to move along the walls and fire just like the Walls robot; it does this until it is hit by a bullet. Once hit by a bullet it switches to spin mode: WallSpin will move to the center of the arena then loop between moving forward and spinning, and moving back and spinning. Whenever WallSpin is hit with a bullet it switches between wall mode and spin mode, under the condition that the bullet hits are at least six seconds apart. As for wall collisions, if it collides with a wall in wall mode it is ignored, but if it collides with a wall in spin mode it backs away from the wall. Finally, if WallSpin collides with another robot it determines if the robot is in front of it or behind it and moves away accordingly.

Targeting for WallSpin is extremely basic. WallSpin will only fire when its gun meets meets paths with another robot, and its gun is always facing sideways. This means that in wall mode WallSpin always has its gun facing away from the wall it is riding, and in spin mode it has to do spin to scan for robots. In other words, my robot doesn't track a specific robot; it just fires at the first robot it scans. In retrospect, I think it might have been more effective to make the gun track the closest robot while in spin mode and be at a set angle while in wall mode.

Firing is another strong point for WallSpin. I based the firing implementation off of the previous assignment's Boom03 robot; it fires bullets proportional to the distance of the enemy. If the enemy is close it will fire powerful bullets and if they're far it will fire weaker bullets. This is effective because when you fire bullets you lose energy proportional to the power of the bullet. This strategy is an alternative to firing weak bullets repeatedly and doing minimal damage, and firing strong bullets and wasting the robot's energy fast. WallSpin also detects if it hit the enemy with a bullet of power greater than two, if it did then it fires another high powered bullet immediately. My thought behind this was if WallSpin hit the enemy with a high powered bullet, the enemy is probably close and will most likely be hit again.

Results
I tested WallSpin against eight sample bots: Walls, RamFire, SpinBot, Crazy, Fire, Corners, Tracker, and SittingDuck. My test consisted of battling each sample robot ten times and reporting its percentage of wins to losses. Here are the results of my testing:
  • WallSpin(60%) vs. Walls(40%)
    Walls seems to be on par with WallSpin; I would say that it is a pretty level playing field. These percentages were obtained from the first ten battles I ran, I ran ten more battles and the results were even closer; %50 wins for WallSpin and 50% for Walls. I think it does decent against Walls because it uses a very similar strategy.
  • WallSpin(100%) vs. RamFire(0%)
    These battles were a complete shutout, as RamFire didn't win a single round. I think WallSpin does so well because it is almost always moving and RamFire spends most of its time trying to catch up instead of attacking.
  • WallSpin(80%) vs. SpinBot(20%)
    Theses battles seemed like they came down to luck for SpinBot. The only time SpinBot won was when it trapped WallSpin in a corner and WallSpin couldn't navigate away. Due to SpinBot's relatively fast fire rate, if it traps WallSpin it will always win. If I were to try and solve this issue I would probably have to implement more advanced evasive maneuvers to avoid getting trapped; perhaps I could try to ram the enemy in this scenario.
  • WallSpin(100%) vs. Crazy(0%)
    These battles were very one-sided; Crazy didn't stand a chance against WallSpin. It seems that the majority of the time Crazy was really far away from WallSpin and when it did get close, with its erratic firing behavior, it rarely landed a bullet. Most of the damage dealt to WallSpin was from Crazy ramming into it.
  • WallSpin(90%) vs. Fire(10%)
    This was also a fairly one-sided battle, and the only time Fire won was when it got WallSpin in close range and unleashed a barrage of bullets on it. I think Fire is at a disadvantage because it spends the majority of the time sitting still which makes it an easy target for WallSpin when it is in wall mode.
  • WallSpin(20%) vs. Corners(80%)
    Corners was the biggest challenge for WallSpin, as the only time it won was when it prevented Corners from reaching a corner. I think Corners does a really good job because it has such a fast fire rate and a great tracking system. If I wanted to beat Corners I would probably have to implement a better tracking/firing system.
  • WallSpin(100%) vs. Tracker(0%)
    WallSpin destroys Tracker because it spends most of its time in wall mode, due to Tracker spending most of its time trying to catch up. I think Tracker would have a chance if it got WallSpin out of wall mode, but even then if it were to shoot WallSpin again it would just go back into wall mode.
  • WallSpin(100%) vs. SittingDuck(0%)
    This is an obvious win because SittingDuck doesn't attack at all.

Lessons Learned
I actually did learn something new about software engineering by doing this assignment; mainly about the development process. For this assignment I took a different approach than I usually do, as I normally program everything first then comment last. Instead, for this assignment, I laid out the structure of my entire program and then started by doing JavaDocs for each of the methods. I was amazed at how much faster and more efficient I was able to write my program. I knew what each method was supposed to do before even implementing it; this might not seem like a big deal, but it actually helped a lot.

Though it was much simpler to code my robot, I did still run into issues and have bugs. In the beginning, when I would find a bug, I would make some rash decision and make a drastic change in an attempt to fix the issue. That didn't go so well. As I found out my approach wasn't working, I decided to actually sit down and read through all of the code to see if I could pinpoint where the issue was; this was the right approach. As soon as I did this, I was able to find my bug and fix it almost immediately. I would say that one of the lessons I learned was patience, because I wasn't able to fix my bugs by just blindly trying to change things. I had to stop and think about the problem, then analyze my existing code to narrow down where the issue was coming from.

If I could do this project over again, and if I had more time to work on it, I would have liked to analyze each of the strategies of the sample robots in more depth and come up with a better overall strategy. Though I believe my strategy is decent, I think I could have come up with a much better strategy given more time to think about and work on the assignment. Overall it was still a great learning experience.

Download
You can download my packaged robot here.

Saturday, September 4, 2010

Robocode

This weeks project was to start working on Robocode. Robocode is a program written in Java which allows programmers to create robots and make them battle in an arena. For this assignment we are creating robots to perform some simple, and some not so simple tasks.

This is the first time I have ever worked with Robocode and I actually find it to be really fun. Doing to tasks that involve planning the movement of the robot are really refreshing my memory on Trigonometry. I also haven't worked too much with Java lately so working on this assignment is really helpful.

Here is my checklist for the assignment:
  • Position01: The minimal robot. Does absolutely nothing at all.
    Creating this robot was beyond simple; all I had to do was create an empty class.
  • Position02: Move forward a total of 100 pixels per turn. When you hit a wall, reverse direction.
    This robot was also relatively simple, though it required me to look in the API for the onHitWall() event.
  • 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.
    The one was still pretty easy, just took some very simple incrementing.
  • Position04: Move to the center of the playing field, spin around in a circle, and stop.
    I decided to have a little fun with this one. I saw that a lot of people were making the robot face north then move up on the y-axis till it was centered and then move along the x-axis till it was in the center of the map. I wanted to give myself a bit of a challenge and make the robot make one diagonal move to the center as opposed to two moves along the y and x axis. It took me about ten minutes to work it out on pencil and paper. I took the following approach:
    1. I check the quadrant the bot is in
    2. I face the bot north
    3. If the bot is in the upper two quadrants I rotate it to face south
    4. I calculate the angle using the following formula: angle = arctan(opposite/adjacent)
    5. Rotate toward center using angle found in previous step
    6. I calculate the distance needed to travel using the Pythagorean Theorem: c = sqrt(a^2+b^2)
    7. I move ahead the distance calculated in the previous step
  • 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.
    This used similar mechanics as Position04 so this was still very basic as far as the programming went.
  • Position06: Move to the center, then move in a circle with a radius of approximately 100 pixels, ending up where you started.
    Again, this was a build off Position04. The only semi-difficult part was getting the robot to follow a path with a radius of 100 pixels.
  • Follow01: Pick one enemy and follow them.
    At first I was lost on this but I was able to look at the Tracker robot, which was provided with Robocode, as inspiration. After reviewing the Tracker robot which did something similar I was able to piece together which events and methods I needed to make this robot work.
  • Follow02: Pick one enemy and follow them, but stop if your robot gets within 50 pixels of them.
    This was just a build off of Follow01; it was just a matter of adding an if statement which check if the robot was within 50 pixels.
  • Follow03: Each turn, Find the closest enemy, and move in the opposite direction by 100 pixels, then stop.
    At first I was a bit stressed about this one, because I couldn't figure out how to detect the closest enemy. After researching a bit I discovered that the onScannedRobot method actually returns the closest robot. This made things a lot easier; all I had to do was rotate towards the detected robot and back away 100 pixels. I also decided to check when a wall was hit, because the bot would repeatedly smash into the wall when I didnt.
  • Boom01: Sit still. Rotate gun. When it is pointing at an enemy, fire.
    This was one of the simpler robots to code; it just took a little research. All this one does is spin its radar to detect an enemy, when it does it fires its gun.
  • Boom02: Sit still. Pick one enemy. Only fire your gun when it is pointing at the chosen enemy.
    This robot is nearly the same as Boom01 except it picks one enemy and only shoots at that enemy. I had to add a variable which stores the name of the enemy, and every time an enemy is scanned it just compares the name to make sure it's the same 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).
    This robot posed a slight challenge. I decided to calculate the max distance obtainable in the arena and then detect how far the enemy was relative to the max distance. Based on that information I have the robot fire with power relative to the distance of the enemy.
  • 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).
    This was a pretty simple task, all I had to do was rotate the radar continuously to scan for the target robot. When the target robot is detected I just have my robot turn its gun towards it. This is updated every time the enemy is scanned so it is updated constantly.
The overall experience of this assignment was pretty fun. Though I'm still a complete novice to Robocode, I do feel like I will have a slight advantage now when writing my competitive robot. I feel more prepared than I would be if I were just assigned to write the competitive robot right off the bat. I'm thinking of doing a combination between the existing Wallbot and Spinbot while using the targeting technique of Boom04. I definitely think this was a great warm up exercise. My source code for this assignment can be found here.