Difference between revisions of "One on One Radar"

From Robowiki
Jump to navigation Jump to search
(→‎Width Lock: Expanding the code out to be easier to understand/read (more important then code similarity))
(→‎Width Lock: ment to do this)
Line 97: Line 97:
  
 
public void onScannedRobot(ScannedRobotEvent e) {
 
public void onScannedRobot(ScannedRobotEvent e) {
     double radarTurn = Utils.normalRelativeAngle(
+
     // Absolute angle towards target
        // Absolute bearing to target
+
    double angleToEnemy = getHeadingRadians() + e.getBearingRadians();
        getHeadingRadians() + e.getBearingRadians()
+
 
        // Subtract current radar heading to get turn required
+
    // Subtract current radar heading to get the turn required, then normalize it
        - getRadarHeadingRadians() );
+
    double radarTurn = Utils.normalRelativeAngle(angleToEnemy - getRadarHeadingRadians() );
  
 
     // Distance we want to scan from middle of enemy to either side
 
     // Distance we want to scan from middle of enemy to either side
 +
    // The 36 is how far from center it scans, the Math.PI/4.0
 
     double extraTurn = Math.min(Math.atan(36.0 / e.getDistance()), Rules.RADAR_TURN_RATE_RADIANS);
 
     double extraTurn = Math.min(Math.atan(36.0 / e.getDistance()), Rules.RADAR_TURN_RATE_RADIANS);
  
     setTurnRadarRightRadians(radarTurn + (radarTurn < 0 ? -extraTurn : extraTurn));
+
     // Adjust the radar turn so it goes further in its current direction
 +
    radarTurn += (radarTurn < 0 ? -extraTurn : extraTurn)
 +
 +
    //Turn radar
 +
    setTurnRadarRightRadians(radarTurn);
  
 
     // ...
 
     // ...

Revision as of 01:55, 20 July 2011

One on One Radars are radars that are used for One on One battles. They usually produce a perfect lock by scanning an enemy every turn.

Spinning radar

A simple spin of the radar, this is very ineffective in one on one, but still used in NanoBots.

Here is an example of this type of radar:

public void run() {
    // ...

    do {
        turnRadarRightRadians(Double.POSITIVE_INFINITY);
    } while (true);
}

The Infinity Lock

The infinity lock is the simplest radar lock and it is used frequently in NanoBots. It has the disadvantage of "slipping" and losing its lock frequently. But is a much better alternative to the Spinning radar in one on one combat.

Here is an example of this type of radar:

public void run() {
    // ...
    turnRadarRightRadians(Double.POSITIVE_INFINITY);
}

public void onScannedRobot(ScannedRobotEvent e) {
    // ...
    setTurnRadarLeftRadians(getRadarTurnRemainingRadians());
}

Perfect radar locks

There are several "perfect" radar locks that will not slip once they have a lock.

Turn Multiplier Lock

Point the radar at the enemy's last known location. This results in a thin beam which follows the enemy around the battlefield. Many recent one on one bots use this type of radar. This radar lock is similar to, and considered an enhancement on the wide radar lock described below.

If implemented correctly, it is not possible for the enemy escape this lock. A robot's width is 36px (that's 18px from the middle) and it can only move at up to 8px/turn, so if your beam is pointing at its centre, it won't be able to move entirely out of it in one turn. However, a robot will only automatically scan for enemies if its radar is turning, which might not happen if you are using a Narrow Lock and your enemy decides to stay still for 2 turns. For this reason, if you decide to use an unmultiplied lock, you must call scan() yourself to avoid losing lock. Furthermore, if you skip turns, your enemy might be able to move out from your radar beam before you recover.

To overcome these issues, a Narrow Lock is often multiplied by a factor (as described below) to keep the radar moving and ensure the enemy does not escape the scan arc.

Here is an example of this kind of radar:

import robocode.util.Utils;

public void run() {
    // ...

    turnRadarRightRadians(Double.POSITIVE_INFINITY);
    do {
        // Check for new targets.
        // Only necessary for Narrow Lock because sometimes our radar is already
        // pointed at the enemy and our onScannedRobot code doesn't end up telling
        // it to turn, so the system doesn't automatically call scan() for us
        // [see the javadocs for scan()].
        scan();
    } while (true);
}

public void onScannedRobot(ScannedRobotEvent e) {
    double radarTurn =
        // Absolute bearing to target
        getHeadingRadians() + e.getBearingRadians()
        // Subtract current radar heading to get turn required
        - getRadarHeadingRadians();

    setTurnRadarRightRadians(Utils.normalRelativeAngle(radarTurn));

    // ...
}

The following factors affect the behaviour in the following ways (eg. factor * Utils.normalRelativeAngle(radarTurn))

  • 1.0 - Thin radar lock. Must call scan() to avoid losing lock. God help you if you ever skip a turn.
  • 1.9 - Radar arc starts wide and slowly narrows as much as possible while staying on target.
  • 2.0 - Radar arc sweeps through a fixed angle. Exact angle chosen depends on positions of enemy and radar when enemy is first picked up. Angle will be increased if necessary to maintain a lock. Most used corrective factor.

Width Lock

The Width Radar Lock or Wide Radar Lock tries to scan a fixed distance to either side of the enemy. It was to the best of knowledge created before the Turn Multiplier or Narrow Radar Lock. Its constant motion means the radar will not slip as long as you don't miss any turns.

Here is an example of this type of radar:

import robocode.util.Utils;

public void run() {
    // ...

    do {
        // ...
        // Turn the radar if we have no more turn, starts it if it stops and at the start of round
        if (getRadarTurnRemaining() == 0.0)
            setTurnRadarRightRadians(Double.POSITIVE_INFINITY);
        execute();
    } while (true);
}

public void onScannedRobot(ScannedRobotEvent e) {
    // Absolute angle towards target
    double angleToEnemy = getHeadingRadians() + e.getBearingRadians();

    // Subtract current radar heading to get the turn required, then normalize it
    double radarTurn = Utils.normalRelativeAngle(angleToEnemy - getRadarHeadingRadians() );

    // Distance we want to scan from middle of enemy to either side
    // The 36 is how far from center it scans, the Math.PI/4.0
    double extraTurn = Math.min(Math.atan(36.0 / e.getDistance()), Rules.RADAR_TURN_RATE_RADIANS);

    // Adjust the radar turn so it goes further in its current direction
    radarTurn += (radarTurn < 0 ? -extraTurn : extraTurn)
	
    //Turn radar
    setTurnRadarRightRadians(radarTurn);

    // ...
}

You can replace 36.0 with any distance you want covered.