Path: utzoo!attcan!uunet!husc6!bloom-beacon!mit-eddie!uw-beaver!tektronix!tekgen!tekred!games From: games@tekred.TEK.COM Newsgroups: comp.sources.games Subject: v04i013: nobs2 - updated version of nobs cribbage game Keywords: cribbage game Message-ID: <2541@tekred.TEK.COM> Date: 20 May 88 22:28:21 GMT Sender: billr@tekred.TEK.COM Lines: 1683 Approved: billr@saab.CNA.TEK.COM Submitted by: ihnp4!odyssey!gls (g.l.sicherman) Comp.sources.games: Volume 4, Issue 13 Archive-name: nobs2 [This is an update of a previously posted nobs game (v04i002). -br] #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh README <<'END_OF_README' X This is C version 1.1 of the Colonel's Cribbage XProgram. (It originally ran in FORTRAN IV on a CDC, Xback in the 70's.) Cribbage is a card game invented Xby Sir John Suckling (1609-1642), and if you don't know Xthe rules, this program will either delight you or Xgive you a headache, depending on your temperament. X X Changes from version 1.0: X X1. Add -h option. X2. Refine discard algorithm to agree with the original. X3. Fix and tweak screen interface bugs. X4. Fix bug in scoring pairs of aces. X5. Add O.S. and related configuration options to Makefile. X X All configurables are in the Makefile. Besides the XOS dependencies, there are two installation options: X X1. Suppress the -h (hint) command-line option. X2. Use 'g' instead of carriage-return when discarding. X XIf you run under Xenix, you will probably need option 2. XThis release works under Ultrix; the previous release did Xnot. X X As before, feed back to ihnp4!odyssey!gls. Bug reports Xare welcome. Suggestions for enhancements may be welcome, Xbut bells and whistles would be out of place. X XRed Hill Road XApril 9, 1988 END_OF_README if test 1088 -ne `wc -c MANIFEST <<'END_OF_MANIFEST' X File Name Archive # Description X----------------------------------------------------------- X MANIFEST 1 This shipping list X Makefile 1 X README 1 X deal.c 1 X defs.h 1 X gamescore.c 1 X globs.c 1 X globs.h 1 X human.c 1 X logaux.c 1 X logglobs.c 1 X logglobs.h 1 X nobs.6 1 X nobs.c 1 X pegs.c 1 X play.c 1 X playscore.c 1 X progaux.c 1 X program.c 1 X show.c 1 X shuf.c 1 X version.c 1 X wglobs.c 1 X window.c 1 X window.h 1 END_OF_MANIFEST if test 864 -ne `wc -c Makefile <<'END_OF_Makefile' X# Makefile for nobs. X# G. L. Sicherman (ihnp4!odyssey!gls). March 1988. April 1988. X# BSD fixes by saab!billr. X# Xenix fixes by 1solaria!gordon. X#------- X# CONFIGURABLE PARAMETERS: X X# Define destinations for executable and manpage: XBINDEST=$$HOME/bin/nobs XMANDEST=$$HOME/man/nobs.6 X X# Define BSD for Berkeley, Sun, Xenix, etc. X# BSDFLAG= -DBSD XBSDFLAG= X X# Define FLOAT for systems that need a floating-point X# interpreter linked in. (3b5, Unix(TM) PC (?), etc.) X# FLOAT= -f XFLOAT= X X# If BSD or Xenix, you need -ltermcap. X# If Xenix, you need -lx. X# LIB= -lcurses -ltermcap -lx XLIB= -lcurses X X# If Xenix, you need -Mm and -F 2000. X# XFLGS= -Mm -F 2000 XXFLGS= X X# Define NOHINT to disable the -h option. X# NOHINTFLAG= -DNOHINT XNOHINTFLAG= X X# Define GDISC to discard with 'g' instead of CR. X# GDISCFLAG= -DGDISC XGDISCFLAG= X X# End of configurable parameters. Good luck! X XCFLAGS= -O $(BSDFLAG) $(FLOAT) $(XFLGS) $(GDISCFLAG) $(NOHINTFLAG) X XOBJS = nobs.o logglobs.o window.o gamescore.o deal.o shuf.o play.o human.o \ X pegs.o program.o playscore.o show.o progaux.o logaux.o wglobs.o globs.o \ X version.o X XSHARS = nobs.c logglobs.c window.c gamescore.c deal.c shuf.c play.c human.c \ X pegs.c program.c playscore.c show.c progaux.c logaux.c wglobs.c \ X globs.c version.c defs.h globs.h logglobs.h window.h nobs.6 Makefile README X Xall: nobs Xnobs: $(OBJS) X cc $(CFLAGS) -o nobs $(OBJS) $(LIB) X$(OBJS): defs.h globs.h Xlog.o progaux.o program.o: logglobs.h Xplay.o program.o human.o gamescore.o pegs.o window.o show.o: window.h X Xinstall: nobs nobs.6 X rm -f $(BINDEST) $(MANDEST) X cp nobs $(BINDEST) X echo ".ds nh $(NOHINTFLAG)" > $(MANDEST) X cat nobs.6 >> $(MANDEST) X Xshar: nobs.shar Xnobs.shar: $(SHARS) X shar $(SHARS) > $@ X Xclean: X rm -f nobs *.o nobs.shar END_OF_Makefile if test 1757 -ne `wc -c deal.c <<'END_OF_deal.c' X#include "defs.h" X#include "globs.h" X Xdeal() X{ X int i; X CARD *packp; X shuf(); X packp = pack+39; /* Only the last 13 cards */ X for (i=0; i<6; i++) { X hand[0][i] = *packp++; X hand[1][i] = *packp++; X } X cut = *packp; X} END_OF_deal.c if test 218 -ne `wc -c defs.h <<'END_OF_defs.h' X/* X * defs.h - definitions. X */ X X/* Suit has 3 bits, so we can use the green suit for estimating the cut. X */ X#define RANK(x) ((x)&0017) X#define SUIT(x) (((x)&0160)>>4) X#define SAMERANK(x,y) (!((x^y)&0017)) X#define SAMESUIT(x,y) (!((x^y)&0160)) X#define MAKECARD(r,s) ((r)|((s)<<4)) X Xtypedef char PLAYER; X X#define PROGRAM 0 X#define HUMAN 1 X X#define SCOREUP(a,b) {if (scoreup((a),(b))) {gameover++; return;}} X#define CABBAGE 4 X#define SPADE 3 X#define HEART 2 X#define DIAMOND 1 X#define CLUB 0 X X#define KING 13 X#define QUEEN 12 X#define KNAVE 11 X#define TEN 10 X#define NINE 9 X#define EIGHT 8 X#define SEVEN 7 X#define SIX 6 X#define FIVE 5 X#define FOUR 4 X#define TREY 3 X#define DEUCE 2 X#define ACE 1 X Xtypedef char CARD; X Xvoid shuf(); END_OF_defs.h if test 726 -ne `wc -c gamescore.c <<'END_OF_gamescore.c' X#include "defs.h" X#include "globs.h" X#include "window.h" X Xgamescore() X{ X sleep(2); X handscore(!dealer); X if (!gameover) { X sleep(2); X handscore(dealer); X } X if (!gameover) { X sleep(1); X werase(Pscore); X werase(Hscore); X exposecrib(); X sleep(2); X cribscore(); X } X} X Xhandscore(who) Xint who; X{ X int i; X CARD dummy[5]; X for (i=0; i<4; i++) dummy[i]=hand[who][i]; X dummy[4]=cut; X evalhand(dummy, 0, who); X} X Xcribscore() X{ X int i; X CARD dummy[5]; X for (i=0; i<4; i++) dummy[i]=crib[i]; X dummy[4]=cut; X evalhand(dummy, 1, dealer); X} X Xint Xevalhand(ehand, iscrib, whoscore) XCARD ehand[]; Xint iscrib; Xint whoscore; /* -1 means silent */ X{ X/* X * If iscrib is on, don't allow four-flushes. X */ X int i, j, mask, bit, hmask, sum, hcount; X char *runname; X int runval; X short rep[15]; /* Extra zeroes make it easier */ X WINDOW *Win; X if (whoscore==1) Win=Hscore; X else if (whoscore==0) Win=Pscore; X if (iscrib && whoscore>=0) { X wprintw(Win, "%s Crib:\n", whoscore? "Your": "My"); X wrefresh(Win); X sleep(1); X } X hcount=0; X for (mask=1; mask<32; mask++) { X hmask=mask; X sum=0; X for (bit=0; bit<5; bit++) { X if (1&hmask) X sum+=rankvalue[RANK(ehand[bit])]; X hmask >>= 1; X } X if (sum==15) { X hcount += 2; X if (whoscore>=0) { X wprintw(Win, "Fifteen-%d\n", hcount); X wrefresh(Win); X sleep(1); X } X } X/* X * Need we add any cards? X */ X if (sum >= 15) mask |= mask-1; X } X/* X * Count the ranks. X */ X for (i=0; i<15; i++) rep[i]=0; X for (i=0; i<5; i++) rep[RANK(ehand[i])]+=1; X/* X * Look for isolated pairs, etc. X */ X for (i=1; i<14; i++) if (rep[i]>1) { X if (!(rep[i-1] && (rep[i-2] || rep[i+1]) || X rep[i+1] && rep[i+2])) { X hcount += pairvalue[rep[i]]; X if (whoscore>=0) { X wprintw(Win, "and a %s is %d\n", X pairname[rep[i]], hcount); X wrefresh(Win); X sleep(1); X } X } X } X/* X * Look for runs, including multiples. X */ X for (i=1; i<12; i++) if (rep[i]) { X if (!rep[i+2]) { X i+=2; X continue; X } X if (!rep[i+1]) { X i+=1; X continue; X } X/* X * We have a run! X */ X if (rep[i+3]) { X if (rep[i+4]) { X runname="Sequence of Five\n"; X runval=5; X } X else { X runname="Sequence of Four\n"; X runval=4; X for (j=i; j1) { X runname="Double Sequence\n of Four"; X runval=10; X break; X } X } X } X else { X for (sum=0, j=i; j=0) { X wprintw(Win, "and a %s is %d\n", runname, hcount); X wrefresh(Win); X sleep(1); X } X break; /* You can't have two runs */ X } X/* X * Check for flushes. X */ X for (i=1; i<4; i++) if (!SAMESUIT(ehand[i],ehand[0])) goto endflush; X if (SAMESUIT(ehand[4], ehand[0])) { X hcount += 5; X if (whoscore>=0) { X wprintw(Win, "and a Flush of Five is %d\n", hcount); X wrefresh(Win); X sleep(1); X } X } X else if (!iscrib) { X hcount += 4; X if (whoscore>=0) { X wprintw(Win, "and a Flush is %d\n", hcount); X wrefresh(Win); X sleep(1); X } X } Xendflush: X for (i=0; i<4; i++) X if (RANK(ehand[i])==KNAVE && SAMESUIT(ehand[i], ehand[4])) { X hcount += 1; X if (whoscore>=0) { X wprintw(Win, "and One for His Nobs is %d\n",hcount); X wrefresh(Win); X sleep(1); X } X break; X } X/* X * Final reckoning, if wanted. X */ X if (whoscore>=0) { X sleep(1); X if (hcount) SCOREUP(whoscore, hcount); X } X return hcount; X} END_OF_gamescore.c if test 3455 -ne `wc -c globs.c <<'END_OF_globs.c' X/* X * globs - global variables. X */ X X#include "defs.h" X Xshort count; XCARD crib[6]; XCARD cut; Xint dealer; Xint (*dscfunc[2])(); Xchar gameover; XCARD go[8]; Xshort gocount; XCARD hand[2][6]; Xchar handover; Xshort hflag = 0; Xshort ncrib; Xshort nleft[2]; XCARD pack[52]; Xint packmade = 0; Xshort peg[2][2]; Xchar played[2][4]; XPLAYER playertype[2]; Xchar quitflag; Xshort score[2]; Xshort whosego; Xchar whoseturn; X Xchar *drunname[3] = {"Sequence","Double Sequence", X "Quadruple Sequence"}; Xshort drunval[3] = {3, 8, 16}; Xchar *pairname[5] = {"0","0","Pair","Pair Royal","Double Pair Royal"}; Xshort pairvalue[5] = {0,0,2,6,12}; Xchar *rankname[14] = {"0", "Ace","Deuce","Trey","Four", X "Five","Six","Seven","Eight","Nine","Ten", X "Knave","Queen","King"}; Xchar *rankrdr[14] = {"0", "A", X "2","3","4","5","6","7","8","9","10","J","Q","K"}; Xshort rankvalue[14] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10}; Xchar *suitname[5] = {"Clubs", "Diamonds", "Hearts", "Spades", "Cabbages"}; Xchar *suitrdr[5] = {"c","d","h","s","x"}; END_OF_globs.c if test 1014 -ne `wc -c globs.h <<'END_OF_globs.h' X/* X * globs.h - global variables. X */ X Xextern short count; Xextern CARD crib[6]; Xextern CARD cut; Xextern int dealer; Xextern char *drunname[]; Xextern short drunval[]; Xextern int (*dscfunc[])(); Xextern char gameover; Xextern CARD go[8]; Xextern short gocount; Xextern CARD hand[2][6]; Xextern char handover; Xextern short hflag; Xextern short ncrib; Xextern short nleft[2]; Xextern CARD pack[52]; Xextern int packmade; Xextern char *pairname[]; Xextern short pairvalue[]; Xextern short peg[2][2]; Xextern char played[2][4]; Xextern PLAYER playertype[2]; Xextern char quitflag; Xextern char *rankname[14]; Xextern char *rankrdr[14]; Xextern short rankvalue[14]; Xextern short score[2]; Xextern char *suitname[5]; Xextern char *suitrdr[5]; Xextern char version[]; Xextern short whosego; Xextern char whoseturn; END_OF_globs.h if test 782 -ne `wc -c human.c <<'END_OF_human.c' X#include "defs.h" X#include "globs.h" X#include "window.h" X X#ifdef BSD X#include X#endif X Xstatic char selected[6]; Xstatic int nselected; X Xhumandiscard(hand, mydeal) XCARD hand[]; Xint mydeal; X{ X int j, j1, j2; X char k; X for (j=0; j<6; j++) mvwaddch(Select, 0, 5*j+2, 'a'+j); X wrefresh(Select); X mvwprintw( X Prompt, 0, 0, mydeal? "It is your crib.\n": "It is my crib.\n"); X#ifdef GDISC X mvwprintw(Prompt, 1, 0, "Select 2 cards. Type \"g\" to discard.\n"); X#else X mvwprintw(Prompt, 1, 0, "Select 2 cards. Type RETURN to discard.\n"); X#endif X if (hflag) { X mvwprintw(Hscore, 0, 0, "Type \"h\" for hint\n"); X wrefresh(Hscore); X } X for (j=0; j<6; j++) selected[j]=0; X nselected = 0; X for (;;) { X mvwaddch(Prompt, 1, 41, '\n'); X wmove(Prompt, 1, 41); X wrefresh(Prompt); X k = wgetch(Prompt); X k = tolower(k); X#ifdef GDISC X if ('g'==k) { X#else X if ('\n'==k || '\r'==k) { X#endif X if (nselected == 2) break; X beep(); X continue; X } X if (hflag && k == 'h') { X hint(hand, mydeal); X continue; X } X if (k > 'f' || k < 'a') { X beep(); X continue; X } X nselected -= selected[k-'a']; X nselected += (selected[k-'a'] ^= 1); X mvwaddch(Humanhand, 2, 5*(k-'a')+3, X selected[k-'a']? '*': ' '); X wrefresh(Humanhand); X } X if (hflag) { X werase(Hscore); X wrefresh(Hscore); X } X werase(Select); X werase(Prompt); X wrefresh(Select); X wrefresh(Prompt); X for (j=0; j<6; j++) if (selected[j]) { X j1 = j2; /* and you know Lint won't like this! */ X j2 = j; X } X makediscard(hand, j1, j2); X} X Xhint(ihand, mydeal) X{ X int a, b, k; X bestdis(ihand, mydeal, &a, &b); X for (k=0; k<6; k++) { X selected[k] = k==a || k==b; X mvwaddch(Humanhand, 2, 5*k+3, selected[k]? '*': ' '); X } X nselected = 2; X werase(Hscore); X wrefresh(Humanhand); X wrefresh(Hscore); X} X Xhumanplay() X{ X char k; X int sco; X if (whosego == whoseturn) { X/* X * It is my go. Can I play? X */ X if (goodgo(whoseturn)) { X SCOREUP(whoseturn, 1); X resetgo(); X handover = !nleft[0] && !nleft[1]; X return; X } X else mvwprintw(Prompt, 1, 0, "Select a card.\n"); X } X else if (!nleft[whoseturn]) { X handover = !nleft[0] && !nleft[1]; X if (handover) SCOREUP(whoseturn, 1); X return; X } X else if (whosego == !whoseturn) return; X else mvwprintw(Prompt, 1, 0, "Select a card, or type \"g\" for go."); X for (;;) { X mvwaddch(Prompt, 1, 41, '\n'); X wrefresh(Prompt); X k = wgetch(Prompt); X k = tolower(k); X if (k == 'g') { X if (goodgo(whoseturn)) { X whosego = !whoseturn; X return; X } X else beep(); X } X else if (k < 'a' || k > 'd') beep(); X else if (goodplay(whoseturn, k-'a')) break; X else beep(); X } X werase(Prompt); X played[whoseturn][k-'a'] = 1; X count += rankvalue[RANK(hand[whoseturn][k-'a'])]; X go[gocount++] = hand[whoseturn][k-'a']; X nleft[whoseturn] -= 1; X sco = playscore(); X showhplay(k-'a', sco); X if (sco) SCOREUP(whoseturn, sco); X handover = !nleft[0] && !nleft[1]; X if (count==31) resetgo(); X else if (handover) { X mvwprintw(Prompt, 0, 0, "That's a Go\n"); X SCOREUP(whoseturn, 1); X } X sleep(1); X} X X/* X * This is pre-defined in Vr2 curses, but I'll just define it anyway. X */ Xbeep() X{ X putchar('\007'); X} END_OF_human.c if test 3095 -ne `wc -c logaux.c <<'END_OF_logaux.c' X#include "defs.h" X Xint Xcindex(a, b) XCARD a, b; X{ X register t, u; X t = RANK(a); X u = RANK(b); X if (t < u) { X t = RANK(b); X u = RANK(a); X } X return u - 1 + (t * (t-1))/2; X} END_OF_logaux.c if test 173 -ne `wc -c logglobs.c <<'END_OF_logglobs.c' Xfloat distable[2][91] = { X6.290,5.028,6.490,5.092,7.256,6.744,5.776,5.297,5.917,6.699,6.083,6.181, X6.734,7.222,9.463,4.993,5.068,4.909,5.277,7.528,7.152,5.177,5.145,5.070, X4.969,7.061,6.503,7.451,4.954,4.970,4.963,4.922,6.283,5.951,8.103,6.808, X4.725,4.810,4.826,4.745,6.170,6.434,5.402,5.959,6.536,4.504,4.610,4.586, X4.485,7.476,4.332,4.465,5.043,5.568,6.114,4.786,4.893,4.869,4.767,7.758, X4.615,4.826,4.678,5.140,5.478,6.666,4.360,4.467,4.443,4.341,7.332,4.189, X4.400,4.310,4.089,4.564,5.359,5.824,4.211,4.318,4.294,4.192,7.184,4.040, X4.251,4.162,4.019,3.763,4.650,4.290,5.526,5.580,4.339,5.966,4.585,7.183, X6.102,5.596,4.545,4.892,5.808,5.562,5.583,6.039,6.501,8.909,3.868,3.876, X3.839,3.818,6.538,5.846,3.784,3.856,3.678,3.797,5.986,4.795,5.945,3.730, X3.644,3.879,3.830,5.490,4.448,6.535,5.380,3.453,3.780,3.828,3.780,5.477, X5.234,3.940,4.531,5.259,3.462,3.602,3.650,3.601,6.725,3.089,3.069,3.742, X4.130,4.878,3.746,3.886,3.934,3.885,7.009,3.372,3.406,3.348,3.933,4.530, X5.435,3.534,3.673,3.722,3.672,6.797,3.160,3.194,3.194,3.086,3.336,4.858, X5.005,3.531,3.671,3.719,3.670,6.794,3.158,3.192,3.191,3.126,2.889,4.031, X3.469,5.003 X}; END_OF_logglobs.c if test 1136 -ne `wc -c logglobs.h <<'END_OF_logglobs.h' Xextern float distable[2][91]; END_OF_logglobs.h if test 30 -ne `wc -c nobs.6 <<'END_OF_nobs.6' X.de QU X.ie t ``\\$1''\\$2 X.el "\\$1"\\$2 X.. X.TH NOBS 6 "23 March 1988" "" "Local UNIX Programmer's Manual" X.SH NAME Xnobs \- cribbage game X.SH SYNOPSIS X.B nobs X[ X.if '\*(nh'' \{\ X.B \-h X] [\} X.B \-v X] X.SH DESCRIPTION XWith no arguments, X.I nobs Xplays screen-oriented games of cribbage with you. XYou select cards by typing a letter from X.QU a Xto X.QU f . XThe program keeps score. XGame is 121 points. X.PP X.if '\*(nh'' \{\ XIf you specify X.BR \-h , X.I nobs Xwill offer you hints on discarding.\} XIf you specify X.BR \-v , X.I nobs Xprints the version number and exits. X.SH WARNING XThis program has been around a long time, having started out Xin FORTRAN on a CDC 6400. XIt is a dangerous opponent. X.SH AUTHOR XG. L. Sicherman (ihnp4\^!\^odyssey\^!\^gls) END_OF_nobs.6 if test 742 -ne `wc -c nobs.c <<'END_OF_nobs.c' X/* X * nobs - play cribbage. X */ X X#include X#include "defs.h" X#include "globs.h" X Xextern int programdiscard(); Xextern int humandiscard(); X Xusage() X{ X#ifdef NOHINT X fprintf(stderr,"usage: nobs [-v]\n"); X#else X fprintf(stderr,"usage: nobs [-h] [-v]\n"); X#endif X exit(-1); X} X Xmain(argc,argv) Xint argc; Xchar **argv; X{ X while (--argc) { X if ('-'==**++argv) switch(*++*argv) { X case 'v': X printf("Nobs Version %s\n", version); X exit(0); X#ifndef NOHINT X case 'h': X hflag = 1; X break; X#endif X default: X usage(); X } X else break; X } X if (argc) usage(); X initrand(); X initwins(); X dealer = randint(2); X playertype[0] = PROGRAM; X playertype[1] = HUMAN; X dscfunc[PROGRAM] = programdiscard; X dscfunc[HUMAN] = humandiscard; X for (quitflag=0; !quitflag; ) playgame(); X termwins(); X exit(0); X} END_OF_nobs.c if test 801 -ne `wc -c pegs.c <<'END_OF_pegs.c' X#include "defs.h" X#include "globs.h" X#include "window.h" X Xint Xpegcol(n) Xint n; X{ X if (n==0) return 0; X else if (n<31) return n+(n+4)/5; X else return 74-n-(n+4)/5; X} X Xresetpegs() X{ X int i, j; X for (i=0; i<2; i++) for (j=0; j<2; j++) { X if (peg[i][j] != 0) { X mvwaddch(Board, 2*i, pegcol(peg[i][j]), ':'); X peg[i][j] = 0; X } X } X for (i=0; i<2; i++) mvwaddch(Board, 2*i, 0, '|'); X wrefresh(Board); X} X Xsetpegs(who) XPLAYER who; X{ X/* X * The first peg in the array is the forward peg. X */ X X/* Pick up the hindward peg. */ X if (peg[who][0] == 0) mvwaddch(Board, 2*who, 0, who? '!': ';'); X else if (peg[who][1] + peg[who][0] == 61) X mvwaddch(Board, 2*who, pegcol(peg[who][1]), X (peg[who][1]>30)==who? ';': '!'); X else mvwaddch(Board, 2*who, pegcol(peg[who][1]), ':'); X/* X * Put it down again. X */ X peg[who][1] = peg[who][0]; X if (score[who] > 120) peg[who][0] = 0; X else peg[who][0] = 1+(score[who]-1)%60; X if (peg[who][0]==0) mvwaddch(Board, 2*who, 0, who? '!': ';'); X else if (peg[who][0] + peg[who][1] == 61) X mvwaddch(Board, 2*who, pegcol(peg[who][0]), '|'); X else mvwaddch(Board, 2*who, pegcol(peg[who][0]), X (peg[who][0]>30)==who? '!': ';'); X wrefresh(Board); X sleep(1); X} END_OF_pegs.c if test 1181 -ne `wc -c play.c <<'END_OF_play.c' X#include "defs.h" X#include "globs.h" X#include "window.h" X Xstatic taketurn(); X Xplaygame() X{ X char k; X score[0]=score[1]=0; X resetpegs(); X for (gameover=0; !gameover; ) playhand(); X mvwprintw(Prompt, 0, 0, score[0]>120? "I win.\n": "You win.\n"); X wrefresh(Prompt); X sleep(2); X mvwprintw(Prompt, 1, 0, "Another game?\n"); X wmove(Prompt, 1, 41); X wrefresh(Prompt); X k = wgetch(Prompt); X if (k != 'y' && k != 'Y') quitflag = 1; X} X Xplayhand() X{ X int i, j; X dealer = !dealer; X deal(); X werase(Pscore); X werase(Hscore); X showhand(); X ncrib=0; X for (i=0; i<2; i++) { X (*dscfunc[playertype[i]])(hand[i], i==dealer); X } X showfour(); X showcut(); X if (RANK(cut)==KNAVE) { X mvwprintw(Prompt, 1, 0, "Two for His Heels\n"); X wrefresh(Prompt); X sleep(2); X SCOREUP(dealer, 2); X sleep(1); X } X whoseturn = dealer; /* to be reversed */ X handover = 0; X nleft[0]=nleft[1]=4; X resetgo(); X for (i=0; i<2; i++) for (j=0; j<4; j++) played[i][j]=0; X while (!gameover && !handover) taketurn(); X if (gameover) return; X gamescore(); X} X Xstatic Xtaketurn() X{ X whoseturn = !whoseturn; X switch (playertype[whoseturn]) { X case HUMAN: X humanplay(); X break; X case PROGRAM: X programplay(); X break; X } X} X Xint Xgoodgo(who) Xint who; X{ X int i; X for (i=0; i<4; i++) if (goodplay(who, i)) return 0; X return 1; X} X Xint Xgoodplay(who, which) Xint who, which; X{ X return !played[who][which] && X rankvalue[RANK(hand[who][which])] + count <= 31; X} X Xresetgo() { X count=gocount=0; X whosego = -1; X mvwprintw(Prompt, 0, 0, "0.\n"); X wrefresh(Prompt); X} X X/* X * Returns nonzero if wins. X */ Xscoreup(who, n) Xint who, n; X{ X score[who] += n; X setpegs(who); X return (score[who] > 120); X} X X/* X * assumes aplayscore.c <<'END_OF_playscore.c' X#include "defs.h" X#include "globs.h" X Xint Xplayscore() X{ X int hold, low; X hold = 0; X if (count == 15 || count == 31) hold=2; X if (gocount > 1 && RANK(go[gocount-2])==RANK(go[gocount-1])) { X hold += 2; X if (gocount > 2 && RANK(go[gocount-3])==RANK(go[gocount-2])) { X hold += 4; X if (gocount > 3 && RANK(go[gocount-4])== X RANK(go[gocount-3])) hold += 6; X } X return hold; /* No need to check for runs */ X } X if (gocount < 3) return hold; X for (low=0; lowhighest) highest=RANK(go[i]); X if (RANK(go[i])progaux.c <<'END_OF_progaux.c' X/* X * nobs - auxiliary program strategy functions. X * G. L. Sicherman. X */ X X#include "defs.h" X#include "globs.h" X#include "logglobs.h" X Xfloat evaldiscard(); X Xbestdis(hand, mydeal, aw, bw) XCARD hand[]; Xint mydeal; Xint *aw, *bw; X{ X float best, new; X int a, b; X best = -999.0; X for (a=0; a<5; a++) for (b=a+1; b<6; b++) { X new = evaldiscard(hand, mydeal, a, b); X if (new>best) { X best=new; X *aw=a; X *bw=b; X } X } X} X Xfloat Xevaldiscard(hand, mydeal, j1, j2) XCARD hand[6]; Xint mydeal, j1, j2; X{ X float retval, disval; X CARD holdhand[5], *hp; X int k, m, v; X int cutrank; X/* X * Evaluate the remaining hand. X */ X retval = 0.0; X hp=holdhand; X for (k=0; k<6; k++) if (k!=j1 && k!=j2) *hp++ = hand[k]; X for (cutrank=ACE; cutrank<=KING; cutrank++) { X holdhand[4] = MAKECARD(cutrank, CABBAGE); X v = evalhand(holdhand, 1, -1); X retval += 4 * v; X for (m=0; m<6; m++) X if (SAMERANK(hand[m], holdhand[4])) retval -= v; X } X retval /= 46; X disval = distable[mydeal][cindex(hand[j1],hand[j2])]; X if (!mydeal) disval= -disval; X retval += disval; X return retval; X} X X/* X * This isn't supposed to be a world-class strategy. X */ Xint Xevalplay(c) XCARD c; X{ X int v; X v = rankvalue[RANK(c)]; X/* X * Are we setting human up for a 15? X */ X if (count+v == 5) return -11; X/* X * Are we setting human up for a 31? X */ X if (count+v == 21) return -9; X if (count+v == 15 || count+v == 31) return 20; X if (gocount && RANK(go[gocount-1])==RANK(c)) { X if (gocount>1 && RANK(go[gocount-2])==RANK(c)) return 30; X if (gocount>3 || randint(5)) return 15; X } X if (gocount > 1 && X isrun(RANK(go[gocount-1]),RANK(go[gocount-2]), RANK(c))) return 25; X/* X * Are we setting human up for a run? X */ X if (gocount && 2==abs(RANK(c)-RANK(go[gocount-1]))) return -10; X if (count+v <= 4) return 10+count+v; X if (count>20) return v; X return 0; X} X Xint Xisrun(a,b,c) Xint a,b,c; X{ X return 4==abs(a-b)+abs(a-c)+abs(b-c); X} END_OF_progaux.c if test 1873 -ne `wc -c program.c <<'END_OF_program.c' X/* X * The program's strategy. X */ X X#include "defs.h" X#include "globs.h" X#include "logglobs.h" X#include "window.h" X Xfloat evaldiscard(); X Xprogramdiscard(ehand, mydeal) XCARD ehand[]; Xint mydeal; X{ X int aw, bw; X bestdis(ehand, mydeal, &aw, &bw); X makediscard(ehand, aw, bw); X mvwaddch(Programhand, 0, 5*4, '\n'); X mvwprintw(Crib, 0, 0, "XXX XXX\n"); X wrefresh(Programhand); X wrefresh(Crib); X} X Xprogramplay() X{ X int t, u, v; X int bestplay, bestval; X/* X * Case I: It's the human's go. Sit tight. X */ X if (whosego == !whoseturn) return; X/* X * Case II: It's my go, and I can't play. Just score the X * go and reset. X */ X if (whosego==whoseturn && goodgo(whoseturn)) { X/* X * If I have cards and human does not, explain to human. X */ X if (nleft[whoseturn] && !nleft[!whoseturn]) { X mvwprintw(Prompt, 1, 0, "That's a Go\n"); X wrefresh(Prompt); X sleep(1); X } X SCOREUP(whoseturn, 1); X handover = !nleft[0] && !nleft[1]; X if (!handover) resetgo(); X return; X } X/* X * Case III: It's nobody's go yet, and I can't play. X * Human still has cards, or we shouldn't be here. X * Say "go". X */ X if (goodgo(whoseturn)) { X whosego = !whoseturn; X/* X * If I have no cards, there's no need to say "go." X */ X if (nleft[whoseturn]) { X mvwprintw(Prompt, 0, 11, "Go.\n"); X wrefresh(Prompt); X sleep(1); X } X return; X } X/* X * I can play. Pick an appropriate play. X */ X bestval = -999; X for (t=0; t<4; t++) if (goodplay(whoseturn, t)) { X if ((v=evalplay(hand[whoseturn][t])) > bestval) { X bestval=v; X bestplay=t; X } X } X makeprogplay(bestplay); X} X Xmakeprogplay(t) Xint t; X{ X int sco; X nleft[whoseturn] -= 1; X played[whoseturn][t]=1; X count += rankvalue[RANK(hand[whoseturn][t])]; X go[gocount++] = hand[whoseturn][t]; X sco = playscore(); X showpplay(whoseturn, t, sco); X if (sco) SCOREUP(whoseturn, sco); X/* X * Say Go to myself? X */ X if (!nleft[whoseturn]) { /* That was my last card. */ X handover = !nleft[!whoseturn]; X if (handover && count != 31) SCOREUP(whoseturn, 1); X if (!handover && (whosego==whoseturn || count==31)) resetgo(); X return; X } X if (!nleft[!whoseturn]) whosego=whoseturn; /* Human out of cards */ X if (whosego != whoseturn) { X if (count==31) resetgo(); X return; /* Give human a chance */ X } X} END_OF_program.c if test 2213 -ne `wc -c show.c <<'END_OF_show.c' X#include "defs.h" X#include "globs.h" X#include "window.h" X Xchar * Xcardname(c) XCARD c; X{ X static char hold[4]; X sprintf(hold, "%2s%s", rankrdr[RANK(c)], suitrdr[SUIT(c)]); X return hold; X} X Xshowhand() X/* X * If a player is human, it's always player 1. X */ X{ X int i; X for (i=0; i<6; i++) mvwprintw(Programhand, 0, 5*i, "XXX"); X for (i=0; i<6; i++) mvwprintw(Humanhand, 2, 5*i, cardname(hand[1][i])); X mvwprintw(Programhand, 2, 0, "\n"); X mvwprintw(Humanhand, 0, 0, "\n"); X werase(Cut); X werase(Crib); X werase(Pscore); X werase(Hscore); X werase(Select); X wrefresh(Cut); X wrefresh(Crib); X wrefresh(Pscore); X wrefresh(Hscore); X wrefresh(Select); X wrefresh(Programhand); X wrefresh(Humanhand); X} X Xshowfour() X{ X int i; X werase(Humanhand); X for (i=0; i<4; i++) mvwprintw(Humanhand, 2, 5*i, cardname(hand[1][i])); X waddch(Humanhand,'\n'); X for (i=2; i<4; i++) mvwprintw(Crib, 0, 5*i, "XXX "); X for (i=0; i<4; i++) mvwaddch(Select, 0, 5*i+2, 'a'+i); X X wrefresh(Humanhand); X wrefresh(Crib); X wrefresh(Select); X} X Xshowpplay(who, i, scored) Xint who, i, scored; X{ X mvwprintw(Programhand, 0, 5*i, " "); X mvwprintw(Programhand, 2, 5*(3-nleft[who]), cardname(hand[who][i])); X if (scored) mvwprintw(Prompt, 0, 0, "%d for %d.\n", count, scored); X else mvwprintw(Prompt, 0, 0, "%d.\n", count); X wrefresh(Programhand); X wrefresh(Prompt); X sleep(2); X} X Xshowhplay(i, scored) Xint i, scored; X{ X mvwprintw(Humanhand, 2, 5*i, " "); X mvwprintw(Humanhand, 0, 5*(3-nleft[1]), cardname(hand[1][i])); X if (scored) mvwprintw(Prompt, 0, 0, "%d for %d.\n", count, scored); X else mvwprintw(Prompt, 0, 0, "%d.\n", count); X wrefresh(Humanhand); X wrefresh(Prompt); X} X Xshowcut() X{ X mvwprintw(Prompt, 0, 0, playertype[dealer]==HUMAN? "I cut:\n": X "You cut:\n"); X mvwaddch(Prompt, 1, 0, '\n'); X wrefresh(Prompt); X sleep(1); X mvwprintw(Prompt, 1, 0, "the %s of %s\n", X rankname[RANK(cut)], suitname[SUIT(cut)]); X mvwprintw(Cut, 0, 0, cardname(cut)); X wrefresh(Prompt); X wrefresh(Cut); X sleep(1); X} X Xexposecrib() X{ X int i; X for (i=0; i<6; i++) mvwprintw(Crib, 0, 5*i, cardname(crib[i])); X wrefresh(Crib); X sleep(1); X} END_OF_show.c if test 2076 -ne `wc -c shuf.c <<'END_OF_shuf.c' X/* X * shuf - shuffle the pack. X */ X X#include "defs.h" X#include "globs.h" X X#ifdef BSD Xint srand(); Xint rand(); X#else Xvoid srand48(); Xdouble drand48(); X#endif X Xstatic makepack(); X Xvoid Xshuf() X{ X int j, k; X CARD dummy; X if (!packmade) makepack(); X for (j=51; j>=39; j--) { X k = randint(j+1); X dummy = pack[k]; X pack[k] = pack[j]; X pack[j] = dummy; X } X} X Xstatic Xmakepack() X{ X int suit, rank; X CARD *packp; X packp = pack; X for (suit=CLUB; suit<=SPADE; suit++) X for (rank=ACE; rank<=KING; rank++) X *packp++ = MAKECARD(rank,suit); X} X Xinitrand() X{ X long time(); X#ifdef BSD X srand(time((long *)0)); X rand(); X#else X srand48(time((long *)0)); X drand48(); X#endif X} X X/* X * Returns a random integer from 0 to n-1. X */ Xint Xrandint(n) Xint n; X{ X#ifdef BSD X return (rand()/3) % n; X#else X return (int)(drand48()*n); X#endif X} END_OF_shuf.c if test 811 -ne `wc -c version.c <<'END_OF_version.c' Xchar version[] = "1.1"; END_OF_version.c if test 24 -ne `wc -c wglobs.c <<'END_OF_wglobs.c' X#include X XWINDOW *Crib; XWINDOW *Select; XWINDOW *Board; XWINDOW *Cut; XWINDOW *Hscore; XWINDOW *Humanhand; XWINDOW *Programhand; XWINDOW *Prompt; XWINDOW *Pscore; END_OF_wglobs.c if test 167 -ne `wc -c window.c <<'END_OF_window.c' X#include "defs.h" X#include "globs.h" X#include "window.h" X Xinitwins() X{ X initscr(); X Humanhand = subwin(stdscr, 3, 29, 16, 30); X Programhand = subwin(stdscr, 3, 28, 5, 30); X Prompt = subwin(stdscr, 2, 72, 22, 5); X Select = subwin(stdscr, 1, 28, 19, 30); X Crib = subwin(stdscr, 1, 20, 12, 1); X Cut = subwin(stdscr, 1, 3, 12, 66); X Hscore = subwin(stdscr, 5, 27, 15, 0); X Pscore = subwin(stdscr, 5, 27, 2, 0); X scrollok(Hscore, TRUE); X scrollok(Pscore, TRUE); X Board = subwin(stdscr, 3, 37, 11, 28); X initboard(); X} X Xinitboard() X{ X int i; X for (i=0; i<37; i++) if (1 != (i%6)) { X mvwaddch(Board, 0, i, ':'); X mvwaddch(Board, 2, i, ':'); X } X} X Xtermwins() X{ X clear(); X refresh(); X endwin(); X} END_OF_window.c if test 690 -ne `wc -c window.h <<'END_OF_window.h' X#include Xextern WINDOW *Crib; Xextern WINDOW *Board; Xextern WINDOW *Select; Xextern WINDOW *Cut; Xextern WINDOW *Hscore; Xextern WINDOW *Humanhand; Xextern WINDOW *Programhand; Xextern WINDOW *Prompt; Xextern WINDOW *Pscore; END_OF_window.h if test 229 -ne `wc -c