Difference between revisions of "Wall Smoothing/Implementations"
(migrating from old wiki) |
m (use <syntaxhighlight/>) |
||
Line 9: | Line 9: | ||
This is used in many bots, such as [[Tityus]] and [[Raiko]]. | This is used in many bots, such as [[Tityus]] and [[Raiko]]. | ||
− | < | + | <syntaxhighlight> |
static double direction; //1 for clockwise or -1 for counterclockwise | static double direction; //1 for clockwise or -1 for counterclockwise | ||
... | ... | ||
Line 34: | Line 34: | ||
setAhead(100); | setAhead(100); | ||
setTurnRightRadians(turn); | setTurnRightRadians(turn); | ||
− | </ | + | </syntaxhighlight> |
== Fast Wall Smoothing (by [[User:Voidious|Voidious]]) == | == Fast Wall Smoothing (by [[User:Voidious|Voidious]]) == | ||
Line 41: | Line 41: | ||
Note that while this is iterative and contains a "sanity check" to avoid an infinite loop, it should never loop more than twice if implemented correctly. It is used in [[Dookious]] and [[Diamond]], so take a look at their source code if you're still confused on how to use it. | Note that while this is iterative and contains a "sanity check" to avoid an infinite loop, it should never loop more than twice if implemented correctly. It is used in [[Dookious]] and [[Diamond]], so take a look at their source code if you're still confused on how to use it. | ||
− | < | + | <syntaxhighlight> |
// _bfWidth and _bfHeight set to battle field width and height | // _bfWidth and _bfHeight set to battle field width and height | ||
private static double WALL_STICK = 140; | private static double WALL_STICK = 140; | ||
Line 106: | Line 106: | ||
return angle; // you may want to normalize this | return angle; // you may want to normalize this | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
== Non-Iterative Wall Smoothing (by [[User:David Alves|David Alves]]) == | == Non-Iterative Wall Smoothing (by [[User:David Alves|David Alves]]) == |
Revision as of 06:59, 1 July 2010
- Wall Smoothing Sub-pages:
- Wall Smoothing - Implementations
Contents
Simple Iterative Wall Smoothing (by PEZ)
This algorithm is simple to code and easy to understand, but it is relatively slow to execute. This is a good one to use for Random Movement or Code Size-restricted bots. If you're Wave Surfing with Precise Prediction, your Wall Smoothing is called many times per tick, so you'll want something faster.
This is used in many bots, such as Tityus and Raiko.
static double direction; //1 for clockwise or -1 for counterclockwise
...
// this is the absolute heading I want to move in to go clockwise or
// counterclockwise around my enemy if I want to move closer to them,
// I would use less of an offset from absBearing (I'll go right toward
// them if I move at absBearing)
double goalDirection = absBearing-Math.PI/2*direction;
Rectangle2D fieldRect = new Rectangle2D.Double(18, 18, getBattleFieldWidth()-36,
getBattleFieldHeight()-36);
while (!fieldRect.contains(getX()+Math.sin(goalDirection)*120, getY()+
Math.cos(goalDirection)*120))
{
goalDirection += direction*.1; //turn a little toward enemy and try again
}
double turn =
robocode.util.Utils.normalRelativeAngle(goalDirection-getHeadingRadians());
if (Math.abs(turn) > Math.PI/2)
{
turn = robocode.util.Utils.normalRelativeAngle(turn + Math.PI);
setBack(100);
}
else
setAhead(100);
setTurnRightRadians(turn);
Fast Wall Smoothing (by Voidious)
This algorithm is much faster than the simple one (above), and the code is nice and compact, but it can be difficult to understand. It's designed to mimic the functionality of the simple one by PEZ, but it is much faster to execute and allows you to get very close to the walls.
Note that while this is iterative and contains a "sanity check" to avoid an infinite loop, it should never loop more than twice if implemented correctly. It is used in Dookious and Diamond, so take a look at their source code if you're still confused on how to use it.
// _bfWidth and _bfHeight set to battle field width and height
private static double WALL_STICK = 140;
private java.awt.geom.Rectangle2D.Double _fieldRect =
new java.awt.geom.Rectangle2D.Double(18, 18,
_bfWidth-36, _bfHeight-36);
// ...
/**
* x/y = current coordinates
* startAngle = absolute angle that tank starts off moving - this is the angle
* they will be moving at if there is no wall smoothing taking place.
* orientation = 1 if orbiting enemy clockwise, -1 if orbiting counter-clockwise
* smoothTowardEnemy = 1 if smooth towards enemy, -1 if smooth away
* NOTE: this method is designed based on an orbital movement system; these
* last 2 arguments could be simplified in any other movement system.
*/
public double wallSmoothing(double x, double y, double startAngle,
int orientation, int smoothTowardEnemy) {
angle = startAngle;
// in Java, (-3 MOD 4) is not 1, so make sure we have some excess
// positivity here
angle += (4*Math.PI);
double testX = x + (Math.sin(angle)*WALL_STICK);
double testY = y + (Math.cos(angle)*WALL_STICK);
double wallDistanceX = Math.min(x - 18, _bfWidth - x - 18);
double wallDistanceY = Math.min(y - 18, _bfHeight - y - 18);
double testDistanceX = Math.min(testX - 18, _bfWidth - testX - 18);
double testDistanceY = Math.min(testY - 18, _bfHeight - testY - 18);
double adjacent = 0;
int g = 0; // because I'm paranoid about potential infinite loops
while (!_fieldRect.contains(testX, testY) && g++ < 25) {
if (testDistanceY < 0 && testDistanceY < testDistanceX) {
// wall smooth North or South wall
angle = ((int)((angle + (Math.PI/2)) / Math.PI)) * Math.PI;
adjacent = Math.abs(wallDistanceY);
} else if (testDistanceX < 0 && testDistanceX <= testDistanceY) {
// wall smooth East or West wall
angle = (((int)(angle / Math.PI)) * Math.PI) + (Math.PI/2);
adjacent = Math.abs(wallDistanceX);
}
// use your own equivalent of (1 / POSITIVE_INFINITY) instead of 0.005
// if you want to stay closer to the wall ;)
angle += smoothTowardEnemy*orientation*
(Math.abs(Math.acos(adjacent/WALL_STICK)) + 0.005);
testX = x + (Math.sin(angle)*WALL_STICK);
testY = y + (Math.cos(angle)*WALL_STICK);
testDistanceX = Math.min(testX - 18, _bfWidth - testX - 18);
testDistanceY = Math.min(testY - 18, _bfHeight - testY - 18);
if (smoothTowardEnemy == -1) {
// this method ended with tank smoothing away from enemy... you may
// need to note that globally, or maybe you don't care.
}
}
return angle; // you may want to normalize this
}
Non-Iterative Wall Smoothing (by David Alves)
This algorithm is very slightly faster than Voidious' and is simple to understand, but the code is huge and ugly. You have been warned! See /Non-Iterative.
Non-Iterative Wall Hugging (by Simonton)
This algorithm allows you to get closer to the walls by adjusting the length of the "blind man's stick" based on your bot's current position relative to the wall. See /Fancy Stick.