Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 18th, 2015 at 4:58:01 PM permalink
Hi all,

I'm working on a project coding a blackjack simulation that will produce a composition dependent basic strategy.
I'm using the Wizard's table to check my EV numbers: https://wizardofodds.com/games/blackjack/appendix/9/2ds17r4/

I've only coded the "Stand" decision so far, but I'm finding all of my EV numbers are 2%-4% lower than the Wizard's across the board and I can't figure out why.

Here's the process flow I'm using:

Play:
User determines the two player cards and dealer up card.
Those cards are removed from the starting shoe.
The shoe is shuffled.
The dealer's hole card is dealt.
The dealer peaks for BJ.
The player stands.
The dealer hits as long as their total is below 17. (Assuming Stand 17)


Store results in array:
Dealer wins recorded as -1.
Pushes recorded as 0.
Player wins recorded as 1.

sum(array)/count(array) = EV

Then I start back at the top with a fresh shoe/shuffle and the same hand for X iterations.


Is there something incorrect with this logic?


Edit:
The number differences are largest when the dealer is showing an Ace. I double checked my code and can't find any errors in the dealer's hit logic. Right now I'm testing 10+7 V A and I'm getting -61% instead of -47%

Here's a sample of the outputs.





===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 10
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 8
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 9
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 4
--------------------------------
Current Dealer Total: 15
--------------------------------
Dealer takes a card: 9
New Dealer total: 24
Dealer hand is soft: Y
--------------------------------
Current Dealer Total: 14
--------------------------------
Dealer takes a card: 6
New Dealer total: 20
Dealer hand is soft: N
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 10
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 2
--------------------------------
Current Dealer Total: 13
--------------------------------
Dealer takes a card: 3
New Dealer total: 16
Dealer hand is soft: Y
--------------------------------
Current Dealer Total: 16
--------------------------------
Dealer takes a card: 3
New Dealer total: 19
Dealer hand is soft: N
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 5
--------------------------------
Current Dealer Total: 16
--------------------------------
Dealer takes a card: 7
New Dealer total: 23
Dealer hand is soft: Y
--------------------------------
Current Dealer Total: 13
--------------------------------
Dealer takes a card: 2
New Dealer total: 15
Dealer hand is soft: N
--------------------------------
Current Dealer Total: 15
--------------------------------
Dealer takes a card: 4
New Dealer total: 19
Dealer hand is soft: N
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 9
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 6
--------------------------------
0
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 6
--------------------------------
0
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 9
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 7
--------------------------------
-1
===============End Trial===============




===============Start Trial===============
Player stands on 17
--------------------------------
Dealer starting hand is 11 2
--------------------------------
Current Dealer Total: 13
--------------------------------
Dealer takes a card: 10
New Dealer total: 23
Dealer hand is soft: Y
--------------------------------
Current Dealer Total: 13
--------------------------------
Dealer takes a card: 10
New Dealer total: 23
Dealer hand is soft: N
--------------------------------
1
===============End Trial===============


ThatDonGuy
ThatDonGuy
  • Threads: 117
  • Posts: 6293
Joined: Jun 22, 2011
August 18th, 2015 at 6:43:19 PM permalink
I think your first hand answers the question.

The numbers on the Wizard's site assume the dealer does not have a 2-card 21. (After all, there's no need for "strategy" if you lose before you can do anything.) You are counting it as a loss.

If you assign 0 instead of -1 when the dealer has a 2-card 21, your numbers should be closer to the Wizard's.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 18th, 2015 at 7:17:35 PM permalink
Ah okay that makes sense.

Still curious why all of my other hands are off by a few % though when te dealer can't possibly have a natural.
beachbumbabs
beachbumbabs
  • Threads: 100
  • Posts: 14265
Joined: May 21, 2013
August 19th, 2015 at 9:28:46 AM permalink
Quote: Donuts

Ah okay that makes sense.

Still curious why all of my other hands are off by a few % though when te dealer can't possibly have a natural.



All your other hands are affected by the % of times they're negated by a natural. I don't think you've fully accounted for that. Your hands as currently programmed have not been filtered by the times they're beaten before a player decision has been made; they all assume the dealer has not yet acted, but the dealer pre-empts the hand in non ENHC BJ with the peek. I don't see where the peek has been programmed (with its attendant losses) as a pre-requisite to even choosing to stand.

Not that I know how to account for this in your stats, but subtracting out that pre-emptive possibility would raise all your stand EV's because they would no longer be measured against that (negative) outcome as well as any non-natural 2nd card. In effect, you're counting that natural twice by your methodology.

I think. I could be wrong.
If the House lost every hand, they wouldn't deal the game.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 19th, 2015 at 10:28:44 AM permalink
Quote: beachbumbabs

All your other hands are affected by the % of times they're negated by a natural. I don't think you've fully accounted for that. Your hands as currently programmed have not been filtered by the times they're beaten before a player decision has been made; they all assume the dealer has not yet acted, but the dealer pre-empts the hand in non ENHC BJ with the peek. I don't see where the peek has been programmed (with its attendant losses) as a pre-requisite to even choosing to stand.

Not that I know how to account for this in your stats, but subtracting out that pre-emptive possibility would raise all your stand EV's because they would no longer be measured against that (negative) outcome as well as any non-natural 2nd card. In effect, you're counting that natural twice by your methodology.

I think. I could be wrong.



I thought that too initially but if I'm looking a hand like 14v8 for example, there's no way the dealer could have a natural.
beachbumbabs
beachbumbabs
  • Threads: 100
  • Posts: 14265
Joined: May 21, 2013
August 19th, 2015 at 11:42:19 AM permalink
Quote: Donuts

I thought that too initially but if I'm looking a hand like 14v8 for example, there's no way the dealer could have a natural.



I guess what I'm saying is that there's a qualifier process your method is skipping, that the wizard's didn't. A certain percentage of 14's are going to auto-lose to dealer's BJ. So only those hands that progress past that initial barrier will be considered. That means that, of the total hands you're using to determine your percentage, you haven't subtracted out those which will auto-lose regardless of value. So I think you're using the wrong total hand denominator in your calculations. It should be total possible hands, less hands that will lose to a natural. Perhaps. Again, I could be wrong.
If the House lost every hand, they wouldn't deal the game.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 19th, 2015 at 12:18:37 PM permalink
Quote: beachbumbabs

I guess what I'm saying is that there's a qualifier process your method is skipping, that the wizard's didn't. A certain percentage of 14's are going to auto-lose to dealer's BJ. So only those hands that progress past that initial barrier will be considered. That means that, of the total hands you're using to determine your percentage, you haven't subtracted out those which will auto-lose regardless of value. So I think you're using the wrong total hand denominator in your calculations. It should be total possible hands, less hands that will lose to a natural. Perhaps. Again, I could be wrong.



I think you're correct for all hands where the dealer is showing a 10 or Ace. I adjusted my code to reflect that.
ThatDonGuy
ThatDonGuy
  • Threads: 117
  • Posts: 6293
Joined: Jun 22, 2011
August 19th, 2015 at 12:47:20 PM permalink
Quote: Donuts

Still curious why all of my other hands are off by a few % though when te dealer can't possibly have a natural.



Pardon me for asking this, but are you making sure that your shoe only has 2 decks?
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 19th, 2015 at 1:50:14 PM permalink
Yeah it definitely has only two decks.

Figured out the problem: my shuffle wasn't thorough enough so my shoes weren't technically random.
Anyone know a fast/thorough shuffle algorithm?
ThatDonGuy
ThatDonGuy
  • Threads: 117
  • Posts: 6293
Joined: Jun 22, 2011
August 19th, 2015 at 2:11:44 PM permalink
Quote: Donuts

Yeah it definitely has only two decks.

Figured out the problem: my shuffle wasn't thorough enough so my shoes weren't technically random.
Anyone know a fast/thorough shuffle algorithm?



Here's one, in C/Java-style code:

(random.next(n) returns an integer in the range 0 to (n-1))

int[104]  deck;
int d;
int n;
int z;

// Populate deck[] with the numbers 0-51, each appearing twice
for (d = 0; d < 104; d++)
{
deck[d] = d / 2;
}

// Shuffle
for (d = 103; d >= 1; d--)
{
n = random.next(d + 1);
if (n < d)
{
z = deck[n];
deck[n] = deck[d];
deck[d] = z;
}
}
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 19th, 2015 at 4:39:51 PM permalink
Quote: ThatDonGuy

Here's one, in C/Java-style code:

(random.next(n) returns an integer in the range 0 to (n-1))

int[104]  deck;
int d;
int n;
int z;

// Populate deck[] with the numbers 0-51, each appearing twice
for (d = 0; d < 104; d++)
{
deck[d] = d / 2;
}

// Shuffle
for (d = 103; d >= 1; d--)
{
n = random.next(d + 1);
if (n < d)
{
z = deck[n];
deck[n] = deck[d];
deck[d] = z;
}
}



That's actually the one I'm using. Its not thorough enough for some reason. I have to iterate the shuffle 3-4 times to get my numbers within .01% of the Wizard's.
ThatDonGuy
ThatDonGuy
  • Threads: 117
  • Posts: 6293
Joined: Jun 22, 2011
August 20th, 2015 at 6:16:26 AM permalink
Quote: Donuts

That's actually the one I'm using. Its not thorough enough for some reason. I have to iterate the shuffle 3-4 times to get my numbers within .01% of the Wizard's.


It could be the underlying Random Number Generator that's the problem. How (if at all) do you seed it?
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 20th, 2015 at 6:09:27 PM permalink
Quote: ThatDonGuy

It could be the underlying Random Number Generator that's the problem. How (if at all) do you seed it?



That's my guess.

I'm in VBA atm so I'm using Randomize to initialize and rnd as the random number generator. May not be sufficient.

using 2x Rnd helps significantly though:

Randomize

For i = 1 To 2000
c1 = Int(101 * Rnd * Rnd)
c2 = Int(101 * Rnd * Rnd)
temp = shoe(c1)
shoe(c1) = shoe(c2)
shoe(c2) = temp
Next i
ThatDonGuy
ThatDonGuy
  • Threads: 117
  • Posts: 6293
Joined: Jun 22, 2011
August 20th, 2015 at 6:26:13 PM permalink
Quote: Donuts


For i = 1 To 2000
c1 = Int(101 * Rnd * Rnd)
c2 = Int(101 * Rnd * Rnd)
temp = shoe(c1)
shoe(c1) = shoe(c2)
shoe(c2) = temp
Next i


First of all, rnd * rnd does not generate uniform random numbers. Think about it; if "rnd" chose a number from 1 to 10,000, then 10,000 would come up far more times than 1,000,000. (Also, why do you multiply by 101? There are 104 cards in the shoe.)

Second, if this is the method that you have been using all along, then it's nothing like the one I mentioned - and the reason it wouldn't have worked is, even with 2000 shuffles, it's fairly likely that few, if any, of the top cards in the shoe would have been shuffled.

What you want is:

Randomize
For i = 104 to 2 step -1
c = int(Rnd * i + 1)
If c < i Then
temp = shoe(c)
shoe(c) = shoe(i)
shoe(i) = temp
End If
Next i
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 20th, 2015 at 6:36:49 PM permalink
Quote: ThatDonGuy

First of all, rnd * rnd does not generate uniform random numbers. Think about it; if "rnd" chose a number from 1 to 10,000, then 10,000 would come up far more times than 1,000,000. (Also, why do you multiply by 101? There are 104 cards in the shoe.)

Second, if this is the method that you have been using all along, then it's nothing like the one I mentioned - and the reason it wouldn't have worked is, even with 2000 shuffles, it's fairly likely that few, if any, of the top cards in the shoe would have been shuffled.

What you want is:

Randomize
For i = 104 to 2 step -1
c = int(Rnd * i + 1)
If c < i Then
temp = shoe(c)
shoe(c) = shoe(i)
shoe(i) = temp
End If
Next i




Good call on the rnd*rnd realized that after I tested it a few times.

I'm only going to 101 since three cards will have already been dealt: 2 to the player and 1 to the dealer. (I pick those cards).

So I actually started off with the shuffle in your last post, I think its called the fisher-yates shuffle, and I found it produced significantly less accurate results than the one I'm using now.
Maybe I implemented it wrong? I'll try again.
ThatDonGuy
ThatDonGuy
  • Threads: 117
  • Posts: 6293
Joined: Jun 22, 2011
August 20th, 2015 at 6:38:40 PM permalink
Quote: Donuts

So I actually started off with the shuffle in your last post, I think its called the fisher-yates shuffle, and I found it produced significantly less accurate results than the one I'm using now.

Maybe I implemented it wrong? I'll try again.


When you do implement it, post the code you use for the shuffle. I'll see if I can find the problem.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 20th, 2015 at 6:52:01 PM permalink
Quote: ThatDonGuy

When you do implement it, post the code you use for the shuffle. I'll see if I can find the problem.



I'm testing the hand AA v 2 player stands. The EV for this hand when standing is about -28.3%. The shuffle I was previously using got me within .1%-.2% of that.

Now I'm getting EV numbers between -11% and -14% instead with the fisher-yates shuffle.

The only piece of code I changed was this string:
(Going 0-100 since there are 101 cards left in the shoe)

Sub ShuffleArrayInPlace(shoe)

Randomize
For i = 100 to 0 step -1
c = int(Rnd * i + 1)
If c < i Then
temp = shoe(c)
shoe(c) = shoe(i)
shoe(i) = temp
End If
Next i


'Worksheets("Sheet1").Range("F1:F104") = WorksheetFunction.Transpose(shoe)

End Sub
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 20th, 2015 at 7:01:48 PM permalink
Sub ShuffleArrayInPlace(shoe)

Randomize
For i = 100 to 0 step -1
c = int(Rnd * i + 1)
If c < i Then
temp = shoe(c)
shoe(c) = shoe(i)
shoe(i) = temp
End If
Next i


'Worksheets("Sheet1").Range("F1:F104") = WorksheetFunction.Transpose(shoe)

End Sub

Ah found the error. the +1 keeps the first card in the same position. Trying again without that.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 20th, 2015 at 7:05:58 PM permalink
Quote: Donuts

Sub ShuffleArrayInPlace(shoe)

Randomize
For i = 100 to 0 step -1
c = int(Rnd * i + 1)
If c < i Then
temp = shoe(c)
shoe(c) = shoe(i)
shoe(i) = temp
End If
Next i


'Worksheets("Sheet1").Range("F1:F104") = WorksheetFunction.Transpose(shoe)

End Sub

Ah found the error. the +1 keeps the first card in the same position. Trying again without that.



This moved all of the cards in the shoe but my results are still off by about .5% now up from the .1% to .2% before.
ThatDonGuy
ThatDonGuy
  • Threads: 117
  • Posts: 6293
Joined: Jun 22, 2011
August 21st, 2015 at 7:28:20 AM permalink
Aren't arrays in VBA 1-based (i.e. the first term is shoe(1), not shoe(0))?

If it is, then what your code does is:
Switch shoe(100) with shoe(some number from 1 to 100)
Switch shoe(99) with shoe(some number from 1 to 99)
Switch shoe(98) with shoe(some number from 1 to 98)
...
Switch shoe(3) with shoe(1, 2, or 3)
Switch shoe(2) with shoe(1 or 2)
However, shoe(101) never moves.

If the array is zero-based, then your shoe(0) term is never going to change - your third line should be:

c = int (Rnd * (i + 1))

As it is, c is between 1 and i.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 10:00:49 AM permalink
Quote: ThatDonGuy

Aren't arrays in VBA 1-based (i.e. the first term is shoe(1), not shoe(0))?

If it is, then what your code does is:
Switch shoe(100) with shoe(some number from 1 to 100)
Switch shoe(99) with shoe(some number from 1 to 99)
Switch shoe(98) with shoe(some number from 1 to 98)
...
Switch shoe(3) with shoe(1, 2, or 3)
Switch shoe(2) with shoe(1 or 2)
However, shoe(101) never moves.

If the array is zero-based, then your shoe(0) term is never going to change - your third line should be:

c = int (Rnd * (i + 1))

As it is, c is between 1 and i.



It's definitely 0-100 in this case , probably due to the way I built it.

Modified the code to what you see below, but I'm still off by a few 1/10th of a percent.

Randomize
For i = 100 To 0 Step -1
c = Int(Rnd * (i + 1))
If c < i Then
temp = shoe(c)
shoe(c) = shoe(i)
shoe(i) = temp
End If
Next i
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
August 21st, 2015 at 10:14:59 AM permalink
Try shoe(i+1) in place of shoe(i).
I heart Crystal Math.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 10:19:26 AM permalink
Quote: CrystalMath

Try shoe(i+1) in place of shoe(i).



Throws "Subscript out of range" since it can't find shoe(i + 1) when i = 100 since the array is 0-100.

Randomize
For i = 100 To 0 Step -1
c = Int(Rnd * (i + 1))
If c < i Then
temp = shoe(c)
shoe(c) = shoe(i + 1)
shoe(i) = temp
End If
Next i

I just transposed the arrays onto a worksheet and it looks like everything's being randomized but there's clearly an issue with the quality of randomization.


3 9
4 11
5 10
6 9
7 10
8 10
9 4
10 9
10 10
10 2
10 10
2 4
3 6
4 9
5 10
6 10
7 11
8 10
9 11
10 5
10 8
10 4
10 8
2 10
3 5
4 10
5 10
6 3
7 4
8 10
9 8
10 7
10 9
10 3
10 10
11 10
2 9
3 10
4 10
5 6
6 5
7 5
8 9
9 6
10 11
10 4
10 3
10 10
11 10
2 11
3 8
4 10
5 3
6 10
7 8
8 10
9 10
10 3
10 6
10 5
10 5
11 7
2 6
3 7
4 10
5 2
6 10
7 10
8 7
9 10
10 6
10 5
10 4
10 7
11 4
2 7
3 3
4 10
5 2
6 10
7 7
8 8
9 3
10 2
10 10
10 5
10 8
11 3
2 6
3 10
4 2
5 10
6 9
7 2
8 6
9 11
10 10
10 7
10 4
10 2
11 8
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
August 21st, 2015 at 10:25:43 AM permalink
Ok. What looks odd to me is that c ranges from 1 to i+1. Shouldn't it range from 0 to i?

Edit: I'm wrong here.
I heart Crystal Math.
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
August 21st, 2015 at 10:35:48 AM permalink
Do you call randomize every time you shuffle? If so, any shuffles started during the same second will be the same. You should only call it once.
I heart Crystal Math.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 10:47:21 AM permalink
Quote: CrystalMath

Do you call randomize every time you shuffle? If so, any shuffles started during the same second will be the same. You should only call it once.



The order of operations:

Set player/dealer hands

For 1 to X
Create new shoe
Remove player/dealer hards
Randomize
Shuffle
Finish hands
Record Results (-1, 0 +1)
Next X

Results/X = EV


Should I only be randomizing once at the beginning of the code?
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 5564
Joined: Jul 23, 2014
August 21st, 2015 at 10:52:58 AM permalink
Quote: Donuts


Randomize
For i = 100 To 0 Step -1
c = Int(Rnd * (i + 1))
If c < i Then
temp = shoe(c)
shoe(c) = shoe(i + 1)
shoe(i) = temp
End If
Next i



Why are you only swapping values if c<i?
Shouldn't it be

temp=shoe(c)
shoe(c)=shoe(i) << change
shoe(i)=temp

So that you don't lose a value?

It shouldn't matter if you're iterating 100 to 0 or 0 to 100, right? You could simplify the program with the possibly more readily optimizable
For i = 0 to 100
c = Int(Rnd * (i + 1))

temp = shoe(c)
shoe(c) = shoe(i)
shoe(i) = temp

Next i
May the cards fall in your favor.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 10:56:25 AM permalink
Quote: Dieter

Why are you only swapping values if c<i?
Shouldn't it be

temp=shoe(c)
shoe(c)=shoe(i) << change
shoe(i)=temp

So that you don't lose a value?

It shouldn't matter if you're iterating 100 to 0 or 0 to 100, right? You could simplify the program with the possibly more readily optimizable

For i = 0 to 100
c = Int(Rnd * (i + 1))

temp = shoe(c)
shoe(c) = shoe(i)
shoe(i) = temp

Next i



I'll try this. Not sure one why we care if c < i, Donguy suggested the code so he probably has a good reason.
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
August 21st, 2015 at 10:57:04 AM permalink
Quote: Donuts



Should I only be randomizing once at the beginning of the code?


Yes.
I heart Crystal Math.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 11:01:37 AM permalink
Quote: CrystalMath

Yes.



Just tried this - no change in the results. Still off by a few 10ths of a %.


As for Dieter's suggestion (code below), still off by .5%. I also tried this code with randomize called once and got the same results.
For some reason removing the if statement actually causes a performance decline.

For i = 0 to 100
c = Int(Rnd * (i + 1))

temp = shoe(c)
shoe(c) = shoe(i)
shoe(i) = temp

Next i
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
August 21st, 2015 at 12:30:26 PM permalink
I just calculated standing on 2 vs 2A, and I get -0.6646142886031181, which matches the Wizard. I just wanted to rule out that there might be an error in the table.

This is the ev given that the dealer did not have a blackjack.

How close do you come when you start with a dealer card which is not an ace or a ten?
I heart Crystal Math.
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 5564
Joined: Jul 23, 2014
August 21st, 2015 at 12:30:35 PM permalink
OK, had a look at wikipedia's explanation of a Fisher Yates shuffle. (It's been a while.)

Quote: Wikipedia

To shuffle an array a of n elements (indices 0..n-1):
for i from n − 1 downto 1 do
j ← random integer such that 0 ≤ j ≤ i
exchange a{j} and a{i}



The order may be important (ascending vs descending), but I'm not convinced it is.

There's no point in iterating from 0 to 100; when i=0, j must equal 0 to satisfy 0 ≤ j ≤ i, and there is no point in swapping an element with itself.

The if c<i conditional in the original may slightly optimize the code; for me, its purpose would make more sense if it was expressed as if c <> i . (I would understand it better if it was !=, as nature intended, but I'll live.)
May the cards fall in your favor.
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 5564
Joined: Jul 23, 2014
August 21st, 2015 at 12:38:33 PM permalink
Quote: Donuts


Then I start back at the top with a fresh shoe/shuffle and the same hand for X iterations.



How many iterations?
May the cards fall in your favor.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 12:56:51 PM permalink
Quote: CrystalMath

I just calculated standing on 2 vs 2A, and I get -0.6646142886031181, which matches the Wizard. I just wanted to rule out that there might be an error in the table.

This is the ev given that the dealer did not have a blackjack.

How close do you come when you start with a dealer card which is not an ace or a ten?



I'm within .1% and .5% for all hands, including 10/A hands.

For that hand specifically (A2V2) I get -0.28.
I think you mean A2 V A - I get -0.666742
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 12:57:07 PM permalink
Quote: Dieter

How many iterations?



1M
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
August 21st, 2015 at 1:51:53 PM permalink
Quote: Donuts

I'm within .1% and .5% for all hands, including 10/A hands.

For that hand specifically (A2V2) I get -0.28.
I think you mean A2 V A - I get -0.666742



Correct A2 V A.
I heart Crystal Math.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 1:57:39 PM permalink
Quote: CrystalMath

Correct A2 V A.




Do you think .1%-.5% matters?

The entire purpose of this is generating index plays for any TC/hand combination. I'm not sure a fraction of a % of EV will matter.
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
August 21st, 2015 at 3:37:04 PM permalink
Quote: Donuts

Do you think .1%-.5% matters?

The entire purpose of this is generating index plays for any TC/hand combination. I'm not sure a fraction of a % of EV will matter.



It probably won't make much difference, but this would keep me up at night.
I heart Crystal Math.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 4:32:54 PM permalink
Quote: CrystalMath

It probably won't make much difference, but this would keep me up at night.



Yeah I spent a few hours actually writing the code and the last week trying to figure out why I'm off by a tenth of a percent. It's driving me nuts.

I've checked and rechecked every single part of my code and the only thing that changes the number in any way is the shuffle procedure, but I can't figure out how to make that work.

Are you using java in your sim?
ThatDonGuy
ThatDonGuy
  • Threads: 117
  • Posts: 6293
Joined: Jun 22, 2011
August 21st, 2015 at 4:59:58 PM permalink
Try doing the full shuffle loop twice in a row, and then see if the numbers look better
CrystalMath
CrystalMath
  • Threads: 8
  • Posts: 1911
Joined: May 10, 2011
August 21st, 2015 at 5:33:36 PM permalink
Quote: Donuts


Are you using java in your sim?



I do use Java, but mine is a calculation and not a sim. Many years ago, I did a lot in VBS, but it was excruciatingly slow.
I heart Crystal Math.
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 5564
Joined: Jul 23, 2014
August 21st, 2015 at 9:17:51 PM permalink
Quote: Donuts

1M



Yeah, that doesn't feel like a big enough sample to bury the noise for simulation. (For comparison, CVCX talks about billions and quadrillions.)

With around 400k iterations per hand, you can loop through all the possible ways of drawing 4 cards (which covers a lot of the situations, but admittedly not all). 1M rounds doesn't get you to 6 card hands vs 6 card hands. Sure, those are outliers, but outliers are what throw off the results by 3 parts in 1000.
May the cards fall in your favor.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 21st, 2015 at 11:47:36 PM permalink
Quote: Dieter

Yeah, that doesn't feel like a big enough sample to bury the noise for simulation. (For comparison, CVCX talks about billions and quadrillions.)

With around 400k iterations per hand, you can loop through all the possible ways of drawing 4 cards (which covers a lot of the situations, but admittedly not all). 1M rounds doesn't get you to 6 card hands vs 6 card hands. Sure, those are outliers, but outliers are what throw off the results by 3 parts in 1000.



I'm only calculating the stand component at the moment so the players hand is always 2 cards which cuts down on the noise considerably I would think. Isn't 1m what the wizard used?
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 5564
Joined: Jul 23, 2014
August 22nd, 2015 at 6:51:28 AM permalink
Quote: Donuts

I'm only calculating the stand component at the moment so the players hand is always 2 cards which cuts down on the noise considerably I would think. Isn't 1m what the wizard used?



Try turning it up to 10m and see if your results are closer.

I really don't understand why you want to run random simulations instead of iterating through the possible draws, and then weighting the results based on deck composition.
May the cards fall in your favor.
Donuts
Donuts
  • Threads: 24
  • Posts: 171
Joined: Oct 17, 2014
August 22nd, 2015 at 7:39:58 AM permalink
Quote: Dieter

Try turning it up to 10m and see if your results are closer.

I really don't understand why you want to run random simulations instead of iterating through the possible draws, and then weighting the results based on deck composition.



Do you mean forcing the player/dealers hand like I am but then also forcing the dealer's draw cards?
Dieter
Administrator
Dieter
  • Threads: 16
  • Posts: 5564
Joined: Jul 23, 2014
August 22nd, 2015 at 12:00:08 PM permalink
Yes.

Iterate through all the possible dealer (and player) draws, and do a little math with your comparison.

You're already running a million comparisons; to handle 5 cards added to the up card (for up to a 6 card dealer hand) should be at most 161k (11^5) comparisons.

You can also change the way you handle the deck; instead of a shuffled list, just keep track of how many of each of 11 ranks remain (and if it's possible to draw a card, and how probable it is to draw that card)...
May the cards fall in your favor.
  • Jump to: