/src/UofAHandEval/ca/ualberta/cs/poker/HandEvaluator.java
Java | 1244 lines | 946 code | 126 blank | 172 comment | 368 complexity | 4d8c74fdf4264f435564eceb40438253 MD5 | raw file
- package UofAHandEval.ca.ualberta.cs.poker;
- /***************************************************************************
- Copyright (c) 2000:
- University of Alberta,
- Deptartment of Computing Science
- Computer Poker Research Group
- See "Liscence.txt"
- ***************************************************************************/
- /**
- * Class for identifying / comparing / ranking Hands.
- *
- * @author Aaron Davidson, Darse Billings, Denis Papp
- */
- public class HandEvaluator {
- public static void main(String args[]){
- Hand hand1 = new Hand("Kc 8c 9c Tc Jc Qc Ac");
- Hand hand2 = new Hand("Kc 8c 9c Tc Jc Qc Ad");
- Hand hand3 = new Hand("5s 5d 5c 5h 2c Qc Ad");
-
- HandEvaluator handEval = new HandEvaluator();
- System.out.println(handEval.getBest5CardHand(hand1));
- System.out.println(handEval.getBest5CardHand(hand2));
- System.out.println(handEval.getBest5CardHand(hand3));
- System.out.println(handEval.rankHand(hand1));
- System.out.println(handEval.rankHand(hand2));
- System.out.println(handEval.nameHand(hand1));
- System.out.println(handEval.nameHand(hand2));
- System.out.println(handEval.nameHand(hand3));
- }
-
- /**
- * Get a numerical ranking of this hand.
- *
- * @param c1
- * first hole card
- * @param c2
- * second hole card
- * @param h
- * a 3-5 card hand
- * @return a unique number representing the hand strength of the best 5-card
- * poker hand in the given cards and board. The higher the number,
- * the better the hand is.
- */
- public int rankHand(Card c1, Card c2, Hand h) {
- h.addCard(c1);
- h.addCard(c2);
- int rank = rankHand(h);
- h.removeCard();
- h.removeCard();
- return rank;
- }
- /**
- * Given a hand, return a string naming the hand ('Ace High Flush', etc..)
- */
- public static String nameHand(Hand h) {
- return name_hand(rankHand(h));
- }
- /**
- * Compares two hands against each other.
- *
- * @param h1
- * The first hand
- * @param h2
- * The second hand
- * @return 1 = first hand is best, 2 = second hand is best, 0 = tie
- */
- public int compareHands(Hand h1, Hand h2) {
- int r1 = rankHand(h1);
- int r2 = rankHand(h2);
- if (r1 > r2)
- return 1;
- if (r1 < r2)
- return 2;
- return 0;
- }
- /**
- * Compares two 5-7 card hands against each other.
- *
- * @param rank1
- * The rank of the first hand
- * @param h2
- * The second hand
- * @return 1 = first hand is best, 2 = second hand is best, 0 = tie
- */
- public int compareHands(int rank1, Hand h2) {
- int r1 = rank1;
- int r2 = rankHand(h2);
- if (r1 > r2)
- return 1;
- if (r1 < r2)
- return 2;
- return 0;
- }
- /**
- * Given a board, cache all possible two card combinations of hand ranks, so
- * that lightenting fast hand comparisons may be done later.
- */
- public int[][] getRanks(Hand board) {
- Hand myhand = new Hand(board);
- int[][] rc = new int[52][52];
- int i, j, v, n1, n2;
- Deck d = new Deck();
- d.extractHand(board);
- // tabulate ranks
- for (i = d.getTopCardIndex(); i < Deck.NUM_CARDS; i++) {
- myhand.addCard(d.getCard(i));
- n1 = d.getCard(i).getIndex();
- for (j = i + 1; j < Deck.NUM_CARDS; j++) {
- myhand.addCard(d.getCard(j));
- n2 = d.getCard(j).getIndex();
- rc[n1][n2] = rc[n2][n1] = rankHand(myhand);
- myhand.removeCard();
- }
- myhand.removeCard();
- }
- return rc;
- }
- /** ******************************************************************* */
- // MORE HAND COMPARISON STUFF (Adapted from C code by Darse Billings)
- /** ******************************************************************* */
- /**
- * Get the best 5 card poker hand from a 7 card hand
- *
- * @param h
- * Any 7 card poker hand
- * @return A Hand containing the highest ranked 5 card hand possible from the
- * input.
- */
- public Hand getBest5CardHand(Hand h) {
- int[] ch = h.getCardArray();
- int[] bh = new int[6];
- int j = Find_Hand(ch, bh);
- Hand nh = new Hand();
- for (int i = 0; i < 5; i++)
- nh.addCard(bh[i + 1]);
- return nh;
- }
-
- private final static int unknown = -1;
- private final static int strflush = 9;
- private final static int quads = 8;
- private final static int fullhouse = 7;
- private final static int flush = 6;
- private final static int straight = 5;
- private final static int trips = 4;
- private final static int twopair = 3;
- private final static int pair = 2;
- private final static int nopair = 1;
- private final static int highcard = 1;
- /**
- * Get a string from a hand type.
- *
- * @param handtype
- * number coding a hand type
- * @return name of hand type
- */
- private String drb_Name_Hand(int handtype) {
- switch (handtype) {
- case -1:
- return ("Hidden Hand");
- case 1:
- return ("High Card");
- case 2:
- return ("Pair");
- case 3:
- return ("Two Pair");
- case 4:
- return ("Three of a Kind");
- case 5:
- return ("Straight");
- case 6:
- return ("Flush");
- case 7:
- return ("Full House");
- case 8:
- return ("Four of a Kind");
- case 9:
- return ("Straight Flush");
- default:
- return ("Very Weird hand indeed");
- }
- }
- /* drbcont: want to Find_ the _best_ flush and _best_ strflush ( >9 cards) */
- private static boolean Check_StrFlush(int[] hand, int[] dist, int[] best) {
- int i, j, suit, strght, strtop;
- boolean returnvalue;
- int[] suitvector = new int[14];
- /*
- * _23456789TJQKA boolean vector 01234567890123 indexing
- */
- returnvalue = false; /* default */
- /* do flat distribution of whole suits (cdhs are 0123 respectively) */
- for (suit = 0; suit <= 3; suit++) {
- /* explicitly initialize suitvector */
- suitvector[0] = 13;
- for (i = 1; i <= suitvector[0]; i++) {
- suitvector[i] = 0;
- }
- for (i = 1; i <= hand[0]; i++) {
- if ((hand[i] != unknown) && ((hand[i] / 13) == suit)) {
- suitvector[(hand[i] % 13) + 1] = 1;
- };
- }
- /* now look for straights */
- if (suitvector[13] >= 1) /* Ace low straight */
- {
- strght = 1;
- } else
- strght = 0;
- strtop = 0;
- for (i = 1; i <= 13; i++) {
- if (suitvector[i] >= 1) {
- strght++;
- if (strght >= 5) {
- strtop = i - 1;
- };
- } else
- strght = 0;
- }
- /* determine if there was a straight flush and copy it to best[] */
- if (strtop > 0) { /* no 2-high straight flushes */
- for (j = 1; j <= 5; j++) {
- best[j] = ((13 * suit) + strtop + 1 - j);
- }
- /* Adjust for case of Ace low (five high) straight flush */
- if (strtop == 3) {
- best[5] = best[5] + 13;
- }
- returnvalue = true;
- }
- }
- return (returnvalue);
- }
- private void Find_Quads(int[] hand, int[] dist, int[] best) {
- int i, j, quadrank = 0, kicker;
- /* find rank of largest quads */
- for (i = 1; i <= 13; i++) {
- if (dist[i] >= 4) {
- quadrank = i - 1;
- }
- ;
- }
- /* copy those quads */
- i = 1; /* position in hand[] */
- j = 1; /* position in best[] */
- while (j <= 4) { /* assume all four will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == quadrank)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- /* find best kicker */
- kicker = unknown; /* default is unknown kicker */
- for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
- if ((dist[i] >= 1) && ((i - 1) != quadrank)) {
- kicker = i - 1;
- }
- }
- /* copy kicker */
- if (kicker != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 5) { /* assume kicker will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- }
- private void Find_FullHouse(int[] hand, int[] dist, int[] best) {
- int i, j, tripsrank = 0, pairrank = 0;
- /* find rank of largest trips */
- for (i = 1; i <= 13; i++) {
- if (dist[i] >= 3) {
- tripsrank = i - 1;
- }
- ;
- }
- /* copy those trips */
- i = 1; /* position in hand[] */
- j = 1; /* position in best[] */
- while (j <= 3) { /* assume all three will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == tripsrank)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- /* find best pair */
- i = 13;
- pairrank = -1;
- while (pairrank < 0) { /* assume kicker will be found before i = 0 */
- if ((dist[i] >= 2) && ((i - 1) != tripsrank)) {
- pairrank = i - 1;
- } else
- i--;
- }
- /* copy best pair */
- i = 1; /* position in hand[] */
- while (j <= 5) { /* assume pair will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == pairrank)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- }
- private void Find_Flush(int[] hand, int[] dist, int[] best) { /*
- * finds only
- * the best
- * flush in
- * highest
- * suit
- */
- int i, j, flushsuit = 0;
- int[] suitvector = new int[14];
- /*
- * _23456789TJQKA boolean vector 01234567890123 indexing
- */
- /* find flushsuit */
- for (i = 14; i <= 17; i++) {
- if (dist[i] >= 5) {
- flushsuit = i - 14;
- }
- ;
- }
- /* explicitly initialize suitvector */
- suitvector[0] = 13;
- for (i = 1; i <= suitvector[0]; i++) {
- suitvector[i] = 0;
- }
- /* do flat distribution of whole flushsuit */
- for (i = 1; i <= hand[0]; i++) {
- if ((hand[i] != unknown) && ((hand[i] / 13) == flushsuit)) {
- suitvector[(hand[i] % 13) + 1] = 1;
- }
- ;
- }
- /* determine best five cards in flushsuit */
- i = 13;
- j = 1;
- while (j <= 5) { /* assume all five flushcards will be found before i < 1 */
- if (suitvector[i] >= 1) {
- best[j] = (13 * flushsuit) + i - 1;
- j++;
- }
- ;
- i--;
- }
- }
- private void Find_Straight(int[] hand, int[] dist, int[] best) {
- int i, j, strght, strtop;
- /* look for highest straight */
- if (dist[13] >= 1) /* Ace low straight */
- {
- strght = 1;
- } else
- strght = 0;
- strtop = 0;
- for (i = 1; i <= 13; i++) {
- if (dist[i] >= 1) {
- strght++;
- if (strght >= 5) {
- strtop = i - 1;
- }
- ;
- } else
- strght = 0;
- }
- /* copy the highest straight */
- if (strtop > 3) { /* note: different extraction from others */
- for (j = 1; j <= 5; j++) {
- for (i = 1; i <= hand[0]; i++) {
- if ((hand[i] != unknown) && (hand[i] % 13 == (strtop + 1 - j))) {
- best[j] = hand[i];
- }
- ;
- }
- }
- } else if (strtop == 3) {
- for (j = 1; j <= 4; j++) {
- for (i = 1; i <= hand[0]; i++) {
- if ((hand[i] != unknown) && (hand[i] % 13 == (strtop + 1 - j))) {
- best[j] = hand[i];
- }
- ;
- }
- }
- for (i = 1; i <= hand[0]; i++) { /* the Ace in a low straight */
- if ((hand[i] != unknown) && (hand[i] % 13 == 12)) {
- best[5] = hand[i];
- }
- ;
- }
- }
- }
- private void Find_Trips(int[] hand, int[] dist, int[] best) {
- int i, j, tripsrank = 0, kicker1, kicker2;
- /* find rank of largest trips */
- for (i = 1; i <= 13; i++) {
- if (dist[i] >= 3) {
- tripsrank = i - 1;
- }
- ;
- }
- /* copy those trips */
- i = 1; /* position in hand[] */
- j = 1; /* position in best[] */
- while (j <= 3) { /* assume all three will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == tripsrank)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- /* find best kickers */
- kicker1 = unknown; /* default is unknown kicker */
- for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
- if ((dist[i] >= 1) && ((i - 1) != tripsrank)) {
- kicker1 = i - 1;
- }
- ;
- }
- kicker2 = unknown;
- for (i = 1; i <= kicker1; i++) { /* find rank of second kicker */
- if ((dist[i] >= 1) && ((i - 1) != tripsrank)) {
- kicker2 = i - 1;
- }
- ;
- }
- /* copy kickers */
- if (kicker1 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 4) { /* assume kicker1 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker1)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- if (kicker2 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 5) { /* assume kicker2 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker2)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- }
- private void Find_TwoPair(int[] hand, int[] dist, int[] best) {
- int i, j, pairrank1 = 0, pairrank2 = 0, kicker;
- /* find rank of largest pair */
- for (i = 1; i <= 13; i++) {
- if (dist[i] >= 2) {
- pairrank1 = i - 1;
- }
- ;
- }
- /* find rank of second largest pair */
- for (i = 1; i <= 13; i++) {
- if ((dist[i] >= 2) && ((i - 1) != pairrank1)) {
- pairrank2 = i - 1;
- }
- ;
- }
- /* copy those pairs */
- i = 1; /* position in hand[] */
- j = 1; /* position in best[] */
- while (j <= 2) { /* assume both will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == pairrank1)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- i = 1; /* position in hand[] */
- while (j <= 4) { /* assume both will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == pairrank2)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- /* find best kicker */
- kicker = unknown; /* default is unknown kicker */
- for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
- if ((dist[i] >= 1) && ((i - 1) != pairrank1) && ((i - 1) != pairrank2)) {
- kicker = i - 1;
- }
- }
- /* copy kicker */
- if (kicker != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 5) { /* assume kicker will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- }
- private void Find_Pair(int[] hand, int[] dist, int[] best) {
- int i, j, pairrank = 0, kicker1, kicker2, kicker3;
- /* find rank of largest pair */
- for (i = 1; i <= 13; i++) {
- if (dist[i] >= 2) {
- pairrank = i - 1;
- }
- ;
- }
- /* copy that pair */
- i = 1; /* position in hand[] */
- j = 1; /* position in best[] */
- while (j <= 2) { /* assume both will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == pairrank)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- /* find best kickers */
- kicker1 = unknown; /* default is unknown kicker */
- for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
- if ((dist[i] >= 1) && ((i - 1) != pairrank)) {
- kicker1 = i - 1;
- }
- ;
- }
- kicker2 = unknown;
- for (i = 1; i <= kicker1; i++) { /* find rank of second kicker */
- if ((dist[i] >= 1) && ((i - 1) != pairrank)) {
- kicker2 = i - 1;
- }
- ;
- }
- kicker3 = unknown;
- for (i = 1; i <= kicker2; i++) { /* find rank of third kicker */
- if ((dist[i] >= 1) && ((i - 1) != pairrank)) {
- kicker3 = i - 1;
- }
- }
- /* copy kickers */
- if (kicker1 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 3) { /* assume kicker1 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker1)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- if (kicker2 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 4) { /* assume kicker2 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker2)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- if (kicker3 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 5) { /* assume kicker3 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker3)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- }
- private void Find_NoPair(int[] hand, int[] dist, int[] best) {
- int i, j, kicker1, kicker2, kicker3, kicker4, kicker5;
- /* find best kickers */
- kicker1 = unknown; /* default is unknown kicker */
- for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
- if (dist[i] >= 1) {
- kicker1 = i - 1;
- }
- ;
- }
- kicker2 = unknown;
- for (i = 1; i <= kicker1; i++) { /* find rank of second kicker */
- if (dist[i] >= 1) {
- kicker2 = i - 1;
- }
- ;
- }
- kicker3 = unknown;
- for (i = 1; i <= kicker2; i++) { /* find rank of third kicker */
- if (dist[i] >= 1) {
- kicker3 = i - 1;
- }
- ;
- }
- kicker4 = unknown;
- for (i = 1; i <= kicker3; i++) { /* find rank of fourth kicker */
- if (dist[i] >= 1) {
- kicker4 = i - 1;
- }
- ;
- }
- kicker5 = unknown;
- for (i = 1; i <= kicker4; i++) { /* find rank of fifth kicker */
- if (dist[i] >= 1) {
- kicker5 = i - 1;
- }
- ;
- }
- /* copy kickers */
- j = 1; /* position in best[] */
- if (kicker1 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 1) { /* assume kicker1 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker1)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- if (kicker2 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 2) { /* assume kicker2 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker2)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- if (kicker3 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 3) { /* assume kicker3 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker3)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- if (kicker4 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 4) { /* assume kicker4 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker4)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- if (kicker5 != unknown) {
- i = 1; /* position in hand[] */
- while (j <= 5) { /* assume kicker5 will be found before i > hand[0] */
- if ((hand[i] != unknown) && ((hand[i] % 13) == kicker5)) {
- best[j] = hand[i];
- j++;
- }
- ;
- i++;
- }
- } else {
- best[j] = unknown;
- j++;
- }
- }
- private int Best_Hand(int[] hand1, int[] hand2) { /*
- * sorted 5-card hands,
- * both same type
- */
- /* could check for proper hand types... */
- /* check value of top cards, then on down */
- if ((hand1[1] % 13) > (hand2[1] % 13))
- return (1);
- else if ((hand1[1] % 13) < (hand2[1] % 13))
- return (2);
- /* same top, check second */
- else if ((hand1[2] % 13) > (hand2[2] % 13))
- return (1);
- else if ((hand1[2] % 13) < (hand2[2] % 13))
- return (2);
- /* same second, check third */
- else if ((hand1[3] % 13) > (hand2[3] % 13))
- return (1);
- else if ((hand1[3] % 13) < (hand2[3] % 13))
- return (2);
- /* same third, check fourth */
- else if ((hand1[4] % 13) > (hand2[4] % 13))
- return (1);
- else if ((hand1[4] % 13) < (hand2[4] % 13))
- return (2);
- /* same fourth, check fifth */
- else if ((hand1[5] % 13) > (hand2[5] % 13))
- return (1);
- else if ((hand1[5] % 13) < (hand2[5] % 13))
- return (2);
- else
- /* same hands */
- return (0);
- }
- private int Find_Hand(int[] hand, int[] best) { /* -1 means unknown card */
- int i, card, rank, suit, hand_type, rankmax1, rankmax2, flushmax, strght, strmax;
- int[] dist = new int[18];
- /*
- * _23456789TJQKAcdhs distribution vector 012345678901234567 indexing
- */
- /* explicitly initialize distribution vector */
- dist[0] = 17;
- for (i = 1; i <= dist[0]; i++) {
- dist[i] = 0;
- }
- for (i = 1; i <= hand[0]; i++) {
- if (hand[i] != unknown) {
- card = hand[i];
- rank = card % 13;
- suit = card / 13;
- if (!((rank < 0) || (rank > 12))) {
- dist[rank + 1]++;
- }
- if (!((suit < 0) || (suit > 3))) {
- dist[suit + 14]++;
- }
- }
- }
- /* scan the distribution array for maximums */
- rankmax1 = 0;
- rankmax2 = 0;
- flushmax = 0;
- strmax = 0;
- if (dist[13] >= 1) {
- strght = 1;
- } else
- strght = 0; /* Ace low straight */
- for (i = 1; i <= 13; i++) {
- if (dist[i] > rankmax1) {
- rankmax2 = rankmax1;
- rankmax1 = dist[i];
- } else if (dist[i] > rankmax2) {
- rankmax2 = dist[i];
- }
- ;
- if (dist[i] >= 1) {
- strght++;
- if (strght > strmax) {
- strmax = strght;
- }
- } else
- strght = 0;
- }
- for (i = 14; i <= 17; i++) {
- if (dist[i] > flushmax) {
- flushmax = dist[i];
- }
- }
- hand_type = unknown;
- if ((flushmax >= 5) && (strmax >= 5)) {
- if (Check_StrFlush(hand, dist, best)) {
- hand_type = strflush;
- } else {
- hand_type = flush;
- Find_Flush(hand, dist, best);
- }
- ;
- } else if (rankmax1 >= 4) {
- hand_type = quads;
- Find_Quads(hand, dist, best);
- } else if ((rankmax1 >= 3) && (rankmax2 >= 2)) {
- hand_type = fullhouse;
- Find_FullHouse(hand, dist, best);
- } else if (flushmax >= 5) {
- hand_type = flush;
- Find_Flush(hand, dist, best);
- } else if (strmax >= 5) {
- hand_type = straight;
- Find_Straight(hand, dist, best);
- } else if (rankmax1 >= 3) {
- hand_type = trips;
- Find_Trips(hand, dist, best);
- } else if ((rankmax1 >= 2) && (rankmax2 >= 2)) {
- hand_type = twopair;
- Find_TwoPair(hand, dist, best);
- } else if (rankmax1 >= 2) {
- hand_type = pair;
- Find_Pair(hand, dist, best);
- } else {
- hand_type = nopair;
- Find_NoPair(hand, dist, best);
- }
- ;
- return (hand_type);
- }
- /** ******************************************************************* */
- // DENIS PAPP'S HAND RANK IDENTIFIER CODE:
- /** ******************************************************************* */
- private static final int POKER_HAND = 5;
- public static final int HIGH = 0;
- public static final int PAIR = 1;
- public static final int TWOPAIR = 2;
- public static final int THREEKIND = 3;
- public static final int STRAIGHT = 4;
- public static final int FLUSH = 5;
- public static final int FULLHOUSE = 6;
- public static final int FOURKIND = 7;
- public static final int STRAIGHTFLUSH = 8;
- public static final int FIVEKIND = 9;
- public static final int NUM_HANDS = 10;
- private static final int NUM_RANKS = 13;
- private static final int ID_GROUP_SIZE = (Card.NUM_RANKS * Card.NUM_RANKS
- * Card.NUM_RANKS * Card.NUM_RANKS * Card.NUM_RANKS);
- private final static byte ID_ExistsStraightFlush(Hand h, byte major_suit) {
- boolean[] present = new boolean[Card.NUM_RANKS];
- // for (i=0;i<Card.NUM_RANKS;i++) present[i]=false;
- for (int i = 0; i < h.size(); i++) {
- int cind = h.getCardIndex(i + 1);
- if (Card.getSuit(cind) == major_suit) {
- present[Card.getRank(cind)] = true;
- }
- }
- int straight = present[Card.ACE] ? 1 : 0;
- byte high = 0;
- for (int i = 0; i < Card.NUM_RANKS; i++) {
- if (present[i]) {
- if ((++straight) >= POKER_HAND) {
- high = (byte) i;
- }
- } else {
- straight = 0;
- }
- }
- return high;
- }
- // suit: Card.NUM_SUITS means any
- // not_allowed: Card.NUM_RANKS means any
- // returns ident value
- private final static int ID_KickerValue(byte[] paired, int kickers,
- byte[] not_allowed) {
- int i = Card.ACE;
- int value = 0;
- while (kickers != 0) {
- while (paired[i] == 0 || i == not_allowed[0] || i == not_allowed[1])
- i--;
- kickers--;
- value += pow(Card.NUM_RANKS, kickers) * i;
- i--;
- }
- return value;
- }
- private final static int ID_KickerValueSuited(Hand h, int kickers, byte suit) {
- int i;
- int value = 0;
- boolean[] present = new boolean[Card.NUM_RANKS];
- // for (i=0;i<Card.NUM_RANKS;i++) present[i] = false;
- for (i = 0; i < h.size(); i++)
- if (h.getCard(i + 1).getSuit() == suit)
- present[h.getCard(i + 1).getRank()] = true;
- i = Card.ACE;
- while (kickers != 0) {
- while (present[i] == false)
- i--;
- kickers--;
- value += pow(Card.NUM_RANKS, kickers) * i;
- i--;
- }
- return value;
- }
- /**
- * Get a numerical ranking of this hand. Uses java based code, so may be
- * slower than using the native methods, but is more compatible this way.
- *
- * Based on Denis Papp's Loki Hand ID code (id.cpp) Given a 1-9 card hand,
- * will return a unique rank such that any two hands will be ranked with the
- * better hand having a higher rank.
- *
- * @param h a 1-9 card hand
- * @return a unique number representing the hand strength of the best 5-card
- * poker hand in the given 7 cards. The higher the number, the better
- * the hand is.
- */
- public final static int rankHand(Hand h) {
- boolean straight = false;
- boolean flush = false;
- byte max_hand = (byte) (h.size() >= POKER_HAND ? POKER_HAND : h.size());
- int r, c;
- byte rank, suit;
- // pair data
- byte[] group_size = new byte[POKER_HAND + 1]; // array to track the groups or cards in your hand
- byte[] paired = new byte[Card.NUM_RANKS]; // array to track paired carsd
- byte[][] pair_rank = new byte[POKER_HAND + 1][2]; // array to track the rank of our pairs
- // straight
- byte straight_high = 0; // track the high card (rank) of our straight
- byte straight_size;
- // flush
- byte[] suit_size = new byte[Card.NUM_SUITS];
- byte major_suit = 0;
- // determine pairs, dereference order data, check flush
- // for (r=0;r<Card.NUM_RANKS;r++) paired[r] = 0;
- // for (r=0;r<Card.NUM_SUITS;r++) suit_size[r] = 0;
- // for (r=0;r<=POKER_HAND;r++) group_size[r] = 0;
- for (r = 0; r < h.size(); r++) {
- int cind = h.getCardIndex(r + 1);
- rank = (byte) Card.getRank(cind);
- suit = (byte) Card.getSuit(cind);
- paired[rank]++; // Add rank of card to paired array to track the pairs we have.
- group_size[paired[rank]]++; // keep track of the groups in our hand (1-pair, 2-pair, 1-trips, 1-trips 1-pair)
- if (paired[rank] != 0) // To prevent looking at group_size[-1], which would be bad.
- group_size[paired[rank] - 1]--; // Decrese the previous group by one. group_size[0] should end up at -5.
- if ((++suit_size[suit]) >= POKER_HAND) { // Add suit to suit array, then check for a flush.
- flush = true;
- major_suit = suit;
- }
- }
- // Card.ACE low? Add to straight_size if so.
- straight_size = (byte) (paired[Card.ACE] != 0 ? 1 : 0);
- for (int i = 0; i < (POKER_HAND + 1); i++) {
- pair_rank[i][0] = (byte) Card.NUM_RANKS;
- pair_rank[i][1] = (byte) Card.NUM_RANKS;
- }
- // check for straight and pair data
- // Start at the Deuce. straight_size = 1 if we have an ace.
- for (r = 0; r < Card.NUM_RANKS; r++) {
- // check straight
- if (paired[r] != 0) {
- if ((++straight_size) >= POKER_HAND) { // Do we have five cards in a row (a straight!)
- straight = true; // We sure do.
- straight_high = (byte) r; // Keep track of that high card
- }
- } else { // Missing a card for our straight. start the count over.
- straight_size = 0;
- }
- // get pair ranks, keep two highest of each
- c = paired[r];
- if (c != 0) {
- pair_rank[c][1] = pair_rank[c][0];
- pair_rank[c][0] = (byte) r;
- }
- }
- // now id type
- int ident;
- if (group_size[POKER_HAND] != 0) { // we have five cards of the same rank in our hand.
- ident = FIVEKIND * ID_GROUP_SIZE; // must have five of a kind !!
- ident += pair_rank[POKER_HAND][0];
- return ident;
- }
- if (straight && flush) {
- byte hi = ID_ExistsStraightFlush(h, major_suit);
- if (hi > 0) {
- ident = STRAIGHTFLUSH * ID_GROUP_SIZE;
- ident += hi;
- return ident;
- }
- }
- if (group_size[4] != 0) {
- ident = FOURKIND * ID_GROUP_SIZE;
- ident += pair_rank[4][0] * Card.NUM_RANKS;
- pair_rank[4][1] = (byte) Card.NUM_RANKS; // just in case 2 sets quads
- ident += ID_KickerValue(paired, 1, pair_rank[4]);
- } else if (group_size[3] >= 2) {
- ident = FULLHOUSE * ID_GROUP_SIZE;
- ident += pair_rank[3][0] * Card.NUM_RANKS;
- ident += pair_rank[3][1];
- } else if (group_size[3] == 1 && group_size[2] != 0) {
- ident = FULLHOUSE * ID_GROUP_SIZE;
- ident += pair_rank[3][0] * Card.NUM_RANKS;
- ident += pair_rank[2][0];
- } else if (flush) {
- ident = FLUSH * ID_GROUP_SIZE;
- ident += ID_KickerValueSuited(h, 5, major_suit);
- } else if (straight) {
- ident = STRAIGHT * ID_GROUP_SIZE;
- ident += straight_high;
- } else if (group_size[3] == 1) {
- ident = THREEKIND * ID_GROUP_SIZE;
- ident += pair_rank[3][0] * Card.NUM_RANKS * Card.NUM_RANKS;
- ident += ID_KickerValue(paired, max_hand - 3, pair_rank[3]);
- } else if (group_size[2] >= 2) { // TWO PAIR
- ident = TWOPAIR * ID_GROUP_SIZE;
- ident += pair_rank[2][0] * Card.NUM_RANKS * Card.NUM_RANKS;
- ident += pair_rank[2][1] * Card.NUM_RANKS;
- ident += ID_KickerValue(paired, max_hand - 4, pair_rank[2]);
- } else if (group_size[2] == 1) { // A PAIR
- ident = PAIR * ID_GROUP_SIZE;
- ident += pair_rank[2][0] * Card.NUM_RANKS * Card.NUM_RANKS
- * Card.NUM_RANKS;
- ident += ID_KickerValue(paired, max_hand - 2, pair_rank[2]);
- } else { // A Low
- ident = HIGH * ID_GROUP_SIZE;
- ident += ID_KickerValue(paired, max_hand, pair_rank[2]);
- }
- return ident;
- }
- private static int pow(int n, int p) {
- int res = 1;
- while (p-- > 0)
- res *= n;
- return res;
- }
- private static final String[] hand_name = { "HIGH", "PAIR", "TWO PAIR",
- "THREE KIND", "STRAIGHT", "FLUSH", "FULL HOUSE", "FOUR KIND",
- "STRAIGHT FLUSH", "FIVE KIND" };
- private static final String[] rank_name = { "Two", "Three", "Four", "Five",
- "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace" };
- /**
- * Return a string naming the hand
- *
- * @param rank
- * calculated by rankHand_java()
- */
- private static String name_hand(int rank) {
- int type = (int) (rank / ID_GROUP_SIZE);
- int ident = (int) (rank % ID_GROUP_SIZE), ident2;
- String t = new String();
- switch (type) {
- case HIGH:
- ident /= NUM_RANKS * NUM_RANKS * NUM_RANKS * NUM_RANKS;
- t = rank_name[ident] + " High";
- break;
- case FLUSH:
- ident /= NUM_RANKS * NUM_RANKS * NUM_RANKS * NUM_RANKS;
- t = "a Flush, " + rank_name[ident] + " High";
- break;
- case PAIR:
- ident /= NUM_RANKS * NUM_RANKS * NUM_RANKS;
- t = "a Pair of " + rank_name[ident]+ (rank_name[ident].charAt(2)=='x'? "es":"s");
- break;
- case TWOPAIR:
- ident2 = ident / (NUM_RANKS * NUM_RANKS);
- ident = (ident % (NUM_RANKS * NUM_RANKS)) / NUM_RANKS;
- t = "Two Pair, " + rank_name[ident2]
- + (rank_name[ident2].charAt(2)=='x'? "es":"s")
- +" and " + rank_name[ident]
- + (rank_name[ident].charAt(2)=='x'? "es":"s");
- break;
- case THREEKIND:
- t = "Three of a Kind, " + rank_name[ident / (NUM_RANKS * NUM_RANKS)]
- + (rank_name[ident/ (NUM_RANKS * NUM_RANKS)].charAt(2)=='x'? "es":"s");
- break;
- case FULLHOUSE:
- t = "a Full House, " + rank_name[ident / NUM_RANKS]
- + (rank_name[ident/ NUM_RANKS].charAt(2)=='x'? "es":"s")+" over "
- + rank_name[ident % NUM_RANKS]
- + (rank_name[ident% NUM_RANKS].charAt(2)=='x'? "es":"s");
- break;
- case FOURKIND:
- t = "Four of a Kind, " + rank_name[ident / NUM_RANKS]
- + (rank_name[ident/ NUM_RANKS ].charAt(2)=='x'? "es":"s");
- break;
- case STRAIGHT:
- t = "a " + rank_name[ident] + " High Straight";
- break;
- case STRAIGHTFLUSH:
- t = "a " + rank_name[ident] + " High Straight Flush";
- break;
- case FIVEKIND:
- t = "Five of a Kind, " + rank_name[ident] + "s";
- break;
- default:
- t = hand_name[type];
- }
- return t;
- }
- }