Difference between revisions of "Anti-Gravity Tutorial"

From Robowiki
Jump to navigation Jump to search
(Here you go, awesomeness!)
 
m (some minor changes)
Line 1: Line 1:
== What is Anti-Gravity Movement? ==
+
[[Anti-Gravity Movement]] is a medium-level movement that is used mainly in melee. Like most melee movements, it is focused on keeping your robot as far as possible from other ones. It involves the using the law of gravity, but reversed; you assign objects (in this case robots and walls) a 'gravity' push, then let the gravity pushes your robot.
[[Anti-Gravity Movement]] is a medium-level movement that is used mainly in melee. Like most melee movements, it is focused on keeping your robot as far as possible from other ones. It involves using the law of gravity, but reversed; you assign objects (in this case robots) a force based on distance, and then move in the direction with the least force. This means that other robots moving toward ours will "push" our robot away from them.
 
  
== So then, what's the first step?==
+
== Tracking the enemies ==
Before we can assign forces to robots, we need to know where the robots are. We'll be using a simple but effective system to track the movements of other robots. In the top of your robot, add:
+
Before we can assign forces to robots, we need to know where the robots are. We are using a simple but effective system to track the movements of other robots. In the top of your robot's code, add:
<pre>static Point2D.Double enemyPoints[]=new Point2D.Double[NUMBER_OF_ENEMIES];
 
int count;</pre>
 
For NUMBER_OF_ENEMIES, just put the largest number of robots that you think you'll be fighting. Making the number higher than normal won't hurt, but making it too low will cause an array out of bounds exception. Also, you will need to add import java.awt.geom.*; at the top for the Point2D.Double to work.
 
  
Then, in your OnScannedRobot method, you should add:
 
 
<pre>
 
<pre>
double absBearing=e.getBearingRadians()+getHeadingRadians();
+
static Point2D.Double[] enemyPoints = new Point2D.Double[NUMBER_OF_ENEMIES];
 +
int count;
 +
</pre>
 +
 
 +
For NUMBER_OF_ENEMIES, just put the largest number of robots that you think you'll be fighting. Making the number higher than normal won't hurt, but making it too low will cause an array out of bounds exception. Also, you will need to add <code>import java.awt.geom.*;</code> at the top for the <code>Point2D.Double</code> to work.
 +
 
 +
Then add the following code in your OnScannedRobot method:
 +
<pre>
 +
double absBearing = e.getBearingRadians() + getHeadingRadians();
 
enemyPoints[count]=new Point2D.Double(getX()+e.getDistance()*Math.sin(absBearing),getY()+e.getDistance()*Math.cos(absBearing));
 
enemyPoints[count]=new Point2D.Double(getX()+e.getDistance()*Math.sin(absBearing),getY()+e.getDistance()*Math.cos(absBearing));
 
if(++count>=getOthers()){
 
if(++count>=getOthers()){

Revision as of 15:13, 21 January 2010

Anti-Gravity Movement is a medium-level movement that is used mainly in melee. Like most melee movements, it is focused on keeping your robot as far as possible from other ones. It involves the using the law of gravity, but reversed; you assign objects (in this case robots and walls) a 'gravity' push, then let the gravity pushes your robot.

Tracking the enemies

Before we can assign forces to robots, we need to know where the robots are. We are using a simple but effective system to track the movements of other robots. In the top of your robot's code, add:

static Point2D.Double[] enemyPoints = new Point2D.Double[NUMBER_OF_ENEMIES];
int count;

For NUMBER_OF_ENEMIES, just put the largest number of robots that you think you'll be fighting. Making the number higher than normal won't hurt, but making it too low will cause an array out of bounds exception. Also, you will need to add import java.awt.geom.*; at the top for the Point2D.Double to work.

Then add the following code in your OnScannedRobot method:

		double absBearing = e.getBearingRadians() + getHeadingRadians();
		enemyPoints[count]=new Point2D.Double(getX()+e.getDistance()*Math.sin(absBearing),getY()+e.getDistance()*Math.cos(absBearing));
		if(++count>=getOthers()){
			count=0;
		}

Now, lets assume you understand Absolute Bearing and move on to the formula for finding the enemy's position. To find a point in Robocode, you need to know two things: the point's distance and bearing from you. After you know that, the formula for the coordinate pair is (!not code!):

new X=Your x-coordinate + distance*sin(bearing)
new Y=Your y-coordinate + distance*cos(bearing)

In the code, we simply use this formula to find the other robots coordinates. The part after that simply keeps track of which robot we are on, and goes back to the beginning after it reaches the amount of robots left alive.

Please not that this is not exactly the optimal system for tracking the enemies' position. It can only be used with spinning radar, and will occasionally mess up.

Well then, how do I calculate the enemy robot's force?

The formula for gravity is 1/distance^2. We'll be using that, with distance being the enemy robots distance. To find the distance from our point to theirs, we could go through the trouble of using the distance formula, or just simply use:

 double distance=enemyPoints[i].distance(getX(),getY());

We'll be taking the easy way. The other thing we have to figure out is the enemy robot's absolute bearing to us. The way we can find this in Robocode is:

Utils.normalAbsoluteAngle(Math.atan2(Enemy X-Our X,Enemy Y-Our Y));

After we have both of these pieces of information, we can actually start figuring out where we want to move. We're going to set up a loop that goes through all the robots for a given angle, and finds the amount of force pushing us toward or away from that direction:

for(double angle=0;angle<Math.PI*2;angle+=Math.PI/16){
	double force=0;
	for(int i=0;i<getOthers();i++){
		try{
			double absBearing=Utils.normalAbsoluteAngle(Math.atan2(enemyPoints[i].x-getX(),enemyPoints[i].y-getY()));
			double distance=enemyPoints[i].distance(getX(),getY());
			if(Math.abs(absBearing-angle)<Math.PI/2){
				force+=1/Math.pow(distance,2);
			}
			else{
				force-=1/Math.pow(distance,2);
			}
		}
		catch(Exception ex){
		
		}
       }
}

Well, this will go through all the angles we could turn to and then find the force for each one. You've seen the absolute bearing, distance, and force calculations; the only real new thing in here is the part that decides whether to add or subtract the robot's force. Basically what it does is it takes the robots bearing, and figures out which side of the current angle we're testing the robot is on. Please note that it is VERY IMPORTANT to have the less than sign pointing the right way, or else other robots will attract yours! The try/catch is needed because it will generate a NPE at the beginning of rounds if you don't include it.


So how do we make our robot move?

Next what we have to do is find the direction of least resistance. Since you can easily figure out how to do that with the above loop, I'll let you figure out the best angle. The main problem here is finding the fastest way to turn to the right angle. We don't ever want to make more than a 90 degree turn! Here's how you do it, once you've found the best angle:

if(Math.abs(angle-getHeadingRadians())<Math.PI/2){
	      setTurnRightRadians(Utils.normalRelativeAngle(angle-getHeadingRadians()));
		setAhead(Double.POSITIVE_INFINITY);
	}
	else{
		setTurnRightRadians(Utils.normalRelativeAngle(angle+Math.PI-getHeadingRadians()));
		setAhead(-Double.POSITIVE_INFINITY);
	}
}

This is basically the same as figuring out which way a robot pushes us, just applied to the angle we wish to turn to instead of the angle of the other robot.

Well, here you go!

That's it for the tutorial! There's something I would like you to know: this tutorial does not create a competitive movement. We haven't even put in wall avoidance, which is very important. Also, it tends to do some melee no-nos such as staying in one spot too long. Some ways you can improve this:

  • Add wall avoidance.
  • Weight robots' danger based on energy.
  • Try to keep the robot from sitting in one spot.