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

📄 lxw_02.java

📁 robocode机器人
💻 JAVA
字号:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
//普通坦克类:ScruchiPu002 - 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 class LXW_02 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(teamFlag == 1)
      		return;

		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();//修改坦克当前的能量
		}

	
		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++;
	}


	//将结果保存到文件中
	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; }	
	
	//接受指挥官坦克发送来的信息
	public void onMessageReceived(MessageEvent e)
	{
		//接收到目标坦克的坐标// Fire at a point
		if (e.getMessage() instanceof Point)
		{
			Point p = (Point)e.getMessage();
			//计算目标坦克的相对于本坦克的角度
			double dx = p.getX() - this.getX();
			double dy = p.getY() - this.getY();
			
			double theta = Math.toDegrees(Math.atan2(dx,dy));
			teamFlag = 1;
			//将雷达和炮管转向目标坦克方向
			turnRadarRight(normalRelativeAngle(theta - getRadarHeading()));
		    turnGunRight(normalRelativeAngle(theta - getGunHeading()));
			teamFlag = 0;
		}
	} 
}															

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -