Anti-Gravity Movement
Origins
Anti-Gravity Movement was one of the primary movement strategies before Wave Surfing was invented. Along with Random movement, Anti-Gravity was how bots evaded bullets—by maintaining distance and avoiding predictable patterns. Minimum Risk Movement (a related technique for melee combat) was pioneered by Aelryen and ABC.
Historical Context
Anti-Gravity Movement was largely superseded by Wave Surfing for competitive 1v1 play around 2003. While it remains an excellent learning tool and performs well in melee battles, top-tier 1v1 bots use Wave Surfing because it directly counters statistical targeting systems. If your goal is competitive 1v1 performance, study Wave Surfing Introduction instead.
Antigravity movement treats battlefield entities—enemies, walls, bullets, and even teammates—as gravitational sources that exert repulsive (or attractive) forces on the bot. By calculating the combined effect of all forces and moving in the resultant direction, the bot achieves smooth, adaptive positioning that responds naturally to changing battlefield conditions.
This technique excels in melee combat where maintaining optimal distance from multiple enemies is crucial. It also provides flexible positioning in one-on-one battles and serves as a foundation for more sophisticated movement systems.
The Core Concept
Antigravity movement models each battlefield entity as exerting a force on the bot. The size and direction of each force depends on:
- Distance: Closer entities exert stronger forces (typically inverse square law: )
- Type: Enemies repel, corners attract (for corner movement), bullets create shadows
- Strength: Different entity types have different force multipliers (the
strengthconstant)
The bot sums all force vectors to get a resultant force, then moves in the direction that minimizes or maximizes this force (depending on whether forces are repulsive or attractive).
Multiple enemies exert repulsive forces on the bot, creating a resultant force vector away from crowded areas
Why Anti-Gravity Works
Traditional movement strategies often use discrete decisions: "move toward this point" or "orbit at this radius."
Antigravity provides several advantages:
Smooth adaptation: Forces naturally blend, creating fluid movement without abrupt direction changes.
Multi-target awareness: In melee, the bot automatically positions itself away from clusters of enemies without explicit logic for each opponent.
Tunable behavior: Adjusting force strengths and distance calculations changes movement characteristics without rewriting algorithms.
Foundation for hybrid systems: Antigravity can combine with other techniques like wave surfing or distancing by adding their goals as additional force sources.
Against simple targeting, antigravity provides evasion through constant motion. Against statistical targeting, the smooth, adaptive nature makes patterns harder to predict than fixed orbits or oscillations.
Basic Implementation
Force Calculation
The fundamental calculation for each entity:
function calculateForce(entity):
dx = myX - entity.x
dy = myY - entity.y
distance = sqrt(dx² + dy²)
if distance < minDistance:
distance = minDistance // Prevent division by zero
// Inverse square law: force decreases with distance
forceMagnitude = strength / distance²
// Force components along x and y axes
forceX = forceMagnitude * (dx / distance)
forceY = forceMagnitude * (dy / distance)
return (forceX, forceY)Where strength is a tunable constant that determines how strongly the entity repels (positive) or attracts (negative).
Summing All Forces
function calculateTotalForce():
totalForceX = 0
totalForceY = 0
// Add enemy repulsions
for each enemy:
(fx, fy) = calculateForce(enemy)
totalForceX += fx * enemyStrength
totalForceY += fy * enemyStrength
// Add wall repulsions
totalForceX += calculateWallForce(x direction)
totalForceY += calculateWallForce(y direction)
return (totalForceX, totalForceY)Converting Force to Movement
on turn:
(forceX, forceY) = calculateTotalForce()
// Calculate angle to move (angle away from combined forces)
targetAngle = atan2(forceY, forceX)
// Convert to heading
angleToTurn = normalizeAngle(targetAngle - myHeading)
// Move in that direction
setTurnRight(angleToTurn)
setAhead(100) // Full speedTutorial: Building a Basic Anti-Gravity Bot
Let's build a simple antigravity movement system step by step.
Step 1: Enemy Force Calculation
Start with basic enemy repulsion:
class AntiGravityBot:
enemyStrength = 50000 // Tune this value
function getEnemyForce():
forceX = 0
forceY = 0
for each scannedEnemy:
dx = myX - enemy.x
dy = myY - enemy.y
distance = max(1, sqrt(dx² + dy²)) // Avoid zero division
force = enemyStrength / distance²
forceX += force * (dx / distance)
forceY += force * (dy / distance)
return (forceX, forceY)Step 2: Wall Avoidance
Add wall repulsion to keep the bot from corners:
wallStrength = 20000
function getWallForce():
forceX = 0
forceY = 0
// Distance to each wall
distanceToLeft = myX
distanceToRight = battlefieldWidth - myX
distanceToBottom = myY
distanceToTop = battlefieldHeight - myY
// Repel from each wall
forceX += wallStrength / distanceToLeft²
forceX -= wallStrength / distanceToRight²
forceY += wallStrength / distanceToBottom²
forceY -= wallStrength / distanceToTop²
return (forceX, forceY)Step 3: Movement Execution
Combine forces and move:
on turn:
(enemyFX, enemyFY) = getEnemyForce()
(wallFX, wallFY) = getWallForce()
totalForceX = enemyFX + wallFX
totalForceY = enemyFY + wallFY
// Calculate movement angle
targetAngle = atan2(totalForceY, totalForceX)
angleToTurn = normalizeAngle(targetAngle - myHeading)
setTurnRight(angleToTurn)
setAhead(100)Step 4: Tuning Force Strengths
The effectiveness depends heavily on tuning:
- Enemy strength: Higher values = stay farther from enemies
- Wall strength: Higher values = stay farther from walls
- Ratio between them: Determines priority (avoid enemies vs. avoid walls)
Start with enemy strength around 50,000 and wall strength around 20,000, then adjust based on battlefield size and combat style.
Antigravity movement creates smooth, adaptive paths that maintain distance from multiple threats
Advanced Variations
Distance-Dependent Forces
Instead of pure inverse square, use different force laws for different ranges:
function calculateForce(entity, distance):
if distance < closeRange:
// Very strong repulsion when too close
return strongStrength / distance²
else if distance > farRange:
// Weak or no force when far away
return 0
else:
// Normal inverse square in medium range
return normalStrength / distance²Enemy Energy Weighting
Adjust forces based on enemy threat level:
function getEnemyForce():
for each enemy:
// More dangerous enemies exert stronger forces
threatMultiplier = enemy.energy / 100.0
force = (enemyStrength * threatMultiplier) / distance²
// ... calculate force componentsAttractive Forces
Corner movement can be implemented by making corners attractive:
function getCornerAttraction():
corners = [(0, 0), (battleWidth, 0), (0, battleHeight), (battleWidth, battleHeight)]
bestCorner = findNearestSafeCorner(corners)
dx = bestCorner.x - myX
dy = bestCorner.y - myY
distance = sqrt(dx² + dy²)
// Negative force = attraction
force = -cornerStrength / distance²
return (force * dx/distance, force * dy/distance)Bullet Shadows
Create repulsion from predicted bullet positions:
function getBulletForce():
for each trackedBullet:
// Project bullet forward
predictedX = bullet.x + bullet.velocityX * 5
predictedY = bullet.y + bullet.velocityY * 5
// Treat as temporary repulsive source
(fx, fy) = calculateForce(predicted position)
// ... add to total forceTuning and Optimization
Finding the Right Constants
Start with these baseline values:
- Enemy strength: 50,000
- Wall strength: 20,000
- Minimum distance (to prevent divide by zero): 1
Then adjust:
- Too close to enemies: Increase enemy strength or change distance exponent
- Hitting walls: Increase wall strength or add a minimum wall distance threshold
- Too passive: Decrease forces or add attractive forces toward optimal positions
- Jittery movement: Smooth force calculations over multiple turns or add momentum
Performance Considerations
Antigravity requires calculating forces for all entities at every turn:
- Computational cost: where is the number of entities
- Optimization: Only calculate forces for entities within a certain range
- Caching: Store battlefield boundaries once rather than recalculating
- Update frequency: In melee, calculate every turn; in 1v1, can update less frequently
Platform Notes
Antigravity movement works identically in classic Robocode and Tank Royale. Both platforms provide:
- Bot position tracking via scan events
- Battlefield dimension queries
- Trigonometric functions for angle calculations
The main difference is coordinate systems: classic Robocode uses north-up (0° = north), while Tank Royale uses east-right (0° = east). Adjust angle calculations accordingly when porting code.
Common Mistakes
Divide by zero errors: Always set a minimum distance threshold when calculating forces. Even a tiny distance like 1 unit prevents infinite forces.
Inconsistent coordinates: Ensure all force calculations use the same coordinate system. Mixing up enemy absolute positions with relative bearings causes erratic movement.
Ignoring walls until too late: Wall forces should ramp up smoothly as the bot approaches boundaries, not suddenly activate when already too close to turn safely.
Over-tuning for one scenario: Constants that work perfectly on a 1000×1000 battlefield may fail on different sizes. Scale force strengths proportionally to battlefield dimensions.
Static force values: Against adaptive opponents, varying force strengths or adding randomization prevents predictable patterns.
When to Use Anti-Gravity
Ideal for:
- Melee combat: Natural multi-target awareness and spacing — this is where Anti-Gravity still shines
- Dynamic positioning: Situations requiring smooth adaptation to changing conditions
- Learning platforms: Simple to implement, easy to visualize and tune
- Hybrid systems: As a base layer combined with wave surfing or statistical analysis
Not recommended for:
- Competitive 1v1: Wave Surfing provides far superior bullet evasion against statistical targeting systems
- Precision positioning: Fixed radius orbits or specific angles are better with geometric movement
- Bullet dodging: Reacting to actual wave danger calculations beats force-based approximations
Antigravity shines in melee when you need fluid, multifactor positioning without complex decision trees. For 1v1 competitive play, it has been obsolete since approximately 2003 when ABC invented Wave Surfing.
Further Reading
- Anti-Gravity Movement — RoboWiki (classic Robocode)
- Minimum Risk Movement — RoboWiki (classic Robocode)
- Movement — RoboWiki (classic Robocode)
- Tank Royale API - Bot Interface — Tank Royale documentation