-1

このメソッドが正確に何をしているのかわかりません。誰かが私にこのトリックを説明してもらえますか?

public void onScannedRobot(ScannedRobotEvent e)
  {
    setTurnRadarLeftRadians(getRadarTurnRemaining());

    setTurnRight(e.getBearing() + 90.0D - dir / 33.0D);
    if (((Guppy.var = var - e.getEnergy()) <= 3) && (var > 0.0D))
    {
      setMaxVelocity(Math.random() * 9.0D + 3);
      setAhead(Guppy.dir = dir * type);
    }
    setTurnGunRightRadians(Math.sin((Guppy.var = e.getBearingRadians() + getHeadingRadians()) - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - var))));
    if (getGunHeat() == 0.0D)
    {
      setFire(2.9D);
      vel = e.getVelocity();
    }
    var = e.getEnergy();
  }
4

2 に答える 2

3

三角法に精通しているが、Robocode には精通していない人への注意事項: Robocode の角度値は、三角法の慣例のようにゼロ中心で反時計回りに増加するのではなく、非負であり、時計回りに増加します。

聖なる牛、それは毛玉です。static変数を割り当ててから同じ式内で使用し、さまざまな目的で変数をランダムに再利用するという面倒なスタイルも同様です。(編集:私は robocode から離れすぎています。難読化されたように見える混乱は、コード サイズを手作業で最適化した結果である可能性があります。) ここから始めて、その厄介な行を 1 つ取り出してみましょう。

setTurnGunRightRadians(Math.sin((Guppy.var = e.getBearingRadians() + getHeadingRadians()) - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - var))));

varが部分式の結果を保持するために使用されているようですe.getBearingRadians() + getHeadingRadians()。あなたのヘディングに対するe.getBearingRadians()ターゲットの方位を返すので、は絶対的なターゲットの方位です。リファクタリング:var

double targetBearing = e.getBearingRadians() + getHeadingRadians();
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - targetBearing))));

うーん、まだ混乱しています。説明されていない変数もありますvelが、コードの残りの部分に基づいて、最後にスキャンされたときのターゲットの速度のようです(そして、1 対 1 の試合のみが行われるという軽率な仮定の下で)。現在の速度と加重平均を組み合わせて、大まかな予測速度を提供するため、おそらくターゲットを導くロジックがここで進行しています。

double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + Math.asin(predictedVelocity / 14.0D * Math.sin(e.getHeadingRadians() - targetBearing))));

ロボコードはコースとヘディングの違いを無視しているように見えるため、最も内側の正弦は、ターゲットの速度のどのコンポーネントがその方位に垂直であるかを示す符号付き係数をMath.sin(e.getHeadingRadians() - targetBearing)与え、したがって発射角度の調整が必要です。

double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
double perpendicularMotionCoefficient = Math.sin(e.getHeadingRadians() - targetBearing);
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + Math.asin(predictedVelocity / 14.0D * perpendicularMotionCoefficient)));

逆正弦表現は、ターゲットの動きの垂直成分を角度調整に戻すことを意図しているようです。アークサインはそのようには機能しないため、この数学のビットは完全に間違っています。区間 [-1, 1] の係数を区間 [-pi/2, pi/2] の角度に戻し、予測された速度を 14 で除算することは、おそらく、引数を逆正弦にその領域内に限定しようとする試みにすぎません。繰り返しますが、ターゲットまでの距離も発射体の速度も計算に入らないため、この調整について私が言える最善のことは、漠然と正しい方向にあるということです.

double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
double perpendicularMotionCoefficient = Math.sin(e.getHeadingRadians() - targetBearing);
double firingAngleAdjustment = Math.asin(predictedVelocity / 14.0D * perpendicularMotionCoefficient);
setTurnGunRightRadians(Math.sin(targetBearing - getGunHeadingRadians() + firingAngleAdjustment));

その最後の正弦は、私にはまったく意味がありません。引数はすでに、銃を動かす必要のあるラジアン単位の角度です:ターゲットの絶対方位から現在の銃の向き (これは、銃がターゲットを正確に指すためにどれだけ回転する必要があるか) を差し引いたものと、ターゲットの動き。そこにある正弦関数を完全に削除します。

double targetBearing = e.getBearingRadians() + getHeadingRadians();
double predictedVelocity = vel * 0.4D + e.getVelocity() * 0.6D;
double perpendicularMotionCoefficient = Math.sin(e.getHeadingRadians() - targetBearing);
double firingAngleAdjustment = Math.asin(predictedVelocity / 14.0D * perpendicularMotionCoefficient);
setTurnGunRightRadians(targetBearing - getGunHeadingRadians() + firingAngleAdjustment);

もちろん、これは銃を半回転 (pi ラジアン) 以上回転するように設定することが、代わりに半回転未満で反対方向に回転させると自動的に理解されるかどうかにも依存します...あなたは多くの無意味なことをすることになるかもしれませんそれ以外の場合は銃を回転させます。

于 2014-05-20T03:34:58.653 に答える
0
    public void onScannedRobot(ScannedRobotEvent e) // for every robots that your robot see {
setTurnRadarLeftRadians(getRadarTurnRemaining()); // Sets the robot's radar to turn left by radians 
setTurnRight(e.getBearing() + 90.0D - dir / 33.0D); //   Sets the robot's body to turn right by degrees, basically you are depending it in your enemy
if (((Guppy.var = var - e.getEnergy()) <= 3) && (var > 0.0D))
{
  setMaxVelocity(Math.random() * 9.0D + 3); //Sets the maximum velocity of the robot measured in pixels/turn if the robot should move slower than Rules.MAX_VELOCITY (8 pixels/turn).
  setAhead(Guppy.dir = dir * type);
}
setTurnGunRightRadians(Math.sin((Guppy.var = e.getBearingRadians() + getHeadingRadians()) - getGunHeadingRadians() + Math.asin((vel * 0.4D + e.getVelocity() * 0.6D) / 14.0D * Math.sin(e.getHeadingRadians() - var))));
if (getGunHeat() == 0.0D)
{
  setFire(2.9D); // how big is the damage of the bullet. The bigger the damage= bigger energy consumed
  vel = e.getVelocity(); //get the enemy velocity
}
var = e.getEnergy(); // get the enemy energy

}

必要に応じて、私のこれらのミニ プロジェクトで遊んでみてください。

                    package sample;
                import robocode.*;
                import java.awt.Color;
                import java.awt.geom.*;
                import java.lang.*;         // for Double and Integer objects
                import java.util.*; // for collection of waves
                import robocode.util.Utils;

                import robocode.RobotDeathEvent;
                import robocode.Rules;
                import robocode.ScannedRobotEvent;
                import robocode.util.Utils;

                /*
            A Robocode that implements the smart targeting(always attack on the nearest opponent) and circles around them
                */

                public class Tutorial extends AdvancedRobot
                {   boolean movingForward;
                    boolean peek; // Don't turn if there's a robot there
                    double moveAmount; // How much to move
                    byte moveDirection= 1;
                    int tooCloseToWall = 0;
                    int wallMargin = 60;

                    static final double GUN_FACTOR = 30;
                    static final double AIM_FACTOR = 25;
                    static final int AIM_START = 10;
                    static final int FIRE_FACTOR = 100;
                    private long    currTime;               
                    static final long RADARTIMEOUT  = 20;
                    static double xForce;
                    static double yForce;
                    static double lastDistance;

                    private boolean radarScan;              
                    private long    lastscan;               

                    public void run(){

                        setAdjustRadarForGunTurn(true);
                        setAdjustGunForRobotTurn(true);

                        // Sets these colors (robot parts): body, gun, radar, bullet, scan_arc
                        setBodyColor(new Color(255, 255, 255));
                        setGunColor(new Color(255, 255, 255));
                        setRadarColor(new Color(255, 255, 255));
                        setBulletColor(new Color(0, 0, 0));
                        setScanColor(new Color(255, 255, 255));

                        while(true) {
                            currTime = getTime();
                            turnRadarRightRadians(Double.POSITIVE_INFINITY);
                            turnRadarLeftRadians(Double.POSITIVE_INFINITY);
                            radarScan = true;
                        }
                    }

                    public void onScannedRobot(ScannedRobotEvent e) {

                        double absoluteBearing = e.getBearingRadians()+ getHeadingRadians();
                        double  distance = e.getDistance();
                        double  bulletPower ;
                        double headingRadians = getHeadingRadians();
                        boolean fired = false;

                        if(getOthers() >= 2){

                            xForce = xForce *.80- Math.sin(absoluteBearing) / distance;
                            yForce = yForce *.80 - Math.cos(absoluteBearing) / distance;

                        setTurnRightRadians(Utils.normalRelativeAngle(
                            Math.atan2(xForce + 1/getX() - 1/(getBattleFieldWidth() - getX()), 
                                       yForce + 1/getY() - 1/(getBattleFieldHeight() - getY()))
                                        - getHeadingRadians()) );
                        setAhead(150- Math.abs(getTurnRemaining()));//speed
                        bulletPower = ( distance > 850 ? 0.1 : (distance > 700 ? 0.49 : (distance > 250 ? 1.9 : 3.0)));
                                bulletPower = Math.min( getEnergy()/5, Math.min( (e.getEnergy()/4) + 0.2, bulletPower));

                        if ((getGunHeat() <= 3.0) && (getGunTurnRemaining() == 0.0) && (bulletPower > 0.0) && (getEnergy() > 9.1)) {
                        // Only fire the gun when it is locked and loaded, do a radarsweep afterwards.
                        bulletPower=3;
                        setFire( bulletPower);
                        fired = true;
                        }
                        if ((fired == true) || (currTime >= (lastscan + RADARTIMEOUT))) {
                            setTurnRadarRightRadians( Double.NEGATIVE_INFINITY * Utils.normalRelativeAngle( absoluteBearing- getRadarHeadingRadians()));
                            lastscan = currTime;
                            radarScan = true;
                        }

                        // when not firing, lock on target.
                        //setTurnRadarRightRadians( 2.2 * Utils.normalRelativeAngle( absoluteBearing - getRadarHeadingRadians()));
                        //radarScan = false;

                        lastDistance = Double.POSITIVE_INFINITY;
                        setTurnRadarLeft(getRadarTurnRemaining());
                        setTurnRadarRight(getRadarTurnRemaining());

                        if(lastDistance+20 > distance){
                            lastDistance = distance;
                            if(getGunHeat() < .1){
                                setTurnRadarLeft(getRadarTurnRemaining());
                                setTurnRadarRight(getRadarTurnRemaining());
                                clearAllEvents();
                            }
                            setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians() + Math.max(1 - distance / (40), 0) * (e.getVelocity() / (AIM_START + Math.pow(AIM_FACTOR, distance))) * Math.sin(e.getHeadingRadians() - absoluteBearing) ));       
                            }
                    }

                        if(getOthers() == 1){

                            setBodyColor(new Color(255, 0, 0));
                            setGunColor(new Color(255,  0, 0));
                            setRadarColor(new Color(255, 0, 0));
                            setBulletColor(new Color(255, 0, 0));
                            setScanColor(new Color(255, 0, 0));

                            double bulletPower1 = 3;
                            if(distance >= 700){
                                lastDistance = Double.POSITIVE_INFINITY;
                            }

                            else if (distance < 700 && distance > 500){
                                bulletPower = 3 - (( 24.5- getEnergy()) / 6);
                                if (getEnergy() >= 3.1 ) {
                                    setFire(bulletPower);
                                    lastDistance = Double.POSITIVE_INFINITY;
                                }
                                else{
                                    lastDistance = Double.POSITIVE_INFINITY;
                                }
                            }

                        else if (distance <=500 && distance >=350){
                            bulletPower = 3 - (( 17.5- getEnergy()) / 6);
                            if (getEnergy() >= 3.1 ) {
                                setFire(bulletPower);
                                lastDistance = Double.POSITIVE_INFINITY;
                            }
                            else{
                                lastDistance = Double.POSITIVE_INFINITY;
                            }
                        }

                        else if (distance < 350 ){
                            bulletPower = 3 - (( 5- getEnergy()) / 6);
                            if (getEnergy() >= 3.1 ) {
                                setFire(bulletPower);
                                lastDistance = Double.POSITIVE_INFINITY;
                            }
                            else{
                                lastDistance = Double.POSITIVE_INFINITY;
                            }
                        }

                    if(lastDistance+25 > distance){
                        lastDistance = distance;
                        if(getGunHeat() < .1){
                                setTurnRadarLeft(getRadarTurnRemaining());
                                setTurnRadarRight(getRadarTurnRemaining());
                                clearAllEvents();
                        clearAllEvents();
                    }
                setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians() + Math.max(1 - distance / (400), 0) * (e.getVelocity() / (AIM_START + Math.pow(AIM_FACTOR, distance))) * Math.sin(e.getHeadingRadians() - absoluteBearing) ));      
                }
                    wall();
                    // always square off against our enemy, turning slightly toward him
                    setTurnRight(e.getBearing() + 90 - (10 * moveDirection));
                    // if we're close to the wall, eventually, we'll move away
                    if (tooCloseToWall > 0) tooCloseToWall--;
                    // normal movement: switch directions if we've stopped
                    if (getVelocity() == 0) {
                        setMaxVelocity(8);
                        moveDirection *= -1;
                        setAhead(500 * moveDirection);
                    }
            }
    }   

                    public void onHitByBullet(HitByBulletEvent e) {
                        setTurnRadarLeft(getRadarTurnRemaining());
                        setTurnRadarRight(getRadarTurnRemaining());
                        clearAllEvents();
                    }

                    public void onBulletMissed(BulletMissedEvent e) {
                        setTurnRadarLeft(getRadarTurnRemaining());
                        setTurnRadarRight(getRadarTurnRemaining());
                        clearAllEvents();
                    }

                    public void onHitRobot(HitRobotEvent e) {
                        setTurnRadarLeft(getRadarTurnRemaining());
                        setTurnRadarRight(getRadarTurnRemaining());
                        clearAllEvents();
                    }

                    public void wall(){
                    //close to left, right, bottom, top wall
                    if(getX() <= wallMargin || getX() >= getBattleFieldWidth() - wallMargin || getY() <= wallMargin || getY() >= getBattleFieldHeight() - wallMargin){
                    if(tooCloseToWall <= 0){
                    // coming near the wall
                        tooCloseToWall += wallMargin;
                        setMaxVelocity(0); // stop!!!
                    }
            }
    }   

}

于 2014-05-20T02:51:14.337 に答える