Estimating the outcome of a Texas hold’em game using Monte Carlo simulation
Introduction
Card games were always fascinating for both players and mathematicians due to the factor of uncertainty or, in less formal words, luck. For many years, they were also the moving force of relatively modern areas of mathematics such as probability theory and statistics.
What is a Monte Carlo simulation?
In layman’s terms, Monte Carlo simulation is a technique for estimating a variable which depends on one or more random factors. This is achieved by repeated random sampling from a source of data (i.e a known distribution, a set of possible poker hands or from multiple tosses of a coin etc).
As you can easily understand, Monte Carlo, as probably the name suggest (no pun intended), is the perfect tool for estimating the outcome of various games that contain a factor of uncertainty.
Texas Hold’em: Let’s remember the game
Texas hold ’em is one of the most popular variants of poker and it is played according to the following rules.
At the start of a round, players receive two down cards as their personal hand (holecards), after which there is a round of betting. Then, three board cards are turned in the middle of the table simultaneously (called the flop) and then another round of betting occurs. The next two board cards are turned one at a time (the first one is called “The Turn” and the second one is called “The River”), with a round of betting after each card.
The board cards are community cards (common within all players), and a player can use any five-card combination from among the board and personal cards. A player can even use all of the board cards and no personal cards to form a hand (“play the board”).
Finally, using the best five-card combination of their hole cards and the community cards, the players show their hands, with the bettor or last raiser showing first. The player with the five-card combination of highest strength wins the pot.
Below, you can see a chart showing the strength ranking (from highest to lowest) of each valid Texas Hold’em poker combination.

And now a bit of math: Calculating the “Hand strength”
In order to express the strength of a hand (a set of 5 cards) with a real value, we should ask ourselves “how many distinct sets of 5 cards each exist” and then “how many of them have distinct strength”?
The first question is simple enough to be answered with some basic combinatorics. This number is the result of the expression “52 choose 5” (5 cards on each set that have been chosen out of 52 unique cards) which is approximately 2.6 millions.

Interestingly, it can be proven that all these hands share only 7642 different values of strength. This is because many combinations have the same strength as in most of them, the suits on the cards of the combinations do not contribute to the strength of the hand. Thus, we can count the strength of any hand on a scale from 0 (no combination in the set of 5 cards) to 7642 (Royal Flush).
The simulation
Now that we have a way to quantify the strength of a hand, we can perform a simulation of a large number of different rounds of Texas Hold’em game given a specific personal hand and the first 3 board cards (flop round) which will remain the same across all iterations. In this way, we will estimate the probabilities the personal hand to win the round, to lose the round, or split (in case there is another or more players in the table that have a hand of equal strength with the strength of our personal hand).
The code
We will implement the simulation in Python and we will use this library to evaluate the hand strength. Keep in mind that this library for technical reasons works on an inverse way based on what we explained on the previous paragraph. Thus, the hands that it evaluates with a higher evaluation, are less strong than the ones ranked with lower evaluation. So for example the strongest hand (Royal Flush) gets a score of 0 and the weakest gets a score of 7642 by this library.
Note that each card is represented by a string of this form {card_Rank}{card_suit} . Ranks take values from the set {A,2,3,4,5,6,7,8,9,T,J,Q,K} (again, for technical reasons we denote “10” as ”T”) and suits take values from the set {c,d,h,s} (c for “clubs”, d for “diamonds”, h for “hearts” and s for “spades”). So for example “Queen of Hearts” is represented by the string Qh.
So we import 2 packages that we will need later in the project (random and phevaluator, the second one needs to be installed using pip install phevaluator) and then we initialize a list that contains all the cards of a standard deck.




