AlexR
Posted by AlexR
Aug 12, 2018

Baccarat Simulator in MATLAB

I was looking for an opportunity to practice some programming so I decided to develop a baccarat simulator in MATLAB.

I ran into a few issues while working on this project, the first of which (which I discussed on the forum) was that I originally tried to use chained comparison operators (a<b<c) for the banker drawing rules, which don't work in MATLAB, which requires separate comparisons (a<b & b<c). This caused the banker to play incorrectly and gave the player a slight advantage.

Another stubborn problem was formatting the text file output. I was finding incorrectly positioned spaces and line breaks in the file until I realized that fprintf evaluates the contents of a matrix one column after another, but prints text left-to-right, so the data has to be reversed from the desired output. In order to print more neatly, the blank entries in the matrix are filled with 32, the ASCII code for spaces, with a carriage return (13) appended to the end of line.

As of version 2.0 (this post shows v2.5), I've implemented a parfor loop, which allows multiple processors to play different games simultaneously. In my case, using a 4-core CPU, I've observed significant improvement in performance when playing more than about 50,000 shoes. This version also implements casino-style burn card and cut card rules.
clear

nshoe = 1000000; %play n shoes
ndeck = 8; %number of decks in shoe
cut = 400; %cut after n cards

maxhand = 13*ndeck+1; %sets width of score chart
undeck = builddeck(ndeck); %create unshuffled deck
ngame = 0; %intl game counter
pwins = 0; bwins = 0; twins = 0; %intl scores
score = zeros(maxhand,nshoe);
shoe = 0; %intl shoe count

parfor i=1:nshoe %parfor is used to play multiple shoes in parallel

deck = undeck(randperm(length(undeck))); %randomly shuffle deck

atcut = false; %cut card detection
cutnext = false;

if deck(1)==1 || deck(1)==0 %burn 10 cards for 1 or 0
c=12;
else
c=deck(1)+2; %burn n cards for n pips
end

hand = 1;
shoescore = 32*ones(maxhand,1); %ascii spaces
shoescore(maxhand,1) = 13; %ascii carriage return at end of line

while atcut == false %main hand play loop

if c==cut || cutnext == true %plays last hand
atcut = true;
end

phand = deck(c); c=c+1; %draw two cards each
bhand = deck(c); c=c+1;
phand = [phand, deck(c)]; c=c+1;
bhand = [bhand, deck(c)]; c=c+1;
natural = false;

ppts = mod(sum(phand),10); %take initial score
bpts = mod(sum(bhand),10);

if c>= cut %if cut is in middle of hand, play one more
cutnext = true;
end

if ppts>=8 || bpts>=8 %check for naturals
natural=true;
end

if ppts<=5 && natural==false %player draw on 0,1,2,3,4,5
phand = [phand, deck(c)]; c=c+1;
ppts = mod(sum(phand),10);
end

if length(phand)==2 && natural==false %banker against two player cards
if bpts<=5 %draw on 0,1,2,3,4,5
bhand = [bhand, deck(c)]; c=c+1;
bpts = mod(sum(bhand),10);
end
elseif natural==false %banker against three player cards
if bpts==6 && 6<=phand(3) && phand(3)<=7 %draw on 6 against 6,7
bhand = [bhand, deck(c)]; c=c+1;
bpts = mod(sum(bhand),10);
elseif bpts==5 && 4<=phand(3) && phand(3)<=7 %draw on 5 against 4-7
bhand = [bhand, deck(c)]; c=c+1;
bpts = mod(sum(bhand),10);
elseif bpts==4 && 2<=phand(3) && phand(3)<=7 %draw on 4 against 2-7
bhand = [bhand, deck(c)]; c=c+1;
bpts = mod(sum(bhand),10);
elseif bpts==3 && phand(3)~=8 %draw on 3 against any except 8
bhand = [bhand, deck(c)]; c=c+1;
bpts = mod(sum(bhand),10);
elseif bpts<=2 %draw on 0,1,2 against any
bhand = [bhand, deck(c)]; c=c+1;
bpts = mod(sum(bhand),10);
end
end

if ppts < bpts %score tally
shoescore(hand,1) = 'B'; %characters store as ascii codes
elseif ppts > bpts
shoescore(hand,1) = 'P';
else
shoescore(hand,1) = 'T';
end

hand = hand+1;

end

score(:,i) = shoescore; %puts score for shoe i in column i

end

bwins = nnz(score=='B'); %counts scores
pwins = nnz(score=='P');
twins = nnz(score=='T');
ngame = bwins+pwins+twins;

ppct = pwins/ngame*100; %win percents
bpct = bwins/ngame*100;
tpct = twins/ngame*100;

F = 'Shoes played: %u (%u deck)\rHands played: %u\rBanker wins: %u (%.2f%%)\rPlayer wins: %u (%.2f%%)\rTies: %u (%.2f%%)\r';
fprintf(F,nshoe,ndeck,ngame,bwins,bpct,pwins,ppct,twins,tpct) %print results

savetext(score)

function savetext(x)
fileid = fopen('score.txt','w'); %opens file
k = char(x); %converts ascii codes to characters
fprintf(fileid,'%s',k); %sends text to file
fclose(fileid);
end

function y = builddeck(x) %construct a deck
y=[]; suit = [1,2,3,4,5,6,7,8,9,0,0,0,0];
for p = 1:4*x
y = [y,suit];
end
end
The code produces the following output in about a minute, along with a text file showing each result.
>> baccarat_par
Shoes played: 1000000 (8 deck)
Hands played: 80597661
Banker wins: 36967725 (45.87%)
Player wins: 35961327 (44.62%)
Ties: 7668609 (9.51%)
Here's a sample of that text file showing the results of the first two shoes:
BTPBTBBPPPPPBPBBBBPPBTPPBPPBPBTBBBTBPTBBBTPPPPPBPBBPBBPBBBPPTPBPPPTBBPTPPPPPPBB
BPBPPBTBTPPPBPBBBTTPPPBPBPPPPBPBBPBBTPPPBBBBBBBBBPTTPBBPPBPPPBTPBTPBBPPPPBPPPPPB
Let me know if you have any suggestions or comments.

Comments

mustangsally
mustangsally Aug 14, 2018

very well done!



you have to feel good about the end result(s)



The BPT text file(s) could be for download too

if you have interest in that (like the Wizard's shoes, not my Moms' shoes)

or a website or online folder that can host them 4U. (Google does it for free)



now, thinking out loud,

You may want to consider to be the first to create an 'EZ Baccarat' simulator in MATLAB

that can also count the player/banker/tie streaks

not to mention the Dragon 7 and it's streaks

(I have mine almost done in Excel)



of course, the Dragon 7 and Panda 8 bets are countable

that could be added also



that would make you very popular with the Baccarat crowd

(I am popular with some parts of the Baccarat crowd,

but for reasons different than you would be)



Sally