This article [0] from 1999 on Texas Hold'em shows how bad some developers have fouled up card shuffling algorithms.

> In a real deck of cards, there are 52! (approximately 2^226) possible unique shuffles. When a computer shuffles a virtual deck of cards, it selects one of these possible combinations. There are many algorithms that can be used to shuffle a deck of cards, some of which are better than others (and some of which are just plain wrong).

> The shuffling algorithm used in the ASF software always starts with an ordered deck of cards, and then generates a sequence of random numbers used to re-order the deck. Recall that in a real deck of cards, there are 52! (approximately 2^226) possible unique shuffles. Also recall that the seed for a 32-bit random number generator must be a 32-bit number, meaning that there are just over 4 billion possible seeds. Since the deck is reinitialized and the generator re-seeded before each shuffle, only 4 billion possible shuffles can result from this algorithm. Four billion possible shuffles is alarmingly less than 52!.

> The RST exploit itself requires five cards from the deck to be known. Based on the five known cards, our program searches through the few hundred thousand possible shuffles and deduces which one is a perfect match. In the case of Texas Hold'em poker, this means our program takes as input the two cards that the cheating player is dealt, plus the first three community cards that are dealt face up (the flop). These five cards are known after the first of four rounds of betting and are enough for us to determine (in real time, during play) the exact shuffle. Figure 5 shows the GUI we slapped on our exploit. The "Site Parameters" box in the upper left is used to synchronize the clocks. The "Game Parameters" box in the upper right is used to enter the five cards and initiate the search. Figure 5 is a screen shot taken after all cards have been determined by our program. We know who holds what cards, what the rest of the flop looks, and who is going to win in advance.

> Once it knows the five cards, our program generates shuffles until it discovers the shuffle that contains the five cards in the proper order. Since the Randomize() function is based on the server's system time, it is not very difficult to guess a starting seed with a reasonable degree of accuracy. (The closer you get, the fewer possible shuffles you have to look through.) Here's the kicker though; after finding a correct seed once, it is possible to synchronize our exploit program with the server to within a few seconds. This post facto synchronization allows our program to determine the seed being used by the random number generator, and to identify the shuffle being used during all future games in less than one second!

From the NY Times article [1]:

> The ASF vulnerability lies in a faulty implementation of what is known as a pseudo-random number generator to produce a shuffled deck of cards before each round of play. The order of each shuffled deck is completely determined by one number, known as the seed. In this case, the program chose a seed based on the time, measured in milliseconds since midnight. By synchronizing their program with the system clock on the server generating the seed, Mr. McGraw and his associates were able to narrow the number of possible decks to about 200,000. Then, given the cards dealt and the community cards in the center, they could quickly compute which deck was being used.

Your friend's strategy of only playing poor players is a lot safer than breaking the casino's wallet. I'm reminded of the scene in the movie Casino [2] where casino staff drag the cheaters into the basement and threaten to cut off their hands with a power saw.

[0] - https://web.archive.org/web/20060205100630/http://www.develo...

[1] - https://www.nytimes.com/1999/09/13/business/compressed-data-...

[2] - https://www.imdb.com/title/tt0112641/