Skip to content

Quick Reference (Formulas)

This page provides a quick lookup for essential formulas and constants used throughout bot development. For detailed explanations, see the linked pages.


Physics Constants

Bot Dimensions

Both games render the bot as a 36×36 unit square visually, centered at the bot's position.

Collision hitbox:

  • Classic Robocode: Axis-aligned 36×36 square (does not rotate with bot heading)
    • Diagonal: ~50.9 units
  • Tank Royale: Circle with radius 18 units (diameter 36; always circular)

Movement Limits

Both Classic Robocode and Tank Royale use identical movement physics:

PropertyValueUnits
Max velocity (vmaxv_{\text{max}})8units/turn
Max acceleration1units/turn²
Max deceleration2units/turn²
Max turn rate (at rest)10degrees/turn
Max turn rate (at max speed)4degrees/turn

Linear velocity has acceleration/deceleration limits, but **rotation (body, gun, radar) has no

acceleration/deceleration**—turn rate changes instantly up to the maximum limit.

Notation:

  • vv: current speed (units/turn)
  • vmaxv_{\text{max}}: maximum speed (=8=8 units/turn)
  • vrestv_{\text{rest}}: rest (=0=0 units/turn)

Turn rate formula:

turnRate=1034×v\text{turnRate} = 10 - \frac{3}{4} \times |v|

maxTurnRatemax=1034×vmax=1034×8=106=4\text{maxTurnRate}_{\text{max}} = 10 - \frac{3}{4} \times |v_{\text{max}}| = 10 - \frac{3}{4} \times 8 = 10 - 6 = 4^\circ

maxTurnRaterest=1034×vrest=1034×0=100=10\text{maxTurnRate}_{\text{rest}} = 10 - \frac{3}{4} \times |v_{\text{rest}}| = 10 - \frac{3}{4} \times 0 = 10 - 0 = 10^\circ

Rotation Limits

ComponentMax RateUnits
Body10°degrees/turn
Gun (relative to body)20°degrees/turn
Radar (relative to gun)45°degrees/turn

Maximum combined rates:

  • Gun relative to battlefield: 30°/turn (body 10° + gun 20°)
  • Radar relative to battlefield: 75°/turn (body 10° + gun 20° + radar 45°)

Bullet Physics

Bullet Speed

bulletSpeed=203×bulletPower\text{bulletSpeed} = 20 - 3 \times \text{bulletPower}

PowerSpeedUnits/turn
0.119.7units/turn
1.017.0units/turn
2.014.0units/turn
3.011.0units/turn

Bullet Damage

damage={4×bulletPowerif bulletPower14×bulletPower+2×(bulletPower1)if bulletPower>1\text{damage} = \begin{cases} 4 \times \text{bulletPower} & \text{if } \text{bulletPower} \leq 1 \\ 4 \times \text{bulletPower} + 2 \times (\text{bulletPower} - 1) & \text{if } \text{bulletPower} > 1 \end{cases}

PowerDamageBonusTotal
0.10.400.4
1.04.004.0
2.08.02.010.0
3.012.04.016.0

Gun Heat

gunHeat=1+bulletPower5\text{gunHeat} = 1 + \frac{\text{bulletPower}}{5}

coolingRate=0.1 per turn\text{coolingRate} = 0.1 \text{ per turn}

PowerHeatCool Time
0.11.0211 turns
1.01.2012 turns
2.01.4014 turns
3.01.6016 turns

Angle & Distance Calculations

Coordinate Systems

Classic Robocode:

  • Origin: bottom-left (0, 0)
  • Heading 0°: North (up)
  • Angles: clockwise from north

Tank Royale:

  • Origin: bottom-left (0, 0)
  • Heading 0°: East (right)
  • Angles: counterclockwise from east

Absolute Bearing

Angle from your position to a target:

dx = target.x - my.x
dy = target.y - my.y
absoluteBearing = atan2(dx, dy)  // Classic: atan2(x, y)
absoluteBearing = atan2(dy, dx)  // Tank Royale: atan2(y, x)

Relative Bearing

Angle from your heading to a target:

relativeBearing=absoluteBearingmyHeading\text{relativeBearing} = \text{absoluteBearing} - \text{myHeading}

relativeBearing=normalizeAngle(relativeBearing)\text{relativeBearing} = \text{normalizeAngle}(\text{relativeBearing}) (wrap to [180°,+180°][-180°, +180°])

Distance

distance=(target.xmy.x)2+(target.ymy.y)2\text{distance} = \sqrt{(\text{target.x} - \text{my.x})^2 + (\text{target.y} - \text{my.y})^2}

Normalize Angle to [-180°, +180°]

while angle>180°:angle=360°\text{while } \text{angle} > 180°: \quad \text{angle} \mathrel{-}= 360°

while angle<180°:angle+=360°\text{while } \text{angle} < -180°: \quad \text{angle} \mathrel{+}= 360°


Targeting Formulas

Head-On Targeting

Aim directly at the current enemy position:

gunTurnRequired=normalizeAngle(absoluteBearinggunHeading)\text{gunTurnRequired} = \text{normalizeAngle}(\text{absoluteBearing} - \text{gunHeading})

Linear Targeting

Predict enemy position assuming constant velocity:

// Solve for bullet flight time (iterative)
bulletSpeed = 20 - 3 * bulletPower
time = distance / bulletSpeed  // Initial guess

for iteration in 1..5:
  futureX = enemy.x + enemy.velocityX * time
  futureY = enemy.y + enemy.velocityY * time
  distance = sqrt((futureX - my.x)² + (futureY - my.y)²)
  time = distance / bulletSpeed

aimAngle = atan2(futureX - my.x, futureY - my.y)

Circular Targeting

Predict enemy position assuming a constant turn rate:

// Estimate angular velocity
angleToEnemy = atan2(enemy.x - my.x, enemy.y - my.y)
lateralVelocity = enemy.velocity * sin(enemy.heading - angleToEnemy)
angularVelocity = lateralVelocity / distance

// Solve for time iteratively
bulletSpeed = 20 - 3 * bulletPower
time = distance / bulletSpeed

for iteration in 1..5:
  futureHeading = enemy.heading + angularVelocity * time
  futureX = enemy.x + enemy.velocity * sin(futureHeading) * time
  futureY = enemy.y + enemy.velocity * cos(futureHeading) * time
  distance = sqrt((futureX - my.x)² + (futureY - my.y)²)
  time = distance / bulletSpeed

aimAngle = atan2(futureX - my.x, futureY - my.y)

GuessFactor Formula

lateralDirection=sign(lateralVelocity)\text{lateralDirection} = \text{sign}(\text{lateralVelocity})

maxEscapeAngle=arcsin(8bulletSpeed)\text{maxEscapeAngle} = \arcsin\left(\frac{8}{\text{bulletSpeed}}\right)

angleOffset=actualBearingAtHitbearingAtFire\text{angleOffset} = \text{actualBearingAtHit} - \text{bearingAtFire}

guessFactor=angleOffsetmaxEscapeAngle\text{guessFactor} = \frac{\text{angleOffset}}{\text{maxEscapeAngle}}

GuessFactor ranges from -1.0 (maximum clockwise dodge) to +1.0 (maximum counter-clockwise dodge).


Movement Calculations

Lateral Velocity

Velocity perpendicular to the enemy line of fire:

angleToEnemy=atan2(enemy.xmy.x,enemy.ymy.y)\text{angleToEnemy} = \text{atan2}(\text{enemy.x} - \text{my.x}, \text{enemy.y} - \text{my.y})

lateralVelocity=my.velocity×sin(my.headingangleToEnemy)\text{lateralVelocity} = \text{my.velocity} \times \sin(\text{my.heading} - \text{angleToEnemy})

Sign:

  • Positive: moving counter-clockwise (left) around an enemy
  • Negative: moving clockwise (right) around an enemy

Advancing Velocity

Velocity toward/away from enemy:

advancingVelocity=my.velocity×cos(my.headingangleToEnemy)\text{advancingVelocity} = \text{my.velocity} \times \cos(\text{my.heading} - \text{angleToEnemy})

Sign:

  • Positive: moving toward an enemy
  • Negative: moving away from an enemy

Orbital Movement

Maintain a constant distance while orbiting:

orbitAngle=90° (perpendicular to enemy)\text{orbitAngle} = 90° \text{ (perpendicular to enemy)}

orbitDirection=+1 or 1 (counter-clockwise or clockwise)\text{orbitDirection} = +1 \text{ or } -1 \text{ (counter-clockwise or clockwise)}

desiredHeading=angleToEnemy+orbitDirection×orbitAngle\text{desiredHeading} = \text{angleToEnemy} + \text{orbitDirection} \times \text{orbitAngle}

turnRequired=normalizeAngle(desiredHeadingmy.heading)\text{turnRequired} = \text{normalizeAngle}(\text{desiredHeading} - \text{my.heading})

Wall Distance

Minimum distance to any wall:

wallDistance=min(my.x,my.y,fieldWidthmy.x,fieldHeightmy.y)\text{wallDistance} = \min(\text{my.x}, \text{my.y}, \text{fieldWidth} - \text{my.x}, \text{fieldHeight} - \text{my.y})

Wall Smoothing (Basic)

Adjust heading to avoid hitting walls. For each wall, calculate push force proportional to proximity:

margin=150 (safety margin in units)\text{margin} = 150 \text{ (safety margin in units)}

adjustHeading+={(marginmy.x)×0.1if my.x<margin0otherwise\text{adjustHeading} \mathrel{+}= \begin{cases} ({\text{margin} - \text{my.x}}) \times 0.1 & \text{if } \text{my.x} < \text{margin} \\ 0 & \text{otherwise} \end{cases}

Similar calculations apply for the right wall, top wall, and bottom wall.


Energy & Scoring

Energy Bonuses

Bullet hit:

energyGained=3×bulletPower\text{energyGained} = 3 \times \text{bulletPower}

NOTE

Neither Classic Robocode nor Tank Royale awards energy bonuses for killing enemies. Energy is only gained from bullet hits (3× bullet power). Kills award scoring points (see Damage Scoring below), not energy.

Damage Scoring

Bullet hit damage:

score+=damage\text{score} \mathrel{+}= \text{damage}

Bullet kill bonus:

When a bot kills an enemy with a bullet, it scores an additional bonus:

Both Classic Robocode and Tank Royale:

bulletDamageBonus=20% of all bullet damage dealt to that enemy\text{bulletDamageBonus} = 20\% \text{ of all bullet damage dealt to that enemy}

Or equivalently: bulletDamageBonus=0.20×bullet damage\text{bulletDamageBonus} = 0.20 \times \sum \text{bullet damage}

Ram damage:

damage=0.6 per turn of contact\text{damage} = 0.6 \text{ per turn of contact}

score+=2×ram damage\text{score} \mathrel{+}= 2 \times \text{ram damage}

Ram kill bonus:

When a bot kills an enemy by ramming, it scores an additional bonus:

Both Classic Robocode and Tank Royale:

ramDamageBonus=30% of all ram damage dealt to that enemy\text{ramDamageBonus} = 30\% \text{ of all ram damage dealt to that enemy}

Or equivalently: ramDamageBonus=0.30×ram damage\text{ramDamageBonus} = 0.30 \times \sum \text{ram damage}

Survival score:

survivalScore=50×number of bots that died while you survived\text{survivalScore} = 50 \times \text{number of bots that died while you survived}

Last survivor bonus:

lastSurvivorBonus=10×number of opponent bots\text{lastSurvivorBonus} = 10 \times \text{number of opponent bots}


Wave Calculations

Max Escape Angle

Maximum angle the enemy can reach by moving perpendicular at full speed:

maxEscapeAngle=arcsin(8bulletSpeed)\text{maxEscapeAngle} = \arcsin\left(\frac{8}{\text{bulletSpeed}}\right)

Bullet PowerSpeedMax Escape Angle
0.119.7~24°
1.017.0~28°
2.014.0~35°
3.011.0~47°

Wave Intersection

Time until a wave intersects bot position:

distanceFromWaveOrigin=(my.xwave.x)2+(my.ywave.y)2\text{distanceFromWaveOrigin} = \sqrt{(\text{my.x} - \text{wave.x})^2 + (\text{my.y} - \text{wave.y})^2}

waveFront=(currentTimewave.fireTime)×wave.bulletSpeed\text{waveFront} = (\text{currentTime} - \text{wave.fireTime}) \times \text{wave.bulletSpeed}

timeUntilHit=distanceFromWaveOriginwaveFrontwave.bulletSpeed\text{timeUntilHit} = \frac{\text{distanceFromWaveOrigin} - \text{waveFront}}{\text{wave.bulletSpeed}}

If timeUntilHit0\text{timeUntilHit} \leq 0, wave has already passed.


Turn Radius

Minimum turn radius at a given velocity:

turnRate=1034×velocityturnRate = 10 - \frac{3}{4} \times |velocity|

radius=velocitysin(turnRate×π180)radius = \frac{|velocity|}{\sin(turnRate \times \frac{π}{180})}

VelocityTurn RateRadius
010°0
4~33 units
8~115 units

Common Trigonometry

Radians ↔ Degrees:

radians=degrees×π180\text{radians} = \text{degrees} \times \frac{\pi}{180}

degrees=radians×180π\text{degrees} = \text{radians} \times \frac{180}{\pi}

Pythagorean theorem:

hypotenuse=a2+b2\text{hypotenuse} = \sqrt{a^2 + b^2}

Sine law:

sin(A)a=sin(B)b=sin(C)c\frac{\sin(A)}{a} = \frac{\sin(B)}{b} = \frac{\sin(C)}{c}

Small angle approximation (θ<15°|\theta| < 15°):

sin(θ)θ\sin(\theta) \approx \theta

cos(θ)1\cos(\theta) \approx 1

tan(θ)θ\tan(\theta) \approx \theta


Platform-Specific API Equivalents

Classic RobocodeTank RoyalePurpose
getX()getX()Bot X position
getY()getY()Bot Y position
getHeading()getDirection()Body heading (note: 0° differs!)
getGunHeading()getGunDirection()Gun absolute heading
getRadarHeading()getRadarDirection()Radar absolute heading
getVelocity()getSpeed()Current velocity
getEnergy()getEnergy()Current energy
getBattleFieldWidth()getArenaWidth()Arena width
getBattleFieldHeight()getArenaHeight()Arena height

Further Reading

Based on RoboWiki content (CC BY-SA 3.0) for classic Robocode and the official Robocode Tank Royale documentation.