Permalink
Browse files

update to use 2 plus 2 eval

  • Loading branch information...
1 parent b0d6f5c commit b72d03b7660838d52bf6b945ed92bc4148108b9b @chenosaurus committed Sep 17, 2012
Showing with 138 additions and 7,888 deletions.
  1. BIN HandRanks.dat
  2. +0 −7,462 hands.txt
  3. +2 −9 index.js
  4. +0 −54 lib/Card.js
  5. +0 −62 lib/Hand.js
  6. +0 −24 lib/Masks.js
  7. +119 −0 lib/PokerEvaluator.js
  8. +0 −252 lib/PokerUtil.js
  9. +2 −3 package.json
  10. +15 −5 readme.md
  11. +0 −17 test.js
View
BIN HandRanks.dat
Binary file not shown.
View
7,462 hands.txt
0 additions, 7,462 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
11 index.js
@@ -1,9 +1,2 @@
-var Card = require("./lib/Card");
-var Hand = require("./lib/Hand");
-var PokerUtil = require("./lib/PokerUtil");
-
-module.exports = {
- Card: Card,
- Hand: Hand,
- PokerUtil: PokerUtil
-}
+var PokerEvaluator = require("./lib/PokerEvaluator");
+module.exports = PokerEvaluator;
View
54 lib/Card.js
@@ -1,54 +0,0 @@
-var Card = function(num, suit) {
- this.num = num;
- this.suit = suit;
-}
-
-Card.makeCard = function(str) {
- var num = str[0].toLowerCase();
- var suit = str[1].toLowerCase();
-
- return new Card(Card.NUMS[num], Card.SUITS[suit]);
-}
-
-Card.TWO = 0;
-Card.THREE = 1;
-Card.FOUR = 2;
-Card.FIVE = 3;
-Card.SIX = 4;
-Card.SEVEN = 5;
-Card.EIGHT = 6;
-Card.NINE = 7;
-Card.TEN = 8;
-Card.JACK = 9;
-Card.QUEEN = 10;
-Card.KING = 11;
-Card.ACE = 12;
-Card.SPADE = 0;
-Card.HEART = 1;
-Card.CLUB = 2;
-Card.DIAMOND = 3;
-
-Card.NUMS = {
- "a": Card.ACE,
- "2": Card.TWO,
- "3": Card.THREE,
- "4": Card.FOUR,
- "5": Card.FIVE,
- "6": Card.SIX,
- "7": Card.SEVEN,
- "8": Card.EIGHT,
- "9": Card.NINE,
- "t": Card.TEN,
- "j": Card.JACK,
- "q": Card.QUEEN,
- "k": Card.KING
-}
-
-Card.SUITS = {
- "s": Card.SPADE,
- "h": Card.HEART,
- "d": Card.DIAMOND,
- "c": Card.CLUB
-}
-
-module.exports = Card;
View
62 lib/Hand.js
@@ -1,62 +0,0 @@
-var PokerUtil = require("./PokerUtil");
-var Card = require("./Card");
-
-var Hand = function(cards) {
- if (cards.length < 5) {
- throw new Error("Hand must have at least 5");
- }
-
- this.nums = 0;
- this.suits = 0;
-
- this.parseHand(cards);
-}
-
-Hand.prototype.parseHand = function(cards) {
-
- cards = cards.sort(Hand.sortCards);
-
- var suitsIndex = 0;
- var lastNum = 0;
- //parse each card
- for (var i = 0; i < cards.length; i ++) {
-
- var card = 1;
- for (var j = 0; j < cards[i].num; j++) {
- card = card << 1;
- }
-
- this.nums = this.nums | card;
-
- //now parse the suit
- if (cards[i].num != lastNum) {
- suitsIndex++;
- lastNum = cards[i].num;
- }
-
- var suit = 1;
- for (var k = 0; k < cards[i].suit; k++) {
- suit = suit << 1;
- }
-
- suit = suit << (suitsIndex * 4);
-
- this.suits = this.suits | suit;
- }
-
-}
-
-Hand.sortCards = function(a, b) {
- return a.num < b.num;
-}
-
-Hand.makeHand = function() {
- var cards = [];
- for (var i = 0; i < arguments.length; i++) {
- cards.push(Card.makeCard(arguments[i]));
- }
-
- return new Hand(cards);
-}
-
-module.exports = Hand;
View
24 lib/Masks.js
@@ -1,24 +0,0 @@
-var Masks = {
-
- straights: [
- parseInt("1111100000000", 2),
- parseInt("0111110000000", 2),
- parseInt("0011111000000", 2),
- parseInt("0001111100000", 2),
- parseInt("0000111110000", 2),
- parseInt("0000011111000", 2),
- parseInt("0000001111100", 2),
- parseInt("0000000111110", 2),
- parseInt("0000000011111", 2)
- ],
-
- flushes: [
- "1000100010001000100000000",
- "0000100010001000100010000"
- ]
-
-
-
-}
-
-module.exports = Masks;
View
119 lib/PokerEvaluator.js
@@ -0,0 +1,119 @@
+var fs = require("fs");
+
+var HANDTYPES = [
+ "invalid hand",
+ "high card",
+ "one pair",
+ "two pairs",
+ "three of a kind",
+ "straight",
+ "flush",
+ "full house",
+ "four of a kind",
+ "straight flush"
+];
+
+var CARDS = {
+ "2c": 1,
+ "2d": 2,
+ "2h": 3,
+ "2s": 4,
+ "3c": 5,
+ "3d": 6,
+ "3h": 7,
+ "3s": 8,
+ "4c": 9,
+ "4d": 10,
+ "4h": 11,
+ "4s": 12,
+ "5c": 13,
+ "5d": 14,
+ "5h": 15,
+ "5s": 16,
+ "6c": 17,
+ "6d": 18,
+ "6h": 19,
+ "6s": 20,
+ "7c": 21,
+ "7d": 22,
+ "7h": 23,
+ "7s": 24,
+ "8c": 25,
+ "8d": 26,
+ "8h": 27,
+ "8s": 28,
+ "9c": 29,
+ "9d": 30,
+ "9h": 31,
+ "9s": 32,
+ "tc": 33,
+ "td": 34,
+ "th": 35,
+ "ts": 36,
+ "jc": 37,
+ "jd": 38,
+ "jh": 39,
+ "js": 40,
+ "qc": 41,
+ "qd": 42,
+ "qh": 43,
+ "qs": 44,
+ "kc": 45,
+ "kd": 46,
+ "kh": 47,
+ "ks": 48,
+ "ac": 49,
+ "ad": 50,
+ "ah": 51,
+ "as": 52
+};
+
+
+var PokerEvaluator = function(handRankFile) {
+ this.init(handRankFile);
+};
+
+PokerEvaluator.prototype.init = function(handRankFile) {
+ console.log('trying to load ', handRankFile);
+ this.ranks = fs.readFileSync(handRankFile);
+};
+
+PokerEvaluator.prototype.evalHand = function(cards) {
+ if (!this.ranks) {
+ throw new Error("HandRanks.dat not loaded");
+ }
+
+ if (cards.length != 7) {
+ throw new Error("Hand must be 7 cards");
+ }
+
+ //if passing in string formatted hand, convert first
+ if (typeof cards[0] == "string") {
+ cards = cards.map(function(card) {
+ return CARDS[card.toLowerCase()];
+ });
+ }
+
+ return this.eval(cards);
+};
+
+PokerEvaluator.prototype.eval = function(cards) {
+ var p = this.ranks.slice((53 + cards[0]) * 4, (53 + cards[0]) * 4 + 4).readUInt32LE(0);
+ p = this.ranks.slice((p + cards[1]) * 4, (p + cards[1]) * 4 + 4).readUInt32LE(0);
+ p = this.ranks.slice((p + cards[2]) * 4, (p + cards[2]) * 4 + 4).readUInt32LE(0);
+ p = this.ranks.slice((p + cards[3]) * 4, (p + cards[3]) * 4 + 4).readUInt32LE(0);
+ p = this.ranks.slice((p + cards[4]) * 4, (p + cards[4]) * 4 + 4).readUInt32LE(0);
+ p = this.ranks.slice((p + cards[5]) * 4, (p + cards[5]) * 4 + 4).readUInt32LE(0);
+ var res = this.ranks.slice((p + cards[6]) * 4, (p + cards[6]) * 4 + 4).readUInt32LE(0);
+
+ var handType = res >> 12;
+ var handRank = res & 0x00000fff;
+
+ return {
+ handType: res >> 12,
+ handRank: res & 0x00000fff,
+ handName: HANDTYPES[res >> 12]
+ }
+};
+
+module.exports = PokerEvaluator;
View
252 lib/PokerUtil.js
@@ -1,252 +0,0 @@
-var Masks = require("./Masks");
-
-var PokerUtil = {
-
- suitMasks: {
- SPADE: parseInt("0001000100010001000100010001", 2),
- HEART: parseInt("0010001000100010001000100010", 2),
- CLUB: parseInt("0100010001000100010001000100", 2),
- DIAMOND: parseInt("1000100010001000100010001000", 2)
- },
-
- numBits4: {
- "0000": 0,
- "0001": 1,
- "0010": 1,
- "0011": 2,
- "0100": 1,
- "0101": 2,
- "0110": 2,
- "0111": 3,
- "1000": 1,
- "1001": 2,
- "1010": 2,
- "1011": 3,
- "1100": 2,
- "1101": 3,
- "1110": 3,
- "1111": 4
- },
-
- numBits5: {
- "00000": 0,
- "00001": 1,
- "00010": 1,
- "00011": 2,
- "00100": 1,
- "00101": 2,
- "00110": 2,
- "00111": 3,
- "01000": 1,
- "01001": 2,
- "01010": 2,
- "01011": 3,
- "01100": 2,
- "01101": 3,
- "01110": 3,
- "01111": 4,
- "10000": 1,
- "10001": 2,
- "10010": 2,
- "10011": 3,
- "10100": 2,
- "10101": 3,
- "10110": 3,
- "10111": 4,
- "11000": 2,
- "11001": 3,
- "11010": 3,
- "11011": 4,
- "11100": 3,
- "11101": 4,
- "11110": 4,
- "11111": 5
- },
-
- suitBits: [1, 2, 4, 8],
-
- cardBits: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096],
-
- padSuit: function(suit) {
- return ("000000000000000000000000000000000000" + suit.toString(2)).slice(-28);
- },
-
- padNum: function(num) {
- //return (num | 8192).toString(2).substr(1);
- return ("0000000000000" + num.toString(2)).slice(-13);
- },
-
- padSingleSuit: function(suit) {
- return ("0000" + suit.toString(2)).slice(-4);
- },
-
- countNums: function(nums) {
- nums = PokerUtil.padNum(nums);
-
- var a = nums.substr(0, 5),
- b = nums.substr(5, 5),
- c = "00" + nums.substr(10, 3);
-
- return PokerUtil.numBits5[a]
- + PokerUtil.numBits5[b]
- + PokerUtil.numBits5[c];
- },
-
- countSuits: function(suits) {
-
- var spades = PokerUtil.suitMasks.SPADE & suits,
- hearts = PokerUtil.suitMasks.HEART & suits,
- clubs = PokerUtil.suitMasks.CLUB & suits,
- diamonds = PokerUtil.suitMasks.DIAMOND & suits;
-
- return {
- spades: PokerUtil.countSuit(spades),
- hearts: PokerUtil.countSuit(hearts),
- clubs: PokerUtil.countSuit(clubs),
- diamonds: PokerUtil.countSuit(diamonds)
- }
- },
-
- countSuit: function(suit) {
- suit = PokerUtil.padSuit(suit);
-
- var a = suit.substr(0, 5),
- b = suit.substr(5, 5),
- c = suit.substr(10, 5),
- d = suit.substr(15, 5),
- e = suit.substr(20, 5),
- f = "00" + suit.substr(25, 3);
-
- return PokerUtil.numBits5[a]
- + PokerUtil.numBits5[b]
- + PokerUtil.numBits5[c]
- + PokerUtil.numBits5[d]
- + PokerUtil.numBits5[e]
- + PokerUtil.numBits5[f];
- },
-
- testStraight: function(nums) {
- for (var i = Masks.straights.length - 1; i >= 0; i--) {
- if ((Masks.straights[i] & nums) == Masks.straights[i]) {
- return true;
- }
- }
- return false;
- },
-
- test4k: function(suits) {
- for (var i = 0; i < 7; i++) {
- var mask = 15 << (i * 4);
- return (mask & suits == mask);
- }
- },
-
- test3k: function(suits) {
- for (var i = 0; i < 7; i++) {
- var curSuit = ((15 << (i * 4)) & suits) >> (i * 4);
- if (PokerUtil.numBits4[PokerUtil.padSingleSuit(curSuit.toString(2))] > 2) {
- return true;
- }
- }
- return false;
- },
-
- test2p: function(suits) {
- var pairsFound = 0;
- for (var i = 0; i < 7; i++) {
- var curSuit = ((15 << (i * 4)) & suits) >> (i * 4);
- if (PokerUtil.numBits4[PokerUtil.padSingleSuit(curSuit.toString(2))] > 1) {
- pairsFound++;
- }
- if (pairsFound >= 2) {
- return 2;
- }
- }
- return pairsFound;
- },
-
-
- evalHand: function(hand) {
-
- var sf = false;
- var k4 = false;
- var fh = false;
- var fl = false;
- var st = false;
- var k3 = false;
- var p2 = false;
- var p1 = false;
- var hc = true;
-
- var suitCount = PokerUtil.countSuits(hand.suits);
-
-
- //distinct numbers
- var numCount = PokerUtil.countNums(hand.nums);
-
- //check for possible flush
- if (suitCount.spades > 4 || suitCount.hearts > 4 || suitCount.clubs > 4 || suitCount.diamonds > 4) {
- fl = true;
- }
-
- //check for 4 of a kind
- k4 = PokerUtil.test4k(hand.suits);
-
- //check for straight
- st = PokerUtil.testStraight(hand.nums);
-
- //if also fl, then sf
- if (st && fl) {
- sf = true;
- }
-
- //check for 3 of a kind
- k3 = PokerUtil.test3k(hand.suits);
-
- //check for full house, must have 3 of a kind && less than 4 distinct nums
- fh = k3 && numCount <= 4;
-
- //check for 2 pairs
- var pairsFound = PokerUtil.test2p(hand.suits);
-
-
- p2 = pairsFound == 2;
-
- //has a pair?
- p1 = pairsFound > 0;
-
- if (sf) {
-
- console.log("sf");
- } else if (k4) {
-
- console.log("4k");
- } else if (fh) {
-
- console.log("fh");
- } else if (fl) {
-
- console.log("fl");
- } else if (st) {
-
- console.log("st");
- } else if (k3) {
-
- console.log("3k");
- } else if (p2) {
-
- console.log("2p");
- } else if (p1) {
-
- console.log("1p");
- } else {
-
- console.log("hc");
- }
-
- }
-
-
-}
-
-module.exports = PokerUtil;
View
5 package.json
@@ -1,7 +1,7 @@
{
"name": "poker-evaluator",
- "version": "0.0.2",
- "description": "A library to evaluate poker 5 to 7 card poker hands",
+ "version": "0.0.3",
+ "description": "A library to evaluate 7 card poker hands",
"homepage": "http://github.com/chenosaurus/poker-evaluator",
"keywords": ["poker", "games"],
"author": "David Chen <chenosaurus@gmail.com>",
@@ -12,7 +12,6 @@
"dependencies": {
},
"devDependencies": {
- "microtime": "0.1.3-1"
},
"main": "index",
"engines": {
View
20 readme.md
@@ -1,13 +1,23 @@
##Poker Hand Evaluator
-Usage:
+Poker hand evaluator using the Two Plus Two alogorithm and lookup table.
+
+--to install:
+
+npm install poker-evaluator
+
+--Usage:
```js
-var Hand = require("./index").Hand;
+var PokerEvaluator = require("poker-evaluator");
+var evaluator = new PokerEvaluator("HandRanks.dat");
-var PokerUtil = require("./index").PokerUtil;
+var res = evaluator.evalHand(["As", "Ks", "Qs", "Js", "Ts", "3c", "5h"]);
-var hand = Hand.makeHand("3h", "4h", "5h", "6h", "7h", "8h", "9d");
+// res = {
+// handType: 9,
+// handRank: 10,
+// handName: 'straight flush'
+// }
-PokerUtil.evalHand(hand);
```
View
17 test.js
@@ -1,17 +0,0 @@
-var Hand = require("./index").Hand;
-var PokerUtil = require("./index").PokerUtil;
-
-
-
-var hand = Hand.makeHand("3h", "4h", "5h", "6h", "7h", "8h", "9d");
-PokerUtil.evalHand(hand);
-
-
-function fac(n) {
- if ((n == 0) || (n == 1))
- return 1
- else {
- result = (n * fac(n-1) )
- return result
- }
-}

0 comments on commit b72d03b

Please sign in to comment.