-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
82 lines (64 loc) · 1.76 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
"use strict";
const shuffle = require('array-shuffle');
const evaluator = require('poker-evaluator');
const cards = Object.keys(evaluator.CARDS);
const outcomes = {
WIN: 0,
LOSE: 1,
SPLIT: 2
};
/**
* Perform Monte Carlo simulation
*
* @param {Array} hand to evaluate
* @param {Array} cards on the table
* @param {Number} number of players
* @param {Number} number of samples
* @return {Array} est. probability distribution
*/
function monteCarlo (hand, table, players, samples) {
const distribution = [0, 0, 0];
players = players || 2;
samples = samples || 10000;
for (let i = 0; i < samples; i++) {
let outcome = simulate(hand, table, players);
distribution[outcome]++;
}
return distribution.map(n => n / samples);
}
/**
* Simulate a random game and return outcome
*/
function simulate (hand, table, players) {
const hands = [];
let deck = shuffle(cards);
hand = hand.slice();
table = table.slice();
// hand needs 2 cards
while (hand.length < 2) {
hand.push(deck.shift());
}
const full = table.concat(hand);
deck = deck.filter(c => !~full.indexOf(c));
// deal cards to players
for (let i = 1; i < players; i++) {
hands.push(deck.splice(0, 2));
}
// flop, turn, river
while (table.length < 5) {
const card = deck.shift();
table.push(card);
full.push(card);
}
// hand rank
const my = evaluator.evalHand(full);
for (let hand of hands) {
const opponent = evaluator.evalHand(table.concat(hand));
if (opponent.handType < my.handType) continue;
if (opponent.handType > my.handType) return outcomes.LOSE;
if (opponent.handRank > my.handRank) return outcomes.LOSE;
if (opponent.handRank == my.handRank) return outcomes.SPLIT;
}
return outcomes.WIN;
}
module.exports = monteCarlo;