Lesson 6 of 8 in the Pre-COSMOS series, 38 slides, on the meta-skill: nobody memorizes a library, you read an example or a doc and adapt it. A module is a toolbox you import, and you reach its tools with the SAME dot you have used all camp, as module.function. You learn to read a function's signature to find out what it takes, then copy the example and adapt it. You practice on three real modules: random, with randint(a, b), which includes BOTH ends, choice(seq), and seed(n) for reproducible runs; math, with sqrt, floor, and ceil; and time, with sleep and time. The two traps are the classic beginner errors: calling sqrt(144) bare after import math, which raises a NameError, and assuming that randint(1, 6) excludes 6 the way range does, when in fact it includes both ends. There are five checks and a scaffolded your-turn Maze Rover Loot Run that you build from documentation you have never been taught. Every snippet was run on CPython 3.12 with random.seed(7), and the output was copied verbatim.
Subject: Python · 68 slides · code lesson
Open the interactive version of this deck · Homework for this lesson
Title
Pre-COSMOS · Lesson 6 of 8
Nobody memorizes a library. Real programmers import a toolbox, read one example, and adapt it. Today you do exactly that with random, math, and time.
Objectives
The big shift today is a mindset: you are not expected to know every tool by heart - you're expected to read and adapt. By the end you can:
import a module and reach its tools with a dot: random.randint(...).random.randint(a, b), random.choice(seq), and random.seed(n).math.sqrt, math.floor, and math.ceil, and meet time.sleep/time.time.randint(1, 6) includes 6 but range(1, 6) does not.Warm-up
Discussion prompt
Before we open The Library Mindset: import, Docs & Small Modules: without looking back, what was the main idea of Hardware as Objects: a gpiozero Preview, 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 7 of 8 (37 slides): real robot code has the SHAPE you already know. Motors and sensors are OBJECTS (Robot, Motor, DistanceSensor) - you make them and call methods on them, exactly like the Rover from Lessons 1-3.
Concept
Figure (svg): A box labeled random with a dot leading out to one of its tools, randint, showing module.function reaches a tool inside the module.
Last lessons, the dot reached inside an object (rover.move()). A module works the same way: import the toolbox, then module.tool() reaches a tool inside it.
random.randint(1, 6) is just the randint tool that lives inside random. Same dot, one level up.
Counterexample
Discussion prompt
Last lessons, the dot reached inside an object (rover.move()). A module works the same way: import the toolbox, then module.tool() reaches a tool inside it.
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:
random.randint(1, 6) is just the randint tool that lives inside random. Same dot, one level up.
Concept
One mindset, three toolboxes to practice it on:
randint, choice, seed.sqrt, floor, ceil.sleep, time.Analogy
Discussion prompt
Explain Today's roadmap 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:
One mindset, three toolboxes to practice it on:
Section
Section 1
Concept
There are thousands of library functions. No one knows them all. The real skill is: find the tool, read its example, adapt it to your problem.
So today is less about random and more about the move - reading a doc you've never seen and using it anyway.
Concept
module — A toolbox of ready-made functions someone already wrote. You bring it in with import, then reach its tools with a dot: random.randint(...).
import — The line that loads a module so you can use it. Write it once at the top: import random.
signature — The function's name plus the inputs it expects, e.g. randint(a, b). The docs show it so you know what to pass.
Matching
Match the pairs
Match each term to the definition this lesson gave it — not the one you would guess from the word.
Why: These are the working definitions of module, import, signature as The Library Mindset: import, Docs & Small Modules uses them. Pairing them correctly is the test of whether you could state each one with the slide switched off.
Picture it
Figure (svg): Three labeled toolboxes on a shelf - random, math, and time - showing a library as a shelf of toolboxes you pick from.
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 a workshop wall of labeled tool boxes. You don't memorize every tool - you walk over, read the label, and pick the one that fits the job.
Intuition
Think of a workshop wall of labeled tool boxes. You don't memorize every tool - you walk over, read the label, and pick the one that fits the job.
Figure (svg): Three labeled toolboxes on a shelf - random, math, and time - showing a library as a shelf of toolboxes you pick from.
import random is taking that box off the shelf. After that, every tool inside it is one dot away.
Explain it
Discussion prompt
Explain A library is a tool shelf 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 a workshop wall of labeled tool boxes. You don't memorize every tool - you walk over, read the label, and pick the one that fits the job.
Worked example
Bring in the toolbox, then call one of its tools with the dot. We seed first so the result is the same for everyone reading this.
import random
random.seed(7)
roll = random.randint(1, 6)
print(roll)random.randint reads as the randint tool inside random - the dot does its usual job.
| line | what it does | result |
|---|---|---|
| import random | load the toolbox | (no output) |
| random.seed(7) | fix the random sequence | (no output) |
| random.randint(1, 6) | a tool inside random | 3 |
| print(roll) | show it | 3 |
Discrimination
Sort into buckets
Sort these by result, from memory, without looking back at import, then reach a tool. Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.
Concept
The docs show a function as randint(a, b). That signature tells you the inputs: two numbers, a low end and a high end. You just copy the shape and plug in your own values.
randint(a, b) -> you supply a and b: randint(1, 6).choice(seq) -> you supply one list/sequence: choice(["a", "b"]).sqrt(x) -> you supply one number: sqrt(144).Ranking
Put in order
These are the steps of How to use ANY library function, scrambled. Put them back in order before the next slide shows you.
import random.randint(a, b)).print the result to see it.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.
Pattern
This recipe works for a tool you've never seen - that's the whole point of today:
import random.randint(a, b)).print the result to see it.Edge cases
Discussion prompt
How to use ANY library function 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:
This recipe works for a tool you've never seen - that's the whole point of today:
Section
Section 2
Worked example
randint(a, b) gives a whole number between a and b. choice(seq) picks one item from a list. Seeded so we all see the same pull.
import random
random.seed(7)
roll = random.randint(1, 6)
item = random.choice(["sword", "shield", "potion"])
print("roll:", roll)
print("item:", item)randint rolls a die; choice reaches into the list and grabs one element.
| call | does | prints |
|---|---|---|
| random.randint(1, 6) | a whole number 1..6 | 3 |
| random.choice([...]) | one item from the list | sword |
| print("roll:", roll) | show the roll | roll: 3 |
| print("item:", item) | show the item | item: sword |
Comparison
Comparison matrix
From randint and choice: refill the prints column from what you know. The rest of the table is as it appeared.
| call | does | prints |
|---|---|---|
| random.randint(1, 6) | a whole number 1..6 | 3 |
| random.choice([...]) | one item from the list | sword |
| print("roll:", roll) | show the roll | roll: 3 |
| print("item:", item) | show the item | item: sword |
Intuition
random isn't truly random - it follows a long fixed list of numbers, and seed(n) says start at the same place in that list. Same seed, same numbers, every run.
Without a seed you'd get different numbers each run - that's normal and expected, not a bug. We seed in this deck only so the printed output matches what you'll see.
Worked example
Seed to the same value twice and you get the identical sequence - that's reproducibility.
import random
for run in (1, 2):
random.seed(42)
print(run, random.randint(1, 6), random.randint(1, 6), random.randint(1, 6))Both passes re-seed to 42 first, so both print the very same three rolls.
| run | after seed(42) | prints |
|---|---|---|
| 1 | rolls 6, 1, 1 | 1 6 1 1 |
| 2 | re-seed -> same rolls | 2 6 1 1 |
| (no seed) | would differ each run | expected, not a bug |
Trade off
Comparison matrix
From Same seed, same result: 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.
| run | after seed(42) | prints |
|---|---|---|
| 1 | rolls 6, 1, 1 | 1 6 1 1 |
| 2 | re-seed -> same rolls | 2 6 1 1 |
| (no seed) | would differ each run | expected, not a bug |
Anomaly
Predict first
A student writes this, and it looks reasonable:
You know range(1, 6) stops before 6, so you assume randint(1, 6) does too.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: Carrying the range rule over: range's stop is excluded, so you expect randint's high end to be excluded too.
Read the doc: randint(a, b) returns N with a <= N <= b - both ends in.
Why: Carrying the range rule over: range's stop is excluded, so you expect randint's high end to be excluded too.
Trap
You know range(1, 6) stops before 6, so you assume randint(1, 6) does too.
Assume randint(1, 6) can only give 1, 2, 3, 4, 5
Why: Carrying the range rule over: range's stop is excluded, so you expect randint's high end to be excluded too.
Reality: randint(1, 6) can return 6
Why: randint includes BOTH ends - 1 through 6. Rolling 20 times with a seed actually produces 6s.
Read the doc: randint(a, b) returns N with a <= N <= b - both ends in.
Use randint(1, 6) for a real 6-sided die
Why: Both 1 and 6 are possible - exactly what a die needs.
If you want the range rule, use range(1, 6) or random.randrange(1, 6)
Why: range and randrange EXCLUDE the stop (1..5). randint INCLUDES it (1..6). Pick the one whose rule matches what you want.
Break the constraint
Discussion prompt
The rule this trap just fixed:
Both 1 and 6 are possible - exactly what a die needs.
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:
Carrying the range rule over: range's stop is excluded, so you expect randint's high end to be excluded too.
Elimination
Eliminate the wrong options
Which call can produce every face of a 6-sided die (1 through 6 inclusive)?
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.
Survives elimination: A
Why: randint(a, b) includes BOTH ends, so randint(1, 6) returns any of 1..6 - exactly a 6-sided die.
Check
A real 6-sided die can land on 1, 2, 3, 4, 5, or 6.
Check your understanding
Which call can produce every face of a 6-sided die (1 through 6 inclusive)?
Answer: A
Why: randint(a, b) includes BOTH ends, so randint(1, 6) returns any of 1..6 - exactly a 6-sided die.
Prediction
Predict first
Why would you call random.seed(7) at the start of a program?
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: So every run produces the same sequence of random numbers - reproducible results.
Why: seed(n) picks a fixed starting point in random's number list, so the same seed gives the same sequence every run - that is reproducibility, useful for testing and for shared examples.
Check
Think about what random.seed(7) is actually for.
Check your understanding
Why would you call random.seed(7) at the start of a program?
Answer: A
Why: seed(n) picks a fixed starting point in random's number list, so the same seed gives the same sequence every run - that is reproducibility, useful for testing and for shared examples.
Section
Section 3
Picture it
Figure (svg): A number line from 3 to 4 with 3.7 marked; an arrow down to 3 labeled floor and an arrow up to 4 labeled ceil.
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:
Picture a number line. floor drops a value down to the whole number below it; ceil lifts it up to the whole number above. The names come from a room: the floor is below you, the ceiling above.
Intuition
Picture a number line. floor drops a value down to the whole number below it; ceil lifts it up to the whole number above. The names come from a room: the floor is below you, the ceiling above.
Figure (svg): A number line from 3 to 4 with 3.7 marked; an arrow down to 3 labeled floor and an arrow up to 4 labeled ceil.
Whenever you forget which is which, you don't have to guess - the doc has a one-line example you can run.
Explain it
Discussion prompt
Explain floor down, ceil up 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:
Whenever you forget which is which, you don't have to guess - the doc has a one-line example you can run.
Worked example
The math docs list sqrt(x), floor(x), ceil(x). Read the signature, plug in a number, print it.
import math
print(math.sqrt(144))
print(math.floor(3.7))
print(math.ceil(3.2))floor rounds down, ceil rounds up - the docs say so, and the output confirms it.
| call | meaning | prints |
|---|---|---|
| math.sqrt(144) | square root | 12.0 |
| math.floor(3.7) | round down | 3 |
| math.ceil(3.2) | round up | 4 |
Anomaly
Predict first
A student writes this, and it looks reasonable:
You did import math, then call sqrt(144) bare, as if the tool jumped out of the box on its own.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: import math brings in the toolbox, but the tool still lives INSIDE it - you have to reach it with the dot.
Reach the tool with the dot, OR import the name directly.
Why: import math brings in the toolbox, but the tool still lives INSIDE it - you have to reach it with the dot.
Trap
You did import math, then call sqrt(144) bare, as if the tool jumped out of the box on its own.
Write import math then sqrt(144)
Why: import math brings in the toolbox, but the tool still lives INSIDE it - you have to reach it with the dot.
Crashes: NameError: name 'sqrt' is not defined
Why: Python looked for a plain name sqrt and found none - the only sqrt available is math.sqrt.
Reach the tool with the dot, OR import the name directly.
Use math.sqrt(144)
Why: The dot reaches into math - this returns 12.0.
Or from math import sqrt then sqrt(144)
Why: from math import sqrt copies the name out so bare sqrt(144) works and returns 12.0. Either fix is fine.
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.
rover.move()). A module works the same way: import the toolbox, then module.tool() reaches a tool inside it.; One mindset, three toolboxes to practice it on:; Think of a workshop wall of labeled tool boxes. You don't memorize every tool - you walk over, read the label, and pick the one that fits the job.range(1, 6) stops before 6, so you assume randint(1, 6) does too.; You did import math, then call sqrt(144) bare, as if the tool jumped out of the box on its own.Commit first
Predict first
import math print(sqrt(144)) This crashes with NameError: name 'sqrt' is not defined. Why?
Commit to an answer, then rate it — certain, fairly sure, or guessing — and write the rating down before you turn the page.
Correct: sqrt lives inside math; you must call it as math.sqrt(144) or first do from math import sqrt.
Why: import math loads the toolbox but the tool stays inside it. Bare sqrt is an undefined name; reach it with math.sqrt(144), or pull the name out with from math import sqrt.
The rating matters as much as the answer: confident-and-wrong is the combination that survives revision, because nothing about it feels like it needs revisiting.
Check
Read the code, then the error, before you tap.
Check your understanding
import math
print(sqrt(144))
This crashes with NameError: name 'sqrt' is not defined. Why?
Answer: A
Why: import math loads the toolbox but the tool stays inside it. Bare sqrt is an undefined name; reach it with math.sqrt(144), or pull the name out with from math import sqrt.
Worked example
You can keep the toolbox name (math.sqrt), or pull one tool out so you can call it bare. Both give the same answer - the second just changes how you spell the call.
from math import sqrt
print(sqrt(144))
import math
print(math.sqrt(144))from math import sqrt copies sqrt out so bare sqrt(144) works; import math keeps it as math.sqrt.
| line | style | prints |
|---|---|---|
| from math import sqrt | name pulled out | (no output) |
| sqrt(144) | call it bare | 12.0 |
| math.sqrt(144) | call via the module | 12.0 |
Sorting
Sort into buckets
These are the pieces of The Library Mindset: import, Docs & Small Modules, out of order. Put each one back under the part of the lesson it belongs to.
Section
Section 4
Concept
The time toolbox has sleep(seconds) (pause the program) and time() (a number of seconds you can subtract to measure how long something took).
time.sleep(1) -> wait one second, then continue.start = time.time() ... time.time() - start -> elapsed seconds.time.sleep, time.time - tools inside time.Analogy
Discussion prompt
Explain time: pause and measure 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:
The time toolbox has sleep(seconds) (pause the program) and time() (a number of seconds you can subtract to measure how long something took).
Worked example
Grab the time before and after some work, then subtract. The two time.time() calls are the same tool used twice.
import time
start = time.time()
total = 0
for i in range(1000000):
total += i
elapsed = time.time() - start
print("done")
print("took about", round(elapsed, 2), "seconds")The exact seconds depend on your computer, so that number will differ for everyone - just like un-seeded random. That's expected.
| line | does | prints |
|---|---|---|
| start = time.time() | stamp the start | (no output) |
| elapsed = time.time() - start | subtract -> seconds | (no output) |
| print("done") | show finished | done |
| print("took about", ...) | show elapsed (machine-dependent) | took about 0.21 seconds |
Discrimination
Sort into buckets
Sort these by prints, from memory, without looking back at Timing a job with time.time(). Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.
Intuition
You've now used random, math, and time without memorizing any of them - you read the signature and adapted an example. That habit is the lesson.
When you hit a tool you've never seen at camp, your move is the same: open the docs, read the signature, copy the example, adapt, print. The docs are where you find what a function does.
Counterexample
Discussion prompt
You've now used random, math, and time without memorizing any of them - you read the signature and adapted an example. That habit is the lesson.
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:
When you hit a tool you've never seen at camp, your move is the same: open the docs, read the signature, copy the example, adapt, print. The docs are where you find what a function does.
Prediction
Predict first
After import time, how do you pause the program for 1 second?
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: time.sleep(1)
Why: sleep is a tool inside the time module, so you reach it with the dot: time.sleep(1). It pauses one second, then the program continues.
Check
You imported time. Now you want to pause for one second.
Check your understanding
After import time, how do you pause the program for 1 second?
Answer: A
Why: sleep is a tool inside the time module, so you reach it with the dot: time.sleep(1). It pauses one second, then the program continues.
Elimination
Eliminate the wrong options
What's the best way to figure out what math.dist does and what inputs it takes?
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.
Survives elimination: A
Why: The docs are exactly where a function's signature and example live - read, don't memorize. That's the whole library mindset: find the tool, read its signature, adapt the example.
Check
You meet a brand-new function, math.dist, that you've never used.
Check your understanding
What's the best way to figure out what math.dist does and what inputs it takes?
Answer: A
Why: The docs are exactly where a function's signature and example live - read, don't memorize. That's the whole library mindset: find the tool, read its signature, adapt the example.
Section
Section 5 · build it yourself
Concept
Your Maze Rover opens chests. Each chest gives a random loot value (a die roll) and a random item. You'll build it using random and math - tools you just read about. Type every line yourself, run after each one, and read errors - don't erase them.
We seed(7) so your output matches this deck. The live version drops the seed so every run is a fresh adventure - that's expected, not a bug.
| # | do this | tool you'll use |
|---|---|---|
| 1 | import the toolboxes and seed | import, random.seed(n) |
| 2 | roll loot and pick an item | random.randint, random.choice |
| 3 | total the loot and rate its power | sum, math.sqrt, math.ceil |
| 4 | open three chests in a loop | for + everything above |
Comparison
Comparison matrix
From The build: a loot simulator from the docs: refill the do this column from what you know. The rest of the table is as it appeared.
| # | do this | tool you'll use |
|---|---|---|
| 1 | import the toolboxes and seed | import, random.seed(n) |
| 2 | roll loot and pick an item | random.randint, random.choice |
| 3 | total the loot and rate its power | sum, math.sqrt, math.ceil |
| 4 | open three chests in a loop | for + everything above |
Worked example
Your turn: import random and math, then seed random to 7 and print a 'ready' line. Say out loud what seed(7) will do for your output.
Hint: the tools you need are import (twice) and random.seed(n). Reach for the docs, not your memory.
import random
import math
random.seed(7)
print("Loot run, seed 7")| line | does | prints |
|---|---|---|
| import random / import math | load both toolboxes | (no output) |
| random.seed(7) | fix the sequence | (no output) |
| print(...) | show it's ready | Loot run, seed 7 |
Worked example
Your turn: roll a loot value with randint(1, 6) and pick an item from a loot list with choice. Predict the roll and item before running.
Hint: the tools are random.randint(a, b) and random.choice(seq). Keep the seed from Milestone 1 so your numbers match.
loot_table = ["sword", "shield", "potion", "gold"]
roll = random.randint(1, 6)
item = random.choice(loot_table)
print("Rolled:", roll)
print("Found:", item)| line | does | prints |
|---|---|---|
| random.randint(1, 6) | loot value 1..6 | 3 |
| random.choice(loot_table) | one item from the list | shield |
| print("Rolled:", roll) | show value | Rolled: 3 |
| print("Found:", item) | show item | Found: shield |
Worked example
Your turn: roll three loot values, sum them, and turn the total into a 'power rating' with math.ceil(math.sqrt(total)). Predict the total first.
Hint: the tools are a list of random.randint(1, 6) rolls, built-in sum, and math.sqrt then math.ceil. Re-seed to 7 so this milestone stands alone.
random.seed(7)
rolls = [random.randint(1, 6) for _ in range(3)]
total = sum(rolls)
print("Rolls:", rolls)
print("Total:", total)
print("Power rating:", math.ceil(math.sqrt(total)))| line | does | prints |
|---|---|---|
| rolls = [randint... for ...] | three rolls 1..6 | [3, 2, 4] |
| total = sum(rolls) | add them | 9 |
| math.sqrt(9) | square root | 3.0 |
| math.ceil(3.0) | round up | 3 |
Trade off
Comparison matrix
From Milestone 3 — total and power rating: every row here is a choice with a cost. Fill the does column, then say which row you would actually pick and what you give up for it.
| line | does | prints |
|---|---|---|
| rolls = [randint... for ...] | three rolls 1..6 | [3, 2, 4] |
| total = sum(rolls) | add them | 9 |
| math.sqrt(9) | square root | 3.0 |
| math.ceil(3.0) | round up | 3 |
Worked example
Your turn: open three chests in a loop - each rolls a value and an item, adds to a running total, then print the total and its power rating. Predict the last two lines before running.
import random
import math
random.seed(7)
loot_table = ["sword", "shield", "potion", "gold"]
print("== Maze Rover Loot Run ==")
grand_total = 0
for chest in range(1, 4):
roll = random.randint(1, 6)
item = random.choice(loot_table)
grand_total += roll
print(f"Chest {chest}: rolled {roll}, found {item}")
print(f"Total loot value: {grand_total}")
print(f"Power rating: {math.ceil(math.sqrt(grand_total))}")| line printed | output |
|---|---|
| header | == Maze Rover Loot Run == |
| chest 1 | Chest 1: rolled 3, found shield |
| chest 2 | Chest 2: rolled 4, found sword |
| chest 3 | Chest 3: rolled 1, found sword |
| total | Total loot value: 8 |
| power | Power rating: 3 |
If yours prints Total loot value: 8 and Power rating: 3 - you built a program from docs you were never taught.
Comparison
Comparison matrix
From Milestone 4 — full program: refill the output column from what you know. The rest of the table is as it appeared.
| line printed | output |
|---|---|
| header | == Maze Rover Loot Run == |
| chest 1 | Chest 1: rolled 3, found shield |
| chest 2 | Chest 2: rolled 4, found sword |
| chest 3 | Chest 3: rolled 1, found sword |
| total | Total loot value: 8 |
| power | Power rating: 3 |
Worked example
Explain your program out loud: point to each module.tool() call and name which toolbox it came from - random or math.
Now delete the random.seed(7) line and run it a few times. The chests change every run - that's real randomness, exactly what you'd want in a live game, and it is not a bug.
You can now beat both of today's traps: calling sqrt(144) bare (use math.sqrt), and assuming randint(1, 6) skips 6 (it includes it).
Connect it up
Draw it
One page, no notation unless you need it: draw how these connect — The Library Mindset · random — dice & choices · math — sqrt, floor, ceil · time & the Read-Adapt habit · Your Turn: Maze Rover Loot Run. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.
Recap
import it, then reach a tool with the dot (random.randint).random.randint (both ends inclusive), random.choice, and random.seed for reproducible runs.math.sqrt, math.floor, math.ceil, and reach time.sleep / time.time the same way.| you want to... | you write |
|---|---|
| bring in a toolbox | import random |
| roll a die (1..6) | random.randint(1, 6) |
| pick from a list | random.choice(items) |
| repeat the same run | random.seed(7) |
| square root / round up | math.sqrt(x) / math.ceil(x) |
Next time (Lesson 7): you take this read-and-adapt habit into your own files - splitting a program into your own small modules and importing them.
Want this taught 1-on-1? Alexander tutors Python — $55/session, free consultation.