One on One Radar

From Robowiki
Revision as of 23:48, 18 January 2011 by Chase-san (talk | contribs) (renaming locks)
Jump to navigation Jump to search

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. Furthermode, 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 {
        // ...
        if (getRadarTurnRemaining() == 0.0)
            setTurnRadarRightRadians(Double.POSITIVE_INFINITY);
        execute();
    } while (true);
}

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

    // Distance we want to scan from middle of enemy to either side
    double extraTurn = Math.min(Math.atan(36.0 / e.getDistance()), Math.PI/4.0);

    setTurnRadarRightRadians(radarTurn + (radarTurn < 0 ? -extraTurn : extraTurn));

    // ...
}

You can replace 36.0 with any distance you want covered.