Thank you @mkeintz for the clarity needed. While all of your assumptions are correct I currently was not dealing with those rules. I am trying to get MOD to correctly be assigned to the ordered players after the first had has completed.
Example would be if the first 5 cards were played from the deck of cards at the start of the second hand player 1 should receive the first card. But the way I have used MOD it assigns player 2 the first card with is incorrect since player 2 is the dealer in a 2 person game
@art297 I have tested the code but it fails to clean house correctly and reuses cards from a single deck of cards.
I have made updates to the SAS program which works as expected for only a single game per shuffled deck of cards.
I would like to make the process use the cards that remain in the deck for a 2nd, 3rd and 4th hand at least currently.
data cards(drop=c2);
length card $5 face $2;
*do decks = 1 to 5;
do suit = "C", "D", "H", "S";
do c2= 1 to 13;
*card=cats(c2,suit);
if c2 in (1) then value = 1*11;
else if c2 in (11, 12, 13) then value = 10;
else;
do;
if c2 in (2) then value = 2;
else if c2 in (3) then value = 3;
else if c2 in (4) then value = 4;
else if c2 in (5) then value = 5;
else if c2 in (6) then value = 6;
else if c2 in (7) then value = 7;
else if c2 in (8) then value = 8;
else if c2 in (9) then value = 9;
else if c2 in (10) then value = 10;
Face = c2;
end;
if face = "11" then face = "J";
else if face = "12" then face = "Q";
else if face = "13" then face = "K";
else if value = 11 then face = "A";
card=cats(face,"-",suit);
put c2;
output;
end; /* values */
end; /* suits */
*end; /* do decks */
run;
%macro shuffle(times=);
proc sql;
create table shuffled×. as
select * from cards
order by rand("uniform");
quit;
%mend shuffle;
%macro deal(times=);
data deal×.;
array p {2} $24.;
array total {2} ;
retain p1 '' p2 '' total1 total2 0 p1a p1a2 p2a p2a2 ace_dealt
d_ace_dealt db pb 0 flag 1 _n 1 winner ' ';
if flag ne 0 then do;
set shuffled×.;
end;
/* need to deal the cards out in the correct order
this only works for a newly shuffled datasets.
*/
*if flag ne 1;
if _n < 5 then do;
/* dealer should always be the last player and last hand */
if mod(_n,2) = 0 then do;
p2 = card||p2;
total2 +value;
if value = 11 and p2a = 0 then p2a = 1;
else if value = 11 and p2a = 1 then p2a2 = 1;
end;
else do;
p1 = card||p1;
total1 +value;
if value = 11 and p1a = 0 then p1a = 1;
else if value = 11 and p1a = 1 then p1a2 = 1;
end;
_n+1;
if total2 = 21 then db = 1;
if total1 = 21 then pb = 1;
end;
/* this works for the first hand of cards but fails
for additional hands being played from
the shuffled dataset. */
else do; /* deal cards for the remander of the hand */
/* test if dealer wins with 21 on the deal */
if total2 = 21 and db = 1 then do;
black_jack = "Dealer";
winner = "Dealer";
flag = 0;
bet=5;*2.5 * ×./2;
cashout = bet;
/* this works but I lose the card that should be
held for the new hand to be played after
the current hand is finished */
output; p1='';p2='';total1=0;total2=0;_n=1;winner='';
*total1=17;
end;/* end if total2 = 21 then do; */
/* Players hand */
else if total1=21 and pb = 1 then /* (p1a=1 or p1a2=1) and total2 < 21 then*/
do;
black_jack = "Player";
winner = "Player";
flag = 0;
bet=5;*2.5 * ×./2;
cashin = bet*2;
*cashin = bet*2;
/* this works but I lose the card that should be
held for the new hand to be played after
the current hand is finished */
output; p1='';p2='';total1=0;total2=0;_n=1;winner='';
*total1=17;
end;
else if total1 <= 13 or (total1 <= 16 and (p1a = 1 or p1a2 = 1)) then do;
if value = 11 then ace_dealt = ace_dealt +1;
p1 = card||p1;
total1 +value;
/* test if the player had an ACE in their hand */
/* if hand over 21 and had an ACE recalculate hand value */
if total1 > 21 and p1a = 1 then do;
total1 = total1-10;
p1a = 0;
end;
else if total1 > 21 and p1a2 = 1 then do;
total1 = total1-10;
p1a2 = 0;
end;
/* test if the current card being drawn is an ACE and if the value is over 21 */
else if total1 > 21 and (ace_dealt > 0 or value = 11) then do;
total1 = total1-10;
if value = 11 then ace_dealt = ace_dealt -1;
end;
end;
/* Dearlers hand */
else if (total2 < 17 and total1 < 22) or (total2 = 22 and (p2a = 1 or p2a2 = 1)) then do;
if value = 11 then d_ace_dealt +1;
p2 = card||p2;
total2 +value;
if total2 > 21 and p2a = 1 then do;
total2 = total2-10;
p2a = 0;
end;
else if total2 > 21 and p2a2 = 1 then do;
total2 = total2-10;
p2a2 = 0;
end;
else if total2 > 21 and value = 11 then total2 = total2-10;
end;
else do;
if total2 = 21 then winner = "Dealer";
else if (total1 < 22 and total1 > total2) or total2 > 21 then winner = "Player";
else winner = "Dealer";
flag = 0;
bet=5;*2.5 * ×./2;
if winner = "Player" then cashin = bet *1;
else cashout = bet;
/* this works but I lose the card that should be
held for the new hand to be played after
the current hand is finished */
output; p1='';p2='';total1=0;total2=0;_n=1;winner='';
end;
end;
/*
if _n_ < 46 then do;
flag = 1;
end;
*/
*end;/* end for flag = 0 */
run;
%mend deal;
/* call the game */
data _null_ ;
i = 1;
do until (i = 101);
call execute (cats('%nrstr(%shuffle)(times=',i,')'));
call execute (cats('%nrstr(%deal)(times=',i,')'));
i=i+1;
end;
run;
/* put the datasets together */
proc sql ;
/* get all the file names into a macro var */
select
trim(libname) || '.' || memname into :dataset_vars separated by ' '
from dictionary.tables
where upcase(libname)="WORK"
and upcase(memname) like 'DEAL%'
;
quit;
data Hands;
set &dataset_vars;* (drop=month);
run;
/* Clean house */
proc sql noprint ;
select 'drop table work.'||memname
into :empties separated
by ';'
from dictionary.tables
where libname='WORK' and upcase(memname) like 'DEAL%'
;
&empties;
quit;
proc sql noprint ;
select 'drop table work.'||memname
into :empties separated
by ';'
from dictionary.tables
where libname='WORK' and upcase(memname) like 'SHUFFLED%'
;
&empties;
quit;
/* Calculate wins and losses */
options missing = 0;
data hands_winner(keep=house_profit hands_played total_bet player_cash phands house_cash_pulled hhands pblackj dblackj Player_win_lost);
retain hands_played total_bet player_cash phands house_cash_pulled hhands pblackj dblackj 0;
set hands end=eof;
total_bet + bet;
hands_played +1;
if winner = "Player" then do;
player_cash = player_cash + cashin;
phands +1;
if black_jack = "Player" then pblackj +1;
end;
else if winner = "Dealer" then do;
house_cash_pulled =house_cash_pulled + cashout;
hhands +1;
if black_jack = "Dealer" then dblackj +1;
end;
if eof=1 then do;
Player_win_lost = player_cash - total_bet;
house_profit=total_bet-player_cash;
output;
end;
run;
/* Just checking */
proc freq data=hands;
tables black_jack / missing;
run;
... View more