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..7eacbc2 100644 --- a/src/game.js +++ b/src/game.js @@ -202,8 +202,12 @@ export default class Game { hits: hits + 1 }) - if (right.playerHasBlackjack) { - // purpose of the game archived !!! + if ( + right.playerHasBlackjack && + (!right.availableActions.insurance || + (right.availableActions.insurance && dealerValue.lo !== 1)) + ) { + // purpose of the game achieved !!! this._dispatch(actions.showdown()) break } @@ -214,7 +218,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 (including even money) action } break } @@ -227,7 +231,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 +249,7 @@ export default class Game { } } }) - if (dealerHasBlackjack) { + if (dealerHasBlackjack || tookEvenMoney) { this._dispatch(actions.showdown()) } break diff --git a/test/game.spec.js b/test/game.spec.js index 7a6ed38..77ffaec 100644 --- a/test/game.spec.js +++ b/test/game.spec.js @@ -303,6 +303,128 @@ 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: should deal ${ + test.cards + }, insure YES, and finish`, () => { + const testActions = ['restore', 'deal', 'insuranceYes'] + const rules = { insurance: 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 1') + 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: should deal ${ + test.cards + }, insure YES, and finish`, () => { + const testActions = ['restore', 'deal20', 'insuranceYes'] + const rules = { insurance: true } + const state = executeFlow( + rules, + test.cards, + testActions.map(x => functions[x]) + ) + 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(finalBet, 20 + 10, 'bet 20 and insurance 10') + assert.equal(right.close, true, 'right hand should be close') + assert.equal( + risk, + 10, + 'insurance pays 2 to 1 when dealer has bj + insurance value' + ) + assert.equal( + win, + 30, + 'insurance pays 2 to 1 when dealer has bj + insurance value' + ) + assert.equal( + wonOnRight, + 20, + "right has prize because it's a push (even money)" + ) + }) + }) + describe('# even money dealer no BJ', () => { + it(`INSURANCE ON: prevent amount injection`, () => { + const testActions = ['restore', 'deal', 'insuranceInjectAmount', 'standR'] + const rules = { insurance: 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)" + ) + }) + }) }) describe('Must Stand on 17', function () { @@ -468,4 +590,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 +})