Chapter 10 Exercises: Randomness, Probability, and the Art of Uncertainty
Exercise 1: Build a Weighted Loot Table
Type: Implementation
Time: 45-60 minutes
Deliverable: Working loot table with test output
Implement the LootTable.gd class from Section 10.4 in your Godot project. Create a loot table for your game's primary enemy type with at least six entries at different weight levels:
| Rarity Tier | Weight Range | Your Items |
|---|---|---|
| Common | 30-50 | (fill in) |
| Uncommon | 15-25 | (fill in) |
| Rare | 5-10 | (fill in) |
| Very Rare | 1-3 | (fill in) |
Write a test function that calls roll() 1,000 times and prints the frequency of each result. Compare the actual frequencies to the expected frequencies (weight / total_weight). Do they match within reasonable variance?
Now run the same test with 100 rolls and 10,000 rolls. At which sample size do the actual frequencies converge closely to the expected frequencies? Write a one-paragraph reflection on what this tells you about player experience --- if your game only has 30 enemies per level, how much variance will individual players experience compared to the theoretical distribution?
What this teaches you: The gap between theoretical probability and small-sample experience. A loot table that is "balanced" over 10,000 trials may produce wildly unbalanced outcomes in a single 30-enemy level.
Exercise 2: Calculate Drop Probabilities
Type: Mathematical / Analytical
Time: 30-45 minutes
Deliverable: Completed probability table and written analysis
Your game has a boss that drops a unique weapon with a 10% chance per kill. Calculate the following:
- Probability of getting the weapon on the first kill.
- Probability of NOT getting the weapon after 5 kills.
- Probability of NOT getting the weapon after 10 kills.
- Probability of NOT getting the weapon after 20 kills.
- Probability of NOT getting the weapon after 30 kills.
- The median number of kills needed (the point where 50% of players will have the weapon).
- The number of kills after which 95% of players will have the weapon.
- The number of kills after which 99% of players will have the weapon.
Use the formula: P(no drop after N kills) = (1 - 0.10)^N = 0.90^N
Present your results in a table. Then answer: if killing the boss takes 10 minutes per attempt, how long will the unluckiest 5% of players spend farming? Is that acceptable? If not, at what kill count would you place a pity timer?
What this teaches you: The concrete time cost of randomness. Drop rates are not abstract percentages --- they translate directly into hours of a player's life.
Exercise 3: Implement a Pity Timer
Type: Implementation
Time: 30-45 minutes
Deliverable: Working pity timer system with test output
Extend your loot table from Exercise 1 with a pity timer. Choose a rare item from your table (something with a 2-5% drop rate) and implement the following:
- Track the number of consecutive rolls that did NOT produce the rare item.
- After a threshold number of failures (you choose the threshold --- justify your choice), guarantee the rare item on the next roll.
- Reset the counter when the rare item drops (whether naturally or via pity).
Write a test function that runs 10,000 rolls with the pity timer and 10,000 rolls without it. Compare:
- The average number of rolls between rare item drops (should be similar).
- The maximum drought length (longest streak without the rare item --- should be dramatically shorter with pity).
- The standard deviation of drought lengths (should be lower with pity).
Experiment with different pity thresholds. If the base rate is 5%, compare pity thresholds of 20, 30, 40, and 50. At which threshold does the pity timer fire frequently enough to meaningfully change the average rate? At which threshold does it only catch extreme outliers?
What this teaches you: Pity timer calibration. Set the threshold too low and you effectively override the randomness system. Set it too high and it only helps the most extreme cases. The sweet spot is typically 3-5x the median number of attempts.
Exercise 4: Implement Pseudo-Random Distribution
Type: Implementation
Time: 45-60 minutes
Deliverable: Working PRD system with comparative analysis
Implement the PseudoRandomDistribution.gd class from Section 10.6. Create two systems: one with flat 25% probability and one with PRD targeting 25%.
Run 10,000 trials of each and record the streak data:
- Longest streak without a proc (consecutive failures).
- Longest streak with consecutive procs (consecutive successes).
- Average gap between procs.
- Standard deviation of gap lengths.
- Overall proc rate (should be approximately 25% for both).
Create a histogram (using print statements, a spreadsheet, or a simple visualization) showing the distribution of "gap lengths" (number of failures between each proc) for both systems. The flat-probability histogram should follow a geometric distribution with a long tail. The PRD histogram should be compressed --- fewer very short gaps and fewer very long gaps.
Write a half-page analysis: in what types of games and situations would you prefer flat probability over PRD? When would you prefer PRD? Are there situations where PRD would be worse than flat probability?
What this teaches you: The practical difference between mathematical fairness and experiential fairness, and the tradeoffs involved in compressing probability distributions.
Exercise 5: Input vs. Output Randomness Redesign
Type: Design / Analytical
Time: 45-60 minutes
Deliverable: Two design documents and written comparison
Choose a game mechanic that uses output randomness (the player acts, then randomness determines the result). Suggestions: hit chance in XCOM, critical hits in any RPG, dodge chance in any action game, random damage ranges in any combat system.
Redesign the same mechanic using input randomness instead. The random element must resolve before the player commits to the action. For example:
- Original (output): "You attack. Roll for hit. 75% chance. Result: miss."
- Redesign (input): "Before your turn, the game shows you a 'combat forecast' for each possible target: Target A will take 30 damage (guaranteed). Target B will take 50 damage (guaranteed). Target C is in cover and cannot be damaged this turn." The randomness determined the forecast; the player's decision is fully informed.
Write a one-page design document for each version (original and redesign). For each, address:
- What is the player's emotional experience when the outcome is good?
- What is the player's emotional experience when the outcome is bad?
- How much does skill influence the outcome?
- How much does luck influence the outcome?
- Which version produces better stories?
- Which version is more frustrating?
What this teaches you: The practical impact of randomness sequencing. Moving randomness from "after the decision" to "before the decision" fundamentally changes the player's relationship to uncertainty.
Exercise 6: Loot Table Balancing Through Playtesting
Type: Playtesting / Iteration
Time: 60-90 minutes
Deliverable: Three iterations of a loot table with playtest notes
Connect your loot table to your progressive project's enemy death system. Play through a combat encounter (at least 10 enemy kills) three times, taking notes each time:
Playtest 1 (initial weights): Use your original loot table from Exercise 1. Note: - How many items dropped in total? - Did the player feel like enemies were worth killing for loot? - Was any item type too frequent (boring) or too rare (frustrating)? - Did the loot feel meaningful or like clutter?
Playtest 2 (adjusted weights): Based on Playtest 1, adjust your weights. Common complaints and fixes: - "Nothing drops too often" --- reduce the "nothing" weight. - "Too much junk, not enough good stuff" --- increase uncommon/rare weights. - "I got the rare item too early, killed the excitement" --- reduce rare weights or add minimum-attempt requirements.
Playtest 3 (final adjustment): One more round of adjustments. By now, the loot table should feel satisfying: enemies are worth killing, drops are frequent enough to be rewarding but rare enough to be exciting, and rare items create genuine excitement when they appear.
Write a one-page reflection comparing the three versions. What changed between each iteration? What did playtesting reveal that the math did not predict?
What this teaches you: The irreplaceable value of playtesting for randomness systems. No amount of mathematical analysis substitutes for watching a real player interact with your probability distributions.
Exercise 7: Analyze a Gacha System Ethically
Type: Analytical / Ethical
Time: 45-60 minutes
Deliverable: Written analysis (2-3 pages)
Choose a free-to-play game with a gacha or loot box system. (Genshin Impact, Honkai: Star Rail, Fire Emblem Heroes, Marvel Snap, Diablo Immortal, and FIFA Ultimate Team are strong candidates.)
Research the game's randomness-based monetization and answer the following questions:
-
What are the published drop rates? How easy are they to find? Are they displayed before the player spends money, or buried in a menu?
-
What is the expected cost (in real currency) to acquire a specific desired item? Show your math. If the drop rate is 0.6% and each pull costs $3 equivalent, what is the expected cost for the median player? For the 95th percentile player?
-
Does the game have a pity timer or ceiling? If so, what is the maximum amount a player can spend before receiving the desired item?
-
What psychological techniques does the game use to encourage spending? Identify at least three from: variable ratio reinforcement, near-miss effects, limited-time availability, social comparison (showing other players' pulls), sunk cost framing, escalating rewards.
-
Would this system be classified as gambling under Belgium's 2018 law? Why or why not?
-
If you were redesigning this system to be ethical while still generating revenue, what would you change? Propose at least three specific modifications.
What this teaches you: The ethical boundary between randomness as a design tool and randomness as an exploitation mechanism. Every designer must be able to recognize the difference.
Exercise 8: Procedural Encounter Generator
Type: Implementation
Time: 60-90 minutes
Deliverable: Working encounter variation system
Implement the random encounter variation described in Section 10.10. For your game's enemy type, add the following randomized parameters at spawn:
- Health variation: +/- 15% of base health.
- Speed variation: +/- 10% of base speed.
- Visual indicator: Slightly different tint, size, or effect for "stronger" variants (e.g., a red tint for enemies in the top 25% of health).
- Lucky flag: 10% chance of doubling rare loot weights.
Spawn 20 enemies in a test scene. Can you visually identify the stronger variants? Can you feel the difference in combat? Play through the scene three times and note whether the variation creates meaningful tactical differences or is too subtle to notice.
If the variation is too subtle, increase it (try +/- 25% health). If it is too dramatic, decrease it. Find the range where variation is noticeable but does not feel unfair --- where a "strong" enemy is a welcome challenge, not a frustrating spike.
What this teaches you: The calibration of randomized parameters. Small variations create texture; large variations create frustration. The sweet spot is where the player notices something is different but does not feel the system is unfair.
Exercise 9: Seed Exploration
Type: Experimental / Implementation
Time: 30-45 minutes
Deliverable: Seed system implementation and comparison screenshots
Implement a seed system for your project's randomness:
- At game start, generate a random seed and display it on screen (or print it to the console).
- Add a way to input a custom seed (a text field on the start screen or a console command).
- Set
seed(value)before any random generation occurs. - Play the same seed twice. Verify that enemy placements, loot drops, and encounter variations are identical.
- Take screenshots of two different seeds side by side. Note the differences.
Bonus: Add the seed to your game's pause menu or death screen. This lets players share seeds that produced interesting or challenging runs.
What this teaches you: The practical value of reproducibility. Seeds turn randomness from an opaque, unrepeatable system into a transparent, shareable one.
Exercise 10: The "Bad Luck" Experience Test
Type: Design / Empathy
Time: 30-45 minutes
Deliverable: Written reflection (1 page)
Create a test scenario in your project (or a standalone test scene) with the following setup:
- An enemy with a single desired drop at a 5% rate.
- A button or action that kills the enemy and rolls the loot table.
- A counter showing how many kills you have performed.
- A display showing whether the rare item has dropped.
Press the button 50 times. If the item has not dropped by attempt 50, keep going until it does.
Record your emotional state at the following checkpoints: - After 10 attempts with no drop. - After 20 attempts with no drop. - After 30 attempts with no drop. - After 40 attempts with no drop. - After 50 attempts with no drop (if applicable).
Write a one-page reflection. At what point did the experience stop being "exciting anticipation" and start being "frustrated grinding"? At what kill count would you place a pity timer based on your own emotional experience? Compare this to the mathematical pity timer you designed in Exercise 3.
What this teaches you: Empathy for the unlucky player. The math tells you that 7.7% of players will reach 50 kills without the item. This exercise makes you one of them. Design decisions made after experiencing the worst case are always more humane than decisions made from the comfort of a spreadsheet.
Exercise 11: Nested Loot Table Architecture
Type: Implementation / Design
Time: 45-60 minutes
Deliverable: Working nested loot table system
Implement a two-stage loot table as described in the "Design Spotlight" in Section 10.4:
Stage 1 (Rarity Tier Roll):
| Tier | Weight |
|---|---|
| Common | 60 |
| Uncommon | 25 |
| Rare | 10 |
| Legendary | 4 |
| Unique | 1 |
Stage 2 (Item Roll within Tier): Create a separate LootTable for each tier, each containing 3-5 items appropriate to that rarity level.
The system rolls Stage 1 first to determine the tier, then rolls the appropriate Stage 2 table to determine the specific item.
Test by running 5,000 total rolls and verifying: - The tier distribution matches the Stage 1 weights. - Within each tier, items are evenly distributed (or weighted as you designed). - Adjusting a single tier weight (e.g., doubling Legendary from 4 to 8) correctly changes the overall Legendary rate without affecting item variety within the tier.
Write a short design note explaining why this architecture is more maintainable than a single flat table with 20+ entries.
What this teaches you: Data architecture for randomness systems. Nested tables separate the "how rare" question from the "which item" question, making both independently tunable.