Distance sensors — 7 of them, in cm (smaller = closer, max 200)
frontleftfrontfrontright
▲ the robot faces this way
leftfrontright
backleftfrontbackright
How to write an "if" (indent inside with 4 spaces)
wheelleft = 25
wheelright = 25
if front < 55:
wheelleft = 25
wheelright = -25
elif frontleft < 35:
wheelleft = 25
wheelright = 8
else:
wheelleft = 25
wheelright = 25
How to work on your code
1. Open the ☰ menu (top left) and press Base code .py to get the starting code
2. Open the downloaded file in VS Code (or any editor) and change it
3. Come back, press Load .py, pick your file — the row shows the file name
4. Press Start Match
Bumper — the ring around the robot
The distance sensors tell you what is near. The bumper tells you what you are already touching — a wall, furniture, the cat, the dog or the rival robot.
bumper == 1 | something is touching me right now — back off! |
bumper == 0 | nothing is touching me |
Watch out — a cat AND a dog live in the house
A cat and a (bigger, faster) dog wander around the rooms and stop for a rest now and then. Your distance sensors see them exactly like walls, and you cannot push them out of the way — you have to go around them. They move, so a path that was clear a second ago may not be clear now.
Colour sensor — at the nose, reading the floor just ahead
color tells you the colour of the floor right in front of the robot's nose. (Not under its centre — a tile is cleaned the instant you touch it, so under the centre you would always see your own colour.) Compare it with these names:
color == white | white — floor ahead not cleaned yet, this is where the points are |
color == red | red — floor ahead was cleaned by the red robot |
color == blue | blue — floor ahead was cleaned by the blue robot |
color == green | green — the BIG rug is ahead: half speed and no points |
color == purple | purple — a DOORWAY MARKER rug is ahead (so are orange and cyan): no points on it, but drive straight over it — turning back here means never entering the room |
color == black | black — a wall or furniture is right ahead |
Turn on Sensors in the ☰ menu and a panel appears at the bottom of the screen showing both robots live: every distance sensor, the bumper, the colour name, wheel speeds, timer and state — so you can watch exactly what your code is reacting to.
if color == green: # on the rug - slow and worthless, turn away
timer = 5
wheelleft = -10
wheelright = -10
elif color == red: # red already cleaned this - go find white floor
timer = 2
wheelleft = 25
wheelright = -25
else: # white floor under me - full speed ahead
wheelleft = 25
wheelright = 25
Easy moves — one call does the whole move
backward(5) | drive backward for exactly 5 seconds |
forward(2) | drive forward for 2 seconds |
turnleft(1) , turnright(1) | spin in place for 1 second |
stop(2) | stand still for 2 seconds |
No timer, no state — the move keeps itself going and then your normal code takes over again. While a move is running, new move calls are ignored.
if color == green: # the rug is ahead
backward(5) # -> reverse for 5 seconds. That's it!
Variable style — movetime: set the wheels yourself, then say how long to hold them. The countdown runs by itself:
if color == green:
wheelleft = -25
wheelright = -25
movetime = seconds(10) # keep these wheels for exactly 10 s
Timer — how long a move lasts (or just use seconds)
The easiest way: timer = seconds(10) keeps the move going for exactly 10 seconds. Or count steps yourself — 10 steps = 1 second.
⚠ timer does nothing by itself! It only works together with the if timer > 0: block at the top of your logic — that block reads the countdown and keeps the move going. In the base code you must also set state so the block knows which move to continue (2 = reverse).
Your code runs 10 times every second. timer keeps its value between runs, so counting it down is how you say how far the robot reverses or turns.
timer = 10 | the move lasts 1 second |
timer = 5 | half a second |
timer = 3 | 0.3 second (a short turn) |
timer = 20 | 2 seconds (a long reverse) |
if timer > 0: # still busy with the last move
timer -= 1
wheelleft = -25 # reverse for as long as the timer runs
wheelright = -25
elif front < 75: # obstacle ahead - reverse for 1 full second
timer = 10
state is a second free memory value you can use the same way. Both start at 0.
Info variables (read only)
x, y | robot position in cm — see the GPS section below |
heading | direction it faces, degrees 0..360 (0 = right, 90 = up) |
mytiles | tiles you own right now |
rivaltiles | tiles the rival owns right now |
timeleft | seconds remaining |
Position (GPS) — go from point A to point B
The robot always knows where it is. The map is a grid of centimetres:
the BOTTOM-LEFT corner is (0, 0), x grows to the right and
y grows up — on the standard map the far corner is (1000, 1000)
and the centre is (500, 500). heading says which way you face:
0 = right, 90 = up, 180 = left, 270 = down.
goto(500, 500) | drive to that point — the robot turns, then follows the straight line there all by itself and stops |
atgoal | 1 the moment a goto arrives, 0 while still driving |
distto(500, 500) | straight-line distance from you to that point, in cm |
angleto(500, 500) | the compass direction to that point (compare with heading) |
stopgoto() | cancel the current goto and take the wheels back |
⚠ goto is not magic: it drives the straight line — it does NOT dodge
furniture, walls, the cat or the dog. Watch the sensors and the bumper while it drives, and
stopgoto() + back off when something blocks the way.
# patrol the four corners, forever
if state == 0: # runs once at the start
goto(150, 150)
state = 1
elif atgoal == 1: # reached the last target -> pick the next corner
state = state + 1
if state == 2:
goto(150, 850)
elif state == 3:
goto(850, 850)
elif state == 4:
goto(850, 150)
else:
state = 1
goto(150, 150)
if bumper == 1: # something is in the way - goto will not dodge it!
stopgoto()
backward(1)
⚡ U19 — battery and the charging station
In the U19 league the robot is not plugged into anything: it runs on a
battery. It starts the match at 100 %, which is about 60 seconds of
full-throttle driving (idling costs much less). To refill it you drive onto the
charging station — the lit pad with the lightning bolt — and sit on it:
it puts back 25 % per second, so a full refill from empty takes 4 seconds.
The station has a fixed home by the east shelf — the same spot every match,
like a real dock. Its coordinates are still sent to both robots at the start:
battery | how much charge is left, 0–100 |
dockx , docky | the station's position in cm, in the same (0,0)-bottom-left grid as x / y. Both are -1 in FS and U14 (there is no station). |
🗑 The dust bin — switched OFF this season. The emptying
station is not placed in the competition houses, so the bin never fills and dumpx /
dumpy read -1. The rule below is kept for the day it is turned back on.
U19, ONE player only. A real robot cannot
clean a whole house on one bin-load. Yours holds 30 tiles: fill it and the robot
cleans nothing at all — it drives on, the floor stays dirty, the score stops — until it
reaches the emptying station, which is its own machine, nowhere near the charging pad.
Two errands, two trips, and it is your code that has to fit them both into three minutes.
In a two-player match the bin never fills; reaching the station once is simply worth +5.
dust | how many tiles are in the bin right now, 0–30 |
dustmax | how many it holds — 30, or 0 when the rule is off |
dustfull | 1 when it is full and nothing counts any more |
dumpx , dumpy | where the emptying station is, in cm. Both -1 unless the rule is on. |
# empty the bin before it costs you a lap of the house
if dust > 24 and state == 0:
state = 1
goto(dumpx, dumpy) # the station's coordinates arrive as variables
if state == 1 and dustfull == 0 and dust == 0:
state = 0 # emptied — back to cleaning
An empty battery does not kill the robot — it LIMPS — at 0% it keeps
going at 15 % speed, so it can still drag itself to the pad. That crawl is the punishment: half a
house at a crawl costs you most of the match while the rival keeps working. The whole game is deciding
when to break off and charge, early enough that you never crawl.
# go charge when the battery gets low, then go back to work
if battery < 30 and state == 0:
state = 1
goto(dockx, docky) # the pad's coordinates arrive as variables
if state == 1 and battery > 95: # full again -> back to cleaning
state = 0
stopgoto()
if state == 0: # normal cleaning code
wheelleft = 25
wheelright = 25
if bumper == 1: # goto does not dodge - help it
stopgoto()
backward(1)
state = 0
The referee and the pad: standing still normally gets you relocated after
15 seconds, but not while you are charging — the watchdog is paused as long as you are on the pad and
the battery is still climbing. The moment it hits 100 % the normal rule is back, so camping on the pad
is not a strategy: charge, then leave.
A neat trick: distto(dockx, docky) tells you how far the pad is.
The robot uses roughly 1.7 % of battery per second at full speed and covers about 60 cm
in that second — so leave yourself a margin of at least
distto(dockx, docky) / 30 percent of charge — plus a fat margin, because at 0% the robot does not die — it crawls at 15 % speed, and a crawl across the house costs more than the detour would have.
🦯 Assistive Technology — guiding a person
In this league you are not cleaning: you are leading a person from one destination
to the next. They walk behind you, slower than you can drive, and every so often they simply
stop. Your rear sensors are how you find that out — that is where they are.
backleft , backright | the person is back there; the reading grows the moment they fall behind |
personback | the same thing without the geometry: distance to them in cm. About 60–70 is comfortable, over 110 they are dropping back |
personwait | 1 when they have lost you completely and stopped to wait |
goalx , goaly | where they want to go (FS and U14) |
goalname | WHICH room they asked for — compare with kitchen, door, sofa, bedroom, window, table |
roomx(kitchen) , roomy(kitchen) | ask the house for a room's address (U19, where goalx is -1) |
goalsleft | destinations still to deliver |
The match is a TOUR: seat them on the sofa, take them to the kitchen, put them to bed — and then finish the chores alone (asleep == 1, goalkind == 2) while they sleep. Use gotoslow(x, y) to lead at walking pace, and mind the doorways: rooms have walls. Fast is not the goal. The score is:
+30 for arriving with the person, +20 for a chore finished alone while they sleep, −6 every time they walk into furniture,
−100 when they FALL (walk further than ~1.6 m and they go down; the referee's autopilot takes your wheels, drives you back, and a 3-2-1 runs while they get up — then your code continues the tour), and a small penalty for violent swerves —
spinning the wheels in opposite directions at speed is a nasty jolt for someone holding on.
# stop the moment they stop
if personwait == 1: # they lost me -> reverse gently until they are close
wheelleft = -9
wheelright = -9
elif personback > 110: # dropping back -> wait for them
wheelleft = 0
wheelright = 0
else: # lead the way, at walking pace, turning gently
wheelleft = 13
wheelright = 13
🥌 Sumo — push them off the platform
A round platform with no walls. Shove the rival off and the round is yours;
drive off yourself and you hand it to them. First to three rounds wins the match
(five in U19). Out there a distance sensor sees nothing but the rival — so any reading
under 200 is the rival.
cliff1 … cliff4 | 1 = no floor under that edge sensor. The most important number in the league. |
edge | cm of platform between you and the drop |
arenax , arenay , arenar | the middle of the platform and how big it is, in cm |
rivalx , rivaly , rivaldist | where the rival is (needs the position sensor) |
impact | 1 while the rival is leaning on you |
round , roundswon , roundslost , resetting | the state of the bout; resetting = 1 between rounds |
Pushing: whoever drives harder into the contact
stands still and the other one slides back. So "push" just means: face them squarely and go to
full throttle. Hitting at an angle loses to hitting straight on.
Never spin on the spot to look for them. Against a robot
doing the same thing you turn together and neither of you ever ends up facing the other. Turn
and drive — a pursuit curve always closes. And nose to nose you push each other nowhere:
break off after a couple of seconds and come back in from the side.
A round that neither robot wins is called after 30 s and
restarted from a new angle. In U14 and U19 the platform also shrinks as the match goes on.
# the order matters: the edge beats everything else
if cliff1 == 1: # no floor in FRONT
wheelleft = -25
wheelright = -25
elif impact == 1 or front < 45: # I am on them -> straight, full power
wheelleft = 25
wheelright = 25
else: # turn AND drive toward them
goto(rivalx, rivaly)
🚒 Firefighter — find it, reach it, hold the spray
Fires break out around the house and grow; a full-grown fire spreads.
Park within 60 cm of a flame and hold still: 2 full seconds of standing your ground
puts it out — break off and the water starts over. The smaller the fire when it dies, the more it pays.
firex , firey , firedist | the nearest burning fire — broadcast to everyone like a smoke alarm (-1 when nothing burns) |
firesize | 0–100, how big it has grown |
spraying | 1 while you are in range and the water is on |
heatdir , heatdist | the flame sensor: which way the fire is relative to your nose (+ = left) and how far. The part real firefighting-contest robots carry. |
firesactive , firesout | fires burning right now · fires you have put out |
🤖 Your robot comes READY-MADE
Nobody builds a robot in this league — every team drives the same
fully-equipped machine: distance sensors all around, bumper, colour sensor,
compass and position. The only thing you choose is the team colour; the
match is decided purely by the code you write.
Turn on Sensors in the ☰ menu during a match and each
robot gets its own window: a little radar showing every sensor with its live reading.
Memory — kept between steps, start at 0
timer and state are yours to use. Every other variable is refreshed each step, but these two keep whatever you put in them.
Wheels — set these, from -25 to 25
wheelleft = 25 , wheelright = 25 | go forward (full speed) |
12 , 12 | go forward at half speed |
-25 , -25 | go backward |
25 , -25 | turn right (in place) |
-25 , 25 | turn left (in place) |
25 , 10 | curve gently to the right while moving |
Bigger number = faster. 25 is the maximum, -25 the minimum.
Match rules
| Scoring | last touch wins — drive over a tile and it becomes yours, even if the rival cleaned it first |
| The rug | green, half speed, gives no points and cannot be cleaned |
| Stuck for 15 s | the referee's system moves you to a random tile at least 6 tiles away and the fine climbs: −5, then −10, then −12 tiles |
| Referee controls | in the ☰ menu (top left): Relocate (the same climbing fine), Stop, End Game, and 2x game speed |
| A draw | goes to overtime: +10 seconds, then +5 seconds each time until someone leads |
Supported Python
if / elif / else, while, comparisons (< > == !=), and / or / not, math (+ - * / % // **), parentheses, and the functions abs, min, max, int, float, round, seconds, the easy moves forward, backward, turnleft, turnright, stop and the GPS family goto, distto, angleto, stopgoto.
Indent the lines inside an if with 4 spaces. If your code has a mistake you get the line number before the match starts.