├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── bower.json
├── package.json
├── pokersolver.js
└── test
├── deuceswild.js
├── fourcard.js
├── fourcardbonus.js
├── jacksbetter.js
├── joker.js
├── paigowpokerfullhands.js
├── standard.js
├── test.js
└── threecard.js
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: goldfire
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gitignore
2 | node_modules/
3 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 James Simpson and GoldFire Studios, Inc.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Description
2 | pokersolver is a poker hand solver and comparison tool written in Javascript. It was written for and is being used in production on [**CasinoRPG**](http://casinorpg.com), an HTML5 MMORPG that features Texas Hold'em as one of its main casino games. It is designed for use on either the client (browser) or the server (Node.js). This library is capable of:
3 |
4 | * Evaluating a hand of up to 7 cards
5 | * Calculating the score of the hand (0-9)
6 | * Returning the name of the hand (Pair, Flush, etc)
7 | * Returning a detailed description (Two Pair, A's & 8's)
8 | * Comparing an array of hands and returning the winner(s)
9 | * Identifying all cards involved in creating the winning hand
10 | * Support for wilds and other game types
11 | * Works in both the browser and Node.js
12 |
13 | ## Installation
14 | ```
15 | npm install pokersolver
16 | ```
17 |
18 | ## Examples
19 | #### Server Usage
20 | ```javascript
21 | var Hand = require('pokersolver').Hand;
22 | ```
23 |
24 | #### Browser Usage
25 | ```javascript
26 |
27 |
31 | ```
32 |
33 | Solve two hands and then determine the winner between the two of them.
34 | ```javascript
35 | var hand1 = Hand.solve(['Ad', 'As', 'Jc', 'Th', '2d', '3c', 'Kd']);
36 | var hand2 = Hand.solve(['Ad', 'As', 'Jc', 'Th', '2d', 'Qs', 'Qd']);
37 | var winner = Hand.winners([hand1, hand2]); // hand2
38 | ```
39 |
40 | Solve a hand and return the type and the description.
41 | ```javascript
42 | var hand = Hand.solve(['Ad', 'As', 'Jc', 'Th', '2d', 'Qs', 'Qd']);
43 | console.log(hand.name); // Two Pair
44 | console.log(hand.descr); // Two Pair, A's & Q's
45 | ```
46 |
47 | ## API
48 | ### Hand Methods
49 | #### solve(cards, game, canDisqualify)
50 | Solves the hand passed in, whether 3 cards or 7. Returns various information such as name, description, score and cards involved.
51 | * **cards**: `Array` All cards involved in the hand, example: `['Ad', '2d', '3d', '4d', 'Qc', 'Ks', '7h']`. Note that a `10` should be passed as a `T` (`Th` for example).
52 | * **game**: `String` Which rule set is used, based on the game being played. Default: 'standard'
53 | * **canDisqualify**: `Boolean` Is this hand subject to qualification rules, which some games have? Default: false
54 |
55 | #### winners(hands)
56 | Compare the passed hands and determine which is the best hand(s). Can return multiple if there is a tie.
57 | * **hands** `Array` All hands solved with `Hand.solve` that should be compared.
58 |
59 | #### toString()
60 | Returns a formatted string of all cards involved in the identified hand type (maximum of 5 cards).
61 |
62 | ### Solved Hand Properties
63 | #### cardPool `Array`
64 | All of the cards passed into the hand.
65 | #### cards `Array`
66 | All of the cards involved in the identified hand type.
67 | #### descr `String`
68 | Detailed description of the identified hand type (`Two Pair, A's & Q's` for example).
69 | #### name `String`
70 | Type of hand identified (`Two Pair` for example).
71 | #### rank `Number`
72 | Ranking of the hand type (Varies from game to game; 0 being the lowest hand).
73 |
74 | ### PaiGowPokerHelper Methods
75 | #### solve(cards)
76 | Solves the hand passed in, sets it according to House Way, and solves both hands.
77 | * **cards**: `Array` All cards involved in the hand, example: `['Ad', '2d', '3d', '4d', 'Qc', 'Ks', '7h']`.
78 |
79 | #### setHands(hiHand, loHand)
80 | Sets the hands according to the input, and solves both hands.
81 | * **hiHand** `Array` Five cards involved in the high hand, example: `['Ad', '2d', '3d', '4d', '7h']`.
82 | * **loHand** `Array` Two cards involved in the low hand, example: `['Qc', 'Ks']`.
83 |
84 | #### winners(player, banker)
85 | Compare the passed PaiGowPokerHelper hands and determine who wins. 1 = Player, -1 = Banker, 0 = Push.
86 | * **player** `PaiGowPokerHelper` Non-banking hand solved with `PaiGowPokerHelper.solve` or `PaiGowPokerHelper.setHands`.
87 | * **banker** `PaiGowPokerHelper` Banking hand solved with `PaiGowPokerHelper.solve` or `PaiGowPokerHelper.setHands`.
88 |
89 | ### Solved PaiGowPokerHelper Properties
90 | #### baseHand `Hand`
91 | All of the cards passed into the helper, run against `Hand.solve`.
92 | #### hiHand `Hand`
93 | Five card high hand, whether calculated or passed into the helper, run against `Hand.solve`.
94 | #### loHand `Hand`
95 | Two card low hand, whether calculated or passed into the helper, run against `Hand.solve`.
96 |
97 | ### Games Available
98 | #### standard
99 | Useful for Texas Hold'em, Seven Card Stud, Five Card Draw, and other Standard Poker Games.
100 | #### jacksbetter
101 | Useful for Jacks or Better Video Poker. Use qualification to determine if a hand is a Pair of Jacks or better.
102 | #### joker
103 | Useful for Joker Video Poker. Jokers are notated as `'Or'` and may be anything. Qualification: Kings or better.
104 | #### deuceswild
105 | Useful for Deuces Wild Video Poker. Deuces may be anything. Hands lower than Three of a Kind are `High Card` and not paying hands.
106 | #### threecard
107 | Useful for Three Card Poker. Qualification: Dealer must have Queen High or better.
108 | #### fourcard
109 | Useful for Four Card Poker. No qualifying hand.
110 | #### fourcardbonus
111 | Useful for calculating the Aces Up Bonus for Four Card Poker. Qualification: Pair of Aces or better.
112 | #### paigowpokerfull
113 | HELPER GAME: Used by `PaiGowPokerHelper` to create a hand that will eventually be split.
114 | #### paigowpokeralt
115 | HELPER GAME: Used by `PaiGowPokerHelper` on a straight and/or flush to create another possible hand.
116 | #### paigowpokersf6
117 | HELPER GAME: Used by `PaiGowPokerHelper` to determine if a six-card straight and/or flush is possible.
118 | #### paigowpokersf7
119 | HELPER GAME: Used by `PaiGowPokerHelper` to determine if a seven-card straight and/or flush is possible.
120 | #### paigowpokerhi
121 | Useful for Pai Gow Poker's High Hand. A2345 is the second highest straight. One joker in the deck as `'Or'`; it may be used to complete a straight and/or flush, else is counted as an Ace.
122 | #### paigowpokerlo
123 | Useful for Pai Gow Poker's Low Hand. One joker in the deck as `'Or'`; it is counted as an Ace.
124 |
125 | ## Testing
126 | ```
127 | npm install
128 | npm test
129 | ```
130 |
131 | ## License
132 | Copyright (c) 2016 James Simpson and GoldFire Studios, Inc.
133 |
134 | Released under the MIT License.
135 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pokersolver",
3 | "description": "Javascript poker hand solver.",
4 | "homepage": "https://github.com/goldfire/pokersolver",
5 | "keywords": [
6 | "poker",
7 | "poker-hand",
8 | "holdem",
9 | "poker-evaluator"
10 | ],
11 | "authors": [
12 | "James Simpson (http://goldfirestudios.com)"
13 | ],
14 | "repository": {
15 | "type": "git",
16 | "url": "git://github.com/goldfire/pokersolver.git"
17 | },
18 | "main": "pokersolver.js",
19 | "license": {
20 | "type": "MIT",
21 | "url": "https://raw.githubusercontent.com/goldfire/pokersolver/master/LICENSE.md"
22 | },
23 | "moduleType": [
24 | "amd",
25 | "globals",
26 | "node"
27 | ]
28 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pokersolver",
3 | "description": "Javascript poker hand solver.",
4 | "homepage": "https://github.com/goldfire/pokersolver",
5 | "keywords": [
6 | "poker",
7 | "poker-hand",
8 | "holdem",
9 | "poker-evaluator"
10 | ],
11 | "author": "James Simpson (http://goldfirestudios.com)",
12 | "repository": {
13 | "type": "git",
14 | "url": "git://github.com/goldfire/pokersolver.git"
15 | },
16 | "main": "pokersolver.js",
17 | "version": "2.1.4",
18 | "license": {
19 | "type": "MIT",
20 | "url": "https://raw.githubusercontent.com/goldfire/pokersolver/master/LICENSE.md"
21 | },
22 | "devDependencies": {
23 | "mocha": "*",
24 | "should": "*"
25 | },
26 | "scripts": {
27 | "test": "mocha test/test.js"
28 | },
29 | "engines": [
30 | "node >= 4.0.0"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/pokersolver.js:
--------------------------------------------------------------------------------
1 | /**
2 | * pokersolver v2.1.2
3 | * Copyright (c) 2016, James Simpson of GoldFire Studios
4 | * http://goldfirestudios.com
5 | */
6 |
7 | (function() {
8 | 'use strict';
9 |
10 | // NOTE: The 'joker' will be denoted with a value of 'O' and any suit.
11 | var values = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'];
12 |
13 | /**
14 | * Base Card class that defines a single card.
15 | */
16 | class Card {
17 | constructor(str) {
18 | this.value = str.substr(0, 1);
19 | this.suit = str.substr(1, 1).toLowerCase();
20 | this.rank = values.indexOf(this.value);
21 | this.wildValue = str.substr(0, 1);
22 | }
23 |
24 | toString() {
25 | return this.wildValue.replace('T', '10') + this.suit;
26 | }
27 |
28 | static sort(a, b) {
29 | if (a.rank > b.rank) {
30 | return -1;
31 | } else if (a.rank < b.rank) {
32 | return 1;
33 | } else {
34 | return 0;
35 | }
36 | }
37 | }
38 |
39 | /**
40 | * Base Hand class that handles comparisons of full hands.
41 | */
42 | class Hand {
43 | constructor(cards, name, game, canDisqualify) {
44 | this.cardPool = [];
45 | this.cards = [];
46 | this.suits = {};
47 | this.values = [];
48 | this.wilds = [];
49 | this.name = name;
50 | this.game = game;
51 | this.sfLength = 0;
52 | this.alwaysQualifies = true;
53 |
54 | // Qualification rules apply for dealer's hand.
55 | // Also applies for single player games, like video poker.
56 | if (canDisqualify && this.game.lowestQualified) {
57 | this.alwaysQualifies = false;
58 | }
59 |
60 | // Ensure no duplicate cards in standard game.
61 | if (game.descr === 'standard' && new Set(cards).size !== cards.length) {
62 | throw new Error('Duplicate cards');
63 | }
64 |
65 | // Get rank based on game.
66 | var handRank = this.game.handValues.length;
67 | for (var i=0; i a.rank) {
120 | return -1;
121 | }
122 |
123 | var result = 0;
124 | for (var i=0; i<=4; i++) {
125 | if (this.cards[i] && a.cards[i] && this.cards[i].rank < a.cards[i].rank) {
126 | result = 1;
127 | break;
128 | } else if (this.cards[i] && a.cards[i] && this.cards[i].rank > a.cards[i].rank) {
129 | result = -1;
130 | break;
131 | }
132 | }
133 |
134 | return result;
135 | }
136 |
137 | /**
138 | * Determine whether a hand loses to another.
139 | * @param {Hand} hand Hand to compare to.
140 | * @return {Boolean}
141 | */
142 | loseTo(hand) {
143 | return (this.compare(hand) > 0);
144 | }
145 |
146 | /**
147 | * Determine the number of cards in a hand of a rank.
148 | * @param {Number} val Index of this.values.
149 | * @return {Number} Number of cards having the rank, including wild cards.
150 | */
151 | getNumCardsByRank(val) {
152 | var cards = this.values[val];
153 | var checkCardsLength = (cards) ? cards.length : 0;
154 |
155 | for (var i=0; i -1) {
157 | continue;
158 | } else if (cards) {
159 | if (this.game.wildStatus === 1 || cards[0].rank === values.length - 1) {
160 | checkCardsLength += 1;
161 | }
162 | } else if (this.game.wildStatus === 1 || val === values.length - 1) {
163 | checkCardsLength += 1;
164 | }
165 | }
166 |
167 | return checkCardsLength;
168 | }
169 |
170 | /**
171 | * Determine the cards in a suit for a flush.
172 | * @param {String} suit Key for this.suits.
173 | * @param {Boolean} setRanks Whether to set the ranks for the wild cards.
174 | * @return {Array} Cards having the suit, including wild cards.
175 | */
176 | getCardsForFlush(suit, setRanks) {
177 | var cards = (this.suits[suit] || []).sort(Card.sort);
178 |
179 | for (var i=0; i= this.game.sfQualify) {
375 | possibleStraight = cards;
376 | break;
377 | }
378 | }
379 |
380 | if (possibleStraight) {
381 | if (this.game.descr !== 'standard') {
382 | for (var suit in this.suits) {
383 | if (possibleStraight[0].suit !== suit) {
384 | nonCards = nonCards.concat(this.suits[suit] || []);
385 | nonCards = Hand.stripWilds(nonCards, this.game)[1];
386 | }
387 | }
388 | }
389 | var straight = new Straight(possibleStraight, this.game);
390 | if (straight.isPossible) {
391 | this.cards = straight.cards;
392 | this.cards = this.cards.concat(nonCards);
393 | this.sfLength = straight.sfLength;
394 | }
395 | }
396 |
397 | if (this.cards[0] && this.cards[0].rank === 13) {
398 | this.descr = 'Royal Flush';
399 | } else if (this.cards.length >= this.game.sfQualify) {
400 | this.descr = this.name + ', ' + this.cards[0].toString().slice(0, -1) + suit + ' High';
401 | }
402 |
403 | return this.cards.length >= this.game.sfQualify;
404 | }
405 | }
406 |
407 | class RoyalFlush extends StraightFlush {
408 | constructor(cards, game, canDisqualify) {
409 | super(cards, game, canDisqualify);
410 | }
411 |
412 | solve() {
413 | this.resetWildCards();
414 | var result = super.solve();
415 | return result && this.descr === 'Royal Flush';
416 | }
417 | }
418 |
419 | class NaturalRoyalFlush extends RoyalFlush {
420 | constructor(cards, game, canDisqualify) {
421 | super(cards, game, canDisqualify);
422 | }
423 |
424 | solve() {
425 | var i = 0;
426 | this.resetWildCards();
427 | var result = super.solve();
428 | if (result && this.cards) {
429 | for (i=0; i= 5) {
496 | this.descr = this.name + ', ' + this.cards[0].toString().slice(0, -1) + '\'s';
497 | }
498 |
499 | return this.cards.length >= 5;
500 | }
501 | }
502 |
503 | class FourOfAKindPairPlus extends Hand {
504 | constructor(cards, game, canDisqualify) {
505 | super(cards, 'Four of a Kind with Pair or Better', game, canDisqualify);
506 | }
507 |
508 | solve() {
509 | var cards;
510 | this.resetWildCards();
511 |
512 | for (var i=0; i= 2) {
536 | this.cards = this.cards.concat(cards || []);
537 | for (var j=0; j= 6) {
559 | var type = this.cards[0].toString().slice(0, -1) + '\'s over ' + this.cards[4].toString().slice(0, -1) + '\'s';
560 | this.descr = this.name + ', ' + type;
561 | }
562 |
563 | return this.cards.length >= 6;
564 | }
565 | }
566 |
567 | class FourOfAKind extends Hand {
568 | constructor(cards, game, canDisqualify) {
569 | super(cards, 'Four of a Kind', game, canDisqualify);
570 | }
571 |
572 | solve() {
573 | this.resetWildCards();
574 |
575 | for (var i=0; i= 4) {
595 | if (this.game.noKickers) {
596 | this.cards.length = 4;
597 | }
598 |
599 | this.descr = this.name + ', ' + this.cards[0].toString().slice(0, -1) + '\'s';
600 | }
601 |
602 | return this.cards.length >= 4;
603 | }
604 | }
605 |
606 | class FourWilds extends Hand {
607 | constructor(cards, game, canDisqualify) {
608 | super(cards, 'Four Wild Cards', game, canDisqualify);
609 | }
610 |
611 | solve() {
612 | if (this.wilds.length === 4) {
613 | this.cards = this.wilds;
614 | this.cards = this.cards.concat(this.nextHighest().slice(0, this.game.cardsInHand-4));
615 | }
616 |
617 | if (this.cards.length >= 4) {
618 | if (this.game.noKickers) {
619 | this.cards.length = 4;
620 | }
621 |
622 | this.descr = this.name;
623 | }
624 |
625 | return this.cards.length >= 4;
626 | }
627 | }
628 |
629 | class ThreeOfAKindTwoPair extends Hand {
630 | constructor(cards, game, canDisqualify) {
631 | super(cards, 'Three of a Kind with Two Pair', game, canDisqualify);
632 | }
633 |
634 | solve() {
635 | var cards;
636 | this.resetWildCards();
637 |
638 | for (var i=0; i 5 && this.getNumCardsByRank(i) === 2) {
662 | this.cards = this.cards.concat(cards || []);
663 | for (var j=0; j= 7) {
702 | var type = this.cards[0].toString().slice(0, -1) + '\'s over ' + this.cards[3].toString().slice(0, -1) + '\'s & ' + this.cards[5].value + '\'s';
703 | this.descr = this.name + ', ' + type;
704 | }
705 |
706 | return this.cards.length >= 7;
707 | }
708 | }
709 |
710 | class FullHouse extends Hand {
711 | constructor(cards, game, canDisqualify) {
712 | super(cards, 'Full House', game, canDisqualify);
713 | }
714 |
715 | solve() {
716 | var cards;
717 | this.resetWildCards();
718 |
719 | for (var i=0; i= 2) {
743 | this.cards = this.cards.concat(cards || []);
744 | for (var j=0; j= 5) {
766 | var type = this.cards[0].toString().slice(0, -1) + '\'s over ' + this.cards[3].toString().slice(0, -1) + '\'s';
767 | this.descr = this.name + ', ' + type;
768 | }
769 |
770 | return this.cards.length >= 5;
771 | }
772 | }
773 |
774 | class Flush extends Hand {
775 | constructor(cards, game, canDisqualify) {
776 | super(cards, 'Flush', game, canDisqualify);
777 | }
778 |
779 | solve() {
780 | this.sfLength = 0;
781 | this.resetWildCards();
782 |
783 | for (var suit in this.suits) {
784 | var cards = this.getCardsForFlush(suit, true);
785 | if (cards.length >= this.game.sfQualify) {
786 | this.cards = cards;
787 | break;
788 | }
789 | }
790 |
791 | if (this.cards.length >= this.game.sfQualify) {
792 | this.descr = this.name + ', ' + this.cards[0].toString().slice(0, -1) + suit + ' High';
793 | this.sfLength = this.cards.length;
794 | if (this.cards.length < this.game.cardsInHand) {
795 | this.cards = this.cards.concat(this.nextHighest().slice(0, this.game.cardsInHand-this.cards.length));
796 | }
797 | }
798 |
799 | return this.cards.length >= this.game.sfQualify;
800 | }
801 | }
802 |
803 | class Straight extends Hand {
804 | constructor(cards, game, canDisqualify) {
805 | super(cards, 'Straight', game, canDisqualify);
806 | }
807 |
808 | solve() {
809 | var card, checkCards;
810 | this.resetWildCards();
811 |
812 | // There are still some games that count the wheel as second highest.
813 | // These games do not have enough cards/wilds to make AKQJT and 5432A both possible.
814 | if (this.game.wheelStatus === 1) {
815 | this.cards = this.getWheel();
816 | if (this.cards.length) {
817 | var wildCount = 0;
818 | for (var i=0; i 1) {
871 | card.rank = this.cards[j-1].rank - 1;
872 | card.wildValue = values[card.rank];
873 | this.cards.push(card);
874 | break;
875 | }
876 | }
877 | }
878 | this.cards = this.cards.sort(Card.sort);
879 | }
880 | if (this.cards.length >= this.game.sfQualify) {
881 | this.descr = this.name + ', ' + this.cards[0].toString().slice(0, -1) + ' High';
882 | this.cards = this.cards.slice(0, this.game.cardsInHand);
883 | this.sfLength = this.cards.length;
884 | if (this.cards.length < this.game.cardsInHand) {
885 | if (this.cards[this.sfLength-1].rank === 0) {
886 | this.cards = this.cards.concat(this.nextHighest().slice(1, this.game.cardsInHand-this.cards.length+1));
887 | } else {
888 | this.cards = this.cards.concat(this.nextHighest().slice(0, this.game.cardsInHand-this.cards.length));
889 | }
890 | }
891 | }
892 |
893 | return this.cards.length >= this.game.sfQualify;
894 | }
895 |
896 | /**
897 | * Get the number of gaps in the straight.
898 | * @return {Array} Highest potential straight with fewest number of gaps.
899 | */
900 | getGaps(checkHandLength) {
901 | var wildCards, cardsToCheck, i, card, gapCards, cardsList, gapCount, prevCard, diff;
902 |
903 | var stripReturn = Hand.stripWilds(this.cardPool, this.game);
904 | wildCards = stripReturn[0];
905 | cardsToCheck = stripReturn[1];
906 |
907 | for (i=0; i0; i--) {
924 | cardsList = [];
925 | gapCount = 0;
926 | for (var j=0; j i) {
929 | continue;
930 | }
931 | prevCard = cardsList[cardsList.length - 1];
932 | diff = (prevCard) ? prevCard.rank - card.rank : i - card.rank;
933 |
934 | if (diff === null) {
935 | cardsList.push(card);
936 | } else if (checkHandLength < (gapCount + diff + cardsList.length)) {
937 | break;
938 | } else if (diff > 0) {
939 | cardsList.push(card);
940 | gapCount += (diff - 1);
941 | }
942 | }
943 | if (cardsList.length > gapCards.length) {
944 | gapCards = cardsList.slice();
945 | }
946 | if (this.game.sfQualify - gapCards.length <= wildCards.length) {
947 | break;
948 | }
949 | }
950 |
951 | return gapCards;
952 | }
953 |
954 | getWheel() {
955 | var wildCards, cardsToCheck, i, card, wheelCards, wildCount, cardFound;
956 |
957 | var stripReturn = Hand.stripWilds(this.cardPool, this.game);
958 | wildCards = stripReturn[0];
959 | cardsToCheck = stripReturn[1];
960 |
961 | for (i=0; i=0; i--) {
972 | cardFound = false;
973 | for (var j=0; j i) {
976 | continue;
977 | }
978 | if (card.rank < i) {
979 | break;
980 | }
981 | wheelCards.push(card);
982 | cardFound = true;
983 | break;
984 | }
985 | if (!cardFound) {
986 | if (wildCount < wildCards.length) {
987 | wildCards[wildCount].rank = i;
988 | wildCards[wildCount].wildValue = values[i];
989 | wheelCards.push(wildCards[wildCount]);
990 | wildCount += 1;
991 | } else {
992 | return [];
993 | }
994 | }
995 | }
996 |
997 | return wheelCards;
998 | }
999 | }
1000 |
1001 | class TwoThreeOfAKind extends Hand {
1002 | constructor(cards, game, canDisqualify) {
1003 | super(cards, 'Two Three Of a Kind', game, canDisqualify);
1004 | }
1005 |
1006 | solve() {
1007 | this.resetWildCards();
1008 | for (var i=0; i 0 && this.getNumCardsByRank(i) === 3) {
1011 | this.cards = this.cards.concat(cards || []);
1012 | for (var j=0; j= 6) {
1050 | var type = this.cards[0].toString().slice(0, -1) + '\'s & ' + this.cards[3].toString().slice(0, -1) + '\'s';
1051 | this.descr = this.name + ', ' + type;
1052 | }
1053 |
1054 | return this.cards.length >= 6;
1055 | }
1056 | }
1057 |
1058 | class ThreeOfAKind extends Hand {
1059 | constructor(cards, game, canDisqualify) {
1060 | super(cards, 'Three of a Kind', game, canDisqualify);
1061 | }
1062 |
1063 | solve() {
1064 | this.resetWildCards();
1065 |
1066 | for (var i=0; i= 3) {
1085 | if (this.game.noKickers) {
1086 | this.cards.length = 3;
1087 | }
1088 |
1089 | this.descr = this.name + ', ' + this.cards[0].toString().slice(0, -1) + '\'s';
1090 | }
1091 |
1092 | return this.cards.length >= 3;
1093 | }
1094 | }
1095 |
1096 | class ThreePair extends Hand {
1097 | constructor(cards, game, canDisqualify) {
1098 | super(cards, 'Three Pair', game, canDisqualify);
1099 | }
1100 |
1101 | solve() {
1102 | this.resetWildCards();
1103 |
1104 | for (var i=0; i 2 && this.getNumCardsByRank(i) === 2) {
1107 | this.cards = this.cards.concat(cards || []);
1108 | for (var j=0; j 0 && this.getNumCardsByRank(i) === 2) {
1126 | this.cards = this.cards.concat(cards || []);
1127 | for (var j=0; j= 6) {
1163 | var type = this.cards[0].toString().slice(0, -1) + '\'s & ' + this.cards[2].toString().slice(0, -1) + '\'s & ' + this.cards[4].toString().slice(0, -1) + '\'s';
1164 | this.descr = this.name + ', ' + type;
1165 | }
1166 |
1167 | return this.cards.length >= 6;
1168 | }
1169 | }
1170 |
1171 | class TwoPair extends Hand {
1172 | constructor(cards, game, canDisqualify) {
1173 | super(cards, 'Two Pair', game, canDisqualify);
1174 | }
1175 |
1176 | solve() {
1177 | this.resetWildCards();
1178 |
1179 | for (var i=0; i 0 && this.getNumCardsByRank(i) === 2) {
1182 | this.cards = this.cards.concat(cards || []);
1183 | for (var j=0; j= 4) {
1221 | if (this.game.noKickers) {
1222 | this.cards.length = 4;
1223 | }
1224 |
1225 | var type = this.cards[0].toString().slice(0, -1) + '\'s & ' + this.cards[2].toString().slice(0, -1) + '\'s';
1226 | this.descr = this.name + ', ' + type;
1227 | }
1228 |
1229 | return this.cards.length >= 4;
1230 | }
1231 | }
1232 |
1233 | class OnePair extends Hand {
1234 | constructor(cards, game, canDisqualify) {
1235 | super(cards, 'Pair', game, canDisqualify);
1236 | }
1237 |
1238 | solve() {
1239 | this.resetWildCards();
1240 |
1241 | for (var i=0; i= 2) {
1260 | if (this.game.noKickers) {
1261 | this.cards.length = 2;
1262 | }
1263 |
1264 | this.descr = this.name + ', ' + this.cards[0].toString().slice(0, -1) + '\'s';
1265 | }
1266 |
1267 | return this.cards.length >= 2;
1268 | }
1269 | }
1270 |
1271 | class HighCard extends Hand {
1272 | constructor(cards, game, canDisqualify) {
1273 | super(cards, 'High Card', game, canDisqualify);
1274 | }
1275 |
1276 | solve() {
1277 | this.cards = this.cardPool.slice(0, this.game.cardsInHand);
1278 |
1279 | for (var i=0; i= values.indexOf('T') && altHand.cards[0].rank <= values.indexOf('K') && altHand.cards[2].wildValue === 'A') {
1404 | var possibleSF = altHand.cards.slice(0, 2);
1405 | possibleSF = possibleSF.concat(altHand.cards.slice(3, 7));
1406 | sfReturn = this.getSFData(possibleSF);
1407 | if (sfReturn[0]) {
1408 | hiCards = sfReturn[0];
1409 | loCards = sfReturn[1];
1410 | loCards.push(altHand.cards[2]);
1411 | } else {
1412 | hiCards = altHand.cards.slice(0, 2);
1413 | loCards = altHand.cards.slice(2, 4);
1414 | hiCards = hiCards.concat(altHand.cards.slice(4, 7));
1415 | }
1416 | } else {
1417 | sfReturn = this.getSFData(altHand.cards.slice(2, 7));
1418 | if (sfReturn[0]) {
1419 | hiCards = sfReturn[0];
1420 | loCards = altHand.cards.slice(0, 2);
1421 | } else {
1422 | sfReturn = this.getSFData(altHand.cards);
1423 | hiCards = sfReturn[0];
1424 | loCards = sfReturn[1];
1425 | }
1426 | }
1427 | } else {
1428 | sfReturn = this.getSFData(altHand.cards);
1429 | hiCards = sfReturn[0];
1430 | loCards = sfReturn[1];
1431 | }
1432 | } else if (handValue === FourOfAKind) {
1433 | if (this.baseHand.cards[0].rank < 6) {
1434 | hiCards = this.baseHand.cards.slice(0, 4);
1435 | loCards = this.baseHand.cards.slice(4, 6);
1436 | hiCards.push(this.baseHand.cards[6]);
1437 | } else if (this.baseHand.cards[0].rank < 10 && this.baseHand.cards[4].wildValue === 'A') {
1438 | hiCards = this.baseHand.cards.slice(0, 4);
1439 | loCards = this.baseHand.cards.slice(4, 6);
1440 | hiCards.push(this.baseHand.cards[6]);
1441 | } else {
1442 | hiCards = this.baseHand.cards.slice(0, 2);
1443 | loCards = this.baseHand.cards.slice(2, 4);
1444 | hiCards = hiCards.concat(this.baseHand.cards.slice(4, 7));
1445 | }
1446 | } else if (handValue === TwoThreeOfAKind) {
1447 | loCards = this.baseHand.cards.slice(0, 2);
1448 | hiCards = this.baseHand.cards.slice(3, 6);
1449 | hiCards.push(this.baseHand.cards[2]);
1450 | hiCards.push(this.baseHand.cards[6]);
1451 | } else if (handValue === ThreeOfAKindTwoPair) {
1452 | hiCards = this.baseHand.cards.slice(0, 3);
1453 | loCards = this.baseHand.cards.slice(3, 5);
1454 | hiCards = hiCards.concat(this.baseHand.cards.slice(5, 7));
1455 | } else if (handValue === FullHouse) {
1456 | if (this.baseHand.cards[3].wildValue === '2' && this.baseHand.cards[5].wildValue === 'A' && this.baseHand.cards[6].wildValue === 'K') {
1457 | hiCards = this.baseHand.cards.slice(0, 5);
1458 | loCards = this.baseHand.cards.slice(5, 7);
1459 | } else {
1460 | hiCards = this.baseHand.cards.slice(0, 3);
1461 | loCards = this.baseHand.cards.slice(3, 5);
1462 | hiCards = hiCards.concat(this.baseHand.cards.slice(5, 7));
1463 | }
1464 | } else if (handValue === ThreeOfAKind) {
1465 | if (this.baseHand.cards[0].wildValue === 'A') {
1466 | hiCards = this.baseHand.cards.slice(0, 2);
1467 | loCards = this.baseHand.cards.slice(2, 4);
1468 | hiCards = hiCards.concat(this.baseHand.cards.slice(4, 7));
1469 | } else {
1470 | hiCards = this.baseHand.cards.slice(0, 3);
1471 | loCards = this.baseHand.cards.slice(3, 5);
1472 | hiCards = hiCards.concat(this.baseHand.cards.slice(5, 7));
1473 | }
1474 | } else if (handValue === ThreePair) {
1475 | loCards = this.baseHand.cards.slice(0, 2);
1476 | hiCards = this.baseHand.cards.slice(2, 7);
1477 | } else if (handValue === TwoPair) {
1478 | if (this.baseHand.cards[0].rank < 6) {
1479 | hiCards = this.baseHand.cards.slice(0, 4);
1480 | loCards = this.baseHand.cards.slice(4, 6);
1481 | hiCards.push(this.baseHand.cards[6]);
1482 | } else if (this.baseHand.cards[0].rank < 10) {
1483 | if (this.baseHand.cards[4].wildValue === 'A') {
1484 | hiCards = this.baseHand.cards.slice(0, 4);
1485 | loCards = this.baseHand.cards.slice(4, 6);
1486 | hiCards.push(this.baseHand.cards[6]);
1487 | } else {
1488 | hiCards = this.baseHand.cards.slice(0, 2);
1489 | loCards = this.baseHand.cards.slice(2, 4);
1490 | hiCards = hiCards.concat(this.baseHand.cards.slice(4, 7));
1491 | }
1492 | } else if (this.baseHand.cards[0].wildValue !== 'A' && this.baseHand.cards[2].rank < 6 && this.baseHand.cards[4].wildValue === 'A') {
1493 | hiCards = this.baseHand.cards.slice(0, 4);
1494 | loCards = this.baseHand.cards.slice(4, 6);
1495 | hiCards.push(this.baseHand.cards[6]);
1496 | } else {
1497 | hiCards = this.baseHand.cards.slice(0, 2);
1498 | loCards = this.baseHand.cards.slice(2, 4);
1499 | hiCards = hiCards.concat(this.baseHand.cards.slice(4, 7));
1500 | }
1501 | } else if (handValue === OnePair) {
1502 | hiCards = this.baseHand.cards.slice(0, 2);
1503 | loCards = this.baseHand.cards.slice(2, 4);
1504 | hiCards = hiCards.concat(this.baseHand.cards.slice(4, 7));
1505 | } else {
1506 | hiCards = [this.baseHand.cards[0]];
1507 | loCards = this.baseHand.cards.slice(1, 3);
1508 | hiCards = hiCards.concat(this.baseHand.cards.slice(3, 7));
1509 | }
1510 |
1511 | this.hiHand = Hand.solve(hiCards, this.hiGame);
1512 | this.loHand = Hand.solve(loCards, this.loGame);
1513 | }
1514 |
1515 | /*
1516 | * Determine the best possible Straight and/or Flush.
1517 | * @param {Array} cards 5-7 Card objects to check.
1518 | * @return {Array} [hiCards, loCards] High and Low components, if any.
1519 | */
1520 | getSFData(cards) {
1521 | var hiCards, possibleLoCards, bestLoCards, bestHand;
1522 | var handsToCheck = [
1523 | new StraightFlush(cards, new Game('paigowpokersf7')),
1524 | new StraightFlush(cards, new Game('paigowpokersf6')),
1525 | new StraightFlush(cards, this.game),
1526 | new Flush(cards, new Game('paigowpokersf7')),
1527 | new Flush(cards, new Game('paigowpokersf6')),
1528 | new Flush(cards, this.game),
1529 | new Straight(cards, new Game('paigowpokersf7')),
1530 | new Straight(cards, new Game('paigowpokersf6')),
1531 | new Straight(cards, this.game)
1532 | ];
1533 |
1534 | for (var i=0; i 6) {
1542 | possibleLoCards.push(hand.cards[6]);
1543 | }
1544 | } else if (cards.length > 5) {
1545 | possibleLoCards = [hand.cards[5]];
1546 | if (cards.length > 6) {
1547 | possibleLoCards.push(hand.cards[6]);
1548 | }
1549 | }
1550 | if (possibleLoCards) {
1551 | possibleLoCards = possibleLoCards.sort(Card.sort);
1552 | if (!bestLoCards || bestLoCards[0].rank < possibleLoCards[0].rank || (bestLoCards.length > 1 && bestLoCards[0].rank === possibleLoCards[0].rank && bestLoCards[1].rank < possibleLoCards[1].rank)) {
1553 | bestLoCards = possibleLoCards;
1554 | bestHand = hand;
1555 | }
1556 | } else if (!bestHand) {
1557 | bestHand = hand;
1558 | break;
1559 | }
1560 | }
1561 | }
1562 |
1563 | if (bestHand) {
1564 | if (bestHand.sfLength === 7) {
1565 | hiCards = bestHand.cards.slice(2, 7);
1566 | } else if (bestHand.sfLength === 6) {
1567 | hiCards = bestHand.cards.slice(1, 6);
1568 | } else {
1569 | hiCards = bestHand.cards.slice(0, 5);
1570 | }
1571 | }
1572 |
1573 | return [hiCards, bestLoCards];
1574 | }
1575 |
1576 | /*
1577 | * Determine if the setting of the hands is valid. Hi must be higher than lo.
1578 | * @return {Boolean}
1579 | */
1580 | qualifiesValid() {
1581 | var compareHands = Hand.winners([this.hiHand, this.loHand]);
1582 |
1583 | return !(compareHands.length === 1 && compareHands[0] === this.loHand);
1584 | }
1585 |
1586 | /**
1587 | * Find which of two split hands is best, according to rules.
1588 | * @param {PaiGowPokerHelper} player Player hand to evaluate. Must be set.
1589 | * @param {PaiGowPokerHelper} banker Banker hand to evaluate. Must be set.
1590 | * @param {int} winner Winning party, if any.
1591 | * Player = 1, Banker = -1, Push = 0
1592 | */
1593 | static winners(player, banker) {
1594 | if (!player.qualifiesValid()) {
1595 | if (banker.qualifiesValid()) {
1596 | return -1;
1597 | }
1598 | // Probably shouldn't get here because the dealer must set house way.
1599 | // However, we'll still have it as a sanity check, just in case.
1600 | return 0;
1601 | }
1602 |
1603 | if (!banker.qualifiesValid()) {
1604 | return 1;
1605 | }
1606 |
1607 | var hiWinner = Hand.winners([player.hiHand, banker.hiHand]);
1608 | var loWinner = Hand.winners([player.loHand, banker.loHand]);
1609 |
1610 | // In Pai Gow Poker, Banker takes any equal valued hands.
1611 | if (hiWinner.length === 1 && hiWinner[0] === player.hiHand) {
1612 | if (loWinner.length === 1 && loWinner[0] === player.loHand) {
1613 | // Player wins both; player wins
1614 | return 1;
1615 | }
1616 | // Player wins hi, Banker wins lo; push
1617 | return 0;
1618 | }
1619 |
1620 | if (loWinner.length === 1 && loWinner[0] === player.loHand) {
1621 | // Banker wins hi, Player wins lo; push
1622 | return 0;
1623 | }
1624 |
1625 | // Banker wins both; banker wins
1626 | return -1;
1627 | }
1628 |
1629 | /*
1630 | * Set a full hand into high and low hands, according to manual input.
1631 | * @param {Array} hiHand High hand to specify.
1632 | * Can also be {Hand} with game of 'paigowpokerhi'.
1633 | * @param {Array} loHand Low hand to specify.
1634 | * Can also be {Hand} with game of 'paigowpokerlo'.
1635 | * @return {PaiGowPokerHelper} Object with split hands.
1636 | */
1637 | static setHands(hiHand, loHand) {
1638 | var fullHand = [];
1639 |
1640 | if (Array.isArray(hiHand)) {
1641 | hiHand = Hand.solve(hiHand, new Game('paigowpokerhi'));
1642 | }
1643 | fullHand = fullHand.concat(hiHand.cardPool);
1644 | if (Array.isArray(loHand)) {
1645 | loHand = Hand.solve(loHand, new Game('paigowpokerlo'));
1646 | }
1647 | fullHand = fullHand.concat(loHand.cardPool);
1648 |
1649 | var result = new PaiGowPokerHelper(fullHand);
1650 | result.hiHand = hiHand;
1651 | result.loHand = loHand;
1652 |
1653 | return result;
1654 | }
1655 |
1656 | /**
1657 | * Build and return PaiGowPokerHelper object with hands split House Way.
1658 | * @param {Array} fullHand Array of cards (['Ad', '3c', 'Th', ...]).
1659 | * Can also be {Hand} with game of 'paigowpokerfull'.
1660 | * @return {PaiGowPokerHelper} Object with split hands.
1661 | */
1662 | static solve(fullHand) {
1663 | var result = new PaiGowPokerHelper(fullHand = fullHand || ['']);
1664 | result.splitHouseWay();
1665 |
1666 | return result;
1667 | }
1668 | }
1669 |
1670 | var gameRules = {
1671 | 'standard': {
1672 | 'cardsInHand': 5,
1673 | 'handValues': [StraightFlush, FourOfAKind, FullHouse, Flush, Straight, ThreeOfAKind, TwoPair, OnePair, HighCard],
1674 | 'wildValue': null,
1675 | 'wildStatus': 1,
1676 | 'wheelStatus': 0,
1677 | 'sfQualify': 5,
1678 | 'lowestQualified': null,
1679 | "noKickers": false
1680 | },
1681 | 'jacksbetter': {
1682 | 'cardsInHand': 5,
1683 | 'handValues': [StraightFlush, FourOfAKind, FullHouse, Flush, Straight, ThreeOfAKind, TwoPair, OnePair, HighCard],
1684 | 'wildValue': null,
1685 | 'wildStatus': 1,
1686 | 'wheelStatus': 0,
1687 | 'sfQualify': 5,
1688 | 'lowestQualified': ['Jc', 'Jd', '4h', '3s', '2c'],
1689 | "noKickers": true
1690 | },
1691 | 'joker': {
1692 | 'cardsInHand': 5,
1693 | 'handValues': [NaturalRoyalFlush, FiveOfAKind, WildRoyalFlush, StraightFlush, FourOfAKind, FullHouse, Flush, Straight, ThreeOfAKind, TwoPair, HighCard],
1694 | 'wildValue': 'O',
1695 | 'wildStatus': 1,
1696 | 'wheelStatus': 0,
1697 | 'sfQualify': 5,
1698 | 'lowestQualified': ['4c', '3d', '3h', '2s', '2c'],
1699 | "noKickers": true
1700 | },
1701 | 'deuceswild': {
1702 | 'cardsInHand': 5,
1703 | 'handValues': [NaturalRoyalFlush, FourWilds, WildRoyalFlush, FiveOfAKind, StraightFlush, FourOfAKind, FullHouse, Flush, Straight, ThreeOfAKind, HighCard],
1704 | 'wildValue': '2',
1705 | 'wildStatus': 1,
1706 | 'wheelStatus': 0,
1707 | 'sfQualify': 5,
1708 | 'lowestQualified': ['5c', '4d', '3h', '3s', '3c'],
1709 | "noKickers": true
1710 | },
1711 | 'threecard': {
1712 | 'cardsInHand': 3,
1713 | 'handValues': [StraightFlush, ThreeOfAKind, Straight, Flush, OnePair, HighCard],
1714 | 'wildValue': null,
1715 | 'wildStatus': 1,
1716 | 'wheelStatus': 0,
1717 | 'sfQualify': 3,
1718 | 'lowestQualified': ['Qh', '3s', '2c'],
1719 | "noKickers": false
1720 | },
1721 | 'fourcard': {
1722 | 'cardsInHand': 4,
1723 | 'handValues': [FourOfAKind, StraightFlush, ThreeOfAKind, Flush, Straight, TwoPair, OnePair, HighCard],
1724 | 'wildValue': null,
1725 | 'wildStatus': 1,
1726 | 'wheelStatus': 0,
1727 | 'sfQualify': 4,
1728 | 'lowestQualified': null,
1729 | "noKickers": true
1730 | },
1731 | 'fourcardbonus': {
1732 | 'cardsInHand': 4,
1733 | 'handValues': [FourOfAKind, StraightFlush, ThreeOfAKind, Flush, Straight, TwoPair, OnePair, HighCard],
1734 | 'wildValue': null,
1735 | 'wildStatus': 1,
1736 | 'wheelStatus': 0,
1737 | 'sfQualify': 4,
1738 | 'lowestQualified': ['Ac', 'Ad', '3h', '2s'],
1739 | "noKickers": true
1740 | },
1741 | 'paigowpokerfull': {
1742 | 'cardsInHand': 7,
1743 | 'handValues': [FiveOfAKind, FourOfAKindPairPlus, StraightFlush, Flush, Straight, FourOfAKind, TwoThreeOfAKind, ThreeOfAKindTwoPair, FullHouse, ThreeOfAKind, ThreePair, TwoPair, OnePair, HighCard],
1744 | 'wildValue': 'O',
1745 | 'wildStatus': 0,
1746 | 'wheelStatus': 1,
1747 | 'sfQualify': 5,
1748 | 'lowestQualified': null
1749 | },
1750 | 'paigowpokeralt': {
1751 | 'cardsInHand': 7,
1752 | 'handValues': [FourOfAKind, FullHouse, ThreeOfAKind, ThreePair, TwoPair, OnePair, HighCard],
1753 | 'wildValue': 'O',
1754 | 'wildStatus': 0,
1755 | 'wheelStatus': 1,
1756 | 'sfQualify': 5,
1757 | 'lowestQualified': null
1758 | },
1759 | 'paigowpokersf6': {
1760 | 'cardsInHand': 7,
1761 | 'handValues': [StraightFlush, Flush, Straight],
1762 | 'wildValue': 'O',
1763 | 'wildStatus': 0,
1764 | 'wheelStatus': 1,
1765 | 'sfQualify': 6,
1766 | 'lowestQualified': null
1767 | },
1768 | 'paigowpokersf7': {
1769 | 'cardsInHand': 7,
1770 | 'handValues': [StraightFlush, Flush, Straight],
1771 | 'wildValue': 'O',
1772 | 'wildStatus': 0,
1773 | 'wheelStatus': 1,
1774 | 'sfQualify': 7,
1775 | 'lowestQualified': null
1776 | },
1777 | 'paigowpokerhi': {
1778 | 'cardsInHand': 5,
1779 | 'handValues': [FiveOfAKind, StraightFlush, FourOfAKind, FullHouse, Flush, Straight, ThreeOfAKind, TwoPair, OnePair, HighCard],
1780 | 'wildValue': 'O',
1781 | 'wildStatus': 0,
1782 | 'wheelStatus': 1,
1783 | 'sfQualify': 5,
1784 | 'lowestQualified': null
1785 | },
1786 | 'paigowpokerlo': {
1787 | 'cardsInHand': 2,
1788 | 'handValues': [OnePair, HighCard],
1789 | 'wildValue': 'O',
1790 | 'wildStatus': 0,
1791 | 'wheelStatus': 1,
1792 | 'sfQualify': 5,
1793 | 'lowestQualified': null
1794 | }
1795 | };
1796 |
1797 | /**
1798 | * Base Game class that defines the rules of the game.
1799 | */
1800 | class Game {
1801 | constructor(descr) {
1802 | this.descr = descr;
1803 | this.cardsInHand = 0;
1804 | this.handValues = [];
1805 | this.wildValue = null;
1806 | this.wildStatus = 0;
1807 | this.wheelStatus = 0;
1808 | this.sfQualify = 5;
1809 | this.lowestQualified = null;
1810 | this.noKickers = null;
1811 |
1812 | // Set values based on the game rules.
1813 | if (!this.descr || !gameRules[this.descr]) {
1814 | this.descr = 'standard';
1815 | }
1816 | this.cardsInHand = gameRules[this.descr]['cardsInHand'];
1817 | this.handValues = gameRules[this.descr]['handValues'];
1818 | this.wildValue = gameRules[this.descr]['wildValue'];
1819 | this.wildStatus = gameRules[this.descr]['wildStatus'];
1820 | this.wheelStatus = gameRules[this.descr]['wheelStatus'];
1821 | this.sfQualify = gameRules[this.descr]['sfQualify'];
1822 | this.lowestQualified = gameRules[this.descr]['lowestQualified'];
1823 | this.noKickers = gameRules[this.descr]['noKickers'];
1824 | }
1825 | }
1826 |
1827 | function exportToGlobal(global) {
1828 | global.Card = Card;
1829 | global.Hand = Hand;
1830 | global.Game = Game;
1831 | global.RoyalFlush = RoyalFlush;
1832 | global.NaturalRoyalFlush = NaturalRoyalFlush;
1833 | global.WildRoyalFlush = WildRoyalFlush;
1834 | global.FiveOfAKind = FiveOfAKind;
1835 | global.StraightFlush = StraightFlush;
1836 | global.FourOfAKindPairPlus = FourOfAKindPairPlus;
1837 | global.FourOfAKind = FourOfAKind;
1838 | global.FourWilds = FourWilds;
1839 | global.TwoThreeOfAKind = TwoThreeOfAKind;
1840 | global.ThreeOfAKindTwoPair = ThreeOfAKindTwoPair;
1841 | global.FullHouse = FullHouse;
1842 | global.Flush = Flush;
1843 | global.Straight = Straight;
1844 | global.ThreeOfAKind = ThreeOfAKind;
1845 | global.ThreePair = ThreePair;
1846 | global.TwoPair = TwoPair;
1847 | global.OnePair = OnePair;
1848 | global.HighCard = HighCard;
1849 | global.PaiGowPokerHelper = PaiGowPokerHelper;
1850 | }
1851 |
1852 | // Export the classes for node.js use.
1853 | if (typeof exports !== 'undefined') {
1854 | exportToGlobal(exports);
1855 | }
1856 |
1857 | // Add the classes to the window for browser use.
1858 | if (typeof window !== 'undefined') {
1859 | exportToGlobal(window);
1860 | }
1861 |
1862 | })();
1863 |
--------------------------------------------------------------------------------
/test/deuceswild.js:
--------------------------------------------------------------------------------
1 | var should = require('should');
2 | var Hand = require('../pokersolver').Hand;
3 | var Flush = require('../pokersolver').Flush;
4 | var StraightFlush = require('../pokersolver').StraightFlush;
5 | var NaturalRoyalFlush = require('../pokersolver').NaturalRoyalFlush;
6 | var WildRoyalFlush = require('../pokersolver').WildRoyalFlush;
7 | var Straight = require('../pokersolver').Straight;
8 | var FiveOfAKind = require('../pokersolver').FiveOfAKind;
9 | var FourOfAKind = require('../pokersolver').FourOfAKind;
10 | var FourWilds = require('../pokersolver').FourWilds;
11 | var FullHouse = require('../pokersolver').FullHouse;
12 | var ThreeOfAKind = require('../pokersolver').ThreeOfAKind;
13 | var Game = require('../pokersolver').Game;
14 |
15 | var gameForTest = new Game('deuceswild');
16 |
17 | // Deuces Wild is designed to be for five cards, but can be for any number.
18 | describe('A basic hand', function() {
19 | it('should return a hand with cards sorted descending, wilds last', function() {
20 | var hand = Hand.solve(['Kh', 'Tc', 'As', '3s', '2h'], gameForTest);
21 | hand.cardPool[0].toString().should.equal('As');
22 | return hand.cardPool[4].toString().should.equal('Ah');
23 | });
24 | return it('should return a correct description with a deuce', function() {
25 | var hand = Hand.solve(['Kh', 'As', '3c', '3s', '2h'], gameForTest);
26 | return hand.descr.should.equal('Three of a Kind, 3\'s');
27 | });
28 | });
29 |
30 | describe('A Natural Royal Flush', function() {
31 | it('should be detected as possible', function() {
32 | var hand = new NaturalRoyalFlush(['As', 'Qs', 'Js', 'Ts', 'Ks'], gameForTest);
33 | return hand.isPossible.should.equal(true);
34 | });
35 | it('should be detected as not possible', function() {
36 | var hand = new NaturalRoyalFlush(['7s', '8s', 'Js', 'Ts', '9s'], gameForTest);
37 | return hand.isPossible.should.equal(false);
38 | });
39 | return it('should be detected as not possible with a deuce', function() {
40 | var hand = new NaturalRoyalFlush(['2s', 'Ks', 'Js', 'Ts', 'Qs'], gameForTest);
41 | return hand.isPossible.should.equal(false);
42 | });
43 | });
44 |
45 | describe('A Wild Royal Flush', function() {
46 | it('should be detected as possible', function() {
47 | var hand = new WildRoyalFlush(['As', '2s', 'Js', 'Ts', 'Ks'], gameForTest);
48 | return hand.isPossible.should.equal(true);
49 | });
50 | it('should be detected as not possible', function() {
51 | var hand = new WildRoyalFlush(['7s', '2s', 'Js', 'Ts', '9s'], gameForTest);
52 | return hand.isPossible.should.equal(false);
53 | });
54 | it('should be detected as possible with any deuce - inside', function() {
55 | var hand = new WildRoyalFlush(['Ks', 'As', 'Js', 'Ts', '2d'], gameForTest);
56 | return hand.isPossible.should.equal(true);
57 | });
58 | it('should be detected as possible with a deuce - outside', function() {
59 | var hand = new WildRoyalFlush(['Ks', 'Qs', 'Js', 'Ts', '2h'], gameForTest);
60 | hand.isPossible.should.equal(true);
61 | });
62 | it('should be detected as possible with two deuces - inside/outside', function() {
63 | var hand = new WildRoyalFlush(['2c', 'Qs', 'Ts', 'Ks', '2s'], gameForTest);
64 | hand.isPossible.should.equal(true);
65 | });
66 | return it('should be detected as possible with deuces - can set as low', function() {
67 | var hand = new WildRoyalFlush(['Qs', '2s', 'As', 'Js', 'Ks'], gameForTest);
68 | hand.isPossible.should.equal(true);
69 | });
70 | });
71 |
72 | describe('A Straight Flush', function() {
73 | it('should be detected as possible', function() {
74 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9s'], gameForTest);
75 | return hand.isPossible.should.equal(true);
76 | });
77 | it('should be detected as not possible', function() {
78 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9d'], gameForTest);
79 | return hand.isPossible.should.equal(false);
80 | });
81 | it('should be detected as possible with a deuce - inside', function() {
82 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '2s'], gameForTest);
83 | return hand.isPossible.should.equal(true);
84 | });
85 | it('should be detected as possible with a deuce - outside', function() {
86 | var hand = new StraightFlush(['7s', '8s', '9s', 'Ts', '2c'], gameForTest);
87 | hand.isPossible.should.equal(true);
88 | return hand.descr.should.equal('Straight Flush, Js High');
89 | });
90 | it('should be detected as possible with two deuces - inside/outside', function() {
91 | var hand = new StraightFlush(['2d', '8s', 'Js', 'Ts', '2h'], gameForTest);
92 | hand.isPossible.should.equal(true);
93 | return hand.descr.should.equal('Straight Flush, Qs High');
94 | });
95 | it('should be detected as possible with deuces - highest possible', function() {
96 | var hand = new StraightFlush(['Qs', '2s', '8s', 'Js', 'Kh', 'Ts', '2c'], gameForTest);
97 | hand.isPossible.should.equal(true);
98 | return hand.descr.should.equal('Royal Flush');
99 | });
100 | it('should be detected as possible with deuces - can set as low', function() {
101 | var hand = new StraightFlush(['Qs', '2h', 'As', 'Js', 'Kh', 'Ts', '2d'], gameForTest);
102 | hand.isPossible.should.equal(true);
103 | return hand.descr.should.equal('Royal Flush');
104 | });
105 | return it('should be detected as not possible, even with a deuce', function() {
106 | var hand = new StraightFlush(['2c', '8s', 'Js', 'Ts', '9d'], gameForTest);
107 | return hand.isPossible.should.equal(false);
108 | });
109 | });
110 |
111 | describe('A Five of a Kind', function() {
112 | it('should be detected as possible with deuce', function() {
113 | var hand = new FiveOfAKind(['7h', '7d', '2s', '7s', '7c'], gameForTest);
114 | return hand.isPossible.should.equal(true);
115 | });
116 | return it('should be detected as not possible', function() {
117 | var hand = new FiveOfAKind(['7h', '7d', '3s', '7s', '7c'], gameForTest);
118 | return hand.isPossible.should.equal(false);
119 | });
120 | return it('should be detected as not possible, even with a deuce', function() {
121 | var hand = new FiveOfAKind(['7h', '2c', '3s', '7s', '7c'], gameForTest);
122 | return hand.isPossible.should.equal(false);
123 | });
124 | });
125 |
126 | describe('Four Deuces', function() {
127 | it('should be detected as possible', function() {
128 | var hand = new FourWilds(['2h', '2d', '3s', '2s', '2c'], gameForTest);
129 | return hand.isPossible.should.equal(true);
130 | });
131 | return it('should be detected as not possible', function() {
132 | var hand = new FourWilds(['2h', '3d', '3s', '2s', '2c'], gameForTest);
133 | return hand.isPossible.should.equal(false);
134 | });
135 | });
136 |
137 | describe('A Four of a Kind', function() {
138 | it('should be detected as possible', function() {
139 | var hand = new FourOfAKind(['7h', '7d', '3s', '7s', '7c'], gameForTest);
140 | return hand.isPossible.should.equal(true);
141 | });
142 | it('should be detected as possible with a deuce', function() {
143 | var hand = new FourOfAKind(['7h', '3d', '2s', '7s', '7c'], gameForTest);
144 | return hand.isPossible.should.equal(true);
145 | });
146 | it('should be detected as not possible', function() {
147 | var hand = new FourOfAKind(['7h', '3d', '3s', '7s', '7c'], gameForTest);
148 | return hand.isPossible.should.equal(false);
149 | });
150 | return it('should be detected as not possible, even with a deuce', function() {
151 | var hand = new FourOfAKind(['7h', '3d', '3s', '2s', '7c'], gameForTest);
152 | return hand.isPossible.should.equal(false);
153 | });
154 | });
155 |
156 | describe('A Full House', function() {
157 | it('should be detected as possible, with/without deuce 1', function() {
158 | var hand = new FullHouse(['Qd', 'Js', 'Qc', 'Jc', 'Jd'], gameForTest);
159 | return hand.isPossible.should.equal(true);
160 | });
161 | it('should be detected as possible, with/without deuce 2', function() {
162 | var hand = new FullHouse(['9c', '9d', 'Jh', 'Jc', 'Js', '9h', 'As'], gameForTest);
163 | return hand.isPossible.should.equal(true);
164 | });
165 | it('should be detected as possible, with/without deuce 3', function() {
166 | var hand = new FullHouse(['9c', '9d', '2s', 'Jc', 'Js'], gameForTest);
167 | return hand.isPossible.should.equal(true);
168 | });
169 | it('should be detected as possible, with/without deuce 4', function() {
170 | var hand = new FullHouse(['9c', '9d', 'Jh', '2s', 'Js', '9h', 'As'], gameForTest);
171 | return hand.isPossible.should.equal(true);
172 | });
173 | it('should be detected as possible, with/without deuce 5', function() {
174 | var hand = new FullHouse(['9h', '9s', '2s', '5c', 'Kd', '5d', 'Kh'], gameForTest);
175 | return hand.isPossible.should.equal(true);
176 | });
177 | it('should be detected as not possible, with/without deuce', function() {
178 | var hand = new FullHouse(['Kd', '6h', '7s', '7d', 'Kh'], gameForTest);
179 | hand.isPossible.should.equal(false);
180 | hand = new FullHouse(['9h', '9s', '2s', '5d', 'Kh'], gameForTest);
181 | return hand.isPossible.should.equal(false);
182 | });
183 | it('should pick the high kickers', function() {
184 | var hand = new FullHouse(['5d', '5h', '3h', '3c', 'Qh', 'Qd', 'Qs'], gameForTest);
185 | hand.cards.toString().indexOf('3h').should.equal(-1);
186 | hand = new FullHouse(['5d', '5h', '3h', '3c', '2s', 'Qd', 'Qs'], gameForTest);
187 | return hand.cards.toString().indexOf('3h').should.equal(-1);
188 | });
189 | it('should be in order', function() {
190 | var hand = new FullHouse(['9c', 'Qs', '9h', '5h', 'Ts', 'Qc', 'Qh'], gameForTest);
191 | hand.cards.toString().should.equal('Qs,Qc,Qh,9c,9h');
192 | hand = new FullHouse(['9c', 'Qs', '9h', '5h', 'Ts', '2s', 'Qh'], gameForTest);
193 | return hand.cards.toString().should.equal('Qs,Qh,Qs,9c,9h');
194 | });
195 | });
196 |
197 | describe('A Flush', function() {
198 | it('should be detected as possible', function() {
199 | var hand = new Flush(['4h', 'Th', '5h', '3h', 'Kh'], gameForTest);
200 | return hand.isPossible.should.equal(true);
201 | });
202 | it('should be detected as not possible', function() {
203 | var hand = new Flush(['Th', '5h', '3h', 'Kh', '8d'], gameForTest);
204 | return hand.isPossible.should.equal(false);
205 | });
206 | it('should be detected as possible with a deuce, highest rank', function() {
207 | var hand = new Flush(['4h', 'Th', '5h', '2c', 'Kh'], gameForTest);
208 | return hand.isPossible.should.equal(true);
209 | });
210 | it('should be detected as possible with a deuce, next highest rank', function() {
211 | var hand = new Flush(['4h', 'Th', 'Ah', '2s', 'Kh'], gameForTest);
212 | return hand.isPossible.should.equal(true);
213 | });
214 | return it('should be detected as not possible, even with deuce', function() {
215 | var hand = new Flush(['4s', 'Th', '2s', 'Ac', '3h', 'Kh', '8d'], gameForTest);
216 | return hand.isPossible.should.equal(false);
217 | });
218 | });
219 |
220 | describe('A Straight', function() {
221 | it('should be detected as possible', function() {
222 | var hand = new Straight(['6s', '3s', '7s', '4s', '5c'], gameForTest);
223 | return hand.isPossible.should.equal(true);
224 | });
225 | it('should be detected as possible', function() {
226 | var hand = new Straight(['5d', '6s', '7s', '8c', 'Ts', '9s', '3d'], gameForTest);
227 | return hand.isPossible.should.equal(true);
228 | });
229 | it('should be detected as not possible', function() {
230 | var hand = new Straight(['5h', '6s', '6h', '7c', '8d'], gameForTest);
231 | return hand.isPossible.should.equal(false);
232 | });
233 | it('should detect a low ace', function() {
234 | var hand = new Straight(['2c', '3s', '4h', '5c', 'As'], gameForTest);
235 | return hand.isPossible.should.equal(true);
236 | });
237 | it('should detect a high ace', function() {
238 | var hand = new Straight(['2d', '3s', '4h', '7c', 'As', 'Ts', 'Kd'], gameForTest);
239 | return hand.isPossible.should.equal(false);
240 | });
241 | it('should be detected as possible with a deuce - inside', function() {
242 | var hand = new Straight(['7s', '8s', 'Jc', 'Ts', '2d'], gameForTest);
243 | return hand.isPossible.should.equal(true);
244 | });
245 | it('should be detected as possible with a deuce - outside', function() {
246 | var hand = new Straight(['7d', '8s', '9s', 'Ts', '2d'], gameForTest);
247 | hand.isPossible.should.equal(true);
248 | return hand.descr.should.equal('Straight, J High');
249 | });
250 | it('should be detected as possible with two deuces - inside/outside', function() {
251 | var hand = new Straight(['2c', '8s', 'Jh', 'Ts', '2d'], gameForTest);
252 | hand.isPossible.should.equal(true);
253 | return hand.descr.should.equal('Straight, Q High');
254 | });
255 | it('should be detected as possible with deuces - highest possible', function() {
256 | var hand = new Straight(['Qs', '2c', '8s', 'Jh', 'Kh', 'Ts', '2d'], gameForTest);
257 | hand.isPossible.should.equal(true);
258 | return hand.descr.should.equal('Straight, A High');
259 | });
260 | it('should be detected as possible with deuces - can set as low', function() {
261 | var hand = new Straight(['Qs', '2h', 'As', 'Js', 'Kh', 'Ts', '2s'], gameForTest);
262 | hand.isPossible.should.equal(true);
263 | return hand.descr.should.equal('Straight, A High');
264 | });
265 | return it('should be detected as not possible, even with a deuce', function() {
266 | var hand = new Straight(['2c', '8s', 'Js', 'Ts', '8d'], gameForTest);
267 | return hand.isPossible.should.equal(false);
268 | });
269 | });
270 |
271 | describe('Three of a Kind', function() {
272 | it('should be detected as possible', function() {
273 | var hand = new ThreeOfAKind(['5c', '5s', '5h', '6c', '3d'], gameForTest);
274 | hand.isPossible.should.equal(true);
275 | });
276 | it('should be detected as not possible', function() {
277 | var hand = new ThreeOfAKind(['5c', '3h', '5h', '6c', '3d'], gameForTest);
278 | return hand.isPossible.should.equal(false);
279 | });
280 | it('should be detected as possible with deuce', function() {
281 | var hand = new ThreeOfAKind(['5c', '5s', '2c', '6c', '3d'], gameForTest);
282 | hand.isPossible.should.equal(true);
283 | });
284 | return it('should be detected as not possible', function() {
285 | var hand = new ThreeOfAKind(['5c', '7h', '3c', '6c', '2d'], gameForTest);
286 | return hand.isPossible.should.equal(false);
287 | });
288 | });
289 |
290 | describe('Qualifying Hands', function() {
291 | it('Royal Flush should qualify', function() {
292 | var hand = Hand.solve(['As', 'Or', 'Js', 'Ts', 'Qs'], gameForTest, true);
293 | var winners = Hand.winners([hand]);
294 | winners.length.should.equal(1);
295 | return winners[0].should.equal(hand);
296 | });
297 | it('Five of a Kind should qualify', function() {
298 | var hand = Hand.solve(['7h', '7d', 'Or', '7s', '7c'], gameForTest, true);
299 | var winners = Hand.winners([hand]);
300 | winners.length.should.equal(1);
301 | return winners[0].should.equal(hand);
302 | });
303 | it('Straight Flush should qualify', function() {
304 | var hand = Hand.solve(['7s', '8s', 'Js', 'Ts', '9s'], gameForTest, true);
305 | var winners = Hand.winners([hand]);
306 | winners.length.should.equal(1);
307 | return winners[0].should.equal(hand);
308 | });
309 | it('Four of a Kind should qualify', function() {
310 | var hand = Hand.solve(['7h', '7d', '3s', '7s', '7c'], gameForTest, true);
311 | var winners = Hand.winners([hand]);
312 | winners.length.should.equal(1);
313 | return winners[0].should.equal(hand);
314 | });
315 | it('Full House should qualify', function() {
316 | var hand = Hand.solve(['9c', '9d', 'Or', 'Jc', 'Js'], gameForTest, true);
317 | var winners = Hand.winners([hand]);
318 | winners.length.should.equal(1);
319 | return winners[0].should.equal(hand);
320 | });
321 | it('Flush should qualify', function() {
322 | var hand = Hand.solve(['7s', '8s', 'Js', 'Ts', 'Qs'], gameForTest, true);
323 | var winners = Hand.winners([hand]);
324 | winners.length.should.equal(1);
325 | return winners[0].should.equal(hand);
326 | });
327 | it('Straight should qualify', function() {
328 | var hand = Hand.solve(['7s', '8d', 'Js', 'Ts', '9s'], gameForTest, true);
329 | var winners = Hand.winners([hand]);
330 | winners.length.should.equal(1);
331 | return winners[0].should.equal(hand);
332 | });
333 | it('Three of a Kind should qualify', function() {
334 | var hand = Hand.solve(['7h', '7d', '3s', '4s', '7c'], gameForTest, true);
335 | var winners = Hand.winners([hand]);
336 | winners.length.should.equal(1);
337 | return winners[0].should.equal(hand);
338 | });
339 | it('Three of a Kind should qualify with deuces', function() {
340 | var hand = Hand.solve(['2h', '2d', '3s', '2s', '7c'], gameForTest, true);
341 | var winners = Hand.winners([hand]);
342 | winners.length.should.equal(1);
343 | return winners[0].should.equal(hand);
344 | });
345 | it('Two Pair should not qualify', function() {
346 | var hand = Hand.solve(['5c', '4s', '4c', '3d', '3h'], gameForTest, true);
347 | var winners = Hand.winners([hand]);
348 | return winners.length.should.equal(0);
349 | });
350 | it('One Pair should not qualify', function() {
351 | var hand = Hand.solve(['Ah', 'As', '6d', '3s', '4h'], gameForTest, true);
352 | var winners = Hand.winners([hand]);
353 | return winners.length.should.equal(0);
354 | });
355 | it('High Card should not qualify', function() {
356 | var hand = Hand.solve(['Qh', '9s', 'Ad', 'Ks', 'Jh'], gameForTest, true);
357 | var winners = Hand.winners([hand]);
358 | return winners.length.should.equal(0);
359 | });
360 | });
361 |
--------------------------------------------------------------------------------
/test/fourcard.js:
--------------------------------------------------------------------------------
1 | var should = require('should');
2 | var Hand = require('../pokersolver').Hand;
3 | var Flush = require('../pokersolver').Flush;
4 | var StraightFlush = require('../pokersolver').StraightFlush;
5 | var Straight = require('../pokersolver').Straight;
6 | var FourOfAKind = require('../pokersolver').FourOfAKind;
7 | var ThreeOfAKind = require('../pokersolver').ThreeOfAKind;
8 | var TwoPair = require('../pokersolver').TwoPair;
9 | var OnePair = require('../pokersolver').OnePair;
10 | var Game = require('../pokersolver').Game;
11 |
12 | var gameForTest = new Game('fourcard');
13 |
14 | // Four Card Poker is only three cards, and a different ranking.
15 | // All hands qualify for the purposes of ante/play.
16 | describe('A basic hand', function() {
17 | it('should return a hand with cards sorted descending', function() {
18 | var hand = Hand.solve(['Kh', 'Tc', 'As', '3s', '2h'], gameForTest);
19 | hand.cardPool[0].toString().should.equal('As');
20 | return hand.cardPool[4].toString().should.equal('2h');
21 | });
22 | return it('should return a correct description', function() {
23 | var hand = Hand.solve(['Kh', 'As', 'Ad', '3s', '2h'], gameForTest);
24 | return hand.descr.should.equal('Pair, A\'s');
25 | });
26 | });
27 |
28 | describe('A Four of a Kind', function() {
29 | it('should be detected as possible', function() {
30 | var hand = new FourOfAKind(['7h', '7d', '7s', '7c'], gameForTest);
31 | return hand.isPossible.should.equal(true);
32 | });
33 | return it('should be detected as not possible', function() {
34 | var hand = new FourOfAKind(['7h', '3d', '7s', '7c'], gameForTest);
35 | return hand.isPossible.should.equal(false);
36 | });
37 | });
38 |
39 | describe('A Straight Flush', function() {
40 | it('should be detected as possible', function() {
41 | var hand = new StraightFlush(['8s', 'Js', 'Ts', '9s'], gameForTest);
42 | return hand.isPossible.should.equal(true);
43 | });
44 | return it('should be detected as not possible', function() {
45 | var hand = new StraightFlush(['8s', 'Js', 'Ts', '9d'], gameForTest);
46 | return hand.isPossible.should.equal(false);
47 | });
48 | });
49 |
50 | describe('Three of a Kind', function() {
51 | it('should be detected as possible', function() {
52 | var hand = new ThreeOfAKind(['5c', '5s', '5h', '6c'], gameForTest);
53 | hand.isPossible.should.equal(true);
54 | });
55 | return it('should be detected as not possible', function() {
56 | var hand = new ThreeOfAKind(['5c', '2h', '5h', '2d'], gameForTest);
57 | return hand.isPossible.should.equal(false);
58 | });
59 | });
60 |
61 | describe('A Flush', function() {
62 | it('should be detected as possible', function() {
63 | var hand = new Flush(['4h', '5h', '2h', 'Kh'], gameForTest);
64 | return hand.isPossible.should.equal(true);
65 | });
66 | return it('should be detected as not possible', function() {
67 | var hand = new Flush(['Th', '2h', 'Kh', '8d'], gameForTest);
68 | return hand.isPossible.should.equal(false);
69 | });
70 | });
71 |
72 | describe('A Straight', function() {
73 | it('should be detected as possible', function() {
74 | var hand = new Straight(['3s', '2s', '4s', '5c'], gameForTest);
75 | return hand.isPossible.should.equal(true);
76 | });
77 | it('should be detected as not possible', function() {
78 | var hand = new Straight(['6s', '6h', '7c', '8d'], gameForTest);
79 | return hand.isPossible.should.equal(false);
80 | });
81 | it('should detect a low ace', function() {
82 | var hand = new Straight(['2c', '3s', '4h', 'As'], gameForTest);
83 | return hand.isPossible.should.equal(true);
84 | });
85 | return it('should detect a high ace', function() {
86 | var hand = new Straight(['2d', '3s', 'As', 'Kd'], gameForTest);
87 | return hand.isPossible.should.equal(false);
88 | });
89 | });
90 |
91 | describe('Two Pair', function() {
92 | it('should be detected as possible', function() {
93 | var hand = new TwoPair(['5c', '5c', '6s', '6c'], gameForTest);
94 | return hand.isPossible.should.equal(true);
95 | });
96 | return it('should be detected as not possible', function() {
97 | var hand = new TwoPair(['5c', '6s', '6h', '8d'], gameForTest);
98 | return hand.isPossible.should.equal(false);
99 | });
100 | });
101 |
102 | describe('One Pair', function() {
103 | it('should be detected as possible', function() {
104 | var hand = new OnePair(['5h', '5c', '9s', '2d'], gameForTest);
105 | return hand.isPossible.should.equal(true);
106 | });
107 | return it('should be detected as not possible', function() {
108 | var hand = new OnePair(['5h', '6s', 'Ts', '8d'], gameForTest);
109 | return hand.isPossible.should.equal(false);
110 | });
111 | });
112 |
113 | describe('Qualifying Hands', function() {
114 | it('Straight Flush should qualify', function() {
115 | var hand = Hand.solve(['8s', 'Js', 'Ts', '9s'], gameForTest, true);
116 | var winners = Hand.winners([hand]);
117 | winners.length.should.equal(1);
118 | return winners[0].should.equal(hand);
119 | });
120 | it('Four of a Kind should qualify', function() {
121 | var hand = Hand.solve(['7h', '7d', '7s', '7c'], gameForTest, true);
122 | var winners = Hand.winners([hand]);
123 | winners.length.should.equal(1);
124 | return winners[0].should.equal(hand);
125 | });
126 | it('Flush should qualify', function() {
127 | var hand = Hand.solve(['7s', '8s', 'Ts', 'Qs'], gameForTest, true);
128 | var winners = Hand.winners([hand]);
129 | winners.length.should.equal(1);
130 | return winners[0].should.equal(hand);
131 | });
132 | it('Straight should qualify', function() {
133 | var hand = Hand.solve(['7s', '8d', 'Ts', '9s'], gameForTest, true);
134 | var winners = Hand.winners([hand]);
135 | winners.length.should.equal(1);
136 | return winners[0].should.equal(hand);
137 | });
138 | it('Three of a Kind should qualify', function() {
139 | var hand = Hand.solve(['7h', '7d', '2s', '7c'], gameForTest, true);
140 | var winners = Hand.winners([hand]);
141 | winners.length.should.equal(1);
142 | return winners[0].should.equal(hand);
143 | });
144 | it('Two Pair should qualify', function() {
145 | var hand = Hand.solve(['9c', '9d', 'Jc', 'Js'], gameForTest, true);
146 | var winners = Hand.winners([hand]);
147 | winners.length.should.equal(1);
148 | return winners[0].should.equal(hand);
149 | });
150 | it('Pair of Aces should qualify', function() {
151 | var hand = Hand.solve(['Ah', 'As', '3s', '2h'], gameForTest, true);
152 | var winners = Hand.winners([hand]);
153 | winners.length.should.equal(1);
154 | return winners[0].should.equal(hand);
155 | });
156 | it('Lower Pair should qualify', function() {
157 | var hand = Hand.solve(['Jh', 'Js', '3s', '2h'], gameForTest, true);
158 | var winners = Hand.winners([hand]);
159 | winners.length.should.equal(1);
160 | return winners[0].should.equal(hand);
161 | });
162 | it('High Card should qualify', function() {
163 | var hand = Hand.solve(['Qh', '9s', 'Ad', 'Jh'], gameForTest, true);
164 | var winners = Hand.winners([hand]);
165 | winners.length.should.equal(1);
166 | return winners[0].should.equal(hand);
167 | });
168 | });
169 |
170 | describe('Determining winning hands', function() {
171 | it('should detect the winning hand from a list', function() {
172 | var h1 = Hand.solve(['2s', '3c', '3s', '3h'], gameForTest, false);
173 | var h2 = Hand.solve(['3h', '2d', '2c', '2s'], gameForTest, true);
174 | var winners = Hand.winners([h1, h2]);
175 | winners.length.should.equal(1);
176 | return winners[0].should.equal(h1);
177 | });
178 | it('should detect the winning hand from a list - 3oaK higher than straight', function() {
179 | var h1 = Hand.solve(['3h', '2d', 'Ac', '4s'], gameForTest, true);
180 | var h2 = Hand.solve(['2s', '3c', '3s', '3h'], gameForTest, false);
181 | var winners = Hand.winners([h1, h2]);
182 | winners.length.should.equal(1);
183 | return winners[0].should.equal(h2);
184 | });
185 | it('should detect the winning hand - 4oaK higher than "royal flush"', function() {
186 | var h1 = Hand.solve(['3h', '3c', '3s', '3d'], gameForTest, true);
187 | var h2 = Hand.solve(['As', 'Ks', 'Qs', 'Js'], gameForTest, false);
188 | var winners = Hand.winners([h1, h2]);
189 | winners.length.should.equal(1);
190 | return winners[0].should.equal(h1);
191 | });
192 | it('should detect a tie', function() {
193 | var h1 = Hand.solve(['2s', '3s', '4h', 'Ad'], gameForTest, true);
194 | var h2 = Hand.solve(['2h', '3h', '4d', 'Ac'], gameForTest, false);
195 | var winners = Hand.winners([h1, h2]);
196 | winners.length.should.equal(2);
197 | (winners.indexOf(h1) >= 0).should.equal(true);
198 | return (winners.indexOf(h2) >= 0).should.equal(true);
199 | });
200 | });
201 |
--------------------------------------------------------------------------------
/test/fourcardbonus.js:
--------------------------------------------------------------------------------
1 | var should = require('should');
2 | var Hand = require('../pokersolver').Hand;
3 | var Flush = require('../pokersolver').Flush;
4 | var StraightFlush = require('../pokersolver').StraightFlush;
5 | var Straight = require('../pokersolver').Straight;
6 | var FourOfAKind = require('../pokersolver').FourOfAKind;
7 | var ThreeOfAKind = require('../pokersolver').ThreeOfAKind;
8 | var TwoPair = require('../pokersolver').TwoPair;
9 | var OnePair = require('../pokersolver').OnePair;
10 | var Game = require('../pokersolver').Game;
11 |
12 | var gameForTest = new Game('fourcardbonus');
13 |
14 | // Four Card Poker is only three cards, and a different ranking.
15 | // This is ONLY for the purposes of the bonus bet.
16 | describe('A basic hand', function() {
17 | it('should return a hand with cards sorted descending', function() {
18 | var hand = Hand.solve(['Kh', 'Tc', 'As', '3s', '2h'], gameForTest);
19 | hand.cardPool[0].toString().should.equal('As');
20 | return hand.cardPool[4].toString().should.equal('2h');
21 | });
22 | return it('should return a correct description', function() {
23 | var hand = Hand.solve(['Kh', 'As', 'Ad', '3s', '2h'], gameForTest);
24 | return hand.descr.should.equal('Pair, A\'s');
25 | });
26 | });
27 |
28 | describe('A Four of a Kind', function() {
29 | it('should be detected as possible', function() {
30 | var hand = new FourOfAKind(['7h', '7d', '7s', '7c'], gameForTest);
31 | return hand.isPossible.should.equal(true);
32 | });
33 | return it('should be detected as not possible', function() {
34 | var hand = new FourOfAKind(['7h', '3d', '7s', '7c'], gameForTest);
35 | return hand.isPossible.should.equal(false);
36 | });
37 | });
38 |
39 | describe('A Straight Flush', function() {
40 | it('should be detected as possible', function() {
41 | var hand = new StraightFlush(['8s', 'Js', 'Ts', '9s'], gameForTest);
42 | return hand.isPossible.should.equal(true);
43 | });
44 | return it('should be detected as not possible', function() {
45 | var hand = new StraightFlush(['8s', 'Js', 'Ts', '9d'], gameForTest);
46 | return hand.isPossible.should.equal(false);
47 | });
48 | });
49 |
50 | describe('Three of a Kind', function() {
51 | it('should be detected as possible', function() {
52 | var hand = new ThreeOfAKind(['5c', '5s', '5h', '6c'], gameForTest);
53 | hand.isPossible.should.equal(true);
54 | });
55 | return it('should be detected as not possible', function() {
56 | var hand = new ThreeOfAKind(['5c', '2h', '5h', '2d'], gameForTest);
57 | return hand.isPossible.should.equal(false);
58 | });
59 | });
60 |
61 | describe('A Flush', function() {
62 | it('should be detected as possible', function() {
63 | var hand = new Flush(['4h', '5h', '2h', 'Kh'], gameForTest);
64 | return hand.isPossible.should.equal(true);
65 | });
66 | return it('should be detected as not possible', function() {
67 | var hand = new Flush(['Th', '2h', 'Kh', '8d'], gameForTest);
68 | return hand.isPossible.should.equal(false);
69 | });
70 | });
71 |
72 | describe('A Straight', function() {
73 | it('should be detected as possible', function() {
74 | var hand = new Straight(['3s', '2s', '4s', '5c'], gameForTest);
75 | return hand.isPossible.should.equal(true);
76 | });
77 | it('should be detected as not possible', function() {
78 | var hand = new Straight(['6s', '6h', '7c', '8d'], gameForTest);
79 | return hand.isPossible.should.equal(false);
80 | });
81 | it('should detect a low ace', function() {
82 | var hand = new Straight(['2c', '3s', '4h', 'As'], gameForTest);
83 | return hand.isPossible.should.equal(true);
84 | });
85 | return it('should detect a high ace', function() {
86 | var hand = new Straight(['2d', '3s', 'As', 'Kd'], gameForTest);
87 | return hand.isPossible.should.equal(false);
88 | });
89 | });
90 |
91 | describe('Two Pair', function() {
92 | it('should be detected as possible', function() {
93 | var hand = new TwoPair(['5c', '5c', '6s', '6c'], gameForTest);
94 | return hand.isPossible.should.equal(true);
95 | });
96 | return it('should be detected as not possible', function() {
97 | var hand = new TwoPair(['5c', '6s', '6h', '8d'], gameForTest);
98 | return hand.isPossible.should.equal(false);
99 | });
100 | });
101 |
102 | describe('One Pair', function() {
103 | it('should be detected as possible', function() {
104 | var hand = new OnePair(['5h', '5c', '9s', '2d'], gameForTest);
105 | return hand.isPossible.should.equal(true);
106 | });
107 | return it('should be detected as not possible', function() {
108 | var hand = new OnePair(['5h', '6s', 'Ts', '8d'], gameForTest);
109 | return hand.isPossible.should.equal(false);
110 | });
111 | });
112 |
113 | describe('Qualifying Hands', function() {
114 | it('Straight Flush should qualify', function() {
115 | var hand = Hand.solve(['8s', 'Js', 'Ts', '9s'], gameForTest, true);
116 | var winners = Hand.winners([hand]);
117 | winners.length.should.equal(1);
118 | return winners[0].should.equal(hand);
119 | });
120 | it('Four of a Kind should qualify', function() {
121 | var hand = Hand.solve(['7h', '7d', '7s', '7c'], gameForTest, true);
122 | var winners = Hand.winners([hand]);
123 | winners.length.should.equal(1);
124 | return winners[0].should.equal(hand);
125 | });
126 | it('Flush should qualify', function() {
127 | var hand = Hand.solve(['7s', '8s', 'Ts', 'Qs'], gameForTest, true);
128 | var winners = Hand.winners([hand]);
129 | winners.length.should.equal(1);
130 | return winners[0].should.equal(hand);
131 | });
132 | it('Straight should qualify', function() {
133 | var hand = Hand.solve(['7s', '8d', 'Ts', '9s'], gameForTest, true);
134 | var winners = Hand.winners([hand]);
135 | winners.length.should.equal(1);
136 | return winners[0].should.equal(hand);
137 | });
138 | it('Three of a Kind should qualify', function() {
139 | var hand = Hand.solve(['7h', '7d', '2s', '7c'], gameForTest, true);
140 | var winners = Hand.winners([hand]);
141 | winners.length.should.equal(1);
142 | return winners[0].should.equal(hand);
143 | });
144 | it('Two Pair should qualify', function() {
145 | var hand = Hand.solve(['9c', '9d', 'Jc', 'Js'], gameForTest, true);
146 | var winners = Hand.winners([hand]);
147 | winners.length.should.equal(1);
148 | return winners[0].should.equal(hand);
149 | });
150 | it('Pair of Aces should qualify', function() {
151 | var hand = Hand.solve(['Ah', 'As', '3s', '2h'], gameForTest, true);
152 | var winners = Hand.winners([hand]);
153 | winners.length.should.equal(1);
154 | return winners[0].should.equal(hand);
155 | });
156 | it('Lower Pair should not qualify', function() {
157 | var hand = Hand.solve(['Jh', 'Js', '3s', '2h'], gameForTest, true);
158 | var winners = Hand.winners([hand]);
159 | return winners.length.should.equal(0);
160 | });
161 | it('High Card should not qualify', function() {
162 | var hand = Hand.solve(['Qh', '9s', 'Ad', 'Jh'], gameForTest, true);
163 | var winners = Hand.winners([hand]);
164 | return winners.length.should.equal(0);
165 | });
166 | });
167 |
--------------------------------------------------------------------------------
/test/jacksbetter.js:
--------------------------------------------------------------------------------
1 | var should = require('should');
2 | var Hand = require('../pokersolver').Hand;
3 | var Flush = require('../pokersolver').Flush;
4 | var StraightFlush = require('../pokersolver').StraightFlush;
5 | var Straight = require('../pokersolver').Straight;
6 | var FourOfAKind = require('../pokersolver').FourOfAKind;
7 | var FullHouse = require('../pokersolver').FullHouse;
8 | var ThreeOfAKind = require('../pokersolver').ThreeOfAKind;
9 | var TwoPair = require('../pokersolver').TwoPair;
10 | var OnePair = require('../pokersolver').OnePair;
11 | var Game = require('../pokersolver').Game;
12 |
13 | var gameForTest = new Game('jacksbetter');
14 |
15 | // Joker Poker is designed to be for five cards, but can be for any number.
16 | describe('A basic hand', function() {
17 | it('should return a hand with cards sorted descending', function() {
18 | var hand = Hand.solve(['Kh', 'Tc', 'As', '3s', '2h'], gameForTest);
19 | hand.cardPool[0].toString().should.equal('As');
20 | return hand.cardPool[4].toString().should.equal('2h');
21 | });
22 | return it('should return a correct description', function() {
23 | var hand = Hand.solve(['Kh', 'As', 'Ad', '3s', '2h'], gameForTest);
24 | return hand.descr.should.equal('Pair, A\'s');
25 | });
26 | });
27 |
28 | describe('A Straight Flush', function() {
29 | it('should be detected as possible', function() {
30 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9s'], gameForTest);
31 | return hand.isPossible.should.equal(true);
32 | });
33 | return it('should be detected as not possible', function() {
34 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9d'], gameForTest);
35 | return hand.isPossible.should.equal(false);
36 | });
37 | });
38 |
39 | describe('A Four of a Kind', function() {
40 | it('should be detected as possible', function() {
41 | var hand = new FourOfAKind(['7h', '7d', '3s', '7s', '7c'], gameForTest);
42 | return hand.isPossible.should.equal(true);
43 | });
44 | return it('should be detected as not possible', function() {
45 | var hand = new FourOfAKind(['7h', '3d', '3s', '7s', '7c'], gameForTest);
46 | return hand.isPossible.should.equal(false);
47 | });
48 | });
49 |
50 | describe('A Full House', function() {
51 | it('should be detected as possible', function() {
52 | var hand = new FullHouse(['Qd', 'Js', 'Qc', 'Jc', 'Jd'], gameForTest);
53 | return hand.isPossible.should.equal(true);
54 | });
55 | it('should be detected as not possible, with/without joker', function() {
56 | var hand = new FullHouse(['Kd', '6h', '7s', '7d', 'Kh'], gameForTest);
57 | return hand.isPossible.should.equal(false);
58 | });
59 | return it('should be in order', function() {
60 | var hand = new FullHouse(['9c', 'Qs', '9h', 'Qc', 'Qh'], gameForTest);
61 | return hand.cards.toString().should.equal('Qs,Qc,Qh,9c,9h');
62 | });
63 | });
64 |
65 | describe('A Flush', function() {
66 | it('should be detected as possible', function() {
67 | var hand = new Flush(['4h', 'Th', '5h', '2h', 'Kh'], gameForTest);
68 | return hand.isPossible.should.equal(true);
69 | });
70 | return it('should be detected as not possible', function() {
71 | var hand = new Flush(['Th', '5h', '2h', 'Kh', '8d'], gameForTest);
72 | return hand.isPossible.should.equal(false);
73 | });
74 | });
75 |
76 | describe('A Straight', function() {
77 | it('should be detected as possible', function() {
78 | var hand = new Straight(['6s', '3s', '2s', '4s', '5c'], gameForTest);
79 | return hand.isPossible.should.equal(true);
80 | });
81 | it('should be detected as not possible', function() {
82 | var hand = new Straight(['5h', '6s', '6h', '7c', '8d'], gameForTest);
83 | return hand.isPossible.should.equal(false);
84 | });
85 | it('should detect a low ace', function() {
86 | var hand = new Straight(['2c', '3s', '4h', '5c', 'As'], gameForTest);
87 | return hand.isPossible.should.equal(true);
88 | });
89 | return it('should detect a high ace', function() {
90 | var hand = new Straight(['2d', '3s', '4h', 'As', 'Kd'], gameForTest);
91 | return hand.isPossible.should.equal(false);
92 | });
93 | });
94 |
95 | describe('Three of a Kind', function() {
96 | it('should be detected as possible', function() {
97 | var hand = new ThreeOfAKind(['5c', '5s', '5h', '6c', '2d'], gameForTest);
98 | hand.isPossible.should.equal(true);
99 | });
100 | return it('should be detected as not possible', function() {
101 | var hand = new ThreeOfAKind(['5c', '2h', '5h', '6c', '2d'], gameForTest);
102 | return hand.isPossible.should.equal(false);
103 | });
104 | });
105 |
106 | describe('Two Pair', function() {
107 | it('should be detected as possible', function() {
108 | var hand = new TwoPair(['5c', '5c', '6s', '6c', '2d'], gameForTest);
109 | return hand.isPossible.should.equal(true);
110 | });
111 | return it('should be detected as not possible', function() {
112 | var hand = new TwoPair(['5c', '6s', '6h', '7c', '8d'], gameForTest);
113 | return hand.isPossible.should.equal(false);
114 | });
115 | });
116 |
117 | describe('One Pair', function() {
118 | it('should be detected as possible', function() {
119 | var hand = new OnePair(['5h', '5c', '7s', '9s', '2d'], gameForTest);
120 | return hand.isPossible.should.equal(true);
121 | });
122 | return it('should be detected as not possible', function() {
123 | var hand = new OnePair(['5h', '6s', '2s', 'Ts', '8d'], gameForTest);
124 | return hand.isPossible.should.equal(false);
125 | });
126 | });
127 |
128 | describe('Qualifying Hands', function() {
129 | it('Royal Flush should qualify', function() {
130 | var hand = Hand.solve(['As', 'Or', 'Js', 'Ts', 'Qs'], gameForTest, true);
131 | var winners = Hand.winners([hand]);
132 | winners.length.should.equal(1);
133 | return winners[0].should.equal(hand);
134 | });
135 | it('Straight Flush should qualify', function() {
136 | var hand = Hand.solve(['7s', '8s', 'Js', 'Ts', '9s'], gameForTest, true);
137 | var winners = Hand.winners([hand]);
138 | winners.length.should.equal(1);
139 | return winners[0].should.equal(hand);
140 | });
141 | it('Four of a Kind should qualify', function() {
142 | var hand = Hand.solve(['7h', '7d', '3s', '7s', '7c'], gameForTest, true);
143 | var winners = Hand.winners([hand]);
144 | winners.length.should.equal(1);
145 | return winners[0].should.equal(hand);
146 | });
147 | it('Full House should qualify', function() {
148 | var hand = Hand.solve(['9c', '9d', 'Jh', 'Jc', 'Js'], gameForTest, true);
149 | var winners = Hand.winners([hand]);
150 | winners.length.should.equal(1);
151 | return winners[0].should.equal(hand);
152 | });
153 | it('Flush should qualify', function() {
154 | var hand = Hand.solve(['7s', '8s', 'Js', 'Ts', 'Qs'], gameForTest, true);
155 | var winners = Hand.winners([hand]);
156 | winners.length.should.equal(1);
157 | return winners[0].should.equal(hand);
158 | });
159 | it('Straight should qualify', function() {
160 | var hand = Hand.solve(['7s', '8d', 'Js', 'Ts', '9s'], gameForTest, true);
161 | var winners = Hand.winners([hand]);
162 | winners.length.should.equal(1);
163 | return winners[0].should.equal(hand);
164 | });
165 | it('Three of a Kind should qualify', function() {
166 | var hand = Hand.solve(['7h', '7d', '3s', '2s', '7c'], gameForTest, true);
167 | var winners = Hand.winners([hand]);
168 | winners.length.should.equal(1);
169 | return winners[0].should.equal(hand);
170 | });
171 | it('Two Pair should qualify', function() {
172 | var hand = Hand.solve(['9c', '9d', 'Ah', 'Jc', 'Js'], gameForTest, true);
173 | var winners = Hand.winners([hand]);
174 | winners.length.should.equal(1);
175 | return winners[0].should.equal(hand);
176 | });
177 | it('Pair of Aces should qualify', function() {
178 | var hand = Hand.solve(['Ah', 'As', '6d', '3s', '2h'], gameForTest, true);
179 | var winners = Hand.winners([hand]);
180 | winners.length.should.equal(1);
181 | return winners[0].should.equal(hand);
182 | });
183 | it('Lowest Possible Pair of Jacks should qualify', function() {
184 | var hand = Hand.solve(['Jh', 'Js', '4d', '3s', '2h'], gameForTest, true);
185 | var winners = Hand.winners([hand]);
186 | winners.length.should.equal(1);
187 | return winners[0].should.equal(hand);
188 | });
189 | it('Highest Possible Pair of Tens should not qualify', function() {
190 | var hand = Hand.solve(['Th', 'Ts', 'Ad', 'Ks', 'Jh'], gameForTest, true);
191 | var winners = Hand.winners([hand]);
192 | return winners.length.should.equal(0);
193 | });
194 | it('High Card should not qualify', function() {
195 | var hand = Hand.solve(['Qh', '9s', 'Ad', 'Ks', 'Jh'], gameForTest, true);
196 | var winners = Hand.winners([hand]);
197 | return winners.length.should.equal(0);
198 | });
199 | });
200 |
--------------------------------------------------------------------------------
/test/joker.js:
--------------------------------------------------------------------------------
1 | var should = require('should');
2 | var Hand = require('../pokersolver').Hand;
3 | var NaturalRoyalFlush = require('../pokersolver').NaturalRoyalFlush;
4 | var FiveOfAKind = require('../pokersolver').FiveOfAKind;
5 | var WildRoyalFlush = require('../pokersolver').WildRoyalFlush;
6 | var StraightFlush = require('../pokersolver').StraightFlush;
7 | var FourOfAKind = require('../pokersolver').FourOfAKind;
8 | var FullHouse = require('../pokersolver').FullHouse;
9 | var Flush = require('../pokersolver').Flush;
10 | var Straight = require('../pokersolver').Straight;
11 | var ThreeOfAKind = require('../pokersolver').ThreeOfAKind;
12 | var TwoPair = require('../pokersolver').TwoPair;
13 | var Game = require('../pokersolver').Game;
14 |
15 | var gameForTest = new Game('joker');
16 |
17 | // Joker Poker is designed to be for five cards, but can be for any number.
18 | // Qualification is not used, as straight hand rank determines pay.
19 | describe('A basic hand', function() {
20 | it('should return a hand with cards sorted descending', function() {
21 | var hand = Hand.solve(['Kh', 'Tc', 'As', '3s', '2h'], gameForTest);
22 | hand.cardPool[0].toString().should.equal('As');
23 | return hand.cardPool[4].toString().should.equal('2h');
24 | });
25 | it('should return a hand with cards sorted descending, jokers last, but set to value', function() {
26 | var hand = Hand.solve(['Kh', 'Or', 'As', '7c', '2h'], gameForTest);
27 | hand.cardPool[0].toString().should.equal('As');
28 | return hand.cardPool[4].toString().should.equal('Ar');
29 | });
30 | return it('should return a correct description with a joker', function() {
31 | var hand = Hand.solve(['Kh', 'As', '3c', '3s', 'Or'], gameForTest);
32 | return hand.descr.should.equal('Three of a Kind, 3\'s');
33 | });
34 | });
35 |
36 | describe('A Natural Royal Flush', function() {
37 | it('should be detected as possible', function() {
38 | var hand = new NaturalRoyalFlush(['As', 'Qs', 'Js', 'Ts', 'Ks'], gameForTest);
39 | return hand.isPossible.should.equal(true);
40 | });
41 | it('should be detected as not possible', function() {
42 | var hand = new NaturalRoyalFlush(['7s', '8s', 'Js', 'Ts', '9s'], gameForTest);
43 | return hand.isPossible.should.equal(false);
44 | });
45 | return it('should be detected as not possible with a joker', function() {
46 | var hand = new NaturalRoyalFlush(['Or', 'Ks', 'Js', 'Ts', 'Qs'], gameForTest);
47 | return hand.isPossible.should.equal(false);
48 | });
49 | });
50 |
51 | describe('A Wild Royal Flush', function() {
52 | it('should be detected as possible', function() {
53 | var hand = new WildRoyalFlush(['As', 'Or', 'Js', 'Ts', 'Ks'], gameForTest);
54 | return hand.isPossible.should.equal(true);
55 | });
56 | it('should be detected as not possible', function() {
57 | var hand = new WildRoyalFlush(['7s', 'Or', 'Js', 'Ts', '9s'], gameForTest);
58 | return hand.isPossible.should.equal(false);
59 | });
60 | it('should be detected as possible with a joker - outside', function() {
61 | var hand = new WildRoyalFlush(['Ks', 'Qs', 'Js', 'Ts', 'Or'], gameForTest);
62 | hand.isPossible.should.equal(true);
63 | });
64 | it('should be detected as possible with two jokers - inside/outside', function() {
65 | var hand = new WildRoyalFlush(['Or', 'Qs', 'Ts', 'Ks', 'Or'], gameForTest);
66 | hand.isPossible.should.equal(true);
67 | });
68 | return it('should be detected as possible with jokers - can set as low', function() {
69 | var hand = new WildRoyalFlush(['Qs', 'Or', 'As', 'Js', 'Ks'], gameForTest);
70 | hand.isPossible.should.equal(true);
71 | });
72 | });
73 |
74 | describe('A Straight Flush', function() {
75 | it('should be detected as possible', function() {
76 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9s'], gameForTest);
77 | return hand.isPossible.should.equal(true);
78 | });
79 | it('should be detected as not possible', function() {
80 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9d'], gameForTest);
81 | return hand.isPossible.should.equal(false);
82 | });
83 | it('should be detected as possible with a joker - inside', function() {
84 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', 'Or'], gameForTest);
85 | return hand.isPossible.should.equal(true);
86 | });
87 | it('should be detected as possible with a joker - outside', function() {
88 | var hand = new StraightFlush(['7s', '8s', '9s', 'Ts', 'Or'], gameForTest);
89 | hand.isPossible.should.equal(true);
90 | return hand.descr.should.equal('Straight Flush, Js High');
91 | });
92 | it('should be detected as possible with two jokers - inside/outside', function() {
93 | var hand = new StraightFlush(['Or', '8s', 'Js', 'Ts', 'Or'], gameForTest);
94 | hand.isPossible.should.equal(true);
95 | return hand.descr.should.equal('Straight Flush, Qs High');
96 | });
97 | it('should be detected as possible with jokers - highest possible', function() {
98 | var hand = new StraightFlush(['9s', 'Or', '7s', 'Js', 'Kh', 'Ts', 'Or'], gameForTest);
99 | hand.isPossible.should.equal(true);
100 | return hand.descr.should.equal('Straight Flush, Ks High');
101 | });
102 | it('should be detected as possible with jokers - can set as low', function() {
103 | var hand = new StraightFlush(['Qs', 'Or', 'As', 'Js', 'Kh', 'Ts', 'Or'], gameForTest);
104 | hand.isPossible.should.equal(true);
105 | return hand.descr.should.equal('Royal Flush');
106 | });
107 | return it('should be detected as not possible, even with a joker', function() {
108 | var hand = new StraightFlush(['Or', '8s', 'Js', 'Ts', '9d'], gameForTest);
109 | return hand.isPossible.should.equal(false);
110 | });
111 | });
112 |
113 | describe('A Five of a Kind', function() {
114 | it('should be detected as possible with joker', function() {
115 | var hand = new FiveOfAKind(['7h', '7d', 'Or', '7s', '7c'], gameForTest);
116 | return hand.isPossible.should.equal(true);
117 | });
118 | return it('should be detected as not possible', function() {
119 | var hand = new FiveOfAKind(['7h', '7d', '3s', '7s', '7c'], gameForTest);
120 | return hand.isPossible.should.equal(false);
121 | });
122 | return it('should be detected as not possible, even with a joker', function() {
123 | var hand = new FiveOfAKind(['7h', 'Or', '3s', '7s', '7c'], gameForTest);
124 | return hand.isPossible.should.equal(false);
125 | });
126 | });
127 |
128 | describe('A Four of a Kind', function() {
129 | it('should be detected as possible', function() {
130 | var hand = new FourOfAKind(['7h', '7d', '3s', '7s', '7c'], gameForTest);
131 | return hand.isPossible.should.equal(true);
132 | });
133 | it('should be detected as possible with a joker', function() {
134 | var hand = new FourOfAKind(['7h', '3d', 'Or', '7s', '7c'], gameForTest);
135 | return hand.isPossible.should.equal(true);
136 | });
137 | it('should be detected as not possible', function() {
138 | var hand = new FourOfAKind(['7h', '3d', '3s', '7s', '7c'], gameForTest);
139 | return hand.isPossible.should.equal(false);
140 | });
141 | return it('should be detected as not possible, even with a joker', function() {
142 | var hand = new FourOfAKind(['7h', '3d', '3s', 'Or', '7c'], gameForTest);
143 | return hand.isPossible.should.equal(false);
144 | });
145 | });
146 |
147 | describe('A Full House', function() {
148 | it('should be detected as possible, with/without joker', function() {
149 | var hand = new FullHouse(['Qd', 'Js', 'Qc', 'Jc', 'Jd'], gameForTest);
150 | hand.isPossible.should.equal(true);
151 | hand = new FullHouse(['9c', '9d', 'Jh', 'Jc', 'Js', '9h', 'As'], gameForTest);
152 | hand.isPossible.should.equal(true);
153 | hand = new FullHouse(['9c', '9d', 'Or', 'Jc', 'Js'], gameForTest);
154 | hand.isPossible.should.equal(true);
155 | hand = new FullHouse(['9c', '9d', 'Jh', 'Or', 'Js', '9h', 'As'], gameForTest);
156 | hand.isPossible.should.equal(true);
157 | hand = new FullHouse(['9h', '9s', 'Or', '5c', 'Kd', '5d', 'Kh'], gameForTest);
158 | return hand.isPossible.should.equal(true);
159 | });
160 | it('should be detected as not possible, with/without joker', function() {
161 | var hand = new FullHouse(['5h', '3h', '3c', '5d', '2s', 'Ts', 'Td'], gameForTest);
162 | hand.isPossible.should.equal(false);
163 | hand = new FullHouse(['Kd', '6h', '7s', '7d', 'Kh'], gameForTest);
164 | hand.isPossible.should.equal(false);
165 | hand = new FullHouse(['9h', '9s', 'Or', '5d', 'Kh'], gameForTest);
166 | return hand.isPossible.should.equal(false);
167 | });
168 | it('should pick the high kickers', function() {
169 | var hand = new FullHouse(['5d', '5h', '3h', '3c', 'Qh', 'Qd', 'Qs'], gameForTest);
170 | hand.cards.toString().indexOf('3h').should.equal(-1);
171 | hand = new FullHouse(['5d', '5h', '3h', '3c', 'Or', 'Qd', 'Qs'], gameForTest);
172 | return hand.cards.toString().indexOf('3h').should.equal(-1);
173 | });
174 | it('should be in order', function() {
175 | var hand = new FullHouse(['9c', 'Qs', '9h', '5h', 'Ts', 'Qc', 'Qh'], gameForTest);
176 | hand.cards.toString().should.equal('Qs,Qc,Qh,9c,9h');
177 | hand = new FullHouse(['9c', 'Qs', '9h', '5h', 'Ts', 'Or', 'Qh'], gameForTest);
178 | return hand.cards.toString().should.equal('Qs,Qh,Qr,9c,9h');
179 | });
180 | });
181 |
182 | describe('A Flush', function() {
183 | it('should be detected as possible', function() {
184 | var hand = new Flush(['4h', 'Th', '5h', '2h', 'Kh'], gameForTest);
185 | return hand.isPossible.should.equal(true);
186 | });
187 | it('should be detected as not possible', function() {
188 | var hand = new Flush(['Th', '5h', '2h', 'Kh', '8d'], gameForTest);
189 | return hand.isPossible.should.equal(false);
190 | });
191 | it('should be detected as possible with a joker, highest rank', function() {
192 | var hand = new Flush(['4h', 'Th', '5h', 'Or', 'Kh'], gameForTest);
193 | return hand.isPossible.should.equal(true);
194 | });
195 | it('should be detected as possible with a joker, next highest rank', function() {
196 | var hand = new Flush(['4h', 'Th', 'Ah', 'Or', 'Kh'], gameForTest);
197 | return hand.isPossible.should.equal(true);
198 | });
199 | return it('should be detected as not possible, even with joker', function() {
200 | var hand = new Flush(['4s', 'Th', 'Or', 'Ac', '2h', 'Kh', '8d'], gameForTest);
201 | return hand.isPossible.should.equal(false);
202 | });
203 | });
204 |
205 | describe('A Straight', function() {
206 | it('should be detected as possible', function() {
207 | var hand = new Straight(['6s', '3s', '2s', '4s', '5c'], gameForTest);
208 | return hand.isPossible.should.equal(true);
209 | });
210 | it('should be detected as possible', function() {
211 | var hand = new Straight(['5d', '6s', '7s', '8c', 'Ts', '9s', '2d'], gameForTest);
212 | return hand.isPossible.should.equal(true);
213 | });
214 | it('should be detected as not possible', function() {
215 | var hand = new Straight(['5h', '6s', '6h', '7c', '8d'], gameForTest);
216 | return hand.isPossible.should.equal(false);
217 | });
218 | it('should detect a low ace', function() {
219 | var hand = new Straight(['2c', '3s', '4h', '5c', 'As'], gameForTest);
220 | return hand.isPossible.should.equal(true);
221 | });
222 | it('should detect a high ace', function() {
223 | var hand = new Straight(['2d', '3s', '4h', '7c', 'As', 'Ts', 'Kd'], gameForTest);
224 | return hand.isPossible.should.equal(false);
225 | });
226 | it('should be detected as possible with a joker - inside', function() {
227 | var hand = new Straight(['7s', '8s', 'Jc', 'Ts', 'Or'], gameForTest);
228 | return hand.isPossible.should.equal(true);
229 | });
230 | it('should be detected as possible with a joker - outside', function() {
231 | var hand = new Straight(['7d', '8s', '9s', 'Ts', 'Or'], gameForTest);
232 | hand.isPossible.should.equal(true);
233 | return hand.descr.should.equal('Straight, J High');
234 | });
235 | it('should be detected as possible with two jokers - inside/outside', function() {
236 | var hand = new Straight(['Or', '8s', 'Jh', 'Ts', 'Or'], gameForTest);
237 | hand.isPossible.should.equal(true);
238 | return hand.descr.should.equal('Straight, Q High');
239 | });
240 | it('should be detected as possible with jokers - highest possible', function() {
241 | var hand = new Straight(['Qs', 'Or', '8c', 'Jh', 'Kh', 'Ts', 'Or'], gameForTest);
242 | hand.isPossible.should.equal(true);
243 | return hand.descr.should.equal('Straight, A High');
244 | });
245 | it('should be detected as possible with jokers - can set as low', function() {
246 | var hand = new Straight(['Qs', 'Or', 'As', 'Js', 'Kh', 'Ts', 'Or'], gameForTest);
247 | hand.isPossible.should.equal(true);
248 | return hand.descr.should.equal('Straight, A High');
249 | });
250 | return it('should be detected as not possible, even with a joker', function() {
251 | var hand = new Straight(['Or', '8s', 'Js', 'Ts', '8d'], gameForTest);
252 | return hand.isPossible.should.equal(false);
253 | });
254 | });
255 |
256 | describe('Three of a Kind', function() {
257 | it('should be detected as possible', function() {
258 | var hand = new ThreeOfAKind(['5c', '5s', '5h', '6c', '2d'], gameForTest);
259 | hand.isPossible.should.equal(true);
260 | });
261 | it('should be detected as not possible', function() {
262 | var hand = new ThreeOfAKind(['5c', '2h', '5h', '6c', '2d'], gameForTest);
263 | return hand.isPossible.should.equal(false);
264 | });
265 | it('should be detected as possible with joker', function() {
266 | var hand = new ThreeOfAKind(['5c', '5s', 'Or', '6c', '2d'], gameForTest);
267 | hand.isPossible.should.equal(true);
268 | });
269 | return it('should be detected as not possible', function() {
270 | var hand = new ThreeOfAKind(['5c', '7h', 'Or', '6c', '2d'], gameForTest);
271 | return hand.isPossible.should.equal(false);
272 | });
273 | });
274 |
275 | describe('Two Pair', function() {
276 | it('should be detected as possible', function() {
277 | var hand = new TwoPair(['5c', '5c', '6s', '6c', 'Td', '9s', '2d'], gameForTest);
278 | return hand.isPossible.should.equal(true);
279 | });
280 | return it('should be detected as not possible', function() {
281 | var hand = new TwoPair(['5c', '6s', '6h', '7c', '2d', 'Ts', '8d'], gameForTest);
282 | return hand.isPossible.should.equal(false);
283 | });
284 | });
285 |
286 | describe('Qualifying Hands', function() {
287 | it('Royal Flush should qualify', function() {
288 | var hand = Hand.solve(['As', 'Or', 'Js', 'Ts', 'Qs'], gameForTest, true);
289 | var winners = Hand.winners([hand]);
290 | winners.length.should.equal(1);
291 | return winners[0].should.equal(hand);
292 | });
293 | it('Five of a Kind should qualify', function() {
294 | var hand = Hand.solve(['7h', '7d', 'Or', '7s', '7c'], gameForTest, true);
295 | var winners = Hand.winners([hand]);
296 | winners.length.should.equal(1);
297 | return winners[0].should.equal(hand);
298 | });
299 | it('Straight Flush should qualify', function() {
300 | var hand = Hand.solve(['7s', '8s', 'Js', 'Ts', '9s'], gameForTest, true);
301 | var winners = Hand.winners([hand]);
302 | winners.length.should.equal(1);
303 | return winners[0].should.equal(hand);
304 | });
305 | it('Four of a Kind should qualify', function() {
306 | var hand = Hand.solve(['7h', '7d', '3s', '7s', '7c'], gameForTest, true);
307 | var winners = Hand.winners([hand]);
308 | winners.length.should.equal(1);
309 | return winners[0].should.equal(hand);
310 | });
311 | it('Full House should qualify', function() {
312 | var hand = Hand.solve(['9c', '9d', 'Or', 'Jc', 'Js'], gameForTest, true);
313 | var winners = Hand.winners([hand]);
314 | winners.length.should.equal(1);
315 | return winners[0].should.equal(hand);
316 | });
317 | it('Flush should qualify', function() {
318 | var hand = Hand.solve(['7s', '8s', 'Js', 'Ts', 'Qs'], gameForTest, true);
319 | var winners = Hand.winners([hand]);
320 | winners.length.should.equal(1);
321 | return winners[0].should.equal(hand);
322 | });
323 | it('Straight should qualify', function() {
324 | var hand = Hand.solve(['7s', '8d', 'Js', 'Ts', '9s'], gameForTest, true);
325 | var winners = Hand.winners([hand]);
326 | winners.length.should.equal(1);
327 | return winners[0].should.equal(hand);
328 | });
329 | it('Three of a Kind should qualify', function() {
330 | var hand = Hand.solve(['7h', '7d', '3s', '2s', '7c'], gameForTest, true);
331 | var winners = Hand.winners([hand]);
332 | winners.length.should.equal(1);
333 | return winners[0].should.equal(hand);
334 | });
335 | it('Two Pair should qualify', function() {
336 | var hand = Hand.solve(['4c', '3d', '3h', '2s', '2c'], gameForTest, true);
337 | var winners = Hand.winners([hand]);
338 | winners.length.should.equal(1);
339 | return winners[0].should.equal(hand);
340 | });
341 | it('One Pair should not qualify', function() {
342 | var hand = Hand.solve(['Ah', 'As', '6d', '3s', '2h'], gameForTest, true);
343 | var winners = Hand.winners([hand]);
344 | return winners.length.should.equal(0);
345 | });
346 | it('High Card should not qualify', function() {
347 | var hand = Hand.solve(['Qh', '9s', 'Ad', 'Ks', 'Jh'], gameForTest, true);
348 | var winners = Hand.winners([hand]);
349 | return winners.length.should.equal(0);
350 | });
351 | });
352 |
--------------------------------------------------------------------------------
/test/paigowpokerfullhands.js:
--------------------------------------------------------------------------------
1 | var should = require('should');
2 | var Hand = require('../pokersolver').Hand;
3 | var Flush = require('../pokersolver').Flush;
4 | var StraightFlush = require('../pokersolver').StraightFlush;
5 | var Straight = require('../pokersolver').Straight;
6 | var FiveOfAKind = require('../pokersolver').FiveOfAKind;
7 | var FourOfAKindPairPlus = require('../pokersolver').FourOfAKindPairPlus;
8 | var FourOfAKind = require('../pokersolver').FourOfAKind;
9 | var TwoThreeOfAKind = require('../pokersolver').TwoThreeOfAKind;
10 | var ThreeOfAKindTwoPair = require('../pokersolver').ThreeOfAKindTwoPair;
11 | var FullHouse = require('../pokersolver').FullHouse;
12 | var ThreeOfAKind = require('../pokersolver').ThreeOfAKind;
13 | var ThreePair = require('../pokersolver').ThreePair;
14 | var TwoPair = require('../pokersolver').TwoPair;
15 | var OnePair = require('../pokersolver').OnePair;
16 | var HighCard = require('../pokersolver').HighCard;
17 | var Game = require('../pokersolver').Game;
18 | var PaiGowPokerHelper = require('../pokersolver').PaiGowPokerHelper;
19 |
20 | var gameForTest = new Game('paigowpokerfull');
21 |
22 | // Pai Gow Poker is a game that uses seven cards.
23 | // These cards are divided into a five-card and two-card hand.
24 | // Special Rules: Joker either completes a straight and/or flush, or is an ace.
25 | // The wheel straight (A2345) is the second highest straight.
26 | describe('A basic hand', function() {
27 | it('should return a hand with cards sorted descending', function() {
28 | var hand = Hand.solve(['Kh', '3c', 'Tc', 'As', '3s', '7d', '2h'], gameForTest);
29 | hand.cardPool[0].toString().should.equal('As');
30 | return hand.cardPool[6].toString().should.equal('2h');
31 | });
32 | it('should return a hand with cards sorted descending, jokers last', function() {
33 | var hand = Hand.solve(['Kh', 'Or', 'Qs', 'Td', '5s', '7c', '2h'], gameForTest);
34 | hand.cardPool[0].toString().should.equal('Kh');
35 | return hand.cardPool[6].toString().should.equal('Ar');
36 | });
37 | it('should return a correct description with a joker', function() {
38 | var hand = Hand.solve(['Kh', 'Or', 'Qs', 'Td', '5s', '7c', '2h'], gameForTest);
39 | return hand.descr.should.equal('A High');
40 | });
41 | it('should use the helper class and be split according to House Way', function() {
42 | var hand = PaiGowPokerHelper.solve(['Kh', 'Or', 'Qs', 'Td', '5s', '7c', '2h']);
43 | hand.hiHand.descr.should.equal('A High');
44 | return hand.loHand.descr.should.equal('K High');
45 | });
46 | return it('should use the helper class and be split manually, even if not house way', function() {
47 | var hand = PaiGowPokerHelper.setHands(['Kh', 'Or', 'Qs', 'Td', '5s'], ['7c', '2h']);
48 | hand.hiHand.descr.should.equal('A High');
49 | return hand.loHand.descr.should.equal('7 High');
50 | });
51 | });
52 |
53 | describe('A Five of a Kind', function() {
54 | it('should be detected as possible with joker', function() {
55 | var hand = new FiveOfAKind(['Ah', 'Ad', 'Or', 'As', 'Ac', 'Kh', 'Qd'], gameForTest);
56 | return hand.isPossible.should.equal(true);
57 | });
58 | it('should be detected as not possible with joker', function() {
59 | var hand = new FiveOfAKind(['Ah', 'Kd', 'Or', 'Ks', 'Kc', 'Kh', 'Qd'], gameForTest);
60 | return hand.isPossible.should.equal(false);
61 | });
62 | it('should be split according to House Way', function() {
63 | var hand = PaiGowPokerHelper.solve(['Ah', 'Ad', 'Or', 'As', 'Ac', 'Kh', 'Kd']);
64 | hand.hiHand.descr.should.equal('Five of a Kind, A\'s');
65 | return hand.loHand.descr.should.equal('Pair, K\'s');
66 | });
67 | return it('should be split according to House Way', function() {
68 | var hand = PaiGowPokerHelper.solve(['Ah', 'Ad', 'Or', 'As', 'Ac', 'Kh', 'Qd']);
69 | hand.hiHand.descr.should.equal('Three of a Kind, A\'s');
70 | return hand.loHand.descr.should.equal('Pair, A\'s');
71 | });
72 | });
73 |
74 | describe('A Four of a Kind with Pair or Better', function() {
75 | it('should be detected as possible', function() {
76 | var hand = new FourOfAKindPairPlus(['Ah', 'Kd', 'Or', 'Ks', 'Kc', 'Kh', 'Qd'], gameForTest);
77 | return hand.isPossible.should.equal(true);
78 | });
79 | it('should be detected as not possible', function() {
80 | var hand = new FourOfAKindPairPlus(['Ah', 'Ad', 'Or', 'As', 'Jc', 'Kh', 'Qd'], gameForTest);
81 | return hand.isPossible.should.equal(false);
82 | });
83 | it('should be split according to House Way', function() {
84 | var hand = PaiGowPokerHelper.solve(['Ah', 'Ad', 'Or', 'As', 'Jc', 'Kh', 'Kd']);
85 | hand.hiHand.descr.should.equal('Four of a Kind, A\'s');
86 | return hand.loHand.descr.should.equal('Pair, K\'s');
87 | });
88 | it('should be split according to House Way', function() {
89 | var hand = PaiGowPokerHelper.solve(['Ah', 'Ad', 'Or', 'As', 'Jc', 'Jh', 'Kd']);
90 | hand.hiHand.descr.should.equal('Two Pair, A\'s & J\'s');
91 | return hand.loHand.descr.should.equal('Pair, A\'s');
92 | });
93 | return it('should be split according to House Way', function() {
94 | var hand = PaiGowPokerHelper.solve(['Ah', 'Kd', 'Kh', 'Kc', 'Ac', 'Kh', 'Qd']);
95 | hand.hiHand.descr.should.equal('Four of a Kind, K\'s');
96 | return hand.loHand.descr.should.equal('Pair, A\'s');
97 | });
98 | });
99 |
100 | describe('A Straight Flush with No Pair', function() {
101 | it('should be detected as possible', function() {
102 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9s', 'Qd', '6c'], gameForTest);
103 | return hand.isPossible.should.equal(true);
104 | });
105 | it('should be detected as not possible', function() {
106 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9d', 'Qc', '6h'], gameForTest);
107 | return hand.isPossible.should.equal(false);
108 | });
109 | it('should be split according to House Way, 5 cards', function() {
110 | var hand = PaiGowPokerHelper.solve(['7s', '8s', 'Js', 'Ts', '9s', 'Ad', '3c']);
111 | hand.hiHand.descr.should.equal('Straight Flush, Js High');
112 | return hand.loHand.descr.should.equal('A High');
113 | });
114 | it('should be split according to House Way, 6 cards', function() {
115 | var hand = PaiGowPokerHelper.solve(['7s', '8s', 'Js', 'Ts', '9s', 'Qd', '3c']);
116 | hand.hiHand.descr.should.equal('Straight Flush, Js High');
117 | return hand.loHand.descr.should.equal('Q High');
118 | });
119 | return it('should be split according to House Way, 7 cards', function() {
120 | var hand = PaiGowPokerHelper.solve(['7s', '8s', 'Js', 'Ts', '9s', 'Qd', '6c']);
121 | hand.hiHand.descr.should.equal('Straight, 10 High');
122 | return hand.loHand.descr.should.equal('Q High');
123 | });
124 | });
125 |
126 | describe('A Straight Flush with One Pair', function() {
127 | it('should be detected as possible', function() {
128 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9s', 'Jd', '6c'], gameForTest);
129 | return hand.isPossible.should.equal(true);
130 | });
131 | it('should be detected as not possible', function() {
132 | var hand = new StraightFlush(['7s', '8s', 'Js', 'Ts', '9d', 'Jc', '6h'], gameForTest);
133 | return hand.isPossible.should.equal(false);
134 | });
135 | it('should be split according to House Way, Pair T-K with A, S/F with A in low', function() {
136 | var hand = PaiGowPokerHelper.solve(['7s', '8s', 'Js', 'Ts', '9s', 'Ad', 'Jc']);
137 | hand.hiHand.descr.should.equal('Straight Flush, Js High');
138 | return hand.loHand.descr.should.equal('A High');
139 | });
140 | it('should be split according to House Way, Pair T-K with A, A needed for S/F', function() {
141 | var hand = PaiGowPokerHelper.solve(['7d', 'Ks', 'Js', 'Ts', 'Qs', 'As', 'Jc']);
142 | hand.hiHand.descr.should.equal('Pair, J\'s');
143 | return hand.loHand.descr.should.equal('A High');
144 | });
145 | it('should be split according to House Way, Pair with preservation', function() {
146 | var hand = PaiGowPokerHelper.solve(['7s', '8s', 'Js', 'Ts', '9s', 'Qd', '7c']);
147 | hand.hiHand.descr.should.equal('Straight, Q High');
148 | return hand.loHand.descr.should.equal('Pair, 7\'s');
149 | });
150 | return it('should be split according to House Way, Pair without preservation', function() {
151 | var hand = PaiGowPokerHelper.solve(['7s', '8s', '9s', 'Ts', '6s', 'Qd', '6c']);
152 | hand.hiHand.descr.should.equal('Straight Flush, 10s High');
153 | return hand.loHand.descr.should.equal('Q High');
154 | });
155 | });
156 |
157 | describe('A Straight Flush with Two Pair', function() {
158 | it('should be detected as possible', function() {
159 | var hand = new StraightFlush(['As', '3s', '2s', '5s', '4s', '4d', '2c'], gameForTest);
160 | return hand.isPossible.should.equal(true);
161 | });
162 | it('should be detected as not possible', function() {
163 | var hand = new StraightFlush(['As', '3s', '2d', '5s', '4s', '4d', '2c'], gameForTest);
164 | return hand.isPossible.should.equal(false);
165 | });
166 | it('should be split according to House Way, Two low pair with A', function() {
167 | var hand = PaiGowPokerHelper.solve(['As', '3s', '2s', '5s', '4s', '4d', '2c']);
168 | hand.hiHand.descr.should.equal('Two Pair, 4\'s & 2\'s');
169 | return hand.loHand.descr.should.equal('A High');
170 | });
171 | it('should be split according to House Way, Two low pair without A', function() {
172 | var hand = PaiGowPokerHelper.solve(['6s', '3s', '2s', '5s', '4s', '4d', '2c']);
173 | hand.hiHand.descr.should.equal('Straight Flush, 6s High');
174 | return hand.loHand.descr.should.equal('4 High');
175 | });
176 | return it('should be split according to House Way, At least one higher pair', function() {
177 | var hand = PaiGowPokerHelper.solve(['6s', '3s', '7s', '5s', '4s', '4d', '7c']);
178 | hand.hiHand.descr.should.equal('Pair, 7\'s');
179 | return hand.loHand.descr.should.equal('Pair, 4\'s');
180 | });
181 | });
182 |
183 | describe('A Straight Flush with Three Pair', function() {
184 | it('should be detected as possible', function() {
185 | var hand = new StraightFlush(['As', '3s', '2s', 'Or', '4s', '4d', '2c'], gameForTest);
186 | return hand.isPossible.should.equal(true);
187 | });
188 | it('should be detected as not possible', function() {
189 | var hand = new StraightFlush(['As', '3s', '2s', 'Or', '4h', '4d', '2c'], gameForTest);
190 | return hand.isPossible.should.equal(false);
191 | });
192 | return it('should be split according to House Way, Three Pair', function() {
193 | var hand = PaiGowPokerHelper.solve(['As', '3s', '2s', 'Or', '4s', '4d', '2c']);
194 | hand.hiHand.descr.should.equal('Two Pair, 4\'s & 2\'s');
195 | return hand.loHand.descr.should.equal('Pair, A\'s');
196 | });
197 | });
198 |
199 | describe('A Straight with Three of a Kind', function() {
200 | it('should be detected as possible', function() {
201 | var hand = new Straight(['6s', '3s', '2s', '4s', '5c', '5h', '5d'], gameForTest);
202 | return hand.isPossible.should.equal(true);
203 | });
204 | it('should be detected as not possible', function() {
205 | var hand = new Straight(['5h', '6s', '6h', '7c', '8d', '6c', 'Td'], gameForTest);
206 | return hand.isPossible.should.equal(false);
207 | });
208 | return it('should be split according to House Way, Three of a Kind', function() {
209 | var hand = PaiGowPokerHelper.solve(['As', '3s', '2s', '4s', '5c', '5h', '5d']);
210 | hand.hiHand.descr.should.equal('Straight, Wheel');
211 | return hand.loHand.descr.should.equal('Pair, 5\'s');
212 | });
213 | });
214 |
215 | describe('A Flush with Full House', function() {
216 | it('should be detected as possible', function() {
217 | var hand = new Flush(['Ah', 'Jh', 'Js', 'Jc', 'Or', '2h', 'Kh'], gameForTest);
218 | return hand.isPossible.should.equal(true);
219 | });
220 | it('should be detected as not possible', function() {
221 | var hand = new Flush(['Ah', 'Jh', 'Js', 'Jc', 'Or', '2s', 'Kh'], gameForTest);
222 | return hand.isPossible.should.equal(false);
223 | });
224 | return it('should be split according to House Way, Full House', function() {
225 | var hand = PaiGowPokerHelper.solve(['Ah', 'Jh', 'Js', 'Jc', 'Or', '2h', 'Kh']);
226 | hand.hiHand.descr.should.equal('Three of a Kind, J\'s');
227 | return hand.loHand.descr.should.equal('Pair, A\'s');
228 | });
229 | });
230 |
231 | describe('A Flush with Four of a Kind', function() {
232 | it('should be detected as possible', function() {
233 | var hand = new Flush(['Ah', 'Or', 'As', 'Ac', 'Jh', '2h', 'Kh'], gameForTest);
234 | return hand.isPossible.should.equal(true);
235 | });
236 | it('should be detected as not possible', function() {
237 | var hand = new Flush(['Ah', 'Jh', 'Js', 'Jc', 'Or', '2s', 'Kh'], gameForTest);
238 | return hand.isPossible.should.equal(false);
239 | });
240 | return it('should be split according to House Way, Four of a Kind', function() {
241 | var hand = PaiGowPokerHelper.solve(['Ah', 'Or', 'As', 'Ac', 'Jh', '2h', 'Kh']);
242 | hand.hiHand.descr.should.equal('Flush, Ah High');
243 | return hand.loHand.descr.should.equal('Pair, A\'s');
244 | });
245 | });
246 |
247 | describe('A Four of a Kind', function() {
248 | it('should be detected as possible', function() {
249 | var hand = new FourOfAKind(['Ah', 'Ad', 'Or', 'As', 'Jc', 'Kh', 'Qd'], gameForTest);
250 | return hand.isPossible.should.equal(true);
251 | });
252 | it('should be detected as not possible', function() {
253 | var hand = new FourOfAKind(['Ah', 'Kd', 'Or', 'Js', 'Kc', 'Kh', 'Qd'], gameForTest);
254 | return hand.isPossible.should.equal(false);
255 | });
256 | it('should be split according to House Way', function() {
257 | var hand = PaiGowPokerHelper.solve(['Ah', 'Ad', 'Or', 'As', '9c', 'Kh', 'Qd']);
258 | hand.hiHand.descr.should.equal('Pair, A\'s');
259 | return hand.loHand.descr.should.equal('Pair, A\'s');
260 | });
261 | it('should be split according to House Way', function() {
262 | var hand = PaiGowPokerHelper.solve(['Th', 'Td', 'Tc', 'Ts', 'Jc', 'Kh', 'Qd']);
263 | hand.hiHand.descr.should.equal('Pair, 10\'s');
264 | return hand.loHand.descr.should.equal('Pair, 10\'s');
265 | });
266 | it('should be split according to House Way', function() {
267 | var hand = PaiGowPokerHelper.solve(['Th', 'Td', 'Tc', 'Ts', 'Jc', 'Ah', 'Qd']);
268 | hand.hiHand.descr.should.equal('Four of a Kind, 10\'s');
269 | return hand.loHand.descr.should.equal('A High');
270 | });
271 | return it('should be split according to House Way', function() {
272 | var hand = PaiGowPokerHelper.solve(['6h', '6d', '6c', '6s', '7c', '3h', '2d']);
273 | hand.hiHand.descr.should.equal('Four of a Kind, 6\'s');
274 | return hand.loHand.descr.should.equal('7 High');
275 | });
276 | });
277 |
278 | describe('Two Threes of a Kind', function() {
279 | it('should be detected as possible', function() {
280 | var hand = new TwoThreeOfAKind(['Ah', 'Ad', 'Jd', 'As', 'Jc', 'Jh', 'Qd'], gameForTest);
281 | return hand.isPossible.should.equal(true);
282 | });
283 | it('should be detected as not possible', function() {
284 | var hand = new TwoThreeOfAKind(['Ah', 'Kd', 'Or', 'Js', 'Kc', 'Kh', 'Qd'], gameForTest);
285 | return hand.isPossible.should.equal(false);
286 | });
287 | return it('should be split according to House Way', function() {
288 | var hand = PaiGowPokerHelper.solve(['Ah', 'Ad', 'Jd', 'As', 'Jc', 'Jh', 'Qd']);
289 | hand.hiHand.descr.should.equal('Three of a Kind, J\'s');
290 | return hand.loHand.descr.should.equal('Pair, A\'s');
291 | });
292 | });
293 |
294 | describe('A Three of a Kind with Two Pair', function() {
295 | it('should be detected as possible', function() {
296 | var hand = new ThreeOfAKindTwoPair(['Ah', 'Ad', 'Jd', 'As', 'Jc', 'Qh', 'Qd'], gameForTest);
297 | return hand.isPossible.should.equal(true);
298 | });
299 | it('should be detected as not possible', function() {
300 | var hand = new ThreeOfAKindTwoPair(['Ah', 'Kd', 'Or', 'Js', 'Kc', 'Kh', 'Qd'], gameForTest);
301 | return hand.isPossible.should.equal(false);
302 | });
303 | return it('should be split according to House Way', function() {
304 | var hand = PaiGowPokerHelper.solve(['Ah', 'Ad', 'Jd', 'As', 'Jc', 'Qh', 'Qd']);
305 | hand.hiHand.descr.should.equal('Full House, A\'s over J\'s');
306 | return hand.loHand.descr.should.equal('Pair, Q\'s');
307 | });
308 | });
309 |
310 | describe('A Full House', function() {
311 | it('should be detected as possible', function() {
312 | var hand = new FullHouse(['Ah', 'Ad', 'Jd', 'As', 'Jc', 'Qh', '9d'], gameForTest);
313 | return hand.isPossible.should.equal(true);
314 | });
315 | it('should be detected as not possible', function() {
316 | var hand = new FullHouse(['8h', 'Kd', 'Or', 'Js', 'Kc', 'Kh', 'Qd'], gameForTest);
317 | return hand.isPossible.should.equal(false);
318 | });
319 | it('should be split according to House Way', function() {
320 | var hand = PaiGowPokerHelper.solve(['Ah', 'Jh', 'Js', 'Jc', 'Or', '2d', 'Kh']);
321 | hand.hiHand.descr.should.equal('Three of a Kind, J\'s');
322 | return hand.loHand.descr.should.equal('Pair, A\'s');
323 | });
324 | return it('should be split according to House Way', function() {
325 | var hand = PaiGowPokerHelper.solve(['Ah', 'Kd', '2d', '2s', '6c', '6h', '6d']);
326 | hand.hiHand.descr.should.equal('Full House, 6\'s over 2\'s');
327 | return hand.loHand.descr.should.equal('A High');
328 | });
329 | });
330 |
331 | describe('Three of a Kind', function() {
332 | it('should be detected as possible', function() {
333 | var hand = new ThreeOfAKind(['5c', '5s', '5h', '6c', '2d', '9h', 'Qs'], gameForTest);
334 | hand.isPossible.should.equal(true);
335 | });
336 | it('should be detected as not possible', function() {
337 | var hand = new ThreeOfAKind(['5c', '2h', '5h', '6c', '2d', '9h', 'Qs'], gameForTest);
338 | return hand.isPossible.should.equal(false);
339 | });
340 | it('should be split according to House Way', function() {
341 | var hand = PaiGowPokerHelper.solve(['5c', '5s', '5h', '6c', '2d', '9h', 'Qs']);
342 | hand.hiHand.descr.should.equal('Three of a Kind, 5\'s');
343 | return hand.loHand.descr.should.equal('Q High');
344 | });
345 | return it('should be split according to House Way', function() {
346 | var hand = PaiGowPokerHelper.solve(['Ac', 'As', 'Ah', '6c', '2d', '9h', 'Qs']);
347 | hand.hiHand.descr.should.equal('Pair, A\'s');
348 | return hand.loHand.descr.should.equal('A High');
349 | });
350 | });
351 |
352 | describe('Three Pair', function() {
353 | it('should be detected as possible', function() {
354 | var hand = new ThreePair(['5c', '5d', '6s', '6c', '9d', '9s', '2d'], gameForTest);
355 | return hand.isPossible.should.equal(true);
356 | });
357 | it('should be detected as not possible', function() {
358 | var hand = new ThreePair(['5c', '6s', '6h', '5d', '2d', 'Ts', '8d'], gameForTest);
359 | return hand.isPossible.should.equal(false);
360 | });
361 | it('should be split according to House Way', function() {
362 | var hand = PaiGowPokerHelper.solve(['Ac', 'As', '6h', '6c', '9d', '9h', 'Qs']);
363 | hand.hiHand.descr.should.equal('Two Pair, 9\'s & 6\'s');
364 | return hand.loHand.descr.should.equal('Pair, A\'s');
365 | });
366 | });
367 |
368 | describe('Two Pair', function() {
369 | it('should be detected as possible', function() {
370 | var hand = new TwoPair(['5c', '5d', '6s', '6c', 'Td', '9s', '2d'], gameForTest);
371 | return hand.isPossible.should.equal(true);
372 | });
373 | it('should be detected as not possible', function() {
374 | var hand = new TwoPair(['5c', '6s', '6h', '7c', '2d', 'Ts', '8d'], gameForTest);
375 | return hand.isPossible.should.equal(false);
376 | });
377 | it('should be split according to House Way', function() {
378 | var hand = PaiGowPokerHelper.solve(['Ac', 'Ts', '6h', '6c', '3d', '3h', 'Qs']);
379 | hand.hiHand.descr.should.equal('Two Pair, 6\'s & 3\'s');
380 | return hand.loHand.descr.should.equal('A High');
381 | });
382 | it('should be split according to House Way', function() {
383 | var hand = PaiGowPokerHelper.solve(['Ac', '5s', '6h', '6c', '9d', '9h', 'Qs']);
384 | hand.hiHand.descr.should.equal('Two Pair, 9\'s & 6\'s');
385 | return hand.loHand.descr.should.equal('A High');
386 | });
387 | it('should be split according to House Way', function() {
388 | var hand = PaiGowPokerHelper.solve(['Kc', '5s', '6h', '6c', '9d', '9h', 'Qs']);
389 | hand.hiHand.descr.should.equal('Pair, 9\'s');
390 | return hand.loHand.descr.should.equal('Pair, 6\'s');
391 | });
392 | it('should be split according to House Way', function() {
393 | var hand = PaiGowPokerHelper.solve(['Ac', '5s', '6h', '6c', 'Kd', 'Kh', 'Qs']);
394 | hand.hiHand.descr.should.equal('Two Pair, K\'s & 6\'s');
395 | return hand.loHand.descr.should.equal('A High');
396 | });
397 | return it('should be split according to House Way', function() {
398 | var hand = PaiGowPokerHelper.solve(['Ac', 'As', '6h', '4c', '9d', '9h', 'Qs']);
399 | hand.hiHand.descr.should.equal('Pair, A\'s');
400 | return hand.loHand.descr.should.equal('Pair, 9\'s');
401 | });
402 | });
403 |
404 | describe('One Pair', function() {
405 | it('should be detected as possible', function() {
406 | var hand = new OnePair(['5h', '5c', '7s', '9s', '2d', 'Kh', 'Tc'], gameForTest);
407 | return hand.isPossible.should.equal(true);
408 | });
409 | it('should be detected as not possible', function() {
410 | var hand = new OnePair(['5h', '6s', '2s', 'Ts', '8d', 'Kh', 'Or'], gameForTest);
411 | return hand.isPossible.should.equal(false);
412 | });
413 | return it('should be split according to House Way', function() {
414 | var hand = PaiGowPokerHelper.solve(['5h', '5c', '7s', '9s', '2d', 'Kh', 'Tc']);
415 | hand.hiHand.descr.should.equal('Pair, 5\'s');
416 | return hand.loHand.descr.should.equal('K High');
417 | });
418 | });
419 |
420 | describe('High Card', function() {
421 | it('should be detected as possible', function() {
422 | var hand = new HighCard(['5h', '6s', '2s', 'Ts', '8d', 'Kh', 'Or'], gameForTest);
423 | return hand.isPossible.should.equal(true);
424 | });
425 | it('should be split according to House Way', function() {
426 | var hand = PaiGowPokerHelper.solve(['5h', '6c', '7s', '9s', '2d', 'Kh', 'Tc']);
427 | hand.hiHand.descr.should.equal('K High');
428 | return hand.loHand.descr.should.equal('10 High');
429 | });
430 | });
431 |
432 | describe('Hand Comparisons and Winners', function() {
433 | it('should disqualify a player who sets the lo hand higher than the hi', function() {
434 | var player = PaiGowPokerHelper.setHands(['Kh', '7c', 'Qs', 'Td', '5s'], ['Ac', '2h']);
435 | var banker = PaiGowPokerHelper.solve(['8h', '9c', '4s', '3d', '5s', '7c', '2h']);
436 | var winners = PaiGowPokerHelper.winners(player, banker);
437 | return winners.should.equal(-1);
438 | });
439 | it('Even if the player is banking, he/she can still be disqualified', function() {
440 | var dealer = PaiGowPokerHelper.solve(['8h', '9c', '4s', '3d', '5s', '7c', '2h']);
441 | var banker = PaiGowPokerHelper.setHands(['Kh', '7c', 'Qs', 'Td', '5s'], ['Ac', '2h']);
442 | var winners = PaiGowPokerHelper.winners(dealer, banker);
443 | return winners.should.equal(1);
444 | });
445 | it('Player must win both to win', function() {
446 | var player = PaiGowPokerHelper.setHands(['Kh', 'Kc', '7s', 'Td', '5s'], ['Ac', 'Qh']);
447 | var banker = PaiGowPokerHelper.solve(['8h', '8c', '4s', 'Ad', 'Js', '7c', '2h']);
448 | var winners = PaiGowPokerHelper.winners(player, banker);
449 | return winners.should.equal(1);
450 | });
451 | it('Banker must win both to win', function() {
452 | var player = PaiGowPokerHelper.setHands(['Kh', 'Kc', '7s', 'Td', '5s'], ['Ac', 'Qh']);
453 | var banker = PaiGowPokerHelper.solve(['8h', '8c', '4s', 'Ad', 'Ks', '4c', '2h']);
454 | var winners = PaiGowPokerHelper.winners(player, banker);
455 | return winners.should.equal(-1);
456 | });
457 | it('Banker takes all ties', function() {
458 | var player = PaiGowPokerHelper.setHands(['Kh', 'Kc', '7s', 'Td', '5s'], ['Ac', 'Qh']);
459 | var banker = PaiGowPokerHelper.solve(['Ah', 'Qc', 'Ks', 'Kd', 'Ts', '7c', '5h']);
460 | var winners = PaiGowPokerHelper.winners(player, banker);
461 | return winners.should.equal(-1);
462 | });
463 | it('Player wins hi, Banker wins lo, push', function() {
464 | var player = PaiGowPokerHelper.setHands(['Kh', 'Kc', '7s', 'Td', '6s'], ['Ac', 'Jh']);
465 | var banker = PaiGowPokerHelper.solve(['Ah', 'Qc', 'Ks', 'Kd', 'Ts', '7c', '5h']);
466 | var winners = PaiGowPokerHelper.winners(player, banker);
467 | return winners.should.equal(0);
468 | });
469 | it('Banker wins hi, Player wins lo, push', function() {
470 | var player = PaiGowPokerHelper.setHands(['Kh', 'Kc', '7s', 'Td', '4s'], ['Ac', 'Qh']);
471 | var banker = PaiGowPokerHelper.solve(['Ah', 'Jc', 'Ks', 'Kd', 'Ts', '7c', '5h']);
472 | var winners = PaiGowPokerHelper.winners(player, banker);
473 | return winners.should.equal(0);
474 | });
475 | it('In Pai Gow Poker, A2345 is the second highest straight', function() {
476 | var player = PaiGowPokerHelper.setHands(['Ah', '2c', '5s', '3d', '4s'], ['Jc', 'Th']);
477 | var banker = PaiGowPokerHelper.solve(['9h', 'Jd', 'Ks', 'Qd', 'Ts', '7c', '5h']);
478 | var winners = PaiGowPokerHelper.winners(player, banker);
479 | return winners.should.equal(1);
480 | });
481 | });
482 |
--------------------------------------------------------------------------------
/test/standard.js:
--------------------------------------------------------------------------------
1 | var should = require('should');
2 | var Hand = require('../pokersolver').Hand;
3 | var Flush = require('../pokersolver').Flush;
4 | var StraightFlush = require('../pokersolver').StraightFlush;
5 | var Straight = require('../pokersolver').Straight;
6 | var FourOfAKind = require('../pokersolver').FourOfAKind;
7 | var FullHouse = require('../pokersolver').FullHouse;
8 | var ThreeOfAKind = require('../pokersolver').ThreeOfAKind;
9 | var TwoPair = require('../pokersolver').TwoPair;
10 | var OnePair = require('../pokersolver').OnePair;
11 | var Game = require('../pokersolver').Game;
12 |
13 | var gameForTest = new Game('standard');
14 |
15 | describe('A basic hand', function() {
16 | it('should return a hand with cards sorted descending', function() {
17 | var hand = Hand.solve(['Kh', 'Tc', '5d', 'As', '3c', '3s', '2h']);
18 | hand.cardPool[0].toString().should.equal('As');
19 | return hand.cardPool[6].toString().should.equal('2h');
20 | });
21 | it('should return a correct description', function() {
22 | var hand = Hand.solve(['Kh', 'Tc', '5d', 'As', '3c', '3s', '2h']);
23 | return hand.descr.should.equal('Pair, 3\'s');
24 | });
25 | return it('should return throw an Error for a hand with duplicate cards', function() {
26 | (function () {
27 | Hand.solve(['As', 'Qh', 'Ts', 'As', '2d']);
28 | }).should.throw();
29 | });
30 | });
31 |
32 | describe('A Straight Flush', function() {
33 | it('should be detected as possible', function() {
34 | var hand = new StraightFlush(['Qd', '7s', '8s', 'Js', 'Kh', 'Ts', '9s'], gameForTest);
35 | return hand.isPossible.should.equal(true);
36 | });
37 | it('should be detected as not possible', function() {
38 | var hand = new StraightFlush(['Qd', '7s', '8s', 'Js', 'Kh', 'Ts', '9d'], gameForTest);
39 | return hand.isPossible.should.equal(false);
40 | });
41 | return it('should return 5 cards with low ace', function() {
42 | var hand = new StraightFlush(['Ad', '2d', '3d', '4d', '5d', 'Ts', '9d'], gameForTest);
43 | return hand.cards.length.should.equal(5);
44 | });
45 | });
46 |
47 | describe('A Four of a Kind', function() {
48 | it('should be detected as possible', function() {
49 | var hand = new FourOfAKind(['7h', '7d', '3s', '2c', '7s', '7c', '4s'], gameForTest);
50 | return hand.isPossible.should.equal(true);
51 | });
52 | return it('should be detected as not possible', function() {
53 | var hand = new FourOfAKind(['7h', '3d', '3s', '2c', '7s', '7c', '4s'], gameForTest);
54 | return hand.isPossible.should.equal(false);
55 | });
56 | });
57 |
58 | describe('A Full House', function() {
59 | it('should be detected as possible', function() {
60 | var hand = new FullHouse(['Qd', 'Js', '3h', 'Qc', '7d', 'Jc', 'Jd'], gameForTest);
61 | hand.isPossible.should.equal(true);
62 | hand = new FullHouse(['9c', '9d', 'Jh', 'Jc', 'Js', '9h', 'As'], gameForTest);
63 | return hand.isPossible.should.equal(true);
64 | });
65 | it('should be detected as not possible', function() {
66 | var hand = new FullHouse(['5h', '3h', '3c', '5d', '2s', 'Ts', 'Td'], gameForTest);
67 | hand.isPossible.should.equal(false);
68 | hand = new FullHouse(['5s', '9d', 'Kd', '6h', '7s', '7d', 'Kh'], gameForTest);
69 | hand.isPossible.should.equal(false);
70 | hand = new FullHouse(['9h', '9s', '3d', '5c', 'Kd', '5d', 'Kh'], gameForTest);
71 | return hand.isPossible.should.equal(false);
72 | });
73 | it('should pick the high kickers', function() {
74 | var hand = new FullHouse(['5d', '5h', '3h', '3c', 'Qh', 'Qd', 'Qs'], gameForTest);
75 | return hand.cards.toString().indexOf('3h').should.equal(-1);
76 | });
77 | return it('should be in order', function() {
78 | var hand;
79 | hand = new FullHouse(['9c', 'Qs', '9h', '5h', 'Ts', 'Qc', 'Qh'], gameForTest);
80 | return hand.cards.toString().should.equal('Qs,Qc,Qh,9c,9h');
81 | });
82 | });
83 |
84 | describe('A Flush', function() {
85 | it('should be detected as possible', function() {
86 | var hand = new Flush(['4h', 'Th', '5h', 'Ac', '2h', 'Kh', '8d'], gameForTest);
87 | return hand.isPossible.should.equal(true);
88 | });
89 | return it('should be detected as not possible', function() {
90 | var hand = new Flush(['4s', 'Th', '5h', 'Ac', '2h', 'Kh', '8d'], gameForTest);
91 | return hand.isPossible.should.equal(false);
92 | });
93 | });
94 |
95 | describe('A Straight', function() {
96 | it('should be detected as possible', function() {
97 | var hand = new Straight(['5c', '6s', '3s', '2s', '5s', '4s', '5d'], gameForTest);
98 | return hand.isPossible.should.equal(true);
99 | });
100 | it('should be detected as possible', function() {
101 | var hand = new Straight(['5d', '6s', '7s', '8c', 'Ts', '9s', '2d'], gameForTest);
102 | return hand.isPossible.should.equal(true);
103 | });
104 | it('should be detected as not possible', function() {
105 | var hand = new Straight(['5h', '6s', '6h', '7c', '2s', 'Ts', '8d'], gameForTest);
106 | return hand.isPossible.should.equal(false);
107 | });
108 | it('should detect a low ace', function() {
109 | var hand = new Straight(['2c', '3s', '4h', '5c', 'As', 'Ts', '8d'], gameForTest);
110 | return hand.isPossible.should.equal(true);
111 | });
112 | it('should detect a high ace', function() {
113 | var hand = new Straight(['2d', '3s', '4h', '7c', 'As', 'Ts', 'Kd'], gameForTest);
114 | return hand.isPossible.should.equal(false);
115 | });
116 | return it('should know that an ace is not high in a wheel', function() {
117 | var lowHand = new Straight(['2s', '3s', '4h', '5c', 'As', 'Ts', '8d'], gameForTest);
118 | var highHand = new Straight(['2s', '3s', '4h', '5c', '6s', 'Ts', '8d'], gameForTest);
119 | return highHand.loseTo(lowHand).should.equal(false);
120 | });
121 | });
122 |
123 | describe('Three of a Kind', function() {
124 | it('should be detected as possible', function() {
125 | var hand = new ThreeOfAKind(['5c', '5s', '5h', '6c', 'Td', '9s', '2d'], gameForTest);
126 | hand.isPossible.should.equal(true);
127 | return hand.toString().should.equal('5c, 5s, 5h, 10d, 9s');
128 | });
129 | return it('should be detected as not possible', function() {
130 | var hand = new ThreeOfAKind(['5c', '2h', '5h', '6c', 'Ts', '9s', '2d'], gameForTest);
131 | return hand.isPossible.should.equal(false);
132 | });
133 | });
134 |
135 | describe('Two Pair', function() {
136 | it('should be detected as possible', function() {
137 | var hand = new TwoPair(['5c', '5d', '6s', '6c', 'Td', '9s', '2d'], gameForTest);
138 | return hand.isPossible.should.equal(true);
139 | });
140 | return it('should be detected as not possible', function() {
141 | var hand = new TwoPair(['5c', '6s', '6h', '7c', '2d', 'Ts', '8d'], gameForTest);
142 | return hand.isPossible.should.equal(false);
143 | });
144 | });
145 |
146 | describe('One Pair', function() {
147 | it('should be detected as possible', function() {
148 | var hand = new OnePair(['5h', '5c', '7s', '6c', 'Ts', '9s', '2d'], gameForTest);
149 | return hand.isPossible.should.equal(true);
150 | });
151 | it('should be detected as not possible', function() {
152 | var hand = new OnePair(['5h', '6s', 'Jh', '7c', '2s', 'Ts', '8d'], gameForTest);
153 | return hand.isPossible.should.equal(false);
154 | });
155 | return it('should select the correct winner', function() {
156 | var highHand = new OnePair(['4d', '4h', 'Ah', 'Jc', 'Ts', '7s', '8d'], gameForTest);
157 | var lowHand = new OnePair(['4d', '4h', 'Ac', 'Tc', '9s', '7c', '8d'], gameForTest);
158 | return lowHand.loseTo(highHand).should.equal(true) && highHand.loseTo(lowHand).should.equal(false);
159 | });
160 | });
161 |
162 | describe('Building hands from 7 cards', function() {
163 | it('should return best hand as Two Pair', function() {
164 | var hand = Hand.solve(['8d', '8s', '4s', '5c', 'Qd', '5d', 'Qh']);
165 | return hand.name.should.equal('Two Pair');
166 | });
167 | it('should detect the best hand string (#1)', function() {
168 | var hand = Hand.solve(['8d', '8s', '4s', '5c', 'Qd', '5d', 'Qh']);
169 | return hand.toString().should.equal('Qd, Qh, 8d, 8s, 5c');
170 | });
171 | return it('should detect the best hand string (#2)', function() {
172 | var hand = Hand.solve(['4s', '4h', 'Ah', 'Jc', 'Ts', '7s', '8d']);
173 | return hand.toString().should.equal('4s, 4h, Ah, Jc, 10s');
174 | });
175 | });
176 |
177 | describe('Building hands from 5 cards', function() {
178 | return it('should return best hand as Two Pair', function() {
179 | var hand = Hand.solve(['8d', '8s', 'Qd', 'Ad', 'Qh']);
180 | return hand.name.should.equal('Two Pair');
181 | });
182 | });
183 |
184 | describe('Determining winning hands', function() {
185 | it('should detect the winning hand from a list', function() {
186 | var h1 = Hand.solve(['2s', '3s', '4h', '5c', 'As', 'Ts', '8d']);
187 | var h2 = Hand.solve(['5s', 'Td', '3h', 'Ac', '2s', 'Ts', '8d']);
188 | var h3 = Hand.solve(['5s', '5h', '3s', '3c', '2s', 'Ts', '3d']);
189 | var winners = Hand.winners([h1, h2, h3]);
190 | winners.length.should.equal(1);
191 | return winners[0].should.equal(h3);
192 | });
193 | return it('should detect the winning hands from a list', function() {
194 | var h1 = Hand.solve(['2s', '3s', '4h', '5c', 'As', 'Ts', '8d']);
195 | var h2 = Hand.solve(['2h', '3h', '4d', '5d', 'Ah', 'Tc', '8c']);
196 | var h3 = Hand.solve(['5s', 'Ts', '3h', 'Ac', '2s', 'Tc', '8d']);
197 | var winners = Hand.winners([h1, h2, h3]);
198 | winners.length.should.equal(2);
199 | (winners.indexOf(h1) >= 0).should.equal(true);
200 | return (winners.indexOf(h2) >= 0).should.equal(true);
201 | });
202 | });
203 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | var should = require('should');
2 |
3 | function importTest(name, path) {
4 | describe(name, function() {
5 | require(path);
6 | });
7 | }
8 |
9 | describe('main', function() {
10 | importTest('Standard', './standard');
11 | importTest('Jacks or Better', './jacksbetter');
12 | importTest('Joker Poker', './joker');
13 | importTest('Deuces Wild', './deuceswild');
14 | importTest('Three Card Poker', './threecard');
15 | importTest('Four Card Poker', './fourcard');
16 | importTest('Four Card Aces Up Bonus', './fourcardbonus');
17 | return importTest('Pai Gow Poker', './paigowpokerfullhands');
18 | });
19 |
--------------------------------------------------------------------------------
/test/threecard.js:
--------------------------------------------------------------------------------
1 | var should = require('should');
2 | var Hand = require('../pokersolver').Hand;
3 | var Flush = require('../pokersolver').Flush;
4 | var StraightFlush = require('../pokersolver').StraightFlush;
5 | var Straight = require('../pokersolver').Straight;
6 | var ThreeOfAKind = require('../pokersolver').ThreeOfAKind;
7 | var OnePair = require('../pokersolver').OnePair;
8 | var HighCard = require('../pokersolver').HighCard;
9 | var Game = require('../pokersolver').Game;
10 |
11 | var gameForTest = new Game('threecard');
12 |
13 | // Three Card Poker is only three cards, and a different ranking.
14 | // Hands are compared in this game, not just based on rank.
15 | // Dealer qualifies with a Queen High
16 | describe('A basic hand', function() {
17 | it('should return a hand with cards sorted descending', function() {
18 | var hand = Hand.solve(['3c', 'Kh', '3s'], gameForTest);
19 | hand.cardPool[0].toString().should.equal('Kh');
20 | return hand.cardPool[2].toString().should.equal('3s');
21 | });
22 | return it('should return a correct description', function() {
23 | var hand = Hand.solve(['As', '3c', '3s'], gameForTest);
24 | return hand.descr.should.equal('Pair, 3\'s');
25 | });
26 | });
27 |
28 | describe('A Straight Flush', function() {
29 | it('should be detected as possible', function() {
30 | var hand = new StraightFlush(['8s', 'Ts', '9s'], gameForTest);
31 | return hand.isPossible.should.equal(true);
32 | });
33 | return it('should be detected as not possible', function() {
34 | var hand = new StraightFlush(['8s', 'Ts', '9d'], gameForTest);
35 | return hand.isPossible.should.equal(false);
36 | });
37 | });
38 |
39 | describe('A Flush', function() {
40 | it('should be detected as possible', function() {
41 | var hand = new Flush(['4h', 'Th', '5h'], gameForTest);
42 | return hand.isPossible.should.equal(true);
43 | });
44 | return it('should be detected as not possible', function() {
45 | var hand = new Flush(['4s', 'Th', '5h'], gameForTest);
46 | return hand.isPossible.should.equal(false);
47 | });
48 | });
49 |
50 | describe('A Straight', function() {
51 | it('should be detected as possible', function() {
52 | var hand = new Straight(['3s', '4s', '5c'], gameForTest);
53 | return hand.isPossible.should.equal(true);
54 | });
55 | it('should be detected as not possible', function() {
56 | var hand = new Straight(['5h', '6s', '6h'], gameForTest);
57 | return hand.isPossible.should.equal(false);
58 | });
59 | it('should detect a low ace', function() {
60 | var hand = new Straight(['2c', '3s', 'As'], gameForTest);
61 | return hand.isPossible.should.equal(true);
62 | });
63 | it('should detect a high ace', function() {
64 | var hand = new Straight(['2d', '4h', 'As'], gameForTest);
65 | return hand.isPossible.should.equal(false);
66 | });
67 | return it('should know that an ace is not high in a wheel', function() {
68 | var lowHand = new Straight(['2s', '3s', 'Ad'], gameForTest);
69 | var highHand = new Straight(['2s', '3s', '4h'], gameForTest);
70 | return highHand.loseTo(lowHand).should.equal(false);
71 | });
72 | });
73 |
74 | describe('Three of a Kind', function() {
75 | it('should be detected as possible', function() {
76 | var hand = new ThreeOfAKind(['5c', '5s', '5h'], gameForTest);
77 | hand.isPossible.should.equal(true);
78 | return hand.toString().should.equal('5c, 5s, 5h');
79 | });
80 | return it('should be detected as not possible', function() {
81 | var hand = new ThreeOfAKind(['5c', '2h', '5h'], gameForTest);
82 | return hand.isPossible.should.equal(false);
83 | });
84 | });
85 |
86 | describe('One Pair', function() {
87 | it('should be detected as possible', function() {
88 | var hand = new OnePair(['5h', '5c', '2d'], gameForTest);
89 | return hand.isPossible.should.equal(true);
90 | });
91 | it('should be detected as not possible', function() {
92 | var hand = new OnePair(['5h', '6s', '8d'], gameForTest);
93 | return hand.isPossible.should.equal(false);
94 | });
95 | return it('should select the correct winner', function() {
96 | var highHand = new OnePair(['4d', '4h', 'Jc'], gameForTest);
97 | var lowHand = new OnePair(['4d', '4h', 'Tc'], gameForTest);
98 | return lowHand.loseTo(highHand).should.equal(true) && highHand.loseTo(lowHand).should.equal(false);
99 | });
100 | });
101 |
102 | describe('Determining winning hands', function() {
103 | it('should detect the winning hand from a list', function() {
104 | var h1 = Hand.solve(['2s', '3s', '3h'], gameForTest, false);
105 | var h2 = Hand.solve(['3h', 'Ac', '2s'], gameForTest, true);
106 | var winners = Hand.winners([h1, h2]);
107 | winners.length.should.equal(1);
108 | return winners[0].should.equal(h2);
109 | });
110 | it('should detect the winning hand - straight higher than flush', function() {
111 | var h1 = Hand.solve(['3h', 'Ac', '2s'], gameForTest, true);
112 | var h2 = Hand.solve(['2s', '3s', '8s'], gameForTest, false);
113 | var winners = Hand.winners([h1, h2]);
114 | winners.length.should.equal(1);
115 | return winners[0].should.equal(h1);
116 | });
117 | it('should detect a tie', function() {
118 | var h1 = Hand.solve(['2s', '3s', '4h'], gameForTest, true);
119 | var h2 = Hand.solve(['2h', '3h', '4d'], gameForTest, false);
120 | var winners = Hand.winners([h1, h2]);
121 | winners.length.should.equal(2);
122 | (winners.indexOf(h1) >= 0).should.equal(true);
123 | return (winners.indexOf(h2) >= 0).should.equal(true);
124 | });
125 | it('should account for a disqualified hand', function() {
126 | var player = Hand.solve(['5c', '3d', '2s'], gameForTest, false);
127 | var dealer = Hand.solve(['Jh', '8s', 'Tc'], gameForTest, true);
128 | var winners = Hand.winners([player, dealer]);
129 | winners.length.should.equal(1);
130 | return winners[0].should.equal(player);
131 | });
132 | });
133 |
--------------------------------------------------------------------------------