Skip to content

Commit fa877b6

Browse files
committed
omaha hold'em
1 parent f6dff13 commit fa877b6

File tree

3 files changed

+238
-3
lines changed

3 files changed

+238
-3
lines changed

pokersolver.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* http://goldfirestudios.com
55
*/
66

7+
var percom = require('percom');
8+
79
(function() {
810
'use strict';
911

@@ -1824,10 +1826,52 @@
18241826
}
18251827
}
18261828

1829+
class OmahaGame {
1830+
/**
1831+
* Build and return the best hand for Omaha Hold'em.
1832+
* @param {Array} boardCards Array of board cards (['Ad', '3c', 'Th', ...]).
1833+
* @param {Array} playerCards Array of player's cards (['Ad', '3c', 'Th', ...]).
1834+
* @return {Hand} Best hand.
1835+
*/
1836+
static solve(boardCards, playerCards) {
1837+
const game = new Game('standard');
1838+
1839+
var boardCombinations = percom.com(boardCards, 3);
1840+
var playerCombinations = percom.com(playerCards, 2);
1841+
var allCombinations = boardCombinations.reduce(function (res, b) {
1842+
return res.concat(
1843+
playerCombinations.map(function (p) {
1844+
return b.concat(...p);
1845+
})
1846+
);
1847+
}, []);
1848+
1849+
var hands = game.handValues;
1850+
var result = null;
1851+
1852+
for (var j = 0; j < allCombinations.length; j++) {
1853+
var combinationResult = null;
1854+
var cards = allCombinations[j];
1855+
for (var i = 0; i < hands.length; i++) {
1856+
combinationResult = new hands[i](cards, game);
1857+
if (combinationResult.isPossible) {
1858+
break;
1859+
}
1860+
}
1861+
if (!result || result.compare(combinationResult) > 0) {
1862+
result = combinationResult;
1863+
}
1864+
}
1865+
1866+
return result;
1867+
}
1868+
}
1869+
18271870
function exportToGlobal(global) {
18281871
global.Card = Card;
18291872
global.Hand = Hand;
18301873
global.Game = Game;
1874+
global.OmahaGame = OmahaGame;
18311875
global.RoyalFlush = RoyalFlush;
18321876
global.NaturalRoyalFlush = NaturalRoyalFlush;
18331877
global.WildRoyalFlush = WildRoyalFlush;

test/omaha.js

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
var Flush = require('../pokersolver').Flush;
2+
var StraightFlush = require('../pokersolver').StraightFlush;
3+
var Straight = require('../pokersolver').Straight;
4+
var FourOfAKind = require('../pokersolver').FourOfAKind;
5+
var FullHouse = require('../pokersolver').FullHouse;
6+
var ThreeOfAKind = require('../pokersolver').ThreeOfAKind;
7+
var TwoPair = require('../pokersolver').TwoPair;
8+
var OnePair = require('../pokersolver').OnePair;
9+
var OmahaGame = require('../pokersolver').OmahaGame;
10+
11+
describe('A basic hand', function () {
12+
var boardCards = ['As', '4h', 'Kd', '3h', '5h'];
13+
var playerCards = ['Ah', 'Ks', '4d', '2h'];
14+
it('should return a hand with cards sorted descending', function () {
15+
var hand = OmahaGame.solve(boardCards, playerCards);
16+
hand.cardPool[0].toString().should.equal('Ah');
17+
return hand.cardPool[4].toString().should.equal('2h');
18+
});
19+
it('should return a correct description', function () {
20+
var hand = OmahaGame.solve(boardCards, playerCards);
21+
return hand.descr.should.equal('Straight Flush, 5h High');
22+
});
23+
return it('should return throw an Error for a hand with duplicate cards', function () {
24+
(function () {
25+
var playerCards = ['As', 'Ah', 'Ks', '4d'];
26+
OmahaGame.solve(boardCards, playerCards);
27+
}.should.throw());
28+
});
29+
});
30+
31+
describe('A Straight Flush', function () {
32+
it('should be detected as possible', function () {
33+
var boardCards = ['As', '4h', 'Kd', '3h', '5h'];
34+
var playerCards = ['Ah', 'Ks', '4d', '2h'];
35+
var hand = OmahaGame.solve(boardCards, playerCards);
36+
return hand.should.be.an.instanceOf(StraightFlush);
37+
});
38+
it('should be detected as not possible', function () {
39+
var boardCards = ['Ah', '4h', 'Kd', '3h', '5h'];
40+
var playerCards = ['As', 'Ks', '4d', '2h'];
41+
var hand = OmahaGame.solve(boardCards, playerCards);
42+
return hand.should.not.be.an.instanceOf(StraightFlush);
43+
});
44+
return it('should return 5 cards with low ace', function () {
45+
var boardCards = ['Ah', '4h', 'Kd', '3h', '5h'];
46+
var playerCards = ['As', 'Ks', '4d', '2h'];
47+
var hand = OmahaGame.solve(boardCards, playerCards);
48+
return hand.cards.length.should.equal(5);
49+
});
50+
});
51+
52+
describe('A Four of a Kind', function () {
53+
it('should be detected as possible', function () {
54+
var boardCards = ['Ah', '4h', 'Kd', 'Ad', '5h'];
55+
var playerCards = ['As', 'Ac', '4d', '2h'];
56+
var hand = OmahaGame.solve(boardCards, playerCards);
57+
return hand.should.be.an.instanceOf(FourOfAKind);
58+
});
59+
return it('should be detected as not possible', function () {
60+
var boardCards = ['Ah', '4h', 'Kd', '4d', '5h'];
61+
var playerCards = ['As', 'Ac', 'Ad', '2h'];
62+
var hand = OmahaGame.solve(boardCards, playerCards);
63+
return hand.should.not.be.an.instanceOf(FourOfAKind);
64+
});
65+
});
66+
67+
describe('A Full House', function () {
68+
it('should be detected as possible', function () {
69+
var boardCards = ['Ah', '4h', '5d', 'Kd', '5h'];
70+
var playerCards = ['As', '5c', '4d', '2h'];
71+
var hand = OmahaGame.solve(boardCards, playerCards);
72+
hand.should.be.an.instanceOf(FullHouse);
73+
74+
boardCards = ['Ah', '4h', '5d', 'Ad', '7h'];
75+
playerCards = ['As', '5c', '4d', '2h'];
76+
hand = OmahaGame.solve(boardCards, playerCards);
77+
return hand.should.be.an.instanceOf(FullHouse);
78+
});
79+
it('should be detected as not possible', function () {
80+
var boardCards = ['2h', 'Ac', '4d', 'Kd', '5h'];
81+
var playerCards = ['As', '5c', '5d', 'Ah'];
82+
var hand = OmahaGame.solve(boardCards, playerCards);
83+
return hand.should.not.be.an.instanceOf(FullHouse);
84+
});
85+
it('should pick the high kickers', function () {
86+
var boardCards = ['Ah', '4h', '5d', 'Ad', '7h'];
87+
var playerCards = ['As', '5c', '4d', '2h'];
88+
var hand = OmahaGame.solve(boardCards, playerCards);
89+
return hand.cards.toString().indexOf('4h').should.equal(-1);
90+
});
91+
return it('should be in order', function () {
92+
var boardCards = ['Ah', '4h', '5d', 'Ad', '7h'];
93+
var playerCards = ['As', '5c', '4d', '2h'];
94+
var hand = OmahaGame.solve(boardCards, playerCards);
95+
return hand.cards.toString().should.equal('Ah,Ad,As,5d,5c');
96+
});
97+
});
98+
99+
describe('A Flush', function () {
100+
it('should be detected as possible', function () {
101+
var boardCards = ['2h', 'Ac', '4d', 'Kh', '5h'];
102+
var playerCards = ['As', '4h', '5d', 'Ah'];
103+
var hand = OmahaGame.solve(boardCards, playerCards);
104+
return hand.should.be.an.instanceOf(Flush);
105+
});
106+
return it('should be detected as not possible', function () {
107+
var boardCards = ['2h', 'Ac', '4d', 'Kh', '5d'];
108+
var playerCards = ['As', '4h', '5h', 'Ah'];
109+
var hand = OmahaGame.solve(boardCards, playerCards);
110+
return hand.should.not.be.an.instanceOf(Flush);
111+
});
112+
});
113+
114+
describe('A Straight', function () {
115+
it('should be detected as possible', function () {
116+
var boardCards = ['2h', '3c', '4d', 'Kh', '5h'];
117+
var playerCards = ['7s', '6c', '5d', 'Ah'];
118+
var hand = OmahaGame.solve(boardCards, playerCards);
119+
return hand.should.be.an.instanceOf(Straight);
120+
});
121+
it('should be detected as possible', function () {
122+
var boardCards = ['9h', 'Jc', '4d', 'Th', '5h'];
123+
var playerCards = ['As', '7c', '8d', 'Ah'];
124+
var hand = OmahaGame.solve(boardCards, playerCards);
125+
return hand.should.be.an.instanceOf(Straight);
126+
});
127+
it('should be detected as not possible', function () {
128+
var boardCards = ['3h', '3c', '4d', 'Kh', '4h'];
129+
var playerCards = ['7s', '6c', '5d', 'Ah'];
130+
var hand = OmahaGame.solve(boardCards, playerCards);
131+
return hand.should.not.be.an.instanceOf(Straight);
132+
});
133+
it('should detect a low ace', function () {
134+
var boardCards = ['2h', '3c', '4d', 'Kh', '5h'];
135+
var playerCards = ['7s', '7c', '5d', 'Ah'];
136+
var hand = OmahaGame.solve(boardCards, playerCards);
137+
return hand.should.be.an.instanceOf(Straight);
138+
});
139+
it('should detect a high ace', function () {
140+
var boardCards = ['2h', 'Jc', '4d', 'Kh', 'Ah'];
141+
var playerCards = ['7s', 'Tc', 'Qd', 'As'];
142+
var hand = OmahaGame.solve(boardCards, playerCards);
143+
return hand.should.be.an.instanceOf(Straight);
144+
});
145+
});
146+
147+
describe('Three of a Kind', function () {
148+
it('should be detected as possible', function () {
149+
var boardCards = ['2h', '3c', '4d', 'Kh', '7h'];
150+
var playerCards = ['7s', '7c', '8d', 'Ah'];
151+
var hand = OmahaGame.solve(boardCards, playerCards);
152+
return hand.should.be.an.instanceOf(ThreeOfAKind);
153+
});
154+
it('should be detected as not possible', function () {
155+
var boardCards = ['2h', '3c', '4d', 'Kh', '5h'];
156+
var playerCards = ['7s', '7c', '7d', 'Ah'];
157+
var hand = OmahaGame.solve(boardCards, playerCards);
158+
return hand.should.not.be.an.instanceOf(ThreeOfAKind);
159+
});
160+
});
161+
162+
describe('Two Pair', function () {
163+
it('should be detected as possible', function () {
164+
var boardCards = ['2h', 'Jc', '4d', '8h', '8d'];
165+
var playerCards = ['7s', '7c', '9d', 'Ah'];
166+
var hand = OmahaGame.solve(boardCards, playerCards);
167+
return hand.should.be.an.instanceOf(TwoPair);
168+
});
169+
it('should be detected as not possible', function () {
170+
var boardCards = ['2h', '3c', '4d', 'Kh', '5h'];
171+
var playerCards = ['7s', '7c', '5d', 'Jh'];
172+
var hand = OmahaGame.solve(boardCards, playerCards);
173+
return hand.should.not.be.an.instanceOf(TwoPair);
174+
});
175+
});
176+
177+
describe('One Pair', function () {
178+
it('should be detected as possible', function () {
179+
var boardCards = ['2h', '3c', '4d', 'Kh', '8h'];
180+
var playerCards = ['Js', 'Qc', '8d', 'Ac'];
181+
var hand = OmahaGame.solve(boardCards, playerCards);
182+
return hand.should.be.an.instanceOf(OnePair);
183+
});
184+
it('should be detected as not possible', function () {
185+
var boardCards = ['2h', '3c', '4d', 'Kh', '7h'];
186+
var playerCards = ['Js', 'Qc', '8d', 'Ac'];
187+
var hand = OmahaGame.solve(boardCards, playerCards);
188+
return hand.should.not.be.an.instanceOf(OnePair);
189+
});
190+
});

test/test.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
var should = require('should');
22

33
function importTest(name, path) {
4-
describe(name, function() {
4+
describe(name, function () {
55
require(path);
66
});
77
}
88

9-
describe('main', function() {
9+
describe('main', function () {
1010
importTest('Standard', './standard');
11+
importTest('Omaha', './omaha');
1112
importTest('Jacks or Better', './jacksbetter');
1213
importTest('Joker Poker', './joker');
1314
importTest('Deuces Wild', './deuceswild');
1415
importTest('Three Card Poker', './threecard');
1516
importTest('Four Card Poker', './fourcard');
1617
importTest('Four Card Aces Up Bonus', './fourcardbonus');
17-
return importTest('Pai Gow Poker', './paigowpokerfullhands');
18+
importTest('Pai Gow Poker', './paigowpokerfullhands');
1819
});

0 commit comments

Comments
 (0)