I am writing an AI to play 5 card Poker. In this version of Poker comes a point where a player is allowed to discard none, one, two or three of the cards in their hand and replace them with random ones from the deck.
EVALUATING A HAND
My AI can give a unique value to any possible poker hand, and this value also corresponds to how "good" the hand is - a higher valued hand will always beat a lower valued one. To do so, the hand is firstly sorted in terms of "most important" cards first, and "least" important last.
e.g.
Two Pair: 7C 7S 4H 4D AS
Straight: 9D 8C 7S 6D 5H
Full House: 2C 2D 2H 7S 7D
Each type of hand is also given a value corresponding to how good this hand type is:
Royal Flush = 9, Straight Flush = 8, ... ,Two Pair = 2, One Pair = 1, High Card = 0
Now, using these sorted hand, as well as its value, a unique hex value is computed for the hand. The hand type value is placed in the most significant position, and then each of the 5 cards values (minus 2) are placed in the order that the hand is sorted. These six hex digits are then concatenated to give the final hand value.
For example, a Royal Flush (AH KH QH JH 10H) would have its vale computed as such:
1st Digit 2nd Digit 3rd Digit 4th Digit 5th Digit 6th Digit
HAND VALUE BEST CARD NEXT BEST ... ... Worst Card
Decimal: RoyalF=9 A=14-2=12 K=13-2=11 Q=12-2=10 J=11-2=9 10=10-2=8
Hex: 9 C B A 9 8
-> Value = 9CBA98 ( = 10,271,384)
DISCARDING CARDS
My AI can now use these values to make decisions on how many, if any, cards to discard. Because of the way the hand is ordered, the cards to be discarded will always be the last card alone, the last two cards, or else the last 3 cards. A lot of work goes into this ordering of cards to ensure that the "least important" cards are last (for example, a broken straight JC 8H 7D 6S 5H would be reordered as 8H 7D 6S 5H JC, to ensure that the JC would be discarded, in the hope of completing the straight.
Next, my AI computes and stores all the possible hands that could be created by replacing the last 1, 2 or 3 cards with every possible combination of cards left in the deck (assuming, for now, that there are still 47 left). It can then compute the unique value for each of these possible hands. In terms of deciding what number of cards to discard, what I have done is simply computed the average hand values across the 3 groups of possible hands that could be achieved when discarding 1, 2, or 3 cards. Whichever of these has the highest average value (highest expected gain), it discards that number of cards, otherwise, if all 3 average values are less than the current hand value, it does not discard any cards.
THE ISSUE
For the most part, this works as I could have hoped. However, there are some rare cases where it does not work, and an average value lower than the value of the current hand is computed, yet, it would still be worth the risk to discard some of the cards.
An example of one of these hands is:
AH KD KS JC 10S
This hand is a broken straight, and so it is reordered as:
AH KD JC 10S KS
As of now, this hand is just a Pair, however, it is most certainly worth attempting to discard one of the Kings in the hope of getting a Queen and completing the Ace high Straight.
Despite this, when the average value is computed across all the hands possible whne discarding the King, it turns out to be a lower value than that of the current hand.
In order to overcome this, I was thinking along the lines of having the Hand Type Value (currently 9, 8, ... , 0) as a linearly/exponentially increasing function, thus the value of the hand type is increased as a factor of how good the hand is (perhaps powers of 2: 256, 128, ..., 4, 2, 1, 0).
This is just the first idea I have just brainstormed, so I do not know how well it would work. I am completely open to any other suggestions as to how this problem can be solved.