Excession/DiveBomber

From RoboWiki
Jump to: navigation, search

A Drone by User:Excession

package excession.drones;
 
import static java.lang.Math.PI;
import static java.lang.Math.atan;
import static java.lang.Math.atan2;
import static java.lang.Math.min;
import static java.lang.Math.exp;
import static java.lang.Math.sqrt;
import static robocode.util.Utils.normalRelativeAngle;
import robocode.AdvancedRobot;
import robocode.ScannedRobotEvent;
 
/**
 * A drone that spirals in towards and then circles its enemy and fires pot
 * shots.
 * 
 * @author Excession
 * @version 1.0, 2008-06-04, released as SpiralCircle
 * @version 1.1, 2008-06-09, better spiraling with Gumpertz function, renamed to
 *          DiveBomber
 */
public class DiveBomber extends AdvancedRobot {
 
    private static final double DISTANCE = 200;
    private static final double SPEED = 20.0;
    private int direction = 1;
 
    private void init() {
        setAdjustRadarForRobotTurn(true);
        setAdjustGunForRobotTurn(true);
        setAdjustRadarForGunTurn(true);
    }
 
    @Override
    public void run() {
        init();
        setTurnRadarRightRadians(2 * PI);
        while (true) {
            execute();
        }
    }
 
    @Override
    public void onScannedRobot(ScannedRobotEvent event) {
        lockOnTarget(event);
        aimAndFire(event);
        move(event);
    }
 
    private void move(ScannedRobotEvent event) {
        double bearing = event.getBearingRadians();
        double range = event.getDistance();
 
        if (stopped()) {
            switchDirection();
        }
 
        double delta = range - DISTANCE;
        double spiral = gompertz(delta);
 
        double d = SPEED;
        double b = sqrt(range * range - (d * d) / 4);
        double alpha = atan2(b, d / 2);
        double tankTurn = bearing - alpha + spiral * direction;
 
        setTurnRightRadians(tankTurn);
        setAhead(d * direction);
    }
 
    /**
     * Calculate Gompertz function with the following values.
     * 
     * <ul>
     * <li> a = PI/2 (90 degrees).
     * <li> b = -PI
     * <li> c = -0.01
     * </ul>
     * 
     * This allows us to sprial in nicely and then stabilize in a circular
     * orbit.
     * 
     * @param x
     * @return Gompertz function value for x
     * @see http://en.wikipedia.org/wiki/Gompertz_function
     */
    private double gompertz(double x) {
        return PI / 2 * exp(-PI * exp(-x * 0.01));
    }
 
    private boolean stopped() {
        return getVelocity() == 0.0;
    }
 
    private void switchDirection() {
        direction *= -1;
    }
 
    /**
     * @see http://testwiki.roborumble.org/w/index.php?title=Radar#Wide_lock
     */
    private void lockOnTarget(ScannedRobotEvent event) {
        double absoluteBearing = getHeadingRadians() + event.getBearingRadians();
        double radarTurn = normalRelativeAngle(absoluteBearing - getRadarHeadingRadians());
        double arcToScan = min(atan(36.0 / event.getDistance()), PI / 4.0);
        radarTurn += (radarTurn < 0) ? -arcToScan : arcToScan;
        setTurnRadarRightRadians(radarTurn);
    }
 
    private void aimAndFire(ScannedRobotEvent event) {
        double absoluteBearing = getHeadingRadians() + event.getBearingRadians();
        double gunTurn = normalRelativeAngle(absoluteBearing - getGunHeadingRadians());
        setTurnGunRightRadians(gunTurn);
 
        final double power = 3.0;
        if (getGunHeat() == 0.0) {
            setFire(power);
        }
    }
}
Personal tools