Wednesday, September 22, 2010

Web Server

This was one of the cooler assignments I've had as a student: create your own webserver.

I've installed apache via Linux but I wasn't aware that it was so simple to make a basic webserver.

Webserver Details:
  • Language: POSIX C
  • Command Line Parameter: port number
  • HTTP 1.1
  • Method Supported: GET
  • Counts and displays accesses
  • Displays current server time
  • Hard-coded domain and file path names
Download webserver source code: here

I've included a few comments that are purely for learning purposes only. Thanks to Beej for outlining the socket library in such great detail.

14. Build System Samples

It seems that there are a lot of examples on how to execute a java file using Ant via a .jar file. But it was a little more difficult to figure out how to compile and run a .java file outright.

Here's my simple java file:
package ant;

public class HelloAnt {
public static void main(String[] args) {
System.out.println("Hello Ant!");
}
}


The main things to remember when using a package or IDE like Eclipse is to:
  1. include the classpath (the build directory)
  2. include the package name before the class name. E.g., ant.HelloAnt
<project name="HelloAnt" default="run">

<description>
Simple Ant build file for Hello Ant
</description>

<property name="src.dir" location="src" />
<property name="build.dir" location="build" />

<target name="clean">
<delete dir="${build.dir}" />
</target>

<target name="makedir">
<mkdir dir="${build.dir}" />
</target>

<target name="compile" depends="clean, makedir">
<javac srcdir="${src.dir}" destdir="${build.dir}" />
</target>

<target name="run" depends="compile">
<java classname="ant.HelloAnt" fork="true">
<classpath>
<path location="${build.dir}" />
</classpath>
</java>
</target>

</project>

Monday, September 13, 2010

09. Competitive Robot (Robocode)


Overview:
As part of our class Robocode tournament, we were each tasked with designing a robot for competition. I've combined what I discerned were the best qualities from our Robocode warm-up exercise due earlier in the week plus a few tweaks that I thought would help it in combat.

This phase of the project was implemented with a single goal: defeat the sample robots.

Design:
  • Movement - based on scan events. Robot will move towards scanned enemies in a circular fashion to avoid getting hit. The following methods have also been overidden: onHitWall - Robot backs away from wall 120 pixels at 45 degrees. This ensures that the robot does not get stuck in a corner or on a wall where it can be easily preyed on. onHitByBullet - Robot will turn gun and radar towards enemy that fired and also move to avoid subsequent shots. onHitRobot - will fire at full power and attempt to ram the robot that it has collided with. This behavior is similar to the RamFire sample robot.
  • Targeting - attempts to keep it's radar locked on an opponent by realigning it's radar to face any scanned robots. If no scanned robots have been spotted, the robot will scan to the left and right to find the nearest robot. Also retargets to an enemy robot if hit by bullets from that enemy robot.
  • Firing - fires using firepower proportional to the distance from the target. Fires whenever an enemy robot is scanned.
Results (1-on-1) Won against all of the Main (not sampleex) sample robots except Walls:
  • Simple robots that were easily conquered: Crazy, Fire, Interactive, MyFirstJuniorRobot, PaintingRobot, SittingDuck, SpinBot, VelociRobot
  • Corners - initially I used a regular tracking implementation where I moved straight towards the target. This allowed Corners to lock on to me. By moving forward in a circular pattern and bouncing off the walls I was able to avoid most bullets and land shots of my own.
  • RamFire - I implemented a similar onHitRobot method to RamFire, but I increased the firepower to max power to inflict maximum damage. This overpowered RamFire's lesser firepower.
  • Tracker/Trackfire - Probably the next hardest to beat, but the circular movement combined with my targeting (that ironically is based off of Tracker) allowed me to stay mobile, avoid bullets, and destroy both of these robots consistently. Both robots use linear movement when moving toward a target.
  • Walls - I lost to this sample robot due to the distance this robot keeps from its target.
After submission of my robot for the tournament, I ran it against the following robots in the sampleex class:
  • Won: Alien, AlienComposition, Master and Slave, ProxyOfGrayEminence, Slave, MyFirstDroid,
Lessons Learned:
I really would've liked to explore some of the targeting algorithms that would've helped to increase accuracy when firing upon a moving robot. Also, the anti-gravity movement algorithm presented by IBM also looked very intriguing and I would've liked to see how well it performed. I also read an article about narrow radar locks and it's also something that seemed worth exploring to try to improve the targeting system.

I'm not sure how my robot will fare when pitted against robots with more complex movement implementations.

I also would've liked to have tested it in multiple/melee battles.

From a software development perspective, I would've liked to have modularized the code a little more. There are definitely some targeting statements that are repeated throughout the code.

Tournament Results:
Out of 25 robots, I made it into the semi-finals, losing to the eventual winner, bubonic. Bubonic was outfitted with Walls-type movement and predictive shooting. I lost all 4 rounds.

Overall, however, I was pleased with the outcome. My robot on preliminary melee battles with other students was found to have a glaring weakness towards Walls-class robots. So the outcome of the battle wasn't surprising at all.

Download:

Tuesday, September 7, 2010

07. Robocode

Initial thoughts:
This is a get-your-feet wet with Robocode project, which was designed by IBM initially before being adopted by the internet community. Our assignment is to create a series of starter robots to familiarize ourselves with Robocode prior to creating our tournament-ready version.

Robots:
  • Position01: 9/2/10 -The minimal robot. Does absolutely nothing at all.
  • Position02: 9/2/10 - Move forward a total of 100 pixels per turn. When you hit a wall, reverse direction.
  • Position03: 9/2/10 - 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: 9/5/10 - Move to the center of the playing field, spin around in a circle, and stop.
  • Position05: 9/4/10 - 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: 9/4/10 - Move to the center, then move in a circle with a radius of approximately 100 pixels, ending up where you started.
  • Follow01: 9/12/10 - Pick one enemy and follow them.
  • Follow02: 9/12/10 - Pick one enemy and follow them, but stop if your robot gets within 50 pixels of them.
  • Follow03: 9/13/10 - Each turn, Find the closest enemy, and move in the opposite direction by 100 pixels, then stop.
  • Boom01: 9/7/10 - Sit still. Rotate gun. When it is pointing at an enemy, fire.
  • Boom02: 9/7/10 - Sit still. Pick one enemy. Only fire your gun when it is pointing at the chosen enemy.
  • Boom03: 9/11/10 - 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: 9/13/10 - 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 definitely seems like a fun project. There's a good deal of quality documentation out there and games are always fun. Some notes on a few of the implementations:

Position04:
After programming the first three positions, this position caught me a little off guard by the amount of trigonometry that was involved in the calculations. Overall though, I like math and it was still a fun exercise. I'm currently trying to modularize the code a little more for the subsequent tasks.

Modularization complete. Version 2.0 of Position04 here with some enhancements. I was able to get the robot to swivel directly to the desired angle, rather than setting it at 0 degrees first.
Without the use of the advanced robot class features, moving the robot in a complete circle of a set radius was simple, but it did have some drawbacks. To move it in a smooth circle I moved it at 1-5 degrees/turn, resulting in a very slow circular path.

Follow01:
I first implemented a simple tracking robot, but after reviewing the code from the Tracker robot packaged with Robocode, I opted to integrate it's more efficient radar movement into my robot.

Follow03:
This robot forced me to investigate the relationship between time and robot movement. I learned that a scan returns all robots detected, the first one being the closest one. I also gained some insight from the following site about what happens in the course of a single turn, in addition to the processing order during gameplay:


Final Thoughts:
This was an excellent (and fun) coding assignment. I learned a little bit about importing external files and .jar files into Eclipse, which I didn't have too much experience doing. I also improved my code-reading a little since the sample robot code is very simple and well-commented. As a final note, I've started to code every day - after a long layoff during summer - and this is going to help me immensely in my growth as a programmer. I just need to keep it up :)

On to the Tourney Robot:

I definitely want to implement a better radar function. This page seems to be worth looking into:


I'd also like to improve the robot's firing mechanism and how it adjusts for enemy robot movement as well as the defensive movement of the robot.

The Code:
Source code can be found here:

Saturday, September 4, 2010

Position04 Version 2.0

Re-did the methods in Position04.  There now exists a method that has a coordinate as a parameter that moves the robot to that coordinate.
Also, I minimized the spin rotation.  My previous code initially spins the robot to point to 0 degrees.  This made for simpler code but lengthened the spin time.  The code below now spins in direction that will produce the shortest rotation to point towards a destination coordinate.
Then, using Pythagorean, the robot moves from it's current position to the destination coordinate.
*************************************************************
package kgl;

import robocode.Robot;

/**
* Position 04 Robot
*
* Move to the center of the playing field, spin around in a circle, and stop.
*
* @class ICS 413
* @author Kevin Leong
* @date 9/2/10
*/

public class Position04 extends Robot{

/*
* Run Method
*/

public void run(){
//Get battlefield dimensions
double width = getBattleFieldWidth();
double height = getBattleFieldHeight();

//Assign coordinates for center and starting position 'current'
Position center = new Position(width/2, height/2);

//Go to the Center
goToCoordinate(center);

//Spin - We're Done!
double heading = getHeading();
turnRight(360 + 360 - heading);
}

/*
* Method that allows input of a coordinate and robot will go to
* that coordinate and stop
*
* @param Position p - x and y coordinate of destination
* @return Void
*/

private void goToCoordinate(Position p){
//Get Current Position
Position current = new Position(getX(), getY());

//Get current heading
double currentHeading = getHeading();

//Variable for recalibrating heading to -180 < 0 < 180
//based on turnRight()
double currentHeadingNormalized;

//Calculate the Distance and angle from the current point
//to the destination point
DistanceAngle ad = current.angleDistanceBetweenTwoPoints(p);

//Convert Heading to be between -180 and 180 only
if(currentHeading > 180){
currentHeadingNormalized
= (-1) * (360 - currentHeading);
}
else
currentHeadingNormalized = currentHeading;

//Get the absolute difference between normalized heading and
//angle to destination point
double angleDeltaAbsolute = Math.abs(Math.abs(currentHeadingNormalized)
-
Math.abs(ad.angle));

//Following Statements minimize spinning to point robot in position of
//destination point

//If current heading (normalized) is negative spin in the appropriate
//direction and the necessary rotation.
if (currentHeadingNormalized < 0){

//If angle and heading are both negative and angle is larger negative
if (ad.angle < currentHeadingNormalized){
turnLeft
(angleDeltaAbsolute);
}
else if (ad.angle < 0){
turnRight
(angleDeltaAbsolute);
}
else{
//If angle is positive then spin left or right depending on shortest
//rotation.
if (360 + ad.angle - currentHeading > 180){
turnLeft
(currentHeading - ad.angle);
}
else{
turnRight
(360 + ad.angle - currentHeading);
}
}

}

//Similar conditions for positive heading (normalized)
else{
if(ad.angle > currentHeadingNormalized){
turnRight
(angleDeltaAbsolute);
}
else if(ad.angle > 0){
turnLeft
(angleDeltaAbsolute);
}
else{
if (360 - currentHeading + ad.angle > 180){
turnLeft
(currentHeading - ad.angle);
}
else{
turnRight
(360 + currentHeading + ad.angle);
}
}
}

//At this point, the robot should be positioned to point towards
//the destiation point.

//Move Robot ahead the correct distance to the destination point
ahead(ad.distance);
}
}

/**
* Position Class to store position of center and starting position
* as coordinates. Also calculates:
*
* - Distance between two points
* - Angle between two points in degrees
*/
class Position{
double x;
double y;

public Position(double x, double y){
this.x = x;
this.y = y;
}

DistanceAngle angleDistanceBetweenTwoPoints
(Position p){
double a = this.x - p.x;
double b = this.y - p.y;

//Calculate distance using Pythagorean Theorem
double distance = Math.sqrt(Math.pow(a, 2) + Math.pow(b,2));

//Angle variables for converting angle to degrees
double angleRadians, angleDegrees;

//Get angle in radians to center
angleRadians = Math.atan(a/b);

//Convert radians to degrees. This represents angle
//if robot starts in quadrant III
angleDegrees = 180 * angleRadians/Math.PI;

//If robot starts in quadrant I or II
if(b > 0){
angleDegrees
= (180 - Math.abs(angleDegrees));

//If we are in quadrant I
if(a > 0){
angleDegrees
*= -1;
}
}

return new DistanceAngle(distance, angleDegrees);
}

}

/**
* Object to hold calculations on Distance and Angle
* Calculated in the Position Class
*/
class DistanceAngle{
double distance;
double angle;

public DistanceAngle(double distance, double angle){
this.distance = distance;
this.angle = angle;
}
}

Robocode Position04

I completed position04 a little while ago and it's been a while since I've used trig functions.  The most time was spent wrapping my head around radians again.
I'm quite proud of the code since it took a lot of diagramming and trial and error.  It's a pretty trivial task (moving a robot to the middle of the battlefield), but it still took a while.
I was trying for a while to use the getBearing() function, but this requires an event and I looked up a few items on creating custom events, but gave up and decided to go with the brute math instead.
Something I want to look at later is using the least amount of turning to position the robot to face the center.  As it is now, the robot rotates to a heading of 0 degrees before doing anything (this is to normalize the heading to a known heading of 0).
********************************************************************************
package kgl
;

import robocode.Robot;

/**
* Position 04 Robot
*
* Move to the center of the playing field, spin around in a circle, and stop.
*
* @class ICS 413
* @author Kevin Leong
* @date 9/2/10
*/

public class Position04 extends Robot{

public void run(){
//Get battlefield dimensions
double width = getBattleFieldWidth();
double height = getBattleFieldHeight();

//Assign coordinates for center and starting position 'current'
Position center = new Position(width/2, height/2);
Position current = new Position(getX(), getY());

//Get starting heading
double currentHeading = getHeading();

//Calculate the Distance and angle from the starting point to the center of the
//battlefield
DistanceAngle ad = current.angleDistanceBetweenTwoPoints(center);

//Align to 0 degrees
turnRight(360-currentHeading);

//Turn the robot to face toward the center
turnRight(ad.angle);

//Move Robot ahead the correct distance
ahead(ad.distance);

//Spin - We're Done!
turnRight(360);
}
}

/**
* Position Class to store position of center and starting position
* as coordinates. Also calculates:
*
* - Distance between two points
* - Angle between two points in degrees
*/
class Position{
double x;
double y;

public Position(double x, double y){
this.x = x;
this.y = y;
}

DistanceAngle angleDistanceBetweenTwoPoints
(Position p){
double a = this.x - p.x;
double b = this.y - p.y;

//Calculate distance using Pythagorean Theorem
double distance = Math.sqrt(Math.pow(a, 2) + Math.pow(b,2));

//Angle variables for converting angle to degrees
double angleRadians, angleDegrees;

//Get angle in radians to center
angleRadians = Math.atan(a/b);
System.out.println("AngleRadians: " + angleRadians);

//Convert radians to degrees. This represents angle
//if robot starts in quadrant III or IV (below the center of the battlefield)
angleDegrees = 180 * angleRadians/Math.PI;

//If robot starts in quadrant I or II
if(b > 0){
angleDegrees
= (180 - Math.abs(angleDegrees));

//If we are in quadrant I
if(a > 0){
angleDegrees
*= -1;
}
}

return new DistanceAngle(distance, angleDegrees);
}

}

/**
* Object to hold calculations on Distance and Angle
* Calculated in the Position Class
*/
class DistanceAngle{
double distance;
double angle;

public DistanceAngle(double distance, double angle){
this.distance = distance;
this.angle = angle;
}
}