Robot Wars 2025 is a real-time robot battle game where you build strategies using easy, drag‑and‑drop blocks. Create your program, send your robot into the arena, and see whose strategy wins.
hit_obstacle to detect collisions with walls, rocks, and turrets.my_angle) or use system ones like enemy_direction and enemy_range.Robot Wars uses a powerful four-lane execution model that allows your robot to multitask and respond to events in real-time.
Your primary logic lane. Typically used for movement patterns, positioning, and main strategy loops.
Runs in parallel with Thread 1. Commonly used for combat logic: scanning, aiming, and firing.
Special blocks that trigger automatically when specific events occur (getting hit, hitting an enemy). Run independently of threads.
Reusable subroutines you define once and call from any thread or event handler. Great for reducing code duplication.
hit_obstaclewhen_hit: Dodge, return fire, or call for helpwhen_i_hit_enemy: Celebrate, track hits, adjust strategyThread 1 (Movement): Thread 2 (Combat):
repeat 100 times repeat 100 times
move_up 100 pixels scan (range: 400)
if hit_obstacle = true if enemy_detected = true
then then
move_down 50 pixels aim_variable enemy_direction
move_right 50 pixels fire
set hit_obstacle to false wait 0.1 seconds
wait 0.5 seconds
In this example, Thread 1 handles movement and collision avoidance while Thread 2 continuously scans and fires at enemies. Both run simultaneously!
The hit_obstacle system variable is your robot's primary way to detect when it has collided with an obstacle, allowing you to implement intelligent collision avoidance.
The hit_obstacle variable is automatically set to true when your robot collides with:
move_forward 100)hit_obstacle is set to truehit_obstacle remains false (or stays true if previously set)Critical: Once hit_obstacle is set to true, it stays true until you manually reset it to false. The game engine does NOT automatically reset it!
If you don't reset hit_obstacle to false after handling a collision, your robot will think it's stuck forever and your evasion logic will keep triggering!
Thread 1:
repeat 100 times
move_forward 100 pixels
if hit_obstacle = true
then
// Evasion maneuver
move_backward 50 pixels
turn_right 45 degrees
// CRITICAL: Reset the flag!
set hit_obstacle to false
wait 0.2 seconds
Thread 1:
repeat 100 times
move_toward_variable enemy_direction for 50 pixels
if hit_obstacle = true
then
// Call custom evasion block
call my block "evade_hit"
// Reset flag after evasion
set hit_obstacle to false
Custom Block "evade_hit":
// Back up
move_backward 30 pixels
// Try moving perpendicular to current direction
turn_right 90 degrees
move_forward 50 pixels
// If still stuck, try opposite direction
if hit_obstacle = true
then
turn_right 180 degrees
move_forward 50 pixels
In Levels mode, turrets are solid obstacles. You can use hit_obstacle to detect when you've bumped into a turret, then back up and destroy it:
Thread 1:
repeat 100 times
move_forward 100 pixels
if hit_obstacle = true
then
// Back up to get firing distance
move_backward 80 pixels
// Scan to detect the turret
scan
// If turret detected, destroy it
if nearest_turret_detected = true
then
aim_variable nearest_turret_direction
repeat 5 times // Turrets need 5 hits
fire
wait 0.2 seconds
// Reset flag
set hit_obstacle to false
hit_obstacle to false after handling a collisionhit_obstacle, use nearest_mine_detected insteadIf your robot seems stuck or keeps executing evasion logic:
hit_obstacle to false after evasionset hit_obstacle to false (not set hit_obstacle to 0)= true (not > 0 or other numeric comparisons)Challenge yourself against AI opponents in progressively harder levels. Earn points for every hit and level completion!
Your score accumulates across levels in a single session:
Earn 200 points for each successful hit on an AI bot (10 points × 20 damage).
Earn 500 bonus points for destroying a turret (requires 5 hits). Destroyed turrets stop firing.
Earn 1,000 bonus points for completing a level (destroying all AI bots).
scan to detect turrets and get their direction/distancescan frequently to track multiple AI bots.Robot Wars provides multiple ways to save and manage your robot programs.
Exported robot programs use the following JSON structure:
{
"name": "MyRobot",
"description": "",
"program": {
"visualProgram": {
"thread1": [
{
"command": "scan",
"params": {}
},
{
"command": "aim_variable",
"params": {
"variable": "enemy_direction"
}
},
{
"command": "fire",
"params": {}
}
],
"thread2": [
{
"command": "move_to_xy",
"params": {
"target_x": 0,
"target_y": 0
}
}
]
},
"dualThreadProgram": { ... },
"userVariables": {
"my_var": {
"type": "persistent",
"value": 100,
"numericValue": 100
}
}
},
"exportedAt": "2025-01-07T14:30:00.000Z",
"version": "1.0"
}
After every battle, you can download a comprehensive JSON replay file containing complete battle data. This is especially useful for analyzing strategies, training AI models, or developing robot programs externally.
replay_[battleId]_[timestamp].json.Each replay file contains comprehensive battle data in JSON format:
The actual thread1/thread2 command structures used by both players - perfect for studying winning strategies!
Frame-by-frame events including game updates, bullet fires, robot hits, and more.
Complete snapshots of robot positions, health, bullets, and obstacles at regular intervals.
Battle configuration including duration, winner, timestamps, game speed, and player information.
{
"metadata": {
"battleId": "abc123",
"battleType": "ai",
"duration": 120000,
"timestamp": "2025-01-21T..."
},
"players": [
{ "name": "MyRobot", "isAI": false },
{ "name": "AI Bot", "isAI": true }
],
"winner": { "name": "MyRobot" },
"programs": [
{
"robotName": "MyRobot",
"program": {
"thread1": [ ... ],
"thread2": [ ... ]
}
}
],
"events": [ ... ],
"frames": [ ... ]
}
For detailed technical documentation on the replay format, including complete schema reference and LLM training workflows, see the Battle Replay Format Documentation.
You can also download the documentation file for offline reference.
programs array to reuse successful patternsevents to understand the flow of battle and identify critical momentsBelow are the supported blocks/commands and how to use them. Some commands also accept variables or computed values via math/variable blocks.
Move the robot by N pixels in the given cardinal direction. Speed limit: 100 pixels per command.
Move the robot forward or backward relative to its current angle by N steps (10 pixels per step). Speed limit: 100 pixels per command.
Move the robot to specific (X, Y) coordinates. Auto-continuing movement at 50px per cycle. Automatically continues until target reached or obstacle hit. No loop required! Params: target_x, target_y (range: -500 to 500).
Move a distance toward an absolute angle. Speed limit: 100 pixels per command. Params: angle (deg), pixels.
Move toward the angle stored in a variable (degrees). Speed limit: 100 pixels per command. Params: variable, pixels.
Pause this thread for N seconds.
move_to_xy uses auto-continuing movement - moves 50px per cycle and automatically repeats until reaching the target. No loop needed!Fire the cannon at the current aim direction. Damage ~20 HP on hit.
Scan for enemies, mines, and turrets within 400px range. Updates multiple system variables (see below).
Instantly aim the cannon to an absolute angle (deg).
Rotate the cannon by N degrees clockwise/counterclockwise.
Aim the cannon using an angle stored in a variable (deg). Param: variable.
The scan command detects enemies, mines, and turrets within a 400-pixel radius and updates these system variables:
enemy_detected - Boolean (true/false)enemy_distance - Distance in pixels to nearest enemyenemy_direction - Direction in degrees to nearest enemymost_recent_enemy_direction - Last known enemy direction (persists after enemy leaves range)previous_enemy_direction - Direction from scan before the most recent onenearest_mine_detected - Boolean (true/false)nearest_mine_distance - Distance in pixels to nearest minenearest_mine_direction - Direction in degrees to nearest minenearest_turret_detected - Boolean (true/false)nearest_turret_distance - Distance in pixels to nearest active turretnearest_turret_direction - Direction in degrees to nearest active turretNote: Only active turrets (health > 0) are detected. Destroyed turrets are ignored.
Repeat nested commands a fixed number of times. Param: count (a.k.a. times).
Repeat nested commands until a condition is met. Params: condition, operator, value, plus nested commands.
Run nested THEN commands if a condition is true. Params: condition (or variable), operator, value.
Run THEN or ELSE nested commands based on a condition. Same parameters as if_then.
Set a variable to a literal value (number/boolean) or a system variable.
Copy the value of one variable to another.
Compute target = source op number. Operators: +, −, ×, ÷.
Apply a math function using variables. Params: targetVariable, mathFunction, sourceVariable.
Functions: sin, cos, tan (input in degrees); arcsin, arccos, arctan (output in degrees); abs, int.
Event handlers are special blocks that run automatically when specific game events occur. They execute independently of Thread 1 and Thread 2.
Event container: runs nested commands when your robot is hit by an enemy bullet. Triggers immediately upon taking damage.
Common uses: Evasive maneuvers, return fire, health monitoring, defensive positioning.
Event container: runs nested commands when your shot successfully hits an enemy robot. Triggers immediately upon confirmed hit.
Common uses: Continue firing, track hit count, aggressive pursuit, celebration.
when_hit and when_i_hit_enemy active simultaneously.Thread 1 (Movement): Thread 2 (Combat): Event: when_hit:
repeat 100 times repeat 100 times // Dodge when hit!
move_forward 100 pixels scan turn_right 90 degrees
if hit_obstacle = true if enemy_detected = true move_forward 80 pixels
then then turn_left 45 degrees
move_backward 50 pixels aim_variable enemy_dir
turn_right 45 degrees fire Event: when_i_hit_enemy:
set hit_obstacle to false wait 0.1 seconds // Keep firing!
wait 0.3 seconds fire
wait 0.1 seconds
fire
In this example, the robot patrols and fires normally, but immediately dodges when hit and continues firing when it lands a hit!
Custom blocks let you define reusable subroutines that can be called from any thread or event handler. This is the fourth execution lane in the system.
Define a named sequence of commands you can reuse. Nested contents become the block's body. The block doesn't execute until called.
Param: blockName - Unique name for your custom block (e.g., "evade_hit", "scan_and_fire")
Execute a previously-defined custom block by name. Can be called from Thread 1, Thread 2, or event handlers.
Param: blockName - Name of the block to execute
Custom Block "evade_hit":
// Back up from obstacle
move_backward 40 pixels
// Try right
turn_right 90 degrees
move_forward 60 pixels
// If still stuck, try left instead
if hit_obstacle = true
then
turn_left 180 degrees
move_forward 60 pixels
// Reset collision flag
set hit_obstacle to false
Thread 1:
repeat 100 times
move_forward 100 pixels
if hit_obstacle = true
then
call my block "evade_hit" // Reuse the evasion logic!
wait 0.2 seconds
Event when_hit:
call my block "evade_hit" // Same evasion when hit by bullet!
Custom Block "scan_and_fire":
scan
if enemy_detected = true
then
aim_variable enemy_direction
fire
wait 0.1 seconds
fire // Double tap!
Thread 2:
repeat 100 times
call my block "scan_and_fire"
wait 0.3 seconds
Event when_i_hit_enemy:
// Hit confirmed! Keep pressure on!
call my block "scan_and_fire"
define_myblock blocks at the top of your programSystem variables are automatically updated by the game engine and can be used in conditionals, math operations, and movement commands.
x_pos - Current X coordinate (-500 to 500, center is 0)y_pos - Current Y coordinate (-500 to 500, center is 0)cannon_angle - Current cannon angle in degrees (0°=East, 90°=North, 180°=West, 270°=South)health - Current health points (0-100)hit_obstacle - Boolean: true if robot collided with wall, obstacle, or turret on last move. Must be manually reset to false! See Using hit_obstacle for details.enemy_detected - Boolean: true if enemy within 400px scan rangeenemy_distance - Distance in pixels to nearest enemy (null if none detected)enemy_direction - Direction in degrees to nearest enemy (null if none detected)most_recent_enemy_direction - Last known enemy direction (persists after enemy leaves range)previous_enemy_direction - Enemy direction from the scan before the most recent onenearest_mine_detected - Boolean: true if mine within 400px scan rangenearest_mine_distance - Distance in pixels to nearest mine (null if none detected)nearest_mine_direction - Direction in degrees to nearest mine (null if none detected)nearest_turret_detected - Boolean: true if active turret within 400px scan rangenearest_turret_distance - Distance in pixels to nearest active turret (null if none detected)nearest_turret_direction - Direction in degrees to nearest active turret (null if none detected)random - Generates a new random value (0.0 to 1.0) each time it is referenced. To use a constant random value throughout a match, store it in a variable at the start: set my_random = randomenemy_detected, hit_obstacle, nearest_mine_detected, nearest_turret_detected) can only be compared to "= true" or "= false" in conditionals.most_recent_enemy_direction to pursue enemies that move out of scan range.Q: My robot doesn’t move.
A: Make sure a Movement block is in Thread 1 or 2 with a non‑zero distance.
Q: My robot keeps missing shots.
A: Use scan to update enemy_direction and aim toward that angle before firing.
Q: The IF condition never triggers.
A: Check the operator and value type (number vs. boolean). For example, enemy_range < 200 uses a numeric value.
Q: My score reset when I started a new level.
A: Each level tracks its own score independently. Your best score for each level is saved to your account.
Q: I can't beat a level.
A: Try different strategies: kiting (hit and run), corner camping, or aggressive rushing. Use the Templates for inspiration.
Q: How do I unlock more levels?
A: Complete the previous level to unlock the next one. Level 1 is always unlocked.
Two quick patterns expressed in blocks: