Learn Python Loops at Blackthorn Manor
Build a terminal mystery game to practice Python loops and input validation.
Introduction
30 Second Summary
A good mystery turns every new clue into a fresh suspicion. The clock makes each decision feel more important.
In this project, you will build a fictional, non-graphic detective game in Python. Your terminal lets you search rooms or accuse a suspect before midnight.
What You'll Build
You will run a terminal mystery where a three-hour countdown turns each clue search into a race to make the right accusation before midnight.
By the end of this project, you'll have:
- An automatically printed case dossier generated by for loops. It displays every suspect. It also lists every searchable room.
- A three-hour countdown that displays 3, 2, then 1 by using range() with a negative step.
- An interactive investigation loop that accepts room searches or accusations. Invalid choices preserve your remaining time. A correct accusation ends the game immediately.
- Secret Mission: Add a second sealed case file with different clues. Its murderer changes to Chef Rowan.
Are there any prerequisites?
No programming knowledge is required. You need a Mac with internet access plus an administrator password for the Python installer.
Before We Start
This is your moment to define the mystery before any setup begins. You are building a non-graphic command-line game in Python that uses for loops to print dossier items, range() to create a countdown, and a while loop to repeat investigation turns until you solve the case or time runs out.
Prepare Your Detective Desk
Your command-line mystery needs a working Python interpreter before any clues can appear. Your editor also needs to know which interpreter should run the game.
In this step, you’ll install Python 3.14.7. You’ll connect it to Visual Studio Code 1.138 through the Python extension for Visual Studio Code. You’ll prove the setup works by running the game title.
In this step, get ready to:
- Prepare Python 3.14.7 for local scripts.
- Connect Visual Studio Code 1.138 to the Microsoft Python extension.
- Run mystery.py in the integrated terminal.
Install Python 3.14.7
The Python interpreter reads your .py file. It carries out each instruction in order.
- Press Cmd+Space to open macOS search.
- Type Terminal into the search field.
- Press Enter to open Terminal.
- Check your current Python version by running this command:
python3 --version
What does this command check?
The command asks macOS which Python 3 interpreter is available. Its output gives you the installed version.
- Choose the tab that matches your Terminal output.
✔️ I see version 3.14.7
Your Mac already has the required interpreter. Complete the certificate setup that comes with the official installer.
- Open Finder from the Dock.
- Select Applications in the Finder sidebar.
- Open the Python 3.14 folder.
- Double-click Install Certificates.command.
A Terminal window runs the certificate setup. You’ll see output that includes Successfully installed certifi followed by update complete.
That completes Python’s macOS setup. Your Mac is ready to run the files you create in this project.
ⓧ I see an older version
The existing interpreter is below the project version. Install Python 3.14.7 before continuing.
The administrator prompt only authorizes this local Python installation.
- Open the official Python macOS downloads page in your browser.
- Download Python 3.14.7 for macOS.
- Open the downloaded .pkg installer.
- Accept the standard installation.
- Enter your administrator password if macOS requests it.
- Open Finder from the Dock.
- Select Applications in the Finder sidebar.
- Open the Python 3.14 folder.
- Double-click Install Certificates.command.
The certificate setup prints Successfully installed certifi followed by update complete.
ⓧ Command not found
Your Mac does not currently expose a Python 3 interpreter. Install the official Python 3.14.7 package.
The administrator prompt only authorizes this local Python installation.
- Open the official Python macOS downloads page in your browser.
- Download Python 3.14.7 for macOS.
- Open the downloaded .pkg installer.
- Accept the standard installation.
- Enter your administrator password if macOS requests it.
- Open Finder from the Dock.
- Select Applications in the Finder sidebar.
- Open the Python 3.14 folder.
- Double-click Install Certificates.command.
The certificate setup prints Successfully installed certifi followed by update complete.
- Close the Terminal window from the first version check.
- Use macOS search to open a fresh Terminal window.
- Confirm the installed Python version by running this command:
python3 --version
What does the result prove?
A fresh Terminal reloads the commands available on your Mac. The reported version confirms which Python interpreter macOS now finds.
You should see Python 3.14.7 in the output.
Still seeing the wrong Python version?
Close every Terminal window before opening a fresh one. This makes the new installation available to the shell.
Confirm that the Python installer completed before checking the version again.
Help me diagnose my Python version check.
Connect Visual Studio Code to Python
Visual Studio Code edits the game file. The Microsoft Python extension adds Python language support.
The extension does not include an interpreter. Selecting the interpreter connects the editor to the Python installation you just verified.
- Search for Visual Studio Code with macOS search.
- Open Visual Studio Code if macOS finds it.
- Select Code in the macOS menu bar if the app opens.
- Select About Visual Studio Code to read the installed version.
- Choose the tab that matches what you find.
✔️ I see version 1.138
Your editor is current. Keep Visual Studio Code open for the extension setup below.
ⓧ I see an older version
Update the editor so your menus match this project.
- Close Visual Studio Code.
- Open the official Visual Studio Code download page in your browser.
- Download Visual Studio Code 1.138 for macOS.
- Open the downloaded .dmg file.
- Drag Visual Studio Code.app into Applications.
- Open Visual Studio Code from Applications.
- Select Code in the macOS menu bar.
- Select About Visual Studio Code to confirm version 1.138.
Your editor now matches the version used for this project.
ⓧ Visual Studio Code is not installed
Install Visual Studio Code before adding Python support.
- Open the official Visual Studio Code download page in your browser.
- Download Visual Studio Code 1.138 for macOS.
- Open the downloaded .dmg file.
- Drag Visual Studio Code.app into Applications.
- Open Visual Studio Code from Applications.
- Select Code in the macOS menu bar.
- Select About Visual Studio Code to confirm version 1.138.
Your editor is installed. You can now add Python support.
- Select the Extensions view in the left sidebar.
- Enter Python in the extension search field.
- Select the extension named Python published by Microsoft.
- Click Install.
- Open the Command Palette with Command+Shift+P.
- Enter Python: Select Interpreter in the Command Palette.
- Choose Python 3.14.7 from the interpreter list.
The selected interpreter controls which Python installation VS Code uses for runs from this folder.
- Select Terminal from the top menu.
- Select New Terminal.
Before you run the check, which Python version do you expect this VS Code terminal to report?
- Confirm the interpreter version in the integrated terminal by running this command:
python3 --version
Why check inside VS Code?
The integrated terminal is where your game displays its story. Checking here confirms that your editor can reach the required Python installation.
You should see Python 3.14.7 in the integrated terminal.
Does VS Code show another version?
Run Python: Select Interpreter again. Choose the entry that shows Python 3.14.7.
Close the existing integrated terminal. Open a fresh one before repeating the version check.
Help me connect VS Code to Python 3.14.7.
Create and run the mystery file
A folder keeps every part of the mystery together. The .py extension tells Visual Studio Code to treat mystery.py as a Python program.
- Press Cmd+Space to open macOS search.
- Type Finder into the search field.
- Press Enter to open Finder.
- Select Desktop in the Finder sidebar.
- Select File in the macOS menu bar.
- Select New Folder.
- Type blackthorn-manor as the folder name.
- Press Enter to create the folder.
You’ll see the new blackthorn-manor folder on your Desktop.
A possible trust prompt
Visual Studio Code may ask whether you trust the folder when you open it. You created this empty folder yourself, so confirm that you trust it.
- Switch back to Visual Studio Code.
- Select File in the top menu.
- Select Open Folder.
- Select Desktop in the folder picker.
- Select the blackthorn-manor folder.
- Click Open.
The Explorer sidebar now shows blackthorn-manor as the open folder.
- Click New File in the Explorer sidebar.
- Name the file mystery.py.
The empty mystery.py file opens in the editor.
- Add the opening title to mystery.py by copying this line:
print("MURDER AT BLACKTHORN MANOR")
What does this code do?
The print() function sends text to the terminal. The quotation marks define the exact string Python should display.
- Save mystery.py with Command+S.
Before you run the file, what title do you expect the integrated terminal to display?
- Click Run Python File in the top-right corner of the editor.
The integrated terminal runs mystery.py. You’ll see MURDER AT BLACKTHORN MANOR in the output.
Your first line of the mystery is alive. Visual Studio Code can now send your saved Python code to the selected interpreter.
Don’t see the game title?
Confirm that the active editor tab is mystery.py before clicking Run Python File.
Save the file before running it. An unsaved editor tab can leave the terminal using an older version of your code.
Help me run mystery.py in Visual Studio Code.
✔️ Awesome, I've got everything!
Great. Confirm that mystery.py is saved inside the open blackthorn-manor folder.
ⓧ I'd like to double check the full code
Your complete mystery.py file should contain this line:
print("MURDER AT BLACKTHORN MANOR")
What should match?
Check the capitalization inside the quotation marks. The saved file contains one print() instruction.
Your detective desk is ready. Next, you’ll turn this single title into a case dossier using lists, for loops, and range().
Print the Case Dossier with for
Your game title now runs in the integrated terminal. The next goal is a case dossier that introduces the whole mystery.
Writing a separate print() call for every suspect or room makes the game harder to update.
A Python list stores a related group of values. A for loop visits every value in that group.
In this step, get ready to:
- Create the story data for the case.
- Print the dossier with for loops.
- Generate the three-hour countdown with range().
Add the story and case data
The dossier needs a story plus compact collections for its suspects. It also needs rooms plus clues for the investigation.
- In mystery.py, paste this code on the blank line below the title:
print("Lord Blackthorn has been found dead in his locked study.")
print("You have three hours to identify the murderer.")
suspects = ["Lady Blackthorn", "Dr. Vale", "Chef Rowan"]
rooms = ["library", "kitchen", "study"]
clues = [
"A train ticket proves Lady Blackthorn left before dinner.",
"A signed delivery receipt places Chef Rowan outside at 10 PM.",
"A torn prescription signed by Dr. Vale lies beside the poisoned glass.",
]
culprit_key = "vale"
culprit_name = "Dr. Vale"
What Does This Case Data Do?
- The opening print() calls establish the crime plus the time limit.
- The suspects list stores every person named in the dossier.
- The rooms list stores every searchable location.
- The clues list keeps the evidence in room order.
- The culprit_key plus culprit_name values store the solution for the investigation.
- Save mystery.py by pressing Cmd+S.
- Run mystery.py by clicking Run Python File in the top-right corner.
The terminal now shows the game title. Two story lines establish the crime plus the time limit.
Good progress. Your one-line test has become the opening of a playable mystery.
Story Lines Not Running?
- Compare every quotation mark in mystery.py with the code above.
- Check that each clue ends with a comma inside the clues list.
- Save mystery.py before running it again.
Help me find the syntax problem in my case data.
Loop through the dossier
Each loop places one list item into a temporary variable. The indented body prints that current item before the loop moves forward.
- Add the suspect section below culprit_name = "Dr. Vale" by pasting this code:
print("\nSuspects:")
for suspect in suspects:
print("-", suspect)
How Does the Suspect Loop Work?
- The first print() call labels the suspect section.
- The for suspect in suspects: line selects each stored suspect in order.
- The indented print() call displays the current suspect.
- Save mystery.py.
- Run mystery.py with Run Python File.
The terminal now lists Lady Blackthorn. Dr. Vale plus Chef Rowan follow on separate lines.
Missing a Suspect?
- Check that print("-", suspect) has four spaces before it.
- Check that the loop uses suspects with the final letter included.
Help me fix my suspect loop.
The room section follows the same pattern. Reusing the pattern lets a different list produce a new section.
- Add the room section below print("-", suspect) by pasting this code:
print("\nRooms you can investigate:")
for room in rooms:
print("-", room)
How Does the Room Loop Work?
- The room variable holds one location during each repetition.
- The loop follows the order stored in rooms.
- The indented body creates one terminal line for each location.
- Save mystery.py.
- Run mystery.py with Run Python File.
The terminal now includes the library. The kitchen plus study complete the room list.
Missing the Room List?
- Check that for room in rooms: starts at the left edge of the file.
- Check that print("-", room) has four spaces before it.
Help me fix my room loop.
Count down to midnight
A range produces a sequence of integers for the loop. A negative step moves the countdown from a larger number toward a smaller stop value.
- Add the countdown below print("-", room) by pasting this code:
print("\nThe clock begins:")
for hour in range(3, 0, -1):
print(hour, "hour(s) until midnight")
How Does the Countdown Work?
- The 3 sets the first value.
- The 0 sets the excluded stop value.
- The -1 moves backward by one during each repetition.
- The hour variable holds the current countdown number.
- Save mystery.py.
Before you run the file, which number do you think the countdown prints last?
- Run mystery.py by clicking Run Python File.
The terminal lists all three suspects. It lists all three rooms.
The countdown starts at 3. It continues with 2 before ending at 1.
You have built the complete case dossier. Every collection now produces visible game output through a loop.
Countdown Out of Order?
- Check that the countdown uses range(3, 0, -1).
- Check that the countdown appears below the room loop in mystery.py.
- Check that the countdown print() call has four spaces before it.
Help me fix my countdown loop.
✔️ Awesome, I've got everything!
Great. Double check that mystery.py is saved before moving on.
ⓧ I'd like to double check the full code
Compare your saved mystery.py with the complete dossier code below.
print("MURDER AT BLACKTHORN MANOR")
print("Lord Blackthorn has been found dead in his locked study.")
print("You have three hours to identify the murderer.")
suspects = ["Lady Blackthorn", "Dr. Vale", "Chef Rowan"]
rooms = ["library", "kitchen", "study"]
clues = [
"A train ticket proves Lady Blackthorn left before dinner.",
"A signed delivery receipt places Chef Rowan outside at 10 PM.",
"A torn prescription signed by Dr. Vale lies beside the poisoned glass.",
]
culprit_key = "vale"
culprit_name = "Dr. Vale"
print("\nSuspects:")
for suspect in suspects:
print("-", suspect)
print("\nRooms you can investigate:")
for room in rooms:
print("-", room)
print("\nThe clock begins:")
for hour in range(3, 0, -1):
print(hour, "hour(s) until midnight")
Your dossier can now introduce every suspect plus every room automatically. Next, you will turn this printed case file into a repeated investigation.
Build the Investigation with while
Your case dossier now introduces the story. It also prints every suspect, room, and remaining hour.
However, a mystery needs to respond to the player more than once. A while loop can repeat investigation turns while time remains.
In this step, get ready to:
- Track the remaining investigation time with a while loop.
- Route room choices and accusations through conditional branches.
- Test how the unfinished loop handles invalid input and a solved case.
Repeat investigation turns
The condition turns_left > 0 keeps the investigation running while at least one hour remains. Each completed turn reduces turns_left by one.
The strip() method removes surrounding spaces. The lower() method makes choices such as LIBRARY match the lowercase action names in your code.
- In mystery.py, place your cursor below the countdown loop.
- Add the first investigation loop by pasting this code:
turns_left = 3
solved = False
while turns_left > 0:
print("\nHours left:", turns_left)
action = input(
"Choose library, kitchen, study, or accuse: "
).strip().lower()
turns_left = turns_left - 1
if not solved:
print("\nMidnight strikes. The case has gone cold.")
What does this code do?
- The turns_left variable starts the investigation with three available turns.
- The solved variable records whether the player identifies the murderer.
- The while condition starts another turn whenever time remains.
- The action variable stores the player's normalized choice.
- The subtraction spends one hour after every turn.
- The final condition prints the cold-case ending when the player has not solved the mystery.
- Save mystery.py with Command+S.
Before you run the game, predict whether the investigation prompt will appear once or three times.
- Click Run Python File in the top-right corner of VS Code.
- Enter library at each of the three investigation prompts.
You'll see the remaining hours change from 3 to 2 to 1. The run finishes with the cold-case message.
Does the investigation keep running?
- Check that turns_left = turns_left - 1 is indented by four spaces inside the loop.
- Compare the while turns_left > 0: line with the code block above.
Help me debug an investigation loop that does not stop.
Route each choice
A conditional chain gives each action a different result. The room branches use zero-based positions to retrieve clues from clues.
- In mystery.py, find the line that begins with turns_left = turns_left - 1.
- Insert the choice-handling branches directly above that line by pasting this code:
if action == "library":
print("Clue:", clues[0])
elif action == "kitchen":
print("Clue:", clues[1])
elif action == "study":
print("Clue:", clues[2])
elif action == "accuse":
accusation = input(
"Who did it? Enter blackthorn, vale, or rowan: "
).strip().lower()
if accusation == culprit_key:
print("Correct!", culprit_name, "committed the murder.")
solved = True
else:
print("That accusation is wrong.")
else:
print("That is not a valid action. Try again.")
How are the choices handled?
- The library branch prints the clue at position 0.
- The kitchen branch prints the clue at position 1.
- The study branch prints the clue at position 2.
- The accuse branch collects a second normalized answer.
- The comparison with culprit_key decides whether solved becomes True.
- The final else branch catches every unknown action.
- Save mystery.py.
- Click Run Python File.
- Enter library at the first prompt.
You'll see the library clue. The next prompt shows Hours left: 2.
- Enter kitchen at the second prompt.
- Enter study at the third prompt.
You'll see a different indexed clue for each room. The cold-case message appears after the third turn.
Are the clues missing?
- Check that every if or elif line ends with a colon.
- Check that each clue-printing line is indented beneath its matching condition.
- Confirm that the new branches appear above the hour-decrement line.
Help me find why a room choice does not print its clue.
✔️ Awesome, I've got everything!
Great. Double check that mystery.py is saved before testing the loop's edge cases.
ⓧ I'd like to double check the full code
Compare your file with the complete mystery.py for this step:
print("MURDER AT BLACKTHORN MANOR")
print("Lord Blackthorn has been found dead in his locked study.")
print("You have three hours to identify the murderer.")
suspects = ["Lady Blackthorn", "Dr. Vale", "Chef Rowan"]
rooms = ["library", "kitchen", "study"]
clues = [
"A train ticket proves Lady Blackthorn left before dinner.",
"A signed delivery receipt places Chef Rowan outside at 10 PM.",
"A torn prescription signed by Dr. Vale lies beside the poisoned glass.",
]
culprit_key = "vale"
culprit_name = "Dr. Vale"
print("\nSuspects:")
for suspect in suspects:
print("-", suspect)
print("\nRooms you can investigate:")
for room in rooms:
print("-", room)
print("\nThe clock begins:")
for hour in range(3, 0, -1):
print(hour, "hour(s) until midnight")
turns_left = 3
solved = False
while turns_left > 0:
print("\nHours left:", turns_left)
action = input(
"Choose library, kitchen, study, or accuse: "
).strip().lower()
if action == "library":
print("Clue:", clues[0])
elif action == "kitchen":
print("Clue:", clues[1])
elif action == "study":
print("Clue:", clues[2])
elif action == "accuse":
accusation = input(
"Who did it? Enter blackthorn, vale, or rowan: "
).strip().lower()
if accusation == culprit_key:
print("Correct!", culprit_name, "committed the murder.")
solved = True
else:
print("That accusation is wrong.")
else:
print("That is not a valid action. Try again.")
turns_left = turns_left - 1
if not solved:
print("\nMidnight strikes. The case has gone cold.")
This reference shows the exact finished state of mystery.py before the loop-control fixes.
Test the unfinished loop
The investigation now handles every planned choice. Edge-case tests reveal whether the loop returns at the right moment.
Before you run the game, predict whether an unknown action will preserve all three hours.
- Click Run Python File.
- Enter attic at the first prompt.
You'll see the invalid-action warning. The next prompt shows Hours left: 2.
The invalid choice spent an hour because the decrement line still ran. This shortfall is intentional.
- Enter attic at the second prompt.
- Enter attic at the third prompt.
You'll reach the cold-case message after three invalid choices.
Before the next run, predict whether identifying the murderer will end the investigation immediately.
- Click Run Python File again.
- Enter accuse at the first prompt.
- Enter vale when the game asks who committed the murder.
You'll see Correct! Dr. Vale committed the murder. The program then displays another action prompt with Hours left: 2.
Setting solved changes the ending condition. It does not currently exit the active loop.
- Enter library at the next prompt.
- Enter kitchen at the final prompt.
The program ends after the final clue. The cold-case message stays hidden because solved is True.
You caught both control-flow flaws in action. Your tests now show exactly where the investigation loop needs more control.
Next, you'll use continue to preserve time after invalid input. You'll use break to end the loop after a correct accusation.
Stop Wasting Time with continue and break
Your Python mystery now accepts every planned action inside a while loop. Two flaws in the game's control flow still make it unfair.
Invalid input spends an hour. A solved case keeps asking for actions.
In this step, get ready to:
- Preserve the remaining time after an invalid action with continue.
- End a correct accusation immediately with break.
- Test invalid input, room searches, a wrong accusation, and the correct accusation.
Retry invalid actions with continue
The continue statement skips the rest of the current while iteration. Placing it before the countdown update sends invalid input back to the loop condition.
- In mystery.py, locate the unknown-action else block near the bottom of the while loop.
- Find this warning line:
print("That is not a valid action. Try again.")
Why Does the Timer Still Change?
The warning currently prints. Execution then reaches turns_left = turns_left - 1 at the bottom of the loop.
- Place continue on the next indented line so the block looks like this:
else:
print("That is not a valid action. Try again.")
continue
How Does Continue Protect the Timer?
The continue statement returns control to the top of the loop. The countdown update is skipped for that iteration.
- Save mystery.py with Cmd+S.
Before you run the game, do you expect attic to leave the next prompt at three hours or reduce it to two?
- Click Run Python File in the top-right corner of the editor.
- Enter attic at the action prompt.
You'll see the invalid-action warning. The next prompt still shows three hours left.
Good, the invalid action now retries without stealing an hour.
Still Losing an Hour?
Confirm that continue sits inside the unknown-action else block. Match its indentation to the warning's print() line.
Check that you saved mystery.py before running it again.
Help me fix an invalid action that still reduces turns_left.
End a solved case with break
The break statement terminates the nearest loop immediately. The solved state remains available for the check after the loop.
- In mystery.py, locate the correct-accusation branch inside if accusation == culprit_key.
- Find this state update:
solved = True
Why Does the Game Keep Going?
The solved flag records the successful accusation. Execution currently continues into another loop iteration while time remains.
- Place break directly below solved = True so the branch looks like this:
if accusation == culprit_key:
print("Correct!", culprit_name, "committed the murder.")
solved = True
break
How Does Break Close the Case?
The break statement exits the investigation loop as soon as the accusation matches culprit_key. Execution moves to the post-loop solved check.
- Save mystery.py with Cmd+S.
Before you test this change, do you think the game will show another action prompt after Dr. Vale is named?
- Click Run Python File in the top-right corner of the editor.
- Enter accuse at the action prompt.
- Enter vale at the accusation prompt.
The terminal names Dr. Vale as the murderer. The program ends without another action prompt.
That fixes the second flaw: a solved case now closes at once.
Seeing Another Action Prompt?
Confirm that break sits directly below solved = True. Keep both lines inside the correct-accusation branch.
Check that you entered vale in lowercase. The program normalizes capitalization before comparing the accusation.
Help me stop the investigation after the correct accusation.
Test the complete investigation
The finished loop treats each action according to its outcome. A full replay lets you compare retries, investigations, wrong accusations, and the solved ending.
Before the first replay, which entries do you expect to spend the three available hours?
- Click Run Python File in the top-right corner of the editor.
- Enter attic at the first action prompt.
- Enter library at the next action prompt.
- Enter kitchen at the next action prompt.
- Enter accuse at the final action prompt.
- Enter rowan at the accusation prompt.
After attic, the next prompt still reports three hours. The two room searches use two hours.
The wrong accusation uses the final hour. The cold-case ending appears when the loop runs out of time.
Before the final run, do you expect a correct accusation to use the remaining hour or end the loop immediately?
- Click Run Python File in the top-right corner of the editor.
- Enter attic at the first action prompt.
- Enter study at the next action prompt.
- Enter accuse at the next action prompt.
- Enter vale at the accusation prompt.
The terminal names Dr. Vale. It ends without another action prompt.
Case closed: your loop now gives players a fair route to the correct ending.
✔️ Awesome, I've got everything!
Your saved mystery.py now retries invalid actions and closes solved cases immediately.
ⓧ I'd like to double check the full code
Here is the complete mystery.py for comparison.
print("MURDER AT BLACKTHORN MANOR")
print("Lord Blackthorn has been found dead in his locked study.")
print("You have three hours to identify the murderer.")
suspects = ["Lady Blackthorn", "Dr. Vale", "Chef Rowan"]
rooms = ["library", "kitchen", "study"]
clues = [
"A train ticket proves Lady Blackthorn left before dinner.",
"A signed delivery receipt places Chef Rowan outside at 10 PM.",
"A torn prescription signed by Dr. Vale lies beside the poisoned glass.",
]
culprit_key = "vale"
culprit_name = "Dr. Vale"
print("\nSuspects:")
for suspect in suspects:
print("-", suspect)
print("\nRooms you can investigate:")
for room in rooms:
print("-", room)
print("\nThe clock begins:")
for hour in range(3, 0, -1):
print(hour, "hour(s) until midnight")
turns_left = 3
solved = False
while turns_left > 0:
print("\nHours left:", turns_left)
action = input(
"Choose library, kitchen, study, or accuse: "
).strip().lower()
if action == "library":
print("Clue:", clues[0])
elif action == "kitchen":
print("Clue:", clues[1])
elif action == "study":
print("Clue:", clues[2])
elif action == "accuse":
accusation = input(
"Who did it? Enter blackthorn, vale, or rowan: "
).strip().lower()
if accusation == culprit_key:
print("Correct!", culprit_name, "committed the murder.")
solved = True
break
else:
print("That accusation is wrong.")
else:
print("That is not a valid action. Try again.")
continue
turns_left = turns_left - 1
if not solved:
print("\nMidnight strikes. The case has gone cold.")
This reference contains both final loop-control lines.
Secret mission
Open a Second Case File
One investigation loop can now solve two mysteries. Add a sealed case selector that changes the clues plus the murderer without duplicating the gameplay.
Clean Up Your Resources
Clean Up Your Resources
Choose whether to keep your project ready, pause the running game, or delete it entirely. This project runs locally on your Mac with no ongoing costs.
Resources you used:
- Project folder blackthorn-manor containing your saved mystery.py game.
Keep everything running
No action needed. Choose this if you want to keep testing both case files or changing the mystery.
- Keep blackthorn-manor open in VS Code.
- Continue testing the game by clicking Run Python File in the top-right of mystery.py.
Pause - I'll come back to this later
Stop the running game to free the integrated terminal while keeping every project file ready for later.
- Switch back to the integrated terminal from earlier.
- Press Ctrl+C if the mystery is waiting for an answer.
- Return to the game later by clicking Run Python File in the top-right of mystery.py.
Delete - I don't want to use this again
Remove the local project folder to start fresh.
Deleting the folder permanently removes your saved mystery from this Mac. Your installed tools stay untouched.
- Switch back to the integrated terminal from earlier.
- Press Ctrl+C if the mystery is waiting for an answer.
- Confirm the terminal is inside blackthorn-manor by running this command:
pwd
Check Your Location
You should see a path ending in blackthorn-manor. This confirms the terminal is inside the folder you are about to remove.
- Move out of the project folder and delete blackthorn-manor by running these commands:
cd ..
rm -rf blackthorn-manor
What Do These Commands Do?
- The first line moves the terminal one level above the project folder.
- The second line permanently removes the project folder with its saved game.
- Confirm the project folder is gone by running this command:
ls
What Should You See?
The output should not include blackthorn-manor. This confirms the project files have been deleted.
Nice Work!
Nice Work!
Case closed! Your playable mystery now uses Python to run two sealed case files through one investigation loop.
You've learned how to:
- Used for loops to print every suspect and searchable room. Used range() to count from 3 to 1.
- Built a while loop that repeats player-controlled investigation turns. Normalized each answer before checking rooms or accusations.
- Exposed two faulty outcomes through testing. Preserved turns after invalid input with continue. Ended solved cases immediately with break.
- Secret Mission: added a case selector that rejects invalid choices. Loaded different clues and culprits through the same investigation loop.
Ready to quiz yourself?