home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 160_01 / bj < prev    next >
Text File  |  1985-11-26  |  15KB  |  695 lines

  1. ###makefile.
  2. FILES=bj.c error.c dekmgr.c \
  3.     getbet.c hndmgr.c nfrom.c outcom.c query.c takes.c
  4.  
  5. OBJECTS=bj.o error.o dekmgr.o \
  6.     getbet.o hndmgr.o nfrom.o outcom.o query.o takes.o
  7.  
  8. DEFS=local.h bj.h dekmgr.h hndmgr.h ttymgr.h
  9.  
  10. LINT=lint -phbxac
  11.  
  12. cleanup:
  13.     -rm *.o
  14.     -du
  15.  
  16. install:
  17.     size bj /a1/phi/bin/bj
  18.     cp bj /a1/phi/bin/bj; rm bj
  19.  
  20. print: Makefile $(DEFS) $(FILES)
  21.     pr $?
  22.     date >print
  23.  
  24. bj: $(DEFS) $(OBJECTS)
  25.     cc -o bj $(OBJECTS)
  26.  
  27. bj.lint: $(DEFS)  $(FILES)
  28.     $(LINT) >bj.lint $(FILES)
  29.  
  30. outcom.x: $(DEFS) outcom.c error.o
  31.     cc -o outcom.x -DTRYMAIN outcom.c error.o
  32.  
  33. all:
  34.     make bj
  35.     make bj.lint
  36.     make install
  37. ###bj.c
  38. /* bj - blackjack
  39.  *        Permission is hereby granted to reproduce and use bj
  40.  */
  41. #include "local.h"
  42. #include "bj.h"
  43. #include "dekmgr.h"
  44. #include "hndmgr.h"
  45. #include "ttymgr.h"
  46. main()
  47.     {
  48.     CASH action;    /* how much money has crossed the table */
  49.     CASH bet;        /* amount of player's current bet per hand */
  50.     CASH result;    /* net result of this hand, plus or minus */
  51.     CASH standing;    /* how much has player won or lost */
  52.     bool canhit;    /* can player's hand take hit? */
  53.     bool isdbl;        /* did player take DBLDN? */
  54.     bool isinsur;    /* did player take insurance? */
  55.     short hand;        /* current hand number */
  56.     short reply;    /* player's reply to DBLDN, SPLIT */
  57.     short tophand;    /* how many hands is player playing, 1 or 2 */
  58.  
  59.     printf("Copyright (c) Plum Hall Inc, 1983\n");
  60.     /* permission to copy and modify is granted, provided that
  61.      * this printout and comment remain intact
  62.      */
  63.     printf("\nWelcome to the Blackjack table\n");
  64.     action = standing = 0;
  65.     opndek();
  66.     while ((bet = getbet()) != 0)
  67.         {
  68.         tophand = 1;
  69.         isinsur = isdbl = NO;
  70.         if (deklow())
  71.             shuffl();
  72.         deal();
  73.         if (val(DEALER, 0) == 11)
  74.             isinsur = takes("i");
  75.         reply = query();
  76.         if (reply == SPLIT)
  77.             tophand = split();
  78.         else if (reply == DBLDN)
  79.             {
  80.             hit(1);
  81.             printf("\n");
  82.             isdbl = YES;
  83.             bet *= 2;
  84.             }
  85.         for (hand = 1; hand <= tophand; ++hand)
  86.             {
  87.             if (tophand == 2)
  88.                 printf("Hand %d:\n", hand);
  89.             canhit = !isdbl;
  90.             canhit &= !isbj(1);
  91.             canhit &= (reply != SPLIT || val(1, 0) != 11);
  92.             while (canhit && takes("h"))
  93.                 {
  94.                 canhit = hit(hand);
  95.                 printf("\n");
  96.                 }
  97.             if (21 < score(hand))
  98.                 printf("Bust\n");
  99.             }
  100.         printf("Dealer has ");
  101.         show(DEALER, 0);
  102.         printf(" + ");
  103.         show(DEALER, 1);
  104.         if (!allbst())
  105.             while (score(DEALER) < 17)
  106.                 hit(DEALER);
  107.         printf(" = %d\n", score(DEALER));
  108.         result = outcom(bet, tophand, isinsur, isdbl);
  109.         action += ABS(result);
  110.         standing += result;
  111.         printf("action = ");
  112.         printf(CASHOUT, action);
  113.         printf(" standing = ");
  114.         printf(CASHOUT, standing);
  115.         printf("\n");
  116.         }
  117.     printf("\nThanks for the game.\n");
  118.     exit(SUCCEED);
  119.     }
  120. ###bj.h
  121. /* bj.h - include-file for blackjack
  122.  */
  123.  
  124. /* defined types
  125.  */
  126. #define CASH long    /* dollars */
  127.  
  128. /* defined constants
  129.  */
  130. #define DEALER 0        /* which hand is dealer; not modifiable */
  131. #define NONE 0            /* no reply */
  132. #define DBLDN 1            /* reply: double down */
  133. #define SPLIT 2            /* reply: split pair */
  134. #define INSUR 3            /* takes: insurance */
  135. #define HIT   4            /* takes: hit */
  136. #define CASHIN "%ld"    /* input format for CASH data */
  137. #define CASHOUT "%ld"    /* output format for CASH data */
  138. ###dekmgr.c
  139. /* dekmgr - deck manager
  140.  */
  141. #include "local.h"
  142. #include "bj.h"
  143. #include "dekmgr.h"
  144. #define NCARDS 4 * 52
  145. static short deck[NCARDS] = 0;    /* the deck */
  146. static short nc = 0;            /* subscript of next card */
  147. static short shufpt = 0;        /* subscript of shuffle point */
  148. /* deklow - is deck at or past shuffle point?
  149.  */
  150. bool deklow()
  151.     {
  152.     return (shufpt <= nc);
  153.     }
  154. /* opndek - initialize the deck
  155.  */
  156. void opndek()
  157.     {
  158.     short i;
  159.     short low;
  160.     short varnum();
  161.  
  162.     for (low = 0; low < NCARDS; low += 52)
  163.         for (i = 0; i < 52; ++i)
  164.             deck[i + low] = i;
  165.     srand(varnum());
  166.     shuffl();
  167.     }
  168. /* shuffl - shuffle the deck
  169.  */
  170. void shuffl()
  171.     {
  172.     short t;        /* temporary for swap */
  173.     short i;        /* index for loop over cards */
  174.     short j;        /* index for swap */
  175.     short nfrom();    /* fn to produce random number */
  176.  
  177.     for (i = 0; i < NCARDS - 1; ++i)
  178.         {
  179.         j = nfrom(i, NCARDS - 1);
  180.         t = deck[j], deck[j] = deck[i], deck[i] = t;
  181.         }
  182.     shufpt = nfrom(NCARDS - 52, NCARDS - 36);
  183.     nc = 0;
  184.     printf("Shuffle\n");
  185.     }
  186.  
  187.  
  188.  
  189. /* tkcard - take a card
  190.  */
  191. short tkcard()
  192.     {
  193.     if (NCARDS <= nc)
  194.         shuffl();
  195.     return (deck[nc++]);
  196.     }
  197. /* varnum - return a varying startoff number
  198.  */
  199. short varnum()
  200.     {
  201.     long time();    /* SYSTEM DEPENDENT - NEEDS CLOCK */
  202.  
  203.     return ((short)time(0));
  204.     }
  205. ###dekmgr.h
  206. /* dekmgr.h - interface for deck manager
  207.  */
  208. bool deklow();
  209. void opndek();
  210. void shuffl();
  211. short tkcard();
  212. ###error.c
  213. /* error - print fatal error message
  214.  */
  215. #include "local.h"
  216. void error(s1, s2)
  217.     char s1[], s2[];
  218.     {
  219.     write(STDERR, s1, strlen(s1));
  220.     write(STDERR, " ", 1);
  221.     write(STDERR, s2, strlen(s2));
  222.     write(STDERR, "\n", 1);
  223.     exit(FAIL);
  224.     }
  225. ###getbet.c
  226. /* getbet - get the player's bet
  227.  */
  228. #include "local.h"
  229. #include "bj.h"
  230. #define MINBET 2
  231. #define MAXBET 1000
  232. CASH getbet()
  233.     {
  234.     char line[BUFSIZ];    /* input line */
  235.     short retn;            /* return from getln and sscanf */
  236.     CASH bet;            /* player's bet */
  237.  
  238.     printf("\n\nYour bet (amount): ");
  239.     FOREVER
  240.         {
  241.         retn = getln(line, BUFSIZ);
  242.         if (retn == EOF)
  243.             return (0);
  244.         retn = sscanf(line, CASHIN, &bet);
  245.         if (retn != 1 || bet < MINBET || MAXBET < bet)
  246.             printf("Number from %d to %d please: ",
  247.                 MINBET, MAXBET);
  248.         else
  249.             return (bet);
  250.         }
  251.     }
  252. ###hndmgr.c
  253. /* hndmgr - hand manager
  254.  */
  255. #include "local.h"
  256. #include "bj.h"
  257. #include "hndmgr.h"
  258. #include "dekmgr.h"
  259. static char spots[13][3] = 
  260.     {"A", "2", "3", "4", "5", "6", "7", "8", "9",
  261.     "10", "J", "Q", "K"};
  262. static char suits[4][2] = {"S", "H", "D", "C"};
  263. static short hands[3][12] = 0;    /* three hands */
  264. static short ncards[3] = 0;        /* how many cards in each hand */
  265. static short tophand = 0;        /* how many player hands active */
  266. /* allbst - are all player's hands busted?
  267.  */
  268. bool allbst()
  269.     {
  270.     if (score(1) <= 21 || (tophand == 2 && score(2) <= 21))
  271.         return (NO);
  272.     else
  273.         return (YES);
  274.     }
  275. /* deal - initialize the hands
  276.  */
  277. void deal()
  278.     {
  279.     hands[1][0] = tkcard();
  280.     hands[DEALER][0] = tkcard();
  281.     hands[1][1] = tkcard();
  282.     hands[DEALER][1] =tkcard();
  283.     ncards[DEALER] = ncards[1] = 2;
  284.     tophand = 1;
  285.     printf("The dealer shows ");
  286.     show(DEALER, 0);
  287.     printf("\nYou have ");
  288.     show(1, 0);
  289.     printf(" + ");
  290.     show(1, 1);
  291.     printf("\n");
  292.     }
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303. /* hit - add a card to a hand
  304.  */
  305. bool hit(h)
  306.     short h;        /* which hand */
  307.     {
  308.     hands[h][ncards[h]] = tkcard();
  309.     printf(" + ");
  310.     show(h, ncards[h]);
  311.     ++ncards[h];
  312.     if (21 < score(h) || h == DEALER && 17 <= score(h))
  313.         return (NO);
  314.     else
  315.         return (YES);
  316.     }
  317. /* isbj - is hand a "natural" 2-card blackjack?
  318.  */
  319. bool isbj(h)
  320.     short h;        /* which hand */
  321.     {
  322.     if (h == DEALER)
  323.         return (ncards[DEALER] == 2 && score(DEALER) == 21);
  324.     else if (h == 1)
  325.         return (tophand == 1 && ncards[1] == 2 && score(1) == 21);
  326.     else
  327.         return (NO);
  328.     }
  329. /* score - tell blackjack value of hand
  330.  */
  331. short score(h)
  332.     short h;        /* which hand */
  333.     {
  334.     short aces = 0;    /* number of aces in hand */
  335.     short i;        /* card counter */
  336.     short sum = 0;    /* accumulated value of hand */
  337.  
  338.     for (i = 0; i < ncards[h]; ++i)
  339.         {
  340.         sum += val(h, i);
  341.         if (val(h, i) == 11)
  342.             ++aces;
  343.         }
  344.     for (i = aces; 0 < i; --i)
  345.         if (21 < sum)
  346.             sum -= 10;
  347.     return (sum);
  348.     }
  349.  
  350.  
  351.  
  352.  
  353. /* show - print a card
  354.  */
  355. void show(h, i)
  356.     short h;    /* which hand */
  357.     short i;    /* which card */
  358.     {
  359.     printf("%s", spots[hands[h][i] % 13]);
  360.     printf("%s", suits[hands[h][i] / 13]);
  361.     }
  362. /* split - split the players pair if allowed
  363.  */
  364. short split()
  365.     {
  366.     if (val(1, 0) != val(1, 1))
  367.         return (1);
  368.     hands[2][0] = hands[1][1];
  369.     hands[1][1] = tkcard();
  370.     hands[2][1] = tkcard();
  371.     ncards[2] = 2;
  372.     printf("Hand 1: "); show(1, 0); printf(" + "); show(1, 1);
  373.     printf("\n");
  374.     printf("Hand 2: "); show(2, 0); printf(" + "); show(2, 1);
  375.     printf("\n");
  376.     tophand = 2;
  377.     return (2);
  378.     }
  379. /* val - tell value of card n of hand h
  380.  */
  381. short val(h, i)
  382.     short h;    /* which hand */
  383.     short i;    /* which card */
  384.     {
  385.     short n;    /* spots value of card */
  386.  
  387.     n = (hands[h][i] % 13) + 1;
  388.     if (n > 9)
  389.         return (10);
  390.     else if (n == 1)
  391.         return (11);
  392.     else
  393.         return (n);
  394.     }
  395. ###hndmgr.h
  396. /* hndmgr.h - interface for hand manager
  397.  */
  398. bool allbst();
  399. void deal();
  400. bool hit();
  401. bool isbj();
  402. CASH outcom();
  403. short score();
  404. void show();
  405. short split();
  406. short val();
  407. ###local.h
  408. /* local.h - definitions for use with
  409.  *      Learning to Program in C
  410.  */
  411. #ifndef FAIL
  412. #include <stdio.h>
  413. #define FAIL        1
  414. #define FOREVER        for (;;)
  415. #define NO            0
  416. #define STDERR        2
  417. #define STDIN        0
  418. #define STDOUT        1
  419. #define SUCCEED        0
  420. #define YES            1
  421. #define bits        ushort
  422. #define bool        int
  423. #define metachar    short
  424. #define tbool        char
  425. #define ushort      unsigned  /* use unsigned short, if you can */
  426. #define void        int
  427. #define getln(s, n) ((fgets(s, n, stdin)==NULL) ? EOF : strlen(s))
  428. #define ABS(x)        (((x) < 0) ? -(x) : (x))
  429. #define MAX(x, y)    (((x) < (y)) ? (y) : (x))
  430. #define MIN(x, y)    (((x) < (y)) ? (x) : (y))
  431. #endif
  432. ###nfrom.c
  433. /* nfrom - return a number between low and high, inclusive
  434.  */
  435. #include "local.h"
  436. short nfrom(low, high)
  437.     register short low, high;
  438.     {
  439.     short rand();
  440.     register short nb = high - low + 1;
  441.  
  442.     return (rand() % nb + low);
  443.     }
  444. ###outcom.c
  445. /* outcom - print outcome of hand(s)
  446.  */
  447. #include "local.h"
  448. #include "bj.h"
  449. #include "hndmgr.h"
  450. static CASH value = 0;
  451. /* outcom - print outcome of hand and compute result
  452.  */
  453. CASH outcom(bet, tophand, isinsur, isdbl)
  454.     CASH bet;        /* amount of player's bet */
  455.     short tophand;    /* how many player hands */
  456.     bool isinsur;    /* player took insurance? */
  457.     bool isdbl;        /* is player DBLDN? */
  458.     {
  459.     short h;        /* which hand */
  460.  
  461.     value = 0;
  462.     if (isinsur && isbj(DEALER))
  463.         prmsg(1, 1, "Insurance wins\n", bet / (isdbl ? 4 : 2));
  464.     else if (isinsur)
  465.         prmsg(1, 1, "Insurance loses\n", -bet / (isdbl ? 4 : 2));
  466.     if (isbj(DEALER) && !isbj(1))
  467.         prmsg(1, 1, "Dealer BJ beats all but BJ",
  468.             -bet / (isdbl ? 2 : 1));
  469.     else if (isbj(DEALER) && isbj(1))
  470.         prmsg(1, 1, "Both BJ: push", (CASH)0);
  471.     else if (isbj(1))
  472.         prmsg(1, 1, "Your BJ wins 3 for 2", (3 * bet) / 2);
  473.     else
  474.         {
  475.         for (h = 1; h <= tophand; ++h)
  476.             {
  477.             if (21 < score(h))
  478.                 value -= bet;    /* "Bust" message printed already */
  479.             else if (score(DEALER) == score(h))
  480.                 prmsg(h, tophand, "Push", (CASH)0);
  481.             else if (score(DEALER) < score(h) || 21 < score(DEALER))
  482.                 prmsg(h, tophand, "Win", bet);
  483.             else
  484.                 prmsg(h, tophand, "Lose", -bet);
  485.             }
  486.         }
  487.     return (value);
  488.     }
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495. /* prmsg - print appropriate message
  496.  */
  497. static void prmsg(h, tophand, s, delta)
  498.     short h;        /* which hand */
  499.     short tophand;    /* how many hands */
  500.     char s[];        /* message */
  501.     CASH delta;        /* change of value (+ | -) */
  502.     {
  503.     if (tophand == 2)
  504.         printf("On hand %d, ", h);
  505.     printf("%s\n", s);
  506.     value += delta;
  507.     }
  508. #ifdef TRYMAIN
  509. static short bj[2] = 0;    /* isbj, for each hand */
  510. static short sc[3] = 0;    /* hand scores, for testing */
  511. main()
  512.     {
  513.     char line[BUFSIZ];        /* line of test input */
  514.     short len;                /* returned value from input fn */
  515.     short ibet;                /* players bet, as short int */
  516.     short ins;                /* isinsur? */
  517.     short toph;                /* tophand */
  518.     short dbl;                /* isdbl? */
  519.     CASH value;                /* return from outcom */
  520.  
  521.     FOREVER
  522.         {
  523.         printf("%-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s\n",
  524.             "bet", "toph", "ins", "dbl",
  525.             "bj[0]", "bj[1]", "sc[0]", "sc[1]", "sc[2]");
  526.         len = echoln(line, BUFSIZ);
  527.         if (len == EOF)
  528.             break;
  529.         if (9 != sscanf(line, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
  530.             &ibet, &toph, &ins, &dbl,
  531.             &bj[0], &bj[1], &sc[0], &sc[1], &sc[2]))
  532.             error("outcom input error", "");
  533.         value = outcom((CASH)ibet, toph, ins, dbl);
  534.         printf("outcom() = ");
  535.         printf(CASHOUT, value);
  536.         printf("\n");
  537.         }
  538.     }
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545. /* score - dummy version for testing
  546.  */
  547. short score(h)
  548.     short h;    /* which hand */
  549.     {
  550.     return (sc[h]);
  551.     }
  552. /* isbj - dummy version for testing
  553.  */
  554. bool isbj(h)
  555.     short h;    /* which hand */
  556.     {
  557.     return (bj[h]);
  558.     }
  559. /* echoln - get and echo an input line
  560.  */
  561. short echoln(line, size)
  562.     char line[];
  563.     short size;
  564.     {
  565.     short len;
  566.  
  567.     if ((len = getln(line, size)) != EOF)
  568.         printf("%s", line);
  569.     return (len);
  570.     }
  571. #endif
  572. ###ttymgr.c
  573. /* ttymgr - tty (terminal) manager
  574.  */
  575. #include "local.h"
  576. #include "bj.h"
  577. #include "hndmgr.h"
  578. #include "ttymgr.h"
  579. #define NMSGS 4
  580. #define LENMSG 15
  581. static bool askedhit = NO;
  582. static bool wanthit = NO;
  583. static char qchar[NMSGS+1] = "dsih";
  584. static char qmsg[NMSGS][LENMSG+1] =
  585.     {
  586.     "Double down",
  587.     "Split pair",
  588.     "Insurance",
  589.     "Hit",
  590.     };
  591. static short nmsg[NMSGS] = 0;
  592. /* query - get players response for DBLDN, SPLIT, HIT
  593.  */
  594. short query()
  595.     {
  596.     short ask();
  597.     short ret;        /* return from ask() */
  598.  
  599.     if (val(1, 0) == val(1, 1))
  600.         ret = ask("dsh");
  601.     else
  602.         ret = ask("dh");
  603.     askedhit = (ret != SPLIT);
  604.     wanthit = (ret == HIT);
  605.     if (wanthit)
  606.         ret = NONE;
  607.     return (ret);
  608.     }
  609. /* takes - get a YES or NO reply to question
  610.  */
  611. bool takes(s)
  612.     char s[];
  613.     {
  614.     short ask();
  615.  
  616.     if (askedhit && strcmp(s, "h") == 0)
  617.         {
  618.         askedhit = NO;
  619.         return (wanthit);
  620.         }
  621.     return (ask(s) != NONE);
  622.     }
  623. /* ask - get a choice among alternatives
  624.  */
  625. static short ask(s)
  626.     char s[];
  627.     {
  628.     bool isbrief;                /* is prompt brief? */
  629.     char ans[BUFSIZ];            /* player's reply line */
  630.     char c;                        /* player's one-char answer */
  631.     short i;                    /* index over chars of s */
  632.     short j;                    /* index over chars of qchar */
  633.     short slen;                    /* length of s */
  634.     static short msglim = 5;    /* verbosity limit */
  635.     unsigned strscn();            /* gives the index of c in s */
  636.  
  637.     isbrief = YES;
  638.     slen = strlen(s);
  639.     for (i = 0; i < slen; ++i)
  640.         {
  641.         j = strscn(qchar, s[i]);
  642.         if (++nmsg[j] <= msglim)
  643.             isbrief = NO;
  644.         }
  645.     if (isbrief)
  646.         {
  647.         for (i = 0; i < slen; ++i)
  648.             printf("%c?", s[i]);
  649.         printf("\n");
  650.         }
  651.     FOREVER
  652.         {
  653.         if (!isbrief)
  654.             {
  655.             printf("Type\n");
  656.             for (i = 0; i < slen; ++i)
  657.                 printf("%c      For %s\n",
  658.                     s[i], qmsg[strscn(qchar, s[i])]);
  659.             printf("RETURN For None\n");
  660.             }
  661.         if (getln(ans, BUFSIZ) == EOF)
  662.             error("Bye!", "");
  663.         c = tolower(ans[0]);
  664.         if (c == '\n')
  665.                 return (NONE);
  666.         for (i = 0; i < slen; ++i)
  667.             if (s[i] == c)
  668.                 return (1 + strscn(qchar, c));
  669.         isbrief = NO;
  670.         }
  671.     }
  672.  
  673. /* strscn - return the index of c in string s
  674.  */
  675. unsigned strscn(s, c)
  676.     char s[];    /* string to be scanned */
  677.     char c;    /* char to be matched */
  678.     {
  679.     register unsigned i;
  680.  
  681.     for (i = 0; s[i] != c && s[i] != '\0'; ++i)
  682.         ;
  683.     return (i);
  684.     }
  685. ###ttymgr.h
  686. /* ttymgr.h - interface for tty manager
  687.  */
  688. CASH getbet();
  689. bool takes();
  690. short query();
  691. ###mk_bj.bat
  692. lccm bj dekmgr getbet hndmgr nfrom outcom ttymgr  ++  bj  +dekmgr+getbet+hndmgr+nfrom+outcom+ttymgr
  693. ###bj.
  694. ###EOF
  695.