How Fair Is My D20? (2015)
markfickett.com
markfickett.com
If you're looking at a single face,
With 2000 rolls, you would expect a range of 81-120. (0.0405- 0.0600)
At 3000 rolls, that "narrows"\* to 127-174 (0.0423 - 0.580)
At just 100 rolls, anywhere between 1 and 10 occurences looks fair.
However, it would be better to do a proper chi-squared test, this was just illustrative, so let's do that.
Let's take the chessex opaque purple, which looks like it has 8300 rolls. By our approximations above, we expect to see rolls between 377 and 454.
In our actual data we appear to have a minimum of 313 with face13, and a maximum of 531 with face17.
So let's do a pearson's chi-squared test. Rolling 8300 times we expect 415 for each face.
We calculate for each observation, the difference between that and the expected value, and divide by the expected value, and then sum over all faces.
This gives a value of 155.3108 . We then have to compare this to the chi-squared test for 19 degrees of freedom. (There are 19 degrees of freedom because we have 20 faces, so after we have 19 results, the 20th must be fixed by being 8300 minus the sum of the first 19 faces).
Digging out our statistical tables (you DO have statistical tables right?), and lookup at 19 degrees of freedom, we can see 155 far exceeds even the p=0.01 level.
So we can conclude that the chessex opaque purple die rolled here is biased. (Or the die-roller is).
\* It narrows in proportion to the total, the absolute margin is wider. This is something that people often forget when dealing with the law of large numbers.
We could use conditional probabilities to determine if the die is biased or if the roller is biased, I think: see if P(face is 19 | face was n before roll) = P(face is 19) by statistical hypothesis testing. Not that the data we have tells whether or not.
import random, statistics
num_of_sims = 10000
num_of_rolls = 3000
results = []
for s in range(num_of_sims):
sum_of_rolls = 0
# roll 20 sided dice
for r in range(num_of_rolls):
sum_of_rolls += random.randint(1,20)
# keep track of the average value
results.append(sum_of_rolls / num_of_rolls)
print("ave: ", statistics.mean(results)) # which is 10.49915
print("stdev: ", statistics.stdev(results)) # which is 0.10492
Now where did I put my statistical tables?I've read the degrees of freedom in statistics explained so many times without actually understanding it. Now I get it. It's that simple. Thank you!
They had a large hall packed with those that would constantly spin up, drop the ball and record results. There was mathematician employed to check series for any statistical anomalies. I had few chats with the guy, I was quite impressed the level of detail and care to make sure the wheels are perfectly symmetrical and fair.
Most of the cost of the machine goes into making the wheel symmetrical. I remember something like 20 or 30 thousand dollars spent on the single piece of metal that becomes the wheel.
This is why casinos like you to gamble more, regardless of what form, because their edge is fixed by regulators. Only by increasing volume can they increase returns.
https://www.engadget.com/2013/09/18/edward-thorp-father-of-w...
A sample size of 10 can be significant (if it were 10 1's for example), and a sample size of 100,000 can be not significant, for example if you were to roll 4,953 1's.
These are my draft updated charts: http://www.markfickett.com/tmp/dice/chart.html
I used bootstrapped subsamples to generate the confidence intervals: https://github.com/markfickett/dicehistogram/blob/master/sum...
That said, I'm not sure that's generalizable to more realistic amounts of bouncing ("only a bit of bouncing" as opposed to "none at all", and "kinda a lot of bouncing" as opposed to "effectively zero resistance").
Also, i wonder how my dad's homemade d20, made out of a double d10(d20 with 0-9 twice, 0's used as 10 and 20) with half the numbers coloured red(11-20 is red), with a pen, would rank up, it was likely just done randomly.
Something like https://rjp.is/dice-graph.png (best I can do with Preview, sorry!)
That's a super cool machine, but the justification seems a bit silly. The randomization library in any programming language should be good enough for casual games, and random.org uses atmospheric noise which is almost certainly more random than dice: https://www.random.org/history/
Well... they explain why the opposite-side numbering convention makes for fairer dice. They don't say anything at all about balanced vertex sums other than "we believe it's important".
Just compare the reasoning:
> If a die is unintentionally oblate (slightly flattened on opposing sides), the flatter regions are more likely to turn up when the die is tossed. If these two opposite numbers were 19 and 20 for example, then the die would on average roll high, since these two numbers would come up too often. Having the two numbers add to 21 avoids any such bias in the average number rolled. For this reason, the opposite-side numbering convention improves fairness.
vs
> Equally important in our opinion is balancing of the vertex sums.
This does not give me confidence that the vertex sums matter.
http://www2.oberlin.edu/math/faculty/bosch/nbd.pdf Bosch, Robert; Fathauer, Robert, Segerman, Henry - Numerically Balanced Dice (2016)
(btw., here's the about page for The Die Lab: https://www.mathartfun.com/thedicelab.com/DiceDesign.html)
More various stuff on fair dice:
On fair but irregular plyhedral dice:
http://statweb.stanford.edu/~cgates/PERSI/papers/fairdice.pd... Diaconis, Persi; Keller, Joseph B. - Fair Dice (1989)
https://mathoverflow.net/questions/46684/fair-but-irregular-...
https://pp.bme.hu/ar/article/download/7607/6570/ - Várkonyi, Péter L. - The Secret of Gambling with Irregular Dice: Estimating the Face Statistics of Polyhedra (2014)
https://web.archive.org/web/20110925191300/http://blog.eqnet...
Note: The link to http://maths.dur.ac.uk:80/~dma0cvj/mathphys/supplements/supp... in the comments there is broken and the archived version doesn't have the images, but the PDF copy survives in the archive. (One can find the other PDFs from that page here, by filtering: https://web.archive.org/web/*/http://www.maths.dur.ac.uk/~dm...)
"Polyisohedral" dices: * http://loki3.com/poly/polyisohedra.html * http://loki3.com/poly/fair-dice.html
http://www.mathpuzzle.com/MAA/37-Fair%20Dice/mathgames_05_16...
https://web.archive.org/web/20050602020925/http://www.geocit...
https://savevsdragon.blogspot.com/2011/11/brief-history-of-p...
https://journals.aps.org/pre/abstract/10.1103/PhysRevE.78.03... How random is dice tossing?
He was probably on to something.
At least way better than spindown dice, which are known to be weighted.
Now, whether it matters if you use a weighted die to determine who goes first is a different story. If you're both using the same die, who cares?
Because the dice aren't evenly weighted, they have a strong bias. IIRC, Spindown D20s crit somewhere around 30% of the time.
I guess some cards use a dice roll, but that's pretty rare.
But the average MTG player at a con did not take stats in college, and not worth a fight. So ya just pull out another dice and smile and roll it.
The second more straightforward one is that the spindown dice vary from set to set and even within the set sometimes. As such the weighting is likely going to vary a lot.
https://www.youtube.com/watch?v=VI3N4Qg-JZM
Anyone know of an easy way to do metal dice?
Metal dice are less likely to have balance issues on the individual dice as long as the mold is balanced (because they are solid and heavy).
Source - I own a dice company.
Hahaha, not ready to dox myself yet but you can probably figure it out with a little digging.
Pieter Wuille created a table based implementation for a d6: https://gist.github.com/sipa/1913cf8aae565ddad0d1de7f2e9f7f3... though it isn't terribly efficient -- extracting only 2.722 bits per 4 roles, instead of the 10.34 which is theoretically possible -- because the table becomes fairly large fairly fast. d20 would be even worse.
https://gist.github.com/sipa/1621c40775007f1c27a39b608a765b1... is a similar implementation for two sides that extracts more than half the theoretical entropy.
If your application wanted uniform d20 throws a table that converted independent but biased d20 throws into unbiased d20 throws would be possible (though like above it would be inefficient unless it were very big.)
I ran bootstrapped subsampling to estimate confidence intervals (see comment above), not sure how similar that is to what you're asking about.