[net.sources] Black Jack

troeger@ttidca.UUCP (Jeff Troeger) (01/20/85)

Due to the massive request I got for the Black Jack game I offered to 
distribute last week, I am posting it to net.sources to make sure
I cover all parties interested (and because I am a novice with  the
net and don't know how to access ARPA.. ) There are a number of problems
with the program which I have commented in the source file but haven't
had a chance to fix. Sorry for the delay, and hope this is what everyone
was looking for.

---------------------------R E M O V E  H E R E------------------------------
# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# bjack.c

echo x - bjack.c
cat > "bjack.c" << '//E*O*F bjack.c//'
/*
   BJACK - Play blackjack.
 
   A Christopher Hall fecit -- 4/84
 
       The Following are bugs found by Jeff Troeger 12/84:
       * Split bet is always 10, should be what the amount bet is.
       * If the Dollar amount won/lost is too large, the variable overflows
        (causing a negative amount to go positive...)
       * The split function doesn't work correctly with recursive
         splits (ie. splitting a split bet)
 
*/
#include <bdscio.h>
 
#define DEBUG   0       /* Debug assembly switch */
#define DEBUG1  0
#define DOSTATS 0       /* 1==keep stats; output at end */
 
#define CLEAR   "\033[H\033[J"  /* Clear screen and move home */
 
#define HNDS    5       /* Maximum number of players' hands */
 
#define PLRROW  11      /* Row where players' output begins */
#define PLSROW  23      /* Row where players' score goes */
#define PLCWID  16      /* Width of each player's space */
#define DLRCOL  33      /* Column for dealer's cards */
 
char insflg;            /* 1==Ask for insurance; 0==Don't */
int numcards;           /* Number of decks to use (up to four) */
int enddeck;            /* When to shuffle (when enddeck is exceeded) */
char deck[208];         /* Holder of up to four decks of cards */
int  deckc;             /* Index into deck */
char *face[5];          /* Names of the face cards */
char *suit[4];          /* Names of the suits */
 
int dtotal,dacef;       /* Dealer's total, ace flag */
char daceup;            /* Flag: dealer has an ace up */
char upcard;            /* Dealer's face-up card */
char dncard;            /* Dealer's face-down card */
 
int hands;              /* Total number of hands to deal */
int plyr;               /* Index of current player */
int total[HNDS];        /* Total of cards in each hand */
int stotal[HNDS];       /* Total of cards in each split hand */
int score[HNDS];        /* Winnings for each player */
int bet[HNDS];          /* Each player's bet for this hand */
int sbet[HNDS];         /* Players' first bet when he's split */
char aceflg[HNDS];      /* Flag: an ace has been dealt to this hand */
int acef;               /* Got-an-ace flag for the current hand */
int insur[HNDS];        /* Amount of insurance for this hand */
int defbet;             /* Default amount of bet */
int newbet;             /* Amount of bet for this hand */
int hpos[HNDS];         /* Column positions for each hand */
 
#if DOSTATS
int  stats[7][13];      /* Counts of score given 1st card */
#endif
 
char strbuf[80];        /* Input string buffer */
 
main(argc,argv)
 char **argv;
{
        int i,j,sum;
 
        printf("%s\nBlackjack, V1.1",CLEAR);
        printf(" -- Copyright (c) 1984 by A Christopher Hall\n\n");
        srand(0);       /* Init the random number generator */
        printf("How many players (1-5)? ");
        gets(strbuf);
        hands = atoi(strbuf);
        if (hands < 1) hands = 1;
        else if (hands > HNDS) hands = HNDS;
 
        printf("How many decks (1-4)? ");
        gets(strbuf);
        numcards = atoi(strbuf);
        if ((numcards < 1) || (numcards > 4)) numcards = 4;
        enddeck = (numcards *= 52) - 2 - hands * 4;
 
        printf("Amount of bet (default=10)? ");
        gets(strbuf);
        defbet = atoi(strbuf);
        if (defbet < 1) defbet = 10;
        newbet = defbet;
 
        printf("Ask for insurance (N,Y)? ");
        insflg = (toupper(getchar()) == 'Y') ? 1 : 0;
 
/* Set up the screen column positions for each hand */
        j = 16;
        if (hands == 5) sum = 1;
        else if (hands == 4) sum = 5;
             else if (hands == 3) { sum = 9; j = 24; }
                  else if (hands == 2) { sum = 17; j = 32; }
                       else sum = 33;
        for (i=0; i<hands; i++) {
                hpos[i] = sum;
                sum += j;
                score[i] = 1000; /* Dole out the money */
        }
 
        setdeck();      /* Initialize the deck */
 
        while(1) {
                poscur(1,1);
                printf("Shuffling");
                shuffle();      /* Shuffle the cards */
                while (deckc < enddeck) {
                        printf(CLEAR); /* Clear the screen */
 
/* Get the players' bets */
                        for (plyr=0; plyr<hands; plyr++) setbet();
                        ddeal();        /* Deal the dealer's cards */
 
/* Deal the players' initial cards */
                        for (plyr=0; plyr<hands; plyr++) sdeal();
 
/* See who has blackjack. If dealer has it don't play the hand. */
/* If dealer has an ace up ask for insurance. Then take the players' money */
/* Else play each player's hand, then play the dealer. */
                        if (!blackj()) {
                            for (plyr=0; plyr<hands; plyr++) phand();
                            pdealr();
                        }
#if DOSTATS
                        statsav();      /* Save dealer's statistics */
#endif
/* Score each player */
                        for (plyr=sum=0; plyr<hands; plyr++) {
                                pscore();
                                sum += score[plyr] - 1000;
                        }
                        poscur(2,60); printf("Total: %d",sum);
                        getbet();
                }
        }
}
/*
   GETBET - Get the bet for the next round.
   The user can type:
        n<x>    to bet $n (x is any non-number),
        ^C      to stop the program and possibly print statistics
                (note: getinp() handles this),
        else    use the default bet.
 
        Rubout can be used to edit the input.
*/
getbet()
{
        char chr;
 
        newbet = 0;
        poscur(3,60); printf("Bet (%d): ",defbet);
        if (!(newbet = getnum())) newbet = defbet;
}
/*
   SETBET - Set up player plyr's bet for this hand.
*/
setbet()
{
        int plcpos;
 
        plcpos = hpos[plyr];
        poscur(PLRROW,plcpos); printf("Player %d:",plyr+1);
        poscur(PLRROW+1,plcpos); printf("$%4d.00",score[plyr]);
        poscur(PLRROW+2,plcpos); printf("Bet: %d",newbet);
        bet[plyr] = newbet;
}
/*
   DDEAL - Deal the dealer's hand
*/
ddeal()
{
        acef = 0;               /* Say no ace has been seen yet */
        poscur(1,DLRCOL-5);
        printf("Dealer:");
        poscur(2,DLRCOL);
        pcard(upcard = deck[deckc++]); /* Deal a card; type it out */
        dncard = deck[deckc++]; /* Deal the second card */
        dtotal = getval(upcard);
        daceup = acef;          /* Remember if the dealer has an ace up */
        dtotal += getval(dncard);
        dacef = acef;           /* Remember if the dealer has an ace */
}
/*
   SDEAL - Deal the first two cards to player plyr.
*/
sdeal()
{
        int card,card1,plcpos;
 
        plcpos = hpos[plyr];
        acef = 0;                       /* Say no ace has been seen yet */
        poscur(PLRROW+4,plcpos);
        pcard(card = deck[deckc++]);    /* Deal a card; type it out */
        poscur(PLRROW+5,plcpos);
        pcard(card1 = deck[deckc++]);   /* Deal; type the second card */
        total[plyr] = getval(card) + getval(card1);
        stotal[plyr] = ((card >> 2) == (card1 >> 2)) ? card1 : -1;
        if (total[plyr] == 21) total[plyr] = 22; /* Make blackjack a winner */
        aceflg[plyr] = acef;            /* Remember if the player has an ace */
}
/*
   BLACKJ - See if the dealer has blackjack. If so, all players lose
   except those who have it, who push. Otherwise players with it win
   half again their bet.
*/
blackj()
{
/* If the dealer has an ace up, ask for insurance.*/
        if (daceup && insflg) {
                for (plyr=0; plyr<hands; plyr++) askins();
                for (plyr=0; plyr<hands; plyr++) doins();
        }
        if (dtotal != 21) return 0; /* Dealer no got. Ha. */
        poscur(3,DLRCOL); pcard(dncard); /* Show his other card */
        printf("\007");         /* Get the player's attention */
        dtotal = 22;            /* Make dealer's hand a winner */
        return 1;               /* Tell caller the dealer's got it */
}
/*
   ASKINS - Ask player plyr if he wants insurance. If so, insure him for
   half his bet.
*/
askins()
{
        int plcpos;
 
        plcpos = hpos[plyr];
        poscur(PLRROW-2,plcpos);
        printf("Insurance? ");
        if (toupper(getchar()) == 'Y') {
                insur[plyr] = bet[plyr] >> 1;
                poscur(PLRROW-2,plcpos+11);
                printf("%d",insur[plyr]);
        }
}
/*
   DOINS - Handle the insurance bet for player plyr.
   If the player insures, then if the dealer has blackjack just push the
   hand. Else take the insurance and let the user play the hand out.
*/
doins()
{
        int plcpos;
 
        plcpos = hpos[plyr];
        poscur(PLRROW-2,plcpos);    /* Erase insurance message */
        printf("             ");
        if (insur[plyr]) {
                if (dtotal == 21) total[plyr] = 22;
                else {
                        score[plyr] -= insur[plyr]; /* Charge him */
                        poscur(PLRROW+1,plcpos); printf("$%4d.00",score[plyr]);
                }
                insur[plyr] = 0;
        }
}
/*
   PHAND - Play a player's hand. Do whatever he wants to do:
        H == hit
        D == double
        S == split
        X == stay
    Space == stay
  Play until he stays or busts.
*/
phand()
{
        int i;
        int plcpos,splitf,tcards;
        char done,card,chr,fflag;
 
        plcpos = hpos[plyr];
        tcards = PLRROW + 5;
        acef = aceflg[plyr];
        if (total[plyr] == 22) goto Black;
        splitf = -1;
Split2: done = fflag = 0;
        while (!done) {
                typscore(plcpos,splitf);
                poscur(++tcards,plcpos);
                printf("Action: ");
                chr = toupper(getchar());
                poscur(tcards,plcpos);
                switch (chr) {
                  case ' ':
                  case 'X':
                    printf("          ");
                    done = 1;
                    break;
                  case 'H':
                    pcard(card = deck[deckc++]); /* Deal a card; type it out */
                    fflag = 1;
                    if ((total[plyr] += getval(card)) > 21) {
                        if (acef) {
                                total[plyr] -= 10;
                                acef = 0;
                        }
                        else done = 1;
                    }
                    break;
                  case 'D':
                    if (fflag) {
                        printf("          ");
                        tcards--;
                        break;
                    }
                    pcard(card = deck[deckc++]); /* Deal a card; type it out */
                    if ((total[plyr] += getval(card)) > 21) {
                        if (acef) {
                                total[plyr] -= 10;
                                acef = 0;
                        }
                    }
                    done = 1;
                    if (splitf >= -1) poscur(PLRROW+2,plcpos+5);
                    else poscur(PLRROW+2,plcpos+9);
            //E*O*F bjack.c//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
    323   1445  11264 bjack.c
!!!
wc  bjack.c | sed 's=[^ ]*/==' | diff -b $temp -
exit 0

-- 
==============================================================================
<This space left intentionally blank>
Jeff Troeger
Citicorp TTI                             
3100 Ocean Park Blvd.                  
Santa Monica, California  90405
(213) 450-9111, ext. 3096
{vortex,philabs}!ttidca!troeger