Function that evaluates poker hands, returns ranks and text descriptions.
0 Downloads
Updated 02 Sep 2008
No LicenseA function that evaluates poker hands and returns a numerical rank and text description for each. The list of cards used to make the best possible hand is returned in 'usedcards'. If handsize is smaller than the length of hands given, then the cards not used in the best possible hand are returned in 'unusedcards'. Rank of 1 is best (Royal Flush), higher numbers are worse. Rank values are not contiguous across all hands, but are correctly ordered.
The hand matrix expected is an mxn list of m hands with n cards. The cards are numbered from 1 to 52. Suit doesn't matter for ranking. Order of the cards in the input vector does not matter. Numbering starts with the Ace at position 1. Here is a suggested card assignment:
A  K  Q  J  10 9  8  7  6  5  4  3  2  Suit

1  2  3  4  5  6  7  8  9  10 11 12 13 Spades
14 15 16 17 18 19 20 21 22 23 24 25 26 Hearts
27 28 29 30 31 32 33 34 35 36 37 38 39 Clubs
40 41 42 43 44 45 46 47 48 49 50 51 52 Diamonds
Example call to the function:
trick = [33,3,43,1,25,4,19;
6,36,20,10,35,21,38;
45,31,51,40,37,22,26;
28,49,46,32,17,16,39];
[ranks,descriptions,usedcards,unusedcards] = rankp(trick,2);
revision 4  fixed a hole in the condition to wipe low aces if not used. 

revision 3


Upload better screenshot 

Rev. 2

MuffinMan (view profile)
Great starting point for a hand evaluator however still has issues and does not rank all hands correctly. I discovered this several months ago but didn't want to bother with registering to post a reply. After a coworker mentioned using this evaluator to prove an argument, I mentioned the shortcomings. Unfortunately now I can't remember the cases it fails at, but I recall the error is due to the arbitrary method of ranking hands by hashing the card numbers. In some cases hands that should not have the same rank are hashed to the same value. A easy test is to use combs=nchoosek([1:52],5); ranks=rankp(combs,5); unique(ranks) and you will find that all possible hands gives 6987 possible ranks using rankp, which is incorrect, and instead you should get 7462.
Once the total ranks checks out, you should test and find that there are 10 straight flushes, 156 four of a kinds and full houses, 1277 flushes, 10 straights, 858 trips and two pairs, 2860 pairs, and 1277 high card ranks. Otherwise, there is still an error.
As an aside, the 2+2 evaluator can do unordered evaluations of 57 card hands, at blazing speeds, and can easily be ported to Matlab.
MuffinMan (view profile)
Thanks Tim C., there was a hole in the conditional statement for hands with pairs. Nice catch, the update has it fixed.
Pretty neat! But I can't seem to wrap my head around what's happening for the test case below. Using the input:
>> trick = [21, 22, 40, 33, 26, 42, 1, 7];
>> [ranks,descriptions,usedcards,unusedcards] = rankp(trick,5);
yields:
>> descriptions{1}
ans =
'Two Pairs, Ace's and 8's with a(n) King'
>> usedcards
usedcards =
21 40 33 1 7
But there are no kings in the 'trick' vector, let alone in the 'usedcards' output. Any hints where this is coming from? I'm using R2007a.
Daniel,
Thanks for the feedback. I don't get this error with handlength of 5. My first thought is that the random cards might sometimes create an erroneous hand, but that's a guess. Can you email me your complete code and we'll have a look please?
Regards,
Rob
hi,
I was looking for a function which gives me the equity of two hands at a certain flop and two cards to come.
So i wrote a function which calls the rankp function 10000 times with a random turn and a random river and then looked which hand won how often. But the problem is when I ran rankp with a handlenght of five I always got an error saying:
Warning: Values other than 0 or 1 converted to logical 1
> In rankp>rankhand at 110
In rankp at 71
Whats this error about? If I run it with a handlenght of two there is no problem at all.
Best regards
Daniel
James,
Yep, a "Straight to the King" beats a "Pair of Jacks" all the time. The straight gets a rank of 80000 and the pair ranks at 801230000, like I think it should. Am I missing something you were pointing out? Please email me with more details if so. Thanks for testing out the function.
Best Regards,
Rob
Is this working properly??? In the example
change the last line of trick to
15 29 43 45 20 9 31
which is a K high straight....it returns a
ranking number greater (ie lower ranking value) than for the first line which is a pair of jacks???
James,
Thanks for the suggestion. In rev 2 (now posted) we actually did replace the bweuler call with something simpler and faster. I like the idea of using sum(diff), but there are some cases that it appears not to work. Check out the any(sum(logical)) method that Doug came up with. I think this is much closer to elegant than my original approach.
So, the image processing toolbox requirement is gone. But there is still a call to combnk, which is from the statistics toolbox. Besides pasting that mfile in as a subfunction, I haven't found a better way.
If you have an interest in simulating poker hands, or the associated stats, please share your work. There are lots of neat combinatorial things to do with card games.
Best,
Rob S
Pretty neat, but it's a bit of shame that it uses toolboxes just to test for a straight. Couldn't the test:
(bweuler(rowsum(1:13))==1)
be replaced with something like
(sum(diff(rowsum(1:13))==1)==1),
it's a bit unwieldy and not nearly as elegant as that in the code, but it seems to works. (Although I only tested it with two hands!)
Marcelo,
Thanks for the input. I considered several ways to identify the cards. The numbered list seemed simple and flexible. Maybe you could write a wrapper script that converts to the type of input you want to use before calling rankp?
Doug,
Thanks for the speed tips, they're included in rev.2. Also, the usedcards and unusedcards output suggestions are there so it should be useful in a variety of apps, depending on how it's called. If you base some Monte Carlo on this, which I employ from time to time, please share.
Best,
Rob
Agreed Doug,
Also, I just spotted an error at my msg. The input should be:
{'A','spades' ; 2,'Diamonds'...}
forming a total of 7 rows and 2 columns.
Another idea, which is similar to the monte carlo simulation, is to use the code to play poker against matlab in a GUI environment.
You can also extend it by allowing to computer to make rational choices over the game considering probabilistic measures (maybe given by monte carlo?).
Marcelo,
I agree that this would be very useful for simulation, that is in fact why I made the request for it on my blog:
http://blogs.mathworks.com/pick/2007/11/13/lazywebonthefileexchange/
I think that the engine should be separate from the Monte Carlo, so this structure is perfect.
This is nice, but I think the input is not very intuitive, Why dont you make it as
[number,suite;number;suite ...]
e.g.
[A,Spades;2,Diamonds ...]
Also, another suggestion to make things interesting is to write functions and scripts for a monte carlo experiment and see how much % of the simulations you can beat with your current hand. Such function could take as input:
 number of players in the table
 you current hand
and the output would be the number of simulations where you beated the other players (or n of the others).
Then you can use the simulation function and play poker with your players assisted by Matlab power. Cool, isn't it?