PageRenderTime 61ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/src/UofAHandEval/ca/ualberta/cs/poker/HandEvaluator.java

https://github.com/WilliamsBros/NLBot
Java | 1244 lines | 946 code | 126 blank | 172 comment | 368 complexity | 4d8c74fdf4264f435564eceb40438253 MD5 | raw file
  1. package UofAHandEval.ca.ualberta.cs.poker;
  2. /***************************************************************************
  3. Copyright (c) 2000:
  4. University of Alberta,
  5. Deptartment of Computing Science
  6. Computer Poker Research Group
  7. See "Liscence.txt"
  8. ***************************************************************************/
  9. /**
  10. * Class for identifying / comparing / ranking Hands.
  11. *
  12. * @author Aaron Davidson, Darse Billings, Denis Papp
  13. */
  14. public class HandEvaluator {
  15. public static void main(String args[]){
  16. Hand hand1 = new Hand("Kc 8c 9c Tc Jc Qc Ac");
  17. Hand hand2 = new Hand("Kc 8c 9c Tc Jc Qc Ad");
  18. Hand hand3 = new Hand("5s 5d 5c 5h 2c Qc Ad");
  19. HandEvaluator handEval = new HandEvaluator();
  20. System.out.println(handEval.getBest5CardHand(hand1));
  21. System.out.println(handEval.getBest5CardHand(hand2));
  22. System.out.println(handEval.getBest5CardHand(hand3));
  23. System.out.println(handEval.rankHand(hand1));
  24. System.out.println(handEval.rankHand(hand2));
  25. System.out.println(handEval.nameHand(hand1));
  26. System.out.println(handEval.nameHand(hand2));
  27. System.out.println(handEval.nameHand(hand3));
  28. }
  29. /**
  30. * Get a numerical ranking of this hand.
  31. *
  32. * @param c1
  33. * first hole card
  34. * @param c2
  35. * second hole card
  36. * @param h
  37. * a 3-5 card hand
  38. * @return a unique number representing the hand strength of the best 5-card
  39. * poker hand in the given cards and board. The higher the number,
  40. * the better the hand is.
  41. */
  42. public int rankHand(Card c1, Card c2, Hand h) {
  43. h.addCard(c1);
  44. h.addCard(c2);
  45. int rank = rankHand(h);
  46. h.removeCard();
  47. h.removeCard();
  48. return rank;
  49. }
  50. /**
  51. * Given a hand, return a string naming the hand ('Ace High Flush', etc..)
  52. */
  53. public static String nameHand(Hand h) {
  54. return name_hand(rankHand(h));
  55. }
  56. /**
  57. * Compares two hands against each other.
  58. *
  59. * @param h1
  60. * The first hand
  61. * @param h2
  62. * The second hand
  63. * @return 1 = first hand is best, 2 = second hand is best, 0 = tie
  64. */
  65. public int compareHands(Hand h1, Hand h2) {
  66. int r1 = rankHand(h1);
  67. int r2 = rankHand(h2);
  68. if (r1 > r2)
  69. return 1;
  70. if (r1 < r2)
  71. return 2;
  72. return 0;
  73. }
  74. /**
  75. * Compares two 5-7 card hands against each other.
  76. *
  77. * @param rank1
  78. * The rank of the first hand
  79. * @param h2
  80. * The second hand
  81. * @return 1 = first hand is best, 2 = second hand is best, 0 = tie
  82. */
  83. public int compareHands(int rank1, Hand h2) {
  84. int r1 = rank1;
  85. int r2 = rankHand(h2);
  86. if (r1 > r2)
  87. return 1;
  88. if (r1 < r2)
  89. return 2;
  90. return 0;
  91. }
  92. /**
  93. * Given a board, cache all possible two card combinations of hand ranks, so
  94. * that lightenting fast hand comparisons may be done later.
  95. */
  96. public int[][] getRanks(Hand board) {
  97. Hand myhand = new Hand(board);
  98. int[][] rc = new int[52][52];
  99. int i, j, v, n1, n2;
  100. Deck d = new Deck();
  101. d.extractHand(board);
  102. // tabulate ranks
  103. for (i = d.getTopCardIndex(); i < Deck.NUM_CARDS; i++) {
  104. myhand.addCard(d.getCard(i));
  105. n1 = d.getCard(i).getIndex();
  106. for (j = i + 1; j < Deck.NUM_CARDS; j++) {
  107. myhand.addCard(d.getCard(j));
  108. n2 = d.getCard(j).getIndex();
  109. rc[n1][n2] = rc[n2][n1] = rankHand(myhand);
  110. myhand.removeCard();
  111. }
  112. myhand.removeCard();
  113. }
  114. return rc;
  115. }
  116. /** ******************************************************************* */
  117. // MORE HAND COMPARISON STUFF (Adapted from C code by Darse Billings)
  118. /** ******************************************************************* */
  119. /**
  120. * Get the best 5 card poker hand from a 7 card hand
  121. *
  122. * @param h
  123. * Any 7 card poker hand
  124. * @return A Hand containing the highest ranked 5 card hand possible from the
  125. * input.
  126. */
  127. public Hand getBest5CardHand(Hand h) {
  128. int[] ch = h.getCardArray();
  129. int[] bh = new int[6];
  130. int j = Find_Hand(ch, bh);
  131. Hand nh = new Hand();
  132. for (int i = 0; i < 5; i++)
  133. nh.addCard(bh[i + 1]);
  134. return nh;
  135. }
  136. private final static int unknown = -1;
  137. private final static int strflush = 9;
  138. private final static int quads = 8;
  139. private final static int fullhouse = 7;
  140. private final static int flush = 6;
  141. private final static int straight = 5;
  142. private final static int trips = 4;
  143. private final static int twopair = 3;
  144. private final static int pair = 2;
  145. private final static int nopair = 1;
  146. private final static int highcard = 1;
  147. /**
  148. * Get a string from a hand type.
  149. *
  150. * @param handtype
  151. * number coding a hand type
  152. * @return name of hand type
  153. */
  154. private String drb_Name_Hand(int handtype) {
  155. switch (handtype) {
  156. case -1:
  157. return ("Hidden Hand");
  158. case 1:
  159. return ("High Card");
  160. case 2:
  161. return ("Pair");
  162. case 3:
  163. return ("Two Pair");
  164. case 4:
  165. return ("Three of a Kind");
  166. case 5:
  167. return ("Straight");
  168. case 6:
  169. return ("Flush");
  170. case 7:
  171. return ("Full House");
  172. case 8:
  173. return ("Four of a Kind");
  174. case 9:
  175. return ("Straight Flush");
  176. default:
  177. return ("Very Weird hand indeed");
  178. }
  179. }
  180. /* drbcont: want to Find_ the _best_ flush and _best_ strflush ( >9 cards) */
  181. private static boolean Check_StrFlush(int[] hand, int[] dist, int[] best) {
  182. int i, j, suit, strght, strtop;
  183. boolean returnvalue;
  184. int[] suitvector = new int[14];
  185. /*
  186. * _23456789TJQKA boolean vector 01234567890123 indexing
  187. */
  188. returnvalue = false; /* default */
  189. /* do flat distribution of whole suits (cdhs are 0123 respectively) */
  190. for (suit = 0; suit <= 3; suit++) {
  191. /* explicitly initialize suitvector */
  192. suitvector[0] = 13;
  193. for (i = 1; i <= suitvector[0]; i++) {
  194. suitvector[i] = 0;
  195. }
  196. for (i = 1; i <= hand[0]; i++) {
  197. if ((hand[i] != unknown) && ((hand[i] / 13) == suit)) {
  198. suitvector[(hand[i] % 13) + 1] = 1;
  199. };
  200. }
  201. /* now look for straights */
  202. if (suitvector[13] >= 1) /* Ace low straight */
  203. {
  204. strght = 1;
  205. } else
  206. strght = 0;
  207. strtop = 0;
  208. for (i = 1; i <= 13; i++) {
  209. if (suitvector[i] >= 1) {
  210. strght++;
  211. if (strght >= 5) {
  212. strtop = i - 1;
  213. };
  214. } else
  215. strght = 0;
  216. }
  217. /* determine if there was a straight flush and copy it to best[] */
  218. if (strtop > 0) { /* no 2-high straight flushes */
  219. for (j = 1; j <= 5; j++) {
  220. best[j] = ((13 * suit) + strtop + 1 - j);
  221. }
  222. /* Adjust for case of Ace low (five high) straight flush */
  223. if (strtop == 3) {
  224. best[5] = best[5] + 13;
  225. }
  226. returnvalue = true;
  227. }
  228. }
  229. return (returnvalue);
  230. }
  231. private void Find_Quads(int[] hand, int[] dist, int[] best) {
  232. int i, j, quadrank = 0, kicker;
  233. /* find rank of largest quads */
  234. for (i = 1; i <= 13; i++) {
  235. if (dist[i] >= 4) {
  236. quadrank = i - 1;
  237. }
  238. ;
  239. }
  240. /* copy those quads */
  241. i = 1; /* position in hand[] */
  242. j = 1; /* position in best[] */
  243. while (j <= 4) { /* assume all four will be found before i > hand[0] */
  244. if ((hand[i] != unknown) && ((hand[i] % 13) == quadrank)) {
  245. best[j] = hand[i];
  246. j++;
  247. }
  248. ;
  249. i++;
  250. }
  251. /* find best kicker */
  252. kicker = unknown; /* default is unknown kicker */
  253. for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
  254. if ((dist[i] >= 1) && ((i - 1) != quadrank)) {
  255. kicker = i - 1;
  256. }
  257. }
  258. /* copy kicker */
  259. if (kicker != unknown) {
  260. i = 1; /* position in hand[] */
  261. while (j <= 5) { /* assume kicker will be found before i > hand[0] */
  262. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker)) {
  263. best[j] = hand[i];
  264. j++;
  265. }
  266. ;
  267. i++;
  268. }
  269. } else {
  270. best[j] = unknown;
  271. j++;
  272. }
  273. }
  274. private void Find_FullHouse(int[] hand, int[] dist, int[] best) {
  275. int i, j, tripsrank = 0, pairrank = 0;
  276. /* find rank of largest trips */
  277. for (i = 1; i <= 13; i++) {
  278. if (dist[i] >= 3) {
  279. tripsrank = i - 1;
  280. }
  281. ;
  282. }
  283. /* copy those trips */
  284. i = 1; /* position in hand[] */
  285. j = 1; /* position in best[] */
  286. while (j <= 3) { /* assume all three will be found before i > hand[0] */
  287. if ((hand[i] != unknown) && ((hand[i] % 13) == tripsrank)) {
  288. best[j] = hand[i];
  289. j++;
  290. }
  291. ;
  292. i++;
  293. }
  294. /* find best pair */
  295. i = 13;
  296. pairrank = -1;
  297. while (pairrank < 0) { /* assume kicker will be found before i = 0 */
  298. if ((dist[i] >= 2) && ((i - 1) != tripsrank)) {
  299. pairrank = i - 1;
  300. } else
  301. i--;
  302. }
  303. /* copy best pair */
  304. i = 1; /* position in hand[] */
  305. while (j <= 5) { /* assume pair will be found before i > hand[0] */
  306. if ((hand[i] != unknown) && ((hand[i] % 13) == pairrank)) {
  307. best[j] = hand[i];
  308. j++;
  309. }
  310. ;
  311. i++;
  312. }
  313. }
  314. private void Find_Flush(int[] hand, int[] dist, int[] best) { /*
  315. * finds only
  316. * the best
  317. * flush in
  318. * highest
  319. * suit
  320. */
  321. int i, j, flushsuit = 0;
  322. int[] suitvector = new int[14];
  323. /*
  324. * _23456789TJQKA boolean vector 01234567890123 indexing
  325. */
  326. /* find flushsuit */
  327. for (i = 14; i <= 17; i++) {
  328. if (dist[i] >= 5) {
  329. flushsuit = i - 14;
  330. }
  331. ;
  332. }
  333. /* explicitly initialize suitvector */
  334. suitvector[0] = 13;
  335. for (i = 1; i <= suitvector[0]; i++) {
  336. suitvector[i] = 0;
  337. }
  338. /* do flat distribution of whole flushsuit */
  339. for (i = 1; i <= hand[0]; i++) {
  340. if ((hand[i] != unknown) && ((hand[i] / 13) == flushsuit)) {
  341. suitvector[(hand[i] % 13) + 1] = 1;
  342. }
  343. ;
  344. }
  345. /* determine best five cards in flushsuit */
  346. i = 13;
  347. j = 1;
  348. while (j <= 5) { /* assume all five flushcards will be found before i < 1 */
  349. if (suitvector[i] >= 1) {
  350. best[j] = (13 * flushsuit) + i - 1;
  351. j++;
  352. }
  353. ;
  354. i--;
  355. }
  356. }
  357. private void Find_Straight(int[] hand, int[] dist, int[] best) {
  358. int i, j, strght, strtop;
  359. /* look for highest straight */
  360. if (dist[13] >= 1) /* Ace low straight */
  361. {
  362. strght = 1;
  363. } else
  364. strght = 0;
  365. strtop = 0;
  366. for (i = 1; i <= 13; i++) {
  367. if (dist[i] >= 1) {
  368. strght++;
  369. if (strght >= 5) {
  370. strtop = i - 1;
  371. }
  372. ;
  373. } else
  374. strght = 0;
  375. }
  376. /* copy the highest straight */
  377. if (strtop > 3) { /* note: different extraction from others */
  378. for (j = 1; j <= 5; j++) {
  379. for (i = 1; i <= hand[0]; i++) {
  380. if ((hand[i] != unknown) && (hand[i] % 13 == (strtop + 1 - j))) {
  381. best[j] = hand[i];
  382. }
  383. ;
  384. }
  385. }
  386. } else if (strtop == 3) {
  387. for (j = 1; j <= 4; j++) {
  388. for (i = 1; i <= hand[0]; i++) {
  389. if ((hand[i] != unknown) && (hand[i] % 13 == (strtop + 1 - j))) {
  390. best[j] = hand[i];
  391. }
  392. ;
  393. }
  394. }
  395. for (i = 1; i <= hand[0]; i++) { /* the Ace in a low straight */
  396. if ((hand[i] != unknown) && (hand[i] % 13 == 12)) {
  397. best[5] = hand[i];
  398. }
  399. ;
  400. }
  401. }
  402. }
  403. private void Find_Trips(int[] hand, int[] dist, int[] best) {
  404. int i, j, tripsrank = 0, kicker1, kicker2;
  405. /* find rank of largest trips */
  406. for (i = 1; i <= 13; i++) {
  407. if (dist[i] >= 3) {
  408. tripsrank = i - 1;
  409. }
  410. ;
  411. }
  412. /* copy those trips */
  413. i = 1; /* position in hand[] */
  414. j = 1; /* position in best[] */
  415. while (j <= 3) { /* assume all three will be found before i > hand[0] */
  416. if ((hand[i] != unknown) && ((hand[i] % 13) == tripsrank)) {
  417. best[j] = hand[i];
  418. j++;
  419. }
  420. ;
  421. i++;
  422. }
  423. /* find best kickers */
  424. kicker1 = unknown; /* default is unknown kicker */
  425. for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
  426. if ((dist[i] >= 1) && ((i - 1) != tripsrank)) {
  427. kicker1 = i - 1;
  428. }
  429. ;
  430. }
  431. kicker2 = unknown;
  432. for (i = 1; i <= kicker1; i++) { /* find rank of second kicker */
  433. if ((dist[i] >= 1) && ((i - 1) != tripsrank)) {
  434. kicker2 = i - 1;
  435. }
  436. ;
  437. }
  438. /* copy kickers */
  439. if (kicker1 != unknown) {
  440. i = 1; /* position in hand[] */
  441. while (j <= 4) { /* assume kicker1 will be found before i > hand[0] */
  442. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker1)) {
  443. best[j] = hand[i];
  444. j++;
  445. }
  446. ;
  447. i++;
  448. }
  449. } else {
  450. best[j] = unknown;
  451. j++;
  452. }
  453. if (kicker2 != unknown) {
  454. i = 1; /* position in hand[] */
  455. while (j <= 5) { /* assume kicker2 will be found before i > hand[0] */
  456. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker2)) {
  457. best[j] = hand[i];
  458. j++;
  459. }
  460. ;
  461. i++;
  462. }
  463. } else {
  464. best[j] = unknown;
  465. j++;
  466. }
  467. }
  468. private void Find_TwoPair(int[] hand, int[] dist, int[] best) {
  469. int i, j, pairrank1 = 0, pairrank2 = 0, kicker;
  470. /* find rank of largest pair */
  471. for (i = 1; i <= 13; i++) {
  472. if (dist[i] >= 2) {
  473. pairrank1 = i - 1;
  474. }
  475. ;
  476. }
  477. /* find rank of second largest pair */
  478. for (i = 1; i <= 13; i++) {
  479. if ((dist[i] >= 2) && ((i - 1) != pairrank1)) {
  480. pairrank2 = i - 1;
  481. }
  482. ;
  483. }
  484. /* copy those pairs */
  485. i = 1; /* position in hand[] */
  486. j = 1; /* position in best[] */
  487. while (j <= 2) { /* assume both will be found before i > hand[0] */
  488. if ((hand[i] != unknown) && ((hand[i] % 13) == pairrank1)) {
  489. best[j] = hand[i];
  490. j++;
  491. }
  492. ;
  493. i++;
  494. }
  495. i = 1; /* position in hand[] */
  496. while (j <= 4) { /* assume both will be found before i > hand[0] */
  497. if ((hand[i] != unknown) && ((hand[i] % 13) == pairrank2)) {
  498. best[j] = hand[i];
  499. j++;
  500. }
  501. ;
  502. i++;
  503. }
  504. /* find best kicker */
  505. kicker = unknown; /* default is unknown kicker */
  506. for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
  507. if ((dist[i] >= 1) && ((i - 1) != pairrank1) && ((i - 1) != pairrank2)) {
  508. kicker = i - 1;
  509. }
  510. }
  511. /* copy kicker */
  512. if (kicker != unknown) {
  513. i = 1; /* position in hand[] */
  514. while (j <= 5) { /* assume kicker will be found before i > hand[0] */
  515. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker)) {
  516. best[j] = hand[i];
  517. j++;
  518. }
  519. ;
  520. i++;
  521. }
  522. } else {
  523. best[j] = unknown;
  524. j++;
  525. }
  526. }
  527. private void Find_Pair(int[] hand, int[] dist, int[] best) {
  528. int i, j, pairrank = 0, kicker1, kicker2, kicker3;
  529. /* find rank of largest pair */
  530. for (i = 1; i <= 13; i++) {
  531. if (dist[i] >= 2) {
  532. pairrank = i - 1;
  533. }
  534. ;
  535. }
  536. /* copy that pair */
  537. i = 1; /* position in hand[] */
  538. j = 1; /* position in best[] */
  539. while (j <= 2) { /* assume both will be found before i > hand[0] */
  540. if ((hand[i] != unknown) && ((hand[i] % 13) == pairrank)) {
  541. best[j] = hand[i];
  542. j++;
  543. }
  544. ;
  545. i++;
  546. }
  547. /* find best kickers */
  548. kicker1 = unknown; /* default is unknown kicker */
  549. for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
  550. if ((dist[i] >= 1) && ((i - 1) != pairrank)) {
  551. kicker1 = i - 1;
  552. }
  553. ;
  554. }
  555. kicker2 = unknown;
  556. for (i = 1; i <= kicker1; i++) { /* find rank of second kicker */
  557. if ((dist[i] >= 1) && ((i - 1) != pairrank)) {
  558. kicker2 = i - 1;
  559. }
  560. ;
  561. }
  562. kicker3 = unknown;
  563. for (i = 1; i <= kicker2; i++) { /* find rank of third kicker */
  564. if ((dist[i] >= 1) && ((i - 1) != pairrank)) {
  565. kicker3 = i - 1;
  566. }
  567. }
  568. /* copy kickers */
  569. if (kicker1 != unknown) {
  570. i = 1; /* position in hand[] */
  571. while (j <= 3) { /* assume kicker1 will be found before i > hand[0] */
  572. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker1)) {
  573. best[j] = hand[i];
  574. j++;
  575. }
  576. ;
  577. i++;
  578. }
  579. } else {
  580. best[j] = unknown;
  581. j++;
  582. }
  583. if (kicker2 != unknown) {
  584. i = 1; /* position in hand[] */
  585. while (j <= 4) { /* assume kicker2 will be found before i > hand[0] */
  586. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker2)) {
  587. best[j] = hand[i];
  588. j++;
  589. }
  590. ;
  591. i++;
  592. }
  593. } else {
  594. best[j] = unknown;
  595. j++;
  596. }
  597. if (kicker3 != unknown) {
  598. i = 1; /* position in hand[] */
  599. while (j <= 5) { /* assume kicker3 will be found before i > hand[0] */
  600. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker3)) {
  601. best[j] = hand[i];
  602. j++;
  603. }
  604. ;
  605. i++;
  606. }
  607. } else {
  608. best[j] = unknown;
  609. j++;
  610. }
  611. }
  612. private void Find_NoPair(int[] hand, int[] dist, int[] best) {
  613. int i, j, kicker1, kicker2, kicker3, kicker4, kicker5;
  614. /* find best kickers */
  615. kicker1 = unknown; /* default is unknown kicker */
  616. for (i = 1; i <= 13; i++) { /* find rank of largest kicker */
  617. if (dist[i] >= 1) {
  618. kicker1 = i - 1;
  619. }
  620. ;
  621. }
  622. kicker2 = unknown;
  623. for (i = 1; i <= kicker1; i++) { /* find rank of second kicker */
  624. if (dist[i] >= 1) {
  625. kicker2 = i - 1;
  626. }
  627. ;
  628. }
  629. kicker3 = unknown;
  630. for (i = 1; i <= kicker2; i++) { /* find rank of third kicker */
  631. if (dist[i] >= 1) {
  632. kicker3 = i - 1;
  633. }
  634. ;
  635. }
  636. kicker4 = unknown;
  637. for (i = 1; i <= kicker3; i++) { /* find rank of fourth kicker */
  638. if (dist[i] >= 1) {
  639. kicker4 = i - 1;
  640. }
  641. ;
  642. }
  643. kicker5 = unknown;
  644. for (i = 1; i <= kicker4; i++) { /* find rank of fifth kicker */
  645. if (dist[i] >= 1) {
  646. kicker5 = i - 1;
  647. }
  648. ;
  649. }
  650. /* copy kickers */
  651. j = 1; /* position in best[] */
  652. if (kicker1 != unknown) {
  653. i = 1; /* position in hand[] */
  654. while (j <= 1) { /* assume kicker1 will be found before i > hand[0] */
  655. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker1)) {
  656. best[j] = hand[i];
  657. j++;
  658. }
  659. ;
  660. i++;
  661. }
  662. } else {
  663. best[j] = unknown;
  664. j++;
  665. }
  666. if (kicker2 != unknown) {
  667. i = 1; /* position in hand[] */
  668. while (j <= 2) { /* assume kicker2 will be found before i > hand[0] */
  669. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker2)) {
  670. best[j] = hand[i];
  671. j++;
  672. }
  673. ;
  674. i++;
  675. }
  676. } else {
  677. best[j] = unknown;
  678. j++;
  679. }
  680. if (kicker3 != unknown) {
  681. i = 1; /* position in hand[] */
  682. while (j <= 3) { /* assume kicker3 will be found before i > hand[0] */
  683. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker3)) {
  684. best[j] = hand[i];
  685. j++;
  686. }
  687. ;
  688. i++;
  689. }
  690. } else {
  691. best[j] = unknown;
  692. j++;
  693. }
  694. if (kicker4 != unknown) {
  695. i = 1; /* position in hand[] */
  696. while (j <= 4) { /* assume kicker4 will be found before i > hand[0] */
  697. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker4)) {
  698. best[j] = hand[i];
  699. j++;
  700. }
  701. ;
  702. i++;
  703. }
  704. } else {
  705. best[j] = unknown;
  706. j++;
  707. }
  708. if (kicker5 != unknown) {
  709. i = 1; /* position in hand[] */
  710. while (j <= 5) { /* assume kicker5 will be found before i > hand[0] */
  711. if ((hand[i] != unknown) && ((hand[i] % 13) == kicker5)) {
  712. best[j] = hand[i];
  713. j++;
  714. }
  715. ;
  716. i++;
  717. }
  718. } else {
  719. best[j] = unknown;
  720. j++;
  721. }
  722. }
  723. private int Best_Hand(int[] hand1, int[] hand2) { /*
  724. * sorted 5-card hands,
  725. * both same type
  726. */
  727. /* could check for proper hand types... */
  728. /* check value of top cards, then on down */
  729. if ((hand1[1] % 13) > (hand2[1] % 13))
  730. return (1);
  731. else if ((hand1[1] % 13) < (hand2[1] % 13))
  732. return (2);
  733. /* same top, check second */
  734. else if ((hand1[2] % 13) > (hand2[2] % 13))
  735. return (1);
  736. else if ((hand1[2] % 13) < (hand2[2] % 13))
  737. return (2);
  738. /* same second, check third */
  739. else if ((hand1[3] % 13) > (hand2[3] % 13))
  740. return (1);
  741. else if ((hand1[3] % 13) < (hand2[3] % 13))
  742. return (2);
  743. /* same third, check fourth */
  744. else if ((hand1[4] % 13) > (hand2[4] % 13))
  745. return (1);
  746. else if ((hand1[4] % 13) < (hand2[4] % 13))
  747. return (2);
  748. /* same fourth, check fifth */
  749. else if ((hand1[5] % 13) > (hand2[5] % 13))
  750. return (1);
  751. else if ((hand1[5] % 13) < (hand2[5] % 13))
  752. return (2);
  753. else
  754. /* same hands */
  755. return (0);
  756. }
  757. private int Find_Hand(int[] hand, int[] best) { /* -1 means unknown card */
  758. int i, card, rank, suit, hand_type, rankmax1, rankmax2, flushmax, strght, strmax;
  759. int[] dist = new int[18];
  760. /*
  761. * _23456789TJQKAcdhs distribution vector 012345678901234567 indexing
  762. */
  763. /* explicitly initialize distribution vector */
  764. dist[0] = 17;
  765. for (i = 1; i <= dist[0]; i++) {
  766. dist[i] = 0;
  767. }
  768. for (i = 1; i <= hand[0]; i++) {
  769. if (hand[i] != unknown) {
  770. card = hand[i];
  771. rank = card % 13;
  772. suit = card / 13;
  773. if (!((rank < 0) || (rank > 12))) {
  774. dist[rank + 1]++;
  775. }
  776. if (!((suit < 0) || (suit > 3))) {
  777. dist[suit + 14]++;
  778. }
  779. }
  780. }
  781. /* scan the distribution array for maximums */
  782. rankmax1 = 0;
  783. rankmax2 = 0;
  784. flushmax = 0;
  785. strmax = 0;
  786. if (dist[13] >= 1) {
  787. strght = 1;
  788. } else
  789. strght = 0; /* Ace low straight */
  790. for (i = 1; i <= 13; i++) {
  791. if (dist[i] > rankmax1) {
  792. rankmax2 = rankmax1;
  793. rankmax1 = dist[i];
  794. } else if (dist[i] > rankmax2) {
  795. rankmax2 = dist[i];
  796. }
  797. ;
  798. if (dist[i] >= 1) {
  799. strght++;
  800. if (strght > strmax) {
  801. strmax = strght;
  802. }
  803. } else
  804. strght = 0;
  805. }
  806. for (i = 14; i <= 17; i++) {
  807. if (dist[i] > flushmax) {
  808. flushmax = dist[i];
  809. }
  810. }
  811. hand_type = unknown;
  812. if ((flushmax >= 5) && (strmax >= 5)) {
  813. if (Check_StrFlush(hand, dist, best)) {
  814. hand_type = strflush;
  815. } else {
  816. hand_type = flush;
  817. Find_Flush(hand, dist, best);
  818. }
  819. ;
  820. } else if (rankmax1 >= 4) {
  821. hand_type = quads;
  822. Find_Quads(hand, dist, best);
  823. } else if ((rankmax1 >= 3) && (rankmax2 >= 2)) {
  824. hand_type = fullhouse;
  825. Find_FullHouse(hand, dist, best);
  826. } else if (flushmax >= 5) {
  827. hand_type = flush;
  828. Find_Flush(hand, dist, best);
  829. } else if (strmax >= 5) {
  830. hand_type = straight;
  831. Find_Straight(hand, dist, best);
  832. } else if (rankmax1 >= 3) {
  833. hand_type = trips;
  834. Find_Trips(hand, dist, best);
  835. } else if ((rankmax1 >= 2) && (rankmax2 >= 2)) {
  836. hand_type = twopair;
  837. Find_TwoPair(hand, dist, best);
  838. } else if (rankmax1 >= 2) {
  839. hand_type = pair;
  840. Find_Pair(hand, dist, best);
  841. } else {
  842. hand_type = nopair;
  843. Find_NoPair(hand, dist, best);
  844. }
  845. ;
  846. return (hand_type);
  847. }
  848. /** ******************************************************************* */
  849. // DENIS PAPP'S HAND RANK IDENTIFIER CODE:
  850. /** ******************************************************************* */
  851. private static final int POKER_HAND = 5;
  852. public static final int HIGH = 0;
  853. public static final int PAIR = 1;
  854. public static final int TWOPAIR = 2;
  855. public static final int THREEKIND = 3;
  856. public static final int STRAIGHT = 4;
  857. public static final int FLUSH = 5;
  858. public static final int FULLHOUSE = 6;
  859. public static final int FOURKIND = 7;
  860. public static final int STRAIGHTFLUSH = 8;
  861. public static final int FIVEKIND = 9;
  862. public static final int NUM_HANDS = 10;
  863. private static final int NUM_RANKS = 13;
  864. private static final int ID_GROUP_SIZE = (Card.NUM_RANKS * Card.NUM_RANKS
  865. * Card.NUM_RANKS * Card.NUM_RANKS * Card.NUM_RANKS);
  866. private final static byte ID_ExistsStraightFlush(Hand h, byte major_suit) {
  867. boolean[] present = new boolean[Card.NUM_RANKS];
  868. // for (i=0;i<Card.NUM_RANKS;i++) present[i]=false;
  869. for (int i = 0; i < h.size(); i++) {
  870. int cind = h.getCardIndex(i + 1);
  871. if (Card.getSuit(cind) == major_suit) {
  872. present[Card.getRank(cind)] = true;
  873. }
  874. }
  875. int straight = present[Card.ACE] ? 1 : 0;
  876. byte high = 0;
  877. for (int i = 0; i < Card.NUM_RANKS; i++) {
  878. if (present[i]) {
  879. if ((++straight) >= POKER_HAND) {
  880. high = (byte) i;
  881. }
  882. } else {
  883. straight = 0;
  884. }
  885. }
  886. return high;
  887. }
  888. // suit: Card.NUM_SUITS means any
  889. // not_allowed: Card.NUM_RANKS means any
  890. // returns ident value
  891. private final static int ID_KickerValue(byte[] paired, int kickers,
  892. byte[] not_allowed) {
  893. int i = Card.ACE;
  894. int value = 0;
  895. while (kickers != 0) {
  896. while (paired[i] == 0 || i == not_allowed[0] || i == not_allowed[1])
  897. i--;
  898. kickers--;
  899. value += pow(Card.NUM_RANKS, kickers) * i;
  900. i--;
  901. }
  902. return value;
  903. }
  904. private final static int ID_KickerValueSuited(Hand h, int kickers, byte suit) {
  905. int i;
  906. int value = 0;
  907. boolean[] present = new boolean[Card.NUM_RANKS];
  908. // for (i=0;i<Card.NUM_RANKS;i++) present[i] = false;
  909. for (i = 0; i < h.size(); i++)
  910. if (h.getCard(i + 1).getSuit() == suit)
  911. present[h.getCard(i + 1).getRank()] = true;
  912. i = Card.ACE;
  913. while (kickers != 0) {
  914. while (present[i] == false)
  915. i--;
  916. kickers--;
  917. value += pow(Card.NUM_RANKS, kickers) * i;
  918. i--;
  919. }
  920. return value;
  921. }
  922. /**
  923. * Get a numerical ranking of this hand. Uses java based code, so may be
  924. * slower than using the native methods, but is more compatible this way.
  925. *
  926. * Based on Denis Papp's Loki Hand ID code (id.cpp) Given a 1-9 card hand,
  927. * will return a unique rank such that any two hands will be ranked with the
  928. * better hand having a higher rank.
  929. *
  930. * @param h a 1-9 card hand
  931. * @return a unique number representing the hand strength of the best 5-card
  932. * poker hand in the given 7 cards. The higher the number, the better
  933. * the hand is.
  934. */
  935. public final static int rankHand(Hand h) {
  936. boolean straight = false;
  937. boolean flush = false;
  938. byte max_hand = (byte) (h.size() >= POKER_HAND ? POKER_HAND : h.size());
  939. int r, c;
  940. byte rank, suit;
  941. // pair data
  942. byte[] group_size = new byte[POKER_HAND + 1]; // array to track the groups or cards in your hand
  943. byte[] paired = new byte[Card.NUM_RANKS]; // array to track paired carsd
  944. byte[][] pair_rank = new byte[POKER_HAND + 1][2]; // array to track the rank of our pairs
  945. // straight
  946. byte straight_high = 0; // track the high card (rank) of our straight
  947. byte straight_size;
  948. // flush
  949. byte[] suit_size = new byte[Card.NUM_SUITS];
  950. byte major_suit = 0;
  951. // determine pairs, dereference order data, check flush
  952. // for (r=0;r<Card.NUM_RANKS;r++) paired[r] = 0;
  953. // for (r=0;r<Card.NUM_SUITS;r++) suit_size[r] = 0;
  954. // for (r=0;r<=POKER_HAND;r++) group_size[r] = 0;
  955. for (r = 0; r < h.size(); r++) {
  956. int cind = h.getCardIndex(r + 1);
  957. rank = (byte) Card.getRank(cind);
  958. suit = (byte) Card.getSuit(cind);
  959. paired[rank]++; // Add rank of card to paired array to track the pairs we have.
  960. group_size[paired[rank]]++; // keep track of the groups in our hand (1-pair, 2-pair, 1-trips, 1-trips 1-pair)
  961. if (paired[rank] != 0) // To prevent looking at group_size[-1], which would be bad.
  962. group_size[paired[rank] - 1]--; // Decrese the previous group by one. group_size[0] should end up at -5.
  963. if ((++suit_size[suit]) >= POKER_HAND) { // Add suit to suit array, then check for a flush.
  964. flush = true;
  965. major_suit = suit;
  966. }
  967. }
  968. // Card.ACE low? Add to straight_size if so.
  969. straight_size = (byte) (paired[Card.ACE] != 0 ? 1 : 0);
  970. for (int i = 0; i < (POKER_HAND + 1); i++) {
  971. pair_rank[i][0] = (byte) Card.NUM_RANKS;
  972. pair_rank[i][1] = (byte) Card.NUM_RANKS;
  973. }
  974. // check for straight and pair data
  975. // Start at the Deuce. straight_size = 1 if we have an ace.
  976. for (r = 0; r < Card.NUM_RANKS; r++) {
  977. // check straight
  978. if (paired[r] != 0) {
  979. if ((++straight_size) >= POKER_HAND) { // Do we have five cards in a row (a straight!)
  980. straight = true; // We sure do.
  981. straight_high = (byte) r; // Keep track of that high card
  982. }
  983. } else { // Missing a card for our straight. start the count over.
  984. straight_size = 0;
  985. }
  986. // get pair ranks, keep two highest of each
  987. c = paired[r];
  988. if (c != 0) {
  989. pair_rank[c][1] = pair_rank[c][0];
  990. pair_rank[c][0] = (byte) r;
  991. }
  992. }
  993. // now id type
  994. int ident;
  995. if (group_size[POKER_HAND] != 0) { // we have five cards of the same rank in our hand.
  996. ident = FIVEKIND * ID_GROUP_SIZE; // must have five of a kind !!
  997. ident += pair_rank[POKER_HAND][0];
  998. return ident;
  999. }
  1000. if (straight && flush) {
  1001. byte hi = ID_ExistsStraightFlush(h, major_suit);
  1002. if (hi > 0) {
  1003. ident = STRAIGHTFLUSH * ID_GROUP_SIZE;
  1004. ident += hi;
  1005. return ident;
  1006. }
  1007. }
  1008. if (group_size[4] != 0) {
  1009. ident = FOURKIND * ID_GROUP_SIZE;
  1010. ident += pair_rank[4][0] * Card.NUM_RANKS;
  1011. pair_rank[4][1] = (byte) Card.NUM_RANKS; // just in case 2 sets quads
  1012. ident += ID_KickerValue(paired, 1, pair_rank[4]);
  1013. } else if (group_size[3] >= 2) {
  1014. ident = FULLHOUSE * ID_GROUP_SIZE;
  1015. ident += pair_rank[3][0] * Card.NUM_RANKS;
  1016. ident += pair_rank[3][1];
  1017. } else if (group_size[3] == 1 && group_size[2] != 0) {
  1018. ident = FULLHOUSE * ID_GROUP_SIZE;
  1019. ident += pair_rank[3][0] * Card.NUM_RANKS;
  1020. ident += pair_rank[2][0];
  1021. } else if (flush) {
  1022. ident = FLUSH * ID_GROUP_SIZE;
  1023. ident += ID_KickerValueSuited(h, 5, major_suit);
  1024. } else if (straight) {
  1025. ident = STRAIGHT * ID_GROUP_SIZE;
  1026. ident += straight_high;
  1027. } else if (group_size[3] == 1) {
  1028. ident = THREEKIND * ID_GROUP_SIZE;
  1029. ident += pair_rank[3][0] * Card.NUM_RANKS * Card.NUM_RANKS;
  1030. ident += ID_KickerValue(paired, max_hand - 3, pair_rank[3]);
  1031. } else if (group_size[2] >= 2) { // TWO PAIR
  1032. ident = TWOPAIR * ID_GROUP_SIZE;
  1033. ident += pair_rank[2][0] * Card.NUM_RANKS * Card.NUM_RANKS;
  1034. ident += pair_rank[2][1] * Card.NUM_RANKS;
  1035. ident += ID_KickerValue(paired, max_hand - 4, pair_rank[2]);
  1036. } else if (group_size[2] == 1) { // A PAIR
  1037. ident = PAIR * ID_GROUP_SIZE;
  1038. ident += pair_rank[2][0] * Card.NUM_RANKS * Card.NUM_RANKS
  1039. * Card.NUM_RANKS;
  1040. ident += ID_KickerValue(paired, max_hand - 2, pair_rank[2]);
  1041. } else { // A Low
  1042. ident = HIGH * ID_GROUP_SIZE;
  1043. ident += ID_KickerValue(paired, max_hand, pair_rank[2]);
  1044. }
  1045. return ident;
  1046. }
  1047. private static int pow(int n, int p) {
  1048. int res = 1;
  1049. while (p-- > 0)
  1050. res *= n;
  1051. return res;
  1052. }
  1053. private static final String[] hand_name = { "HIGH", "PAIR", "TWO PAIR",
  1054. "THREE KIND", "STRAIGHT", "FLUSH", "FULL HOUSE", "FOUR KIND",
  1055. "STRAIGHT FLUSH", "FIVE KIND" };
  1056. private static final String[] rank_name = { "Two", "Three", "Four", "Five",
  1057. "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace" };
  1058. /**
  1059. * Return a string naming the hand
  1060. *
  1061. * @param rank
  1062. * calculated by rankHand_java()
  1063. */
  1064. private static String name_hand(int rank) {
  1065. int type = (int) (rank / ID_GROUP_SIZE);
  1066. int ident = (int) (rank % ID_GROUP_SIZE), ident2;
  1067. String t = new String();
  1068. switch (type) {
  1069. case HIGH:
  1070. ident /= NUM_RANKS * NUM_RANKS * NUM_RANKS * NUM_RANKS;
  1071. t = rank_name[ident] + " High";
  1072. break;
  1073. case FLUSH:
  1074. ident /= NUM_RANKS * NUM_RANKS * NUM_RANKS * NUM_RANKS;
  1075. t = "a Flush, " + rank_name[ident] + " High";
  1076. break;
  1077. case PAIR:
  1078. ident /= NUM_RANKS * NUM_RANKS * NUM_RANKS;
  1079. t = "a Pair of " + rank_name[ident]+ (rank_name[ident].charAt(2)=='x'? "es":"s");
  1080. break;
  1081. case TWOPAIR:
  1082. ident2 = ident / (NUM_RANKS * NUM_RANKS);
  1083. ident = (ident % (NUM_RANKS * NUM_RANKS)) / NUM_RANKS;
  1084. t = "Two Pair, " + rank_name[ident2]
  1085. + (rank_name[ident2].charAt(2)=='x'? "es":"s")
  1086. +" and " + rank_name[ident]
  1087. + (rank_name[ident].charAt(2)=='x'? "es":"s");
  1088. break;
  1089. case THREEKIND:
  1090. t = "Three of a Kind, " + rank_name[ident / (NUM_RANKS * NUM_RANKS)]
  1091. + (rank_name[ident/ (NUM_RANKS * NUM_RANKS)].charAt(2)=='x'? "es":"s");
  1092. break;
  1093. case FULLHOUSE:
  1094. t = "a Full House, " + rank_name[ident / NUM_RANKS]
  1095. + (rank_name[ident/ NUM_RANKS].charAt(2)=='x'? "es":"s")+" over "
  1096. + rank_name[ident % NUM_RANKS]
  1097. + (rank_name[ident% NUM_RANKS].charAt(2)=='x'? "es":"s");
  1098. break;
  1099. case FOURKIND:
  1100. t = "Four of a Kind, " + rank_name[ident / NUM_RANKS]
  1101. + (rank_name[ident/ NUM_RANKS ].charAt(2)=='x'? "es":"s");
  1102. break;
  1103. case STRAIGHT:
  1104. t = "a " + rank_name[ident] + " High Straight";
  1105. break;
  1106. case STRAIGHTFLUSH:
  1107. t = "a " + rank_name[ident] + " High Straight Flush";
  1108. break;
  1109. case FIVEKIND:
  1110. t = "Five of a Kind, " + rank_name[ident] + "s";
  1111. break;
  1112. default:
  1113. t = hand_name[type];
  1114. }
  1115. return t;
  1116. }
  1117. }