Stage 8: Win and Lose States
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.
capture checks and all-tasks-complete victory
how conditions end a game loop
a round that can be won or lost
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.
- 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
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.
Check: Conditions and Booleans
What are the only two values a Boolean can have?
Check your thinking
`True` and `False`.
The player moves through the ship, collects tasks, and avoids the chaser. All playable shapes are drawn with Python Turtle code.
Build it
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.
Type, run, test
Need a hint?
Add the new code to the same Trinket project. Keep previous stage code unless the stage says to replace a function.
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.
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.
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
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
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!")
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 the idea
- The capture check compares two Turtle positions.
- The task check compares progress to the total.
- `return` stops the loop from scheduling another frame.
Understand 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
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
Try this
Three short experiments. Predict before you run, then test your guess.
Test your stage
- Touching the chaser ends the game.
- Completing all tasks wins the game.
- The chaser stops after the game ends.