diff --git a/src/engine.js b/src/engine.js index 09d05e4..5843ee8 100644 --- a/src/engine.js +++ b/src/engine.js @@ -108,7 +108,7 @@ export const getHandInfo = (playerCards: Array, dealerCards: Array, 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, @@ -140,7 +140,7 @@ export const getHandInfoAfterDeal = (playerCards: Array, dealerCards: Arra } return { ...hand, - close: hand.playerHasBlackjack + close: hand.playerHasBlackjack && !availableActions.insurance } } @@ -289,7 +289,7 @@ export const isActionAllowed = (actionName: string, stage: string): boolean => { } } -export const getPrize = (playerHand: Hand, dealerCards: Array): number => { +export const getPrize = (playerHand: Hand, dealerCards: Array, tookInsurance: boolean): number => { const { close = false, playerHasSurrendered = true, @@ -309,7 +309,7 @@ export const getPrize = (playerHand: Hand, dealerCards: Array): number => if (playerHasSurrendered) { return bet / 2 } - if (playerHasBlackjack && !dealerHasBlackjack) { + if (playerHasBlackjack && (!dealerHasBlackjack || (!dealerHasBlackjack && tookInsurance))) { return bet + (bet * 1.5) } const dealerHasBusted = higherValidDealerValue > 21 @@ -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, diff --git a/src/game.js b/src/game.js index ce0f9fc..cecd9ec 100644 --- a/src/game.js +++ b/src/game.js @@ -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 ] @@ -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 } @@ -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 } @@ -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 } @@ -244,7 +250,7 @@ export default class Game { } } }) - if (dealerHasBlackjack) { + if (dealerHasBlackjack || tookEvenMoney) { this._dispatch(actions.showdown()) } break diff --git a/src/presets.js b/src/presets.js index 31f7a01..98677d0 100644 --- a/src/presets.js +++ b/src/presets.js @@ -39,6 +39,7 @@ export const getRules = ({ doubleAfterSplit = true, surrender = true, insurance = true, + evenMoneyInsurance = false, showdownAfterAceSplit = true }: Rule) => { return { @@ -49,6 +50,7 @@ export const getRules = ({ doubleAfterSplit: doubleAfterSplit, surrender: surrender, insurance: insurance, + evenMoneyInsurance: evenMoneyInsurance, showdownAfterAceSplit: showdownAfterAceSplit } } diff --git a/src/types/index.js b/src/types/index.js index 6cf009c..7972482 100644 --- a/src/types/index.js +++ b/src/types/index.js @@ -56,6 +56,7 @@ export type Rule = { split: boolean, surrender: boolean, insurance: boolean, + evenMoneyInsurance: boolean, showdownAfterAceSplit: boolean } diff --git a/test/game.spec.js b/test/game.spec.js index 7a6ed38..540ae55 100644 --- a/test/game.spec.js +++ b/test/game.spec.js @@ -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 () { @@ -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') }) -}) \ No newline at end of file +}) diff --git a/types/index.d.ts b/types/index.d.ts index e211589..1b390a3 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -91,6 +91,7 @@ declare module 'engine-blackjack' { split: boolean; surrender: boolean; insurance: boolean; + evenMoneyInsurance: boolean; showdownAfterAceSplit: boolean; }