//* 译权：Robocode 中华联盟 www.robochina.org
//* 转载请保留此文件头 @2002.10 31 All Rights Reserved
* SnippetBot - a robot by Alisdair Owens
* This bot includes all sorts of useful snippets. It is not
* designed to be a good fighter (although it does well 1v1),
* just to show how certain things are done
* Bits of code lifted from Nicator and Chrisbot
* Conventions in this bot include: Use of radians throughout
* Storing absolute positions of enemy bots rather than relative ones
* Very little code in events
* These are all good programming practices for robocode
* There may also be methods that arent used; these might just be useful for you.
public class SnippetBot extends AdvancedRobot
* run: SnippetBot's default behavior
Enemy target; //our current enemy 代表对手，包括了对手的所有有用参数
final double PI = Math.PI; //just a constant
int direction = 1; //direction we are heading...1 = forward, -1 = backwards
double firePower; //the power of the shot we will be using - set by do firePower() 设置我们的火力
public void run()
target = new Enemy(); //实例化Enemy()类
target.distance = 100000; //initialise the distance so that we can select a target
setColors(Color.red,Color.blue,Color.green); //sets the colours of the robot
//the next two lines mean that the turns of the robot, gun and radar are independant
turnRadarRightRadians(2*PI); //turns the radar right around to get a view of the field 以弧度计算旋转一周
doMovement(); //Move the bot 移动机器人
doFirePower(); //select the fire power to use 选择火力
doScanner(); //Oscillate the scanner over the bot 扫描
doGun(); //move the gun to predict where the enemy will be 预测敌人，调整炮管
execute(); //execute all commands 上面使用的都为AdvancedRobot类中的非阻塞调用
* This simple function calculates the fire power to use (from 0.1 to 3)
* based on the distance from the target. We will investigate the data structure
* holding the target data later.
firePower = 400/target.distance;//selects a bullet power based on our distance away from the target
* This is the movememnt function. It will cause us
* to circle strafe the enemy (ie move back and forward,
* circling the enemy. if you don't know what strafing means
* play more quake.
* The direction variable is global to the class. Passing a
* negative number to setAhead causes the bot to go backwards
if (getTime()%20 == 0) //?过20的倍数时间就反转方向
//every twenty 'ticks'
direction *= -1; //reverse direction
setAhead(direction*300); //move in that direction
setTurnRightRadians(target.bearing + (PI/2)); //every turn move to circle strafe the enemy
* this scanner method allows us to make our scanner track our target.
* it will track to where our target is at the moment, and some further
* in case the target has moved. This way we always get up to the minute
* information on our target 雷达锁定目标
double radarOffset; //雷达偏移量
if (getTime() - target.ctime > 4) //???why来回扫了4个回合都没扫到意味失去了目标，再全扫一遍
//if we haven't seen anybody for a bit....
radarOffset = 360; //rotate the radar to find a target
//next is the amount we need to rotate the radar by to scan where the target is now
radarOffset = getRadarHeadingRadians() - absbearing(getX(),getY(),target.x,target.y);
//this adds or subtracts small amounts from the bearing for the radar to produce the wobbling
//and make sure we don't lose the target
if (radarOffset < 0)
radarOffset -= PI/8; //(0.375)
radarOffset += PI/8;
//turn the radar
* This simple method moves the gun to the bearing that we predict the
* enemy will be by the time our bullet will get there.
* the 'absbearing' method can be found in the helper functions section
* the nextX and nextY method can be found in the 'Enemy' class description
//works out how long it would take a bullet to travel to where the enemy is *now*
//this is the best estimation we have
//计算子弹到达目标的时间长speed = 20 - 3 * power;有计算公式,距离除速度=时间
long time = getTime() + (int)(target.distance/(20-(3*firePower)));
//offsets the gun by the angle to the next shot based on linear targeting provided by the enemy class
double gunOffset = getGunHeadingRadians() - absbearing(getX(),getY(),target.guessX(time),target.guessY(time));
* This set of helper methods. You may find several of these very useful
* They include the ability to find the angle to a point.
//if a bearing is not within the -pi to pi range, alters it to provide the shortest angle
double NormaliseBearing(double ang)
if (ang > PI)
ang -= 2*PI;
if (ang < -PI)
ang += 2*PI;
//if a heading is not within the 0 to 2pi range, alters it to provide the shortest angle
double NormaliseHeading(double ang)
if (ang > 2*PI)
ang -= 2*PI;
if (ang < 0)
ang += 2*PI;
//returns the distance between two x,y coordinates '**'
public double getrange( double x1,double y1, double x2,double y2 )
double xo = x2-x1;
double yo = y2-y1;
double h = Math.sqrt( xo*xo + yo*yo );
//gets the absolute bearing between to x,y coordinates
public double absbearing( double x1,double y1, double x2,double y2 )
double xo = x2-x1;
double yo = y2-y1;
double h = getrange( x1,y1, x2,y2 );
if( xo > 0 && yo > 0 )
return Math.asin( xo / h );
if( xo > 0 && yo < 0 )
return Math.PI - Math.asin( xo / h ); //x为正,y为负第二象限角
if( xo < 0 && yo < 0 )
return Math.PI + Math.asin( -xo / h ); //第三象限内180+角度
if( xo < 0 && yo > 0 )
return 2.0*Math.PI - Math.asin( -xo / h ); //四象限360-角度
* onScannedRobot: What to do when you see another robot
public void onScannedRobot(ScannedRobotEvent e)
//if we have found a closer robot....
if ((e.getDistance() < target.distance)||(target.name == e.getName()))
//the next line gets the absolute bearing to the point where the bot is
double absbearing_rad = (getHeadingRadians()+e.getBearingRadians())%(2*PI);
//this section sets all the information about our target
target.name = e.getName();
target.x = getX()+Math.sin(absbearing_rad)*e.getDistance(); //works out the x coordinate of where the target is
target.y = getY()+Math.cos(absbearing_rad)*e.getDistance(); //works out the y coordinate of where the target is
target.bearing = e.getBearingRadians();
target.head = e.getHeadingRadians();
target.ctime = getTime(); //game time at which this scan was produced 扫描到机器人的游戏时间
target.speed = e.getVelocity(); //得到敌人速度
target.distance = e.getDistance();
public void onRobotDeath(RobotDeathEvent e)
if (e.getName() == target.name)
target.distance = 10000; //this will effectively make it search for a new target
* This class holds scan data so that we can remember where enemies were
* and what they were doing when we last scanned then.
* You could make a hashtable (with the name of the enemy bot as key)
* or a vector of these so that you can remember where all of your enemies are
* in relation to you.
* This class also holds the guessX and guessY methods. These return where our targeting
* system thinks they will be if they travel in a straight line at the same speed
* as they are travelling now. You just need to pass the time at which you want to know
* where they will be.
* ok, we should really be using accessors and mutators here,
* (i.e getName() and setName()) but life's too short.
public double bearing;
public double head;
public long ctime; //game time that the scan was produced
public double speed;
public double x,y;
public double distance;
public double guessX(long when)
//以扫描时和子弹到达的时间差 ＊ 最大速度=距离, 再用对手的坐标加上移动坐标得到敌人移动后的坐标
long diff = when - ctime;
return x+Math.sin(head)*speed*diff; //目标移动后的坐标
public double guessY(long when)
long diff = when - ctime;
I started Duelist as a general purpose bot, based off of SnippetBot by Alisdair Owens. I quickly realized that melee and duel matches were two completely different ball games and for a time my code was riddled with if(duel) statements. Eventually I decided that I would focus on duels since they present a much simpler and more elegant problem than melee, to me at least, and Duelist was born.
Duelist uses many common concepts found in the top bots. Among them, it fires virtual bullets, the idea made famous by SandboxLump (written by Paul Evans). Duelist also uses anti-gravity for movement, though it has been thoroughly overhauled to eliminate the problems with anti-gravity, such as getting stuck in a local minimum. I also keep statistics on how well my various targetting methods are doing in a data structure that persists from round to round, so that I can learn which methods work the best without having to guess randomly at the start of each round.
Some things I think I'm the only bot out there doing:
Conduct my initial radar sweep by turning the body, gun, and radar before setting them to move independantly. This saves about 3 turns in the beginning.
Firing virtual bullets ONLY when I fire a real one. Although this slows down my learning, there's no better way to learn the movement of bots that attempt bullet dodging. Since they move when I fire, I learn only their dodging movement.
Changing bullet power based on how hard the enemy is to hit as well as the current range. It's silly to fire a .5 power bullet at SittingDuck just because he's 900 units away from you. I'm sure someone else is doing this but I don't know of any personally so I'll list it here.
In a straightforward anti-gravity movement system, you resolve the forces and move along the vector. If you visualize the battlefield as terrain with anti-gravity points being hills, what you're doing is always rolling downhill. However, you can get trapped in bad places this way. For example, if you're cornered, the walls will be repelling pushing you towards the enemy and the enemy will push you towards the walls, and you'll jiggle in place while he shoots you at his leisure. The method that I use to avoid this is to test how much force is at many different points around me and move towards the one with the lowest force. Using the hill analogy, rather than rolling downhill, I'm going to the place with the lowest elevation... even if I have to travel uphill for a while before I can go downhill to get there. I encourage you to play with this on your own, it certainly helped my bot's performance. :-)
I may add more to this page if I discover that anyone is interested.