// this method will determine the amount to bet on the next // hand public virtual void DetermineBet(StatisticsMgr stats) { int bet = Bet; // likelihood of a win or lose streak greater than 1 is 66%. As the // streak continues, the chance of another win/lose inside the streak // is about 40%. if (stats.WinStreak == 1) { bet = 2000; } else if (stats.WinStreak == 2) { bet = 1000; } else if (stats.WinStreak > 2) { bet -= (int)(bet * .42); } else if (stats.LosingStreak == 1) { bet = 100; } else if (stats.LosingStreak > 2) { bet += (int)(bet * .42); } bet = Math.Max(bet, 100); bet = Math.Min(bet, 100000); Bet = bet; }
static void Main(string[] args) { StatisticsMgr stats = new StatisticsMgr(); // turning off a couple of time-consuming features stats.Features.HasCalculateWinSequenceLengths = false; stats.Features.HasTrackLastFewCards = false; PlayModifiedBetting play = new PlayModifiedBetting(); play.PlayHands(5000000, stats); stats.CalculateDerivedStatistics(); stats.ReportStatistics(); }
// this is logic to determine if the player should split the hand public virtual bool DetermineSplit(HouseHand dealerHand, Hand playerHand, StatisticsMgr stats) { // don't do anything special if it's not likely to work if ( stats.WinStreak > 4 || (stats.LosingStreak > 0 && stats.LosingStreak < 3) || !playerHand.IsSplittable ) { return(false); } // split a pair of aces if (playerHand.SumCards == 2) { return(true); } // avoid pair of 4s, pair of 5s if ( // more likely to have 18 or 20 in these cases, so don't split ( stats.TensIndex < 5 && (playerHand.SumCards == 8 || playerHand.SumCards == 10) ) ) { return(false); } if (Math.Min(dealerHand.CardShowing.Face, (byte)10) >= playerHand.Cards[0].Face) { return(false); } if (dealerHand.CardShowing.Face == 1) { return(false); } return(true); }
public Dealer(StatisticsMgr stats) { Statistics = stats; _shoe = new List <Card>(); for (int i = 0; i < 6; i++) { for (byte x = 1; x < 14; x++) { _shoe.Add(new Card(0, x)); _shoe.Add(new Card(1, x)); _shoe.Add(new Card(2, x)); _shoe.Add(new Card(3, x)); } } _nextshoe = _shoe.ToArray(); Extensions.Shuffle(_shoe); }
public override void PlayHands(int iterations, StatisticsMgr stats) { Dealer dlr = new Dealer(stats); while (--iterations >= 0) { var hands = dlr.DealHands(new NaiveHand()); hands.Item1.Hit(dlr); if (!hands.Item1.IsBust) { hands.Item2.Hit(dlr); } if (hands.Item1.IsBust) { stats.Losses++; } else if (hands.Item1.IsBlackJack && !hands.Item2.IsBlackJack) { stats.Wins++; } else if (hands.Item2.IsBust) { stats.Wins++; stats.WinsByBust++; } else if (hands.Item1.SumCards > hands.Item2.SumCards) { stats.Wins++; } else if (hands.Item2.SumCards > hands.Item1.SumCards) { stats.Losses++; } } }
// return true = should doubledown public virtual bool DetermineDoubleDown(HouseHand dealerHand, Hand playerHand, StatisticsMgr stats) { if (stats.WinStreak > 3 || !playerHand.IsDoubleDownable) { // just don't return(false); } // if the dealer's shown card is not a 10 pt or ace, continue if (dealerHand.CardShowing.Face == 1 || (dealerHand.CardShowing.Face > 9 && stats.TensIndex > 2)) { return(false); } if (playerHand.HasAce && playerHand.SumCards < 14 && stats.TensIndex > 4) { return(true); } // if the card sum is between 9 and 12 if (playerHand.SumCards < 12 && playerHand.SumCards >= 9) { if (dealerHand.CardShowing.Face < 9) { return(true); } } return(false); }
public virtual void PlayHands(int iterations, StatisticsMgr stats) { }
// this method will play a series of hands, using a specific behavior public override void PlayHands(int iterations, StatisticsMgr stats) { Dealer dlr = new Dealer(stats); BettingBehavior betting = new BettingBehavior(); // this is done like this to avoid re-allocating hands ModifiedBettingHand bettingHand = new ModifiedBettingHand(); // doing this here to avoid allocations Hand[] playerHands = new Hand[2]; while (--iterations >= 0) { betting.DetermineBet(stats); bettingHand.Reset(); dlr.DealHands(bettingHand); // tweak the stats before the doubledown bet foreach (Card playerCard in dlr.PlayerHand.Cards) { // this records the card displayed, emulating a user that is // counting the last 12 cards or so. Counting more cards would // result in better performance. stats.DiscardCard(playerCard); } stats.DiscardCard(dlr.DealerHand.Cards[1]); stats.BlackJacks += (dlr.PlayerHand.IsBlackJack) ? 1 : 0; // apply the hit logic to the player's hand. This will also // split if necessary dlr.PlayerHand.Hit(dlr, betting); // dealer only hits if the player doesn't go bust if (!dlr.PlayerHand.IsBust || (dlr.PlayerSplitHand != null && !dlr.PlayerSplitHand.IsBust)) { dlr.DealerHand.Hit(dlr); } if (iterations % 1000000 == 0) { Debug.WriteLine("\tProfits: {0} Bet: {1}", stats.Profit, betting.Bet); } playerHands[0] = dlr.PlayerHand; if (null != dlr.PlayerSplitHand) { // if the hand was split, add the split hand results as well playerHands[1] = dlr.PlayerSplitHand; } else { playerHands[1] = null; } foreach (var playerHand in playerHands) { if (null == playerHand) { continue; } // keep track of the total amount bet since it's dynamic stats.CumulativeBet += playerHand.Bet; if (playerHand.IsBust) { stats.Profit -= playerHand.Bet; stats.RecordLoss(); stats.LossesByBust++; if (playerHand.IsDoubledDown) { stats.LossesByDoubleDown++; } if (playerHand.IsSplit) { stats.LossesBySplit++; } } else if (playerHand.IsBlackJack && !dlr.DealerHand.IsBlackJack) { // blackjack pays 3 to 2 stats.Profit += (int)(1.5 * playerHand.Bet); stats.RecordWin(iterations); if (playerHand.IsSplit) { stats.WinsBySplit++; } } else if (!playerHand.IsBlackJack && dlr.DealerHand.IsBlackJack) { stats.Profit -= playerHand.Bet; stats.RecordLoss(); if (playerHand.IsDoubledDown) { stats.LossesByDoubleDown++; } if (playerHand.IsSplit) { stats.LossesBySplit++; } } else if (dlr.DealerHand.IsBust) { stats.Profit += playerHand.Bet; stats.RecordWin(iterations); stats.WinsByBust++; if (playerHand.IsDoubledDown) { stats.WinsByDoubleDown++; } if (playerHand.IsSplit) { stats.WinsBySplit++; } } else if (playerHand.SumCards > dlr.DealerHand.SumCards) { stats.Profit += playerHand.Bet; stats.RecordWin(iterations); if (playerHand.IsDoubledDown) { stats.WinsByDoubleDown++; } if (playerHand.IsSplit) { stats.WinsBySplit++; } } else if (dlr.DealerHand.SumCards > playerHand.SumCards) { stats.Profit -= playerHand.Bet; stats.RecordLoss(); if (playerHand.IsDoubledDown) { stats.LossesByDoubleDown++; } if (playerHand.IsSplit) { stats.LossesBySplit++; } } } // now keep track of the last few discarded cards from both players int index = 0; foreach (Card dlrCard in dlr.DealerHand.Cards) { // skip the card that was initially shown because it was counted // earlier if (index++ == 1) { continue; } stats.DiscardCard(dlrCard); } } }