[Home]CodeSnippets/Nano Circular Linear Predictor

Robo Home | CodeSnippets | Changes | Preferences | AllPages

Hereunder is the source-code from my bot Nano_Circular_Linear_Predictor, a bot I built just to prove that a circular predictor fits into a NanoBot. :-)


public class Nano_Circular_Linear_Predictor extends AdvancedRobot
{
	static double lastEnemyHeading;
	static double radarturn=1;
	
	public void run()
	{
		do
		{
			setAhead(20*Math.sin(getTime()/10));
			setTurnRadarRightRadians(radarturn);	
			fire(3);
		}while(true);
	}
	
	public void onScannedRobot(ScannedRobotEvent e)
	{
		radarturn=-radarturn;
		double w=e.getHeadingRadians()-lastEnemyHeading;
		lastEnemyHeading=e.getHeadingRadians();
		double absbearing=e.getBearingRadians()+getHeadingRadians();
		double eX=e.getDistance()*Math.sin(absbearing);
		double eY=e.getDistance()*Math.cos(absbearing);

		double db=0;
		double ww=lastEnemyHeading;  // enemy's starting heading
		do
		{
			db+=11; //11 is the velocity of a fire(3) bullet.
			double dx=e.getVelocity()*Math.sin(ww);
			double dy=e.getVelocity()*Math.cos(ww);
			ww+=w;  // turn w radians for next step
			eX+=dx;
			eY+=dy;
		}while (db< Point2D.distance(0,0,eX,eY));	// The bullet travelled far enough to hit
								// our target!
		
		setTurnGunRightRadians(Math.asin(Math.sin(Math.atan2(eX, eY) - getGunHeadingRadians())));
		setTurnRightRadians(e.getBearingRadians() + .5*Math.PI);
	}
}


Smaller code
		double enemyAbsoluteBearing=e.getBearingRadians()+getHeadingRadians();
		double eX=e.getDistance()*Math.sin(enemyAbsoluteBearing);
		double eY=e.getDistance()*Math.cos(enemyAbsoluteBearing);
				
		double db=0;
		double ww=lastEnemyHeading;  // enemy's starting heading
							
		do
		{
			db+=11; //11 is the velocity of a fire(3) bullet.
			//db += (20.0 - 3.0 * bulletPower);
			//double dx=e.getVelocity()*Math.sin(ww);
			//double dy=e.getVelocity()*Math.cos(ww);
			//ww+=w;  // turn w radians for next step
			ww += e.getHeadingRadians()-lastEnemyHeading;
			eX+=e.getVelocity()*Math.sin(ww);//dx;
			eY+=e.getVelocity()*Math.cos(ww);//dy;
		} while (db < Point2D.distance(0,0,eX,eY));	// The bullet travelled far enough to hit our target!

		lastEnemyHeading=e.getHeadingRadians();
				
		setTurnGunRightRadians(Utils.normalRelativeAngle(Math.atan2(eX, eY) - getGunHeadingRadians()));

-- Stelokim


To make the code smaller, set variables inside another line:

double enemyAbsoluteBearing;
double eX = e.getDistance() + Math.sin(enemyAbsoluteBearing = e.getBearingRadians() + getHeadingRadians());
double eY = e.getDistance() + Math.sin(enemyAbsoluteBearing);
-- Kinsen

Don't you mean

double eX = getX() + Math.sin...
double eY = getY() + Math.cos...
-- Starrynte

No, in this example, eX and eY represent the enemy Position relative to yours --Dummy

btw, I'm not sure that putting "lastenemyHeading = e.getHeadingRadians()" after the loop is a good idea, because before the loop, "ww=lastenemyHeading" will get an incorrect value. (though I haven't tested this, I haven't played with RoboCode for years now :-p) -- Dummy

I don't think it would make much of a difference, though. The first tick of the round it would be wrong, but no one can fire the first tick anyway, so it should be irrelevant. I think so, at least. I'm in no way an expert on this, all I know about Java is what I've figured out and what people have told me here at the wiki. --Bayen

Well, the thing is that ww needs to start at the enemies current heading. If you put "lastenemyHeading = ..." after the assignment to ww, you'll be using the enemy heading of the previous scan, and the circular prediction will be a slightly less accurate. This will be even more of a problem if you're not scanning your target every tick, which may be the case during melee. --Dummy

Oh wow, this is gonna sound really retarded, but, couldn't you do something like this? Its probably bigger, but I dislike loops.

package chase.nano;

import static java.lang.Math.*;
import robocode.*;

public class NanoCircle extends AdvancedRobot {
	public static double lastX, lastY, lastHeading;
	
	public void run() {
		lastX = lastY = 0;
		while(true) {
			setTurnRadarRightRadians(Double.POSITIVE_INFINITY);
		}
	}
	
	public void onScannedRobot(ScannedRobotEvent e) {
		double absAngle, x, y, heading;
		
		absAngle = e.getBearingRadians() + getHeadingRadians();
		x = getX() + sin(absAngle) * e.getDistance();
		y = getY() + cos(absAngle) * e.getDistance();
		heading = e.getHeadingRadians();
		
		if(lastX != 0) {
			//the lines, unmutilated
			//b=-tan(heading + PI/2)*x+y
			//lastB=-tan(lastHeading + PI/2)*lastX+lastY
			double m1,m2,b1,r, circleX;;
			double circleY = (circleX = ((m2=-tan(heading + PI/2))*x+y - 
					(b1=(m1=-tan(lastHeading + PI/2))*lastX+lastY))
					/ (m1 - m2))*m1+b1;
			//the radius, fyi
			r = sqrt((circleX-x)*(circleX-x)+(circleY-y)*(circleY-y));
			
			//yay, I found the center, now to project along it
			//.. I kinda got lost here, but I would think find
			//where the bullet can intercept the robot
		}
		
		lastX = x;
		lastY = y;
		lastHeading = heading;
		
		setTurnRadarLeftRadians(getRadarTurnRemainingRadians());
	}
}

--Chase-san


Robo Home | CodeSnippets | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited December 7, 2007 22:12 EST by Chase-san (diff)
Search: