Skip to content

tphummel/node-craps

Repository files navigation

node-craps

Github Workflow Status

🎲🎲 craps simulator πŸ’΅

architecture overview

                        +-----------+
                        | hands.js  | CLI: simulate hands, show roll-by-roll detail
                        +-----------+
                        | monte-    |
                        | carlo.js  | CLI: run trials, summarize distributions
                        +-----------+
                               |
                               v
  +-----------------------------------------------------+
  | playHand() (index.js)                               |
  |-----------------------------------------------------|
  | β€’ apply betting strategy from betting.js            |
  | β€’ roll dice via shoot()/rollD6                      |
  | β€’ settle bets with settle.all() from settle.js      |
  +-----------------------------------------------------+
           |                |                    |
           v                v                    v
      +---------+     +--------------+     +--------------+
      | shoot() |     | betting.js   |     |  settle.js   |
      | rollD6  |     | strategies   |     | payout logic |
      +---------+     +--------------+     +--------------+

betting strategies

All strategies share the same calling convention and are exported from betting.js:

function myStrategy ({ rules, bets, hand, playerMind }) { ... }

base strategies

strategy description
noBetting Makes no bets. Useful as a baseline or placeholder.
minPassLineOnly Pass line bet at minBet on each come-out. No odds.
minPassLineMaxOdds Pass line at minBet + max odds behind the line once a point is set.
minPassLineMidOdds Pass line at minBet + mid odds behind the line once a point is set. Odds multiple is Math.ceil(maxOddsMultiple / 2).
minPassLineMinOdds Pass line at minBet + min odds behind the line once a point is set. Rounds up to nearest $5 for points 6/8, nearest even number for points 5/9, exact minBet for points 4/10.
placeSixEight Place the 6 and 8 at the nearest multiple of $6 β‰₯ minBet. No pass line. Bets come down on a win and are re-placed next turn.
minComeLineMaxOdds One come bet at minBet with max odds once it travels to a point.

variants

strategy description
placeSixEightUnlessPoint Same as placeSixEight but skips whichever number is the current point (avoids redundant coverage).
placeSixEightUnlessPassOrCome Same as placeSixEight but skips any number already covered by a pass or come bet.

composed strategies

strategy description
minPassLinePlaceSixEight Pass line + place 6 and 8 (skips whichever is the point).
minPassLineMaxOddsPlaceSixEight Pass line + max odds + place 6 and 8 (skips point).
minPassLineMaxOddsMinComeLineMaxOdds Pass line + max odds + one come bet with max odds behind each.
passCome68 Pass line + max odds + one come bet with max odds + place 6/8 (skips numbers covered by pass or come).
passcome2place68 Pass line + max odds + up to two come bets with max odds + place 6/8 (skips covered numbers).

stateful strategies

These strategies track state across rolls within a hand via playerMind.

strategy description
pressPlaceSixEight Place 6 and 8. On each win, press the winning number by one $6 unit. Starts at Math.ceil(minBet/6)*6. Resets each hand.
fiveCountMinPassLineMaxOddsPlaceSixEight Applies the five-count gate before engaging minPassLineMaxOddsPlaceSixEight. Waits for a new shooter to establish a point (count 1) then survive four more qualifying rolls (counts 2–5) before any bets are placed.

simulate a hand

node hands.js <numHands> <strategy> [detail]
$ node hands.js 1 pressPlaceSixEight
Simulating 1 Craps Hand(s)
Using betting strategy: pressPlaceSixEight
[table rules] minimum bet: $15

Dice Roll Distribution
...

Session Summary
...

Hands Summary
...

Pass detail as a third argument to print a roll-by-roll table for each hand:

$ node hands.js 1 pressPlaceSixEight detail
Hand: 1, Balance: $81
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ (index) β”‚ passLine β”‚ placeBets     β”‚ moneyInPlay β”‚ roll       β”‚ result      β”‚ wins              β”‚ losses                     β”‚ netChange β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 0       β”‚ ''       β”‚ ''            β”‚ '$0'        β”‚ '10 (4,6)' β”‚ 'point set' β”‚ ''                β”‚ ''                         β”‚ '$0'      β”‚
β”‚ 1       β”‚ ''       β”‚ '6:$18 8:$18' β”‚ '$36'       β”‚ '8 (2,6)'  β”‚ 'neutral'   β”‚ 'place 8 win:$39' β”‚ ''                         β”‚ '$39'     β”‚
β”‚ 2       β”‚ ''       β”‚ '6:$18 8:$24' β”‚ '$42'       β”‚ '8 (3,5)'  β”‚ 'neutral'   β”‚ 'place 8 win:$52' β”‚ ''                         β”‚ '$52'     β”‚
β”‚ 3       β”‚ ''       β”‚ '6:$18 8:$30' β”‚ '$48'       β”‚ '6 (2,4)'  β”‚ 'neutral'   β”‚ 'place 6 win:$39' β”‚ ''                         β”‚ '$39'     β”‚
β”‚ ...     β”‚ ...      β”‚ ...           β”‚ ...         β”‚ ...        β”‚ ...         β”‚ ...               β”‚ ...                        β”‚ ...       β”‚
β”‚ 18      β”‚ ''       β”‚ '6:$24 8:$42' β”‚ '$66'       β”‚ '7 (1,6)'  β”‚ 'seven out' β”‚ ''                β”‚ 'place-6:$24, place-8:$42' β”‚ '$-66'    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The placeBets column shows each number and its current bet size β€” you can see pressing in action as the amounts grow after each win.

monte carlo simulation

Run many trials to see how a strategy performs over time.

node monte-carlo.js <trials> <handsPerTrial> <startingBankroll> <minBet> <oddsFormat> [strategy]

Odds format is X-Y-Z where X = odds on 4/10, Y = odds on 5/9, Z = odds on 6/8. Defaults to 3-4-5. Strategy defaults to minPassLineMaxOddsPlaceSixEight.

$ node monte-carlo.js 5 10 500 15 3-4-5 pressPlaceSixEight
Running 5 trials with 10 hand(s) each
[table rules] minimum bet: $15, odds 3-4-5
betting strategy: pressPlaceSixEight

Trial Results
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”
β”‚ (index) β”‚ trial β”‚ balance β”‚ rolls β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 0       β”‚ 1     β”‚ 872     β”‚ 97    β”‚
β”‚ 1       β”‚ 2     β”‚ 407     β”‚ 107   β”‚
β”‚ 2       β”‚ 3     β”‚ 185     β”‚ 51    β”‚
β”‚ 3       β”‚ 4     β”‚ 900     β”‚ 120   β”‚
β”‚ 4       β”‚ 5     β”‚ 348     β”‚ 79    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”˜

Final Balance Summary
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”
β”‚ (index) β”‚ stat   β”‚ value β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 0       β”‚ 'min'  β”‚ 185   β”‚
β”‚ 5       β”‚ 'p50'  β”‚ 407   β”‚
β”‚ 6       β”‚ 'mean' β”‚ 542.4 β”‚
β”‚ 11      β”‚ 'max'  β”‚ 900   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”˜
stdDev: 324.18
95% CI: [258.24, 826.56]

Individual trial rows are omitted when trials exceeds 100. The standard deviation shows how widely results vary around the mean. The 95% confidence interval is the range expected to contain the true mean in 95% of repeated samples.

table rules

playHand accepts a rules object. Defaults:

const defaultRules = {
  comeOutLoss: [2, 3, 12],
  comeOutWin: [7, 11],
  placeBetsOffOnComeOut: true  // place bets do not win or lose on come-out rolls
}

minBet and maxOddsMultiple are also accepted (required by strategies that use them):

const rules = {
  minBet: 15,
  maxOddsMultiple: {
    4: 3, 5: 4, 6: 5,
    8: 5, 9: 4, 10: 3
  }
}

customizing come-out numbers

// make boxcars (12) a come-out win instead of a loss
const rules = {
  comeOutLoss: [2, 3],
  comeOutWin: [7, 11, 12]
}

place bet working flag

Individual place bets can override the table placeBetsOffOnComeOut rule using a working flag:

// this bet is active even on come-out rolls, regardless of table rule
bets.place.six = { amount: 18, working: true }

// this bet is off on come-out rolls, even if the table rule allows it
bets.place.six = { amount: 18, working: false }

use as a module

import { simulateHands } from './hands.js'
const { sessionSummary } = simulateHands({ numHands: 100, bettingStrategy: 'pressPlaceSixEight' })
console.log(sessionSummary)
import { monteCarlo } from './monte-carlo.js'
import { playHand } from './index.js'
import * as betting from './betting.js'

const rules = { minBet: 15, maxOddsMultiple: { 4: 3, 5: 4, 6: 5, 8: 5, 9: 4, 10: 3 } }
const results = monteCarlo({
  trials: 1000,
  handsPerTrial: 20,
  startingBankroll: 500,
  rules,
  bettingStrategy: betting.pressPlaceSixEight
})

what? why?

I like to play craps sometimes. I have a handful of strategies I like to play. It is time consuming to play in an app. I'd like to play 5, 50, 500 hands very fast using various strategies. Which strategies are best is well understood, the variability comes in with how aggressive your strategies are and the level of risk you assume at any given moment. And of course the dice outcomes and their deviation from long term probabilities and how they interact with the strategies you employ is the fun part. This simulator lets me scratch my craps itch very quickly.

dev

git clone git@github.com:tphummel/node-craps.git
cd node-craps
npm i
npm t

About

🎲🎲 craps simulator πŸ’΅

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Contributors