📄 lxw_01.java
字号:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 指挥官类:ScruchiPu003 - by LeiYan, XiaoBin,WangChengSong
// Uses external NeuralNetwork library - NRJLIB by Daniele Denaro
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
package apv;//申明java包apv
//引入java公共包
import robocode.*;
import java.awt.geom.Point2D;
import java.awt.geom.Line2D;
import java.awt.Color;
import java.io.*;
//引入神经网络公共包
import apv.nrlibj.NNet;
//建立public类 ScruchiPu003
public class LXW_01 extends TeamRobot {
//设定神经网络算法所需要的类变量和实例变量
static final int embed = 40; //30
static final int delay = 1; //2
static final double VIN_SF = 2; //Input Vel. Scale factor
static final double HIN_SF = 1; //Input Hed. Scale factor
static final double VOUT_SF = 20; //Output Vel. Scale factor //12
static final double HOUT_SF = 1; //Output Hed. Scale factor
static String NNdescr[] = // 初始化表结构
{
//定义各层的层数、节点以及类名称
"layer=0 tnode=80 nname=NodeLin",
"layer=1 tnode=10 nname=NodeSigm",
"layer=2 tnode=5 nname=NodeSigm",
"layer=3 tnode=2 nname=NodeSigm",
//连接第一层和隐藏层
"linktype=all fromlayer=0 tolayer=1",
//连接隐藏层的第一层和第二层
"linktype=all fromlayer=1 tolayer=2",
//连接隐藏层和最后一层
"linktype=all fromlayer=2 tolayer=3"};
static double[] ev = new double[100000];
static double[] eh = new double[100000];
static Line2D[] ps = new Line2D[100000];
static int n,m;
static String botname;
static double predBearing;
static double power;
static double lastHeading;
static double eGetDistance = 1000;
static double targetBearing;
static NNet networkL = null;
static NNet networkC = null;
//用于坦克躲避子弹和确定运动轨迹的实例变量
double previousEnergy = 100;//坦克锁定目标的最近一次被雷达扫描到时的能量
double preTime, waitTime;//坦克锁定目标的最近一次被雷达扫描到时的时间和等待时间
int movementDirection = 1;//确定坦克的运动方向(movementDirection = 1:坦克向前运动 ; movementDirection = -1:坦克向后运动)
int gunDirection = 1;//
int direction = 1;
double targetbearing = 0;//目标坦克的相对角度(单位:弧度)
double changeInEnergy = 0;//坦克锁定目标当前一次和最近一次扫描到时的能量改变量
int flag = 1;//flag = 1:锁定的目标没有向本坦克发炮; flag = 0:锁定的目标向本坦克发炮
int hitWall = 0;//设置坦克撞墙的标志
String targetName;//雷达扫描到的目标坦克的名字
int teamFlag = 0;//团队是否选中目标坦克作为攻击对象(teamFlag = 0:已经选中目标坦克; teamFlag = 1:团队没有选中目标坦克)
public void run() {
double nextMove, lastMove;
double bestX, bestY, bestA;
setAdjustRadarForGunTurn(true);//炮转动时,雷达会保持原来的方向
setAdjustGunForRobotTurn(true);//坦克车转动时,炮保持原来的方向
// After trying out your robot, try uncommenting the import at the top,
// and the next line:
setColors(Color.red,Color.red,Color.red);//将坦克的车身,炮管,雷达均设置为红色
nextMove = bestA = Math.PI;
lastMove = bestX = bestY = 2.0;
power = 3;
predBearing = 0;
m = Math.max(n-1,0);
do {
//获取当前坦克的横纵坐标
double x = getX();
double y = getY();
//坦克的躲避子弹的运动函数
doMovement();
//RADAR
if (getRadarTurnRemainingRadians() == 0)
setTurnRadarRightRadians(Double.POSITIVE_INFINITY);
execute();
} while (true);
}
//坦克的躲避子弹的运动函数
public void doMovement()
{
//目标坦克向本坦克发炮,并且发炮至现在的时间大于 0.7 * (目标坦克从发跑到到达该坦克所需要的时间)
if (flag==0 && (getTime()-preTime)>0.7*waitTime )
{
flag=1;
//向前或向后随机运动60个像素点
if(Math.random()>0.5)
{
movementDirection=-movementDirection;
}
if(hitWall == 0)
setAhead(60*movementDirection);
}
}
//响应雷达扫描到坦克事件函数
public void onScannedRobot(ScannedRobotEvent e)
{
// 若扫描到的坦克是自己的队友
if (isTeammate(e.getName()))
{
//已目标坦克为圆心当前距离为半径前进或后退100个像素点
setTurnRight(e.getBearing()+90);
setAhead(100*movementDirection);
return;
}
//使坦克的方向和目标与该坦克的连线垂直
setTurnRight(e.getBearing()+90);
if(flag==1)
{
//计算目标坦克的能量的改变量
changeInEnergy = previousEnergy-e.getEnergy();
//若目标坦克的能量改变介于(0,3)之间,则判断为目标坦克向该坦克发炮
if(changeInEnergy>0 && changeInEnergy<=3 )
{
//计算目标坦克从发跑到到达该坦克所需要的时间
waitTime=e.getDistance()/(20-changeInEnergy*3);
preTime=getTime();//获取目标坦克向本坦克发泡的时刻
flag=0;//目标坦克向本坦克发炮
}
// Track the energy level
previousEnergy = e.getEnergy();//修改坦克当前的能量
}
targetName = e.getName();//获取目标坦克的名字
botname = getBotClass(e.getName());
targetbearing = e.getBearingRadians();//获取目标坦克的相对弧度
if (networkL == null || networkC == null) {
try { networkL = new NNet(botname+".L",false,this); }
catch (Exception ex)
{ networkL = new NNet(NNdescr); }
}
//RADAR
setTurnRadarRightRadians(normalRelativeAngle((targetBearing=e.getBearingRadians() + getHeadingRadians())-getRadarHeadingRadians()) * 1.9);
//ENEMY DATA (1)
eGetDistance = e.getDistance();//获取目标的距离
//目标坦克与本坦克所构成的直线
ps[n] = new Line2D.Double(getX(),getY(),getX()+eGetDistance*Math.sin(targetBearing),getY()+eGetDistance*Math.cos(targetBearing));
ev[n] = e.getVelocity();//获取目标的速度
eh[n] = normalRelativeAngle(e.getHeadingRadians()-lastHeading);//目标坦克的局对弧度的改变量
lastHeading = e.getHeadingRadians();
//CALCULATE BEARINGS & TRAIN THE NETWORK
if (getTime()>embed*delay && e.getEnergy()>0)
learn(networkL,n);
//AIMING & FIRING
if (e.getEnergy()>0 && n > 0) {
predBearing = normalRelativeAngle(aim(networkL)-targetBearing);
}
else predBearing = 0;
double gunturn = normalRelativeAngle(predBearing+targetBearing-getGunHeadingRadians());
setTurnGunRightRadians(gunturn);
if( getEnergy()>power+0.1 && getGunHeat()==0 && Math.abs(gunturn)<0.06) { setFire(power); }
if ( getEnergy()<= 3)
power = 0.2;
n++;
//如果没有将目标坐标发送给队友,则指挥官将目标坦克的坐标发送给其他的所有队友
if(teamFlag == 0)
{
try {
// Send enemy position to teammates
broadcastMessage(new Point(getX()+eGetDistance*Math.sin(targetBearing),getY()+eGetDistance*Math.cos(targetBearing)));
} catch (IOException ex) {
System.out.println("Unable to send order: " + ex);
}
teamFlag = 1;
}
}
//将结果保存到文件中
public void onWin(WinEvent event) { onDeath(null); }
public void onDeath(DeathEvent e) { if (getRoundNum()==getNumRounds()-1) { networkL.saveNNet(botname+".L",this); } }
//响应本坦克撞墙的事件处理
public void onHitWall(HitWallEvent event)
{
hitWall=1;
//坦克的反向运动120个像素点
movementDirection=-movementDirection;
setAhead(120*movementDirection);
hitWall=0;
}
//响应本坦克中弹的时间处理
public void onHitByBullet(HitByBulletEvent event)
{
//坦克的反向运动60个像素点
movementDirection=-movementDirection;
setAhead(60*movementDirection);
}
//神经网络学习过程
public void learn(NNet network, int n) {
float[] input = buildInput(n-1);
float[] output = buildOutput(n-1);
if (input != null && output !=null) { network.ebplearnNNet(input,output); }
}
//瞄准系统设置
public double aim(NNet network) {
double x = getX() + Math.sin(targetBearing)*eGetDistance;
double y = getY() + Math.cos(targetBearing)*eGetDistance;
double ah = lastHeading;
int time = 0;
int match = n;
float[] output = new float[2];
double vel = 0;
//在子弹到达敌人未来位置之前调整攻击角度
while ((time * (20.0 - 3.0 * power)) < Point2D.distance(getX(),getY(),x,y)) {
float[] input = buildInput(n+time);
//利用前馈函数设置输入、输出值
if (input != null)
network.frwNNet(input,output);
else
{
output[0] = 0;
output[1] = 0;
}
vel = Math.max(-8,Math.min(8,(output[0]-0.5)*VOUT_SF));
if (vel - ev[n+time] > 2)
vel = ev[n+time] + 2;
if (ev[n+time] - vel > 2)
vel = ev[n+time] - 2;
x += Math.sin(ah) * vel; //调整x值
x = Math.max(18,Math.min(getBattleFieldWidth()-18,x));
y += Math.cos(ah) * vel; //调整y值
y = Math.max(18,Math.min(getBattleFieldHeight()-18,y));
ev[n+time+1] = vel;
double hed = Math.max(-(0.17453293-0.01308997*Math.abs(vel)),Math.min(0.17453293-0.01308997*Math.abs(vel),(output[1]-0.5)*HOUT_SF));
ah += hed;
eh[n+time+1] = hed;
time++;
}
//返回调整后的攻击角度
return Math.atan2(x-getX(),y-getY());
}
//构造输出N+1的输入N(input N for output N+1)
public float[] buildInput(int n)
{
if (n<embed*delay) return null;
else {
float[] input = new float[embed*2];
for (int i=0; i<embed; i++) {
input[2*i] = (float) (ev[n-i*delay]/VIN_SF);
input[2*i+1] = (float) (eh[n-i*delay]/HIN_SF);
}
return input;
}
}
//构造输入N+1的输出N
public float[] buildOutput(int n)
{
if (n<0)
return null;
else
{
float[] output = new float[2];
output[0] = (float) ((ev[n+1]/VOUT_SF) + 0.5);
output[1] = (float) ((eh[n+1]/HOUT_SF)+0.5);
return output;
}
}
//将相对角度转化为弧度(-PI,PI)
private double normalRelativeAngle(double angle)
{
return ((angle + 5*Math.PI) % (2*Math.PI)) - Math.PI;
}
//将弧度(-PI,PI)转化为(0,PI/2)
private double scoring(double a1)
{
return Math.abs(Math.abs(normalRelativeAngle(a1))-Math.PI/2);
}
private double newpos(double len)
{
return 100 + Math.random()*(len-200);
}
private String getBotClass(String name)
{
String n = name;
int low = name.indexOf(" ");
if (low >= 0)
n = name.substring(0, low);
return n;
}
//团队所攻击的目标被击毙,设置teamFlag = 0即另外选取攻击目标
public void onRobotDeath(RobotDeathEvent e) {
if (e.getName() == targetName)
teamFlag = 0; //this will effectively make it search for a new target
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -