## Sunday, November 1, 2009

### Texas Holdem Hand Equity Calculation in IronPython

This year I have been working in my free time to create easy to use Texas Holdem poker spreadsheets based on IronPython using Resolver One. These spreadsheets can be used to calculate Win/Tie/Loss odds, but some people like to use hand equity instead since it represents a player’s overall stake in the pot. Equity of 1.0 or 100% means that they will win the entire pot, where as equity of 0.5 (50%) or 0.25 (25%) means that they will split the pot with other players. You can again use Monte Carlo analysis to run a number of trials before all of the board cards are dealt to estimate a player’s current equity in the hand. This means that if during 4 trials I would win 2 of them and split the pot with one other player on the other 2, then my equity would be (1.0+1.0+0.5+0.5)/4 =  3/4 or 75%.

Calculating Win/Tie/Loss statistics on an independent player vs player basis is very simple, as the player’s pocket cards are evaluated against each opponent one at a time to show which opponent hands are stronger or weaker than your own. This does not take into account how the pocket cards of other opponents might change the odds, since in reality you usually play verse a table of opponents not just one opponent at a time. Changing the spreadsheet to work against the whole table would require changing the Monte Carlo simulation from a “row by row” analysis to a “table by table” analysis, where by you setup a table of opponents using a random hand for each player given the information that you have about their hand (AK, KK or QQ, Group1, etc..) and then generate a random 5 card hand based on the currently dealt cards.

There are a lot of issues that you have to watch out for in this type of Multiway Isometric Ranged Equity Calculation, but the basics are simple so long as you have a method of comparing multiple player’s hands for a given board. The C# poker library that I use is mainly focused on heads-up hands, but it only took me about an hour to whip up a method that would take a board setup and a list of player pocket hands and return the scored value and equity for each hand as well as the highest ranked hand and a list of the winners. Here’s the code:

Here is a sample print-out when bPrintResults is True:

testBoard = ((288<< (13 * 3)) + (7<< (13 * 2))) #0b100100000000000000011100000000000000000000000000 is Ts 7s 4h 3h 2h
testHands = [3, 3 << 13, 3 << (13*2), int('1100',2)] #Hands: 3c 2c, 3d 2d, 3h 2h, and 4c 5c
(lstintScores, lstfEquity, intHighScore, lstHighScorers) = HandEquity(testBoard, testHands, True)

Start HandEquity with 4 hands and board cards: Ts 7s 4h 3h 2h
Best hand is 'Two pair, Three's and Two's with a Ten for a kicker' with 2 winner(s) getting 0.50 equity in the hand.
000: Hand 3c 2c HandScore=033622016 Equity=0.50
001: Hand 3d 2d HandScore=033622016 Equity=0.50
002: Hand 3h 2h HandScore=None        Equity=None
003: Hand 5c 4c HandScore=016942384 Equity=0.00

This is just a first step towards a full table Monte Carlo Simulator, but it gives you all of the details that are needed to find the winner(s) for a hand and calculate hand equity. The code used to generate a random board would be the same as in the other poker spreadsheets, but the player hand selection logic would need to use some sort of Round Robin algorithm to make sure that each player gets equal access to all of their possible pocket cards. Then you would use the HandEquity method to calculate the player’s equity for each hand and aggregate the results. My next goal is to change the spreadsheet code to use multiple threads, so I probably won’t tackle multi-way analysis anytime soon.