Poker program (My "triumphant return" to QB coding
Posted: Mon Jul 04, 2005 8:30 pm
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.
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.