Quantum/Source (Java)
< Quantum
Jump to navigation
Jump to search
// -------------------------------------------------------------------------------------------------
// ==============
// 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
//
// 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
// ================================================================================
// - No functional changes, added credits, version history and commented the code
// -------------------------------------------------------------------------------------------------
// TODO
// -------------------------------------------------------------------------------------------------
// - Measure the APS/Survival impact of moving setTurnRadarRight from run() to onRobotDeath()
// - Experiment with other guns and energy management
// - Find a way to avoid doing a circle of death in the corner, mainly an issue in the final 1v1
// - Thorough testing of different settings for the tuning knobs
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;
static final double AGRAV_DECAY = 0.9;
static final double AHEAD_AMOUNT = 120;
static final double AIM_START = 10;
static final double AIM_FACTOR = 1.008;
static final double RADAR_LOCK_THRESHOLD = 1;
static final int POWER_FACTOR = 2;
// ---------------------------------------------------------------------------------------------
// Globals
// ---------------------------------------------------------------------------------------------
static String targetName;
static double targetDistance;
static double xForce;
static double yForce;
@Override
public void run() {
setAllColors(Color.cyan);
setAdjustGunForRobotTurn(true);
onRobotDeath(null);
}
// Moving setTurnRadarRight here, instead of in run(), saves 1 byte
@Override
public void onRobotDeath(RobotDeathEvent e) {
setTurnRadarRight(targetDistance = Double.POSITIVE_INFINITY);
}
@Override
public void onScannedRobot(ScannedRobotEvent e) {
double distance; // Keep this first to save 2 bytes
double absoluteBearing;
double aimAngle;
// 1. Calculate the angle DustBunny 3.8's gun would aim at
// 2. Update rolling averages of antigravity forces, using the aim angle of DustBunny 3.8's
// gun instead of the absoluteBearing
// 3. Move based on angtigravity forces
setTurnRightRadians(Utils.normalRelativeAngle(
Math.atan2(
(xForce = xForce * AGRAV_DECAY
- Math.sin(
aimAngle = (absoluteBearing = e.getBearingRadians() + getHeadingRadians())
+ (e.getVelocity()
/ (AIM_START + Math.pow(AIM_FACTOR, distance = e.getDistance()))
)
* Math.sin(e.getHeadingRadians() - absoluteBearing)
) / distance
)
+ calcWallForce(getX())
//+ calcWallForce(getX(), getBattleFieldWidth())
,
(yForce = yForce * AGRAV_DECAY - Math.cos(aimAngle) / distance)
+ calcWallForce(getY())
//+ calcWallForce(getY(), getBattleFieldHeight())
)
- getHeadingRadians()
));
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) {
setTurnRadarLeft(getRadarTurnRemaining());
}
// Fire more agressively when there are more enemies.
// 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);
setTurnGunRightRadians(Utils.normalRelativeAngle(aimAngle - getGunHeadingRadians()));
}
}
// Factoring out the code for wall forces saves 8 bytes
public static double calcWallForce(double d) {
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));
}
*/
}