UNPKG

casino-server

Version:

An multi-rule scalable online poker game server powered by redis, node.js and socket.io

327 lines (271 loc) 7.63 kB
var Poker = require('./poker'); var POKER_CARDS = Poker.CARDS; var HIGH_CARD = 1, // 高牌, AQ953 ONE_PAIR = 2, // 一对, KK854 TWO_PAIR = 3, // 两对, KKJJ9 THREE = 4, // 三条, KKK98 STRAIGHT = 5, // 顺子, 98765 FLUSH = 6, // 同花, FULLHOUSE = 7, // 葫芦, KKK99 FOUR = 8, // 四条, KKKK9 STRAIGHT_FLUSH = 9, // 同花顺, 98765 ROYAL_FLUSH = 10; // 皇家同花顺, AKQJ10 var HOLDEM_PATTERNS = { 0: 'invalid', // 错误 1: 'high card', // 高牌 2: 'one pair', // 一对 3: 'two pair', // 两对 4: 'three of a kind', // 三条 5: 'straight', // 顺子 6: 'flush', // 同花 7: 'fullhouse', // 葫芦 8: 'four of a kind', // 四条 9: 'straight flush', // 同花顺 10: 'royal flush' // 皇家同花顺 }; var Holdem = { HIGH_CARD: 1, ONE_PAIR: 2, TWO_PAIR: 3, THREE: 4, STRAIGHT: 5, FLUSH: 6, FULLHOUSE: 7, FOUR: 8, STRAIGHT_FLUSH: 9, ROYAL_FLUSH: 10, PATTERNS: HOLDEM_PATTERNS, }; exports = module.exports = Holdem; Holdem.sort = function(cards) { if(cards.length != 5) return cards; Poker.sortByNumber(cards); var n0 = cards[0] & 0xf, n1 = cards[1] & 0xf, n2 = cards[2] & 0xf, n3 = cards[3] & 0xf, n4 = cards[4] & 0xf; var d0 = n0 - n1, d1 = n1 - n2, d2 = n2 - n3, d3 = n3 - n4; if((d1 === 0) && (d2 === 0)) { if(d0 === 0) { // XXXXM } else if(d3 === 0) { // MXXXX -> XXXXM cards.push( cards.shift() ); } else { // MXXXN var c0 = cards.shift(); cards.splice(3, 0, c0); } } else if((d0 === 0) && (d1 === 0)) { // XXXMN, or XXXMM } else if((d2 === 0) && (d3 === 0)) { // MNXXX -> XXXMN cards.push( cards.shift() ); cards.push( cards.shift() ); } else if((d0 === 0) && (d2 === 0)) { //edit by kalbas d1->d2 // XXYYM } else if((d0 === 0) && (d3 === 0)) { // XXMYY -> XXYYM var c2 = cards[2]; cards.splice(2, 1); cards.push( c2 ); } else if((d1 === 0) && (d3 === 0)) { // MXXYY -> XXYYM cards.push( cards.shift() ); } else if(d0 === 0) { // XXABC } else if(d1 === 0) { // AXXBC -> XXABC var c_0 = cards.shift(); cards.splice(2, 0, c_0); } else if(d2 === 0) { // ABXXC -> XXABC var c_2 = cards[2], c_3 = cards[3]; cards.splice(2, 2); cards.unshift(c_3); cards.unshift(c_2); } else if(d3 === 0) { //edit by kalbas added d3 condition // ABCXX -> XXABC cards.push( cards.shift() ); cards.push( cards.shift() ); cards.push( cards.shift() ); } else { // ABCDE } return cards; }; Holdem.rank = function(cards) { if(cards.length != 5) return 0; Holdem.sort(cards); var c0 = cards[0] >> 4, c1 = cards[1] >> 4, c2 = cards[2] >> 4, c3 = cards[3] >> 4, c4 = cards[4] >> 4; var n0 = cards[0] & 0xf, n1 = cards[1] & 0xf, n2 = cards[2] & 0xf, n3 = cards[3] & 0xf, n4 = cards[4] & 0xf; var d0 = n0 - n1, d1 = n1 - n2, d2 = n2 - n3, d3 = n3 - n4; var isFlush = ((c0 === c1) && (c1 === c2) && (c2 === c3) && (c3 === c4)); var isStraight; if ((n0 === 14) && (d0 === 9)){ isStraight = ((n0 === 14) && (d0 === 9) && (d1 === 1) && (d2 === 1) && (d3 === 1)); // edited by kalbas A 5 4 3 2 1 straight } else { isStraight = ((d0 === 1) && (d1 === 1) && (d2 === 1) && (d3 === 1)); } var rank = (n0 << 16) | (n1 << 12) | (n2 << 8) | (n3 << 4) | n4; //edit by kalbas //if we face an A5432 straight we should n0=1 and then calculate the rank if ((n0 === 14) && (d0 === 9) && (d1 === 1) && (d2 === 1) && (d3 === 1)) { var exceptionaln0 = 1; rank = (exceptionaln0 << 16) | (n1 << 12) | (n2 << 8) | (n3 << 4) | n4; } //end edit by kalbas var pattern = 0; if(isFlush && isStraight) { if(n4 === 10) { // Poker.NUMBER_RANK['A'] // edited by kalbas, n0=14 can be A5432 too, we use n4=11=jack pattern = ROYAL_FLUSH; } else { pattern = STRAIGHT_FLUSH; } } else if((d0 === 0) && (d1 === 0) && (d2 === 0)) { pattern = FOUR; } else if((d0 === 0) && (d1 === 0) && (d3 === 0)) { pattern = FULLHOUSE; } else if(isFlush) { pattern = FLUSH; } else if(isStraight) { pattern = STRAIGHT; } else if((d0 === 0) && (d1 === 0)) { pattern = THREE; } else if((d0 === 0) && (d2 === 0)) { pattern = TWO_PAIR; } else if((d0 === 0)) { pattern = ONE_PAIR; } else { pattern = HIGH_CARD; } return (pattern << 20) | rank; }; /* * 如有两名以上的牌手在最后一轮下注结束时仍未盖牌,则须进行斗牌。 * 斗牌时,每名牌手以自己的两张底牌,加上桌面五张公共牌,共七张牌中,取最大的五张牌组合决定胜负. * 当中可包括两张或一张底牌,甚至只有公共牌。 */ Holdem.maxFive = function(private_cards, shared_cards) { var cards = Poker.sort( Poker.merge( Poker.clone(private_cards), shared_cards ) ); var len = cards.length; if(len < 5 || len > 7 ) return null; var maxrank = 0, maxcards = null, i, j, tmp, tmprank; if(len === 5) { return cards; } else if(len === 6) { for(j=0; j<6; j++) { tmp = Poker.clone(cards); tmp.splice(j, 1); tmprank = Holdem.rank( tmp ); if(tmprank > maxrank) { maxrank = tmprank; maxcards = tmp; } } } else if(len === 7) { /* for(i=0; i<7; i++) { for(j=0; j<6; j++) { tmp = Poker.clone(cards); tmp.splice(i, 1); tmp.splice(j, 1); tmprank = Holdem.rank( tmp ); if(tmprank > maxrank) { maxrank = tmprank; maxcards = tmp; } } } */ // edit start by kalbas // we rank only board cards at first, all 5 of them tmprank = Holdem.rank( shared_cards ); if(tmprank > maxrank) { maxrank = tmprank; maxcards = shared_cards; } // we rank 1st hole card + 4 board cards for(j=0; j<5; j++) { tmp = Poker.clone( shared_cards ); tmp.splice(j,1); tmp.push( private_cards[0] ); tmprank = Holdem.rank( tmp ); if(tmprank > maxrank) { maxrank = tmprank; maxcards = tmp; } } // we rank 2nd hole card + 4 board cards for(j=0; j<5; j++) { tmp = Poker.clone( shared_cards ); tmp.splice(j,1); tmp.push( private_cards[1] ); tmprank = Holdem.rank( tmp ); if(tmprank > maxrank) { maxrank = tmprank; maxcards = tmp; } } // we rank two hole cards + 3 board cards var iii = [1,1,1,1,1,1,2,2,2,3]; var jjj = [2,2,2,3,3,4,3,3,4,4]; var kkk = [3,4,5,4,5,5,4,5,5,5]; /* There are 10 ways to choose 3 cards out of 5, (5x4x3)/(3x2x1) 123(45) 124(35) 125(34) 134(25) 135(24) 145(23) 234(15) 235(14) 245(13) 345(12) therefore: push : iii[n] + jjj[n] + kkk[n] and then add two hole cards */ for(j=0; j<10; j++) { tmp = []; tmp.push( shared_cards[iii[j]-1] ); tmp.push( shared_cards[jjj[j]-1] ); tmp.push( shared_cards[kkk[j]-1] ); tmp.push( private_cards[0] ); tmp.push( private_cards[1] ); tmprank = Holdem.rank( tmp ); if(tmprank > maxrank) { maxrank = tmprank; maxcards = tmp; } } cards = maxcards; console.log(Poker.visualize(cards)+' : '+Holdem.patternString(cards)); // end edit by kalbas } return maxcards; }; Holdem.pattern = function(cards) { return Holdem.rank(cards) >> 20; }; Holdem.patternString = function(cards) { return HOLDEM_PATTERNS[ Holdem.rank(cards) >> 20 ]; }; Holdem.compare = function(a, b) { return Holdem.rank(a) - Holdem.rank(b); }; Holdem.view = function(cards) { var rank = Holdem.rank(cards); var pattern = rank >> 20; var str = Poker.visualize(cards).join(',') + ' -> ' + HOLDEM_PATTERNS[ pattern ] + ', rank:' + rank; console.log( str ); };