⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lxw_01.java

📁 robocode机器人
💻 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 + -