Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow even money with insurance #61

Closed
wants to merge 2 commits into from
Closed
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
12 changes: 7 additions & 5 deletions src/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const getHandInfo = (playerCards: Array<Card>, dealerCards: Array<Card>,
const isClosed = hasBusted || hasBlackjack || handValue.hi === 21
const canDoubleDown = !isClosed && true
const canSplit = playerCards.length > 1 && playerCards[ 0 ].value === playerCards[ 1 ].value && !isClosed
const canInsure = dealerCards[ 0 ].value === 1 && !isClosed
const canInsure = dealerCards[0].value === 1 && playerCards.length === 2
return {
cards: playerCards,
playerValue: handValue,
Expand Down Expand Up @@ -140,7 +140,7 @@ export const getHandInfoAfterDeal = (playerCards: Array<Card>, dealerCards: Arra
}
return {
...hand,
close: hand.playerHasBlackjack
close: hand.playerHasBlackjack && !availableActions.insurance
}
}

Expand Down Expand Up @@ -289,7 +289,7 @@ export const isActionAllowed = (actionName: string, stage: string): boolean => {
}
}

export const getPrize = (playerHand: Hand, dealerCards: Array<Card>): number => {
export const getPrize = (playerHand: Hand, dealerCards: Array<Card>, tookInsurance: boolean): number => {
const {
close = false,
playerHasSurrendered = true,
Expand All @@ -309,7 +309,7 @@ export const getPrize = (playerHand: Hand, dealerCards: Array<Card>): number =>
if (playerHasSurrendered) {
return bet / 2
}
if (playerHasBlackjack && !dealerHasBlackjack) {
if (playerHasBlackjack && (!dealerHasBlackjack || (!dealerHasBlackjack && tookInsurance))) {
return bet + (bet * 1.5)
}
const dealerHasBusted = higherValidDealerValue > 21
Expand All @@ -330,7 +330,9 @@ export const getPrizes = ({ history, handInfo: { left, right }, dealerCards }: {
memo += x.value
return memo
}, 0)
const wonOnRight = getPrize(right, dealerCards)
const insuranceAction = history.find(x => x.type === TYPES.INSURANCE)
const tookInsurance = insuranceAction && insuranceAction.payload.bet > 0
const wonOnRight = getPrize(right, dealerCards, tookInsurance)
const wonOnLeft = getPrize(left, dealerCards)
return {
finalBet: finalBet,
Expand Down
18 changes: 12 additions & 6 deletions src/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export default class Game {
switch (action.type) {
case TYPES.DEAL: {
const { bet, sideBets } = action.payload
const { rules: { insurance }, availableBets, history, hits } = this.state
const { rules: { insurance, evenMoneyInsurance }, availableBets, history, hits } = this.state
const playerCards = this.state.deck.splice(this.state.deck.length - 2, 2)
const dealerCards = this.state.deck.splice(this.state.deck.length - 1, 1)
const dealerHoleCard = this.state.deck.splice(this.state.deck.length - 1, 1)[ 0 ]
Expand Down Expand Up @@ -202,8 +202,13 @@ export default class Game {
hits: hits + 1
})

if (right.playerHasBlackjack) {
// purpose of the game archived !!!
if (
right.playerHasBlackjack &&
(!right.availableActions.insurance ||
(right.availableActions.insurance &&
(!evenMoneyInsurance || dealerValue.lo !== 1)))
) {
// purpose of the game achieved !!!
this._dispatch(actions.showdown())
break
}
Expand All @@ -214,7 +219,7 @@ export default class Game {
}
// else
// in this case, the game must continue in "player-turn-right"
// waiting for the insurance action
// waiting for the insurance action, including even money if enabled
}
break
}
Expand All @@ -227,7 +232,8 @@ export default class Game {
const insurancePrize = (isFirstCardAce && dealerHasBlackjack && insuranceValue > 0 && bet > 0) ? insuranceValue * 3 : 0
const right = this.enforceRules(engine.getHandInfoAfterInsurance(handInfo.right.cards, dealerCards))
right.bet = initialBet
right.close = dealerHasBlackjack
const tookEvenMoney = insuranceValue > 0 && handInfo.right.playerHasBlackjack
right.close = dealerHasBlackjack || tookEvenMoney
const historyItem = appendEpoch({
...action,
payload: { bet: insuranceValue || 0 }
Expand All @@ -244,7 +250,7 @@ export default class Game {
}
}
})
if (dealerHasBlackjack) {
if (dealerHasBlackjack || tookEvenMoney) {
this._dispatch(actions.showdown())
}
break
Expand Down
2 changes: 2 additions & 0 deletions src/presets.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const getRules = ({
doubleAfterSplit = true,
surrender = true,
insurance = true,
evenMoneyInsurance = false,
showdownAfterAceSplit = true
}: Rule) => {
return {
Expand All @@ -49,6 +50,7 @@ export const getRules = ({
doubleAfterSplit: doubleAfterSplit,
surrender: surrender,
insurance: insurance,
evenMoneyInsurance: evenMoneyInsurance,
showdownAfterAceSplit: showdownAfterAceSplit
}
}
Expand Down
1 change: 1 addition & 0 deletions src/types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export type Rule = {
split: boolean,
surrender: boolean,
insurance: boolean,
evenMoneyInsurance: boolean,
showdownAfterAceSplit: boolean
}

Expand Down
111 changes: 110 additions & 1 deletion test/game.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,115 @@ describe('Game flow', function () {
assert.equal(wonOnLeft, 20, 'won 20 on left')
assert.equal(wonOnRight, 20, 'won 20 on right')
})
describe('# even money dealer BJ', () => {
const test = {
cards: '♦10 ♥1 ♠10 ♠1'
}
it(`INSURANCE ON AND EVEN_MONEY ON ${
test.cards
}, insure YES, and finish`, () => {
const testActions = ['restore', 'deal', 'insuranceYes']
const rules = { insurance: true, evenMoneyInsurance: true }
const state = executeFlow(
rules,
test.cards,
testActions.map(x => functions[x])
)
const {
finalBet,
wonOnRight,
handInfo: { right },
sideBetsInfo: {
insurance: { win }
}
} = state
assert.equal(
state.stage,
'done',
'blackjack but insurance is ON and first card is ♥1'
)
assert.equal(finalBet, 15, 'bet 10 and insurance 5')
assert.equal(right.close, true, 'right hand should be close')
assert.equal(
win,
5 * 3,
'insurance pays 2 to 1 when dealer has bj + insurance value'
)
assert.equal(
wonOnRight,
10,
"right has prize because it's a push (even money)"
)
})
it(`INSURANCE ON AND EVEN_MONEY OFF ${
test.cards
}, insure YES, and finish`, () => {
const testActions = ['restore', 'deal']
const rules = { insurance: true, evenMoneyInsurance: false }
const state = executeFlow(
rules,
test.cards,
testActions.map(x => functions[x])
)
const {
sideBetsInfo: { insurance }
} = state
assert.equal(insurance, undefined, 'insurance not offered')
})
})
describe('# even money dealer no BJ', () => {
it(`INSURANCE ON AND EVEN_MONEY ON`, () => {
const testActions = ['restore', 'deal', 'insuranceYes']
const rules = { insurance: true, evenMoneyInsurance: true }
const state = executeFlow(
rules,
'♦5 ♥1 ♠10 ♠1',
testActions.map(x => functions[x])
)
const bet = 10
const maxInsuranceAmount = bet / 2
const {
finalBet,
wonOnRight,
handInfo: { right },
sideBetsInfo: {
insurance: { risk, win }
}
} = state
assert.equal(
state.stage,
'done',
'blackjack but insurance is ON and first card is ♥1'
)
assert.equal(right.playerValue.hi, 21, 'player value must be 4')
assert.equal(
finalBet,
bet + maxInsuranceAmount,
`bet ${bet} and max insurance ${maxInsuranceAmount}`
)
assert.equal(right.close, true, 'right hand should be close')
assert.equal(risk, 5, 'insurance risk value is 5')
assert.equal(win, 0, 'insurance win value is 0')
assert.equal(
wonOnRight,
bet + bet * 1.5,
"right has prize because it's a player blackjack (even money)"
)
})
it(`INSURANCE ON AND EVEN_MONEY OFF`, () => {
const testActions = ['restore', 'deal']
const rules = { insurance: true, evenMoneyInsurance: false }
const state = executeFlow(
rules,
'♦5 ♥1 ♠10 ♠1',
testActions.map(x => functions[x])
)
const {
sideBetsInfo: { insurance }
} = state
assert.equal(insurance, undefined, 'insurance not offered')
})
})
})

describe('Must Stand on 17', function () {
Expand Down Expand Up @@ -468,4 +577,4 @@ describe('No matter how many aces ... soft hands do not busts', () => {
assert.equal(playerHasBusted, false, 'Player should be 12 not 22')
assert.equal(wonOnRight, 0, 'player lose. dealer has 21, player 12 or 22')
})
})
})
1 change: 1 addition & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ declare module 'engine-blackjack' {
split: boolean;
surrender: boolean;
insurance: boolean;
evenMoneyInsurance: boolean;
showdownAfterAceSplit: boolean;
}

Expand Down