Difference between revisions of "Quantum/Source (Java)"

From Robowiki
Jump to navigation Jump to search
m (Fix syntax highlighting)
(Update source code to v0.2.3)
Line 17: Line 17:
 
// Version History
 
// Version History
 
// -------------------------------------------------------------------------------------------------
 
// -------------------------------------------------------------------------------------------------
// ================================================================================
+
// =================================================================================================
 
// v0.2.2 (2024-04-06) Codesize: 249  | Colors: Yes | 1v1 capable: No
 
// v0.2.2 (2024-04-06) Codesize: 249  | Colors: Yes | 1v1 capable: No
// ================================================================================
+
// =================================================================================================
 
// - Antigravity movement based on DustBunny, but with forces calculated based on
 
// - Antigravity movement based on DustBunny, but with forces calculated based on
 
//  where we would aim to hit the enemy, rather than where they currently are
 
//  where we would aim to hit the enemy, rather than where they currently are
Line 27: Line 27:
 
// - Quite a bit of code shrinking to make room for Infinity style target tracking
 
// - Quite a bit of code shrinking to make room for Infinity style target tracking
 
//
 
//
// Nano melee:    2nd APS (64.81),  1st Survival (25.36)
+
// =================================================================================================
// Micro melee:    9th APS (64.17),  3rd Survival (25.20)
 
// Mini melee:    18th APS (63.52),  8th Survival (24.63)
 
// General melee: 67th APS (60.56), 55th Survival (21.60)
 
//
 
// Knocked DustBunny off of the top of the table for a few days before settling in to second place.
 
// Only 0.2 APS behind but significantly ahead on survival.
 
// Currently assumes a 1000x1000 battlefield. There would be space to remove this restriction but
 
// that would mean giving up on my colours :(
 
//
 
// ================================================================================
 
 
// v0.2.2a (2024-04-11) Codesize: 249  | Colors: Yes | 1v1 capable: No
 
// v0.2.2a (2024-04-11) Codesize: 249  | Colors: Yes | 1v1 capable: No
// ================================================================================
+
// =================================================================================================
 
// - No functional changes, added credits, version history and commented the code
 
// - No functional changes, added credits, version history and commented the code
 
+
//
// -------------------------------------------------------------------------------------------------
+
// =================================================================================================
// TODO
+
// v0.2.3 (2024-05-14) Codesize: 245  | Colors: Yes | 1v1 capable: No
// -------------------------------------------------------------------------------------------------
+
// =================================================================================================
// - Measure the APS/Survival impact of moving setTurnRadarRight from run() to onRobotDeath()
+
// - Change to int for distance and targetDistance variables
// - Experiment with other guns and energy management
+
// - Switch to a gunHeat radar lock that doesn't require an if statement
// - Find a way to avoid doing a circle of death in the corner, mainly an issue in the final 1v1
+
// - Switch from setTurnRight to setTurnLeft
// - Thorough testing of different settings for the tuning knobs
 
  
 
package d414.nano;
 
package d414.nano;
Line 61: Line 50:
 
     // Tuning Knobs
 
     // Tuning Knobs
 
     // ---------------------------------------------------------------------------------------------
 
     // ---------------------------------------------------------------------------------------------
     static final double WALL_FORCE = 1;
+
     static final double WALL_FORCE = 1.0;
 
     static final double AGRAV_DECAY = 0.9;
 
     static final double AGRAV_DECAY = 0.9;
     static final double AHEAD_AMOUNT = 120;
+
     static final double AHEAD_AMOUNT = 120.0;
  
     static final double AIM_START = 10;
+
     static final double AIM_START = 10.0;
 
     static final double AIM_FACTOR = 1.008;
 
     static final double AIM_FACTOR = 1.008;
     static final double RADAR_LOCK_THRESHOLD = 1;
+
     static final double RADAR_LOCK_THRESHOLD = 1.0;
     static final int   POWER_FACTOR = 2;
+
     static final int POWER_FACTOR = 2;
  
 
     // ---------------------------------------------------------------------------------------------
 
     // ---------------------------------------------------------------------------------------------
Line 74: Line 63:
 
     // ---------------------------------------------------------------------------------------------
 
     // ---------------------------------------------------------------------------------------------
 
     static String targetName;
 
     static String targetName;
     static double targetDistance;
+
     static int targetDistance;
 
     static double xForce;
 
     static double xForce;
 
     static double yForce;
 
     static double yForce;
Line 83: Line 72:
 
         setAdjustGunForRobotTurn(true);
 
         setAdjustGunForRobotTurn(true);
 
         onRobotDeath(null);
 
         onRobotDeath(null);
 +
        setTurnRadarRight(Double.POSITIVE_INFINITY);
 
     }
 
     }
  
    // Moving setTurnRadarRight here, instead of in run(), saves 1 byte
 
 
     @Override
 
     @Override
     public void onRobotDeath(RobotDeathEvent e) {
+
     public void onRobotDeath(RobotDeathEvent r1e) {
         setTurnRadarRight(targetDistance = Double.POSITIVE_INFINITY);
+
         targetDistance = Integer.MAX_VALUE;
 
     }
 
     }
  
 
     @Override
 
     @Override
     public void onScannedRobot(ScannedRobotEvent e) {
+
     public void onScannedRobot(ScannedRobotEvent r1e) {
         double distance; // Keep this first to save 2 bytes
+
         int r2i;
        double absoluteBearing;
+
         double r3d;
         double aimAngle;
 
  
         // 1. Calculate the angle DustBunny 3.8's gun would aim at
+
         setTurnLeftRadians(Utils.normalRelativeAngle(
        // 2. Update rolling averages of antigravity forces, using the aim angle of DustBunny 3.8's
+
                     (r3d = getHeadingRadians())
        //    gun instead of the absoluteBearing
+
                    - Math.atan2(
        // 3. Move based on angtigravity forces
 
        setTurnRightRadians(Utils.normalRelativeAngle(
 
                     Math.atan2(
 
 
                         (xForce = xForce * AGRAV_DECAY
 
                         (xForce = xForce * AGRAV_DECAY
                         - Math.sin(
+
                         - Math.sin(r3d = (r3d += r1e.getBearingRadians())
                            aimAngle = (absoluteBearing = e.getBearingRadians() + getHeadingRadians())
+
                             + (r1e.getVelocity()
                             + (e.getVelocity()
+
                                * Math.sin(r1e.getHeadingRadians() - r3d)
                                 / (AIM_START + Math.pow(AIM_FACTOR, distance = e.getDistance()))
+
                                 / (AIM_START + Math.pow(AIM_FACTOR, r2i = (int)r1e.getDistance()))
 
                               )
 
                               )
                            * Math.sin(e.getHeadingRadians() - absoluteBearing)
+
                             ) / r2i
                             ) / distance
 
 
                         )
 
                         )
 
                         + calcWallForce(getX())
 
                         + calcWallForce(getX())
                        //+ calcWallForce(getX(), getBattleFieldWidth())
 
 
                         ,  
 
                         ,  
                         (yForce = yForce * AGRAV_DECAY - Math.cos(aimAngle) / distance)
+
                         (yForce = yForce * AGRAV_DECAY - Math.cos(r3d) / r2i)
 
                         + calcWallForce(getY())
 
                         + calcWallForce(getY())
                        //+ calcWallForce(getY(), getBattleFieldHeight())
 
 
                         )
 
                         )
                    - getHeadingRadians()
 
 
                     ));
 
                     ));
 
         setAhead(AHEAD_AMOUNT - Math.abs(getTurnRemaining()));
 
         setAhead(AHEAD_AMOUNT - Math.abs(getTurnRemaining()));
       
 
        // Use Infinity style target tracking
 
        if (distance < targetDistance || e.getName() == targetName) {
 
            targetName = e.getName();
 
            targetDistance = distance;
 
  
            if (getGunHeat() < RADAR_LOCK_THRESHOLD) {
+
        if (r2i < targetDistance || r1e.getName() == targetName) {
                setTurnRadarLeft(getRadarTurnRemaining());
+
            targetName = r1e.getName();
             }
+
             targetDistance = r2i;
  
             // Fire more agressively when there are more enemies.
+
             setTurnRadarRight((getGunHeat() - RADAR_LOCK_THRESHOLD) * getRadarTurnRemaining());
            // With POWER_FACTOR = 2
 
            // 6-9 enemies: setFire(3)
 
            // 4-5 enemies: setFire(2)
 
            // 2-3 enemies: setFire(1)
 
            // 1v1:        setFire(0.1)
 
 
             setFire(getOthers() / POWER_FACTOR);
 
             setFire(getOthers() / POWER_FACTOR);
 
+
             setTurnGunRightRadians(Utils.normalRelativeAngle(r3d - getGunHeadingRadians()));
             setTurnGunRightRadians(Utils.normalRelativeAngle(aimAngle - getGunHeadingRadians()));
 
 
         }
 
         }
 
     }
 
     }
  
    // Factoring out the code for wall forces saves 8 bytes
+
     public static double calcWallForce(double r0d) {
     public static double calcWallForce(double d) {
+
         return (WALL_FORCE / r0d) - (WALL_FORCE / (1000 - r0d));
         return (WALL_FORCE / d) - (WALL_FORCE / (1000 - d));
 
    }
 
 
 
    // Use this version of calcWallForce to remove the assumption that the battlefield is 1000x1000
 
    // This would cost us 6 bytes
 
    /*
 
    public static double calcWallForce(double d, double len) {
 
        return (WALL_FORCE / d) - (WALL_FORCE / (len - d));
 
 
     }
 
     }
    */
 
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>

Revision as of 07:05, 14 May 2024

// -------------------------------------------------------------------------------------------------
// ==============
// Quantum (Nano)
// ==============
// Author: David414
// License: RWPCL (https://robowiki.net/wiki/RWPCL)
// -------------------------------------------------------------------------------------------------

// -------------------------------------------------------------------------------------------------
// Credits
// -------------------------------------------------------------------------------------------------
// Quantum started out life as a tweaked version of Mike Dorgan's DustBunny before being heavily
// shrunk to make room for improved target tracking (inspired by Infinity, also by Mike).

// -------------------------------------------------------------------------------------------------
// Version History
// -------------------------------------------------------------------------------------------------
// =================================================================================================
// v0.2.2 (2024-04-06) Codesize: 249  | Colors: Yes | 1v1 capable: No
// =================================================================================================
// - Antigravity movement based on DustBunny, but with forces calculated based on
//   where we would aim to hit the enemy, rather than where they currently are
// - Aim like DustBunny but with different energy management based only on how
//   many enemies are still alive. Fire more agressively early on and much less
//   agressively in 1v1
// - Quite a bit of code shrinking to make room for Infinity style target tracking
//
// =================================================================================================
// v0.2.2a (2024-04-11) Codesize: 249  | Colors: Yes | 1v1 capable: No
// =================================================================================================
// - No functional changes, added credits, version history and commented the code
//
// =================================================================================================
// v0.2.3 (2024-05-14) Codesize: 245  | Colors: Yes | 1v1 capable: No
// =================================================================================================
// - Change to int for distance and targetDistance variables
// - Switch to a gunHeat radar lock that doesn't require an if statement
// - Switch from setTurnRight to setTurnLeft

package d414.nano;

import robocode.*;
import robocode.util.Utils;

import java.awt.Color;

public class Quantum extends AdvancedRobot {
    // ---------------------------------------------------------------------------------------------
    // Tuning Knobs
    // ---------------------------------------------------------------------------------------------
    static final double WALL_FORCE = 1.0;
    static final double AGRAV_DECAY = 0.9;
    static final double AHEAD_AMOUNT = 120.0;

    static final double AIM_START = 10.0;
    static final double AIM_FACTOR = 1.008;
    static final double RADAR_LOCK_THRESHOLD = 1.0;
    static final int POWER_FACTOR = 2;

    // ---------------------------------------------------------------------------------------------
    // Globals
    // ---------------------------------------------------------------------------------------------
    static String targetName;
    static int targetDistance;
    static double xForce;
    static double yForce;

    @Override
    public void run() {
        setAllColors(Color.cyan);
        setAdjustGunForRobotTurn(true);
        onRobotDeath(null);
        setTurnRadarRight(Double.POSITIVE_INFINITY);
    }

    @Override
    public void onRobotDeath(RobotDeathEvent r1e) {
        targetDistance = Integer.MAX_VALUE;
    }

    @Override
    public void onScannedRobot(ScannedRobotEvent r1e) {
        int r2i;
        double r3d;

        setTurnLeftRadians(Utils.normalRelativeAngle(
                    (r3d = getHeadingRadians())
                    - Math.atan2(
                        (xForce = xForce * AGRAV_DECAY
                         - Math.sin(r3d = (r3d += r1e.getBearingRadians())
                             + (r1e.getVelocity()
                                 * Math.sin(r1e.getHeadingRadians() - r3d)
                                 / (AIM_START + Math.pow(AIM_FACTOR, r2i = (int)r1e.getDistance()))
                               )
                             ) / r2i
                        )
                        + calcWallForce(getX())
                        , 
                        (yForce = yForce * AGRAV_DECAY - Math.cos(r3d) / r2i)
                        + calcWallForce(getY())
                        )
                    ));
        setAhead(AHEAD_AMOUNT - Math.abs(getTurnRemaining()));

        if (r2i < targetDistance || r1e.getName() == targetName) {
            targetName = r1e.getName();
            targetDistance = r2i;

            setTurnRadarRight((getGunHeat() - RADAR_LOCK_THRESHOLD) * getRadarTurnRemaining());
            setFire(getOthers() / POWER_FACTOR);
            setTurnGunRightRadians(Utils.normalRelativeAngle(r3d - getGunHeadingRadians()));
        }
    }

    public static double calcWallForce(double r0d) {
        return (WALL_FORCE / r0d) - (WALL_FORCE / (1000 - r0d));
    }
}