Skip to content

Commit 7553737

Browse files
authored
Merge pull request #22 from tphummel/codex/enable-hands.js-as-cli-and-module
Expose hands.js as module with cli
2 parents fa4ddc3 + a455253 commit 7553737

File tree

2 files changed

+156
-136
lines changed

2 files changed

+156
-136
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ Hand: 1
8888
└─────────┴──────┴──────┴─────────┴─────────────┴───────────┴───────┘
8989
```
9090

91+
## use as a module
92+
93+
```js
94+
const simulateHands = require('./hands.js')
95+
const result = simulateHands(1)
96+
console.log(result.sessionSummary)
97+
```
98+
9199
## table rules
92100

93101
`playHand` accepts a `rules` object that controls minimum bets and odds limits.

hands.js

Lines changed: 148 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,158 +1,170 @@
1+
#!/usr/bin/env node
12
'use strict'
23

34
const { playHand } = require('./index.js')
45
const { minPassLineMaxOddsPlaceSixEight } = require('./betting.js')
56

6-
const numHands = parseInt(process.argv.slice(2)[0], 10)
7-
const showDetail = process.argv.slice(2)[1]
8-
9-
console.log(`Simulating ${numHands} Craps Hand(s)`)
10-
console.log('Using betting strategy: minPassLineMaxOddsPlaceSixEight')
11-
12-
const summaryTemplate = {
13-
balance: 0,
14-
rollCount: 0,
15-
pointsSet: 0,
16-
pointsWon: 0,
17-
comeOutWins: 0,
18-
comeOutLosses: 0,
19-
netComeOutWins: 0,
20-
neutrals: 0,
21-
placeSixWins: 0,
22-
placeSixLosses: 0,
23-
placeEightWins: 0,
24-
placeEightLosses: 0,
25-
dist: {
26-
2: { ct: 0, prob: 1 / 36 },
27-
3: { ct: 0, prob: 2 / 36 },
28-
4: { ct: 0, prob: 3 / 36 },
29-
5: { ct: 0, prob: 4 / 36 },
30-
6: { ct: 0, prob: 5 / 36 },
31-
7: { ct: 0, prob: 6 / 36 },
32-
8: { ct: 0, prob: 5 / 36 },
33-
9: { ct: 0, prob: 4 / 36 },
34-
10: { ct: 0, prob: 3 / 36 },
35-
11: { ct: 0, prob: 2 / 36 },
36-
12: { ct: 0, prob: 1 / 36 }
37-
}
38-
}
39-
40-
const sessionSummary = Object.assign({}, summaryTemplate)
41-
42-
const hands = []
43-
const rules = {
44-
minBet: 10,
45-
maxOddsMultiple: {
46-
4: 3,
47-
5: 4,
48-
6: 5,
49-
8: 5,
50-
9: 4,
51-
10: 3
7+
function simulateHands (numHands, showDetail) {
8+
const summaryTemplate = {
9+
balance: 0,
10+
rollCount: 0,
11+
pointsSet: 0,
12+
pointsWon: 0,
13+
comeOutWins: 0,
14+
comeOutLosses: 0,
15+
netComeOutWins: 0,
16+
neutrals: 0,
17+
placeSixWins: 0,
18+
placeSixLosses: 0,
19+
placeEightWins: 0,
20+
placeEightLosses: 0,
21+
dist: {
22+
2: { ct: 0, prob: 1 / 36 },
23+
3: { ct: 0, prob: 2 / 36 },
24+
4: { ct: 0, prob: 3 / 36 },
25+
5: { ct: 0, prob: 4 / 36 },
26+
6: { ct: 0, prob: 5 / 36 },
27+
7: { ct: 0, prob: 6 / 36 },
28+
8: { ct: 0, prob: 5 / 36 },
29+
9: { ct: 0, prob: 4 / 36 },
30+
10: { ct: 0, prob: 3 / 36 },
31+
11: { ct: 0, prob: 2 / 36 },
32+
12: { ct: 0, prob: 1 / 36 }
33+
}
5234
}
53-
}
54-
55-
console.log(`[table rules] minimum bet: $${rules.minBet}`)
5635

57-
for (let i = 0; i < numHands; i++) {
58-
if (process.env.DEBUG) {
59-
console.log(`\n================ HAND ${i + 1} ================`)
60-
}
61-
const hand = playHand({ rules, bettingStrategy: minPassLineMaxOddsPlaceSixEight })
62-
hand.summary = Object.assign({}, summaryTemplate)
63-
64-
sessionSummary.balance += hand.balance
65-
hand.summary.balance = hand.balance
66-
67-
hand.history.reduce((memo, roll) => {
68-
memo.rollCount++
69-
hand.summary.rollCount++
70-
memo.dist[roll.diceSum].ct++
71-
72-
switch (roll.result) {
73-
case 'neutral':
74-
memo.neutrals++
75-
hand.summary.neutrals++
76-
break
77-
case 'point set':
78-
memo.pointsSet++
79-
hand.summary.pointsSet++
80-
break
81-
case 'point win':
82-
memo.pointsWon++
83-
hand.summary.pointsWon++
84-
break
85-
case 'comeout win':
86-
memo.comeOutWins++
87-
hand.summary.comeOutWins++
88-
memo.netComeOutWins++
89-
hand.summary.netComeOutWins++
90-
break
91-
case 'comeout loss':
92-
memo.comeOutLosses++
93-
hand.summary.comeOutLosses++
94-
memo.netComeOutWins--
95-
hand.summary.netComeOutWins--
96-
break
36+
const sessionSummary = Object.assign({}, summaryTemplate)
37+
const hands = []
38+
const rules = {
39+
minBet: 10,
40+
maxOddsMultiple: {
41+
4: 3,
42+
5: 4,
43+
6: 5,
44+
8: 5,
45+
9: 4,
46+
10: 3
9747
}
48+
}
9849

99-
if (Array.isArray(roll.payouts)) {
100-
roll.payouts.forEach(p => {
101-
if (p.type === 'place 6 win') {
102-
memo.placeSixWins++
103-
hand.summary.placeSixWins++
104-
} else if (p.type === 'place 8 win') {
105-
memo.placeEightWins++
106-
hand.summary.placeEightWins++
107-
}
108-
})
50+
for (let i = 0; i < numHands; i++) {
51+
if (process.env.DEBUG) {
52+
console.log(`\n================ HAND ${i + 1} ================`)
10953
}
54+
const hand = playHand({ rules, bettingStrategy: minPassLineMaxOddsPlaceSixEight })
55+
hand.summary = Object.assign({}, summaryTemplate)
56+
57+
sessionSummary.balance += hand.balance
58+
hand.summary.balance = hand.balance
59+
60+
hand.history.reduce((memo, roll) => {
61+
memo.rollCount++
62+
hand.summary.rollCount++
63+
memo.dist[roll.diceSum].ct++
64+
65+
switch (roll.result) {
66+
case 'neutral':
67+
memo.neutrals++
68+
hand.summary.neutrals++
69+
break
70+
case 'point set':
71+
memo.pointsSet++
72+
hand.summary.pointsSet++
73+
break
74+
case 'point win':
75+
memo.pointsWon++
76+
hand.summary.pointsWon++
77+
break
78+
case 'comeout win':
79+
memo.comeOutWins++
80+
hand.summary.comeOutWins++
81+
memo.netComeOutWins++
82+
hand.summary.netComeOutWins++
83+
break
84+
case 'comeout loss':
85+
memo.comeOutLosses++
86+
hand.summary.comeOutLosses++
87+
memo.netComeOutWins--
88+
hand.summary.netComeOutWins--
89+
break
90+
}
11091

111-
if (roll.result === 'seven out') {
112-
if (roll.betsBefore?.place?.six) {
113-
memo.placeSixLosses++
114-
hand.summary.placeSixLosses++
92+
if (Array.isArray(roll.payouts)) {
93+
roll.payouts.forEach(p => {
94+
if (p.type === 'place 6 win') {
95+
memo.placeSixWins++
96+
hand.summary.placeSixWins++
97+
} else if (p.type === 'place 8 win') {
98+
memo.placeEightWins++
99+
hand.summary.placeEightWins++
100+
}
101+
})
115102
}
116-
if (roll.betsBefore?.place?.eight) {
117-
memo.placeEightLosses++
118-
hand.summary.placeEightLosses++
103+
104+
if (roll.result === 'seven out') {
105+
if (roll.betsBefore?.place?.six) {
106+
memo.placeSixLosses++
107+
hand.summary.placeSixLosses++
108+
}
109+
if (roll.betsBefore?.place?.eight) {
110+
memo.placeEightLosses++
111+
hand.summary.placeEightLosses++
112+
}
119113
}
120-
}
121114

122-
return memo
123-
}, sessionSummary)
115+
return memo
116+
}, sessionSummary)
117+
118+
hands.push(hand)
119+
}
120+
121+
sessionSummary.handCount = hands.length
122+
123+
for (const k of Object.keys(sessionSummary.dist)) {
124+
sessionSummary.dist[k].ref = Number((sessionSummary.dist[k].prob * sessionSummary.rollCount).toFixed(1))
125+
sessionSummary.dist[k].diff = Number((sessionSummary.dist[k].ct - sessionSummary.dist[k].ref).toFixed(1))
126+
sessionSummary.dist[k].diff_pct = Number((((sessionSummary.dist[k].ct - sessionSummary.dist[k].ref) / sessionSummary.dist[k].ref) * 100).toFixed(1))
127+
if (showDetail) {
128+
sessionSummary.dist[k].ref_work = `${(sessionSummary.dist[k].prob * sessionSummary.rollCount).toFixed(1)} (${sessionSummary.rollCount} * ${sessionSummary.dist[k].prob.toFixed(2)})`
129+
}
130+
delete sessionSummary.dist[k].prob
131+
}
124132

125-
hands.push(hand)
133+
return { sessionSummary, hands, rules }
126134
}
127135

128-
sessionSummary.handCount = hands.length
136+
function printResults ({ sessionSummary, hands, showDetail, rules }) {
137+
console.log(`[table rules] minimum bet: $${rules.minBet}`)
138+
139+
console.log('\nDice Roll Distribution')
140+
console.table(sessionSummary.dist)
141+
delete sessionSummary.dist
142+
143+
console.log('\nSession Summary')
144+
console.table(sessionSummary)
145+
146+
console.log('\nHands Summary')
147+
console.table(hands.map(hand => {
148+
delete hand.summary.dist
149+
return hand.summary
150+
}))
129151

130-
for (const k of Object.keys(sessionSummary.dist)) {
131-
sessionSummary.dist[k].ref = Number((sessionSummary.dist[k].prob * sessionSummary.rollCount).toFixed(1))
132-
sessionSummary.dist[k].diff = Number((sessionSummary.dist[k].ct - sessionSummary.dist[k].ref).toFixed(1))
133-
sessionSummary.dist[k].diff_pct = Number((((sessionSummary.dist[k].ct - sessionSummary.dist[k].ref) / sessionSummary.dist[k].ref) * 100).toFixed(1))
134152
if (showDetail) {
135-
sessionSummary.dist[k].ref_work = `${(sessionSummary.dist[k].prob * sessionSummary.rollCount).toFixed(1)} (${sessionSummary.rollCount} * ${sessionSummary.dist[k].prob.toFixed(2)})`
153+
console.log('\nHands')
154+
hands.forEach((hand, handNum) => {
155+
console.log(`\nHand: ${handNum + 1}, Balance: $${hand.balance}`)
156+
console.table(hand.history)
157+
})
136158
}
137-
delete sessionSummary.dist[k].prob
138159
}
139-
console.log('\nDice Roll Distribution')
140-
console.table(sessionSummary.dist)
141-
delete sessionSummary.dist
142-
143-
console.log('\nSession Summary')
144-
console.table(sessionSummary)
145-
146-
console.log('\nHands Summary')
147-
console.table(hands.map(hand => {
148-
delete hand.summary.dist
149-
return hand.summary
150-
}))
151-
152-
if (showDetail) {
153-
console.log('\nHands')
154-
hands.forEach((hand, handNum) => {
155-
console.log(`\nHand: ${handNum + 1}, Balance: $${hand.balance}`)
156-
console.table(hand.history)
157-
})
160+
161+
if (require.main === module) {
162+
const numHands = parseInt(process.argv[2], 10)
163+
const showDetail = process.argv[3]
164+
console.log(`Simulating ${numHands} Craps Hand(s)`)
165+
console.log('Using betting strategy: minPassLineMaxOddsPlaceSixEight')
166+
const result = simulateHands(numHands, showDetail)
167+
printResults({ ...result, showDetail })
168+
} else {
169+
module.exports = simulateHands
158170
}

0 commit comments

Comments
 (0)