Friday, 25 November 2011

Java: Texas Hold Em (10)

Hi hi, this is the last post for the week, because I'm lazy and went down to only 5 posts a week, remember. Going to be continuing with our HandEvaluator, which is fairly big, as far as what we've seen goes, and it'll be made longer by me messing around and looking for better ways to do what Stigter did! At least, for my own uses.

Now, we want our evaluator to work straight off, on being created, without calling any special methods on the object, which means our constructor is actually going to need to make use of methods we declare in the class. For this reason, it's probably best that we don't work on the constructor until we finish our methods! Here's what I got so far:

Hoo boy, shit gets complicated now. But hey, good news is I found why the rankDist and suitDist arrays were there. More on that later! Be sure to click on the image if you need it enlarged!

The method starting on line 65 is just a getType method, this actually tells us what the hand has, be it nothing or a straight flush. Get methods, woo!
The one starting on line 70 gets back the value. This is an integer representation of a hand, primarily used to compare hands to each other (in case of both hands having the same value type, 2 players with One Pair, for instance). This is actually pretty smart, and I would not have come up with it on my own! Remember the powers of 13 array in the instance variables? That's used to generate this value. I still don't fully get it, but I get that its awesome, and saves a lot of time compared to what I was planning out!

Those were just our basic get methods (and what I learned while playing with them), these next 2 methods get a lot trickier, starting with calculateDistributions() starting on line 74. Yeah, these are used to hold what the cards actually contain. For instance, if I've only been dealt one hand, and its a Three of Hearts, this method will go to the arrays, then add 1 to the position in rankDist that represents Three, and likewise for the suit. The great advantage to this is, its now tremendously easy to check if we have a pair, three of a kind, 2 pairs or 4 of a kind (Just check rankDist for a value higher than 1, meaning more than 1 card in the hand holds that rank), as well as a flush (look in suitDist), and to a lesser extend, a straight (look for 5 1's in a row). See, this might be obvious to other programmers, I don't know, but it struck me as absolute brilliance!

One last method for this screenshot, and that is to find flushes. The method reads as follows:
Lines 85-87: For every suit in the distribution, if there's 5 of said suit, the suit of the flush is that one.
Lines 88-89: Then, for every card in the given set, if a card's suit is the same as that of the flush suit...
Lines 90-92: ...and its not a wheeling straight, or the card just isn't an ace, make the rank of the flush the same as this card. Now gtfo of the loop.
All this does is set a rank and suit for a flush, if a flush actually exists! Not as complex as I made out, but compared to our get methods, sure works up a mental sweat :D

Oh fuck, that was only 1 screenshot? I'll probably cut back to 1, or 1 and a half, these make posts really really long. But eh, today I prepared a full second one, so lucky you!

This one's got some size on it, it's only a single method! Finding a straight, first we need some variables, one to hold whether or not we actually HAVE a straight, then another to hold the rank of said straight.
This method is straight from Mr. Stigter's work, so bear with me. Lines 107-122 is a huge for-loop, it starts at the highest possible rank (Position 12 [13th value] of rankDist), and goes all the way down.
Lines 108-110 check to see if a card exists with the current rank (Going through the highest first), if the value at the position is 0, a card does not exist, so there is no straight with that rank, and then the count is reset to 0. This reset is used in case of having a Jack through Ace, but no 10 existing, so we get to reset!
Lines 111-116 is part of what we'd do in the case of a card actually existing. If we don't currently have a straight going on, we toggle the boolean and set the rank to this value. If we do have a potential straight, skip this and go right on to...
Lines 117-122, where we increase the count every time a new card is found without a break. When the count is at 5, we officially set the straight's rank and leave the loop.
Lines 123-128 are what we use in the case of a wheeling straight (where the Ace is the low card), this would only give us a count of 4 using the above loop, so if count is 4 AND the high card is five, AND there's an Ace available, we set the wheelingAce variable to true, and officially set our straight rank.

God DAMN that took some time. See ya'll on Monday! Questions/comments welcome, as always!


  1. Each time is complicating more and more, but great explanation as always.

    A question, with a program like the one you're designing it's possible to make any kind of "online poker" with payments and stuff or is so much more complicated?

  2. @Orang3 It totally is, BUT nothing in the realm of what I can do! Sorry! I might work on it after I've got a bit more experience under my belt, but online takes some networking skill! (I'll repeat this in my Monday post in case you don't read it here)

  3. I'm so lazy, too.

  4. It's good to take time off for yourself too you know, don't feel bad. :P