Quote:richodudeQuote:gordonm888

Make separate categories out of 4 card straight plus a pair, 4 card flush plus a pair, and 4 card SF plus a pair.

link to original post

This bit is really helpful. I started again today with a fresh mind and think I've got it. The cells marked "(calculated)" are my answers

4sflush 2,032 4flush w/ 5straight 360 4flush w/ pair 34,320 4flush w/ kicker 102,600 4flush (theoretical) 134,888 4flush (calculated) 134,888 4straight w/ 4flush 1,320 4straight w/ 5straight 10,200 4straight w/ pair 33,264 4straight w/ kicker 89,592 4straight (theoretical) 121,536 4straight (calculated) 121,536

4sflush =36*46+8*47 4flush w/ 5straight =4*30*3 4flush w/ pair =4*COMBIN(13,4)*12 4flush w/ kicker =4*COMBIN(13,4)*36-360 4flush (theoretical) =4*(COMBIN(13,4)*48) - B22-B23 4flush (calculated) =sum(B24:B25) - B22 4straight w/ 4flush =(11*4^4)*12/256*10 4straight w/ 5straight =10*(4^5-4) 4straight w/ pair =11*(4^4-4)*12 4straight w/ kicker =11*(4^4-4)*36-B27 4straight (theoretical) =11*(4^4-4)*48-B27-B26 4straight (calculated) =SUM(B28,B29)-B26

I used google sheets on cells A22-B33 for this with the order slightly different. I had it

4sflush (red)

4flush w/ 5straight (yellow)

4flush w/ pair (green)

4flush w/ kicker (green)

4straight w/ 4flush (red)

4straight w/ 5straight (red)

4straight w/ pair (green)

4straight w/ kicker (green)

4flush (orange)

4straight (blue)

4flush (calculated) (orange)

4straight (calculated) (blue)

where a red cell got subtracted from each respective total cell, a yellow got subtracted only from the theoretical, and green was what was added in the calculated cells. I'm sure there's a better way to display this information but I couldn't be bothered finding how.

There is a special case where a 4-card straight with a pair where the paired card also forms a 4-card flush. It happens to be that every single scenario of this forms a 4 card straight flush which I already subtracted out.

These calculations help me with the whole hierarchy

royal flush 4 straight flush 36 4 card royal 188 quads 624 4 card straight flush 1,844 full house 3,744 flush 5,108 straight 10,200 trips 54,912 4 card flush 134,888 4 card straight 121,536 two pair 123,552 pair 1,030,656 high card 1,111,668 total (theoretical) 2,598,960 total (calculated) 2,598,960

I'm somewhat confident in these numbers but now have some decisions about the game. Should 4-card flush still outrank straight and two pair? The difference is little and would be more intuitive for people without the numbers and knowledge of 5-card hands. Next, how would I add sections for ace high/king high/queen high etc. combinations? Normally it wouldn't be so bad but the 4-card combos really screw you.

Commenting on Mental's calculations, I'm curious as to how your code got lower answers than me. The 4flush is definitely too low at only 3x more likely than a 5flush but the 4straight is ballpark. I like the video poker prediction but this will be a stud game of player vs. dealer. Hoping to get into game invention and looking at a class in LV in August where corporations can buy final projects (table game ideas).

link to original post

In your categories, when you use the word kicker, you might substitute the word "singleton" when it is meant that the uncoordinated 5th card is unpaired.

I was going to cite the omission of '4 straight +4 flush + pair' as a category and thus that your '4-straight + pair' may be too high. I do now see your note on '4 straight +4 flush + pair' hands but I still wonder if '4 straight + pair' is too high because of double counting.

Okay, except for that typo that I spotted last night, I do not see any other mistakes. I assigned my 4-straights and 4-flush types a different way than the previous iteration and I still get the same results as the previous post.Quote:MentalOkay, I just looked at my code and saw a single character typo in the 4-flush code.

Hand, Pay, #Flops

Royal, 800.00, 4

Str_Flush, 50.00, 36

Quads, 25.00, 624

Full_House, 9.00, 3744

Flush, 6.00, 5108

Straight, 4.00, 10200

Trips, 3.00, 54912

Flush4, 2.70, 110940

Straight4, 2.30, 92208

Two_Pair, 2.00, 123552

JOB, 1.00, 323268

Nada, 0.00, 1874364

Just to make comparisons easier, I defined a pair as twos or better and reran the calculation:

Hand, Pay, #Flops

Royal, 800.00, 4

Str_Flush, 50.00, 36

Quads, 25.00, 624

Full_House, 9.00, 3744

Flush, 6.00, 5108

Straight, 4.00, 10200

Trips, 3.00, 54912

Flush4, 2.70, 110940

Straight4, 2.30, 92208

Two_Pair, 2.00, 123552

2OB, 1.00, 1047552

Nada, 0.00, 1150080

If I restrict my count to hands that only use J,Q,K, and A, I count 48 hands that qualify as 4-flushes and 1488 hands that qualify as 4-straights. The 48 is four suits x 12 kickers. Here are the 48 possible 4-flushes:

JQKAJ

JQKAQ

JQKAK

JQKAA

JQKAJ

JQKAQ

JQKAK

JQKAA

JQKAJ

JQKAQ

JQKAK

JQKAA

JJQKA

JJQKA

JJQKA

QJQKA

QJQKA

QJQKA

KJQKA

KJQKA

KJQKA

AJQKA

AJQKA

AJQKA

JQKAJ

JQKAQ

JQKAK

JQKAA

JQKAJ

JQKAQ

JQKAK

JQKAA

JJQKA

JJQKA

QJQKA

QJQKA

KJQKA

KJQKA

AJQKA

AJQKA

JQKAJ

JQKAQ

JQKAK

JQKAA

JJQKA

QJQKA

KJQKA

AJQKA

Hand, Pay, #Flops

Royal, 800.00, 4

Str_Flush, 50.00, 36

RF4, 40.00, 188

Quads, 25.00, 624

SF4, 15.00, 1844

Full_House, 9.00, 3744

Flush, 6.00, 4792

Straight, 4.00, 9960

Trips, 3.00, 54912

Flush4, 2.70, 109464

Straight4, 2.30, 92208

Two_Pair, 2.00, 123552

2OB, 1.00, 1047552

Nada, 0.00, 1150080

I believe your flush number is wrong. You have flush = 5,108, but that is the total number of flushes that are not SF5 and RF5. Some of the Flushes are also also RF4 and SF4, so the number of plain 5-flushes has to be less than 5,108. Am I missing something about how you are defining and counting hands? A hand can only evaluate to one type, right?

Here are the flops for the traditional JOB VP hands.

Hand, Pay, #Flops

Royal, 800.00, 4

Str_Flush, 50.00, 36

Quads, 25.00, 624

Full_House, 9.00, 3744

Flush, 6.00, 5108

Straight, 4.00, 10200

Trips, 3.00, 54912

Two_Pair, 2.00, 123552

JOB, 1.00, 337920

Nada, 0.00, 2062860

Quote:MentalI added in SF4 and RF4 hands because these eat up some of the 4-flush and 4-straight hands.

So, we agree on everything except the straights and flushes.Hand, Pay, #Flops

Royal, 800.00, 4

Str_Flush, 50.00, 36

RF4, 40.00, 188

Quads, 25.00, 624

SF4, 15.00, 1844

Full_House, 9.00, 3744

Flush, 6.00, 4792

Straight, 4.00, 9960

Trips, 3.00, 54912

Flush4, 2.70, 109464

Straight4, 2.30, 92208

Two_Pair, 2.00, 123552

2OB, 1.00, 1047552

Nada, 0.00, 1150080

I believe your flush number is wrong. You have flush = 5,108, but that is the total number of flushes that are not SF5 and RF5. Some of the Flushes are also also RF4 and SF4, so the number of plain 5-flushes has to be less than 5,108. Am I missing something about how you are defining and counting hands? A hand can only evaluate to one type, right?

Here are the flops for the traditional JOB VP hands.Hand, Pay, #Flops

Royal, 800.00, 4

Str_Flush, 50.00, 36

Quads, 25.00, 624

Full_House, 9.00, 3744

Flush, 6.00, 5108

Straight, 4.00, 10200

Trips, 3.00, 54912

Two_Pair, 2.00, 123552

JOB, 1.00, 337920

Nada, 0.00, 2062860

link to original post

My responses are usually quick. Why the delay? well I've been teaching myself to program of course! It's far from perfect, but I believe my logic for the 4-card hands is correct. Well, what did I get? Out of 2.6m random hands, ~95k of them were 4-card straights and ~89.5k were 4-card flushes. Along with ~1.16m high cards, ~1.05m pairs, ~54.8k trips and so on. Both of these 4-card hands still contain straight flush combos and I'm working that out but its 6:30 in the morning and I want to share something before I crash. That means your 4straight result is most likely correct! But how is my mathematical solution wrong? My brain already hurts and I don't wanna figure that out. That means then the actual number of 4flush combos should be closer to 86k, unless my code logic is undercounting something but it shouldn't with the lines

if temp_suit.count(0) == 4 or temp_suit.count(1) == 4 or temp_suit.count(2) == 4 or temp_suit.count(3) == 4:

is_4flush = True

where suits have a value of 0-3 hearts-spades. The hand is ranked higher than 4straight so that's not undercounted. I'd take another look at how you're counting 4flushes. I'll definitely have another go tomorrow and use this code to build onto the full game. I could provide the code somewhere if you'd like

Also, yes. That 5108 flush count is a silly mistake from me

Good for you. I don't think I could get very far with just a spreadsheet. Is this C++?Quote:richodudeMy responses are usually quick. Why the delay? well I've been teaching myself to program of course! It's far from perfect, but I believe my logic for the 4-card hands is correct. Well, what did I get? Out of 2.6m random hands, ~95k of them were 4-card straights and ~89.5k were 4-card flushes. Along with ~1.16m high cards, ~1.05m pairs, ~54.8k trips and so on. Both of these 4-card hands still contain straight flush combos and I'm working that out but its 6:30 in the morning and I want to share something before I crash. That means your 4straight result is most likely correct! But how is my mathematical solution wrong? My brain already hurts and I don't wanna figure that out. That means then the actual number of 4flush combos should be closer to 86k, unless my code logic is undercounting something but it shouldn't with the lines

if temp_suit.count(0) == 4 or temp_suit.count(1) == 4 or temp_suit.count(2) == 4 or temp_suit.count(3) == 4:

is_4flush = True

where suits have a value of 0-3 hearts-spades. The hand is ranked higher than 4straight so that's not undercounted. I'd take another look at how you're counting 4flushes. I'll definitely have another go tomorrow and use this code to build onto the full game. I could provide the code somewhere if you'd like

Also, yes. That 5108 flush count is a silly mistake from me

link to original post

I learned 25 years ago that the double counting problem is hard and prone to subtle errors. I wanted a general solution. What I do to handle double counting is to write a series of functions defining any hand type in terms of five indices i0, i1, i2, i3, i4 which range from 0-51 for a standard deck with no jokers. Nada is the type that you refer to as 'high card'. In my VP program, I could assign a payoff to Nada if I wanted to. When my program reads in a pay table, it sets a variable is'Type' to the line number in the pay table (where 'Type' is a specific hand type like Flush). Every specific variable isType is initialized to -1 before this. The first thing any of these hand-definition functions does is check the type. If it is less than 0, then that particular type was never defined in the pay table and I can skip it.

void handInfo::setNada(int type)

{

int k, int i0, i1, i2, i3, i4;

if (type < 0) return; // isNada type was not found in pay table

for (i0 = 0; i0 < 48; i0++) {

for (i1 = i0 + 1; i1 < 49; i1++) {

for (i2 = i1 + 1; i2 < 50; i2++) {

for (i3 = i2 + 1; i3 < 51; i3++) {

for (i4 = i3 + 1; i4 < 52; i4++) {

k = indexHand(i0, i1, i2, i3, i4);

tentative(k, type);

}

}

}

}

}

}

All I did to implment you stud game was to add three new hand-definition functions and call them like this:

setSF4(v.isSF4, v.isRF4); // 4-Flush

setFl4(v.isFlush4); // 4-Flush

setStr4(v.isStr4); // 4-Straight

Here. v.isStr4 is the new type of a 4-Straight, etc. The setSF4() function defines 4-SF and 4-RF hands in the same function. A single hand could be resolved to isNada, isStr4, isFlush4, isStraight, isFlush, isSF4, isSF, and isRF. Only the last type would stick. Other hands could resolve to isNada, isHiPair, isStr4, isFlush4.

The indexHand(i0, i1, i2, i3, i4) function is implemented as an array lookup table. It is generic and reusable for any game. I currently support single and double joker games, so I can quickly index 54 choose 5 = 3162510 different hands. You could use a hash table to do this indexing faster, but the hash table would consume a lot of memory.

Quote:MentalIs this C++?

Python. Learned a tiny bit, made switching to other languages harder so stuck with it. I can still run ~150k hands/second on a r5 3600.

Anyways, I'm here to share my refined code update. I can confirm our results now match exactly. Hooray! Some things that were wrong were: the super simple checking for suits 0-3 when the suits were labeled 1-4 ;-; also I added 4sflush checks which was by far the most difficult thing with my logic. There was also this weird bug in my logic where the hand [A,K,4,3,2] would not register as a straight but [A,x,4,3,2] would.

You can check out my project at https://github.com/richodude/MinnesotaStud/tree/master

The part I'm most proud of is the logic I used to rank hands. Looking online, there's surprisingly little (at least that I understood) about programming poker. I took a concept from someone who categorized poker hand in excel and it will likely work with many cards and any poker combo.

Start by taking your list [x,x,x,x,x] and arrange your cards in order. I also had my cards in number form pulling from the list 2♥,2♣,2♦,2♠,3♥...A♠. So the hand [0,1,2,3,51] would be 2♥,2♣,2♦,2♠,A♠

Then do whatever you need to have the rank and suit separate. For example in the above list I made two separate lists, [2,2,2,2,14] and [1,2,3,4,4]. I'll call them the 'rank_list' and 'suit_list'

To find pairs, sets, two pairs, quads, and full houses, we can make another list I'll call 'has_pair'. Start by comparing index 0 and 1 (first and second number) and if they're the same, add 1 to the has_pair list, and if not, a 0. continue until index 4,5 where we will have a list looking like [1,1,1,0] Another example for [3♣,5♦,5♠,K♥,K♦] would yield the list [0,1,0,1]. The has_pair list determines the hand rank. [1,0,0,0] [0,1,0,0] [0,0,1,0] or [0,0,0,1] is just a pair, [1,0,1,0] [1,0,0,1] or [0,1,0,1] is two pair, [1,1,0,0] [0,1,1,0] or [0,0,1,1] is trips, [1,1,0,1] or [1,0,1,1] is a full house, and [1,1,1,0] or [0,1,1,1] is quads. A lot to read but the pattern is there.

to find flushes, you just find the mode of suit_list and if it's at least 4, you have a 4-card flush or better

to find straights (the tricky part) is actually pretty easy. I make another list called 'connector_list' and use it similarly to pair_list. if index 1 minus index 0 = 1, those two cards are connected to form a potential straight. the list [1,1,1,1] means a 5-card straight. Ace is 14 in my code so I added special logic for the case where the list is [1,1,1,0] and there is an Ace-Two present. 4-cards is a bit trickier but not too bad. lists [1,1,1,0] and [0,1,1,1] are 4straights, but also any single pair hand where the connector_list XOR the pair_list is [1,1,1,1] For example if the hand is [3♣,4♠,5♠,5♥,6♦] our connector_list would be [1,1,0,1] and the pair_list would be [0,0,1,0] XOR'ing combines the lists where they are not matching.

4-card straight flushes were pretty scuffed with the sheer amount of edge cases. Look at lines ~140 in HandRanking.py if you want to see how I did it

Most of this code was my brain doing the work, but every programmer knows there's some BS line that you need that you would never figure out yourself so thanks chatGPT for that. It also taught me a dual-line solution for cycling through all ~2.6 million hand combinations

import itertools

combinations = itertools.combinations(range(0,52),5)

for hand in combinations:

rank_the_hand()

remember python is line based rather than bracket/semicolon/whatever-else-you-use based in case it looks weird

Now I can actually move on to the game... *sudden realisation I've barely started this project*

I use python where I have to, but I am not proficient. I can usually understand code in any procedural programming language.

When I started out, I used an approach similar to the one you describe. But, I like to code fast and then check for mistakes. Someone who is more methodical than me might be able to code these classifying functions better than I can. I found that I make less mistakes by defining every hand within a class, and then having the program sort out which one is ranked highest. I can have my program print out any subset of hands with color coding for suits. I usually can spot any errors quickly.

The Wizard has a page somewhere on indexing any hand to an integer quickly. When I dug into the algorithm, it is equivalent to my array lookup table. That is, his indexing formula is equivalent to the math that the processor does to calculate the address of an element in a 4-dimensional array like the one I use. Since compiler know how to do array-index math very efficiently, my method is just a bit faster, but both methods are very fast in C++.

Let me know if you want or need any help with fast hand indexing. Since you are working on a stud game, you won't need fast code for drawing cards. If I recall correctly, I got hints for using the Serpinski triangle for this task from VP Genius. This is really the only way to go.