Robocode历史概况:
1995年,Mat Nelson进入IBM,开始接触JAVA。2000年,随着JAVA语言成熟,Mat Nelson这个狂热的玩家看到了创建这个他一直想玩的游戏的机会,着手开始创建Robocode。
2001年,IBM以 alphaWorks 下载的形式发布。
2008年1月,Robocode1.5.2 最新版本发布。
安装要求
Java 5.0 or newer(Windows和Unix/Linux平台)。
注意部分linux操作系统下,由于JSDK的内部BUG,可能无法正确安装运行。
平台参数
方向 - 整个战场是以屏幕正上角为0度,按顺时针排列,90,180,270...。
位置 - 整个战场的坐标是以屏幕左下角为原点,高为Y坐标,宽为X坐标。
距离 - 游戏中规定的距离是以像素(Pixels)点为单位,如果你把屏幕缩小了,那就是以缩小后的像素点为单位,反之就是放大后的像素点为单位。
时间 - 游戏中规定的时间是以帧(frame)或滴答(ticks)(有点像时钟滴答),或时间周期(turns),或单独的时间片(simply timeslices)为单位。 回合 比赛回合是比赛中由用户自己设置的比赛次数,默认值为10。
帧速 - 默认为30。
扫描 - 默认为无。
声音 - 默认为无。
游戏规则:
生命规则:
相撞损失:撞到墙时,生命点损伤度=Math.abs (velocity) * 0.5 -1。撞到另一个坦克时,移动停止,生命点损失6点,扣除积分1.2分。
击中损失:当子弹能量为1时,我们生命点损失=4 * power,如果子弹能量大于1,那么我们的生命损失+= 2 * (power-1)。
发射损失:如果我们的子弹打中别的坦克,我们可以从子弹那窃取到3*power的能量。
炮弹规则:
子弹能量:子弹能量是通过函数getPower()得到的。它大于等于0.1,小于等于 3。
子弹速度:每一颗子弹有着自身的速度,这在处理敌人向你开炮前的移动策略可是很有帮助的。子弹的速度也和它的能量有关: speed = 20 - 3 * power。由于能量范围在0.1到3之间我们可求得子弹的速度范围:11 <= bullet speed <= 19.7。
炮管规则:
旋转速率:炮管在每一个时间周期内旋转速率=20 度/帧(frame)
炮管热量:当我们开火时,炮管产生的热量由子弹开火时的能量决定。即:热量=1+(firepower/5), 利用函数 getGunHeat()可以得到炮管当时的热量,只有当getGunHeat恒等于0时,我们才能再次发射子弹。
冷却度:有热度当然就有冷却度,不冷却我们的炮管会永远不会开火的。系统设定的默认冷却速度是0.1/tick(时间周期),我们可通过函数 getGunCoolingRate()得到这个参数值。
雷达规则:
旋转速度:雷达以每时间周期45度的速度旋转。也即45 degrees/frame.
扫描面积: 雷达扫描是呈扇形的,它的开始位置到终止位置的长度大约为1200。只要我们放大屏幕可以通过眼睛估算出这个面积。
扫描排列:扫描到的数据有墙,目标,子弹等等。这些是按扫描距离来排列,从离雷达最近的物体开始到最后扫描到的物体。
运行规则:
前进速度:坦克最大的速度(Velocity)为8,函数getVelocity()返回了坦克当前的速度。
加/减速度:加速度为 1 像素(pixel)/帧frame ,减速度为 2 pixel/frame。
参考公式: 设s为距离,Vt为终速度,Vo为初速度,t为时间,a为加速度:
位移公式 s=Vo*t+a*t*t/2
速度公式 Vt =Vo +a*t
平均速度公式 v=(Vt + Vo)/2=s/t
加速度公式 a=(Vt - Vo)/t
(这些公式高一大家都学过吧?)
旋转规则:
旋转速度:机器人的旋转速度和当前的速度有关即旋转速度=10 - 0.75 * getVelocity()。
相互作用参数:雷达安装在炮上,炮安装在机器人上,它们会相互影响。如果我们向左转动炮管,而使雷达向右转动,那么雷达只会向右转动(45-20) =25度;如果两者都向右转动,雷达将向右转(45+20)=65度。同样的道理炮和机器人也是方向同相加,方向反相减。
积分规则:
Robot Name - 机器人的名字;
Total Scroe - 为这次比赛你的总共得分;
Survival - 是你存活率的得分;
Last Survivor Bonus:你是赢的次数相对对手的分红得分;
Bullet Dmg:是你的子弹损失得分也即发射的子弹数的得分;
Bonus:是子弹数的分红得分;
Ram Dmg *2是你的撞击得分;
Bonus:是你撞击得分分红;
最后两项Survival 1sts,是你赢的次数,不算做分数。
所有分数加起来就是你的总分。记住在联赛并不是总分越高越好,它是算综合平均分的。其中撞击分和子弹损失分就要越少越好。你如果观察两大高手比赛的记分牌,你会发现他们的Ram Dmg 和Ram Dmg中的Bonus一般都为0。
部分重要的接口函数介绍(全部函数参考安装文件夹下的Javadoc文件夹):
坦克属性:
double getBattleFieldHeight() 战场高度
double getBattleFieldWidth() 战场宽度
double getHeight() 坦克高度
String getName() 坦克名称
double getWidth() 坦克宽度
double getGunHeading() 炮管角度
double getHeading() 坦克角度
double getRadarHeading() 雷达角度
double getX() 坐标X
double getY() 坐标Y
double getGunHeat() 炮管热量
double getEnergy() 能量数值
double getGunCoolingRate() 炮管冷却比例
double getVelocity() 坦克速度
运行控制:
void ahead(double distance) 前进
void back(double distance) 后退
void doNothing() 空
void fire(double power) 开火
void setAdjustGunForRobotTurn(boolean independent) 炮\车同向
void setAdjustRadarForGunTurn(boolean independent) 炮\雷达同向
void setAdjustRadarForRobotTurn(boolean independent) 雷达\车同向
void turnRadarLeft(double degrees) 雷达左转角度
void turnRadarRight(double degrees) 雷达右转角度
void turnGunLeft(double degrees) 炮左转角度
void turnGunRight(double degrees) 炮右转角度
void turnLeft(double degrees) 车左转角度
void turnRight(double degrees) 车右转角度
战斗事件:
void onBulletHit(BulletHitEvent event) 子弹击中坦克
void onBulletHitBullet(BulletHitBulletEvent event) 子弹击中子弹
void onBulletMissed(BulletMissedEvent event) 子弹没有击中目标
void onDeath(DeathEvent event) 坦克被消灭的时候
void onHitByBullet(HitByBulletEvent event) 被子弹击中
void onHitRobot(HitRobotEvent event) 被坦克撞击
void onHitWall(HitWallEvent event) 撞墙
void onRobotDeath(RobotDeathEvent event) 坦克死亡
void onScannedRobot(ScannedRobotEvent event) 扫描到坦克
void onWin(WinEvent event) 胜利
void run() 运行 voidscan() 扫描
ScannedRobotEvent –雷达扫描:
double getBearing() 获得相对自己坦克方向的角度
double getBearingRadians() 获得相对自己坦克方向的弧度
double getDistance() 获得距离
double getEnergy() 获得运行能量
double getHeading() 获得方向角度
double getHeadingRadians() 获得方向弧度
String getName() 获得坦克名称
double getVelocity() 获得运行速度
构造坦克的方式:
Robot (常用) –支持较为全面的简单控制逻辑;
TeamRobot –支持团队作战模式;
AdvancedRobot –支持自定义事件.
一个比较简单的坦克框架:
(由自动生成的源码改写,可以在RobocodeIDE环境下运行)
package myrobotpackage;
import java.awt.Color;
import robocode.*;
/**
* AHeader - a robot by (your name here)
*/
public class AHeader extends Robot
{
/**
* run: AHeader's default behavior
*/
public void run() {
// After trying out your robot, try uncommenting the import at the top, and the next line:
SetSkin();//换身衣服
turnLeft(getHeading());
while(true) {
// Replace the next lines with any behavior you would like
ahead(100);
turnGunRight(360);
scan();
}
}
/**
* onScannedRobot: What to do when you see another robot,扫描事件
*/
public void onScannedRobot(ScannedRobotEvent e)
{
SmartFire(e.getDistance());
}
/**
* onHitWall: Handle collision with wall.撞墙事件
*/
public void onHitWall(HitWallEvent e)
{
//
turnRight(180);
ahead(2000);
}
/**
* onHitRobot: Aim at it. Fire!撞车事件
*/
public void onHitRobot(HitRobotEvent e)
{
double turnGunAmt = normalRelativeAngle(e.getBearing() + getHeading() - getGunHeading());
turnGunRight(turnGunAmt);
fire(1);
}
/**
* onHitByBullet: What to do when you're hit by a bullet,被炮弹集中事件
*/
public void onHitByBullet(HitByBulletEvent e)
{
turnLeft(90 - e.getBearing());
}
///自定义函数//////////////////////////////////////////////////////////////////////////////////////////
/* smartFire: Custom fire method that determines firepower based on distance */
public void SmartFire(double robotDistance) {
if (robotDistance > 200 || getEnergy() < 15) {
fire(1);
} else if (robotDistance > 50) {
fire(2);
} else {
fire(3);
}
}
/* Set Robot Colors */
public void SetSkin()
{
setBodyColor(new Color(0, 200, 0));
setGunColor(Color.black);
setRadarColor(Color.yellow);
setBulletColor(Color.red);
setScanColor(Color.yellow);
}
/**
* normalRelativeAngle: Returns angle such that -180 < angle <= 180
*/
public double normalRelativeAngle(double angle)
{
if (angle > -180 && angle <= 180) {
return angle;
}
double fixedAngle = angle;
while (fixedAngle <= -180) {
fixedAngle += 360;
}
while (fixedAngle > 180) {
fixedAngle -= 360;
}
return fixedAngle;
}
}
--本文源出处:西安海码教育基地,西安程序员俱乐部,有修改
张庆(网眼)http://www.why100000.com 2008-1-21