Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion betting.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,53 @@ function pressPlaceSixEight ({ rules, bets: existingBets, hand, playerMind }) {
return bets
}

function fourBetGrindContinuous (opts) {
const { rules, bets: existingBets = {}, hand } = opts
const bets = Object.assign({ new: 0 }, existingBets)

// On come-out: place don't pass if not present
if (hand.isComeOut) {
if (!bets?.dontPass?.line) {
bets.dontPass = { line: { amount: rules.minBet } }
bets.new += rules.minBet
if (process.env.DEBUG) console.log(`[action] make dont pass line bet $${rules.minBet}`)
}
return bets
}

// Point phase: don't pass is established, work through the sequence
bets.come = bets.come || {}
bets.come.pending = bets.come.pending || []
bets.come.points = bets.come.points || {}
bets.dontCome = bets.dontCome || {}
bets.dontCome.pending = bets.dontCome.pending || []
bets.dontCome.points = bets.dontCome.points || {}

const comePointCount = Object.values(bets.come.points).reduce((sum, arr) => sum + arr.length, 0)
const comePendingCount = bets.come.pending.length
const dontComePointCount = Object.values(bets.dontCome.points).reduce((sum, arr) => sum + arr.length, 0)
const dontComePendingCount = bets.dontCome.pending.length

if (comePendingCount === 0 && comePointCount < 2) {
// Place next come bet (first or second) once none are pending
bets.come.pending.push({ amount: rules.minBet })
bets.new += rules.minBet
if (process.env.DEBUG) console.log(`[action] make come line bet $${rules.minBet} (come point count: ${comePointCount})`)
return bets
}

if (comePointCount >= 2 && comePendingCount === 0 && dontComePointCount === 0 && dontComePendingCount === 0) {
// Both come bets established, now place don't come
bets.dontCome.pending.push({ amount: rules.minBet })
bets.new += rules.minBet
if (process.env.DEBUG) console.log(`[action] make dont come line bet $${rules.minBet}`)
return bets
}

// All four established (or waiting for pending bets to establish) - no new bets
return bets
}

function noBetting () {
return { new: 0 }
}
Expand Down Expand Up @@ -428,6 +475,9 @@ function minDontPassOnly (opts) {
minDontPassOnly.title = "Don't Pass Line Only"
minDontPassOnly.description = "Bet the minimum on the don't pass line each come-out roll."

fourBetGrindContinuous.title = 'Four Bet Grind Continuous'
fourBetGrindContinuous.description = "Places four bets in sequence at table minimum: don't pass, come, come, don't come. Each bet is placed only after the previous is established (moved to a point). Once all four are established, no new bets are placed unless one needs to be replaced. Continuous — no per-hand limit on replacement."

export {
noBetting,
minDontPassOnly,
Expand All @@ -447,5 +497,6 @@ export {
minPassLineMaxOddsMinComeLineMaxOdds,
minComeLineMaxOdds,
passCome68,
passcome2place68
passcome2place68,
fourBetGrindContinuous
}
161 changes: 161 additions & 0 deletions betting.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1413,3 +1413,164 @@ tap.test('minPassLineMidOdds: no odds on come-out', (t) => {
t.notOk(result.pass?.odds, 'no odds on come-out')
t.end()
})

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

tap.test('fourBetGrindContinuous: come-out places dont pass', (t) => {
const hand = { isComeOut: true }
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand })

t.equal(bets.dontPass.line.amount, fourBetRules.minBet, "don't pass placed at minBet")
t.equal(bets.new, fourBetRules.minBet)
t.end()
})

tap.test('fourBetGrindContinuous: come-out with existing dont pass does nothing', (t) => {
const hand = { isComeOut: true }
const bets = lib.fourBetGrindContinuous({
rules: fourBetRules,
hand,
bets: { dontPass: { line: { amount: 5 } } }
})

t.equal(bets.new, 0, 'no new bets when dont pass already placed')
t.end()
})

tap.test('fourBetGrindContinuous: point phase places first come bet', (t) => {
const hand = { isComeOut: false, point: 6 }
const existingBets = { dontPass: { line: { amount: 5 } } }
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.come.pending.length, 1, 'one come bet pending')
t.equal(bets.come.pending[0].amount, fourBetRules.minBet)
t.equal(bets.new, fourBetRules.minBet)
t.end()
})

tap.test('fourBetGrindContinuous: waits while come bet is pending', (t) => {
const hand = { isComeOut: false, point: 6 }
const existingBets = {
dontPass: { line: { amount: 5 } },
come: { pending: [{ amount: 5 }], points: {} }
}
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.come.pending.length, 1, 'still only one pending come bet')
t.equal(bets.new, 0, 'no new bets while pending')
t.end()
})

tap.test('fourBetGrindContinuous: one come established places second come bet', (t) => {
const hand = { isComeOut: false, point: 6 }
const existingBets = {
dontPass: { line: { amount: 5 } },
come: { pending: [], points: { 4: [{ line: { amount: 5 } }] } }
}
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.come.pending.length, 1, 'second come bet pending')
t.equal(bets.new, fourBetRules.minBet)
t.end()
})

tap.test('fourBetGrindContinuous: waits while second come bet is pending', (t) => {
const hand = { isComeOut: false, point: 6 }
const existingBets = {
dontPass: { line: { amount: 5 } },
come: { pending: [{ amount: 5 }], points: { 4: [{ line: { amount: 5 } }] } }
}
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.come.pending.length, 1, 'still only one pending')
t.equal(bets.new, 0)
t.end()
})

tap.test('fourBetGrindContinuous: two come bets established places dont come', (t) => {
const hand = { isComeOut: false, point: 6 }
const existingBets = {
dontPass: { line: { amount: 5 } },
come: { pending: [], points: { 4: [{ line: { amount: 5 } }], 9: [{ line: { amount: 5 } }] } }
}
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.dontCome.pending.length, 1, "don't come pending")
t.equal(bets.dontCome.pending[0].amount, fourBetRules.minBet)
t.equal(bets.new, fourBetRules.minBet)
t.end()
})

tap.test('fourBetGrindContinuous: waits while dont come is pending', (t) => {
const hand = { isComeOut: false, point: 6 }
const existingBets = {
dontPass: { line: { amount: 5 } },
come: { pending: [], points: { 4: [{ line: { amount: 5 } }], 9: [{ line: { amount: 5 } }] } },
dontCome: { pending: [{ amount: 5 }], points: {} }
}
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.dontCome.pending.length, 1, 'still only one pending dont come')
t.equal(bets.new, 0)
t.end()
})

tap.test('fourBetGrindContinuous: all four established - no new bets', (t) => {
const hand = { isComeOut: false, point: 6 }
const existingBets = {
dontPass: { line: { amount: 5 } },
come: { pending: [], points: { 4: [{ line: { amount: 5 } }], 9: [{ line: { amount: 5 } }] } },
dontCome: { pending: [], points: { 8: [{ line: { amount: 5 } }] } }
}
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.new, 0, 'no bets when all four established')
t.end()
})

tap.test('fourBetGrindContinuous: replaces lost come bet', (t) => {
const hand = { isComeOut: false, point: 6 }
// One come bet was won/lost, only one remains
const existingBets = {
dontPass: { line: { amount: 5 } },
come: { pending: [], points: { 4: [{ line: { amount: 5 } }] } },
dontCome: { pending: [], points: { 8: [{ line: { amount: 5 } }] } }
}
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.come.pending.length, 1, 'replacement come bet placed')
t.equal(bets.new, fourBetRules.minBet)
t.end()
})

tap.test('fourBetGrindContinuous: replaces lost dont come bet', (t) => {
const hand = { isComeOut: false, point: 6 }
// Don't come was lost (its point was rolled), two come bets still established
const existingBets = {
dontPass: { line: { amount: 5 } },
come: { pending: [], points: { 4: [{ line: { amount: 5 } }], 9: [{ line: { amount: 5 } }] } },
dontCome: { pending: [], points: {} }
}
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.dontCome.pending.length, 1, "replacement don't come placed")
t.equal(bets.new, fourBetRules.minBet)
t.end()
})

tap.test('fourBetGrindContinuous: new come-out after point win places dont pass', (t) => {
const hand = { isComeOut: true }
// After a point win: dont pass was settled out, come bets may remain
const existingBets = {
come: { pending: [], points: { 9: [{ line: { amount: 5 } }] } },
dontCome: { pending: [], points: { 8: [{ line: { amount: 5 } }] } }
}
const bets = lib.fourBetGrindContinuous({ rules: fourBetRules, hand, bets: existingBets })

t.equal(bets.dontPass.line.amount, fourBetRules.minBet, "don't pass re-placed on new come-out")
t.equal(bets.new, fourBetRules.minBet)
t.end()
})
Loading