Blackjack and Card Counting Forums - BlackjackInfo.com

  #1  
Old July 24th, 2009, 05:15 PM
blazin22's Avatar
blazin22 blazin22 is offline
Member
 
Join Date: Jul 2008
Posts: 47
Default work in progress blackjack side bet analysis tool

Hey guys,
I am currently working on a 21+3 side bet analysis tool for blackjack. My code is only in a preliminary state, I am having a few problems replicating the odds listed in the casinos "house edge" booklet which shows a house edge of 3.29% which is consistent with the wizard of odds site which shows 3.24.
assuming six decks.

bash-3.2$ ./pairplus.exe
pairplus <Number of Decks> <penetration>

where penetration is an number between 0 and 311

bash-3.2$ ./pairplus.exe 1000000 52
deck penetration level 83.333333%
rounds per shoe 87
total shoes played 1000000
hands won per shoe 8.418248
winrate in percentage terms -3.585452%

As you can see I get around 3.58 house edge, which is a huge difference from the that given in the booklet. I must be doing something wrong and I can't even begin to start analyzing any advantage obtainable by counting cards in this game until I can exactly replicate the house edge.

Source code is available at http://pastebin.com/m1353b5cd

-blazin
  #2  
Old July 24th, 2009, 07:29 PM
Automatic Monkey's Avatar
Automatic Monkey Automatic Monkey is offline
Banned
 
Join Date: May 2006
Location: Connecticut
Posts: 5,171
Default

I don't understand your computer language so I can't effectively debug, but the difference you get is around what I would expect for failing to consider both A23 and AKQ are straights.

This sidebet will be tough to beat. The Royal Match sidebet on a SD game gets nearly all of its return from a two-card "flush", and counting all four suits independently only earns you a return of around 1.5% or so, not worth it alone in a SD game especially given a $100 limit on the sidebet. But with exactly one partner at the table and counting both BJ and the sidebet, it is worth it.

The 21+3 sidebet takes less than 100% return from the flush and is offered on shoe games. You will probably need a team of 3 guys working together to do this.
  #3  
Old July 25th, 2009, 02:43 AM
blazin22's Avatar
blazin22 blazin22 is offline
Member
 
Join Date: Jul 2008
Posts: 47
Default

Quote:
Originally Posted by Automatic Monkey View Post
I don't understand your computer language so I can't effectively debug, but the difference you get is around what I would expect for failing to consider both A23 and AKQ are straights.
Yes I initially made that mistake but have since fixed it, checking for a flush and three of a kind is very easy, the straight is relatively complex in comparison, I use the following algorithm,

Because the three cards are not in order and I didn't want to use a sorting algorithm for speed purposes, I do the following,

0 = A in my program so I first check if any of the three cards contain an 0 if they do I just add the other two numbers up and see if they equal 23, since Q = 11 and k= 12 so (A and QK) or (A and KQ) would be 0 and 23.

for the other straights adding one to lowest number and subtracting 1 from the highest number and seeing if there is a match.

The odds still don't match those given on wizzardofodds.

Quote:
Originally Posted by Automatic Monkey View Post
This sidebet will be tough to beat. The Royal Match sidebet on a SD game gets nearly all of its return from a two-card "flush", and counting all four suits independently only earns you a return of around 1.5% or so, not worth it alone in a SD game especially given a $100 limit on the sidebet. But with exactly one partner at the table and counting both BJ and the sidebet, it is worth it.

Quote:
Originally Posted by Automatic Monkey View Post
The 21+3 sidebet takes less than 100% return from the flush and is offered on shoe games. You will probably need a team of 3 guys working together to do this.
I'm reconsidering it now, I don't have any play partners. I want to play alone. I'm thinking about converting my program into a simulation for the four deck blackjack ENHC game I have locally so I can study the return from my play style. I don't want to buy CVCX.

Last edited by blazin22; July 25th, 2009 at 02:47 AM.
  #4  
Old July 25th, 2009, 04:43 AM
UK-21's Avatar
UK-21 UK-21 is offline
Executive Member
 
Join Date: Apr 2008
Location: One of the green, leafy parts of the UK
Posts: 968
Default

Hold on . . . . I'll get some of my mates who work as suits and PBs in various casinos around the UK to get in touch. I'm sure they'll be able to help. What're your contact details . . . .? ? ? Can you send a photo just so they know who they're dealing with?

http://www.blackjackinfo.com/bb/showthread.php?t=14665
  #5  
Old August 4th, 2009, 10:39 AM
Sonny's Avatar
Sonny Sonny is offline
Moderator
 
Join Date: Mar 2006
Location: Los Angeles, CA
Posts: 4,748
Default

Thanks for including your C++ source code! We don’t see a lot of code around here so I’m always excited to see what other people are doing. It looks like you spent a lot of time on that project and I’m sure we can get it working properly with some tweaking.

Unfortunately, the program needs a lot of work. Even if we found the bug, the program would still be waaaaay too slow. There is a lot of cleaning up we need to do before we start debugging it. You’ve got structures within structures, a very inefficient shuffle procedure, several functions that only perform one line of code and a lot of extra overhead that we can shed. Let’s simplify this program as much as we can first. I tried to use the same variable names from your program in the examples below.

The first step is to dump the built-in RNG. It’s crap and it isn’t sufficient for simulations. Slap in the RNG below:

Code:
#include <iostream>

double u[98],c,cd,cm;  // make sure these are global variables
int i97,j97;

void initRNG(int ij,int kl) {
   int i,j,k,l,m,ii,jj;
   double s,t;

   if (ij<0 || ij>31328 || kl<0 || kl>30081) {
      cerr << "Seed1 must be between 0 and 31328" << endl;
      cerr << "Seed2 must be between 0 and 30081" << endl;
   } else {
      i = 2 + int(ij/177)%177;
      j = 2 + ij%177;
      k = 1 + int(kl/169)%178;
      l = kl%169;
      for (ii = 1; ii <= 97; ii++) {
         s = 0.0;
         t = 0.5;
         for (jj = 1; jj <= 24; jj++) {
            m = (k*((i*j)%179))%179;
            i = j;
            j = k;
            k = m;
            l = (53*l + 1)%169;
            if ((l*m)%64 >= 32) s = s + t;
            t = 0.5*t;
         }
      u[ii] = s;
      }
   }
    
   c =    362436.0/16777216.0;
   cd =  7654321.0/16777216.0;
   cm = 16777213.0/16777216.0;
   i97 = 97;
   j97 = 33;
}

double GetRND() {
   double uni;

   uni = u[i97] - u[j97];
   if (uni < 0.0) uni = uni + 1.0;
   u[i97] = uni;
   if (--i97 == 0) i97 = 97;
   if (--j97 == 0) j97 = 97;
   c = c - cd;
   if (c < 0.0) c = c + cm;
   uni = uni - c;
   if (uni < 0.0) uni = uni + 1.0;
   return uni;
}
Initialize the RNG by calling initRNG(seed1,seed2) where seed1 is between 0 and 31328 and seed2 is between 0 and 30081. Then replace every rand() statement with GetRND(). That will improve the results.

The shuffle procedure can be greatly condensed as well. Something simple like this should work:

Code:
if (Offset > 233) {            // Past the virtual cut card?
   for (int i=311; i>0; i--) {
      a = int(GetRND() * i);   // Pick a random card and
      swap1 = Shoe[a];         // swap it with the current one
      Shoe[a] = Shoe[i];
      Shoe[i] = swap1;
   }
   Offset = 1;                // burn card 0
}
The shuffle procedure can be one of the most time-intensive (and frequently used) routines in a simulator so you want it to be as quick as possible. The code above also allows you to dump the cut_cards procedure completely. Once we get rid of the structures (see below) we can use the assembly instruction xchg to make things even easier.

Next, dump all those structures. The only information you need is the card’s rank and suit. That can be held in a single byte (or short int). The lower four bits can hold the rank (decimal number between 0 and 12) and the upper four bits can hold the suit information. Each upper bit can represent a suit, so 0b1000 might be hearts, 0b0100 spades, 0b0010 clubs and 0b0001 diamonds. Packing everything into a single byte saves you a lot of space and overhead from the structures. Checking for flushes is now a simple bitwise operation:

Code:
if (Shoe[Offset] & Shoe[Offset+1] & Shoe[Offset+2] & 0xf0) {
   // you’ve got a flush  
} else {
   // no flush
}
The algorithms you have (check_flush, check_straight, etc.) are fine, but lookup tables would be faster. There are 741 unique Three Card Poker hands so you just need an array that gives a rank to each one. For example, an A,Q,K flush would be ranked 1, a K,Q,J flush would be ranked 2…all the way down to an off-suit 5,3,2 with a value of 741. Checking for a winning hand would only require that all of the paying hands be at the top of the list (ranks 1-311 I believe, but I'm not sure about that yet) and you could check for ALL winning payouts like this:

Code:
if (HandRank < 312) {          
   // Flush or better gets paid
} else {                         
   // Otherwise you lose
}
You can also dump a lot of those library files, but that’s just nitpicking.

Those are just a few ideas I had off the top of my head. I’m working on a simulator for this side bet now so I’ll post the code when it’s done. I'm sure my code can be optimized quite a bit and maybe other members will have some suggestions.

-Sonny-

Last edited by Sonny; August 6th, 2009 at 10:30 AM.
  #6  
Old August 4th, 2009, 11:41 AM
sagefr0g's Avatar
sagefr0g sagefr0g is offline
Executive Member
 
Join Date: Apr 2006
Posts: 5,141
Default

is there valid source code available for like just making a player flat bet and play basic strategy over a bunch of deals? i mean with out all the bells and whistles, sort of stuff?

i looked at power sim's code, but it has so many bells and whistles.

i'd like to have a 'stripped' down sort of thing that i could then get to do stuff i wanted, with out all the other 'baggage'.
  #7  
Old August 4th, 2009, 12:40 PM
blazin22's Avatar
blazin22 blazin22 is offline
Member
 
Join Date: Jul 2008
Posts: 47
Default

Quote:
Originally Posted by Sonny View Post
Thanks for including your C++
Those are just a few ideas I had off the top of my head. Iím working on a simulator for this side bet now so Iíll post the code when itís done. I'm sure my code can be optimized quite a bit and maybe other members will have some suggestions.

-Sonny-
Hey Sonny, Thanks for the input, If I dump the use of nested structures and/or structures entirely I will have to recode 90% of the program. This is exactly what I am doing.

I strongly suspect my use of rand() is the reason for the wrong output. I've been told I should look into using the time stamp counter within the CPU to generate a much more random value, RDTSC. This would obviously involve the use of some inline assembler which would break the potential for future portability or I could just use your random function.

i'm going to spend some time on it this weekend see if I can recreate it all, I'd eventually like to create a full blackjack simulator but thats a long way off.
  #8  
Old August 6th, 2009, 10:30 AM
Sonny's Avatar
Sonny Sonny is offline
Moderator
 
Join Date: Mar 2006
Location: Los Angeles, CA
Posts: 4,748
Default Some Corrections

Quote:
Originally Posted by Sonny View Post
There are 741 unique Three Card Poker hands so you just need an array that gives a rank to each one...Checking for a winning hand would only require that all of the paying hands be at the top of the list (ranks 1-311 I believe, but I'm not sure about that yet)...
The 741 unique hands are only for a single-deck game. The 21+3 game uses six decks, which allows the possibility of suited pairs and even suited three-of-a-kinds. That brings the number of unique hands up to 911. Only the top 480 hands are winners, but using the lookup table makes that an easy fix. Just adjust the line if(HandRank < 312) to if(HandRank < 481) and youíre ready to roll. Itís much easier than using logic-based strategies that you have to rewrite every time you need to test a different strategy, which happens often.

The lookup table also makes it easier to keep track of the frequencies of each hand type for debugging purposes. You can check for any hand type (or even a specific three-card hand) just by looking at the handís unique rank. Hereís how my program tallies the hand frequencies:

Code:
if (PlayerRank < 1 || PlayerRank > 911)
   // On error, dump the hand contents to the output file
else if (PlayerRank < 13) 
   StraightFlush++;
else if (PlayerRank < 169)
   SuitedPair++;
else if (PlayerRank < 182)
   SuitedTOAK++;
else if (PlayerRank < 456) 
   Flush++;
else if (PlayerRank < 469)
   TOAK++;
else if (PlayerRank < 481) 
   Straight++;
else if (PlayerRank < 638) 
   Pair++;
else 
   Nothing++;
That way you can see right away which hands are creating a problem. It can save you a lot of time tracking down the bugs.

If anyone is interested in other portions of my code (or the entire program) I'm happy to share. I'd also love to hear some tips/criticisms from other members. I know at least 4 of you write your own simulators!

-Sonny-
  #9  
Old August 6th, 2009, 12:37 PM
blazin22's Avatar
blazin22 blazin22 is offline
Member
 
Join Date: Jul 2008
Posts: 47
Default

Quote:
Originally Posted by Sonny View Post

If anyone is interested in other portions of my code (or the entire program) I'm happy to share. I'd also love to hear some tips/criticisms from other members. I know at least 4 of you write your own simulators!

-Sonny-
Nice, I'm going to use a lookup table for my simulator. When I first started looking at advantage play in blackjack it was mostly your postings I'd read to further my understanding of card counting. I didn't think you were also a programmer. Counting/shuffle tracking/simulator coding, you're like the complete AP package . I'm going to finish my sim before I ask to see all of your code, I won't have the same sense of accomplishment if I just copy/paste all of yours .
  #10  
Old August 6th, 2009, 04:54 PM
stophon stophon is offline
Senior Member
 
Join Date: Feb 2009
Posts: 141
Default

Quote:
Originally Posted by sagefr0g View Post
is there valid source code available for like just making a player flat bet and play basic strategy over a bunch of deals? i mean with out all the bells and whistles, sort of stuff?

i looked at power sim's code, but it has so many bells and whistles.

i'd like to have a 'stripped' down sort of thing that i could then get to do stuff i wanted, with out all the other 'baggage'.
I have a sim that generates an accurate house edge, but its far from efficient or intelligently programmed and it is written in vb.
 

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -6. The time now is 01:53 PM.


Forum Software vBulletin®
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Copyright 2005-2011 Bayview Strategies LLC