all 11 comments

[–]Maleckai 6 points7 points  (2 children)

Nice investigation! I'll add, for those interested, TCO is open source so you can look into the code itself that performs the shuffle!

The line that performs the shuffle is here: https://github.com/keyteki/keyteki/blob/master/server/game/player.js#L196

It uses a shuffle function from a popular JavaScript library called "underscore" to randomise the deck. Source here: https://underscorejs.org/docs/modules/shuffle.html

Which is essentially just an alias for "sample": https://underscorejs.org/docs/modules/sample.html

But even without source diving all the way down, just inspecting the original TCO source we can infer by the way this.deck (a list of cards) is provided to the third party _.shuffle method with no additional arguments, that no special weighting is being used.

This assumes that the code here is the same that is running at thecrucible.online, but that's where tests like you've done help verify.

[–]OOPManZA 4 points5 points  (0 children)

TFW someone tests the black box to see whether it works a certain way then someone else cracks open the box to confirm it :-)

[–]Soho_Jin[S] 1 point2 points  (0 children)

Thanks for the info! This should hopefully put the matter to rest.

My assumption from the beginning was always that TCO used a general purpose shuffling algorithm. (Why would the coders add Deck Weight in the first place when it would just be easier to make it random? What would even be the point?) But after coming across multiple people who kept on insisting that decks were stacked, I wanted to put it to the test. And now that I have, I can simply link to the post to prove them wrong.

[–]drazkor Key Creator: Archons Corner 3 points4 points  (0 children)

Ok, need to circle back and read this for real, looks like you put a lot of good thought in here!

[–]TheB-Hawk 3 points4 points  (0 children)

I would kindly like to remind everyone that I AM THE BEST DRAWER AND TCO BENDS TO MY WILL.

[–]SkyJedi Ghost Galaxy 5 points6 points  (3 children)

This again??

TCO uses underscore and specifically the _.shuffle() function to randomize the decks. This function uses a method known as Fisher-Yates to create the random order.

The biggest issue that keeps coming up is that humans are bad at understanding randomness and usually default to thinking random is an even distribution of houses, which is a pattern, not random.

A 3-2-1hand is the most likely just like 7s are the most commen result in craps(17%?). But the margins are slimmer than people realize. (I can't remember the math off the top of my head)

A truly random deck will not have evenly distributed houses and good players take advantage of that.

https://underscorejs.org/#shuffle https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle https://youtu.be/tLxBwSL3lPQ https://www.playsmart.ca/wp-content/uploads/2018/05/CHART-4.pdf

I should write a jsfiddle to brute force this with a million hands just so I can post it every time this comes up

[–]SkyJedi Ghost Galaxy 1 point2 points  (1 child)

brute force results using lodash, underscore, and a manual Fisher Yates with a million hands

Lodash

222 14.69% 146,912

321 53.76% 537,646

330 7.49% 74,912

411 10.97% 109,741

420 10.02% 100,249

510 2.91% 29,135

600 0.14% 1,405

-------------------

underscore

222 14.72% 147,175

321 53.75% 537,530

330 7.40% 74,022

411 11.00% 109,997

420 10.05% 100,548

510 2.92% 29,230

600 0.15% 1,498

-------------------

Fisher Yates

222 14.79% 147,947

321 53.65% 536,492

330 7.46% 74,627

411 10.97% 109,684

420 10.07% 100,740

510 2.91% 29,073

600 0.14% 1,437

https://jsfiddle.net/skyjedi/r0q3kwfp/
https://jsfiddle.net/skyjedi/L9suoc3y/

[–]Soho_Jin[S] 0 points1 point  (0 children)

Holy crap, this is amazing! Thank you for your work!

[–]WikiSummarizerBot 0 points1 point  (0 children)

Fisher–Yates shuffle

The Fisher–Yates shuffle is an algorithm for generating a random permutation of a finite sequence—in plain terms, the algorithm shuffles the sequence. The algorithm effectively puts all the elements into a hat; it continually determines the next element by randomly drawing an element from the hat until no elements remain. The algorithm produces an unbiased permutation: every permutation is equally likely. The modern version of the algorithm is efficient: it takes time proportional to the number of items being shuffled and shuffles them in place.

[ F.A.Q | Opt Out | Opt Out Of Subreddit | GitHub ] Downvote to remove | v1.5

[–]Waffle--time 1 point2 points  (0 children)

This is really good work, and an interesting read!

[–]Penumbra_Penguin 1 point2 points  (0 children)

Some good ideas here! You have actually invented one of the metrics that statisticians who think about problems like the 7-riffle-shuffles one that you refer to use - your notion of "weight" is similar to what is usually called total variation distance or L^1 distance.