Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

PHP texas hold hand ranking help

Options
  • 30-03-2006 2:12pm
    #1
    Registered Users Posts: 7,869 ✭✭✭


    hey, im just looking for advice on the best way to get who has the best hand in texas hold em. ie how would i go about seeing who has a pair, 2 pair, flush, straight etc. would i be better to use an array with 1-52 representing each card or better having say 5c, 3d, Kh etc?
    thanks for the help.


Comments

  • Closed Accounts Posts: 4,943 ✭✭✭Mutant_Fruit


    Assign each card a "value" such as 1, 2, 3, 4... 13 and a type (spades/hearts etc). Then run a function that sees what values each person has, and if they have two cards of value 3 (i.e. two 3's) or two cards of value 11 (i.e. jack) then they have a pair. etc etc.

    You'll just have to run comparisons between all the possible winning hands to see if the persons current hand matches any of the winning hands.

    i.e. you could have
    if(card1.type == card2.type == card3.type)
    {
    return three_of_the_same_suit;
    }
    else if(card1.value == card2.value)
    {
    return pair;
    }

    etc etc.


  • Registered Users Posts: 7,869 ✭✭✭The_B_Man


    cool thanks. i was split between the two ways but i'll do it that way if its the best/easiest way.

    but then again, the problem with that is i have very little experience setting up objects and stuff in PHP, so never used the dot operator. plus, thats assuming i have deciphered which are the best 5 cards out of the 7 to use.
    this is turning out to be a little more complicated than i originally thought. :s


  • Closed Accounts Posts: 4,943 ✭✭✭Mutant_Fruit


    I'm not too sure on how texas holdem works... but if you're trying to find out which are the best 5... just run your "best hand" function on the hand with all seven cards. Then that function will return the best possible hand from those 7 (i.e. it might return 4_of_the_same_number), so then its up to you to then pick out the 5 cards needed to make that hand. In this case, you'd pick out the four cards with the same number, and then any other one.

    As you can see, finding the best 5 out of the 7 is simple as long as you've written a function which can find "winning hands" from the cards in your hand.

    EDIT: Its up to you to decide which way would be better, thats just the way i'd do it :p


  • Registered Users Posts: 7,869 ✭✭✭The_B_Man


    ye i know. the part that has me stuck is the actual function to get the best hand! i can easily get the 7 cards but going thru them to find a match is the hard part. i hav to look for a pair, 2 pairs, 3 of a kind, 4 of a kind, a straight, a flush, straight flush, royal flush so it might get tricky.


  • Moderators, Social & Fun Moderators Posts: 10,501 Mod ✭✭✭✭ecksor


    There are about 10000 ways of doing this and about 9990 of those ways are slow or error prone or both. Download the poker-eval libraries. If you're at all comfortable reading C, have a look at the way they build up caches of bitmasks for fast evaluation of hands and hand rankings.

    http://freshmeat.net/projects/poker-eval/


  • Advertisement
  • Registered Users Posts: 7,869 ✭✭✭The_B_Man


    ok thanks, i'll have a look.

    on another note. what would be feasible for me in terms of keeping track of the current active user? i hav a table for the game (with a filed "active_user") and another one wit a list of all the users in the game. i have to keep track of the player who starts the betting ie to the left of the dealer or whatever, but then if someone raises, the loop has to go back around until it gets back to the user who raised. but then in the next round, ie the flop, turn or river, the original player must make the first move.
    any ideas?


  • Closed Accounts Posts: 4,943 ✭✭✭Mutant_Fruit


    You could have an array of "Player" objects (or just a string array with player names) that holds all the players and a seperate variable that just holds the "first player". Then just loop through your array one by one until you reach the "first player" again.


  • Registered Users Posts: 885 ✭✭✭clearz


    Assign each card a "value" such as 1, 2, 3, 4... 13 and a type (spades/hearts etc). Then run a function that sees what values each person has, and if they have two cards of value 3 (i.e. two 3's) or two cards of value 11 (i.e. jack) then they have a pair. etc etc.

    You'll just have to run comparisons between all the possible winning hands to see if the persons current hand matches any of the winning hands.

    i.e. you could have
    if(card1.type == card2.type == card3.type)
    {
    return three_of_the_same_suit;
    }
    else if(card1.value == card2.value)
    {
    return pair;
    }

    etc etc.

    I think you have completely underestimated the scale of the problem. The algorithm could never be found using simple if/else clauses.
    I have attached a pure java based HandEvaluator that I found a while back when researching the problem. It is fully functional but I diddn't end up using it as it would be too slow on a server that needed to cater for 300-1000 players. I ended up building a JNI layer over the native poker-eval library that ecksor provided a link to. The speed gains where unbelievable. poker-eval is simply the best Texas Hold em HandEvaluator out there.

    The way both these methods work is you pass in 5 cards to a function and an integer is returned representing the value of the hand. Its then a simple mather of picking the player with the highest integer value right.

    wrong.

    Texas Holdem can have multiple pots and winners each round depending on how much each player has in the main pot. You will need to develop an algorithm that will handle multiple winner situitions which complicates things even more. I discused this problem on the poker forum before

    http://www.boards.ie/vbulletin/showthread.php?p=50891338#post50891338


  • Closed Accounts Posts: 4,943 ✭✭✭Mutant_Fruit


    clearz wrote:
    I think you have completely underestimated the scale of the problem. The algorithm could never be found using simple if/else clauses.
    Done and done.

    Just wrote an algorithm using simple if/else clauses (and some not so simple if/else clauses). I'm just gonna compile the C evaluator and see if it gives the same answers as my script. If it doesn't, mine is wrong. But i'd be fairly sure its right :P

    EDIT: I in no way expect this to be anyway near as fast as the C version... simply because this is C# (slower) and i'm crap (so i write slow code :P).


  • Moderators, Science, Health & Environment Moderators Posts: 8,950 Mod ✭✭✭✭mewso


    Theres a good chance if you are doing a holdem hand calculator that you want know what the hand is. i.e. out of 7 cards what is the best hand I have? Telling me which of 2 hands is better may not be sufficient.


  • Advertisement
  • Closed Accounts Posts: 4,943 ✭✭✭Mutant_Fruit


    musician wrote:
    Theres a good chance if you are doing a holdem hand calculator that you want know what the hand is. i.e. out of 7 cards what is the best hand I have? Telling me which of 2 hands is better may not be sufficient.
    Do you mean choosing the best 5 card hand out of the 7 available to you? I.e. checking each of the 21 five-card combinations to find the best hand?

    I'm not sure what ya mean when you say "telling me which of the 2 hands is better may not be sufficient".


  • Moderators, Science, Health & Environment Moderators Posts: 8,950 Mod ✭✭✭✭mewso


    I may have misunderstood this poker evaluator code. It says it gives the hand a number value. Maybe this number can be directly related to a particular hand. If so I'm wrong. Sorry wasn't referring to your solution.


  • Closed Accounts Posts: 4,943 ✭✭✭Mutant_Fruit


    Can anyone tell me how long it would take the C evaluator to evaluate 1,000,000 randomly generated hands?

    After a little (And i mean little) optimisation, i got mine down from 10 seconds (initial version) to a mere 1.43seconds. I'm expecting the C one to do about 20 million in that time. If not a lot more.


  • Moderators, Social & Fun Moderators Posts: 10,501 Mod ✭✭✭✭ecksor


    Is this on some sort of generalised testing computer that I've never heard of? I don't think I can adequately answer your question.

    Your if/else code above looks a bit strange. Are you actually able to rank a few hands in order of which beats what?


  • Registered Users Posts: 885 ✭✭✭clearz


    musician wrote:
    I may have misunderstood this poker evaluator code. It says it gives the hand a number value. Maybe this number can be directly related to a particular hand. If so I'm wrong. Sorry wasn't referring to your solution.

    Yes that is how most evaluators work. An unique integer value can be attributed to every possible hand combination. The higher the value the better the hand.

    Can anyone tell me how long it would take the C evaluator to evaluate 1,000,000 randomly generated hands?

    I'm just gonna run that test now using the C poker-eval lib and ill post the results. I would also like to see your solution if you dont mind posting it.


  • Closed Accounts Posts: 4,943 ✭✭✭Mutant_Fruit


    Is this on some sort of generalised testing computer that I've never heard of? I don't think I can adequately answer your question.
    Ah, very good point :P I was testing on a 1.7 ghz Pentium M, averaging my result over 5 runs of 1,000,000 comparisons.
    I'm just gonna run that test now using the C poker-eval lib and ill post the results. I would also like to see your solution if you dont mind posting it.
    I was looking at the poker eval library, but i was far too lazy to make it into a program to test it's speed. I'll nice my code up a little more with some comments, and then post it up if ya want. Its not the best solution (not by a long shot, a 52bit bit-array would be a lot faster to use as opposed to the objects i've made here). But it does demonstrate an easy enough way to compare hands. Its 95% finished. I think all that's left to do is the tie-breaker code.


  • Closed Accounts Posts: 4,013 ✭✭✭kincsem


    The_B_Man wrote:
    cool thanks. i was split between the two ways but i'll do it that way if its the best/easiest way.

    but then again, the problem with that is i have very little experience setting up objects and stuff in PHP, so never used the dot operator. plus, thats assuming i have deciphered which are the best 5 cards out of the 7 to use.
    this is turning out to be a little more complicated than i originally thought. :s

    Just came across your post.

    A few months ago on the poker forum there was a question posed "How often will you have the nuts?" (nuts = an unbeatable hand).

    I started to solve this using Foxpro and am about 10% from completion.
    So far I've programmed a deal (any number of hands e.g. million random hands) ..... your two hole cards and the five board cards ....... and worked out the best hand hand you can make from the seven.
    I have worked out most of the best possible hands from the unseen cards i.e. the five board cards and the 45 undealt cards. This is just a re-hash of my earlier work.
    There are nine possible hands - straight flush, quads, full house, flush, straight, trips, two pair, pair, high card.
    You need to assess each hand. Picking a hand of five from seven could give you a straight but also trips. You must then decide which is higher. And you must also consider kickers e.g. KK J 5 3 beats KK T 9 8
    I dropped it about a month ago due to circumstances but I'm so close I must finish it.
    The basic analysis can be used again to handle different poker questions and possibly rejigged to assist in decision making when playing poker online.


  • Closed Accounts Posts: 4,943 ✭✭✭Mutant_Fruit


    nuts = an unbeatable hand
    Meaning a royal flush?


  • Closed Accounts Posts: 4,943 ✭✭✭Mutant_Fruit


    I finally got around to testing the C library. It manages about 41 million comparisons per second. Mine manages about 3.3 million comparisons. That'd make the C routine roughly 12 times faster. Pretty much what i was expecting.

    Still, i've learned a bit. I've increased the initial performance of my C# routine quite a lot, so i'm happy. I'm sure it could be further improved upon by using a 52bit bit-array, but i'll leave that for the OP to do :p I'm far too lazy.

    The guts of my code is the following:
            // These bools are for making choosing the best hand
            // out of the available hands easy.
            internal bool twoOfAKindFirst = false;  // One pair found
            internal bool twoOfAKindSecond = false; // Second pair found
            internal bool flush = false;            // Flush found
            internal bool straight = true;          // Straight found
            internal bool threeOfAKind = false;     // Three Of A Kind found
            internal bool fourOfAKind = false;      // Four of a Kind
            
            internal int[] suit = new int[4];        // Int array to store how many of each suit we have
            internal int[] rank = new int[13];       // Int array to store how many of each rank we have.
          
            internal void PreProcessHand()
            {
                suit.Initialize();  // initialise array to 0's
                rank.Initialize();  // initialise array to 0's
    
                for (int i = 0; i < this.cards.Count; i++) // this.cards is my "Hand" array. It contains 5 'cards'.
                {
                    rank[cards[i].Rank - 1]++;
                    suit[cards[i].Suit]++;
                }
    
    
                for (int i = 0; i < suit.Length; i++)
                    if (i == 5)         //5 of the one suit is a flush
                        flush = true;
    
                for (int j = 0; j < rank.Length; j++)
                {
                    if (j > 0)
                    {
                        if (rank[j] != (rank[j - 1] + 1))   // check if all the cards are in ascending rank.
                        {                                   // if they are not, then set straight = false
                            straight = false;               // as we do not have a straight.
                        }
                    }
    
                    if (rank[j] == 4)                       // if we have four of this rank, we have four of a kind
                    {
                        fourOfAKind = true;
                    }
    
                    else if (rank[j] == 3)                  // if we have three of this rank, we have three of a kind
                    {
                        threeOfAKind = true;
                    }
    
                    else if (rank[j] == 2)                  // if we have two of this rank, we have two of a kind
                    {
                        if (!twoOfAKindFirst)               // If this is the first pair we've found
                        {                                   // set the firstPair variable to true
                            twoOfAKindFirst = true;
                        }
                        else
                        {                                   // if we have already found one pair
                            twoOfAKindSecond = true;        // we have two pairs.
                        }
                    }
                }
                // Previous check for a straight can't take into account an ace.
                // Its faster to do a single check for this outside of the above loop.
                // than adding in extra if statements above.
                if (rank[0] == 1 && rank[1] == 10 && rank[2] == 11 && rank[3] == 12 && rank[4] == 13)
                    straight = true;
            }
    
            public int Calculate()
            {
                PreProcessHand();
    
                // WinningHandType.RoyalFlush
                if (straight && flush && rank[0] == 1 && rank[4] == 14) // ace is first card, king is last.
                    return 900;
    
                //WinningHandType.StraightFlush
                if (straight && flush)
                    return 800;
    
                //WinningHandType.FourOfAKind
                if (fourOfAKind)
                    return 700;
    
               //WinningHandType.FullHouse
                if (twoOfAKindFirst && threeOfAKind)
                    return 600;
    
                //WinningHandType.Flush
                if (flush)
                    return 500;
    
               //WinningHandType.Straight
                if (straight)
                    return 400;
    
               //WinningHandType.ThreeOfAKind
                if (threeOfAKind)
                    return 300;
    
                //WinningHandType.TwoPairs
                if (twoOfAKindFirst && twoOfAKindSecond)
                    return 200;
    
               //WinningHandType.Pair
                if (twoOfAKindFirst)
                    return 100;
    
                return 1; // highcard
            }
    


  • Moderators, Social & Fun Moderators Posts: 10,501 Mod ✭✭✭✭ecksor


    Meaning a royal flush?

    Not exactly. In Hold 'em specifically (although it applies to some other forms of poker too), a player can look at the board and determine based upon the community cards whether or not they have the best possible two card combination to match the cards that are shared with everyone else. I.e, you know if you have the best possible hand or what someone would have to have to have the best possible hand. The best possible hand is called the nuts. On a board with a pair in it, the nuts is 4 of a kind. Or, if the board has a pair of it's highest ranking card on it and you have one of those plus one of the next highest rank, then you have the nut full house and you know that nobody can have quads out against you (of course someone could make a straight flush to beat your house on some boards, etc etc).

    I think I read somewhere that it's to do with some old american tradition of settlers betting their wagons on unbeatable hands, so they'd take the nuts off the wheels of their wagons and bet those on the table.


  • Advertisement
Advertisement