package exe; import robocode.*; import baseRobot.*; /** * キャノンクラス * * @author Fumi Iseki * @version 1.0 */ public class Cannon { private final int traceCannon = 0; // 砲の追跡モード private final int autoCannon = 1; private final int randomCannon = 2; private final int traceFire = 0; // 撃つ時の砲種選択 private final int randomFire = 1; private final int acceleMover = 0; // 敵の動きのモード private final int circleMover = 1; //private final int randomMover = 2; private final double crtHitRate = 0.2; // これ以下の命中率の場合は砲の角度補正を変える. private ExtRobot myRobo; private GeneData geneData; private double bulletMinPower = 0.1; private double bulletMaxPower = 3.0; private int setModeCnt; protected int cannonMode; // 追跡モード protected int fireMode; // 砲撃モード protected int enemyMoveMode; // 敵の運動モード protected int fireCrct = 0; // 砲の角度補正値の初期値 protected Enemy targetEnemy; protected String targetName; /** * コンストラクタ */ public Cannon(ExtRobot robo, GeneData data) { myRobo = robo; geneData = data; setModeCnt = 0; } /** * 砲種の選択と砲撃 */ public void fireCannon() { double kd = RoboTool.getRelAngle(targetEnemy.getAngle(), myRobo.getGunHeading()); if (myRobo.getEnergy()>2 || myRobo.getEnemyEnergy()==0.) { setBulletPower(); if (fireMode==traceFire) { if (targetEnemy.isConstAccele(3)) { // 等加速度運動 enemyMoveMode = acceleMover; // 敵の運動モードは mightCannon()で使用 mightyCannon(kd); } else if (targetEnemy.isCircle(1)) { // 円運動 enemyMoveMode = circleMover; mightyCannon(kd); } else { // その他の動き gaussCannon(kd, 5); } } else { //if (fireMode==randomFire) { gaussCannon(kd, 5); } } else myRobo.turnGunRight(kd); } /** * ガウス砲 */ public void gaussCannon(double kd, int n) { Vector vt = targetEnemy.timeData.acceleMover(n); vt.x += myRobo.rand.nextGaussian()*fireCrct; vt.y += myRobo.rand.nextGaussian()*fireCrct; if (!(vt.x<0 || vt.y<0 || vt.x>myRobo.getXMax() || vt.y>myRobo.getYMax())) { Vector vr = myRobo.getRoboTool().getRelPolar(vt.x, vt.y); double th = RoboTool.getRelAngle(vr.y, myRobo.getGunHeading()); if (Math.abs(th-kd)<=myRobo.turnRadarAngle*2) { attackEnemy(th, bulletMaxPower); } else myRobo.setTurnGunRight(kd); } else myRobo.setTurnGunRight(kd); } /** * マイティ砲 */ public void mightyCannon(double kd) { Vector vt = null, vr; double bp = 0; double th = kd; boolean findFuture = false; int dt = (int)(myRobo.getEnemyDistance()/20); for (int t=30; t>=dt; t--) { // 標的合わせ if (enemyMoveMode==acceleMover) { vt = targetEnemy.acceleMover(t); } else if (enemyMoveMode==circleMover) { vt = targetEnemy.circleMover(t); } if (vt.x<0 || vt.y<0 || vt.x>myRobo.getXMax() || vt.y>myRobo.getYMax()) continue; double dx = vt.x - targetEnemy.timeData.pX.getData(0); double dy = vt.y - targetEnemy.timeData.pY.getData(0); if (dx*dx+dy*dy>64*t*t) continue; // 移動不能な場所を予測してしまった vr = myRobo.getRoboTool().getRelPolar(vt.x, vt.y); th = RoboTool.getRelAngle(vr.y, myRobo.getGunHeading()); if (Math.abs(th-kd)<=myRobo.turnRadarAngle*1.5) { double bv = vr.x*45/(t*45 - th); if (bv>0) bp = (20 - bv)/3.0; else bp = 0; if (bp>=bulletMinPower && bp<=bulletMaxPower) { findFuture = true; break; } } } if (findFuture) attackEnemy(th, bp); else myRobo.setTurnGunRight(kd); } /** * 砲撃!!!    あたれ! 落ちろ!!! */ public void attackEnemy(double kd, double p) { myRobo.turnGunRight(kd); myRobo.fire(p); myRobo.bltNum++; } /** * 砲弾のエネルギーの設定範囲を指定. */ public void setBulletPower() { bulletMaxPower = myRobo.getEnergy()/10; double dd = myRobo.getEnemyDistance(); if (dd<=100) bulletMinPower = 1.0; else if (dd<=200) bulletMinPower = 0.8; else if (dd<=300) bulletMinPower = 0.5; else if (dd<=400) bulletMinPower = 0.2; else bulletMinPower = 0.1; bulletMaxPower = Math.min(bulletMaxPower, 3.0); bulletMinPower = Math.max(bulletMinPower, 0.1); } /** * 砲撃モードの設定 (悩み所) */ public void setMode(int en) { if (en==1 && setModeCnt==0) { // 1対1用 if (myRobo.getNumRounds()>=10) cannonMode = GeneData.getCannonMode(); else cannonMode = autoCannon; /* if (myRobo.getNumRounds()>=10) { int n = myRobo.getRoundNum()%10; if (n==0) cannonMode = traceCannon; else if (n==1) cannonMode = autoCannon; else if (n==2) cannonMode = randomCannon; else { int m = GeneData.hitRate.getMaxDataNum(); cannonMode = (int)GeneData.canMode.getData(m); fireCrct = (int)GeneData.firCrct.getData(m); } } else cannonMode = autoCannon; */ setModeCnt++; } else if (en==1 && myRobo.enemyMaxNum>1) { cannonMode = autoCannon; } else if (en>1) { // 集団戦用 //cannonMode = randomCannon; cannonMode = traceCannon; //cannonMode = autoCannon; } if (cannonMode==randomCannon) fireMode = randomFire; else fireMode = traceFire; //System.out.println("Cannon Mode = "+cannonMode+" "+fireMode+" "+fireCrct); } /** * 標的を決める. */ public void setTargetEnemy(int en) { int n = geneData.enemyNowDist.getMinDataNum(); targetName = geneData.enemyNowName.getID(n); targetEnemy = geneData.getEnemy(targetName); geneData.setTargetEnemy(targetEnemy); //System.out.println("Target = "+targetName); } /** * 砲撃パラメータの補正 */ public void correctCannonParameter(double rate) { if (rate<=crtHitRate) { if (cannonMode==autoCannon) { fireMode = randomFire; // オート追撃モードでの砲撃モードの変更 } else if (fireMode==randomFire) { fireCrct += 2; if (fireCrct>20) fireCrct = 0; } } } /** * ターゲットへ砲を向けるように設定 */ public void setTurnTarget() { double kd = RoboTool.getRelAngle(targetEnemy.getAngle(), myRobo.getGunHeading()); myRobo.setTurnGunRight(kd); } /** * ターゲットへ砲を向ける */ public void turnTarget() { double kd = RoboTool.getRelAngle(targetEnemy.getAngle(), myRobo.getGunHeading()); myRobo.turnGunRight(kd); } /** * ターゲットへのアングルを得る */ public double getTargetAngle() { return targetEnemy.getAngle(); } }