The Robot Control Loop (sense, decide, act, wait)

Lesson 3 of 8 in the Pre-COSMOS series, 40 slides, on the shape of every robot program. A robot runs the same heartbeat forever - sense, decide, act, wait - and this lesson names that pattern and builds it. time.sleep(seconds) supplies the wait. The decide step is a finite-state-machine dictionary, next_state = {"sense":"decide", "decide":"act", "act":"wait", "wait":"sense"}, advanced with state = next_state[state]. You then put it together from a provided Rover, the loop, and the dictionary, using a BOUNDED loop - range(8), or while rover.energy > 0 - so that the demo terminates. The lesson points out that this quietly reuses loops, a function, a dictionary lookup, and the class from Lessons 1 and 2, all at once. The three traps are the classic FSM bugs: while True with no exit, which loops forever; forgetting state = next_state[state], which sticks you in one state; and a typo in a state name that is not in the dictionary, which raises a KeyError. There are five checks and a scaffolded your-turn Maze Rover Simulator control loop. Every snippet was run on CPython 3.12, with the outputs copied verbatim.

Subject: Python · 70 slides · code lesson

Open the interactive version of this deck · Homework for this lesson

What this lesson covers

The lesson, slide by slide

1. The Robot Control Loop

Title

Pre-COSMOS · Lesson 3 of 8

Every robot program has the same heartbeat: sense, decide, act, wait - forever. Today you name that shape and build it from parts you already know.

2. What you will be able to do

Objectives

A robot doesn't run once and stop - it runs the same four steps over and over. That repeating shape is the control loop. By the end you can:

3. What survived from Objects, Part 2: Write Your Own Class?

Warm-up

Discussion prompt

Before we open The Robot Control Loop (sense, decide, act, wait): without looking back, what was the main idea of Objects, Part 2: Write Your Own Class, 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:

Pre-COSMOS Lesson 2 of 8 (41 slides): the leap from USING a provided Rover to WRITING the class yourself - the heaviest new lift of the eight. Built concrete and tiny across five ideas: class Rover defines a new TYPE (a blueprint) while an instance is one rover built from it; __init__(self, name) is the setup method that runs automatically when you make one and stores starting attributes via self.name=...

4. A robot's heartbeat

Concept

Figure (svg): Four boxes labeled sense, decide, act, wait arranged in a circle with arrows pointing from each to the next and back to sense, showing a loop that repeats forever.

Round and round, forever.

A robot is never 'done'. While it's on, it keeps cycling through the same four steps:

  1. sense - look at the world (a sensor reading).
  2. decide - pick what to do next.
  3. act - do it (move, turn, grab).
  4. wait - pause a moment, then start over.

Then it goes back to sense. That circle is the whole program - everything else just fills in the steps.

5. Break it if you can: A robot's heartbeat

Counterexample

Discussion prompt

A robot is never 'done'. While it's on, it keeps cycling through the same four steps:

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.

6. Today's roadmap

Concept

Four stops, each a piece of the same loop:

The loop
sense -> decide -> act -> wait.
The wait
time.sleep(seconds).
The decide
A next_state dictionary.
Put it together
Rover + loop + dict.

7. The Shape of Every Robot Program

Section

Section 1

8. What a control loop is

Concept

control loop — The repeating heartbeat of a robot: sense the world, decide what to do, act on it, wait a moment, then repeat - forever, or until something tells it to stop.

You already know the tool that repeats things: a loop. The control loop is just a while (or for) loop whose body runs those four steps in order, again and again.

9. By analogy: What a control loop is

Analogy

Discussion prompt

Explain What a control loop is 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:

You already know the tool that repeats things: a loop. The control loop is just a while (or for) loop whose body runs those four steps in order, again and again.

10. It's like brushing your teeth

Intuition

You don't run your whole life in one straight line. You wake, decide, do, rest - then repeat tomorrow. A robot's loop is that, but every fraction of a second.

The point of naming the loop is this: once you know the shape, every robot program looks the same. You just fill in what sense, decide, and act mean for this robot.

11. Teach it back: It's like brushing your teeth

Explain it

Discussion prompt

Explain It's like brushing your teeth 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:

You don't run your whole life in one straight line. You wake, decide, do, rest - then repeat tomorrow. A robot's loop is that, but every fraction of a second.

12. The loop skeleton (bounded so it stops)

Worked example

Here is the bare shape. We use for step in range(8) so it runs a fixed number of ticks and terminates - perfect for a demo.

for step in range(8):
    # sense
    # decide
    # act
    # wait
    print("tick", step)

Each pass through the body is one tick of the robot's heartbeat. Eight ticks, then it ends.

stepprints
0tick 0
1tick 1
2tick 2
...(through tick 7)
7tick 7

13. Fill in: prints for The loop skeleton (bounded so it stops)

Comparison

Comparison matrix

From The loop skeleton (bounded so it stops): refill the prints column from what you know. The rest of the table is as it appeared.

stepprints
0tick 0
1tick 1
2tick 2
...(through tick 7)
7tick 7

14. Rebuild the recipe: The control-loop recipe

Ranking

Put in order

These are the steps of The control-loop recipe, scrambled. Put them back in order before the next slide shows you.

  1. Set up the robot and a starting state (we start at "sense").
  2. Loop while the robot should keep running (bounded, so it stops).
  3. Run the step for the current state: sense / decide / act / wait.
  4. Advance the state: state = next_state[state].
  5. Wait a moment with time.sleep(seconds), then loop again.

Why: This is the order the recipe itself gives. Recalling the sequence without the slide in front of you is the difference between recognising the method and being able to run it — most of what goes wrong in practice is a step done out of turn.

15. The control-loop recipe

Pattern

Every robot program you write at camp follows this skeleton:

  1. Set up the robot and a starting state (we start at "sense").
  2. Loop while the robot should keep running (bounded, so it stops).
  3. Run the step for the current state: sense / decide / act / wait.
  4. Advance the state: state = next_state[state].
  5. Wait a moment with time.sleep(seconds), then loop again.

16. Where does it stop working: The control-loop recipe

Edge cases

Discussion prompt

The control-loop recipe works on the cases you have just seen. Push it to the edge: what is the most degenerate input it still handles — empty, zero, one item, everything equal — and what is the first case where it stops being true? Name the case, not just "it breaks".

Hint: Try the smallest legal input, then the largest, then the one where two things collide. Methods are specified at their edges; the middle takes care of itself.

Answer:

Every robot program you write at camp follows this skeleton:

17. The Wait: time.sleep

Section

Section 2

18. time.sleep is the pause

Concept

The wait step is a real pause. time.sleep(seconds) tells Python to stop and do nothing for that many seconds, then continue.

time.sleep(seconds) — A function from the time module that suspends the program for the given number of seconds. seconds can be a fraction, like 0.5. You must import time first.

19. Take the definitions apart: control loop vs time.sleep(seconds)

Definition probe

Sort into buckets

Every line below is part of the definition of control loop or of time.sleep(seconds) — one or the other, never both. Put each where it belongs.

control loop
The repeating heartbeat of a robot; sense the world, decide what to do, act on it, wait a moment, then repeat - forever, or until something tells it to stop.
time.sleep(seconds)
A function from the time module that suspends the program for the given number of seconds.; seconds can be a fraction, like 0.5.
b1
The repeating heartbeat of a robot: sense the world, decide what to do, act on it, wait a moment, then repeat - forever, or until something tells it to stop.
b2
A function from the time module that suspends the program for the given number of seconds. seconds can be a fraction, like 0.5. You must import time first.

20. Why a robot waits at all

Intuition

Without a wait, the loop would spin millions of times a second - faster than any motor or sensor can keep up, and it would pin the processor.

The pause sets the robot's pace: one tick every half-second, say. The wait is how fast the heartbeat beats.

21. A loop that paces itself

Worked example

Import time, then sleep half a second each tick. (In a deck we don't feel the pause, but the order of work is what matters.)

import time
for step in range(3):
    print("tick", step)
    time.sleep(0.5)

Each pass prints, then pauses 0.5s before the next pass. The sleep is the 'wait' step of the loop.

stepprintsthen
0tick 0sleep 0.5s
1tick 1sleep 0.5s
2tick 2sleep 0.5s

22. What each one costs: A loop that paces itself

Trade off

Comparison matrix

From A loop that paces itself: every row here is a choice with a cost. Fill the prints column, then say which row you would actually pick and what you give up for it.

stepprintsthen
0tick 0sleep 0.5s
1tick 1sleep 0.5s
2tick 2sleep 0.5s

23. Rule out three: Check: the role of the wait

Elimination

Eliminate the wrong options

In a control loop, what is the job of time.sleep(0.5)?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. It pauses each tick so the loop runs at a steady pace instead of spinning as fast as possible
  • B. It makes the robot move faster
  • C. It decides which state comes next
  • D. It stops the loop permanently

Survives elimination: A

Why: time.sleep(0.5) suspends the program for half a second each tick. That sets the heartbeat's pace and keeps the loop from spinning millions of times a second.

24. Check: the role of the wait

Check

Think about what the loop would do without it.

Check your understanding

In a control loop, what is the job of time.sleep(0.5)?

  • A. It pauses each tick so the loop runs at a steady pace instead of spinning as fast as possible (correct)
  • B. It makes the robot move faster
  • C. It decides which state comes next
  • D. It stops the loop permanently

Answer: A

Why: time.sleep(0.5) suspends the program for half a second each tick. That sets the heartbeat's pace and keeps the loop from spinning millions of times a second.

Why B tempts people
Sleep does the opposite of speeding things up - it slows each tick down by pausing. It controls pace, not motor speed.
Why C tempts people
Choosing the next state is the job of the next_state dictionary and state = next_state[state], not of sleep.
Why D tempts people
Sleep only pauses for the given seconds, then the loop continues. It never ends the loop - the loop's condition or range does that.

25. The Decide: a State Dictionary

Section

Section 3

26. States in a fixed order

Concept

The four steps always happen in the same order: after sense comes decide, after decide comes act, after act comes wait, after wait we're back to sense.

A dictionary is the perfect tool to store 'what comes after what'. The current state is the key; the next state is the value.

27. Picture it first: A dictionary of arrows

Picture it

Figure (svg): Four labels sense, decide, act, wait in a row with arrows: sense to decide, decide to act, act to wait, and a curved arrow from wait back to sense.

Each key points to the next state.

Discussion prompt

Read the picture before the words. What is this showing, and what is the one thing it is built to make obvious? Commit to an answer, then read on.

Hint: Name the parts, then say what changes between them — and if nothing changes, say what is being held still.

Answer:

Think of next_state as a little map of one-way arrows. You stand on a state, look up where its arrow points, and step there. Four arrows make a loop.

28. A dictionary of arrows

Intuition

Think of next_state as a little map of one-way arrows. You stand on a state, look up where its arrow points, and step there. Four arrows make a loop.

Figure (svg): Four labels sense, decide, act, wait in a row with arrows: sense to decide, decide to act, act to wait, and a curved arrow from wait back to sense.

Each key points to the next state.

29. Teach it back: A dictionary of arrows

Explain it

Discussion prompt

Explain A dictionary of arrows 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:

Think of next_state as a little map of one-way arrows. You stand on a state, look up where its arrow points, and step there. Four arrows make a loop.

30. Build the next_state dictionary

Worked example

Store the four arrows as key -> value pairs, then look one up. The key is where you are; the value is where you go next.

next_state = {"sense": "decide",
              "decide": "act",
              "act": "wait",
              "wait": "sense"}
print(next_state["act"])

next_state["act"] looks up the key "act" and hands back its value, "wait".

you look upyou get back
next_state["sense"]decide
next_state["decide"]act
next_state["act"]wait
next_state["wait"]sense

31. Where does each piece belong: The Robot Control Loop (sense, decide, act…

Sorting

Sort into buckets

These are the pieces of The Robot Control Loop (sense, decide, act, wait), out of order. Put each one back under the part of the lesson it belongs to.

The Shape of Every Robot Program
What a control loop is; It's like brushing your teeth; The loop skeleton (bounded so it stops)
The Wait: time.sleep
time.sleep is the pause; Why a robot waits at all; A loop that paces itself
The Decide: a State Dictionary
States in a fixed order; A dictionary of arrows; Build the next_state dictionary
s1
The Shape of Every Robot Program is where The Robot Control Loop (sense, decide, act, wait) puts What a control loop is, It's like brushing your teeth, The loop skeleton (bounded so it stops). Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s2
The Wait: time.sleep is where The Robot Control Loop (sense, decide, act, wait) puts time.sleep is the pause, Why a robot waits at all, A loop that paces itself. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s3
The Decide: a State Dictionary is where The Robot Control Loop (sense, decide, act, wait) puts States in a fixed order, A dictionary of arrows, Build the next_state dictionary. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.

32. Advance with state = next_state[state]

Concept

To take one step around the loop, you overwrite state with its next value: state = next_state[state]. The lookup on the right replaces the variable on the left.

state — A variable holding the name of the step the robot is on right now, like "sense". Each tick, state = next_state[state] moves it forward to the following step.

33. Term to definition: The Robot Control Loop (sense, decide, act, wait)

Matching

Match the pairs

Match each term to the definition this lesson gave it — not the one you would guess from the word.

  • t1. control loop
  • t2. time.sleep(seconds)
  • t3. state
  • d1. The repeating heartbeat of a robot: sense the world, decide what to do, act on it, wait a moment, then repeat - forever, or until something tells it to stop.
  • d2. A function from the time module that suspends the program for the given number of seconds. seconds can be a fraction, like 0.5. You must import time first.
  • d3. A variable holding the name of the step the robot is on right now, like "sense". Each tick, state = next_state[state] moves it forward to the following step.

Why: These are the working definitions of control loop, time.sleep(seconds), state as The Robot Control Loop (sense, decide, act, wait) uses them. Pairing them correctly is the test of whether you could state each one with the slide switched off.

34. Walk the cycle eight times

Worked example

Start at "sense", print the state each tick, then advance. Eight ticks land back where we started - twice around the four-step loop.

next_state = {"sense": "decide", "decide": "act",
              "act": "wait", "wait": "sense"}
state = "sense"
for step in range(8):
    print(step, state)
    state = next_state[state]

Print first, then advance - so step 0 shows the starting state. The assign-back is what moves us forward.

stepstate printedstate after advance
0sensedecide
1decideact
2actwait
3waitsense
4sensedecide
5decideact
6actwait
7waitsense

35. Watch it run: Walk the cycle eight times

Pattern

Step through it

Step through Walk the cycle eight times one row at a time. What is driving the change, and what would the row after the last one be?

  1. Step 1: step is 0
  2. Step 2: step is 1
  3. Step 3: step is 2
  4. Step 4: step is 3
  5. Step 5: step is 4
  6. Step 6: step is 5
  7. Step 7: step is 6
  8. Step 8: step is 7

36. Something is wrong here: forgetting to assign back

Anomaly

Predict first

A student writes this, and it looks reasonable:

You compute the next state but never store it back into state.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: This looks up the next state and then throws the answer away.

Assign the lookup back into state.

Why: This looks up the next state and then throws the answer away. The variable state is never changed.

37. Trap: forgetting to assign back

Trap

The trap

You compute the next state but never store it back into state.

Write next_state[state] on its own line

Why: This looks up the next state and then throws the answer away. The variable state is never changed.

Every tick prints the same thing: sense, sense, sense, sense

Why: Because state still equals "sense" forever, the robot is stuck in one step and never advances.

The fix

Assign the lookup back into state.

Write state = next_state[state]

Why: The = overwrites state with its next value, so the loop actually moves forward.

Now it prints sense, decide, act, wait, ...

Why: Each tick the state advances one arrow. The assign-back is the whole point of the step.

38. Check: what does the lookup return?

Check

Use the dict: next_state = {"sense":"decide","decide":"act","act":"wait","wait":"sense"}.

Check your understanding

What does next_state["act"] return?

  • A. "wait" (correct)
  • B. "act"
  • C. "decide"
  • D. "sense"

Answer: A

Why: The key "act" is paired with the value "wait" in the dictionary, so next_state["act"] hands back "wait" - the step that follows act.

Why B tempts people
"act" is the KEY you looked up, not the value. A dict lookup returns the value paired with the key, which here is "wait".
Why C tempts people
"decide" is the value for the key "sense", not for "act". Look up the right key: act points to wait.
Why D tempts people
"sense" is the value for the key "wait" (the loop wrapping around). The key "act" points to "wait", not "sense".

39. Answer it before you see the options: Check: the order of the loop

Prediction

Predict first

What is the correct order of the four control-loop steps?

Answer it in your own words, now, with nothing to choose from. The options are on the next slide — and picking the right one off a list is an easier skill than producing it.

Correct: sense -> decide -> act -> wait, then back to sense

Why: A robot looks at the world (sense), chooses what to do (decide), does it (act), pauses (wait), then starts over at sense. That order is the heartbeat.

40. Check: the order of the loop

Check

Recall the heartbeat that repeats forever.

Check your understanding

What is the correct order of the four control-loop steps?

  • A. sense -> decide -> act -> wait, then back to sense (correct)
  • B. decide -> sense -> wait -> act, then back to decide
  • C. act -> sense -> decide -> wait, then back to act
  • D. sense -> act -> decide -> wait, then back to sense

Answer: A

Why: A robot looks at the world (sense), chooses what to do (decide), does it (act), pauses (wait), then starts over at sense. That order is the heartbeat.

Why B tempts people
You can't decide before you sense - deciding needs the sensor reading first. Sensing always comes first in the tick.
Why C tempts people
Acting before sensing means acting on stale or no information. The robot must sense, then decide, before it acts.
Why D tempts people
Deciding has to come BEFORE acting - you choose the move, then make it. Here act and decide are swapped.

41. Put It Together: Rover + Loop + Dict

Section

Section 4

42. Wire the Rover into the act step

Concept

Now we add the provided Rover from Lesson 1. The plan: run the loop, and only on the "act" step call rover.move(). Sense, decide, and wait don't spend energy - acting does.

We keep it bounded with range(8) so the demo ends. Energy should drop exactly when the state is "act".

43. By analogy: Wire the Rover into the act step

Analogy

Discussion prompt

Explain Wire the Rover into the act step 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:

We keep it bounded with range(8) so the demo ends. Energy should drop exactly when the state is "act".

44. The whole loop, eight ticks

Worked example

A Rover("Rex"), the next_state dict, and the loop together. Print the state and energy each tick; move only on "act".

rover = Rover("Rex")
state = "sense"
for step in range(8):
    print(step, state, "energy:", rover.energy)
    if state == "act":
        rover.move()
    state = next_state[state]

Watch energy: it only drops at step 2 and step 6 - the two "act" ticks in eight steps.

stepstateenergy at startmove?
0sense100no
1decide100no
2act100yes -> 90
3wait90no
4sense90no
5decide90no
6act90yes -> 80
7wait80no

45. Watch it run: The whole loop, eight ticks

Pattern

Step through it

Step through The whole loop, eight ticks one row at a time. What is driving the change, and what would the row after the last one be?

  1. Step 1: step is 0
  2. Step 2: step is 1
  3. Step 3: step is 2
  4. Step 4: step is 3
  5. Step 5: step is 4
  6. Step 6: step is 5
  7. Step 7: step is 6
  8. Step 8: step is 7

46. One program, four ideas

Intuition

Look at that tiny program again - it secretly uses everything from the course so far, all at once:

That's the secret of the control loop: it's not new material, it's the assembly of the parts you already have.

47. Break it if you can: One program, four ideas

Counterexample

Discussion prompt

Look at that tiny program again - it secretly uses everything from the course so far, all at once:

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.

48. Something is wrong here: while True with no way out

Anomaly

Predict first

A student writes this, and it looks reasonable:

You want it to 'run forever', so you write while True: and never stop it.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: Nothing inside the loop can ever make it false, so the loop never ends.

Give the loop a way to stop.

Why: Nothing inside the loop can ever make it false, so the loop never ends.

49. Trap: while True with no way out

Trap

The trap

You want it to 'run forever', so you write while True: and never stop it.

Write while True: with no break and no changing condition

Why: Nothing inside the loop can ever make it false, so the loop never ends.

The program hangs - an infinite loop you have to kill

Why: It keeps ticking forever, printing endlessly or freezing. Real robots want this, but a demo or test must terminate.

The fix

Give the loop a way to stop.

Use a bounded loop: for step in range(8):

Why: It runs a fixed number of ticks, then ends - safe for a demo.

Or a real stop condition: while rover.energy > 0:

Why: When energy hits 0 the condition is false and the loop exits. The robot runs until its battery dies.

50. Break it on purpose: while True with no way out

Break the constraint

Discussion prompt

The rule this trap just fixed:

When energy hits 0 the condition is false and the loop exits. The robot runs until its battery dies.

Now break it on purpose. Build a case that violates it and follow the consequences until something visibly fails. Where does the failure first show up — and would you have noticed it if you had not been looking?

Hint: The dangerous rules are the ones whose violation still produces an answer. If yours fails loudly, try to find one that fails quietly.

Answer:

Nothing inside the loop can ever make it false, so the loop never ends.

51. Something is wrong here: a state that isn't in the dict

Anomaly

Predict first

A student writes this, and it looks reasonable:

You set the state to something the dictionary doesn't have a key for - a typo like "drive".

It is wrong. Say what breaks — and say it before you turn the page.

Correct: "drive" is not a key in next_state - the dict only knows sense, decide, act, wait.

Only use states that are keys in the dict.

Why: "drive" is not a key in next_state - the dict only knows sense, decide, act, wait.

52. Trap: a state that isn't in the dict

Trap

The trap

You set the state to something the dictionary doesn't have a key for - a typo like "drive".

Write state = "drive" then next_state[state]

Why: "drive" is not a key in next_state - the dict only knows sense, decide, act, wait.

Crashes: KeyError: 'drive'

Why: Python looked for the key "drive", didn't find it, and raised a KeyError naming the missing key.

The fix

Only use states that are keys in the dict.

Start from a real key: state = "sense"

Why: "sense" is in the dict, so the lookup succeeds and returns "decide".

If you see KeyError, check spelling against the dict's keys

Why: A KeyError almost always means a typo or a state you forgot to add to next_state.

53. Which of these survive contact with The Robot Control Loop (sense, decide, act…?

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.

Holds up
A robot is never 'done'. While it's on, it keeps cycling through the same four steps:; You already know the tool that repeats things: a loop. The control loop is just a while (or for) loop whose body runs those four steps in order, again and again.; You don't run your whole life in one straight line. You wake, decide, do, rest - then repeat tomorrow. A robot's loop is that, but every fraction of a second.
Breaks
You compute the next state but never store it back into state.; You want it to 'run forever', so you write while True: and never stop it.
sound
These are stated as this lesson states them — each one survives the edge cases The Robot Control Loop (sense, decide, act, wait) puts it through.
flawed
Each of these is lifted from a trap in this deck: reasonable-sounding, and wrong in a way that only shows up once you rely on it.

54. Answer it before you see the options: Check: the stuck-state bug

Prediction

Predict first

state = "sense" for step in range(4): print(state) next_state[state] What does this print?

Answer it in your own words, now, with nothing to choose from. The options are on the next slide — and picking the right one off a list is an easier skill than producing it.

Correct: sense, sense, sense, sense

Why: The line next_state[state] looks up the next state but throws it away - there's no state = ... to store it. So state stays "sense" every tick and it prints sense four times.

55. Check: the stuck-state bug

Check

Read carefully - one line is missing the assignment.

Check your understanding

state = "sense"
for step in range(4):
print(state)
next_state[state]

What does this print?

  • A. sense, sense, sense, sense (correct)
  • B. sense, decide, act, wait
  • C. decide, act, wait, sense
  • D. It crashes with a KeyError

Answer: A

Why: The line next_state[state] looks up the next state but throws it away - there's no state = ... to store it. So state stays "sense" every tick and it prints sense four times.

Why B tempts people
That output needs state = next_state[state] to actually advance. Without the assignment, state never changes from "sense".
Why C tempts people
This would advance AND skip printing the first state. Here the print happens before any advance, and no advance ever happens anyway.
Why D tempts people
There's no typo and "sense" is a valid key, so the lookup succeeds - it just discards the result. No KeyError, just a stuck state.

56. Rule out three: Check: why the KeyError?

Elimination

Eliminate the wrong options

state = "drive" print(next_state[state]) Why does this raise KeyError: 'drive'?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. "drive" is not one of the dictionary's keys, so the lookup fails
  • B. You can't print a dictionary value
  • C. The dictionary is empty
  • D. "drive" needs parentheses to be looked up

Survives elimination: A

Why: next_state only has the keys sense, decide, act, and wait. Looking up a key that isn't there - "drive" - raises KeyError naming the missing key.

57. Check: why the KeyError?

Check

next_state has keys sense, decide, act, wait.

Check your understanding

state = "drive"
print(next_state[state])

Why does this raise KeyError: 'drive'?

  • A. "drive" is not one of the dictionary's keys, so the lookup fails (correct)
  • B. You can't print a dictionary value
  • C. The dictionary is empty
  • D. "drive" needs parentheses to be looked up

Answer: A

Why: next_state only has the keys sense, decide, act, and wait. Looking up a key that isn't there - "drive" - raises KeyError naming the missing key.

Why B tempts people
Printing a dict value is completely fine. The crash happens during the lookup, before print ever runs, because the key is missing.
Why C tempts people
The dictionary has four pairs, not zero. An empty dict would still raise KeyError, but the real cause here is the unknown key "drive".
Why D tempts people
Dictionary lookups use square brackets, never parentheses. The syntax is correct; the problem is purely that "drive" is not a key.

58. Your Turn: Maze Rover Simulator

Section

Section 5 · build it yourself

59. The build: a control loop until the battery dies

Concept

Build a control loop that runs the provided Rover through the sense/decide/act/wait cycle and stops when its energy runs out, printing the state each tick. Type every line yourself, run after each line, and read errors - don't erase them.

#do thistool you'll use
1build the next_state dictionary{ } with 4 key->value pairs
2loop skeleton that advances the statewhile + state = next_state[state]
3move the rover on the act stepif state == "act": rover.move()
4stop when the battery dieswhile rover.energy > 0

60. Fill in: tool you'll use for The build: a control loop until the battery…

Comparison

Comparison matrix

From The build: a control loop until the battery dies: refill the tool you'll use column from what you know. The rest of the table is as it appeared.

#do thistool you'll use
1build the next_state dictionary{ } with 4 key->value pairs
2loop skeleton that advances the statewhile + state = next_state[state]
3move the rover on the act stepif state == "act": rover.move()
4stop when the battery dieswhile rover.energy > 0

61. Milestone 1 — the next_state dict

Worked example

Your turn: build the four-arrow dictionary, then look up what follows "wait". Predict the answer before you run it.

Hint: the current step is the key, the next step is the value. "wait" wraps back around to the start.

next_state = {"sense": "decide",
              "decide": "act",
              "act": "wait",
              "wait": "sense"}
print(next_state["wait"])
lineprints
print(next_state["wait"])sense

62. Milestone 2 — the loop skeleton

Worked example

Your turn: start at "sense" and walk the cycle eight times, printing the state and advancing each tick. Predict the first and last lines before running.

Hint: print the state, then advance with state = next_state[state] - the assign-back is what moves you forward.

state = "sense"
for step in range(8):
    print(step, state)
    state = next_state[state]
stepprints
00 sense
11 decide
22 act
33 wait
...(4 sense, 5 decide, 6 act, 7 wait)

63. Milestone 3 — move on the act step

Worked example

Your turn: add a Rover and call rover.move() only when the state is "act". Predict which steps print the 'rolls forward' line.

Hint: an if state == "act": guard, then rover.move() inside it. Acting spends energy; the other steps don't.

rover = Rover("Scout")
state = "sense"
for step in range(8):
    print(step, state)
    if state == "act":
        rover.move()
    state = next_state[state]
stepstateextra line printed
2actScout rolls forward. Energy: 90
6actScout rolls forward. Energy: 80

64. Milestone 4 — stop when the battery dies

Worked example

Your turn: swap the bounded for for a real stop condition - run while rover.energy > 0. Predict roughly how many ticks before it stops.

Hint: while rover.energy > 0: keeps looping until a move() brings energy to 0. Energy starts at 100 and each act spends 10 - so ten acts end it.

rover = Rover("Scout")
state = "sense"
tick = 0
while rover.energy > 0:
    print("tick", tick, "state:", state)
    if state == "act":
        rover.move()
    state = next_state[state]
    tick += 1
tickstatenote
0senseenergy 100
2actScout rolls forward. Energy: 90
38actScout rolls forward. Energy: 0
loopendsenergy is now 0, condition false

65. What each one costs: Milestone 4 — stop when the battery dies

Trade off

Comparison matrix

From Milestone 4 — stop when the battery dies: every row here is a choice with a cost. Fill the state column, then say which row you would actually pick and what you give up for it.

tickstatenote
0senseenergy 100
2actScout rolls forward. Energy: 90
38actScout rolls forward. Energy: 0
loopendsenergy is now 0, condition false

66. Milestone 5 — full program

Worked example

Your turn: put all four milestones together into one running simulator, and print a final report when the battery dies. Predict the last line first.

next_state = {"sense": "decide", "decide": "act",
              "act": "wait", "wait": "sense"}
rover = Rover("Scout")
state = "sense"
tick = 0
while rover.energy > 0:
    print("tick", tick, "state:", state)
    if state == "act":
        rover.move()
    state = next_state[state]
    tick += 1
print("Mission over. Scout energy:", rover.energy)
eventprints
tick 0tick 0 state: sense
tick 2 (act)Scout rolls forward. Energy: 90
tick 38 (act)Scout rolls forward. Energy: 0
after loopMission over. Scout energy: 0

If yours ends with Mission over. Scout energy: 0 after 39 ticks - you just built a real robot control loop.

67. Fill in: prints for Milestone 5 — full program

Comparison

Comparison matrix

From Milestone 5 — full program: refill the prints column from what you know. The rest of the table is as it appeared.

eventprints
tick 0tick 0 state: sense
tick 2 (act)Scout rolls forward. Energy: 90
tick 38 (act)Scout rolls forward. Energy: 0
after loopMission over. Scout energy: 0

68. Show it off

Worked example

Explain your simulator out loud, line by line: point to the loop, the dict lookup, the method call, and the stop condition - and name which control-loop step each one is.

Then point to the line that quietly does the most work: state = next_state[state]. That single assign-back is the whole decide step.

You can now beat all three of today's traps: an infinite while True, a missing assign-back that gets stuck, and a typo'd state that raises KeyError.

69. Connect it up: The Robot Control Loop (sense, decide, act, wait)

Connect it up

Draw it

One page, no notation unless you need it: draw how these connect — The Shape of Every Robot Program · The Wait: time.sleep · The Decide: a State Dictionary · Put It Together: Rover + Loop + Dict · Your Turn: Maze Rover Simulator. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.

70. What you can do now

Recap

you want to...you write
pause each ticktime.sleep(0.5)
store what comes nextnext_state = { "act": "wait", ... }
advance one stepstate = next_state[state]
stop when the battery dieswhile rover.energy > 0:

The big idea: a robot program is just a loop running the same four steps. Everything else this camp - sensors, decisions, maps - plugs into one of those four slots.

Sources

  1. Python 3 docs - time.sleep (suspend execution for a number of seconds)
  2. Python 3 docs - Mapping types (dict): key lookup and KeyError
  3. All snippets executed on CPython 3.12; output copied verbatim. Author verification run, 2026-06-24 (Pre-COSMOS Lesson 3 of 8). — Author verification run, 2026-06-24 (Pre-COSMOS Lesson 3 of 8).

Want this taught 1-on-1? Alexander tutors Python — $55/session, free consultation.

Book on Wyzant · Text (657) 465-8108