Pre-COSMOS Day 7, for Cluster 10: Robot Inventors, a 60-minute maze block covered in depth. It teaches while loops as a robot control loop - sense, decide, act, update, stop - built around the core question of what makes this robot stop. Students BUILD the maze controller themselves across four "your turn" levels, each giving a skeleton and the target behavior but no answer; the teacher demo shows only the target behavior; the debug challenges hide the body; and the complete solution is revealed on a single slide at the very end. Every reference trace was run through a real Python grid-maze simulator.
Subject: Python · 62 slides · code lesson
Open the interactive version of this deck · Homework for this lesson
Objectives
This is the heart of the maze challenge: while not at the goal, read the camera and move. Today you build the controller yourself, one level at a time. By the end you can:
1. Read a while loop and name its condition, its update, and what makes it stop.
2. Explain why while not at_goal() fits a robot better than a beginner repeat-this-code loop.
3. Read the camera inside the loop so the robot never acts on a stale sensor.
4. Add a steps < max_steps safety timeout so a bad maze can't trap the robot forever.
5. Debug an infinite loop by asking one question: what value should change to make it stop?
Warm-up
Discussion prompt
Before we open while Loops as Robot Control Loops: without looking back, what was the main idea of Decisions: if / elif / else & Finite-State Thinking, and what could you do by the end of it that you could not do before?
Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.
Answer:
Highly detailed (65 slides, 2+ hours): comparisons and booleans; if/elif/else with first-true-branch-wins and why order matters; and/or/not with the classic 'or green' bug; the == vs = trap; advanced techniques (in, chained comparisons, truthiness, precedence and De Morgan); building the Maze Robot Brain v1; and finite state machines two ways - nested if/elif and table-driven (dictionary dispatch plus a transition table). Eight checks, four traps, an FSM diagram.
Concept
Every loop you write today has to answer one question:
What makes this robot stop?
A loop that can't answer it runs forever. Keep the question in your head for every slide - it is the whole game.
Counterexample
Discussion prompt
Every loop you write today has to answer one question:
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Answer:
A loop that can't answer it runs forever. Keep the question in your head for every slide - it is the whole game.
Concept
A while loop repeats its body as long as a condition is True. Before every pass it checks the condition; the moment the condition is False, it stops.
condition — The True/False test a while loop checks before each pass. While it is True the body runs again; when it turns False the loop ends.
Analogy
Discussion prompt
Explain What a while loop does by analogy to something with no Python in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
A while loop repeats its body as long as a condition is True. Before every pass it checks the condition; the moment the condition is False, it stops.
Estimation
Predict first
Before the robot, here is a tiny while to read - the only finished code we will trace together. Watch the value that changes.
Commit before you compute: what does A first while loop: counting come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.
Correct: Trace each pass
Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. Verified by execution: prints 0, 1, 2, then done.
Worked example
Before the robot, here is a tiny while to read - the only finished code we will trace together. Watch the value that changes.
count = 0
while count < 3:
print(count)
count = count + 1
print("done")Line 4 is the line that makes it stop
Why: count = count + 1 changes the value the condition checks. Without it, count would stay 0 and the loop would run forever.
Trace each pass
Why: Verified by execution: prints 0, 1, 2, then done. When count reaches 3, count < 3 is False and the loop ends.
| pass | count (checked) | prints | count after +1 |
|---|---|---|---|
| 1 | 0 | 0 | 1 |
| 2 | 1 | 1 | 2 |
| 3 | 2 | 2 | 3 |
| stop | 3 | count < 3 is False | - |
Comparison
Comparison matrix
From A first while loop: counting: refill the count (checked) column from what you know. The rest of the table is as it appeared.
| pass | count (checked) | prints | count after +1 |
|---|---|---|---|
| 1 | 0 | 0 | 1 |
| 2 | 1 | 1 | 2 |
| 3 | 2 | 2 | 3 |
| stop | 3 | count < 3 is False | - |
Intuition
Picture a gate you reach again and again. Each time, you ask the condition: still True? If yes, you walk through and do the body; if no, you stop and move on.
Unlike a for loop (which counts through a known list), a while loop runs an unknown number of times - exactly what a robot needs, because it doesn't know in advance how many moves the maze will take.
Explain it
Discussion prompt
Explain A while loop is a question asked before every pass to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
Picture a gate you reach again and again. Each time, you ask the condition: still True? If yes, you walk through and do the body; if no, you stop and move on.
Concept
For a loop to ever stop, something inside the body must change the value the condition checks - moving it toward False.
If nothing inside changes the condition, it stays True forever. That is the definition of an infinite loop - and the single most common bug today.
Concept
A beginner loop like Guess My Number repeats until the player types the right number. The thing that changes is a typed guess.
A robot control loop is different in spirit. Each pass it does five things: sense -> decide -> act -> update -> check. The thing that changes is the robot's own position in the world.
That is why while not at_goal() fits robotics: the robot loops until the world reaches a target state, not until a person types something.
Concept
The simulator gives you four helpers - you just call them. You do not write these today; you only write the loop that uses them.
| helper | what it does |
|---|---|
| look() | SENSE: returns "wall" if the cell ahead is blocked, else "clear" |
| move_forward() | ACT: step one cell in the direction the robot faces |
| turn_right() | ACT: rotate 90 degrees clockwise, staying in place |
| at_goal() | CHECK: returns True when the robot is standing on the goal |
Concept
Here is the tiny maze. # is a wall, . is open, S is the start, G is the goal. The robot begins on S facing east (to the right).
| row \ col | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | # | # | # | # |
| 1 | # | S | # | # |
| 2 | # | . | # | # |
| 3 | # | . | # | # |
| 4 | # | G | # | # |
| 5 | # | # | # | # |
Notice: the robot faces east, but the cell to its east (row 1, col 2) is a wall. So its very first move has to be a turn, not a step.
Trade off
Comparison matrix
From The maze (the map): every row here is a choice with a cost. Fill the 3 column, then say which row you would actually pick and what you give up for it.
| row \ col | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | # | # | # | # |
| 1 | # | S | # | # |
| 2 | # | . | # | # |
| 3 | # | . | # | # |
| 4 | # | G | # | # |
| 5 | # | # | # | # |
Concept
Every pass of the maze controller follows the same five beats - this is the shape you will build, in your own words:
Sense - read the camera. Decide - is it a wall? Act - turn or move. Update - add one to the step counter. Check - the while condition runs again.
Sense and check are what make it a robot loop: it reacts to the world every pass, and it re-asks whether it should keep going.
Concept
Your teacher will run a working controller on the maze so you can see the target. You don't get the code - you get the behavior to aim for.
Watch how the camera, the action, the position, and the step count change each pass:
| loop run | camera | decision | robot at | steps |
|---|---|---|---|---|
| 1 | wall | turn right (now facing south) | (1,1) | 1 |
| 2 | clear | move forward | (2,1) | 2 |
| 3 | clear | move forward | (3,1) | 3 |
| 4 | clear | move forward | (4,1) = goal | 4 |
Four passes, then at_goal() is True and it stops. This is what your controller should do.
Concept
Ask the lesson question about that run: what makes it stop? The answer is the condition - not at_goal(). The robot loops until it stands on the goal.
And the value that changes toward stopping is the robot's position: every move_forward() brings it closer, until at_goal() flips to True.
Concept
One rule before you build: the camera reading must be fresh. Read the camera inside the loop, so the robot senses the cell it is actually facing on this pass.
stale reading — A sensor value read once and then reused. A real robot that acts on a stale reading drives blind - it ignores walls that appeared after it last looked. Read sensors inside the loop.
Definition probe
Sort into buckets
Every line below is part of the definition of condition or of stale reading — one or the other, never both. Put each where it belongs.
Pattern
Predict first
The table runs: start | (1,1) · after run 1 | (1,2) · after run 2 | (1,3)
In Your turn - Level 1: move until a wall, given the rows so far: what is the next one — the row where loop run is after run 3?
Correct: after run 3 | (1,4) - wall ahead, stop
| loop run | the robot should be at |
|---|---|
| start | (1,1) |
| after run 1 | (1,2) |
| after run 2 | (1,3) |
| after run 3 | (1,4) - wall ahead, stop |
Why: The relationship between the columns, not the individual numbers, is what generates the next row. On a clear 3-cell corridor, a correct loop drives forward three times, then stops because look() returns "wall".
Concept
Build it. Make the robot drive forward while the path ahead is clear, and stop the moment it senses a wall. Fill in the blanks - don't peek ahead.
# Tools: look() returns "wall" or "clear"; move_forward()
while ____________: # keep going while the way ahead is clear
____________ # take one step forwardTarget behavior to aim for
Why: On a clear 3-cell corridor, a correct loop drives forward three times, then stops because look() returns "wall".
| loop run | the robot should be at |
|---|---|
| start | (1,1) |
| after run 1 | (1,2) |
| after run 2 | (1,3) |
| after run 3 | (1,4) - wall ahead, stop |
Fill the middle
Fill in the blanks
From Your turn - Level 2: turn when blocked — one line has had its right-hand side removed. Put it back.
# inside your loop:
camera = ____________ # sense (fresh, every pass)
if ___: # is the way blocked?
turn_right()
else:
move_forward()
Why: camera is what everything below it consumes, so the wrong expression here fails later and somewhere else. Each pass, the camera decides the single action: a wall means turn, a clear cell means move.
Concept
Build it. A robot that only moves forward crashes at the first wall. Add a decision inside the loop - a nested if - so it turns instead. Fill in the blanks.
# inside your loop:
camera = ____________ # sense (fresh, every pass)
if ____________: # is the way blocked?
turn_right()
else:
move_forward()Target behavior to aim for
Why: Each pass, the camera decides the single action: a wall means turn, a clear cell means move.
| camera | your code should |
|---|---|
| wall | turn_right() |
| clear | move_forward() |
Pattern
Predict first
The table runs: 1 | wall | (1,1) turned · 2 | clear | (2,1) · 3 | clear | (3,1)
In Your turn - Level 3: stop at the goal, given the rows so far: what is the next one — the row where loop run is 4?
Correct: 4 | clear | (4,1) = goal, stop
| loop run | camera | robot at |
|---|---|---|
| 1 | wall | (1,1) turned |
| 2 | clear | (2,1) |
| 3 | clear | (3,1) |
| 4 | clear | (4,1) = goal, stop |
Why: The relationship between the columns, not the individual numbers, is what generates the next row. On the maze, a correct Level 3 loop turns once, then moves down to the goal - four passes, matching the demo run.
Concept
Build it. Give the loop a real reason to end: keep going until the robot reaches the goal. The new part is the condition - reuse your sense-decide-act body from Levels 1 and 2.
# Tool: at_goal() is True when the robot is on the goal.
while ____________: # loop UNTIL at the goal
# your sense -> decide -> act body from Levels 1 and 2 goes hereTarget behavior to aim for
Why: On the maze, a correct Level 3 loop turns once, then moves down to the goal - four passes, matching the demo run.
| loop run | camera | robot at |
|---|---|---|
| 1 | wall | (1,1) turned |
| 2 | clear | (2,1) |
| 3 | clear | (3,1) |
| 4 | clear | (4,1) = goal, stop |
Comparison
Comparison matrix
From Your turn - Level 3: stop at the goal: refill the camera column from what you know. The rest of the table is as it appeared.
| loop run | camera | robot at |
|---|---|---|
| 1 | wall | (1,1) turned |
| 2 | clear | (2,1) |
| 3 | clear | (3,1) |
| 4 | clear | (4,1) = goal, stop |
Fill the middle
Fill in the blanks
From Your turn - Level 4: add the safety stop — one line has had its right-hand side removed. Put it back.
steps = ____ # start the counter
while ___ and ___: # not at goal AND under the limit
# your sense -> decide -> act body
___ # update the counter each pass
Why: steps is what everything below it consumes, so the wrong expression here fails later and somewhere else. Now the loop has two ways to stop.
Concept
Build it. A maze with no path would make Level 3 loop forever. Add a step counter and a limit, so the loop stops for either reason: it reached the goal, OR it tried too many times.
steps = ____ # start the counter
while ____________ and ____________: # not at goal AND under the limit
# your sense -> decide -> act body
____________ # update the counter each passTarget behavior to aim for
Why: Now the loop has two ways to stop. On a solvable maze it still reaches the goal; on a bad maze it stops at the limit instead of forever.
| the loop now stops when | because |
|---|---|
| it reaches the goal | at_goal() becomes True |
| OR it runs too long | steps reaches max_steps |
Concept
While you build Level 4, mind the count. With steps starting at 0, while steps < N runs for steps = 0, 1, ..., N-1.
So steps < 20 runs exactly 20 times. Using < gives a clean count; the trap is using <=, which sneaks in one extra pass.
Concept
steps = steps + 1 is small, but it is the off-switch for the safety timeout. It is the value that moves the condition toward False.
When you read any loop, find this line. If you can't point to the thing that changes the condition, the loop probably never stops.
Explain it
Discussion prompt
Explain The update line is the off-switch to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
steps = steps + 1 is small, but it is the off-switch for the safety timeout. It is the value that moves the condition toward False.
Concept
Level 4's condition is not at_goal() and steps < max_steps. and means both must be True to keep going.
So there are two ways to stop: the robot arrives (success), or it runs out of steps (timeout). Either one failing ends the loop.
Analogy
Discussion prompt
Explain Two ways to stop, joined by and by analogy to something with no Python in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
Level 4's condition is not at_goal() and steps < max_steps. and means both must be True to keep going.
Concept
Every run finishes in one of three states - and your finished controller should handle all three:
| failure mode | what happened | what stopped it |
|---|---|---|
| goal reached | the robot arrived | at_goal() became True |
| stuck | no path exists; it spins | steps hit max_steps (timeout) |
| timeout | ran out of moves | steps hit max_steps |
Without max_steps, 'stuck' would become 'forever'. The counter turns an infinite loop into a clean, reportable failure.
Counterexample
Discussion prompt
Every run finishes in one of three states - and your finished controller should handle all three:
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Answer:
Without max_steps, 'stuck' would become 'forever'. The counter turns an infinite loop into a clean, reportable failure.
Anomaly
Predict first
A student writes this, and it looks reasonable:
This controller reads the camera in the wrong place. What goes wrong?
It is wrong. Say what breaks — and say it before you turn the page.
Correct: If the first look() was "wall", the robot turns every single pass and never moves.
The fix: move the reading inside the loop.
Why: If the first look() was "wall", the robot turns every single pass and never moves. A stale sensor can't react to the maze.
Trap
This controller reads the camera in the wrong place. What goes wrong?
camera = look() # read ONCE, before the loop
while not at_goal() and steps < max_steps:
# ... decide & act using camera ...
steps = steps + 1camera never updates - it is frozen at the first reading
Why: If the first look() was "wall", the robot turns every single pass and never moves. A stale sensor can't react to the maze.
| camera value | every pass does |
|---|---|
| "wall" (read once) | the same thing, forever |
The fix: move the reading inside the loop.
while not at_goal() and steps < max_steps:
camera = look() # FIX: read fresh, every pass
# ... decide & act ...
steps = steps + 1A fresh reading each pass
Why: Now the robot senses its current cell every iteration, so it turns at real walls and moves through real openings.
| loop run | camera (fresh) | decision |
|---|---|---|
| 1 | wall | turn right |
| 2 | clear | move forward |
Error analysis
Annotate
Walk the callouts on Debug challenge: a stale sensor. Each one is a place this is easy to get subtly wrong.
Anomaly
Predict first
A student writes this, and it looks reasonable:
You want at most 20 passes. Does this give 20?
It is wrong. Say what breaks — and say it before you turn the page.
Correct: steps takes the values 0, 1, ..., 20 - that is 21 passes, not 20.
Use < for an exact cap.
Why: steps takes the values 0, 1, ..., 20 - that is 21 passes, not 20. <= includes the limit itself.
Trap
You want at most 20 passes. Does this give 20?
steps = 0
while steps <= 20:
# ... act ...
steps = steps + 1<= runs one too many
Why: steps takes the values 0, 1, ..., 20 - that is 21 passes, not 20. <= includes the limit itself.
| condition | steps values | passes |
|---|---|---|
| steps <= 20 | 0 to 20 | 21 (one too many) |
Use < for an exact cap.
steps = 0
while steps < 20:
# ... act ...
steps = steps + 1< gives exactly the count you want
Why: steps takes 0 through 19 - exactly 20 passes. For a cap of N passes from a 0-start counter, use steps < N.
| condition | steps values | passes |
|---|---|---|
| steps < 20 | 0 to 19 | 20 (exactly) |
Anomaly
Predict first
A student writes this, and it looks reasonable:
The robot is boxed in (no path to the goal), and one line is missing. What happens?
It is wrong. Say what breaks — and say it before you turn the page.
Correct: steps stays 0 forever, so steps < max_steps is always True; the boxed-in robot is never at_goal() either.
Add the update so the counter climbs to the cap.
Why: steps stays 0 forever, so steps < max_steps is always True; the boxed-in robot is never at_goal() either. Both parts stay True - an infinite loop.
Trap
The robot is boxed in (no path to the goal), and one line is missing. What happens?
steps = 0
while not at_goal() and steps < max_steps:
# ... sense, decide, act ...
# (nothing changes steps!)Nothing changes the condition, so it never stops
Why: steps stays 0 forever, so steps < max_steps is always True; the boxed-in robot is never at_goal() either. Both parts stay True - an infinite loop.
| steps each pass | loop |
|---|---|
| 0, 0, 0, ... | never stops |
Add the update so the counter climbs to the cap.
while not at_goal() and steps < max_steps:
# ... sense, decide, act ...
steps = steps + 1 # FIX: the off-switchThe counter reaches the cap and stops the robot
Why: Now steps climbs 1, 2, 3, ... until steps < max_steps is False. A boxed-in robot stops at the timeout instead of looping forever.
| steps each pass | loop |
|---|---|
| 1, 2, 3, ... | stops (timeout safety) |
Error analysis
Annotate
Walk the callouts on Debug challenge: the missing update. Each one is a place this is easy to get subtly wrong.
Anomaly
Predict first
A student writes this, and it looks reasonable:
This loop has the condition backwards. What does the robot do?
It is wrong. Say what breaks — and say it before you turn the page.
Correct: If the robot is not yet at the goal, at_goal() is False, so the body never runs - the robot never moves.
Loop until the goal: add not.
Why: If the robot is not yet at the goal, at_goal() is False, so the body never runs - the robot never moves. The 'not' is missing.
Trap
This loop has the condition backwards. What does the robot do?
while at_goal():
# ... sense, decide, act ...
steps = steps + 1It loops only while ALREADY at the goal
Why: If the robot is not yet at the goal, at_goal() is False, so the body never runs - the robot never moves. The 'not' is missing.
| start state | at_goal() | loop runs? |
|---|---|---|
| not at goal | False | 0 times - frozen |
Loop until the goal: add not.
while not at_goal():
# ... sense, decide, act ...
steps = steps + 1not at_goal() is True while there is still distance to cover
Why: Now the robot keeps going until it arrives. Read it out loud: 'while NOT at the goal, sense and move.'
| start state | not at_goal() | loop runs? |
|---|---|---|
| not at goal | True | keeps going until arrival |
Two truths and a lie
Sort into buckets
Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.
while loop repeats its body as long as a condition is True. Before every pass it checks the condition; the moment the condition is False, it stops.; Picture a gate you reach again and again. Each time, you ask the condition: still True? If yes, you walk through and do the body; if no, you stop and move on.Pattern
1. Write the stop condition first
Why: not at_goal() and steps < max_steps. Two ways to stop: success, or a safety timeout.
2. Sense inside the loop
Why: camera = look() on every pass, so the reading is always fresh - never a stale sensor.
3. Decide, then act
Why: An if on the camera chooses turn_right() or move_forward(). One action per pass.
4. Update the counter
Why: steps = steps + 1 - the off-switch for the timeout. Forget it and the loop can run forever.
5. Ask: what makes this stop?
Why: Point to the value that changes (position, or steps). If you can't, the loop has no off-switch yet.
Real world
Discussion prompt
Outside this lesson: where does while Loops as Robot Control Loops actually turn up? Name one concrete situation — a job, a piece of software someone ships, a decision somebody has to make — and say which part of The robot control-loop recipe is doing the work in it.
Hint: Vague is the failure mode here. "Engineering" is not a situation; "deciding whether this build is fast enough to ship" is.
Answer:
Pre-COSMOS Day 7 (Cluster 10: Robot Inventors), 60-minute maze block, in depth. while loops taught as a robot control loop - sense, decide, act, update, stop - around the core question: what makes this robot stop?
Check
The robot starts already standing on the goal.
steps = 0
while not at_goal() and steps < 20:
# ... sense, decide, act ...
steps = steps + 1
print(steps)| start | at_goal() | steps printed |
|---|---|---|
| on the goal | ? | ? |
Check your understanding
What does this print?
Answer: A
Why: A while loop checks its condition BEFORE each pass. The robot is already on the goal, so at_goal() is True, not at_goal() is False, and the body never runs. steps stays 0 and it prints 0. Verified by the simulator.
Check
Clear straight path, the goal is 3 cells ahead, no walls in the way.
steps = 0
while not at_goal() and steps < 20:
# ... sense; move forward when clear ...
steps = steps + 1| each run | robot |
|---|---|
| clear | moves forward one cell |
Check your understanding
How many times does the loop run?
Answer: A
Why: Each pass sees a clear camera and moves forward one cell. After 3 moves the robot is on the goal, at_goal() becomes True, and the loop stops - well before the cap of 20. Verified.
Check
This maze needs 4 loop runs to reach the goal, but max_steps is 3.
steps = 0
while not at_goal() and steps < 3:
# ... sense, decide, act ...
steps = steps + 1| max_steps | runs | reached goal? |
|---|---|---|
| 3 | ? | ? |
Check your understanding
What happens?
Answer: A
Why: steps < 3 lets steps reach 1, 2, 3 - exactly 3 passes. The goal needs 4, so the safety cap stops the robot one move short, at a timeout. That is the off-by-one: a cap of 3 leaves no room for the 4th move. Verified by the simulator.
Check
The camera is read once, before the loop, and that first reading is "wall".
camera = look()
while not at_goal() and steps < max_steps:
# ... decide & act using camera ...
steps = steps + 1| camera | each pass |
|---|---|
| "wall" | ? |
Check your understanding
What does the robot do on each pass?
Answer: A
Why: camera is read only once, outside the loop, so its value never changes. It stays "wall" for every pass, and the robot turns right again and again without ever sensing that the way might now be clear. The fix is to read look() inside the loop. Verified.
Check
The robot is boxed in (it can never reach the goal), and the steps update line is missing.
steps = 0
while not at_goal() and steps < max_steps:
# ... sense, decide, act ...
# (no steps update)| steps each pass | loop |
|---|---|
| ? | ? |
Check your understanding
What happens?
Answer: A
Why: Without steps = steps + 1, steps stays 0, so steps < max_steps is always True. The robot is boxed in, so at_goal() is always False too. Neither part of the condition ever changes, so the loop runs forever. The fix: update the value that is supposed to make the loop stop. Verified.
Check
Look closely at the two-part condition.
while not at_goal() and steps < max_steps:
# ... sense, decide, act ...
steps = steps + 1| condition part | keeps looping while |
|---|---|
| not at_goal() | not yet arrived |
| steps < max_steps | under the cap |
Check your understanding
When does this loop KEEP going?
Answer: A
Why: and requires both sides to be True. The loop continues only while the robot is not yet at the goal AND still under the cap. The moment either fails - it arrives, or steps hits max_steps - the loop stops. That gives two ways to stop: success or timeout. Verified.
Trade off
Comparison matrix
From Check: reading the and condition: every row here is a choice with a cost. Fill the keeps looping while column, then say which row you would actually pick and what you give up for it.
| condition part | keeps looping while |
|---|---|
| not at_goal() | not yet arrived |
| steps < max_steps | under the cap |
Estimation
Predict first
Now compare your build to the finished controller. If yours produces the same behavior, the code can look a little different - that's fine.
Commit before you compute: what does The answer: the complete controller come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.
Correct: Run it on the maze (real simulator output)
Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. Verified against the grid-maze simulator: 4 passes, then at_goal() is True and the loop stops.
Worked example
Now compare your build to the finished controller. If yours produces the same behavior, the code can look a little different - that's fine.
steps = 0
while not at_goal() and steps < max_steps:
camera = look()
if camera == "wall":
turn_right()
else:
move_forward()
steps = steps + 1Every piece you built, assembled
Why: The stop condition (Level 3 + 4), the fresh sense, the decide/act (Levels 1-2), and the counter update - all five beats of the control loop in eight lines.
Run it on the maze (real simulator output)
Why: Verified against the grid-maze simulator: 4 passes, then at_goal() is True and the loop stops. The safety cap is never hit because the robot succeeds first.
| loop run | camera | decision | robot at | steps |
|---|---|---|---|---|
| 1 | wall | turn right (now facing south) | (1,1) | 1 |
| 2 | clear | move forward | (2,1) | 2 |
| 3 | clear | move forward | (3,1) | 3 |
| 4 | clear | move forward | (4,1) = goal | 4 |
Comparison
Comparison matrix
From The answer: the complete controller: refill the steps column from what you know. The rest of the table is as it appeared.
| loop run | camera | decision | robot at | steps |
|---|---|---|---|---|
| 1 | wall | turn right (now facing south) | (1,1) | 1 |
| 2 | clear | move forward | (2,1) | 2 |
| 3 | clear | move forward | (3,1) | 3 |
| 4 | clear | move forward | (4,1) = goal | 4 |
Connect it up
Draw it
One page, no notation unless you need it: draw how these connect — The robot control-loop recipe · The one question for the whole lesson · What a while loop does · A while loop is a question asked before every pass · The one rule: something inside must change. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.
Recap
You built a robot control loop: sense -> decide -> act -> update -> check, stopping the moment its condition fails. For every loop, ask the one question: what value changes to make this stop?
| Idea | In your controller | Why it matters |
|---|---|---|
| stop condition | not at_goal() and steps < max_steps | two ways to stop: success or timeout |
| sense each pass | camera = look() inside the loop | fresh readings, never stale |
| the update | steps = steps + 1 | the off-switch - without it, forever |
| off-by-one | steps < 20 runs exactly 20 | < counts exactly; <= runs one extra |
| failure modes | goal / stuck / timeout | max_steps turns 'forever' into 'stuck' |
So why while not at_goal() and not Guess My Number? Because a robot loops until the world reaches a target, sensing and acting every pass - and a safety counter guarantees it always stops.
Want this taught 1-on-1? Alexander tutors Python — $55/session, free consultation.