Difference between revisions of "Anti-Gravity Tutorial"
m (some minor changes) |
(some little fixes, add category) |
||
Line 13: | Line 13: | ||
Then add the following code in your OnScannedRobot method: | Then add the following code in your OnScannedRobot method: | ||
<pre> | <pre> | ||
− | + | 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; | |
− | + | }</pre> | |
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!): | 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!): | ||
<pre>new X=Your x-coordinate + distance*sin(bearing) | <pre>new X=Your x-coordinate + distance*sin(bearing) | ||
Line 23: | Line 23: | ||
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. | 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' | + | Please not that this is not exactly the optimal system for tracking the enemies' positions. It can only be used with spinning radar, and will occasionally mess up. |
== Well then, how do I calculate the enemy robot's force? == | == 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: | 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: | ||
− | <pre> double distance=enemyPoints[i].distance(getX(),getY());</pre> | + | <pre>double distance=enemyPoints[i].distance(getX(),getY());</pre> |
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: | 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: | ||
<pre>Utils.normalAbsoluteAngle(Math.atan2(Enemy X-Our X,Enemy Y-Our Y));</pre> | <pre>Utils.normalAbsoluteAngle(Math.atan2(Enemy X-Our X,Enemy Y-Our Y));</pre> | ||
Line 33: | Line 33: | ||
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: | 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: | ||
<pre>for(double angle=0;angle<Math.PI*2;angle+=Math.PI/16){ | <pre>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){ | |
− | + | ||
− | + | } | |
− | + | } | |
} | } | ||
</pre> | </pre> | ||
− | 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 | + | 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 robot's 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? == | == So how do we make our robot move? == | ||
Line 58: | Line 57: | ||
<pre> | <pre> | ||
if(Math.abs(angle-getHeadingRadians())<Math.PI/2){ | 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); | |
− | + | } | |
}</pre> | }</pre> | ||
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. | 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. | ||
Line 73: | Line 72: | ||
* Weight robots' danger based on energy. | * Weight robots' danger based on energy. | ||
* Try to keep the robot from sitting in one spot. | * Try to keep the robot from sitting in one spot. | ||
+ | |||
+ | [[Category:Tutorials]] |
Revision as of 17:02, 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.
Contents
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' positions. 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 robot's 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.