Poker program (My "triumphant return" to QB coding

If you have questions about any aspect of QBasic programming, or would like to help fellow programmers solve their problems, check out this board!

Moderators: Pete, Mods

Post Reply
Snoogins47
Newbie
Posts: 2
Joined: Mon Jul 04, 2005 7:51 pm

Poker program (My "triumphant return" to QB coding

Post by Snoogins47 »

Okay, so the title is a bit of a joke. It's far from triumphant, I'm hardly returning, and nobody really cares.

This first part will be my vague backstory and introduction. You can skip it, if you want to get to the important part of the post.

I'm 20 years old, and currently playing poker professionally, and planning on using that income to put myself through school, if I can ever settle on one academic track long enough to actually get a degree. For a period of time in my younger days, I couldn't be pried away from the computer, and nearly all I did was program in QBasic. I never took any classes, read any books, or anything, so that period of time did a LOT more for furthering my aptitude for logic and mathematics as opposed to coding. So, basically 90% of what I know about programming is self-taught.

Until a few days ago, I hadn't fired up any form of Basic, or done any programming (though I had a brief stint of dabbling in HTML) in 8 or 9 years. "Rusty" doesn't even begin to describe it.

Anyway, three days ago, after arguing with somebody over the flaws of traditional poker analysis (I won't bore you with the details, but essentially, I feel that the tools that many players rely on for hand analysis are flawed enough that it can cause a lot of poor decisions and conclusions to be drawn) I thought about how to improve on it. I could come up with a marginally good answer, and a marginally efficient answer, but not both. I thought it would be interesting to write up a few simple programs to help me calculate common poker situations, and maybe I could crack this cookie. So I fired up QB.

I intended to only make very rudimentary programs, basically just to make my own methods of hand analysis easier, and to facilitate my laziness (I don't feel like plugging in 7 different variables, firing up a calculator, etc) I'm sure you understand that.

Today, the program I'm working on is a barebones architecture for a poker simulation program that places an emphasis on customization, so the applications can be broad. After finishing up all the codes for ranking hands and so forth, I'm debating trying to convert it to VB.net as my own crash course in the language, but that's a ways off, if it happens at all.

Progress is odd and sporadic (I seem to come up with a vastly superior way to do something every few hours, and have to run to the computer to re-work a certain routine), but going well. My two questions to you are things which I have not yet found an "easy" answer to, and am fairly convinced that I'm missing something obvious.




HERE'S THE QUESTION PART OF THE POST:

The way I have the program set up, each player's hand consists of however many cards the game requires. After shuffling and dealing, the data of a player's hand is basically laid out thusly.

Absolutecardrank = an integer, 1 through 52. This only really matters in the shuffle phase, but it *could* come in handy in a hand ranking process. I'm not sure. All the analysis on hand ranks I've done ignores this.

Cardrank= 1 through 13. 1 being a deuce, 2 being a three, and so on, with 13 being the ace. Originally, I had the ace represented by 1, but having it represented as 13 makes how I envisioned the hand-rankings a bit easier.

Cardsuit= 1 through 4. 1 is clubs, 2 is diamonds, 3 is hearts, you know the rest.


Detecting the presence of hands (A straight here, a flush here) is simple. The problem arises when ranking hands of the same "value" (I.E., comparing one flush to another, one straight to another, or more commonly, one pair to another, or possibly the kickers)

Now, the ways to rank hands in some cases is fairly easy to see. For instance, I assign a value, straight(i) where i = the numbers of players in the game. If this value is 0, he cannot use any combination of however many cards he has to make a straight. If it is a positive value, it correlates to the highest card of his straight. (4 = A2345, 5 = 23456, 13 = TJKWA, etc)

That's easy to compare when we get down to it. If the highest possible hands are straights, then this value alone denotes who wins the pot, or if it is split between tying hands (as suits do not have any bearing on power, four straights could split the pot)

Now, hands like flushes, one pair, etc... these get a bit trickier.


For flushes (5 cards the same suit, if anybody isn't familiar) , if two players hold a flush, they compare highest cards. Any flush containing an Ace beats any flush not containing an ace. If both flushes contain an Ace, the SECOND highest card is checked. If these match, the third is. Only when ALL FIVE match is the pot decided to be split.

My obtuse way of checking rankings between flushes and similar hands involves assigning a cardrank value, between 1 and 13, for each of the cards in the flush (so five values for each player). They'd then be compared individually, and so forth.

What I was wondering, is if anybody can envision a way to assign some sort of absolute value to these sorts of hands, as opposed to comparing the five individually. "Flush" is insufficient. "Flush containing Ace, Queen, Jack, Four, Deuce" (or more specifically, 13,11,10,5,3) seems to be a bit annoying as far as coding is concerned.

If there was some easy way to run through every possible flush combination (which I believe would be 1287 different flushes) and assign a value based on which combination the player's hand matched, this would return an absolute figure with which to rank the hands. I fear this would almost certainly be even MORE inefficient than my way. I also fear that I'm missing an easy solution, which tends to be a theme the past two days.


The second question is a bit shorter. I haven't implemented community card games (such as Texas Hold'em) yet, but it's easy to see how to do so. Player hands will consist of only 2 unique cards in Hold'em, and then the 5 community cards can be very easily applied to take up the values of card 3 through 7 in ALL player's hands, for ranking purposes.

There's a game called Omaha though, that I wouldn't mind implementing. This is a similar game to hold'em. Each player receives four cards, and there are five community cards. However, to make their hands, each player must use ONLY 2 from his hand and ONLY 3 from the community. No more, no less.

I could set up a function/subroutine to run through all the possible hand combinations, but this would GREATLY complicate things, and not be efficient at all.

If I use the idea mentioned above, it would become a process of evaluating 60 7-card hands for EACH player, returning the highest ranked one of those, and THEN comparing those 9 highest individually. Not so efficient, eh? It's nice to have the luxury nowadays that redundancy in code, especially in a program like this, probably barely effects performance. But I'm not one for redundancy just because "it works," if I can avoid it.

Any easy way that I'm overlooking to implement that?


Thanks a bunch in advance everybody.
User avatar
Xerol
Veteran
Posts: 81
Joined: Tue Jan 04, 2005 6:27 pm
Location: Timonium, MD
Contact:

Post by Xerol »

I think the best way to implement the hand ranking would be as follows:

1) Determine WHAT the best hand the player has is. Assign these values in terms of 1000's:

High Card: 0
One Pair: 1000
Two Pair: 2000
Three of a Kind: 3000
Straight: 4000
Flush: 5000
Full House: 6000
Four of a Kind: 7000
Straight Flush: 8000

Then, depending on the type of hand(this can be handled with a SELECT CASE) assign extra points. For one pair, 3 of a kind, straight, flush, 4 of a kind, and straight flush, this can just be the high card. So a pair of 2's would be "worth" 1001, and a pair of aces 1013. Meanwhile the three kings are worth 3012, and beat both of those other hands.

Two pair is slightly more complicated, but not too hard. Add the high pair's value times 13, and then add the low pair's value. So pairs of A-Q would be worth 2000 + 13*13 + 11 or 2180 points, while someone with A-K would have 2181, and someone with K-Q would only have 2168 points. Since you're multiplying the high card by 13, it gets enough "weight" to beat out the worse hand (even if the sum of the values of the cards is the same). The same concept can be applied to the full house.


As far as the second situation goes, you'll probably just have to deal with it. It's pretty much the same situation as figuring out hands for Texas Hold'Em, but you've got more local cards to deal with, and that just complicates things a little. Obviously you'd need to modularise your code, making a single function to calculate the value of a particular five card hand, and just call that function a lot.
If you need music composed in MP3, WAV, or MIDI format, please contact me via email.

Xerol's Music - Updated Regularly!
MystikShadows
Veteran
Posts: 703
Joined: Sun Nov 14, 2004 7:36 am
Contact:

Re: Poker program (My "triumphant return" to QB co

Post by MystikShadows »

Snoogins47 wrote:Okay, so the title is a bit of a joke. It's far from triumphant, I'm hardly returning, and nobody really cares.

This first part will be my vague backstory and introduction. You can skip it, if you want to get to the important part of the post.

I'm 20 years old, and currently playing poker professionally, and planning on using that income to put myself through school, if I can ever settle on one academic track long enough to actually get a degree. For a period of time in my younger days, I couldn't be pried away from the computer, and nearly all I did was program in QBasic. I never took any classes, read any books, or anything, so that period of time did a LOT more for furthering my aptitude for logic and mathematics as opposed to coding. So, basically 90% of what I know about programming is self-taught.
Man, you have NO idea how long I've waited for your return....Infact, I don't even have an idea I waited so long for your return ;-). But welcome back none the less :-). even if it's my first time seeing you ever lol.
Until a few days ago, I hadn't fired up any form of Basic, or done any programming (though I had a brief stint of dabbling in HTML) in 8 or 9 years. "Rusty" doesn't even begin to describe it.

Anyway, three days ago, after arguing with somebody over the flaws of traditional poker analysis (I won't bore you with the details, but essentially, I feel that the tools that many players rely on for hand analysis are flawed enough that it can cause a lot of poor decisions and conclusions to be drawn) I thought about how to improve on it. I could come up with a marginally good answer, and a marginally efficient answer, but not both. I thought it would be interesting to write up a few simple programs to help me calculate common poker situations, and maybe I could crack this cookie. So I fired up QB.

I intended to only make very rudimentary programs, basically just to make my own methods of hand analysis easier, and to facilitate my laziness (I don't feel like plugging in 7 different variables, firing up a calculator, etc) I'm sure you understand that.

Today, the program I'm working on is a barebones architecture for a poker simulation program that places an emphasis on customization, so the applications can be broad. After finishing up all the codes for ranking hands and so forth, I'm debating trying to convert it to VB.net as my own crash course in the language, but that's a ways off, if it happens at all.

Progress is odd and sporadic (I seem to come up with a vastly superior way to do something every few hours, and have to run to the computer to re-work a certain routine), but going well. My two questions to you are things which I have not yet found an "easy" answer to, and am fairly convinced that I'm missing something obvious.
Sounds like a very interesting project you set yourself, I'd be more than curious and interested to see what it can do and what it will do in the future :-).
HERE'S THE QUESTION PART OF THE POST:

The way I have the program set up, each player's hand consists of however many cards the game requires. After shuffling and dealing, the data of a player's hand is basically laid out thusly.

Absolutecardrank = an integer, 1 through 52. This only really matters in the shuffle phase, but it *could* come in handy in a hand ranking process. I'm not sure. All the analysis on hand ranks I've done ignores this.

Cardrank= 1 through 13. 1 being a deuce, 2 being a three, and so on, with 13 being the ace. Originally, I had the ace represented by 1, but having it represented as 13 makes how I envisioned the hand-rankings a bit easier.

Cardsuit= 1 through 4. 1 is clubs, 2 is diamonds, 3 is hearts, you know the rest.


Detecting the presence of hands (A straight here, a flush here) is simple. The problem arises when ranking hands of the same "value" (I.E., comparing one flush to another, one straight to another, or more commonly, one pair to another, or possibly the kickers)

Now, the ways to rank hands in some cases is fairly easy to see. For instance, I assign a value, straight(i) where i = the numbers of players in the game. If this value is 0, he cannot use any combination of however many cards he has to make a straight. If it is a positive value, it correlates to the highest card of his straight. (4 = A2345, 5 = 23456, 13 = TJKWA, etc)

That's easy to compare when we get down to it. If the highest possible hands are straights, then this value alone denotes who wins the pot, or if it is split between tying hands (as suits do not have any bearing on power, four straights could split the pot)

Now, hands like flushes, one pair, etc... these get a bit trickier.


For flushes (5 cards the same suit, if anybody isn't familiar) , if two players hold a flush, they compare highest cards. Any flush containing an Ace beats any flush not containing an ace. If both flushes contain an Ace, the SECOND highest card is checked. If these match, the third is. Only when ALL FIVE match is the pot decided to be split.

My obtuse way of checking rankings between flushes and similar hands involves assigning a cardrank value, between 1 and 13, for each of the cards in the flush (so five values for each player). They'd then be compared individually, and so forth.

What I was wondering, is if anybody can envision a way to assign some sort of absolute value to these sorts of hands, as opposed to comparing the five individually. "Flush" is insufficient. "Flush containing Ace, Queen, Jack, Four, Deuce" (or more specifically, 13,11,10,5,3) seems to be a bit annoying as far as coding is concerned.

If there was some easy way to run through every possible flush combination (which I believe would be 1287 different flushes) and assign a value based on which combination the player's hand matched, this would return an absolute figure with which to rank the hands. I fear this would almost certainly be even MORE inefficient than my way. I also fear that I'm missing an easy solution, which tends to be a theme the past two days.
Imagine an array of possible hands (can't think of them all but let's assume 5 hands) and a multiplier (if they are 5 hands then

RoyalFlush 5
Flush 4
4 of a kind 3
Straight 2
Full House 1

if there are 9 possible hands then Royal Flush gets 9, Flush get 8, etc etc down the list. Each card have 1 to 13 in each suitee

With this matrix of 5 by 13 you could create a multiplication table even before you know which hand you're dealing with.

Royal Flush 2, 3, 4, 5, 6 would be 1*2*3*4*5
Royal Flush 10, J, Q, K, A would be 9*10*11*12*13

Royal flush needs 5 cards so you'd have 8 possible values and based on which set of cards form the flush you'd have just one value to compare

Starting to sound longer than your test? lol....I'll see about making the matrix so you know exactly what I'm talking about :-).

The second question is a bit shorter. I haven't implemented community card games (such as Texas Hold'em) yet, but it's easy to see how to do so. Player hands will consist of only 2 unique cards in Hold'em, and then the 5 community cards can be very easily applied to take up the values of card 3 through 7 in ALL player's hands, for ranking purposes.

There's a game called Omaha though, that I wouldn't mind implementing. This is a similar game to hold'em. Each player receives four cards, and there are five community cards. However, to make their hands, each player must use ONLY 2 from his hand and ONLY 3 from the community. No more, no less.

I could set up a function/subroutine to run through all the possible hand combinations, but this would GREATLY complicate things, and not be efficient at all.

If I use the idea mentioned above, it would become a process of evaluating 60 7-card hands for EACH player, returning the highest ranked one of those, and THEN comparing those 9 highest individually. Not so efficient, eh? It's nice to have the luxury nowadays that redundancy in code, especially in a program like this, probably barely effects performance. But I'm not one for redundancy just because "it works," if I can avoid it.

Any easy way that I'm overlooking to implement that?


Thanks a bunch in advance everybody.
I say it's the best way to code, without redundancy. It's always the best way. I see about that matrix and let you know. of course of you could post your code I could compare my technique with yours :-)....maybe even email it to me even :-)
When God created light, so too was born, the first Shadow!

MystikShadows

Need hosting? http://www.jc-hosting.net

Interested in Text & ASCII development? Look no further!
http://www.ascii-world.com
Antoni
Veteran
Posts: 132
Joined: Wed Jun 15, 2005 3:01 pm
Contact:

Post by Antoni »

A poker duel is preparing.....

Pete: Prepare a "Mississippi boat" skin for the forum!
MystikShadows
Veteran
Posts: 703
Joined: Sun Nov 14, 2004 7:36 am
Contact:

Post by MystikShadows »

LOL Antoni....Can bring my gun to put on the table huh, can I can I can I? ;-)
When God created light, so too was born, the first Shadow!

MystikShadows

Need hosting? http://www.jc-hosting.net

Interested in Text & ASCII development? Look no further!
http://www.ascii-world.com
Antoni
Veteran
Posts: 132
Joined: Wed Jun 15, 2005 3:01 pm
Contact:

Post by Antoni »

Better a gambler's gun hidden in the sock...
MystikShadows
Veteran
Posts: 703
Joined: Sun Nov 14, 2004 7:36 am
Contact:

Post by MystikShadows »

well of course I got one of those ;-)...but the big gun on the table is more intimidating ;-)..lol
When God created light, so too was born, the first Shadow!

MystikShadows

Need hosting? http://www.jc-hosting.net

Interested in Text & ASCII development? Look no further!
http://www.ascii-world.com
Antoni
Veteran
Posts: 132
Joined: Wed Jun 15, 2005 3:01 pm
Contact:

Post by Antoni »

Now seriously...
Being poker played for centuries with the same rules, is there still place for strategic improvements? It must have been studied by generations of statisticians. Ibelieved it was more a matter of psychology, of deducting what's the contrary's game from his/her reactions...
Am I wrong?
Snoogins47
Newbie
Posts: 2
Joined: Mon Jul 04, 2005 7:51 pm

Re: Poker program (My "triumphant return" to QB co

Post by Snoogins47 »

First off, let me say thanks for the replies.
MystikShadows wrote: Imagine an array of possible hands (can't think of them all but let's assume 5 hands) and a multiplier (if they are 5 hands then

RoyalFlush 5
Flush 4
4 of a kind 3
Straight 2
Full House 1

if there are 9 possible hands then Royal Flush gets 9, Flush get 8, etc etc down the list. Each card have 1 to 13 in each suitee

With this matrix of 5 by 13 you could create a multiplication table even before you know which hand you're dealing with.

Royal Flush 2, 3, 4, 5, 6 would be 1*2*3*4*5
Royal Flush 10, J, Q, K, A would be 9*10*11*12*13

Royal flush needs 5 cards so you'd have 8 possible values and based on which set of cards form the flush you'd have just one value to compare

Starting to sound longer than your test? lol....I'll see about making the matrix so you know exactly what I'm talking about :-).
I'm not 100% sure I understand what you're saying, but let me try to clarify where I'm struggling here:

Is the idea to use the value of card1*card2*card3*card4*card5 to compare hand ranks within the hand 'types' (such as flush, full house, etc)? That's gonna be an issue if it's purely that, because, for instance:

Hand 1: Flush; Ad(13) * 2d(1) * 3d(2) * 4d(3) * 6d(5)
Hand 2: Flush; Kh(12) * Qh(11) * Jh(10) * Th(9) * 9h(8)

(Actual best hand)Hand 1:390
(Worst hand) Hand 2:95040


Now, if the idea was to go one step farther, and assign each potential value of the multiplied cards together to a rank of 1 to X where X is the number of combinations possible (for instance, take the value of the worst possible flush, which would be 1*2*3*4*6, and then have some sort of data set that would input the value (144 in this case) and assign a rank of 1 to it. Repeat ad nauseum. Well, that's a whole lot of data to set manually beforehand, and if any value of X1*X2*X3*X4*X5 repeats itself, well... yeah.


So there's a good chance I'm not quite understanding your method here.



As for Xerol: It seems to be an excellent way of doing things, but I think the precise formula would have to be re-tooled. Flushes and "high card" hands are again where the issue lies, as the specific ranks of every single card in a flush are important as far as rankings go. Just have to think a little more about the details as far as implementation, and the easiest way to assign absolute mathematical ranks based on the cards (basically, just the precise values to subscribe for each individual card in the hand based on 'importance' like you mentioned with two pair) Might take more than just 4 digits, but that's not the biggest deal. Kickers complicate things too, but not to that much of an extent.

This is probably the general method I'm going to implement.


As for the second issue: Last night I had a manic-depressive sort of 5 minutes. At about 3am, while on the slightly inebriated side of life sitting on the porch of my friend's apartment, I had a revelation.

There's 60 5 card hands to rank, but the handranking code is designed to look at hands with any number of cards. I realized that there would only be SIX 7-card hands possible: all combinations of two of the heros' hole cards, + the five board cards.

Then I realized that if I wanted to do things that way, I'd have to re-tool the hand detection code even more, since I'd have to add a qualifier that made sure that you're using only 3 from one pool, and 2 from the other. This was disappointing, because in my state at the time, my thoughts were that Omaha implementation would take basically zero thought, and then that was proven wrong. It will require a tad more thought to implement this, but at probably 1/10th the computing power needed, I think I'll probably give that a shot.
Sounds like a very interesting project you set yourself, I'd be more than curious and interested to see what it can do and what it will do in the future
Probably not nearly as much as would be necessary to make it TOO useful. To make it more useful that a typical poker evaluator (which are available free online) I would have to add some sort of somewhat meaningful AI, and allow that to be customizeable. I don't think I have the energy to get that going on my own.

However, I think user-defined actions for each player could make the program useful enough to actually matter. For instance, a program that can Monte-Carlo the hell out of AQs vs. 4h4s in Texas Hold'em is pretty worthless, considering the glut of them out there, for free. However, if this program ends up as I want it, there are definitely some things it could do that you can't do with just any program around the 'net.

The example I think of: Take this situation:

The active player holds Ad 2d and the board is 5d 9d Jh 7s

We could throw some parameters into the action, and monte-carlo the hell out of that, to get something that is much closer to useful. For instance, a tree of decisions where say, for instance, our hero might bet, and play the rest of the hand differently depending on the other players actions, as well as the cards that come.

That brings me to another question, something that I have no idea about (as you'll recall, I haven't coded in a long time. I wasn't really "good" then, but I come from a time where my standard pause in a program was)


Code: Select all

For t = 1 to 1000
next t
My question is, what sort of limitations would QBasic have in running Monte-Carlo type analysis, and what do you think the best way to implement it would be? (For those not familiar, I basically just mean running the same situation over and over and over again until the average results are at least somewhat meaningful.)

And the kicker (I searched around the 'net but couldn't find a good answer):

How good/bad is the standard RNG in QB? I've never really thought about it before, but does your everyday run of the mill randomize timer seed plus int(rand*13) sort of command generate a normal distribution? If not, that's something I should probably work on before I go any farther with this program.

Thanks again all for the help[/i]
MystikShadows
Veteran
Posts: 703
Joined: Sun Nov 14, 2004 7:36 am
Contact:

Post by MystikShadows »

Random isn't all that good in QB....over a large number of random calls it might server it's purpose however, but not for like a couple hundrad randoms sample..But there are algorithms to help with good randomness..you can google for those and get a couple good examples.

QB is capable of running monte carlo simulations...but with a limited range of probably 32761 since it's the limit of the arrays in QB...in freebasic that dissapears :-)....
When God created light, so too was born, the first Shadow!

MystikShadows

Need hosting? http://www.jc-hosting.net

Interested in Text & ASCII development? Look no further!
http://www.ascii-world.com
User avatar
{Nathan}
Veteran
Posts: 1169
Joined: Thu Aug 19, 2004 6:08 pm
Location: The wetlands of central Ohio, USA
Contact:

Post by {Nathan} »

I can't help ya there, but I would love to help with GFX if you decide to add any and testing... I love poker. I am going to have to teach my dad's friends Omaha next time I play with them.
Image
User avatar
Xerol
Veteran
Posts: 81
Joined: Tue Jan 04, 2005 6:27 pm
Location: Timonium, MD
Contact:

Post by Xerol »

Does anyone play on PartyPoker? We oughta get a game going sometime.
If you need music composed in MP3, WAV, or MIDI format, please contact me via email.

Xerol's Music - Updated Regularly!
Post Reply