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); }