diff --git a/README.md b/README.md index 7d5159a..8a156d3 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,14 @@ const rules = { } ``` +## betting strategies + +Several betting strategies are included: + +* `minPassLineOnly` – always keep the table minimum on the pass line +* `minPassLineMidOdds` – take about half of the allowed odds when a point is set +* `minPassLineMaxOdds` – always take the maximum odds allowed + ## 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. diff --git a/betting.js b/betting.js index 47623f4..e6cfd94 100644 --- a/betting.js +++ b/betting.js @@ -35,7 +35,27 @@ function minPassLineMaxOdds (opts) { return bets } +function minPassLineMidOdds (opts) { + const bets = minPassLineOnly(opts) + const { rules, hand } = opts + + if (process.env.DEBUG) console.log(`[decision] make a new pass odds bet?: ${!hand.isComeOut} && ${!bets?.pass?.odds}`) + + if (hand.isComeOut === false && !bets?.pass?.odds) { + const maxMultiple = rules.maxOddsMultiple[hand.point] + const oddsMultiple = Math.ceil(maxMultiple / 2) + const oddsAmount = oddsMultiple * bets.pass.line.amount + bets.pass.odds = { + amount: oddsAmount + } + bets.new += oddsAmount + } + + return bets +} + module.exports = { minPassLineOnly, - minPassLineMaxOdds + minPassLineMaxOdds, + minPassLineMidOdds } diff --git a/betting.test.js b/betting.test.js index 1387e26..36d3c86 100644 --- a/betting.test.js +++ b/betting.test.js @@ -209,3 +209,81 @@ tap.test('minPassLineMaxOdds: continue existing bet', (t) => { t.end() }) + +tap.test('minPassLineMidOdds: make new bet upon establishing point', (t) => { + const rules = { + minBet: 5, + maxOddsMultiple: { + 4: 3, + 5: 4, + 6: 5, + 8: 5, + 9: 4, + 10: 3 + } + } + + const hand = { + isComeOut: false, + result: 'point set', + point: 5 + } + + const bets = { + pass: { + line: { + amount: 5, + isContract: true + } + } + } + + const expected = Math.ceil(rules.maxOddsMultiple['5'] / 2) * rules.minBet + const updatedBets = lib.minPassLineMidOdds({ rules, bets, hand }) + t.equal(updatedBets.pass.line.amount, rules.minBet, 'line bet is not changed') + t.equal(updatedBets.pass.odds.amount, expected, 'odds bet made properly') + t.equal(updatedBets.new, updatedBets.pass.odds.amount) + + t.end() +}) + +tap.test('minPassLineMidOdds: continue existing bet', (t) => { + const rules = { + minBet: 5, + maxOddsMultiple: { + 4: 3, + 5: 4, + 6: 5, + 8: 5, + 9: 4, + 10: 3 + } + } + + const hand = { + isComeOut: false, + result: 'neutral', + point: 5, + diceSum: 8 + } + + const bets = { + pass: { + line: { + amount: 5, + isContract: true + }, + odds: { + amount: Math.ceil(rules.maxOddsMultiple['5'] / 2) * 5, + isContract: false + } + } + } + + const updatedBets = lib.minPassLineMidOdds({ rules, bets, hand }) + t.equal(updatedBets.pass.line.amount, bets.pass.line.amount, 'line bet is not changed') + t.equal(updatedBets.pass.odds.amount, bets.pass.odds.amount, 'odds bet is not changed') + t.notOk(updatedBets.new, 'no new bets were made') + + t.end() +}) diff --git a/index.test.js b/index.test.js index 064c877..bd22f3b 100644 --- a/index.test.js +++ b/index.test.js @@ -496,3 +496,46 @@ tap.test('integration: minPassLineMaxOdds, one hand with everything', (suite) => suite.end() }) + +tap.test('integration: minPassLineMidOdds, one hand with everything', (suite) => { + let rollCount = -1 + const fixedRolls = [ + 4, 3, // comeout win + 5, 6, // comeout win + 1, 1, // comeout loss + 1, 2, // comeout loss + 6, 6, // comeout loss + 3, 3, // point set + 4, 1, // neutral + 2, 4, // point win + 4, 4, // point set + 3, 4 // seven out + ] + + function testRoll () { + rollCount++ + if (!fixedRolls[rollCount]) { + console.log('falsy return from fixed dice') + process.exit(1) + } + return fixedRolls[rollCount] + } + + const rules = { + minBet: 5, + maxOddsMultiple: { + 4: 3, + 5: 4, + 6: 5, + 8: 5, + 9: 4, + 10: 3 + } + } + + const hand = lib.playHand({ rules, roll: testRoll, bettingStrategy: betting.minPassLineMidOdds }) + suite.ok(Array.isArray(hand.history)) + suite.ok(typeof hand.balance === 'number') + + suite.end() +})