/* ** Compile as: cc bj.c -lm -o bj */ static char ID[] = "@(#)bj.c 1.1"; #include <stdio.h> #include <signal.h> #include <math.h> #include <setjmp.h> #define MINSHUF 8 /* minimum number of `shuffles' */ #define MAXSHUF 30 /* maximum number of `shuffles' */ struct card { char rank; /* 2-9, 10=T, 11=J, 12=Q, 13=K, 14=A */ char suit; /* 0=S, 1=H, 2=C, 3=D */ } deck[52]; char curcrd[] = "XX"; /* current card */ int nxtcrd; /* next card; index into `deck' */ long action; /* total bucks bet */ long bux; /* signed gain/loss */ int ins; /* player took insurance against bj */ int shuff; /* A shuffle has occured */ int wager = 2; /* bet per hand */ int split; jmp_buf jbuf; /* place to stash a stack frame */ main() { register r, s, aced; register d1, d2, p1, p2, dtot; int ptot[2]; char ddown[3]; long t; extern leave(); signal(SIGINT, leave); if(signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, leave); time(&t); srand(getpid() + (int)((t>>16) + t)); /* set random number seed */ printf("Black Jack!\n\n"); for(r = 2; r < 15; r++) /* initialize the deck */ for(s = 0; s < 4; s++) { deck[nxtcrd].rank = r; deck[nxtcrd++].suit = s; } shuffle(); /* and shuffle it */ setjmp(jbuf); /* longjmps to here from win(), lose() & draw() */ printf("New game\n"); if(shuff) { printf("Shuffle\n"); shuff = 0; } ins = split = aced = 0; d1 = getcard(0); printf(" up\n"); d2 = getcard(1); strcpy(ddown, curcrd); if(d1 > 10) d1 = 10; if(d2 > 10) d2 = 10; dtot = d1 + d2; p1 = getcard(0); putchar('+'); p2 = getcard(0); putchar('\n'); if(d1 == 1) /* dealer has an ace showing */ if(getresp("Insurance")) ins++; if((aced = (d1 == 1 || d2 == 1)) && dtot == 11) { /* dealers got a bj */ printf("Dealer has %s for blackjack!\n", ddown); if(ins) draw(); else lose(); } if(p1 == p2) if(getresp("Split pair")) split++; if(p1 > 10) p1 = 10; if(p2 > 10) p2 = 10; if(split) { wager *= 2; printf("First down card: "); p2 = getcard(0); if(p2 > 10) p2 = 10; putchar('\n'); r = play(p1, p2); printf("Second down card: "); p2 = getcard(0); if(p2 > 10) p2 = 10; putchar('\n'); s = play(p1, p2); if(r == 22 && s == 22) /* two blackjacks! */ win(); if(r < 0 && s < 0) /* two busts! */ lose(); ptot[0] = r; ptot[1] = s; } else switch(ptot[0] = play(p1, p2)) { case -1: lose(); case 22: win(); } printf("Dealer has %s", ddown); if(aced && dtot < 12 && dtot > 5) dtot += 10; while(dtot < 17) { putchar('+'); d2 = getcard(0); if(d2 > 10) d2 = 10; if(d2 == 1 && !aced) aced = 1; dtot += d2; if(aced && dtot < 12 && dtot > 5) dtot += 10; } printf(" = "); if(dtot > 21) { printf("bust\n"); win(); } printf("%d\n", dtot); if(!(split && ptot[0] != ptot[1])) { if(ptot[0] > dtot) win(); if(dtot > ptot[0]) lose(); draw(); } if(dtot > ptot[0]) { if(dtot > ptot[1]) lose(); if(dtot == ptot[1]) { wager /= 2; lose(); } draw(); } if(ptot[0] > dtot) { if(ptot[1] > dtot) win(); if(ptot[1] == dtot) { wager /= 2; win(); } draw(); } wager /= 2; if(dtot > ptot[1]) lose(); if(dtot < ptot[1]) win(); draw(); } shuffle() { register i; int rancomp(); shuff = 1; i = MINSHUF + ranf(MAXSHUF - MINSHUF); /* how many times to shuffle */ while(i--) qsort(deck, 52, sizeof(struct card), rancomp); nxtcrd = 0; /* reset deck index */ } rancomp(p1, p2) char *p1, *p2; /* these are unused but necessary */ { register r; r = ranf(3) - 1; /* either -1, 0 or 1 */ return(r); } /* ** Return random number greater than ** or equal to zero and less than max. */ ranf(max) register max; { register t; double d; double pow(); if(max <= 0) return(0); tryagain: /* d is a random real bewteen 0 and 1 */ d = rand() / pow(2.0, 15.0); t = d * max; /* multiply by max and truncate fractional part */ if(t == 0) goto tryagain; return(t); } status() { printf("\nAction $%ld\nYou're ", action); if(bux == 0) printf("even\n"); else if(bux > 0) printf("up $%ld\n", bux); else printf("down $%ld\n", -bux); } getcard(f) register f; { register r, s; static char brix[] = "TJQKA"; static char suits[] = "SHCD"; if(nxtcrd > 51) /* no more! */ shuffle(); r = deck[nxtcrd].rank; s = deck[nxtcrd++].suit; if(r > 9) curcrd[0] = brix[r - 10]; else curcrd[0] = '0' + r; curcrd[1] = suits[s]; if(!f) /* not dealer's down card, so we can show it */ printf("%s", curcrd); if(r == 14) /* ace */ return(1); else return(r); } leave() { status(); printf("Bye!!\n"); exit(0); } lose() { action += wager; if(ins) /* took insurance, dealer didn't have bj */ wager += 1; printf("\nYou lose $%d\n", wager); bux -= wager; wager = 2; status(); longjmp(jbuf, 0); } win() { action += wager; if(ins) wager -= 1; printf("\nYou win $%d\n", wager); bux += wager; wager = 2; status(); longjmp(jbuf, 0); } draw() { action += wager; printf("\nYou break even\n"); wager = 2; status(); longjmp(jbuf, 0); } getresp(s) char *s; { char buf[120]; printf("\n%s? ", s); gets(buf); if(buf[0] == 'y') return(1); else return(0); } play(p1, p2) register p1, p2; { register ptot, acep, p; ptot = p1 + p2; if((acep = (p1 == 1 || p2 == 1)) && ptot == 11 ) { printf("You have blackjack!\n"); wager += 1; return(22); } if(ptot == 10 || ptot == 11) if(getresp("Double down")) { wager *= 2; p1 = getcard(0); putchar('\n'); if(p1 > 10) p1 = 10; if(p1 == 1 && ptot == 10) p1 = 11; ptot += p1; goto stick; } while(getresp("Hit")) { p = getcard(0); putchar('\n'); if(p == 1 && !acep) acep = 1; if(p > 10) p = 10; if((ptot += p) > 21) { printf("You bust!\n"); return(-1); } } stick: if(ptot < 12 && acep) ptot += 10; printf("You have %d\n\n", ptot); acep = 0; return(ptot); }