/// <summary> /// Get the next move suggestion by Wizard's Strategy: http://wizardofodds.com/games/blackjack/basics/ /// </summary> /// <param name="dealerHandCards">Dealer's Hand</param> /// <param name="playerHandCards">Player's Hand</param> /// <param name="playerHands">Current hand count the player has</param> /// <param name="gameContext">Game Context</param> /// <returns></returns> public static PlayerAction GetActionByWizardStrategy(HandCards dealerHandCards, PlayerHandCards playerHandCards, int playerHands, GameContext gameContext) { bool isSoftValue; int dealerValue = dealerHandCards.GetHandValue(out isSoftValue); int playerValue = playerHandCards.GetHandValue(out isSoftValue); if (playerValue == 16 && dealerValue == 10 && playerHandCards.EligibleToSurrender(gameContext)) { return(PlayerAction.Surrender); } if (dealerValue >= 2 && dealerValue <= 6) { if (playerHandCards.EligibleToSplit(playerHands, gameContext)) { if (playerValue != 8 && playerValue != 10 && playerValue != 20) { return(PlayerAction.Split); } } if (isSoftValue) { if (playerValue >= 12 && playerValue <= 15) { return(PlayerAction.Hit); } else if (playerValue >= 16 && playerValue <= 18) { return(playerHandCards.EligibleToDouble(gameContext) ? PlayerAction.Double : (playerValue == 18 ? PlayerAction.Stand : PlayerAction.Hit)); } else if (playerValue >= 19 && playerValue <= 21) { return(PlayerAction.Stand); } } else { if (playerValue >= 4 && playerValue <= 8) { return(PlayerAction.Hit); } else if (playerValue >= 9 && playerValue <= 11) { return(playerHandCards.EligibleToDouble(gameContext) ? PlayerAction.Double : PlayerAction.Hit); } else if (playerValue >= 12 && playerValue <= 21) { return(PlayerAction.Stand); } } } else if (dealerValue >= 7 && dealerValue <= 11) { if (playerHandCards.EligibleToSplit(playerHands, gameContext)) { if (playerValue == 16 || playerHandCards.ToString().Equals("AA")) { return(PlayerAction.Split); } } if (isSoftValue) { if (playerValue >= 12 && playerValue <= 18) { return(PlayerAction.Hit); } else if (playerValue >= 19 && playerValue <= 21) { return(PlayerAction.Stand); } } else { if (playerValue >= 4 && playerValue <= 16) { if (playerValue == 10 || playerValue == 11) { if (playerValue > dealerValue) { return(playerHandCards.EligibleToDouble(gameContext) ? PlayerAction.Double : PlayerAction.Hit); } } return(PlayerAction.Hit); } else if (playerValue >= 12 && playerValue <= 21) { return(PlayerAction.Stand); } } } else { throw new ArgumentException(string.Format("Dealer value is invalid: {0}", dealerValue), "dealerHandCards"); } throw new ArgumentException(string.Format("Player value is invalid: {0} IsSoftValue: {1}", playerValue, isSoftValue), "playerHandCards"); }
private static GameRecord PlayOneGame( long gameId, decimal initalBet, decimal initalWinAmount, GameContext gameContext, Func <HandCards, PlayerHandCards, int, GameContext, PlayerAction> getPlayerAction) { GameRecord newGame = new GameRecord(gameId); // Player place initial bet, game starts decimal totalWinThisGame = 0; newGame.AddGameStartedEvent(initalBet); // Initial round of card dealing PlayerHandCards playerCards = new PlayerHandCards(initalBet); playerCards.AddCard(gameContext.GetCardWithReshuffle()); // player first card int dealerFaceDownCard = gameContext.GetCardWithReshuffle(); // dealer first card, face-down playerCards.AddCard(gameContext.GetCardWithReshuffle()); // player second card HandCards dealerCards = new HandCards(gameContext.GetCardWithReshuffle()); // dealer second card, face-up LinkedList <PlayerHandCards> playerHands = new LinkedList <PlayerHandCards>(); playerHands.AddFirst(playerCards); newGame.AddOpenHandEvent(playerHands.Count, dealerCards, playerHands.First()); // Handle player hands until all of them either stand or be busted. int playerId = 1; for (LinkedListNode <PlayerHandCards> node = playerHands.First; node != null;) { PlayerHandCards currentHand = node.Value; PlayerAction currentAction = getPlayerAction(dealerCards, currentHand, playerHands.Count, gameContext); PlayerHandCards newHand = null; switch (currentAction) { case PlayerAction.Double: currentHand.BetAmount *= 2; currentHand.AddCard(gameContext.GetCardWithReshuffle()); break; case PlayerAction.Hit: currentHand.AddCard(gameContext.GetCardWithReshuffle()); break; case PlayerAction.Split: newHand = currentHand.SplitAndGetNewHandCards( gameContext.GetCardWithReshuffle(), gameContext.GetCardWithReshuffle(), gameContext); break; case PlayerAction.Surrender: currentHand.HasSurrendered = true; break; } newGame.AddEventByPlayerAction(currentAction, playerId, dealerCards, currentHand, gameContext); if (newHand != null) { playerHands.AddLast(newHand); newGame.AddOpenHandEvent(playerHands.Count, dealerCards, newHand); } // Conditions to move to next hand LinkedListNode <PlayerHandCards> nodeToRemove; if (currentHand.HasSurrendered) { decimal lostAmount = currentHand.BetAmount / 2; totalWinThisGame -= lostAmount; newGame.AddCloseHandEvent(playerId, dealerCards, currentHand, lostAmount, "Surrender"); nodeToRemove = node; playerHands.Remove(nodeToRemove); node = node.Next; playerId++; } else if (currentHand.IsBusted) { totalWinThisGame -= currentHand.BetAmount; newGame.AddCloseHandEvent(playerId, dealerCards, currentHand, -currentHand.BetAmount, "Busted"); nodeToRemove = node; playerHands.Remove(nodeToRemove); node = node.Next; playerId++; } else if (currentAction == PlayerAction.Stand) { node = node.Next; playerId++; } } // Dealer dealing for himself until he is busted, or over 17 if (playerHands.Count > 0) { bool isSoftValue; dealerCards.AddCard(dealerFaceDownCard); string initialCards = dealerCards.ToString(); int currentValue = dealerCards.GetHandValue(out isSoftValue); while (!dealerCards.IsBusted && !dealerCards.IsBlackJack) { if (currentValue >= 17) { if (!isSoftValue || !gameContext.DealerHitsOnSoft17) { break; } } int newCard = gameContext.GetCardWithReshuffle(); dealerCards.AddCard(newCard); currentValue = dealerCards.GetHandValue(out isSoftValue); } newGame.AddDealerEvent(initialCards, dealerCards.ToString(), currentValue); // Check game result by comparing dealer with each player hand playerId = 1; for (LinkedListNode <PlayerHandCards> node = playerHands.First; node != null; node = node.Next, playerId++) { if (!node.Value.HasSurrendered && !node.Value.IsBusted) { decimal winAmount; if (CheckGameStatus(dealerCards, node.Value, gameContext, out winAmount) != GameStatus.NotComplete) { totalWinThisGame += winAmount; newGame.AddCloseHandEvent(playerId, dealerCards, node.Value, winAmount); } } } } newGame.AddGameCompletedEvent(totalWinThisGame, initalWinAmount + totalWinThisGame); return(newGame); }