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 >
Wrap
Text File
|
1985-11-26
|
15KB
|
695 lines
###makefile.
FILES=bj.c error.c dekmgr.c \
getbet.c hndmgr.c nfrom.c outcom.c query.c takes.c
OBJECTS=bj.o error.o dekmgr.o \
getbet.o hndmgr.o nfrom.o outcom.o query.o takes.o
DEFS=local.h bj.h dekmgr.h hndmgr.h ttymgr.h
LINT=lint -phbxac
cleanup:
-rm *.o
-du
install:
size bj /a1/phi/bin/bj
cp bj /a1/phi/bin/bj; rm bj
print: Makefile $(DEFS) $(FILES)
pr $?
date >print
bj: $(DEFS) $(OBJECTS)
cc -o bj $(OBJECTS)
bj.lint: $(DEFS) $(FILES)
$(LINT) >bj.lint $(FILES)
outcom.x: $(DEFS) outcom.c error.o
cc -o outcom.x -DTRYMAIN outcom.c error.o
all:
make bj
make bj.lint
make install
###bj.c
/* bj - blackjack
* Permission is hereby granted to reproduce and use bj
*/
#include "local.h"
#include "bj.h"
#include "dekmgr.h"
#include "hndmgr.h"
#include "ttymgr.h"
main()
{
CASH action; /* how much money has crossed the table */
CASH bet; /* amount of player's current bet per hand */
CASH result; /* net result of this hand, plus or minus */
CASH standing; /* how much has player won or lost */
bool canhit; /* can player's hand take hit? */
bool isdbl; /* did player take DBLDN? */
bool isinsur; /* did player take insurance? */
short hand; /* current hand number */
short reply; /* player's reply to DBLDN, SPLIT */
short tophand; /* how many hands is player playing, 1 or 2 */
printf("Copyright (c) Plum Hall Inc, 1983\n");
/* permission to copy and modify is granted, provided that
* this printout and comment remain intact
*/
printf("\nWelcome to the Blackjack table\n");
action = standing = 0;
opndek();
while ((bet = getbet()) != 0)
{
tophand = 1;
isinsur = isdbl = NO;
if (deklow())
shuffl();
deal();
if (val(DEALER, 0) == 11)
isinsur = takes("i");
reply = query();
if (reply == SPLIT)
tophand = split();
else if (reply == DBLDN)
{
hit(1);
printf("\n");
isdbl = YES;
bet *= 2;
}
for (hand = 1; hand <= tophand; ++hand)
{
if (tophand == 2)
printf("Hand %d:\n", hand);
canhit = !isdbl;
canhit &= !isbj(1);
canhit &= (reply != SPLIT || val(1, 0) != 11);
while (canhit && takes("h"))
{
canhit = hit(hand);
printf("\n");
}
if (21 < score(hand))
printf("Bust\n");
}
printf("Dealer has ");
show(DEALER, 0);
printf(" + ");
show(DEALER, 1);
if (!allbst())
while (score(DEALER) < 17)
hit(DEALER);
printf(" = %d\n", score(DEALER));
result = outcom(bet, tophand, isinsur, isdbl);
action += ABS(result);
standing += result;
printf("action = ");
printf(CASHOUT, action);
printf(" standing = ");
printf(CASHOUT, standing);
printf("\n");
}
printf("\nThanks for the game.\n");
exit(SUCCEED);
}
###bj.h
/* bj.h - include-file for blackjack
*/
/* defined types
*/
#define CASH long /* dollars */
/* defined constants
*/
#define DEALER 0 /* which hand is dealer; not modifiable */
#define NONE 0 /* no reply */
#define DBLDN 1 /* reply: double down */
#define SPLIT 2 /* reply: split pair */
#define INSUR 3 /* takes: insurance */
#define HIT 4 /* takes: hit */
#define CASHIN "%ld" /* input format for CASH data */
#define CASHOUT "%ld" /* output format for CASH data */
###dekmgr.c
/* dekmgr - deck manager
*/
#include "local.h"
#include "bj.h"
#include "dekmgr.h"
#define NCARDS 4 * 52
static short deck[NCARDS] = 0; /* the deck */
static short nc = 0; /* subscript of next card */
static short shufpt = 0; /* subscript of shuffle point */
/* deklow - is deck at or past shuffle point?
*/
bool deklow()
{
return (shufpt <= nc);
}
/* opndek - initialize the deck
*/
void opndek()
{
short i;
short low;
short varnum();
for (low = 0; low < NCARDS; low += 52)
for (i = 0; i < 52; ++i)
deck[i + low] = i;
srand(varnum());
shuffl();
}
/* shuffl - shuffle the deck
*/
void shuffl()
{
short t; /* temporary for swap */
short i; /* index for loop over cards */
short j; /* index for swap */
short nfrom(); /* fn to produce random number */
for (i = 0; i < NCARDS - 1; ++i)
{
j = nfrom(i, NCARDS - 1);
t = deck[j], deck[j] = deck[i], deck[i] = t;
}
shufpt = nfrom(NCARDS - 52, NCARDS - 36);
nc = 0;
printf("Shuffle\n");
}
/* tkcard - take a card
*/
short tkcard()
{
if (NCARDS <= nc)
shuffl();
return (deck[nc++]);
}
/* varnum - return a varying startoff number
*/
short varnum()
{
long time(); /* SYSTEM DEPENDENT - NEEDS CLOCK */
return ((short)time(0));
}
###dekmgr.h
/* dekmgr.h - interface for deck manager
*/
bool deklow();
void opndek();
void shuffl();
short tkcard();
###error.c
/* error - print fatal error message
*/
#include "local.h"
void error(s1, s2)
char s1[], s2[];
{
write(STDERR, s1, strlen(s1));
write(STDERR, " ", 1);
write(STDERR, s2, strlen(s2));
write(STDERR, "\n", 1);
exit(FAIL);
}
###getbet.c
/* getbet - get the player's bet
*/
#include "local.h"
#include "bj.h"
#define MINBET 2
#define MAXBET 1000
CASH getbet()
{
char line[BUFSIZ]; /* input line */
short retn; /* return from getln and sscanf */
CASH bet; /* player's bet */
printf("\n\nYour bet (amount): ");
FOREVER
{
retn = getln(line, BUFSIZ);
if (retn == EOF)
return (0);
retn = sscanf(line, CASHIN, &bet);
if (retn != 1 || bet < MINBET || MAXBET < bet)
printf("Number from %d to %d please: ",
MINBET, MAXBET);
else
return (bet);
}
}
###hndmgr.c
/* hndmgr - hand manager
*/
#include "local.h"
#include "bj.h"
#include "hndmgr.h"
#include "dekmgr.h"
static char spots[13][3] =
{"A", "2", "3", "4", "5", "6", "7", "8", "9",
"10", "J", "Q", "K"};
static char suits[4][2] = {"S", "H", "D", "C"};
static short hands[3][12] = 0; /* three hands */
static short ncards[3] = 0; /* how many cards in each hand */
static short tophand = 0; /* how many player hands active */
/* allbst - are all player's hands busted?
*/
bool allbst()
{
if (score(1) <= 21 || (tophand == 2 && score(2) <= 21))
return (NO);
else
return (YES);
}
/* deal - initialize the hands
*/
void deal()
{
hands[1][0] = tkcard();
hands[DEALER][0] = tkcard();
hands[1][1] = tkcard();
hands[DEALER][1] =tkcard();
ncards[DEALER] = ncards[1] = 2;
tophand = 1;
printf("The dealer shows ");
show(DEALER, 0);
printf("\nYou have ");
show(1, 0);
printf(" + ");
show(1, 1);
printf("\n");
}
/* hit - add a card to a hand
*/
bool hit(h)
short h; /* which hand */
{
hands[h][ncards[h]] = tkcard();
printf(" + ");
show(h, ncards[h]);
++ncards[h];
if (21 < score(h) || h == DEALER && 17 <= score(h))
return (NO);
else
return (YES);
}
/* isbj - is hand a "natural" 2-card blackjack?
*/
bool isbj(h)
short h; /* which hand */
{
if (h == DEALER)
return (ncards[DEALER] == 2 && score(DEALER) == 21);
else if (h == 1)
return (tophand == 1 && ncards[1] == 2 && score(1) == 21);
else
return (NO);
}
/* score - tell blackjack value of hand
*/
short score(h)
short h; /* which hand */
{
short aces = 0; /* number of aces in hand */
short i; /* card counter */
short sum = 0; /* accumulated value of hand */
for (i = 0; i < ncards[h]; ++i)
{
sum += val(h, i);
if (val(h, i) == 11)
++aces;
}
for (i = aces; 0 < i; --i)
if (21 < sum)
sum -= 10;
return (sum);
}
/* show - print a card
*/
void show(h, i)
short h; /* which hand */
short i; /* which card */
{
printf("%s", spots[hands[h][i] % 13]);
printf("%s", suits[hands[h][i] / 13]);
}
/* split - split the players pair if allowed
*/
short split()
{
if (val(1, 0) != val(1, 1))
return (1);
hands[2][0] = hands[1][1];
hands[1][1] = tkcard();
hands[2][1] = tkcard();
ncards[2] = 2;
printf("Hand 1: "); show(1, 0); printf(" + "); show(1, 1);
printf("\n");
printf("Hand 2: "); show(2, 0); printf(" + "); show(2, 1);
printf("\n");
tophand = 2;
return (2);
}
/* val - tell value of card n of hand h
*/
short val(h, i)
short h; /* which hand */
short i; /* which card */
{
short n; /* spots value of card */
n = (hands[h][i] % 13) + 1;
if (n > 9)
return (10);
else if (n == 1)
return (11);
else
return (n);
}
###hndmgr.h
/* hndmgr.h - interface for hand manager
*/
bool allbst();
void deal();
bool hit();
bool isbj();
CASH outcom();
short score();
void show();
short split();
short val();
###local.h
/* local.h - definitions for use with
* Learning to Program in C
*/
#ifndef FAIL
#include <stdio.h>
#define FAIL 1
#define FOREVER for (;;)
#define NO 0
#define STDERR 2
#define STDIN 0
#define STDOUT 1
#define SUCCEED 0
#define YES 1
#define bits ushort
#define bool int
#define metachar short
#define tbool char
#define ushort unsigned /* use unsigned short, if you can */
#define void int
#define getln(s, n) ((fgets(s, n, stdin)==NULL) ? EOF : strlen(s))
#define ABS(x) (((x) < 0) ? -(x) : (x))
#define MAX(x, y) (((x) < (y)) ? (y) : (x))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
###nfrom.c
/* nfrom - return a number between low and high, inclusive
*/
#include "local.h"
short nfrom(low, high)
register short low, high;
{
short rand();
register short nb = high - low + 1;
return (rand() % nb + low);
}
###outcom.c
/* outcom - print outcome of hand(s)
*/
#include "local.h"
#include "bj.h"
#include "hndmgr.h"
static CASH value = 0;
/* outcom - print outcome of hand and compute result
*/
CASH outcom(bet, tophand, isinsur, isdbl)
CASH bet; /* amount of player's bet */
short tophand; /* how many player hands */
bool isinsur; /* player took insurance? */
bool isdbl; /* is player DBLDN? */
{
short h; /* which hand */
value = 0;
if (isinsur && isbj(DEALER))
prmsg(1, 1, "Insurance wins\n", bet / (isdbl ? 4 : 2));
else if (isinsur)
prmsg(1, 1, "Insurance loses\n", -bet / (isdbl ? 4 : 2));
if (isbj(DEALER) && !isbj(1))
prmsg(1, 1, "Dealer BJ beats all but BJ",
-bet / (isdbl ? 2 : 1));
else if (isbj(DEALER) && isbj(1))
prmsg(1, 1, "Both BJ: push", (CASH)0);
else if (isbj(1))
prmsg(1, 1, "Your BJ wins 3 for 2", (3 * bet) / 2);
else
{
for (h = 1; h <= tophand; ++h)
{
if (21 < score(h))
value -= bet; /* "Bust" message printed already */
else if (score(DEALER) == score(h))
prmsg(h, tophand, "Push", (CASH)0);
else if (score(DEALER) < score(h) || 21 < score(DEALER))
prmsg(h, tophand, "Win", bet);
else
prmsg(h, tophand, "Lose", -bet);
}
}
return (value);
}
/* prmsg - print appropriate message
*/
static void prmsg(h, tophand, s, delta)
short h; /* which hand */
short tophand; /* how many hands */
char s[]; /* message */
CASH delta; /* change of value (+ | -) */
{
if (tophand == 2)
printf("On hand %d, ", h);
printf("%s\n", s);
value += delta;
}
#ifdef TRYMAIN
static short bj[2] = 0; /* isbj, for each hand */
static short sc[3] = 0; /* hand scores, for testing */
main()
{
char line[BUFSIZ]; /* line of test input */
short len; /* returned value from input fn */
short ibet; /* players bet, as short int */
short ins; /* isinsur? */
short toph; /* tophand */
short dbl; /* isdbl? */
CASH value; /* return from outcom */
FOREVER
{
printf("%-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s\n",
"bet", "toph", "ins", "dbl",
"bj[0]", "bj[1]", "sc[0]", "sc[1]", "sc[2]");
len = echoln(line, BUFSIZ);
if (len == EOF)
break;
if (9 != sscanf(line, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
&ibet, &toph, &ins, &dbl,
&bj[0], &bj[1], &sc[0], &sc[1], &sc[2]))
error("outcom input error", "");
value = outcom((CASH)ibet, toph, ins, dbl);
printf("outcom() = ");
printf(CASHOUT, value);
printf("\n");
}
}
/* score - dummy version for testing
*/
short score(h)
short h; /* which hand */
{
return (sc[h]);
}
/* isbj - dummy version for testing
*/
bool isbj(h)
short h; /* which hand */
{
return (bj[h]);
}
/* echoln - get and echo an input line
*/
short echoln(line, size)
char line[];
short size;
{
short len;
if ((len = getln(line, size)) != EOF)
printf("%s", line);
return (len);
}
#endif
###ttymgr.c
/* ttymgr - tty (terminal) manager
*/
#include "local.h"
#include "bj.h"
#include "hndmgr.h"
#include "ttymgr.h"
#define NMSGS 4
#define LENMSG 15
static bool askedhit = NO;
static bool wanthit = NO;
static char qchar[NMSGS+1] = "dsih";
static char qmsg[NMSGS][LENMSG+1] =
{
"Double down",
"Split pair",
"Insurance",
"Hit",
};
static short nmsg[NMSGS] = 0;
/* query - get players response for DBLDN, SPLIT, HIT
*/
short query()
{
short ask();
short ret; /* return from ask() */
if (val(1, 0) == val(1, 1))
ret = ask("dsh");
else
ret = ask("dh");
askedhit = (ret != SPLIT);
wanthit = (ret == HIT);
if (wanthit)
ret = NONE;
return (ret);
}
/* takes - get a YES or NO reply to question
*/
bool takes(s)
char s[];
{
short ask();
if (askedhit && strcmp(s, "h") == 0)
{
askedhit = NO;
return (wanthit);
}
return (ask(s) != NONE);
}
/* ask - get a choice among alternatives
*/
static short ask(s)
char s[];
{
bool isbrief; /* is prompt brief? */
char ans[BUFSIZ]; /* player's reply line */
char c; /* player's one-char answer */
short i; /* index over chars of s */
short j; /* index over chars of qchar */
short slen; /* length of s */
static short msglim = 5; /* verbosity limit */
unsigned strscn(); /* gives the index of c in s */
isbrief = YES;
slen = strlen(s);
for (i = 0; i < slen; ++i)
{
j = strscn(qchar, s[i]);
if (++nmsg[j] <= msglim)
isbrief = NO;
}
if (isbrief)
{
for (i = 0; i < slen; ++i)
printf("%c?", s[i]);
printf("\n");
}
FOREVER
{
if (!isbrief)
{
printf("Type\n");
for (i = 0; i < slen; ++i)
printf("%c For %s\n",
s[i], qmsg[strscn(qchar, s[i])]);
printf("RETURN For None\n");
}
if (getln(ans, BUFSIZ) == EOF)
error("Bye!", "");
c = tolower(ans[0]);
if (c == '\n')
return (NONE);
for (i = 0; i < slen; ++i)
if (s[i] == c)
return (1 + strscn(qchar, c));
isbrief = NO;
}
}
/* strscn - return the index of c in string s
*/
unsigned strscn(s, c)
char s[]; /* string to be scanned */
char c; /* char to be matched */
{
register unsigned i;
for (i = 0; s[i] != c && s[i] != '\0'; ++i)
;
return (i);
}
###ttymgr.h
/* ttymgr.h - interface for tty manager
*/
CASH getbet();
bool takes();
short query();
###mk_bj.bat
lccm bj dekmgr getbet hndmgr nfrom outcom ttymgr ++ bj +dekmgr+getbet+hndmgr+nfrom+outcom+ttymgr
###bj.
###EOF