Skip to main content

Stage 8: Win and Lose States

Course progressStage 8 of 10
~70 min
One game, one Trinket

Keep building in the workspace on the right.

This stage is part of the same Crewmate Task Dash project you started in Setup. Type each new code block into the Trinket rail and keep building on the last stage.

Build

capture checks and all-tasks-complete victory

Learn

how conditions end a game loop

Ship

a round that can be won or lost

Before you start

Make sure you finished Stage 7: Make the Chaser Move. Your Trinket project should already have a chase loop that follows the player on a timer while the arrow keys still work. Open the same file you used last stage and keep building from there.

The big idea

A game needs rules for ending. Capture ends the round one way; finishing every task ends it another way.

New words
collision
when two game objects touch or get close enough
win state
the condition that means the player won
lose state
the condition that means the player lost
return
leave a function immediately

Python concept

Trace it

Conditions and Booleans

What it means: Some questions only have two answers — yes or no, true or false. A Boolean is a value that holds one of those answers, either `True` or `False`. A condition is a check that *asks* a Boolean question.

Tiny Python example:

game_on = True # the round is alive
print(game_on) # prints True

game_on = False # the chaser caught the player
print(game_on) # prints False

In this game: `game_on` starts the round as `True`. The moment the chaser catches the player, `end_game(...)` flips it to `False`. From that frame on, every system that checks `if not game_on:` quietly stops responding.

Why it matters: Conditions are how games make decisions: caught or safe, win or keep playing, game on or game over. A Boolean variable lets every part of the game agree on which one it currently is.

Think first

Check: Conditions and Booleans

What are the only two values a Boolean can have?

Check your thinking

`True` and `False`.

Finished game target
Tasks 2/4Score 80
Crewmate playerTask stationShadow chaser

The player moves through the ship, collects tasks, and avoids the chaser. All playable shapes are drawn with Python Turtle code.

Build it

Think first

Two endings, one helper

Why pass a `message` into `end_game` instead of writing two separate ending functions?

Check your thinking

The shutdown steps are the same. Only the message changes, so one helper avoids duplicate code.

Your turn

Type, run, test

Read the code aloud before you run it. The goal is to understand what changed in the game.
Need a hint?

Add the new code to the same Trinket project. Keep previous stage code unless the stage says to replace a function.

Your turn

Step 1 - Write one ending function

`end_game(message)` keeps every shutdown step in one place: flip `game_on` off, position the HUD writer, and print the final message. Both the win rule and the lose rule will send their own text into this same function instead of duplicating the shutdown code.

You should see — calling `end_game("Test message")` directly proves the helper works — movement stops and the message appears centered on screen. A second call does nothing visible because `game_on` is already `False`.

Need a hint?

Type and run one step at a time. If this step breaks, fix it before adding the next one.

Your turn

Step 2 - Check capture distance

`chaser.distance(player) < 28` is the collision rule. The exact number is a design choice: a bigger radius means easier to get caught, a smaller radius means the player can squeeze past. Stage 9 will give this number a name so tuning it is obvious.

You should see — when the chaser closes in, the 'Captured!' message appears and the chaser stops chasing. Slip past it at the last second and nothing happens — the condition was simply `False` that frame.

Your turn

Step 3 - Return when the round ends

`return` exits `game_loop` immediately. Without it, the function would keep running, reach `screen.ontimer(game_loop, 80)`, and schedule another frame — meaning the game would technically keep looping even after the player has won or lost.

You should see — with `return` in place, the final message stays on screen and the chaser freezes in position. Take it out and the chaser keeps drifting after the 'You win!' text — that is the exact bug `return` prevents.

Active coding checkpoint

Your turn

Write the ending condition

Fill in the condition that should end the game when the chaser gets close to the player.

if __________________________:
end_game("Caught by the impostor!")
Need a hint?

Try this before opening the solution. Type the starter code, then fill in or fix the missing part yourself.

Stuck? Compare carefully
Answer check
Debug compare only

main.py

`distance(...) < 28` becomes either `True` or `False`. The ending only runs when the condition is true.

if chaser.distance(player) < 28:
end_game("Caught by the impostor!")
Python code task
Full stage code

main.py

Use this as the stage target after you understand the smaller steps. Add it to your current Trinket file.

def end_game(message):
global game_on
game_on = False
hud.setposition(0, 0)
hud.write(message, align="center", font=("Arial", 24, "bold"))

def game_loop():
check_tasks()
move_chaser()
if chaser.distance(player) < 28:
end_game("Captured! Try again.")
return
if tasks_done == 4:
end_game("All tasks complete! You win!")
return
screen.ontimer(game_loop, 80)
Trace it

Trace the idea

  1. The capture check compares two Turtle positions.
  2. The task check compares progress to the total.
  3. `return` stops the loop from scheduling another frame.

Understand it

Trace it

Why this code works

  • A game state is a condition the whole game agrees on. Here, `game_on` tells every moving system whether the round is still active.
  • Collision in beginner Turtle games is usually distance-based. If two objects are close enough, we treat them as touching.
  • Checking lose before win means capture wins ties. That is a rule choice students can discuss and change.

If it breaks

Trace it

Troubleshooting wisdom

If the chaser catches you and the game keeps going anyway, `end_game(...)` is running but the loop is not stopping. Two things both have to happen: `game_on = False` inside `end_game`, and `return` immediately after the call inside `game_loop`. The flag stops movement; the return stops the next frame from being scheduled.

If finishing every task never triggers the win, the win count is off. The condition should compare `tasks_done` to the total number of tasks the round started with (often `== 4`). Read your win condition out loud and check that the number on the right actually matches the original `tasks` list length.

If the win or lose message lands on top of the HUD, two writers want the same screen space. Either call `hud.clear()` before writing the final message, or move the HUD writer to a different `setposition` before it writes. The safest rule: one writer per spot on the screen.

Try this

Learning beat

Try this

Three short experiments. Predict before you run, then test your guess.

Predict first
Change capture radius from `28` to `8`. Predict how much harder it is for the chaser to catch you.
Compare
Try checking win before lose. What happens if the player finishes a task while touching the chaser?
Connect
What other games have more than one ending condition?

Test your stage

  • Touching the chaser ends the game.
  • Completing all tasks wins the game.
  • The chaser stops after the game ends.