# include # include # define DECKS 6 # define DEAL_DEPTH 5.5 # define HANDS 100 # define DEBUG_LEVEL 9 // DEBUG_LEVEL description // 9 banker draws; hard + soft decision generator // 7 player draws; hard + soft decision generator // 5 banker draws; soft decision generator // 3 player draws; soft decision generator // 0 quiet static int BankerDecision (int, int) ; static int PlayerDecision (int, int, int) ; static void PlayerStrategy (int*, int*, int, int*, int*, int) ; static void BankerStrategy (int*, int*, int*, int*) ; static int DealCard (int*, int*) ; static int HandValue (int, int) ; static void ShuffleShoe (int*,int*) ; static int IsNatural (int, int) ; static int showdown (int, int, int, int) ; static void sprintfHandValue(char*, int, int) ; static int HardDecision[23][11], SoftDecision[23][11] ; static int Double11Decision[11], Double12Decision[11] ; static int hist[11], cardsDealt ; void main () { int i,j,k ; int PlayerSum, PlayerSoft, PlayerJoker, PlayerNatural ; int BankerSum, BankerSoft, BankerJoker, BankerUp, BankerNatural ; int game_no, bet, outcome, net, card1, card2 ; int shoePtr, shoePenetration ; int shoe[53*DECKS] ; int TotalAction, FrontLineAction, SoftSum, shoeCnt ; double EV ; char ResultString[10], PlayerHandString[10], BankerHandString[10] ; FILE *fp ; srand48(63514) ; shoeCnt = 0 ; TotalAction = 0 ; FrontLineAction = 0 ; net = 0 ; game_no = 1 ; shoePenetration = (int)(DEAL_DEPTH*53.) ; shoePtr = DECKS*52 ; // prepeare for 1st shuffle cardsDealt = 0 ; for (i=0; i<11; i++) hist[i] = 0 ; // initialize deicison matricies for (j=0; j<11; j++) { for (i=0; i<22; i++) { HardDecision[i][j] = 1 ; SoftDecision[i][j] = 1 ; } Double11Decision[j] = 1 ; Double12Decision[j] = 1 ; } if ((fp = fopen("HardDecision.tbl","r")) == NULL) { fprintf(stderr,"error: cannot open HardDecision.tbl\n") ; exit (-1) ; } for (PlayerSum = 19; PlayerSum >= 13; PlayerSum--) { fscanf(fp,"%d %d %d %d %d %d %d %d %d %d", &HardDecision[PlayerSum][1], &HardDecision[PlayerSum][2], &HardDecision[PlayerSum][3], &HardDecision[PlayerSum][4], &HardDecision[PlayerSum][5], &HardDecision[PlayerSum][6], &HardDecision[PlayerSum][7], &HardDecision[PlayerSum][8], &HardDecision[PlayerSum][9], &HardDecision[PlayerSum][10]) ; } fclose(fp) ; if ((fp = fopen("SoftDecision.tbl","r")) == NULL) { fprintf(stderr,"error: cannot open SoftDecision.tbl\n") ; exit (-1) ; } for (SoftSum = 10; SoftSum >= 3; SoftSum--) { fscanf(fp,"%d %d %d %d %d %d %d %d %d %d", &SoftDecision[SoftSum][1], &SoftDecision[SoftSum][2], &SoftDecision[SoftSum][3], &SoftDecision[SoftSum][4], &SoftDecision[SoftSum][5], &SoftDecision[SoftSum][6], &SoftDecision[SoftSum][7], &SoftDecision[SoftSum][8], &SoftDecision[SoftSum][9], &SoftDecision[SoftSum][10]) ; } fclose(fp) ; if ((fp = fopen("Double11Decision.tbl","r")) == NULL) { fprintf(stderr,"error: cannot open Double11Decision.tbl\n") ; exit (-1) ; } fscanf(fp,"%d %d %d %d %d %d %d %d %d %d", &Double11Decision[1], &Double11Decision[2], &Double11Decision[3], &Double11Decision[4], &Double11Decision[5], &Double11Decision[6], &Double11Decision[7], &Double11Decision[8], &Double11Decision[9], &Double11Decision[10]) ; fclose(fp) ; if ((fp = fopen("Double12Decision.tbl","r")) == NULL) { fprintf(stderr,"error: cannot open Double12Decision.tbl\n") ; exit (-1) ; } fscanf(fp,"%d %d %d %d %d %d %d %d %d %d", &Double12Decision[1], &Double12Decision[2], &Double12Decision[3], &Double12Decision[4], &Double12Decision[5], &Double12Decision[6], &Double12Decision[7], &Double12Decision[8], &Double12Decision[9], &Double12Decision[10]) ; fclose(fp) ; while (game_no <= HANDS) { if (DEBUG_LEVEL >= 5) printf("game %d\n",game_no) ; bet = 1 ; if (shoePtr > shoePenetration) { shoeCnt++ ; ShuffleShoe(shoe,&shoePtr) ; if (DEBUG_LEVEL >= 2) printf("shuffle\n") ; } // deal initial banker hand BankerNatural = 0 ; BankerSoft = 0 ; card1 = DealCard(shoe,&shoePtr) ; card2 = DealCard(shoe,&shoePtr) ; BankerSoft = (card1 == 1) || (card2 == 1) ; BankerJoker = (card1 == -1) || (card2 == -1) ; BankerNatural = IsNatural(card1, card2) ; BankerSum = BankerJoker ? 22 : card1 + card2 ; BankerUp = card1 ; if (DEBUG_LEVEL >= 7) { printf("banker start: %d %d\n",card1,card2) ; if (BankerJoker) printf("banker joker\n") ; } // deal initial player hand PlayerNatural = 0 ; PlayerSoft = 0 ; card1 = DealCard(shoe,&shoePtr) ; card2 = DealCard(shoe,&shoePtr) ; PlayerSoft = (card1 == 1) || (card2 == 1) ; PlayerJoker = (card1 == -1) || (card2 == -1) ; PlayerNatural = IsNatural(card1, card2) ; PlayerSum = card1 + card2 ; if (DEBUG_LEVEL >= 5) { printf("player start: %d %d\n",card1,card2) ; if (PlayerJoker) printf("player joker\n") ; } if (DEBUG_LEVEL >= 10) printf("cards dealt: %d\n",shoePtr) ; if (BankerNatural) { sprintf(BankerHandString,"natural") ; if (PlayerNatural) { sprintf(PlayerHandString,"natural") ; outcome = 0 ; sprintf(ResultString,"ties") ; } else { outcome = -1 ; sprintf(ResultString,"loses to") ; sprintfHandValue(PlayerHandString,PlayerSum,PlayerSoft) ; } } else if (BankerUp == -1) { // no one draws if (DEBUG_LEVEL >= 7) printf("banker has Joker upcard\n") ; sprintf(BankerHandString,"22") ; if (PlayerNatural) { sprintf(PlayerHandString,"natural") ; sprintf(ResultString,"beats") ; outcome = 1 ; } else if (PlayerJoker) { sprintf(PlayerHandString,"22") ; sprintf(ResultString,"ties") ; outcome = 0 ; } else { sprintfHandValue(PlayerHandString,PlayerSum,PlayerSoft) ; sprintf(ResultString,"loses to") ; outcome = -1 ; } } else if (PlayerNatural) { sprintf(PlayerHandString,"natural") ; sprintf(ResultString,"beats") ; sprintfHandValue(BankerHandString,BankerSum,BankerSoft) ; outcome = 1 ; } else { // play out hand if (PlayerJoker) { PlayerSum = 22 ; } else if ( ( ((PlayerSum == 11) && Double11Decision[BankerUp]) || ((PlayerSum == 12) && Double12Decision[BankerUp]) ) && (PlayerSoft != 1) && (PlayerJoker != 1) ) { // double down if (DEBUG_LEVEL >= 5) printf("double down\n") ; bet = BankerJoker ? 1 : 2 ; PlayerStrategy(&PlayerSum,&PlayerSoft,BankerUp,shoe,&shoePtr,2) ; } else { PlayerStrategy(&PlayerSum,&PlayerSoft,BankerUp,shoe,&shoePtr,99) ; } BankerStrategy(&BankerSum,&BankerSoft,shoe,&shoePtr) ; outcome = showdown(PlayerSum,PlayerSoft,BankerSum,BankerSoft) ; if (outcome == 1) sprintf(ResultString,"beats") ; else if (outcome == 0) sprintf(ResultString,"ties") ; else sprintf(ResultString,"loses to") ; sprintfHandValue(PlayerHandString,PlayerSum,PlayerSoft) ; sprintfHandValue(BankerHandString,BankerSum,BankerSoft) ; } net += outcome*bet ; TotalAction += bet ; FrontLineAction += 1 ; game_no++ ; if (DEBUG_LEVEL >= 5) { printf("player %s %s banker %s\n", PlayerHandString, ResultString, BankerHandString) ; printf("outcome: %d net: %d\n",outcome*bet,net) ; printf("\n") ; } if (game_no%10000 == 0) { EV = (double)net/(double)TotalAction ; printf("hands dealt: %d EV = %f\n",game_no,EV) ; EV = (double)net/(double)FrontLineAction ; printf("EV (FrontLineAction) = %f\n",EV) ; } } printf("shoes dealt: %d\n",shoeCnt) ; EV = (double)net/(double)TotalAction ; printf("EV (TotalAction) = %f\n",EV) ; EV = (double)net/(double)FrontLineAction ; printf("EV (FrontLineAction) = %f\n",EV) ; fp = fopen("CardHist","w") ; for (i=0; i<11; i++) { fprintf(fp,"%d %e\n",i,(double)hist[i]/(double)cardsDealt) ; } fclose(fp) ; } static void PlayerStrategy (int *total, int *soft, int BankerUp, int *shoe, int *ptr, int DrawCntLimit) { int card, drawCnt ; char valueString[10] ; drawCnt = 0 ; if (DEBUG_LEVEL >= 9) { sprintfHandValue(valueString,*total,*soft) ; printf("player total: %s\n",valueString) ; } while ( (drawCnt < DrawCntLimit) && PlayerDecision(*total,*soft,BankerUp) ) { drawCnt++ ; card = DealCard(shoe,ptr) ; *soft = *soft || (card == 1) ; *total = (card == -1) ? 22 : (*total + card) ; if (DEBUG_LEVEL >= 7) { sprintfHandValue(valueString,*total,*soft) ; if (DrawCntLimit == 2) printf("player draw #%d: %d player total: %s\n", drawCnt,card,valueString) ; else printf("player draw: %d player total: %s\n",card,valueString) ; } if (DEBUG_LEVEL >= 9) { sprintfHandValue(valueString,*total,*soft) ; } } if (DEBUG_LEVEL >= 5) { sprintfHandValue(valueString,*total,*soft) ; if (*total > 22) printf("> player busts (%d)",*total) ; else printf("> player stays at %s\n",valueString) ; } } static void BankerStrategy (int *total, int *soft, int *shoe, int* ptr) { int card ; char valueString[10] ; if (DEBUG_LEVEL >= 7) { sprintfHandValue(valueString,*total,*soft) ; printf("banker total: %s\n",valueString) ; } while (BankerDecision(*total,*soft)) { card = DealCard(shoe,ptr) ; *soft = *soft || (card == 1) ; *total = (card == -1) ? 22 : (*total + card) ; if (DEBUG_LEVEL >= 5) { sprintfHandValue(valueString,*total,*soft) ; printf("banker draw: %d banker total: %s\n",card,valueString) ; } } if (DEBUG_LEVEL >= 7) { sprintfHandValue(valueString,*total,*soft) ; if (*total > 22) printf("> banker busts (%d)\n",*total) ; else printf("> banker stays at %s\n",valueString) ; } } static int PlayerDecision (int total, int soft, int upcard) { int hit ; if (soft) { if ((total == 11) || (total == 12)) { // soft 21, 22 hit = 0 ; } else if (total < 11) { hit = SoftDecision[total][upcard] ; } else if (total < 20) { hit = HardDecision[total][upcard] ; } else { hit = 0 ; } } else { if (total <= 12) { hit = 1 ; } else if ((total > 12) && (total < 20)) { hit = HardDecision[total][upcard] ; } else { hit = 0 ; } } return (hit) ; } static int BankerDecision (int total, int soft) { int hit ; if (soft) { hit = (total <= 8) || ((total > 12) && (total < 18)) ; } else { hit = (total < 18) ; } return (hit) ; } static int showdown (int PlayerTotal, int PlayerSoft, int BankerTotal, int BankerSoft) { // this subroutine does not cover banker nor player naturals int outcome ; // -1 = player loses; 0 = push; +1 = player wins if (BankerTotal > 22) { if (PlayerTotal <= 22) { outcome = 1 ; } else { outcome = (PlayerTotal < BankerTotal) ? 0 : -1 ; } } else if (PlayerTotal > 22) { outcome = -1 ; } else if ( HandValue(PlayerTotal,PlayerSoft) == HandValue(BankerTotal,BankerSoft) ) { outcome = 0 ; if (DEBUG_LEVEL >=9 ) { printf( "player: %d banker: %d\n", HandValue(PlayerTotal,PlayerSoft), HandValue(BankerTotal,BankerSoft) ) ; } } else { outcome = ( HandValue(PlayerTotal,PlayerSoft) > HandValue(BankerTotal,BankerSoft) ) ? 1 : -1 ; if (DEBUG_LEVEL >=9 ) { printf( "player: %d banker: %d\n", HandValue(PlayerTotal,PlayerSoft), HandValue(BankerTotal,BankerSoft) ) ; } } return (outcome) ; } static void ShuffleShoe (int *shoe, int *ptr) { int i,j,k, temp, TotalCards, TotalSwaps ; *ptr = 0 ; TotalCards = DECKS*53 ; // initialize shoe for (i=0; i 22) sprintf(valueString,"%d (bust)",HandValue(total,soft)) ; else sprintf(valueString,"%d",HandValue(total,soft)) ; }