9C 7D QS KS JS AS TSis given the highest ranking, as it is a royal flush; the hand
8S 9S QS KS JS AS TSis given the same ranking, so if one player has the
9C &D hole
cards and the other one has 8S 9S, it is a split pot.
Other hands rank lower, with a "Nine-high" hand being the worst
possible hand for Texas Hold'em. When it comes to a showdown, all
7-card hands (consisting of the two hole cards and 5 community cards)
are ranked, and the one with the best ranking wins.
Hand evaluators can be used to simulate games, preferrably a lot of
them, hence they need to be fast (on a modern PC, they should rank
millions of hands in a second). Such simulations can be used for
producing fancy graphics like this one: 

| Column | Name | Function | Values |
|---|---|---|---|
| 1 | Node ID | The ID of the node, which corresponds to the line number (-1) | 0-76513 |
| 2-14 | Next pointers | Pointers to the next node, from a "2" to an "A", so if we see a card with rank "J", we go to the node with the ID found in column 11. | 0-76513, 0 indicating that seeing such a rank (again) is not possible. |
| 15 | Flush class | The ID of the equivalence class if this node was reached by cards of the same color | -1 (indicating that this is not a flush yet), 1 (Royal flush) - 1599 (Seven high flush) |
| 16 | Rank class | The ID of the equivalence class if no flush is present | -1 (no seven cards yet), 11 (Four Aces) - 7462 (Seven High) |
| 17 | Cards | A textual depiction of the cards in this equivalence class | Things like [J, 4, 2] |
| 18 | Worst normal hand | The equivalence class ID of the worst hand reachable with this cards | 11-7462 |
| 19 | Worst flush hand | The equivalence class ID of the worst hand reachable with this cards, if they are from the same color, and a flush in this color is achieved | -1 for flush-incompatible cards (featuring pairs), 1-1599 |
| 20 | Best normal hand | The equivalence class ID of the best hand reachable with this cards (excluding flushes) | 11-7462 |
| 21 | Best flush hand | The equivalence class ID of the best flush hand reachable with this cards | -1 for flush-incompatible cards, 1-1599 |
configure.local in order to run
make (it contains the location of the JDK, which is
required for javah and the JNI header files). Java
sources need to be compiled by hand or in an IDE.
The code is pretty much undocumented, but should be easy to
understand. The Java sources in
src/handevaluator/generator are used for generating the
DAG, the other sources are for testing it. The C sources may use the
"SIMD-oriented Fast Mersenne Twister", which can be obtained here. (I
named the object file SFMT.eo, so a make
clean does not delete it.) Use it as you see fit, or edit
randomgenerator.h so that the standard
rand() function will be used.
| Experiment | Trials | Time in ms |
|---|---|---|
| Java Overhead | 3M | 4353 |
| Java One-Pass | 3M | 7235 |
| Java Two-Pass | 3M | 7071 |
| JNI | 3M | 6736 |
| C Overhead | 3M | 1470 |
| C Two-Pass | 3M | 2435 |
| Java Overhead | 15M | 21795 |
| Java One-Pass | 15M | 36106 |
| Java Two-Pass | 15M | 34686 |
| JNI | 15M | 33779 |
| C Overhead | 15M | 5931 |
| C Two-Pass | 15M | 11896 |
rand() function) and ranking them. On my almost vintage
P4 3Ghz I obtain approx. 3M ranked hands and 1.3M simulated hands per
second. The speedup over Java is smaller than I experienced before (I
once got a 150x speed-up for a model checker, but then the C version
also incorporated a lot of algorithmic improvements over the Java
version), but nevertheless expected. I think that neither the Java nor
the C version of the algorithm are really maxed out with respect to
optimization, though. Note that the algorithm does not involve
allocation/deallocation of memory (after initialization).