Brainlag
  1. Library
  2. Examples
  3. Python

A loot table

How games pick a random drop: weighted chances, a seeded random generator so the results repeat, and a tally of a thousand drops.

Python15 min

What to look at

The weights in LOOT are not percentages. Each item's chance is its weight divided by the total of all weights. random.seed(7) makes the "random" numbers the same on every run, which is how games replay a level or let you test drop rates.

Run it: a thousand drops

Run it, read it, change it. Open in playground keeps your own copy.

main.py to run
import random

LOOT = {
    "coin": 60,
    "potion": 25,
    "shield": 10,
    "golden sword": 4,
    "dragon egg": 1,
}

def drop(table):
    total = sum(table.values())
    roll = random.randint(1, total)
    for item, weight in table.items():
        if roll <= weight:
            return item
        roll -= weight

random.seed(7)
tally = {item: 0 for item in LOOT}
for _ in range(1000):
    tally[drop(LOOT)] += 1

total = sum(LOOT.values())
for item, n in sorted(tally.items(), key=lambda kv: -kv[1]):
    expected = LOOT[item] / total * 1000
    print(f"{item:<13} {n:>4}  (about {expected:.0f} expected)")

Change it

  • Give the dragon egg a weight of 0. Does drop() still work, and can the egg ever drop?
  • Remove random.seed(7) and run it three times. Which numbers move the most?
  • Add a "rare_mode" table where the weights are flipped (rare things common). Reuse drop() without changing it.
  • Change the loop to stop at the first golden sword and print how many drops it took.

Code editor. Press Control or Command plus Enter to run the code. Tab indents; to move focus out of the editor, press Escape and then Tab.