?? wangdong.java
字號(hào):
package wd;
import robocode.*;
import java.awt.Color;
import java.awt.geom.Point2D;
public class Wangdong extends AdvancedRobot
{
static double nextMove; //the time before our next move
final static int storedInfo = 800; //how many frames we store in our pattern analyzer.
//not too large to get fresh details on target quickly,
//but large enough to remember the opponents behavior a little while
static double[][] pattern = new double[storedInfo][4]; //all stored info about our enemy
public void run() {
setAdjustRadarForGunTurn(true);
setAdjustGunForRobotTurn(true);
Color c = Color.darkGray.brighter();
setColors( c , c , new Color( 162 , 244 , 89 ) ); //new and better ninja colors:-p
while( true ) {
turnRadarRightRadians( Double.POSITIVE_INFINITY ); //turn radar to find a target
}
}
public void onScannedRobot(ScannedRobotEvent e) {
int time = (int) getTime() % storedInfo; // store time to save codesize
double targetBearing = getHeadingRadians() + e.getBearingRadians();
double ourX = getX(); //store own coordinates
double ourY = getY(); //-"-
double firePower = Math.min( 3 , 30 * getEnergy() / e.getDistance() ); //powersaving when far from target and low on energy
//movement code
/**
* 在場(chǎng)地中隨機(jī)尋找一點(diǎn)作為運(yùn)動(dòng)的目標(biāo)點(diǎn)(這一點(diǎn)要滿足離墻不能太近,而且如果要過去這一點(diǎn),我需要的用方向要滿足不能和當(dāng)前正在運(yùn)動(dòng)的方向相差太少
* 也就是要>minimumAngleDifference,也不能于相對(duì)敵人的方向相差太少,要>2 * minimumAngleDifference,意思就是說,方向要變多些,不能看起來(lái)
* 跟沒改變差不多,也不能向著敵人沖過去。minimumAngleDifference是一個(gè)自己設(shè)定的數(shù),因該是經(jīng)過測(cè)試和塞選出來(lái)的,為什么要跟a有關(guān),也就是為什么
* 循環(huán)到后面minimumAngleDifference越小?因?yàn)槿f(wàn)一前面找不到滿足條件的角度呢?那么后面,限制就因該小一些)
* nextMove = e.getDistance() / ( 29 - 3 * firePower );if ( nextMove-- <= 0 )的意思是在敵人第二發(fā)子彈快要發(fā)出的時(shí)候改變運(yùn)動(dòng)目標(biāo)點(diǎn)
*/
if ( nextMove-- <= 0 ) { //it's time to make our next move
for ( double a = 0 ; a < 500 ; a++ ) {
double testX = Math.random() * getBattleFieldWidth(); //make random test points
double testY = Math.random() * getBattleFieldHeight(); //-"-
double distToWall = Math.min( testX , getBattleFieldWidth() - testX ) * Math.min( testY , getBattleFieldHeight() - testY ); //check the product of the distance to the shortest walls
if ( distToWall > 7600 ) { //make sure the point is within the current wall tolerance (which is always 7600 in this bot which is good for a 800 x 600 battlefield)
//use point if angle to point is a certain amount from angle to target
double ourAngleToPoint = getAngle( ourX , ourY , testX , testY ); //angle to the testpoint
double minimumAngleDifference = ( ( 500 - a ) / 500 ) * Math.PI / 6; //minimumAngleDifference is the smallest angle difference to accept
if ( Math.abs( angle_180( targetBearing ) - ourAngleToPoint ) > 2 * minimumAngleDifference
&& Math.abs( angle_180( getHeadingRadians() ) - ourAngleToPoint ) > minimumAngleDifference ) {
double turnAngle = angle_180( getAngle( ourX , ourY , testX , testY ) - getHeadingRadians() ); //calculate angle to turn to next point
//decide which direction to go to reach our point as soon as possible
double moveDirection = 1; //use front if next check is false
if ( Math.abs( turnAngle ) > Math.PI / 2 ) { //if angle is greater than PI / 2 in either directions
moveDirection = - 1; //switch direction
turnAngle += Math.acos( moveDirection ); //and change turnangle acordingly
}
setTurnRightRadians( angle_180( turnAngle ) ); //make turn
setAhead( moveDirection * Point2D.Double.distance( ourX , ourY , testX , testY ) ); //move towards point
break;
}
}
}
//make nextMove a little before a bullet will reach you next time
nextMove = e.getDistance() / ( 29 - 3 * firePower ); //use own firePower here to save space. The enemy is likely to use about the same power as us since firepower often is based on own energy
}
setMaxVelocity( getTurnRemaining() > 45 ? 0.001 : 8 ); //adjust velocity when turning to make sharper turns
//end of movement
//pattern analyzer
/**
* 射擊策略主要思路是用一個(gè)800長(zhǎng)度的數(shù)組紀(jì)錄一個(gè)直線提前量射擊策略的PredictionAngle
* 每個(gè)記錄點(diǎn)都記錄從自己子彈到敵人這段時(shí)間(子彈假定能量為3,敵人假定為不動(dòng),雖然這樣不精確,但是也只能這樣,你知道敵人怎樣動(dòng)?如果知道你還計(jì)算啥?)
* 里PredictionAngle的累加
* 需要射擊時(shí),尋找一個(gè)歷史中(所有以前的記錄節(jié)點(diǎn)中)完成了累加的,而且與目前的PredictionAngle最相似的記錄節(jié)點(diǎn)(也就是以PredictionAngle最相似
* 就視為運(yùn)動(dòng)方式最相似),那么,敵人以后的運(yùn)動(dòng)因該和歷史中的那段運(yùn)動(dòng)情況很相似(也就是歷史重現(xiàn))。
* 找到了歷史要重現(xiàn)的地方了,那么用那段歷史中的平均PredictionAngle作為射擊Angle射擊
*
* 這種射擊方式就是尋找歷史中和你現(xiàn)在運(yùn)動(dòng)相似的情況,所以如果你的運(yùn)動(dòng)有規(guī)律的話,他能很好的找出你下一步會(huì)怎樣走,那么,你被命中的幾率就很大
* 這也正是作者的運(yùn)動(dòng)采用隨機(jī)運(yùn)動(dòng)的原因。
*/
int match = 0;
pattern[ time ][0] = e.getDistance() / ( 20 - 3 * firePower ); //store time before we will use this angle in our analyzer
pattern[ time ][1] = e.getVelocity() * Math.sin( e.getHeadingRadians() - targetBearing ); //store linear prediction angle
/**
* pattern[ time ][1] = e.getVelocity() * Math.sin( e.getHeadingRadians() - targetBearing );
* 正弦定理e.getVelocity()/Math.sin(predictionAngle)==myBulletVelocity/Math.sin(e.getHeadingRadians() - targetBearing);
* 所以pattern[ time ][1]==myBulletVelocity*Math.sin(predictionAngle);
* 也就是說pattern[ time ][1]記錄的是直線提前量的射擊角度與自己子彈速度的乘積
*/
pattern[ time ][2] = pattern[ time ][3] = 0; //reset values used to store our target's actual move
for ( int a = 0; a < storedInfo; a++ ) {
//每個(gè)記錄點(diǎn)pattern[a]中,如果當(dāng)前時(shí)間是在我的子彈到達(dá)敵人之前則累加計(jì)算到的myBulletVelocity*Math.sin(predictionAngle)值;
//同時(shí)記錄累加了多少次(pattern[ a ][3]的值)
if ( pattern[ a ][0] > 0 ) { //if angle is under evaluation
pattern[ a ][2] += e.getVelocity() * Math.sin( e.getHeadingRadians() - targetBearing ); //add angle to prediction
pattern[ a ][0]--; //decrease time before use
pattern[ a ][3]++; //increase counter for number of angles used
}
}
//在歷史中(所有記錄中)尋找一個(gè)和目前的myBulletVelocity*Math.sin(predictionAngle)值最相近的記錄點(diǎn)(這個(gè)紀(jì)錄點(diǎn)必須是累加完畢的點(diǎn)pattern[a][0]<0)
//把這個(gè)紀(jì)錄點(diǎn)的數(shù)組下表記錄到match中
for ( int a = 0; a < storedInfo; a++ ) { //cycle all our stored values
double testAngle = pattern[ time ][1]; //store the angle this turn to save codesize
if ( pattern[ a ][0] < 0 && Math.abs( testAngle - pattern[ a ][1] ) < Math.abs( testAngle - pattern[ match ][1] ) ) { //if this value is better than our current match
match = a; //change match to this value
}
}
//計(jì)算需要射擊的角度linearPredictionAngle
//這角度是在我子彈到達(dá)敵人這段時(shí)間里的predictionAngle的平均值
double linearPredictionAngle = pattern[ match ][2] / ( pattern[ match ][3] * ( 20 - 3 * firePower ) ); //prediction angle with our best match
//end of pattern analyzer
linearPredictionAngle = linearPredictionAngle >= 0 ? linearPredictionAngle : 0;
setTurnGunRightRadians( angle_180( targetBearing - getGunHeadingRadians() + linearPredictionAngle ) ); //turn gun to target with an offset as predicted in our analyzer
setTurnRadarRightRadians( Math.tan( targetBearing - getRadarHeadingRadians() ) * 3 ); //turn radar to target enemy
if ( getEnergy() > Math.min( e.getEnergy() + firePower + 0.1 , 3.1 ) ) { //make sure we won't kill ourself when shooting, also let the enemy run out of energy before you
setFire( firePower ); //fire
}
scan(); //scan to see if our target is still here
}
//helpers
/**
* 返回角度ang的-PI到PI相對(duì)應(yīng)的值(弧度表示)
*/
public double angle_180( double ang ) { //get the relative angle where -180 < angle < 180
return Math.atan2( Math.sin( ang ), Math.cos( ang ) );
}
/**
* 返回點(diǎn)(x2,y2)到(x1,y1)連線的絕對(duì)角度(戰(zhàn)場(chǎng)場(chǎng)地參照系)
*/
double getAngle( double x1 , double y1 , double x2 , double y2 ) { //get the angle between two points
return Math.atan2( x2 - x1 , y2 - y1 );
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -