A Heat Map in JavaScript for Texas Holdem Win Probability

Jeff Lowery
Level Up Coding
Published in
5 min readSep 3, 2019

--

You are probably familiar with Texas Holdem, a variant of poker where two cards, known as hole cards, are dealt face down to each player, and then five community cards are dealt face up in three stages, for a total of four stages in all. After each stage, players have the opportunity to bet or raise.

Let’s say you’re dealt two hole cards. Before the flop is dealt, what are your chances of winning? Know this and you can bet, or plan to bet, accordingly.

Professor Apu Kapadia of Indiana University took a statistical approach to analyzing this by running 4 billion simulated games of poker to determine the outcomes. Several 169-row lists were the result, showing winning percentages based on number of players, from two to ten. Though each list is very informative, with that many rows it can be hard to see any pattern in the numbers, other than showing high ranking hole cards win more often than low ranking hole cards.

Awhile back I created a simple heat map package. Looking for a practical use, I ran across Dr. Kapadia’s statistics and they were a perfect for a demonstration.

Massaging the statistics

Photo by Christin Hume on Unsplash

Since each set of statistics are inconveniently embedded in HTML, I had two options:

  1. screen-scrape the data from the rendered Document Object Model using Cheerio or equivalent;
  2. cut and paste the stats on the rendered HTML page into a file, then convert that to JSON format using some regex magic

Since the stats bore a copyright notice, I asked which method the Professor would prefer, and he was okay with option 2. The regex wasn’t too hard to write, and so I wound up with JSON like the following:

const arry = [
{ pair: 'AA', wins: '84.97 ', ties: '0.57 ' },
{ pair: 'KK', wins: '82.10 ', ties: '0.58 ' },
{ pair: 'QQ', wins: '79.63 ', ties: '0.61 ' },
{ pair: 'JJ', wins: '77.16 ', ties: '0.65 ' },
{ pair: 'TT', wins: '74.66 ', ties: '0.72 ' },
{ pair: '99', wins: '71.69 ', ties: '0.80 ' },
{ pair: '88', wins: '68.72 ', ties: '0.91 ' },
{ pair: '77', wins: '65.72 ', ties: '1.04 ' },
{ pair: 'KAs', wins: '65.28 ', ties: '2.66 ' },
{ pair: 'QAs', wins: '64.41 ', ties: '2.78 ' },...

This still wasn’t in the proper format for the jsheatmap API, but few lines of code took care of that.

Now all was ready.

The heat map API

I wrote the jsheatmap package in TypeScript, which takes the following constructor parameters:

type labeledValuesType = [string, number[]]

class Sterno {
headings: Array<string>
rows: Array<labeledValuesType>

constructor(headings: string[], rows: Array<labeledValuesType>) {...

The headings are the column headings, ['A', 'K', ..., '2']; rows are of the format:

[['A', [51.7, 36.2, 25.1,...], ['K', [...], ..., ['2', [...]]

where the first value of each array element is the row label, and the array of numbers that follow are the cell values for that row. These cell values will be scaled to a number between 0.0 and 1.0, and an RGB color value will be assigned to those scaled values. This all happens when the method getData() is called, which returns a data structure that shows how the raw input data was scaled and what the corresponding color gradient will be for each scaled value:

Now all that is left is to present the map data in a colorful format.

The React application

I used create-react-app to get a React application up and running quickly. After the script has finished running, I just edit the code that was generated.

The first thing I want to do is to add some user interactivity by way of radio buttons and check boxes. There are three things the user can specify:

  1. number of players
  2. suited or unsuited hole cards
  3. whether to include ties

I’ve mentioned the effect of number of players. If hole cards are suited (both are hearts, for example), then winning odds increase a small amount. Ties are when pots are split because two or more players have the same rank of cards in their 5-card hand (their two hole cards plus three of the five community cards).

Several screenshots follow:

2 players, unsuited, no ties
5 players, suited, with ties
10 players, suited, no ties

What is noticeable in the heat map

Here are some things easily spotted in the heat map, which you can verify at https://pokermap.netlify.com:

More players lessen the odds

With 2 players, there’s a lot of green towards the upper left, indicating better odds for higher-ranking hole cards in a two-player game (about 50% for an A-2, about the same as a pair of 2's). With 10 players, is significantly worse that two 2's.

Low ranking pairs don’t help much

With 10 players, a pair of 6’s has about the same or less winning chances as any unpaired face card combination.

Suited hole cards have more effect when there are more players

K-Q unsuited in a 2 player game wins 59% of the time. Suited, the percentage increases only slightly to 61.6%. In a 10-player game, unsuited K-Q as a 13.6% chance of winning, but this jumps to 17.1% when suited.

This post has demonstrated that even a simple heat map can be useful for finding patterns and correlations in large amounts of data. Feel free to explore the source code for both jsheatmap and pokermap on github.

Photo by Amanda Jones on Unsplash

Originally published at https://www.jeffamabob.com.

--

--