Difference between revisions of "SuperSpinBot"

From Robowiki
Jump to navigation Jump to search
(SuperSpinBot)
 
m (Using <syntaxhighlight>.)
Line 11: Line 11:
  
 
== Code ==
 
== Code ==
<pre>package wiki.SuperSampleBot;
+
<syntaxhighlight>package wiki.SuperSampleBot;
  
 
import robocode.*;
 
import robocode.*;
Line 188: Line 188:
  
 
}
 
}
  </pre>
+
  </syntaxhighlight>

Revision as of 09:31, 1 July 2010

SuperSpinBot is a part of the Super Sample Bots set by CrazyBassoonist. It is intended to provide new robocoders with a new challenge after beating all of the sample robots. This robot is currently far more difficult to beat than the other SuperSamples, but expect them to get harder soon too.


Movement

SuperSpinBot moves in circles, changing speed and turn rate every turn. It also randomly changes turn and movement direction when the enemy fires.


Targeting

SuperTracker uses a averaged velocity circular gun for aiming, segmented on enemy velocity. This is a decent gun in itself, and I expect it could be modified very easily to make it almost rumble-quality. This robot is a good starting point for learning very simple segmentation.


Code

package wiki.SuperSampleBot;

import robocode.*;
import java.awt.*;
import robocode.util.*;
import java.awt.geom.*;

/**
 * SuperSpinBot - a Super Sample Robot by CrazyBassoonist based on the robot Spinbot by Mathew Nelson and maintained by Flemming N. Larsen
 * <p/>
 * Circular movement, Circular targeting.... Everything is circles.
 *                                                                                      
 * 		       S                            S                                             		
 *              R       P                    R       P                                         
 *             E         I                  E         I                                         
 *            P     O     N                P     O     N                                       
 *             U         B                  U         B                                         
 *               S     O                     S       O                                        
 *                  T                            T
 */





public class SuperSpinBot extends AdvancedRobot {
	//gun variables
	static double enemyVelocities[][]=new double[400][4];
	static int currentEnemyVelocity;
	static int aimingEnemyVelocity;
	double velocityToAimAt;
	boolean fired;
	double oldTime;
	int count;
	int averageCount;
	
	//movement variables
	static double turn=2;
	int turnDir=1;
	int moveDir=1;
	double oldEnemyHeading;
	double oldEnergy=100;
	public void run(){
		// Set colors
		setBodyColor(Color.blue);
		setGunColor(Color.blue);
		setRadarColor(Color.black);
		setScanColor(Color.yellow);

		setAdjustGunForRobotTurn(true);
		setAdjustRadarForGunTurn(true);
		do{
			turnRadarRightRadians(Double.POSITIVE_INFINITY);
		}while(true);
	}
	public void onScannedRobot(ScannedRobotEvent e){
		double absBearing=e.getBearingRadians()+getHeadingRadians();
		Graphics2D g=getGraphics();
		
		//increase our turn speed amount each tick,to a maximum of 8 and a minimum of 4
		turn+=0.2*Math.random();
		if(turn>8){
			turn=2;
		}
		
		//when the enemy fires, we randomly change turn direction and whether we go forwards or backwards
		if(oldEnergy-e.getEnergy()<=3&&oldEnergy-e.getEnergy()>=0.1){
			if(Math.random()>.5){
				turnDir*=-1;
			}
			if(Math.random()>.8){
				moveDir*=-1;
			}
		}
		
		//we set our maximum speed to go down as our turn rate goes up so that when we turn slowly, we speed up and vice versa;
		setMaxTurnRate(turn);
		setMaxVelocity(12-turn);
		setAhead(90*moveDir);
		setTurnLeft(90*turnDir);
		oldEnergy=e.getEnergy();
		
		
		//find our which velocity segment our enemy is at right now
		if(e.getVelocity()<-2){
			currentEnemyVelocity=0;
		}
		else if(e.getVelocity()>2){
			currentEnemyVelocity=1;
		}
		else if(e.getVelocity()<=2&&e.getVelocity()>=-2){
			if(currentEnemyVelocity==0){
				currentEnemyVelocity=2;
			}
			else if(currentEnemyVelocity==1){
					currentEnemyVelocity=3;
			}
		}
		
		//update the one we are using to determine where to store our velocities if we have fired and there has been enough time for a bullet to reach an enemy
		//(only a rough approximation of bullet travel time);
		if(getTime()-oldTime>e.getDistance()/12.8&&fired==true){
			aimingEnemyVelocity=currentEnemyVelocity;
		}
		else{
			fired=false;
		}
		
		//record a new enemy velocity and raise the count
		enemyVelocities[count][aimingEnemyVelocity]=e.getVelocity();
		count++;
		if(count==400){
			count=0;
		}
		
		//calculate our average velocity for our current segment
		averageCount=0;
		velocityToAimAt=0;
		while(averageCount<400){
			velocityToAimAt+=enemyVelocities[averageCount][currentEnemyVelocity];
			averageCount++;
		}
		velocityToAimAt/=400;
		
		
		//pulled straight out of the circular targeting code on the Robowiki. Note that all I did was replace the enemy velocity and
		//put in pretty graphics that graph the enemies predicted movement(actually the average of their predicted movement) 
		//Press paint on the robot console to see the debugging graphics.
		//Note that this gun can be improved by adding more segments and also averaging turn rate.
		double bulletPower = Math.min(2.4,Math.min(e.getEnergy()/4,getEnergy()/10));
		double myX = getX();
		double myY = getY();
		double enemyX = getX() + e.getDistance() * Math.sin(absBearing);
		double enemyY = getY() + e.getDistance() * Math.cos(absBearing);
		double enemyHeading = e.getHeadingRadians();
		double enemyHeadingChange = enemyHeading - oldEnemyHeading;
		oldEnemyHeading = enemyHeading;
		double deltaTime = 0;
		double battleFieldHeight = getBattleFieldHeight(), 
		       battleFieldWidth = getBattleFieldWidth();
		double predictedX = enemyX, predictedY = enemyY;
		while((++deltaTime) * (20.0 - 3.0 * bulletPower) < 
		      Point2D.Double.distance(myX, myY, predictedX, predictedY)){		
			predictedX += Math.sin(enemyHeading) * velocityToAimAt;
			predictedY += Math.cos(enemyHeading) * velocityToAimAt;
			enemyHeading += enemyHeadingChange;
			g.setColor(Color.red);
			g.fillOval((int)predictedX-2,(int)predictedY-2,4,4);
			if(	predictedX < 18.0 
				|| predictedY < 18.0
				|| predictedX > battleFieldWidth - 18.0
				|| predictedY > battleFieldHeight - 18.0){

				predictedX = Math.min(Math.max(18.0, predictedX), 
				    battleFieldWidth - 18.0);	
				predictedY = Math.min(Math.max(18.0, predictedY), 
				    battleFieldHeight - 18.0);
				break;
			}
		}
		double theta = Utils.normalAbsoluteAngle(Math.atan2(
		    predictedX - getX(), predictedY - getY()));

		setTurnRadarRightRadians(Utils.normalRelativeAngle(
		    absBearing - getRadarHeadingRadians())*2);
		setTurnGunRightRadians(Utils.normalRelativeAngle(
		    theta - getGunHeadingRadians()));
		if(getGunHeat()==0){
			fire(bulletPower);
			fired=true;
		}

		
		
	}

}