Uses Monte Carlo simulation to estimate win probability of any poker hand.
Check it out in action at https://emileindik.com/projects/poker.html (Heroku will probably be sleepy and need to wake up, so give it a minute)
npm install poker-odds-machine
const Calculator = require('poker-odds-machine').Calculator;
const input = {
/**
* Hands of players, following the syntax below.
* A player can have a partial hand (one card specified) in order
* to have their next card randomly selected.
* If hands option not supplied, then numPlayers must be provided.
*/
hands: ['Ac,Kc', '2h,7d', 'Js'],
/**
* If not supplied, defaults to length of hands array.
* For every player above the length of hands array,
* a NPC will be created and dealt random cards.
*/
numPlayers: 4,
/**
* Defaults to empty board, which is populated with number of
* cards specified in boardSize option.
*/
board: 'Td,2d,Qc',
/**
* Defaults to 5.
*/
boardSize: 5,
/**
* Defaults to 2.
*/
handSize: 2,
/**
* Defaults to 1.
*/
numDecks: 1,
/**
* If true, returns additional data containing stats on each player's winning hands.
* Defaults to false.
*/
returnHandStats: true,
/**
* If true, returns additional data containing stats on each player's tied hands.
* Defaults to false.
*/
returnTieHandStats: true,
/**
* Number of iterations in the Monte Carlo simluation to perform.
* The more iterations, the more accurate the returned probabilities,
* but the longer the calculation takes.
* Defaults to 1000.
*/
iterations: 1000000
};
const c = new Calculator(input);
const s = c.simulate();
console.log(s);
Super verbose sample output
{
'Ac,Kc': {
winCount: 280171,
tieCount: 6678,
handStats: {
highCard: { count: 0, percent: 0 },
pair: { count: 95106, percent: 9.5106 },
twoPair: { count: 30744, percent: 3.0744 },
trips: { count: 5180, percent: 0.518 },
straight: { count: 104479, percent: 10.4479 },
flush: { count: 43626, percent: 4.3626 },
fullHouse: { count: 0, percent: 0 },
quads: { count: 0, percent: 0 },
straightFlush: { count: 1036, percent: 0.1036 }
},
tieHandStats: {
highCard: { count: 0, percent: 0 },
pair: { count: 775, percent: 0.0775 },
twoPair: { count: 1603, percent: 0.1603 },
trips: { count: 19, percent: 0.0019 },
straight: { count: 4281, percent: 0.4281 },
flush: { count: 0, percent: 0 },
fullHouse: { count: 0, percent: 0 },
quads: { count: 0, percent: 0 },
straightFlush: { count: 0, percent: 0 }
},
winPercent: 28.0171,
tiePercent: 0.6678
},
'2h,7d': {
winCount: 284788,
tieCount: 17209,
handStats: {
highCard: { count: 0, percent: 0 },
pair: { count: 39160, percent: 3.916 },
twoPair: { count: 140578, percent: 14.0578 },
trips: { count: 48312, percent: 4.8312 },
straight: { count: 0, percent: 0 },
flush: { count: 32751, percent: 3.2751 },
fullHouse: { count: 22944, percent: 2.2944 },
quads: { count: 1043, percent: 0.1043 },
straightFlush: { count: 0, percent: 0 }
},
tieHandStats: {
highCard: { count: 0, percent: 0 },
pair: { count: 2544, percent: 0.2544 },
twoPair: { count: 11370, percent: 1.137 },
trips: { count: 1840, percent: 0.184 },
straight: { count: 0, percent: 0 },
flush: { count: 0, percent: 0 },
fullHouse: { count: 1455, percent: 0.1455 },
quads: { count: 0, percent: 0 },
straightFlush: { count: 0, percent: 0 }
},
winPercent: 28.4788,
tiePercent: 1.7209
},
Js: {
winCount: 191810,
tieCount: 11826,
handStats: {
highCard: { count: 0, percent: 0 },
pair: { count: 54926, percent: 5.4926 },
twoPair: { count: 33710, percent: 3.371 },
trips: { count: 11381, percent: 1.1381 },
straight: { count: 81774, percent: 8.1774 },
flush: { count: 4881, percent: 0.4881 },
fullHouse: { count: 4907, percent: 0.4907 },
quads: { count: 231, percent: 0.0231 },
straightFlush: { count: 0, percent: 0 }
},
tieHandStats: {
highCard: { count: 0, percent: 0 },
pair: { count: 464, percent: 0.0464 },
twoPair: { count: 4559, percent: 0.4559 },
trips: { count: 366, percent: 0.0366 },
straight: { count: 5835, percent: 0.5835 },
flush: { count: 0, percent: 0 },
fullHouse: { count: 602, percent: 0.0602 },
quads: { count: 0, percent: 0 },
straightFlush: { count: 0, percent: 0 }
},
winPercent: 19.181,
tiePercent: 1.1826
},
'NPC 1': {
winCount: 213260,
tieCount: 24612,
handStats: {
highCard: { count: 0, percent: 0 },
pair: { count: 66905, percent: 6.6905 },
twoPair: { count: 76426, percent: 7.6426 },
trips: { count: 21628, percent: 2.1628 },
straight: { count: 10761, percent: 1.0761 },
flush: { count: 24377, percent: 2.4377 },
fullHouse: { count: 12442, percent: 1.2442 },
quads: { count: 671, percent: 0.0671 },
straightFlush: { count: 50, percent: 0.005 }
},
tieHandStats: {
highCard: { count: 0, percent: 0 },
pair: { count: 3783, percent: 0.3783 },
twoPair: { count: 10083, percent: 1.0083 },
trips: { count: 1645, percent: 0.1645 },
straight: { count: 7976, percent: 0.7976 },
flush: { count: 0, percent: 0 },
fullHouse: { count: 1125, percent: 0.1125 },
quads: { count: 0, percent: 0 },
straightFlush: { count: 0, percent: 0 }
},
winPercent: 21.326,
tiePercent: 2.4612
}
}
Disclaimer:
I do not bound the value of most of the options, such as handSize
and boardSize
, on purpose. So have fun messin some shiz up with totally crazy options values, but know I haven't tested this library with outlier options values.
npm install
npm run build
npm test
┌─────────┬─────────────────┬───────────┬─────────────┬─────────┐
│ (index) │ hand │ % hypo │ % estimated │ % error │
├─────────┼─────────────────┼───────────┼─────────────┼─────────┤
│ 0 │ 'highCard' │ 17.41192 │ 17.4821 │ 0.4031 │
│ 1 │ 'pair' │ 43.822546 │ 43.8405 │ 0.041 │
│ 2 │ 'twoPair' │ 23.495536 │ 23.4381 │ -0.2445 │
│ 3 │ 'trips' │ 4.82987 │ 4.815 │ -0.3079 │
│ 4 │ 'straight' │ 4.619382 │ 4.6163 │ -0.0667 │
│ 5 │ 'flush' │ 3.025494 │ 3.0321 │ 0.2183 │
│ 6 │ 'fullHouse' │ 2.596102 │ 2.5828 │ -0.5124 │
│ 7 │ 'quads' │ 0.168067 │ 0.1623 │ -3.4314 │
│ 8 │ 'straightFlush' │ 0.031083 │ 0.0308 │ -0.9105 │
└─────────┴─────────────────┴───────────┴─────────────┴─────────┘
The test calculates estimated probability for all hands and compares them against their true hypothetical value (% hypo).