# blackjack_sim.py - the-datascientist.com # Six decks, S17, 3:2, DAS, split once, no surrender, 75% penetration. # Usage: python3 blackjack_sim.py HANDS flat|count SEED import random, sys, json # 6 decks, dealer stands soft 17, 3:2 BJ, double any 2, DAS, split once (aces get one card), no surrender, 75% penetration def hv(h): t=sum(h); a=h.count(11) while t>21 and a: t-=10; a-=1 return t, a>0 # basic strategy tables (6D S17 DAS) def hard(t,d): if t>=17: return 'S' if t>=13: return 'S' if d<=6 else 'H' if t==12: return 'S' if 4<=d<=6 else 'H' if t==11: return 'D' if d<=10 else 'H' if t==10: return 'D' if d<=9 else 'H' if t==9: return 'D' if 3<=d<=6 else 'H' return 'H' def soft(t,d): if t>=20: return 'S' if t==19: return 'S' if t==18: return 'D' if 3<=d<=6 else ('S' if d<=8 else 'H') if t==17: return 'D' if 3<=d<=6 else 'H' if t in (15,16): return 'D' if 4<=d<=6 else 'H' if t in (13,14): return 'D' if 5<=d<=6 else 'H' return 'H' def pair(c,d): if c==11 or c==8: return True if c==10 or c==5: return False if c==9: return d not in (7,10,11) if c==7: return d<=7 if c==6: return d<=6 if c==4: return d in (5,6) if c in (2,3): return d<=7 return False HILO={2:1,3:1,4:1,5:1,6:1,7:0,8:0,9:0,10:-1,11:-1} class Shoe: def __init__(s,n=6,pen=.75): s.n=n; s.pen=pen; s.shuffle() def shuffle(s): s.c=[v for v in [2,3,4,5,6,7,8,9,10,10,10,10,11] for _ in range(4*s.n)]; random.shuffle(s.c); s.i=0; s.rc=0 def draw(s): v=s.c[s.i]; s.i+=1; s.rc+=HILO[v]; return v def tc(s): dl=(len(s.c)-s.i)/52; return s.rc/dl def need(s): return s.i>len(s.c)*s.pen def play_hand(sh,h,d,can_split=True,split_aces=False): # returns list of (hand, bet_mult) if split_aces: return [(h,1)] if can_split and len(h)==2 and h[0]==h[1] and pair(h[0],d): out=[] for c in (h[0],h[1]): nh=[c,sh.draw()] out+=play_hand(sh,nh,d,False,c==11) return out mult=1 while True: t,s=hv(h) if t>21: return [(h,mult)] a=soft(t,d) if s else hard(t,d) if a=='D': if len(h)==2: h.append(sh.draw()); return [(h,2)] a='H' if not (s and t==18) else 'S' if a=='S': return [(h,mult)] h.append(sh.draw()) def round_(sh,bet): p=[sh.draw(),sh.draw()]; d=[sh.draw(),sh.draw()] pt,_=hv(p); dt,_=hv(d) if pt==21 and dt==21: return 0,bet if pt==21: return 1.5*bet,bet if dt==21: return -bet,bet hands=play_hand(sh,p,d[0]) if all(hv(h)[0]>21 for h,_ in hands): return -sum(bet*m for _,m in hands), sum(bet*m for _,m in hands) while True: t,s=hv(d) if t>=17: break d.append(sh.draw()) dt=hv(d)[0]; res=0; wag=0 for h,m in hands: t=hv(h)[0]; w=bet*m; wag+=w if t>21: res-=w elif dt>21 or t>dt: res+=w elif t