Welcome to Orime!
The Math of Divination
Every time you draw on Orime, an algorithm decides which card you see.
We looked at our own code — and compared it to what happens when a human shuffles a physical deck. The gap is bigger than you'd expect.
The standard
A fair shuffle means every card has an equal chance of landing in any position. If you have 52 cards, each one should have a 1-in-52 chance of being first, 1-in-52 chance of being second, and so on.
No card should be more likely to show up than another. No position should be sticky. Every draw is independent — the deck has no memory.
That's the standard. Now let's see how each method holds up.
The human shuffle
When you riffle-shuffle a deck, you split it roughly in half and let the two halves interleave. Each card from the left half drops between cards from the right half — but in a pattern that's far from fully mixed.
Think of it this way: the card that sat on top before your shuffle is still likely to be somewhere near the top after. The card at the bottom is still likely to be near the bottom. The shuffle moves things around, but not enough to break the original order.
Persi Diaconis and Dave Bayer proved this in 1992. They measured how far a shuffled deck is from truly random using total variation distance — TV distance — where 1.0 means completely ordered and 0.0 means perfectly random.
The finding: a 52-card deck stays nearly ordered through 6 shuffles. The randomness doesn't build gradually — it arrives almost all at once at shuffle 7, then collapses fast. This is called the cutoff phenomenon.
And this depends on deck size. Larger decks need more shuffles to reach the same level of randomness.
| Deck size | Shuffles needed | Example |
|---|---|---|
| 32 cards | ~6 | Piquet, some oracle decks |
| 52 cards | 7 | Standard playing cards (proven by Bayer-Diaconis) |
| 78 cards | ~8 | Tarot (22 major + 56 minor arcana) |
| 90 cards | ~9 | Orime oracle (Heirs of the Dragon & Fairy) |
| Most people do | 2–3 | Regardless of deck size |
Most people riffle-shuffle 2 or 3 times, regardless of how many cards they're holding. For a 90-card oracle deck, that leaves TV distance near 1.0 — the cards are barely mixed at all.
In plain terms: the card you drew last time is still more likely to come up again than chance would predict. The deck remembers.
The common digital approach
The most common way to shuffle an array in code is this one-liner:
array.sort(() => Math.random() - 0.5)It looks right. Math.random() produces unpredictable numbers, so sorting by them should give a random order — right?
Not quite. The problem is subtle. Array.sort() is a comparison algorithm — it calls that random function a different number of times depending on the current state of the array. Some cards get compared more often than others, which quietly tilts the odds.
In plain terms: some cards end up in certain positions slightly more often than they should. It's not dramatic. For a 3-card deck [A, B, C], the numbers look like this:
| Card | Position 1 | Position 2 | Position 3 |
|---|---|---|---|
| A | 24.6% | 28.9% | 46.5% |
| B | 30.3% | 40.5% | 29.2% |
| C | 45.1% | 30.6% | 24.3% |
| Fair | 33.3% | 33.3% | 33.3% |
Card A has a 46.5% chance of landing in position 3 — nearly three times the fair rate of 16.7%. Card C is 45.1% likely to land in position 1. The bias is real.
For larger decks the per-cell distortion shrinks, but it doesn't disappear. A 52-card deck has a TV distance of roughly 0.05–0.10. A 90-card deck: roughly 0.03–0.08.
That's a massive improvement over 2–3 human riffles (TV ≈ 1.0). But it's not perfectly fair.
The correct approach
The right algorithm was worked out by Fisher and Yates in 1938, refined by Durstenfeld in 1964, and analyzed by Knuth in 1969. It's a single pass through the deck — at each step, swap the current card with any card at a randomly chosen position behind it.
for (let i = n - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}Step 1 — swap position 4 with a random position
Step 2 — swap position 3 with a random position
Step 3 — random pick lands on same position (stays)
Step 4 — swap position 1 with a random position
Why is this provably fair? At step i, the card at position i is equally likely to be any of the i+1 remaining cards — j is chosen uniformly. Chain those probabilities across every step:
Every possible ordering of n cards has exactly the same probability. No ghost. TV distance is essentially zero — limited only by how good Math.random() is, not by the algorithm.
It's also faster. Sort-shuffle runs in O(n log n) — the cost of sorting. Fisher-Yates is O(n) — one pass, one swap per card. For 90 cards that difference is microseconds, but the point stands: the correct algorithm is also the faster one.
This is what Orime uses.
Putting it together
Here's the honest picture across common deck sizes:
| Method | 32 cards | 52 cards | 78 cards | 90 cards |
|---|---|---|---|---|
| 2–3 human riffles | ~1.0 | ~1.0 | ~1.0 | ~1.0 |
| Sort-shuffle | ~0.10 | ~0.07 | ~0.05 | ~0.04 |
| Fisher-Yates (Orime) | ~0.00 | ~0.00 | ~0.00 | ~0.00 |
Going from human to any digital shuffle is the big leap — TV drops from ~1.0 to ~0.04–0.10.
Going from sort-shuffle to Fisher-Yates closes that remaining 0.04–0.10. Real, provable, but you would never feel it across a lifetime of readings.
We use Fisher-Yates because it's correct, not because you'll notice the difference. The meaningful win is that any digital draw — done right — starts from a genuinely randomized deck, every single time.
In this guide