system

Use when

You need to design drops, rewards, or randomized acquisition.

What it is. A table maps a roll to a reward. Weight each entry, sort into rarity tiers, and pull from it with a deterministic RNG. The whole design of “what you get and how badly you wanted it” lives in these numbers.

Player fantasy / why it’s fun. The pull of the unknown chest, the spike when the gold-bordered thing drops, the story of the run that hinged on one lucky roll. Loot turns repetition into anticipation — but only when the odds feel authored, not hostile.

When to use / when NOT

Variants

VariantShapeFeels likeReach for it when
FlatEvery entry equal oddsFair, flat, forgettablePrototyping; tiny pools where all outcomes are fine
WeightedPer-entry integer weightsSome things are “the good drop”Default. Common junk, rare jackpots — one table
TieredRoll a tier first, then an item in itLegible rarity (“orange!”)You want players to read value at a glance
Smart lootBias toward what the player can useGenerous, tailored, low-junkClass/build systems where off-slot drops are dead (genre-action-adventure, Diablo 3)
Pity / bad-luck protectionA counter that guarantees a rare after N missesTrustworthy, never cruelLong grinds; capping the worst-case tail (system-meta-progression)
Pool without replacementDrawn entries removed until refillNo dupes, guaranteed spreadCard offers, run-scoped collectibles (system-collectibles)

Twist seams

Tuning levers

How it wires to Hayao

Fails when…

Verify

Odds are a claim you can prove. Roll the table thousands of times against a fixed seed and assert empirical frequencies match the authored weights within tolerance; assert the pity counter always fires by its threshold; assert no roll can exceed the level-gated ceiling. Feel-check the drought and the spike against the roguelike track in verify-with (design/FUN.md#10-·-traditional-roguelike). The reward lands elsewhere — see design/JUDGE.md for whether the drop reads as loot at a glance.

This module rendersthe repo's markdowndirectly — edit it there, it changes here.