konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
January 28th, 2015 at 9:38:41 PM permalink
Hi all,
I am thinking the way to simulate the winning odd for poker game. I wrote a code to simulate how the blackjack game played. As the very first version, I totally simulate the game based on random decision. I know there is not correct but I am still thinking a better way to do so. After reading some introduction, it seems that someone will refer to what they called the strategy table to make a decision, but I wonder how do they create that table?

I have one thought but it seems that it will be a huge amount of calculation to find that table. Firstly listing all possible hand the player may get. For each hand, enumerate all possible decisions that the player could made and to find the payout for hand made from that decision. Save the decision that give the maximum outcome. Then each time I got a new hand, I should following that table to make a decision. This looks right but if we use several decks, there will be too much calculation one need to finished so to find that table, isn't it?

Any better idea? Thanks.
ThatDonGuy
ThatDonGuy
  • Threads: 122
  • Posts: 6679
Joined: Jun 22, 2011
January 29th, 2015 at 6:29:44 AM permalink
I assume you're talking about how a blackjack "strategy card" is made, right?

This question has been asked before. Since my answer is long, I'll put inside a "spoiler button"


The first thing to do is to determine the probability of the dealer getting 17, 18, 19, 20, 21, or busting, for each combination of three things: (a) The dealer's up card, (b) The number of decks used, and (c) Whether the dealer hits or stands on Soft 17. This is done by counting every possible combination of cards that reaches 17 or more, except for 2-card 21s, and adding up their probabilities. You have to remember to take into account the number of decks; in a one-deck game, you're not going to have five or more 3s, for example.

Once you have those (and adjust them so the probabilities of each up card / number / Soft 17 combination add up to 1), then you calculate the player's "expected return" for standing on each number from 4 to 21. For numbers less than 16, they are the same, since you win if the dealer busts and lose if the dealer has 17-21. For 17-21, start with the probability of the dealer busting, add the probabilities of the numbers less than the player total, and subtract the probabilities of the numbers greater than the player total.

Now, calculate the expected returns for hitting. Start with 21 and work down, since you will need to know higher values to calculate the lower ones. Obviously, if you hit 21, you will bust, so your expected return is -1. Since the expected return for standing on 21 is greater than the expected return for hitting, then the strategy (so far) is to stand on 21, and the ER for 21 is the ER for standing on 21.
Calculate 20; the ER for hitting 20 is 1/13 (i.e. getting an Ace) x the ER for 21 (which you just calculated) + 12/13 (i.e. getting a 2 through King) x the ER for busting (which is always -1). Add those up; if the total is greater than the ER for standing on 20, then the strategy for 20 is "hit" and the ER is this value, but if it is less, then the strategy for 20 is "stand" and the ER is the "stand on 20 ER".

Once you have Hard 12-21 calculated, calculate Soft 21, 20, and so on down to 12; this is the same, except that, for example, for Soft 14, you multiply the probability of a 4 by the ER for Soft 18 (instead of the ER for Hard 18 - again, this is why you do it backwards, from 21 to 12), but the probability of an 8 by the ER for Hard 12 (instead of the ER for busting).
Next, calculate Hard 11-4 (there is no such thing as a "hard 3"), remembering that an Ace makes it a Soft hand.

At this point, you have a "Hit or Stand" strategy card. The next thing to do is to determine the Double Down strategy. Since you must stand after taking another card when doubling, the Double ER for, say, 11 is (1/13 (Ace) x the Stand ER for 12 + 1/13 (for a 2) x the Stand ER for 13 + ... + 4/13 (for a 10 or face card) x the Stand ER for 21) x 2 (since you have doubled your bet). If this is greater than the Hit/Stand ER for that value, then you double.

Finally, calculate the ER for splitting a pair. If you split a pair of 8s, the ER is (1/13 x the ER for soft 19 + 1/13 x the ER for 10 + 1/13 x the ER for 11 + ... + 1/13 x the ER for hard 18) x 2 (since there are two hands). Remember that, in most cases, if you split Aces, you can only take one card, so you would use the Stand ERs.


Also, when you say "poker", do you mean video poker, or the kind you play against other people at a table?
MangoJ
MangoJ
  • Threads: 10
  • Posts: 905
Joined: Mar 12, 2011
January 29th, 2015 at 11:38:46 AM permalink
Are you simulating Blackjack or Poker ?

In blackjack: start with infinite deck to get some feel for the problem. Deal the player a hard 21 and see what happens of you stand or hit against each dealers hand. The "strategy" is then just the option which gives the best expectation.
After that, try a hard 20, then hard 19 ... (you should reuse the result of hard 21 for any lower hand).

After you come to hard 12, start with soft 21 and work your way down to soft 12.
Then, after soft 12 you work your way down from hard 11 down to hard 4.

Why this sequence of hands ? With any hard hand >=12, you end up with a hard hand with more points. Likewise, with any soft hand you either end up with a soft hand with more points, or a hard hand >= 12. You get the idea... use the previously computed values to evaluate the next hands in your sequence.

Then at the end, you should try to calculate double down hands. Then at the end, you should be able to calculate splits. Try different rules: double down after splits, re-splits.

Then at last try to calculate the overall game expectancy and the full strategy table.

After that, you can start to think about non-infinite deck games.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
January 29th, 2015 at 12:36:08 PM permalink
Sorry for the misleading terms. I am thinking to simulate the most card games but start with blackjack first. I will read your post carefully first.

Quote: ThatDonGuy

I assume you're talking about how a blackjack "strategy card" is made, right?

This question has been asked before. Since my answer is long, I'll put inside a "spoiler button"


The first thing to do is to determine the probability of the dealer getting 17, 18, 19, 20, 21, or busting, for each combination of three things: (a) The dealer's up card, (b) The number of decks used, and (c) Whether the dealer hits or stands on Soft 17. This is done by counting every possible combination of cards that reaches 17 or more, except for 2-card 21s, and adding up their probabilities. You have to remember to take into account the number of decks; in a one-deck game, you're not going to have five or more 3s, for example.

Once you have those (and adjust them so the probabilities of each up card / number / Soft 17 combination add up to 1), then you calculate the player's "expected return" for standing on each number from 4 to 21. For numbers less than 16, they are the same, since you win if the dealer busts and lose if the dealer has 17-21. For 17-21, start with the probability of the dealer busting, add the probabilities of the numbers less than the player total, and subtract the probabilities of the numbers greater than the player total.

Now, calculate the expected returns for hitting. Start with 21 and work down, since you will need to know higher values to calculate the lower ones. Obviously, if you hit 21, you will bust, so your expected return is -1. Since the expected return for standing on 21 is greater than the expected return for hitting, then the strategy (so far) is to stand on 21, and the ER for 21 is the ER for standing on 21.
Calculate 20; the ER for hitting 20 is 1/13 (i.e. getting an Ace) x the ER for 21 (which you just calculated) + 12/13 (i.e. getting a 2 through King) x the ER for busting (which is always -1). Add those up; if the total is greater than the ER for standing on 20, then the strategy for 20 is "hit" and the ER is this value, but if it is less, then the strategy for 20 is "stand" and the ER is the "stand on 20 ER".

Once you have Hard 12-21 calculated, calculate Soft 21, 20, and so on down to 12; this is the same, except that, for example, for Soft 14, you multiply the probability of a 4 by the ER for Soft 18 (instead of the ER for Hard 18 - again, this is why you do it backwards, from 21 to 12), but the probability of an 8 by the ER for Hard 12 (instead of the ER for busting).
Next, calculate Hard 11-4 (there is no such thing as a "hard 3"), remembering that an Ace makes it a Soft hand.

At this point, you have a "Hit or Stand" strategy card. The next thing to do is to determine the Double Down strategy. Since you must stand after taking another card when doubling, the Double ER for, say, 11 is (1/13 (Ace) x the Stand ER for 12 + 1/13 (for a 2) x the Stand ER for 13 + ... + 4/13 (for a 10 or face card) x the Stand ER for 21) x 2 (since you have doubled your bet). If this is greater than the Hit/Stand ER for that value, then you double.

Finally, calculate the ER for splitting a pair. If you split a pair of 8s, the ER is (1/13 x the ER for soft 19 + 1/13 x the ER for 10 + 1/13 x the ER for 11 + ... + 1/13 x the ER for hard 18) x 2 (since there are two hands). Remember that, in most cases, if you split Aces, you can only take one card, so you would use the Stand ERs.


Also, when you say "poker", do you mean video poker, or the kind you play against other people at a table?

charliepatrick
charliepatrick
  • Threads: 39
  • Posts: 3011
Joined: Jun 17, 2011
January 30th, 2015 at 8:39:08 AM permalink
Unless it's a single deck poker game (where you can't have two Aces of Spades), when you're analysing a game, or a sidebet, the first point of call is using an infinite deck. This means the chances of any card is 1/13 and ratios for the dealer's cards are not affected by what the player has done. Personally I use two methods and hope they come to the same answer - a spreadsheet and running a program through all the possibilities.

As has been said, you have to pick the best option at each stage, starting with whether to hit or stand, working from 21 downwards including soft totals. I actually use (H30...S22) H21, S21, H20, S20 etc. e.g. Hit X = [ H(X+10)*4 + H(X+9)+....+H(X+2) + S(X+1) ] /13.

First work out the chances of the dealer's outcomes based on the starting card (S21: P(21)=1, P(20,19,18,17,Bust)=0.) and adjust for Blackjacks.

Then for each starting card, work out whether the player
(i) Stands or Hits any given total.
(ii) Doubles, Hits or Stands any given total.
(iii) Splits pairs.
(iv) If you care this can work out House Edge.

(In practice, UK rules, if I remember correctly the only difference cf 6dx is whether to double A4 v 4).

I've never analysed BJ further, except the Push-22 chances, and that just worked out all the possible hands the dealer can make. However for other games, you have to work through all the player hands and for each (given which cards have been used) determine the chances of each dealer result and hence the probability of winning by standing. Then using this work out all the outcomes by hitting/doubling and compare. Similarly for pairs.

It shouldn't take too long, perhaps two hours, to work out all the excel formulae and how to make the various sheets.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 3rd, 2015 at 5:24:43 AM permalink
Thanks for your guys' guiding. I just saw in this website that a strategy table is given, one of the table is with peeking. I wonder how does it change if we allow the player to peek the dealer's up card? It is quite confusing to me. Which part in above analysis really changed if we allow peeking?

While I am playing blackjack with my friend, we create a variation game by allowing the player to exchange the very last card between dealer and player if the player would like to pay more. Which part in above analysis really changed if we allow that? Thanks.
MangoJ
MangoJ
  • Threads: 10
  • Posts: 905
Joined: Mar 12, 2011
February 4th, 2015 at 11:24:18 AM permalink
The dealers upcard is already visible :)

If you can see the dealers holecard, you should look at the strategy table for "double exposure", a common variant of blackjack.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 9th, 2015 at 6:17:48 AM permalink
Hi again, I am starting the math following your instruction. But I stuck at the first stage. When you say to list the probability of getting 17, 18, 19, 20, 21 or busting. Do you mean all possible hands to get those points or just the initial two cards dealt to the dealer? For example, if we only interest on the first 2 cards giving 17, we might have

K + 7
Q + 7
J + 7
10 + 7
A(11) + 6
etc.

But if you mean all possible hands which dealt 2 to N cards giving 17, it will be quite a lot.

Meanwhile, I am writing a code to do the job. Do you think the order matter? Should I go with combination or permutation while listing the probability?

Quote: ThatDonGuy

I assume you're talking about how a blackjack "strategy card" is made, right?

This question has been asked before. Since my answer is long, I'll put inside a "spoiler button"


The first thing to do is to determine the probability of the dealer getting 17, 18, 19, 20, 21, or busting, for each combination of three things: (a) The dealer's up card, (b) The number of decks used, and (c) Whether the dealer hits or stands on Soft 17. This is done by counting every possible combination of cards that reaches 17 or more, except for 2-card 21s, and adding up their probabilities. You have to remember to take into account the number of decks; in a one-deck game, you're not going to have five or more 3s, for example.

Once you have those (and adjust them so the probabilities of each up card / number / Soft 17 combination add up to 1), then you calculate the player's "expected return" for standing on each number from 4 to 21. For numbers less than 16, they are the same, since you win if the dealer busts and lose if the dealer has 17-21. For 17-21, start with the probability of the dealer busting, add the probabilities of the numbers less than the player total, and subtract the probabilities of the numbers greater than the player total.

Now, calculate the expected returns for hitting. Start with 21 and work down, since you will need to know higher values to calculate the lower ones. Obviously, if you hit 21, you will bust, so your expected return is -1. Since the expected return for standing on 21 is greater than the expected return for hitting, then the strategy (so far) is to stand on 21, and the ER for 21 is the ER for standing on 21.
Calculate 20; the ER for hitting 20 is 1/13 (i.e. getting an Ace) x the ER for 21 (which you just calculated) + 12/13 (i.e. getting a 2 through King) x the ER for busting (which is always -1). Add those up; if the total is greater than the ER for standing on 20, then the strategy for 20 is "hit" and the ER is this value, but if it is less, then the strategy for 20 is "stand" and the ER is the "stand on 20 ER".

Once you have Hard 12-21 calculated, calculate Soft 21, 20, and so on down to 12; this is the same, except that, for example, for Soft 14, you multiply the probability of a 4 by the ER for Soft 18 (instead of the ER for Hard 18 - again, this is why you do it backwards, from 21 to 12), but the probability of an 8 by the ER for Hard 12 (instead of the ER for busting).
Next, calculate Hard 11-4 (there is no such thing as a "hard 3"), remembering that an Ace makes it a Soft hand.

At this point, you have a "Hit or Stand" strategy card. The next thing to do is to determine the Double Down strategy. Since you must stand after taking another card when doubling, the Double ER for, say, 11 is (1/13 (Ace) x the Stand ER for 12 + 1/13 (for a 2) x the Stand ER for 13 + ... + 4/13 (for a 10 or face card) x the Stand ER for 21) x 2 (since you have doubled your bet). If this is greater than the Hit/Stand ER for that value, then you double.

Finally, calculate the ER for splitting a pair. If you split a pair of 8s, the ER is (1/13 x the ER for soft 19 + 1/13 x the ER for 10 + 1/13 x the ER for 11 + ... + 1/13 x the ER for hard 18) x 2 (since there are two hands). Remember that, in most cases, if you split Aces, you can only take one card, so you would use the Stand ERs.


Also, when you say "poker", do you mean video poker, or the kind you play against other people at a table?

Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 9th, 2015 at 6:39:29 AM permalink
Quote: MangoJ

If you can see the dealers holecard, you should look at the strategy table for "double exposure", a common variant of blackjack.



The game "double exposure blackjack" has a different strategy than standard blackjack with a known hole card, because other rules are different - specifically, player loses ties.
May the cards fall in your favor.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 9th, 2015 at 7:00:56 AM permalink
Quote: Dieter

The game "double exposure blackjack" has a different strategy than standard blackjack with a known hole card, because other rules are different - specifically, player loses ties.


Thanks. So what I am interesting is how to create the strategy table for "double exposure"?
ThatDonGuy
ThatDonGuy
  • Threads: 122
  • Posts: 6679
Joined: Jun 22, 2011
February 9th, 2015 at 7:05:54 AM permalink
Quote: konglify

Hi again, I am starting the math following your instruction. But I stuck at the first stage. When you say to list the probability of getting 17, 18, 19, 20, 21 or busting. Do you mean all possible hands to get those points or just the initial two cards dealt to the dealer? For example, if we only interest on the first 2 cards giving 17, we might have

K + 7
Q + 7
J + 7
10 + 7
A(11) + 6
etc.

But if you mean all possible hands which dealt 2 to N cards giving 17, it will be quite a lot.


I mean all possible hands. Yes, that includes, for example, a 17 consisting of A, A, A, A, A, A, 6, A, A, A, A, A. Of course, this would require 3 or more decks, as otherwise there wouldn't be 11 Aces in the deck (and there are situations where the strategy is different with 2 decks than with 3; the one I can think of off the top of my head is, with a hard 16 and the dealer showing a 10, you stand if there are 1 or 2 decks, but hit if there are 3 or more). If it is single-deck, you would still count, for example, A, A, 2, 2, 6, 3, A, A.

Also remember two things: first, you have to separate them by the dealer's first card (which is considered the up card), and second, you have to ignore 2-card 21s, as the player won't have to worry about what to do in those situations.
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 9th, 2015 at 7:39:50 AM permalink
Quote: konglify

Thanks. So what I am interesting is how to create the strategy table for "double exposure"?



There was a pretty good, fairly lengthy video posted a few months back about how to derive basic strategy for S17, infinite decks, using a spreadsheet.

That's a start. The process gets changed as the manner hands get evaluated changes.
May the cards fall in your favor.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 9th, 2015 at 9:14:12 AM permalink
Ok. I just watch that video. I understand the basic idea now when considering infinite decks. But if we limit to finite decks, usually will similar spreadsheet helps or need other computer language like c++ to do the math? Also, I have a question about the multiplayer and reshuffle. Usually, there will be more than 1 players playing the game and it will shuffle the decks every N cards dealt. So how do those affect the strategy?

Quote: Dieter

There was a pretty good, fairly lengthy video posted a few months back about how to derive basic strategy for S17, infinite decks, using a spreadsheet.

That's a start. The process gets changed as the manner hands get evaluated changes.

ThatDonGuy
ThatDonGuy
  • Threads: 122
  • Posts: 6679
Joined: Jun 22, 2011
February 9th, 2015 at 9:21:31 AM permalink
Quote: konglify

Also, I have a question about the multiplayer and reshuffle. Usually, there will be more than 1 players playing the game and it will shuffle the decks every N cards dealt. So how do those affect the strategy?


Since basic strategy assumes that you're not counting cards, it doesn't. Always assume that the game is being played from a full deck. Also, the number of players is irrelevant; assume that you are the only player there.

The only time the number of cards in the deck would matter is, each time 52 cards are dealt, the strategy would change from N decks to N-1 decks. However, you don't need to take that into account when calculating N-deck strategy; always assume there are N full decks in the shoe.
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 9th, 2015 at 9:23:42 AM permalink
Quote: konglify

Usually, there will be more than 1 players playing the game and it will shuffle the decks every N cards dealt. So how do those affect the strategy?



If the composition of the remaining cards is typical, it won't.

You don't have a way of knowing the composition of the remaining cards without some sort of counting system.

The adjustments from infinite decks to 8 decks to 6 decks are very minor. (I believe the changes start coming noticeably into play with 2 decks / 1 deck.)

You can do the math with whatever tools are convenient. I believe Thorp did it with Fortran, but C or C++ should work fine. It would be somewhat complicated with a spreadsheet, but not impossible.
May the cards fall in your favor.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 9th, 2015 at 9:43:31 AM permalink
Makes sense to me when considering the strategy. But if we looking for the house edge for the game, do you think we should base on the basic strategy or not? The video I watched and many books on blackjack is using this or that basic strategy to figure out the house edge but will that cause uncertainty on the house because of the assumption we made to generate the strategy table?

It might be wrong but I am just thinking is it possible to use computer to generate so many hands for player and dealer, for each hand, try stand, hit, double, split, surrender, insurance ... so to find out which one give the maximum winning so to determine which action should be made when the dealer's upcard is X and when player's total point is Y. I don't know if that's make sense since says the player makes one decision at this round, each decision will lead to many others decision to make next so the decision tree grows pretty fast. I might be wrong but that's something I am going to program next.

Quote: ThatDonGuy

Since basic strategy assumes that you're not counting cards, it doesn't. Always assume that the game is being played from a full deck. Also, the number of players is irrelevant; assume that you are the only player there.

The only time the number of cards in the deck would matter is, each time 52 cards are dealt, the strategy would change from N decks to N-1 decks. However, you don't need to take that into account when calculating N-deck strategy; always assume there are N full decks in the shoe.

Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 9th, 2015 at 9:59:13 AM permalink
Quote: konglify

It might be wrong but I am just thinking is it possible to use computer to generate so many hands for player and dealer, for each hand, try stand, hit, double, split, surrender, insurance ... so to find out which one give the maximum winning so to determine which action should be made when the dealer's upcard is X and when player's total point is Y.



This has been done. You can find the results conveniently as a number of charts showing the "Basic Strategy for Blackjack", in different variants for the various common rule changes and number of decks in play.

https://www.blackjackinfo.com/blackjack-basic-strategy-engine/
May the cards fall in your favor.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 9th, 2015 at 10:58:10 AM permalink
Thanks for the resource. I found that website before. But it doesn't support all options or rules stated in the wiki http://en.wikipedia.org/wiki/Blackjack

I am going to see how those rules will affect the strategy or house. For example, in wiki, there will be "insurance" option, "Resplitting" to N hands, "Hit/resplit split aces" and the one rule called even money (http://en.wikipedia.org/wiki/Even_money) that I played in online blackjack. So do you know any engine will give strategy for all those options?

BTW, in many strategy tables I saw online or in books, why they don't count the side bet like "insurance" and/or "even money"? Shall we always include them if we are looking for more "accurate" strategy? Thanks.




Quote: Dieter

This has been done. You can find the results conveniently as a number of charts showing the "Basic Strategy for Blackjack", in different variants for the various common rule changes and number of decks in play.

https://www.blackjackinfo.com/blackjack-basic-strategy-engine/

Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 9th, 2015 at 11:42:33 AM permalink
Quote: konglify

I am going to see how those rules will affect the strategy or house. For example, in wiki, there will be "insurance" option, "Resplitting" to N hands, "Hit/resplit split aces" and the one rule called even money (http://en.wikipedia.org/wiki/Even_money) that I played in online blackjack. So do you know any engine will give strategy for all those options?



None of those change basic strategy. Basic strategy is the "best" set of plays at neutral counts.

Insurance is the same thing as even money (on a game where blackjack pays 3:2).

Insurance is not recommended at neutral or negative counts.

Resplitting to 3 or 4 hands vs splitting to 2 hands doesn't change basic strategy, but it does change the house edge (slightly). You split if you can, and if you can't you treat it like a hard (or soft, in the case of AA) hand.

The option to hit split aces doesn't change basic strategy. The option to resplit aces doesn't change basic strategy. These options only change the house edge. Again, in either case, you split if you can, and hit if appropriate and allowed.

The options that do change basic strategy are - S17/H17, what totals you're allowed to double on (D9, D10, D11, DA), whether you're allowed to double after split or not, is surrender allowed, do you lose all bets to dealer natural or original bets only or original and busted bets only.
May the cards fall in your favor.
MangoJ
MangoJ
  • Threads: 10
  • Posts: 905
Joined: Mar 12, 2011
February 10th, 2015 at 3:50:07 PM permalink
Quote: ThatDonGuy

The only time the number of cards in the deck would matter is, each time 52 cards are dealt, the strategy would change from N decks to N-1 decks. However, you don't need to take that into account when calculating N-deck strategy; always assume there are N full decks in the shoe.



I might be picky, but this is quite wrong. If you play N deck, and 52 cards were dealt, you stick to the N deck strategy, not the N-1 deck strategy (if you are not counting, that is).

Why ? The N-1 deck strategy is only valid if you face N-1 complete decks, not (N-1)*52 cards. If you remove random 52 cards from an N deck game, strategy stays N deck game (imagine putting 52 from the front of the shoe behind the cut card, it doesn't change strategy - its obvious when the cards are face down).
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 12th, 2015 at 5:26:46 AM permalink
After some coding, I have got the basic strategy that similar to the one obtained in books and website. Now I am going to use that for simulation to find out the house edge. To do so, I start thousands of initial hands randomly and play the game based on the strategy table to decide if I should hit, stands, split, surrender or double down etc. But I want to ask how should I modify the code to simulate the house edge when the following allowed?

1) if the player has an option to peek the dealer's second card
2) if the player has an option to switch his or her last card with the dealer's last card?

I want to consider the above separately, i.e. house edge when 1) applied and house edge when 2) applied.

In my currently code, for example, for case 2), before looking up the strategy table, I randomly choose if the player want to switch the card or not, if yes, switch the cards and then looking up the strategy table and estimate the payout.

I feel strange to do that way but cannot think of other better way to do so. Do you think this random event good or not for simulating 2)?

But for 1), I am stuck on it. How does it change the house edge by peeking the dealer's card or not?

Quote: Dieter

None of those change basic strategy. Basic strategy is the "best" set of plays at neutral counts.

Insurance is the same thing as even money (on a game where blackjack pays 3:2).

Insurance is not recommended at neutral or negative counts.

Resplitting to 3 or 4 hands vs splitting to 2 hands doesn't change basic strategy, but it does change the house edge (slightly). You split if you can, and if you can't you treat it like a hard (or soft, in the case of AA) hand.

The option to hit split aces doesn't change basic strategy. The option to resplit aces doesn't change basic strategy. These options only change the house edge. Again, in either case, you split if you can, and hit if appropriate and allowed.

The options that do change basic strategy are - S17/H17, what totals you're allowed to double on (D9, D10, D11, DA), whether you're allowed to double after split or not, is surrender allowed, do you lose all bets to dealer natural or original bets only or original and busted bets only.

Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 12th, 2015 at 6:17:35 AM permalink
Quote: konglify

I feel strange to do that way but cannot think of other better way to do so. Do you think this random event good or not for simulating 2)?

But for 1), I am stuck on it. How does it change the house edge by peeking the dealer's card or not?



To determine if it's advantageous to switch the last hit card (or not), try both. It's advantageous if it wins (or turns a loss into a push). Keep stats on what works and what doesn't, build a chart.

It doesn't change the house edge of the game; it changes the temporary player advantage if the player knows the hole card. For example, a player might elect not to hit a 16 against a dealer K with a 6 down.

Look at https://wizardofodds.com/games/blackjack/appendix/16/
May the cards fall in your favor.
ThatDonGuy
ThatDonGuy
  • Threads: 122
  • Posts: 6679
Joined: Jun 22, 2011
February 12th, 2015 at 6:46:23 AM permalink
Quote: konglify

After some coding, I have got the basic strategy that similar to the one obtained in books and website. Now I am going to use that for simulation to find out the house edge. To do so, I start thousands of initial hands randomly and play the game based on the strategy table to decide if I should hit, stands, split, surrender or double down etc. But I want to ask how should I modify the code to simulate the house edge when the following allowed?

1) if the player has an option to peek the dealer's second card


In this case, then instead of calculating the probabilities of the dealer having 17, 18, 19, 20, 21, or bust based on one card, you calculate them based on two (and you do have to take into account the values of the individual cards - for example, you don't calculate the probabilities based on the dealer having hard 15, but separately for 10/J/Q/K-5, 9-6, and 8-7). I suppose you could calculate them based on the sum, but the number won't be as accurate, especially in a single-deck game - and you would still have to differentiate between the dealer having hard 15 and soft 15.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 12th, 2015 at 12:32:05 PM permalink
Ok, I see the difference from the strategy table you listed now.

For the switch card case, do you mean the following? I randomly create thousands hands. For each hand, I duplicate it as two independent hands, for first one, I go like usual (i.e. to determine the action based on the basic strategy) to calculate the payout. For the second duplicated hand, I exchange the card before applying the strategy so to calculate the new payout. I will use the maximum payout as to calculate the house edge, right? But in real case, I don't think the player is smarter enough to always do the right action. So the simulation stated above will give the minimum-possible house edge (or maximum-possible pay back), correct?

Quote: Dieter

To determine if it's advantageous to switch the last hit card (or not), try both. It's advantageous if it wins (or turns a loss into a push). Keep stats on what works and what doesn't, build a chart.

It doesn't change the house edge of the game; it changes the temporary player advantage if the player knows the hole card. For example, a player might elect not to hit a 16 against a dealer K with a 6 down.

Look at https://wizardofodds.com/games/blackjack/appendix/16/

konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 13th, 2015 at 11:48:00 PM permalink
Hi all, I just wrote a program to do the simulation based on the basic strategy. To test my code, I refer to the house edge calculation at https://wizardofodds.com/games/blackjack/calculator/. I used 8 decks, dealer hit on soft 17, can double after split, double only on 10-11, maximum 3 splits, resplit ace, hit split ace, Player loses only original bet against dealer BJ, late surrender, BJ pays 3 to 2. The website said the house edge is about 0.53. In the same page, it is linking to blackjack basic strategy calculator at https://wizardofodds.com/games/blackjack/strategy/calculator/. So in my code, I applied the same strategy to the pseudo code as follows

1) I randomly generate 2 cards to player, 2 cards to dealer from 8 decks
2) Check if there is any pair first, if yes, look up the table to see if we should double, hit, stand or split
3) if not pair, look up the table to see the next action
4) if any split suggested, split the current hand into two hands (3 hands if allowed). Any split hands will follow the same strategy table to take more actions if needed

But after running the simulation for 50000000 cycles, I obtained the house edge about 0.71, which is too much off from the one given in wizard of odds. My code is pretty messy now, I will upload it to help clarify my question after I got them organized.

At this point, I wonder if you have any idea what to improve or any open source code which could be used to do the simulation based on a given strategy table? thanks
MangoJ
MangoJ
  • Threads: 10
  • Posts: 905
Joined: Mar 12, 2011
February 14th, 2015 at 9:06:03 PM permalink
Quote: konglify

After some coding, I have got the basic strategy that similar to the one obtained in books and website. Now I am going to use that for simulation to find out the house edge. To do so, I start thousands of initial hands randomly and play the game based on the strategy table to decide if I should hit, stands, split, surrender or double down etc.



First of all, if you really want to simulate hands for EV calculation, you need billions of hands, not thousands.

Second, and more important - since you calculated all EVs for each decision (as I understand your text), why not simply sum them up to get the EV of the whole game ? All you need to do is weight the EV of your strategy tables starting hands with the probability of getting them against a dealers upcard, and account for all cases where no strategy is needed (dealers blackjack or players blackjack).
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 15th, 2015 at 12:10:59 PM permalink
Quote: MangoJ

First of all, if you really want to simulate hands for EV calculation, you need billions of hands, not thousands.

Second, and more important - since you calculated all EVs for each decision (as I understand your text), why not simply sum them up to get the EV of the whole game ? All you need to do is weight the EV of your strategy tables starting hands with the probability of getting them against a dealers upcard, and account for all cases where no strategy is needed (dealers blackjack or players blackjack).



Thanks for your reply. Yes, I modified the code to simulate 50million games but still get something off from the number given in wizard of odds result.

For second question, I am not sure I understanding it correctly on 'weight the EV of strategy', but what I did is randomly generating the hand, play the game based on the aid of strategy table, if win, add the pays to the total pays. So the house edge is

1 - total pays/ total games

"total games" is the total number of game played, since each game charge 1 credit for bet so I use "total games" as total bets.

One more question I want to confirm, in regular blackjack game for player's blackjack winning, there will pay 3:2 and all others regular winning other than blackjack pays 1:1, so in the case when I accumulate pays, should I make add 1.5 or 2.5 to the total pays in case the player winning blackjack?
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 15th, 2015 at 8:22:25 PM permalink
Quote: konglify

One more question I want to confirm, in regular blackjack game for player's blackjack winning, there will pay 3:2 and all others regular winning other than blackjack pays 1:1, so in the case when I accumulate pays, should I make add 1.5 or 2.5 to the total pays in case the player winning blackjack?



It depends.

On a 3:2 game, yes. +1.5x.
On a 6:5 game, it's +1.2x.
On a 1:1 game, its +1x.
There may be other ratios. There may be special rules or promotions, like Ace of Spades plus a Black Jack pays 2:1 instead of 3:2, or a Q-A of diamonds pays a $25 bonus.
Some video blackjack games pay 3:2 on a player blackjack, but only if an even number of coins are wagered. (This is often listed as "pays 5 for 2".) If only wagering 1 coin, it comes out as 1:1. If wagering 3 coins, it pays 4 ("7 for 3"). It won't pay a half coin. (These machines may also allow surrender, but only if an even number of coins are bet.)

Being thorough:
If I lose an ordinary hand, I lose my wager.
If I lose a hand that I've doubled, I lose my wager, plus the second wager.
If I tie a hand, it's a "push". My original wager is returned.
If I tie a hand that I've doubled, my original wager is returned, and the second wager is returned.
Suppose I wager $20...
If I win a hand, I get my original $20 back, plus another $20 to pay the win.
If I win a hand that I've doubled, I get my original $20 back, plus the $20 double back, plus $40 to pay the win.
If I foolishly doubled for less (say, $10), I get my original $20 back, plus the $10 double-for-less back, plus $30 to pay the win.
If I win a blackjack on a 3:2 game, I get my original $20 back, plus $30 to pay the win.
If I win a blackjack on a 6:5 game, I get my original $20 back, plus $24 to pay the win.
If I win a blackjack on a 1:1 game, I get my original $20 back, plus $20 to pay the win.

Program it in the way that makes sense to you.
May the cards fall in your favor.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 16th, 2015 at 4:20:58 PM permalink
Hi all,
After reading the comments here, I am trying to organize my code so I can post there. I am going to apply the rules

Player can double after a split: (yes)
Player can double on: (10-11 only)
Player can resplit aces: Yes
Player can hit split aces: Yes
Player loses only original bet against dealer BJ: Yes
Surrender rule: Late

and https://wizardofodds.com/games/blackjack/calculator/ give house edge to be about 0.52%. However, my code gives -97.1%, which is huge difference! To help reading the code, I will explain the flow as follows

I am using basic strategy same as https://wizardofodds.com/games/blackjack/strategy/calculator/

1) in function "void Simulation(void)", the game reply for many times, each game will randomly generate two cards for player and two cards for dealer. The simulator will check BJ on dealer and player first, if any BJ, conclude the game. Otherwise, the code will any any possible hands could be split out of the original hand. We can at most split up to 3 hands. So after this step, we have at least 1 hand or at most 3 hands available.

2) For each of the hands (including split hands if available), search the table to find the appropriate strategy based on the sum of the points on the hand and the dealer upcard.

3) after the hand evaluated, calculate the total pay. The game is pay 3:2 for BJ, 1:1 for regular winning, 0:1 for push and -0.5:1 for surrender. So the pays will be

2.5 if player BJ win
2 if player wins (without BJ)
0 if player push
0.5 if player surrender

But I still didn't see the same house edge given by wizard of odds. Any one give me some idea what's wrong with my code? Thanks.


#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <fstream>
#include <random>
#include <algorithm>
#include <map>
#include <string>
#include <utility>
#include <iomanip>

using namespace std;

std::random_device rd;
std::mt19937 gen(time(0));

enum {H,S,P,D,Dh,Ds,Rh,Rs,Rp,R};
enum {ACE=1,TWO=2,THREE=3,FOUR=4,FIVE=5,SIX=6,SEVEN=7,EIGHT=8,NIGHT=9,TEN=10,SOFTACE=11};
enum {DEALERMINPOINTS=17, BJPOINTS=21};
enum {BJWIN=0, WIN=1, PUSH=2, SURR=3, X=4};
const double BET=1.0; // bet for each game
const double PAYS[X] = {2.5, 2.0, 0, 0.5};

const int NONESTRATEGY=-1;
const int MAXSPLITS=3; // split into maximum 3 hands

bool HITSOFT17=true,
DOUBLE1011=true,
LATESURRENDER=true;

double totalPays=0, totalBets=0;
long SIMULATIONS = 10000000;
int ST[36][10] =
{
{H,H,H,H,H,H,H,H,H,H},
{H,H,H,H,H,H,H,H,H,H},
{H,H,H,H,H,H,H,H,H,H},
{H,H,H,H,H,H,H,H,H,H},
{H,Dh,Dh,Dh,Dh,H,H,H,H,H},
{Dh,Dh,Dh,Dh,Dh,Dh,Dh,Dh,H,H},
{Dh,Dh,Dh,Dh,Dh,Dh,Dh,Dh,Dh,Dh},
{H,H,S,S,S,H,H,H,H,H},
{S,S,S,S,S,H,H,H,H,H},
{S,S,S,S,S,H,H,H,H,H},
{S,S,S,S,S,H,H,H,Rh,Rh},
{S,S,S,S,S,H,H,Rh,Rh,Rh},
{S,S,S,S,S,S,S,S,S,Rs},
{S,S,S,S,S,S,S,S,S,S},
{S,S,S,S,S,S,S,S,S,S},
{S,S,S,S,S,S,S,S,S,S},
{S,S,S,S,S,S,S,S,S,S},
{H,H,H,Dh,Dh,H,H,H,H,H},
{H,H,H,Dh,Dh,H,H,H,H,H},
{H,H,Dh,Dh,Dh,H,H,H,H,H},
{H,H,Dh,Dh,Dh,H,H,H,H,H},
{H,Dh,Dh,Dh,Dh,H,H,H,H,H},
{Ds,Ds,Ds,Ds,Ds,S,S,H,H,H},
{S,S,S,S,Ds,S,S,S,S,S},
{S,S,S,S,S,S,S,S,S,S},
{S,S,S,S,S,S,S,S,S,S},
{P,P,P,P,P,P,H,H,H,H},
{P,P,P,P,P,P,H,H,H,H},
{H,H,H,P,P,H,H,H,H,H},
{Dh,Dh,Dh,Dh,Dh,Dh,Dh,Dh,H,H},
{P,P,P,P,P,H,H,H,H,H},
{P,P,P,P,P,P,H,H,H,H},
{P,P,P,P,P,P,P,P,P,Rp},
{P,P,P,P,P,S,P,P,S,S},
{S,S,S,S,S,S,S,S,S,S},
{P,P,P,P,P,P,P,P,P,P}
};

typedef struct _HAND
{
vector<int> cardRanks; // cardRanks carries the value after mapping the face value to value 1, 2, ..., 10 or 11
double pays, bets; // winning amount in credit for this hand
int points; // total points for this hand
int splits; // number of splits made
bool isBJ; // is blackjack?
bool isDD; // is double down?
bool isBUST; // is bust?
bool isSOFT; // is soft hand?
bool isSUR; // is surrender
bool endGame;

void reset(void)
{
cardRanks.clear();
bets = pays = 0.0;
points = splits = 0;
isBJ = isDD = isBUST = isSOFT = isSUR = endGame = false;
}

int countCard(void) {return cardRanks.size();}

void addCard(int card)
{
if (card==ACE)
{
if (!isSOFT) // if the hand is not a soft hand, make it soft by switching the ACE to 11
{
isSOFT = true;
card = SOFTACE;
}
}
cardRanks.push_back(card);
points += card; // add the rank of the card to the total points

if (points>BJPOINTS) // if bust
{
if (isSOFT) // if currently count as soft hand, try to reduce the 11 to ACE to see if bust also
{
for (int k=0; k<cardRanks.size(); k++)
{
if (cardRanks[k] == SOFTACE)
{
cardRanks[k] -= TEN;
points -= TEN;
isSOFT = false; // if SOFT hand, make it a HARD hand
break;
}
}

}
}
else isBUST = true;
}

bool checkBJ(void)
{
if ( (points==BJPOINTS) && (cardRanks.size()==2) ) // blackjack when two cards added up to 21
isBJ = true;
else isBJ = false;
return isBJ;
}

bool isPair(void)
{
if (cardRanks.size()==2)
{
return ( (cardRanks[0]==cardRanks[1]) ||
((cardRanks[0]==SOFTACE) && (cardRanks[1]==ACE)) ||
((cardRanks[1]==SOFTACE) && (cardRanks[0]==ACE)) );
}
else return false;
}

int splitable(const int &dealerUpcard)
{
if (isPair())
{
if ( (cardRanks[0]>=TWO) && (cardRanks[1]<=TEN) )
return ST[26+cardRanks[0]-TWO][dealerUpcard-2]; // refers to 22, 33, 44, ..., 99, TT
else return ST[35][dealerUpcard-2]; // refers to AA
}
else return NONESTRATEGY;
}

int removeLastCard4Split(void)
{
points -= cardRanks[1];
cardRanks.erase(cardRanks.begin()+1);
return cardRanks[0];
}
} HAND;

typedef map<int, int> DECK; // map<rank, number of cards>

const int NDECK = 8; // number of deck
const int RANKS = 10; // number of unique rank in blackjack (A, 2, 3, 4, 5, 6, 7, 8, 9, 10)
const int TOTALNUMCARDS = RANKS*13*4; // total number of cards in the shoe

DECK deck;

int DrawCard() // return card in rank
{
int card;
DECK::iterator it;
std::uniform_int_distribution<> rnd(1, RANKS); // return card of point 1, 2, ..., 10

while (true)
{
card = rnd(gen);
it = deck.find(card);
if ( (it!=deck.end()) && (deck[card]>0) )
{
deck[card]--;
if (deck[card]==0) deck.erase(it);
break;
}
}
return card;
}

int AppendCard(HAND &hand, int card=-1)
{
if (card==-1)
card=DrawCard(); // randomly draw one card from the deck if the given card is -1;
else // otherwise, add the given card to the hand and remove that card from the deck
{
DECK::iterator it;
if ( (it!=deck.end()) && (deck[card]>0) )
{
deck[card]--;
if (deck[card]==0) deck.erase(it);
}
}
hand.addCard(card); // add the card to the hand
return card;
}

void Estimate(HAND &player, HAND &dealer)
{
if ((dealer.isBUST) || (player.points>dealer.points)) // when dealer bust or player points more than dealer
{
if (player.isDD) player.pays += 2.0*PAYS[WIN];
else player.pays += PAYS[WIN];
}
else if (player.points>dealer.points)
{
if (player.isDD) player.pays += 2.0*PAYS[WIN];
else player.pays += PAYS[WIN];
}
else {player.pays += PAYS[PUSH];} // tie
//else {}
}

void DealerAction(HAND &dealer)
{
while (true)
{
if (dealer.isBUST) return;
else if ( (dealer.points<DEALERMINPOINTS) || ((dealer.points==DEALERMINPOINTS) && (dealer.isSOFT)) ) // dealer must hit when the dealer's total points less than 17 or when his hand is soft hand (HIT ON SOFT17)
AppendCard(dealer); // add a random card from the deck
else return; // if dealer's points more than 17, quit
}
}

void PlayerAction(HAND &player, int dealerUpcard)
{
int strategy;

// here player could be player first hand, first split hand or second split hand
if (player.countCard()==1) AppendCard(player); // if the player's hand only have 1 card, add a random card from the deck to it

while (!player.isBUST)
{
if (player.isPair()) // if it is still in pair
{
// check pair strategy. Since split tackled already, we should not have P or Rp here
if ( (player.cardRanks[0]>=TWO) && (player.cardRanks[1]<=TEN) )
strategy = ST[26+player.cardRanks[0]-TWO][dealerUpcard-2]; // refers to 22, 33, 44, ..., 99, TT
else strategy = ST[35][dealerUpcard-2]; // refers to AA
if ( (strategy==P) || (strategy==Rp) )
{
cerr << "error in pair (should not have any more split after splitting)" << endl;
exit(0);
}
}
else // if not pair, check strategy
{
if (player.isSOFT) // soft hand
strategy = STRATEGY[4+player.points][dealerUpcard-2];
else // hard hand
strategy = STRATEGY[player.points-5][dealerUpcard-2];
}

switch (strategy)
{
case S: return; // stand so return directly
case H:
{
AppendCard(player); // adding one more card from
break;
}
case Dh: case Ds:
{
if ( DOUBLE1011 && (player.points>=TEN) && (player.points<=SOFTACE) ) // if DD allowed, hit one card, double it and return
{
AppendCard(player);
player.isDD = true;
player.bets += BET;
return;
}
else if (strategy==Dh) AppendCard(player); // if not DD allowed, but can hit it, hit it
else if (strategy==Ds) return; // if not DD allowed, but can stand, stand it
break;
}
case Rh: case Rs: case Rp:
{
if (LATESURRENDER)
{
player.isSUR = true;
player.pays += PAYS[SURR];
return;
}
else if (strategy==Rh) AppendCard(player); // no surrender allowed but hit, hit it
else if (strategy==Rs) return; // no surrender allowed but stand, return
else if (strategy==Rp)
{
// should not see Rp as split because the splitting has be tackled already
cerr << "error in Rp (should not have any more split after splitting)" << endl;
exit(0);
}
break;
}
}
} // end while (!player.isBUST)
}

void InitializeHands(vector<HAND> &players, HAND &dealer)
{
players[0].reset(); // for main hand
players[1].reset(); // first split hand
players[2].reset(); // second split hand
dealer.reset();

// reset deck
deck.clear();
for (int card=ACE; card<=TEN; card++) deck.insert(std::pair<int, int>(card, 0)); // insert all the keys but keeps the count ZERO

for (int ndeck=1; ndeck<=NDECK; ndeck++)
{
for (int suit=1; suit<=4; suit++)
{
for(int card=1; card<=13; card++)
{
if (card<TEN) deck[card]++;
else deck[TEN]++;
}
}
} // end reset deck
}

void Simulation(void)
{
vector<HAND> players;
HAND dealer;
int strategy;

players.resize(3);
InitializeHands(players, dealer);

for (long samples = 0; samples < SIMULATIONS; samples++)
{
players[0].bets = BET;
AppendCard(players[0]);
AppendCard(players[0]);
AppendCard(dealer);
AppendCard(dealer);

players[0].checkBJ();
dealer.checkBJ();

if (players[0].isBJ)
{
players[0].endGame = true;
if (dealer.isBJ) {players[0].pays += PAYS[PUSH];} // BJ PUSH
else players[0].pays += PAYS[BJWIN]; // player BJ but dealer not
}
else if (dealer.isBJ) {players[0].endGame = players[1].endGame = players[2].endGame = true;} // dealer BJ but player not (end all player hands)
else
{
// let's check the pair and to see if we should split or not first
// check original hand
strategy = players[0].splitable(dealer.cardRanks[0]);
if ( (strategy==P) || ((strategy==Rp) && !LATESURRENDER) ) // split or (Rp => split)
{
AppendCard(players[1], players[0].removeLastCard4Split());
AppendCard(players[0]);
players[1].bets = BET;
players[0].splits++;

// if split the original hand, check the new-original hand again to see any possible split
strategy = players[0].splitable(dealer.cardRanks[0]);
if ( (strategy==P) || ((strategy==Rp) && !LATESURRENDER) ) // split or (Rp => split)
{
AppendCard(players[2], players[0].removeLastCard4Split());
AppendCard(players[0]);
players[2].bets = BET;
players[0].splits++;
}
else if ( (strategy==Rp) && LATESURRENDER ) // if Rp but surrender instead of split (players[0])
{
players[0].isSUR = true;
players[0].endGame = true;
players[0].pays += PAYS[SURR];
}
else // if new-original hand not split again, what about split hand, can it be split?
{
strategy = players[1].splitable(dealer.cardRanks[0]);
if ( (strategy==P) || ((strategy==Rp) && !LATESURRENDER) ) // if the players[1] hand splitable
{
AppendCard(players[2], players[1].removeLastCard4Split());
AppendCard(players[1]);
players[2].bets = BET;
players[0].splits++;
}
else if ( (strategy==Rp) && LATESURRENDER ) // if Rp => surrender (players[1])
{
players[1].isSUR = true;
players[1].endGame = true;
players[1].pays += PAYS[SURR];
}
}
}
else if ( (strategy==Rp) && LATESURRENDER ) // Rp => surrender (players[0])
{
players[0].isSUR = true;
players[0].endGame = true;
players[0].pays += PAYS[SURR];
}

// after considering splitting, we play each non-ended hands
for (int currentHand=0; currentHand<=players[0].splits; currentHand++)
{
if (players[currentHand].endGame)
{
PlayerAction(players[currentHand], dealer.cardRanks[0]); // dealer.cardRanks[0] is the up card in dealer's hand
}
}
}

if (!players[0].endGame || !players[1].endGame || !players[2].endGame)
{
DealerAction(dealer);
for (int currentHand=0; currentHand<=players[0].splits; currentHand++)
{
if (!players[currentHand].endGame)
{
Estimate(players[currentHand], dealer);
}
}
}

totalPays += players[0].pays + players[1].pays + players[2].pays;
totalBets += players[0].bets + players[1].bets + players[2].bets;
InitializeHands(players, dealer);
if (samples%1000000==0) cout << "RTP: " << (double)totalPays/(double)totalBets << " HOUSE EDGE:" << 100.0-100.0*(double)totalPays/(double)totalBets << "%" << endl;
} // for (samples ...
}

int main(void)
{
Simulation();
system("pause");
return 0;
}

Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 16th, 2015 at 4:26:01 PM permalink
Quote: konglify


3) after the hand evaluated, calculate the total pay. The game is pay 3:2 for BJ, 1:1 for regular winning, 0:1 for push and -0.5:1 for surrender. So the pays will be

2.5 if player BJ win
2 if player wins (without BJ)
0 if player push
0.5 if player surrender



Try

0 for loss
.5 for surrender
1 for push
2 for win
2.5 for BJ win

Edit: those are the "for 1" pays, not the "to 1" pays.
May the cards fall in your favor.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 16th, 2015 at 4:34:21 PM permalink
Quote: Dieter

Try

0 for loss
.5 for surrender
1 for push
2 for win
2.5 for BJ win

Edit: those are the "for 1" pays, not the "to 1" pays.



I just try but I still get the very strange house edge (-97%). In the code, I am accumulating the pays for each hand and divide the total pays by total bets (same as the number of hands after considering the split), which gives the player payback so the house edge is

1 - total pays/total bets

but I get very negative number. I think there mush be something wrong in my code but I spent couple days to program it and cannot figure out the problem
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 16th, 2015 at 5:44:29 PM permalink
Dumb question - should AppendCard be getting called with the -1 second argument?

Not fluent enough in that language to recognize if -1 is passed in place of an unspecified argument, or 0, or NULL, or something else.
May the cards fall in your favor.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 16th, 2015 at 7:10:57 PM permalink
Quote: Dieter

Dumb question - should AppendCard be getting called with the -1 second argument?

Not fluent enough in that language to recognize if -1 is passed in place of an unspecified argument, or 0, or NULL, or something else.



thanks for the reply. in C++, we could make default argument, so I set the default value to -1, so if ignore the second parameter, it will use -1 instead (and -1 means randomly draw one card from the deck).

BTW, do you know any open source BJ simulator that I can refer to so to see how people simulate the game?
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 6013
Joined: Jul 23, 2014
February 17th, 2015 at 2:28:01 AM permalink
Quote: konglify

BTW, do you know any open source BJ simulator that I can refer to so to see how people simulate the game?



No particular experience with either, but look for "blackjacksim-py" and "blackjack powersim" to start.

There are surely others.
May the cards fall in your favor.
ThatDonGuy
ThatDonGuy
  • Threads: 122
  • Posts: 6679
Joined: Jun 22, 2011
February 17th, 2015 at 6:52:21 AM permalink
My C++ is not as sharp as I would like it to be, but I see something that doesn't seem to make much sense.

It appears as if the DrawCard() function is doing this:

Get a uniformly random integer N in {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
If there are any cards of rank N left in the deck:
. Subtract 1 from the number of cards of rank N in the deck
. If the number of cards of rank N is now 0:
..... Remove N from the deck
..... Exit the function
. Otherwise:
..... Repeat the function

This has two problems.
First, using this method, you are just as likely to draw an Ace (for example) from a full deck as you are a 10.
Second, as long as there is at least one card of a particular value in the deck, you are just as likely to draw a card of that value as a card of any other value.

What I normally do is, something like this:

int DECKS = 8;
int[52*DECKS] deck
int N;

// Populate the deck

for (N = 0; N < 36 * DECKS; N++)
{
deck[N] = N % 9 + 1;
}
for (N = 36 * DECKS; N < 52 * DECKS; N++)
{
deck[N] = 10;
}

// Shuffle the deck as follows:
// Starting with the last card, randomly select a card from the first one to the "current" one, and swap them
// Repeat with the next-to-last card, then the card before that, and so on until you reach the first card

int C, Z;
for (N = 52 * DECKS - 1; N >= 1; N--)
{
C = rand() % N;
if (C < N)
{
Z = deck
;
deck
= deck[N];
deck[N] = Z;
}
}

C = 0;
// C points to the top card in the deck

N = Deck[C++];
// N is the value of the top card in the deck; C now points to what is now the top card
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 17th, 2015 at 1:26:23 PM permalink
Quote: ThatDonGuy

My C++ is not as sharp as I would like it to be, but I see something that doesn't seem to make much sense.

It appears as if the DrawCard() function is doing this:

Get a uniformly random integer N in {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
If there are any cards of rank N left in the deck:
. Subtract 1 from the number of cards of rank N in the deck
. If the number of cards of rank N is now 0:
..... Remove N from the deck
..... Exit the function
. Otherwise:
..... Repeat the function

This has two problems.
First, using this method, you are just as likely to draw an Ace (for example) from a full deck as you are a 10.
Second, as long as there is at least one card of a particular value in the deck, you are just as likely to draw a card of that value as a card of any other value.

What I normally do is, something like this:


int DECKS = 8;
int[52*DECKS] deck
int N;

// Populate the deck

for (N = 0; N < 36 * DECKS; N++)
{
deck[N] = N % 9 + 1;
}
for (N = 36 * DECKS; N < 52 * DECKS; N++)
{
deck[N] = 10;
}

// Shuffle the deck as follows:
// Starting with the last card, randomly select a card from the first one to the "current" one, and swap them
// Repeat with the next-to-last card, then the card before that, and so on until you reach the first card

int C, Z;
for (N = 52 * DECKS - 1; N >= 1; N--)
{
C = rand() % N;
if (C < N)
{
Z = deck
;
deck
= deck[N];
deck[N] = Z;
}
}

C = 0;
// C points to the top card in the deck

N = Deck[C++];
// N is the value of the top card in the deck; C now points to what is now the top card



Thank you for pointing that out. I appreciate your code also. I apply your code instead. Now the house edge changed from -97% to -94%. But it is still not consistent to wizard of odds. I think the way that I handle strategy is not correct but I can't figure where.
ThatDonGuy
ThatDonGuy
  • Threads: 122
  • Posts: 6679
Joined: Jun 22, 2011
February 17th, 2015 at 1:41:52 PM permalink
Part of the code came out wrong - it converted "[C]" to a newline. It should be:

if (C < N)
{
Z = deck[C];
deck[C] = deck[N];
deck[N] = Z;
}
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 17th, 2015 at 1:49:07 PM permalink
Quote: ThatDonGuy

Part of the code came out wrong - it converted "[C]" to a newline. It should be:


if (C < N)
{
Z = deck[C];
deck[C] = deck[N];
deck[N] = Z;
}



I fixed that also but result the same.
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 17th, 2015 at 9:14:49 PM permalink
Quote: Dieter

No particular experience with either, but look for "blackjacksim-py" and "blackjack powersim" to start.

There are surely others.


I wonder if anyone has any experience in using blacksim-py. The sample code is like

from Blackjack import *

p = Player("Joe")

basic = {}

basic['P2'] = ['P', 'P', 'P', 'P', 'P', 'P', 'H', 'H', 'H', 'H']
basic['P3'] = ['P', 'P', 'P', 'P', 'P', 'P', 'H', 'H', 'H', 'H']
basic['P4'] = ['H', 'H', 'H', 'P', 'P', 'H', 'H', 'H', 'H', 'H']
basic['P5'] = ['D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'H', 'H']
basic['P6'] = ['P', 'P', 'P', 'P', 'P', 'H', 'H', 'H', 'H', 'H']
basic['P7'] = ['P', 'P', 'P', 'P', 'P', 'P', 'H', 'H', 'H', 'H']
basic['P8'] = ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P']
basic['P9'] = ['P', 'P', 'P', 'P', 'P', 'S', 'P', 'P', 'S', 'S']
basic['P10'] = ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']
basic['P1'] = ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P']
basic['A2'] = ['H', 'H', 'H', 'D', 'D', 'H', 'H', 'H', 'H', 'H']
basic['A3'] = ['H', 'H', 'H', 'D', 'D', 'H', 'H', 'H', 'H', 'H']
basic['A4'] = ['H', 'H', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'H']
basic['A5'] = ['H', 'H', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'H']
basic['A6'] = ['H', 'D', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'H']
basic['A7'] = ['S', 'D', 'D', 'D', 'D', 'S', 'S', 'H', 'H', 'H']
basic['A8'] = ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']
basic['A9'] = ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']
basic['A10'] = ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']
basic['3'] = ['H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H']
basic['4'] = ['H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H']
basic['5'] = ['H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H']
basic['6'] = ['H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H']
basic['7'] = ['H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H']
basic['8'] = ['H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H']
basic['9'] = ['H', 'D', 'D', 'D', 'D', 'H', 'H', 'H', 'H', 'H']
basic['10'] = ['D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'H', 'H']
basic['11'] = ['D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'H']
basic['12'] = ['H', 'H', 'S', 'S', 'S', 'H', 'H', 'H', 'H', 'H']
basic['13'] = ['S', 'S', 'S', 'S', 'S', 'H', 'H', 'H', 'H', 'H']
basic['14'] = ['S', 'S', 'S', 'S', 'S', 'H', 'H', 'H', 'H', 'H']
basic['15'] = ['S', 'S', 'S', 'S', 'S', 'H', 'H', 'H', 'H', 'H']
basic['16'] = ['S', 'S', 'S', 'S', 'S', 'H', 'H', 'H', 'H', 'H']
basic['17'] = ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']
basic['18'] = ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']
basic['19'] = ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']
basic['20'] = ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']
basic['21'] = ['S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S', 'S']


p.setStrategyByCount('N', basic)
p.setStrategyByCount('L', basic)
p.setStrategyByCount('M', basic)
p.setStrategyByCount('H', basic)
p.setStrategyByCount('VH', basic)

game = BlackjackGame(8, 1.5, 0, [p])

outcomes = []
episodes = 10000

for k in range(0, episodes):
game.dealer.shuffleDeck()
for i in range(0, 100):
game.playRound(False)
outcomes.append(p.getBankroll())
print str(p.getBankroll())
p.setBankroll(0)
if k % 10 == 0 and k > 0:
print "Episode " + str(k)


Does any know how to use the bankroll (or outcomes) to find out the house edge? I read the code and modify few things to calculate the house edge.

1) I modify the code such that it only records the pays for player's winning hand

in blackjack.py, modify


if winner == 2: #win by blackjack
p.adjustBankroll(self.blackjackpayoff*hand.getWager())
else: ORIGINAL
p.adjustBankroll(winner*hand.getWager()) ORIGINAL


to


if winner == 2: #win by blackjack
p.adjustBankroll(self.blackjackpayoff*hand.getWager())
elif winner>0: # regular win
p.adjustBankroll(winner*hand.getWager())


2) I add a function to accumulate the total wager (bet)

in blackjackPlayer.py, adding

def getTotalWagers(self):
return self.totalWagers
def setTotalWagers(self, br):
self.totalWagers = br
def adjustWagers(self, amount): # accumulating total bets
self.totalWagers = self.totalWagers + amount


The total house edge is 1 - total win /total bets, so in sample.py, I change


outcomes = []
incomes = []
episodes = 10000

for k in range(0, episodes):
game.dealer.shuffleDeck()
for i in range(0, 100):
game.playRound(False)
outcomes.append(p.getBankroll())
incomes.append(p.getTotalWagers())
p.setBankroll(0)
p.setTotalWagers(0)
if k % 10 == 0 and k > 0:
print "Episode " + str(k)

print "Final bankroll: " + str(sum(outcomes))
print "Final wagers: " + str(sum(incomes))
HOUSE = 1-float(sum(outcomes))/float(sum(incomes));


But it gave me 53.1% as the house edge. Am I doing anything wrong with that code?
konglify
konglify
  • Threads: 28
  • Posts: 160
Joined: Aug 28, 2014
February 26th, 2015 at 2:21:13 PM permalink
This update has been removed. I found the BUG, will modify it and upload again.
  • Jump to: