diff options
author | cgd <cgd@NetBSD.org> | 1993-03-21 09:45:37 +0000 |
---|---|---|
committer | cgd <cgd@NetBSD.org> | 1993-03-21 09:45:37 +0000 |
commit | 77e3814f0c0e3dea4d0032e25666f77e6f83bfff (patch) | |
tree | 7eddfcbf3dd12089e71dc3fafb0a106c5c5766c7 /cribbage | |
parent | e81d63576b2e46ab90da7d75fa155ea57ee4d32e (diff) | |
download | bsdgames-darwin-77e3814f0c0e3dea4d0032e25666f77e6f83bfff.tar.gz bsdgames-darwin-77e3814f0c0e3dea4d0032e25666f77e6f83bfff.tar.zst bsdgames-darwin-77e3814f0c0e3dea4d0032e25666f77e6f83bfff.zip |
initial import of 386bsd-0.1 sources
Diffstat (limited to 'cribbage')
-rw-r--r-- | cribbage/Makefile | 14 | ||||
-rw-r--r-- | cribbage/cards.c | 161 | ||||
-rw-r--r-- | cribbage/crib.c | 610 | ||||
-rw-r--r-- | cribbage/cribbage.6 | 129 | ||||
-rw-r--r-- | cribbage/cribbage.h | 61 | ||||
-rw-r--r-- | cribbage/cribbage.n | 226 | ||||
-rw-r--r-- | cribbage/cribcur.h | 57 | ||||
-rw-r--r-- | cribbage/deck.h | 85 | ||||
-rw-r--r-- | cribbage/extern.c | 67 | ||||
-rw-r--r-- | cribbage/instr.c | 81 | ||||
-rw-r--r-- | cribbage/io.c | 615 | ||||
-rw-r--r-- | cribbage/pathnames.h | 38 | ||||
-rw-r--r-- | cribbage/score.c | 364 | ||||
-rw-r--r-- | cribbage/support.c | 357 |
14 files changed, 2865 insertions, 0 deletions
diff --git a/cribbage/Makefile b/cribbage/Makefile new file mode 100644 index 00000000..81e39ae3 --- /dev/null +++ b/cribbage/Makefile @@ -0,0 +1,14 @@ +# @(#)Makefile 5.11 (Berkeley) 5/11/90 + +PROG= cribbage +DPADD= ${LIBCURSES} ${LIBTERM} ${LIBCOMPAT} +LDADD= -lcurses -ltermlib -lcompat +SRCS= extern.c crib.c cards.c instr.c io.c score.c support.c +MAN6= cribbage.0 +HIDEGAME=hidegame + +beforeinstall: + install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/cribbage.n \ + ${DESTDIR}/usr/share/games/cribbage.instr + +.include <bsd.prog.mk> diff --git a/cribbage/cards.c b/cribbage/cards.c new file mode 100644 index 00000000..c7314128 --- /dev/null +++ b/cribbage/cards.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cards.c 5.5 (Berkeley) 2/28/91"; +#endif /* not lint */ + +#include <stdio.h> +#include "deck.h" + + +/* + * initialize a deck of cards to contain one of each type + */ + +makedeck( d ) + + CARD d[]; +{ + register int i, j, k; + long time(); + + i = time( (long *) 0 ); + i = ( (i&0xff) << 8 ) | ( (i >> 8)&0xff ) | 1; + srand( i ); + k = 0; + for( i = 0; i < RANKS; i++ ) { + for( j = 0; j < SUITS; j++ ) { + d[k].suit = j; + d[k++].rank = i; + } + } +} + + + +/* + * given a deck of cards, shuffle it -- i.e. randomize it + * see Knuth, vol. 2, page 125 + */ + +shuffle( d ) + + CARD d[]; +{ + register int j, k; + CARD c; + + for( j = CARDS; j > 0; --j ) { + k = ( rand() >> 4 ) % j; /* random 0 <= k < j */ + c = d[j - 1]; /* exchange (j - 1) and k */ + d[j - 1] = d[k]; + d[k] = c; + } +} + + + +/* + * return true if the two cards are equal... + */ + +eq( a, b ) + + CARD a, b; +{ + return( ( a.rank == b.rank ) && ( a.suit == b.suit ) ); +} + + + +/* + * isone returns TRUE if a is in the set of cards b + */ + +isone( a, b, n ) + + CARD a, b[]; + int n; +{ + register int i; + + for( i = 0; i < n; i++ ) { + if( eq( a, b[i] ) ) return( TRUE ); + } + return( FALSE ); +} + + + +/* + * remove the card a from the deck d of n cards + */ + +cremove( a, d, n ) + + CARD a, d[]; + int n; +{ + register int i, j; + + j = 0; + for( i = 0; i < n; i++ ) { + if( !eq( a, d[i] ) ) d[j++] = d[i]; + } + if( j < n ) d[j].suit = d[j].rank = EMPTY; +} + + + +/* + * sorthand: + * Sort a hand of n cards + */ +sorthand(h, n) +register CARD h[]; +int n; +{ + register CARD *cp, *endp; + CARD c; + + for (endp = &h[n]; h < endp - 1; h++) + for (cp = h + 1; cp < endp; cp++) + if ((cp->rank < h->rank) || + (cp->rank == h->rank && cp->suit < h->suit)) { + c = *h; + *h = *cp; + *cp = c; + } +} + diff --git a/cribbage/crib.c b/cribbage/crib.c new file mode 100644 index 00000000..d1d8bc74 --- /dev/null +++ b/cribbage/crib.c @@ -0,0 +1,610 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)crib.c 5.6 (Berkeley) 2/28/91"; +#endif /* not lint */ + +# include <sys/signal.h> +# include <curses.h> +# include "deck.h" +# include "cribbage.h" +# include "cribcur.h" +# include "pathnames.h" + +main(argc, argv) +int argc; +char *argv[]; +{ + extern char *optarg; + extern int optind; + register char *p; + int ch; + BOOLEAN playing; + char *s; /* for reading arguments */ + FILE *f; + FILE *fopen(); + char *getline(), *getlogin(); + void rint(); + + while ((ch = getopt(argc, argv, "eqr")) != EOF) + switch(ch) { + case 'e': + explain = TRUE; + break; + case 'q': + quiet = TRUE; + break; + case 'r': + rflag = TRUE; + break; + case '?': + default: + (void) fprintf(stderr, "usage: cribbage [-eqr]\n"); + exit(1); + } + + initscr(); + signal(SIGINT, rint); + crmode(); + noecho(); + Playwin = subwin(stdscr, PLAY_Y, PLAY_X, 0, 0); + Tablewin = subwin(stdscr, TABLE_Y, TABLE_X, 0, PLAY_X); + Compwin = subwin(stdscr, COMP_Y, COMP_X, 0, TABLE_X + PLAY_X); + Msgwin = subwin(stdscr, MSG_Y, MSG_X, Y_MSG_START, SCORE_X + 1); + leaveok(Playwin, TRUE); + leaveok(Tablewin, TRUE); + leaveok(Compwin, TRUE); + clearok(stdscr, FALSE); + + if (!quiet) { + msg("Do you need instructions for cribbage? "); + if (getuchar() == 'Y') { + endwin(); + clear(); + mvcur(0, COLS - 1, LINES - 1, 0); + fflush(stdout); + instructions(); + crmode(); + noecho(); + clear(); + refresh(); + msg("For the rules of this program, do \"man cribbage\""); + } + } + playing = TRUE; + do { + wclrtobot(Msgwin); + msg(quiet ? "L or S? " : "Long (to 121) or Short (to 61)? "); + if (glimit == SGAME) + glimit = (getuchar() == 'L' ? LGAME : SGAME); + else + glimit = (getuchar() == 'S' ? SGAME : LGAME); + game(); + msg("Another game? "); + playing = (getuchar() == 'Y'); + } while (playing); + + if (f = fopen(_PATH_LOG, "a")) { + (void)fprintf(f, "%s: won %5.5d, lost %5.5d\n", + getlogin(), cgames, pgames); + (void)fclose(f); + } + bye(); + if (!f) { + (void)fprintf(stderr, "\ncribbage: can't open %s.\n", + _PATH_LOG); + exit(1); + } + exit(0); +} + +/* + * makeboard: + * Print out the initial board on the screen + */ +makeboard() +{ + mvaddstr(SCORE_Y + 0, SCORE_X, "+---------------------------------------+"); + mvaddstr(SCORE_Y + 1, SCORE_X, "| Score: 0 YOU |"); + mvaddstr(SCORE_Y + 2, SCORE_X, "| *.....:.....:.....:.....:.....:..... |"); + mvaddstr(SCORE_Y + 3, SCORE_X, "| *.....:.....:.....:.....:.....:..... |"); + mvaddstr(SCORE_Y + 4, SCORE_X, "| |"); + mvaddstr(SCORE_Y + 5, SCORE_X, "| *.....:.....:.....:.....:.....:..... |"); + mvaddstr(SCORE_Y + 6, SCORE_X, "| *.....:.....:.....:.....:.....:..... |"); + mvaddstr(SCORE_Y + 7, SCORE_X, "| Score: 0 ME |"); + mvaddstr(SCORE_Y + 8, SCORE_X, "+---------------------------------------+"); + gamescore(); +} + +/* + * gamescore: + * Print out the current game score + */ +gamescore() +{ + extern int Lastscore[]; + + if (pgames || cgames) { + mvprintw(SCORE_Y + 1, SCORE_X + 28, "Games: %3d", pgames); + mvprintw(SCORE_Y + 7, SCORE_X + 28, "Games: %3d", cgames); + } + Lastscore[0] = -1; + Lastscore[1] = -1; +} + +/* + * game: + * Play one game up to glimit points. Actually, we only ASK the + * player what card to turn. We do a random one, anyway. + */ +game() +{ + register int i, j; + BOOLEAN flag; + BOOLEAN compcrib; + + makeboard(); + refresh(); + makedeck(deck); + shuffle(deck); + if (gamecount == 0) { + flag = TRUE; + do { + if (!rflag) { /* player cuts deck */ + msg(quiet ? "Cut for crib? " : + "Cut to see whose crib it is -- low card wins? "); + getline(); + } + i = (rand() >> 4) % CARDS; /* random cut */ + do { /* comp cuts deck */ + j = (rand() >> 4) % CARDS; + } while (j == i); + addmsg(quiet ? "You cut " : "You cut the "); + msgcard(deck[i], FALSE); + endmsg(); + addmsg(quiet ? "I cut " : "I cut the "); + msgcard(deck[j], FALSE); + endmsg(); + flag = (deck[i].rank == deck[j].rank); + if (flag) { + msg(quiet ? "We tied..." : + "We tied and have to try again..."); + shuffle(deck); + continue; + } + else + compcrib = (deck[i].rank > deck[j].rank); + } while (flag); + } + else { + werase(Tablewin); + wrefresh(Tablewin); + werase(Compwin); + wrefresh(Compwin); + msg("Loser (%s) gets first crib", (iwon ? "you" : "me")); + compcrib = !iwon; + } + + pscore = cscore = 0; + flag = TRUE; + do { + shuffle(deck); + flag = !playhand(compcrib); + compcrib = !compcrib; + } while (flag); + ++gamecount; + if (cscore < pscore) { + if (glimit - cscore > 60) { + msg("YOU DOUBLE SKUNKED ME!"); + pgames += 4; + } + else if (glimit - cscore > 30) { + msg("YOU SKUNKED ME!"); + pgames += 2; + } + else { + msg("YOU WON!"); + ++pgames; + } + iwon = FALSE; + } + else { + if (glimit - pscore > 60) { + msg("I DOUBLE SKUNKED YOU!"); + cgames += 4; + } + else if (glimit - pscore > 30) { + msg("I SKUNKED YOU!"); + cgames += 2; + } + else { + msg("I WON!"); + ++cgames; + } + iwon = TRUE; + } + gamescore(); +} + +/* + * playhand: + * Do up one hand of the game + */ +playhand(mycrib) +BOOLEAN mycrib; +{ + register int deckpos; + extern char Msgbuf[]; + + werase(Compwin); + + knownum = 0; + deckpos = deal(mycrib); + sorthand(chand, FULLHAND); + sorthand(phand, FULLHAND); + makeknown(chand, FULLHAND); + prhand(phand, FULLHAND, Playwin, FALSE); + discard(mycrib); + if (cut(mycrib, deckpos)) + return TRUE; + if (peg(mycrib)) + return TRUE; + werase(Tablewin); + wrefresh(Tablewin); + if (score(mycrib)) + return TRUE; + return FALSE; +} + + + +/* + * deal cards to both players from deck + */ + +deal( mycrib ) +{ + register int i, j; + + j = 0; + for( i = 0; i < FULLHAND; i++ ) { + if( mycrib ) { + phand[i] = deck[j++]; + chand[i] = deck[j++]; + } + else { + chand[i] = deck[j++]; + phand[i] = deck[j++]; + } + } + return( j ); +} + +/* + * discard: + * Handle players discarding into the crib... + * Note: we call cdiscard() after prining first message so player doesn't wait + */ +discard(mycrib) +BOOLEAN mycrib; +{ + register char *prompt; + CARD crd; + + prcrib(mycrib, TRUE); + prompt = (quiet ? "Discard --> " : "Discard a card --> "); + cdiscard(mycrib); /* puts best discard at end */ + crd = phand[infrom(phand, FULLHAND, prompt)]; + cremove(crd, phand, FULLHAND); + prhand(phand, FULLHAND, Playwin, FALSE); + crib[0] = crd; +/* next four lines same as last four except for cdiscard() */ + crd = phand[infrom(phand, FULLHAND - 1, prompt)]; + cremove(crd, phand, FULLHAND - 1); + prhand(phand, FULLHAND, Playwin, FALSE); + crib[1] = crd; + crib[2] = chand[4]; + crib[3] = chand[5]; + chand[4].rank = chand[4].suit = chand[5].rank = chand[5].suit = EMPTY; +} + +/* + * cut: + * Cut the deck and set turnover. Actually, we only ASK the + * player what card to turn. We do a random one, anyway. + */ +cut(mycrib, pos) +BOOLEAN mycrib; +int pos; +{ + register int i, cardx; + BOOLEAN win = FALSE; + + if (mycrib) { + if (!rflag) { /* random cut */ + msg(quiet ? "Cut the deck? " : + "How many cards down do you wish to cut the deck? "); + getline(); + } + i = (rand() >> 4) % (CARDS - pos); + turnover = deck[i + pos]; + addmsg(quiet ? "You cut " : "You cut the "); + msgcard(turnover, FALSE); + endmsg(); + if (turnover.rank == JACK) { + msg("I get two for his heels"); + win = chkscr(&cscore,2 ); + } + } + else { + i = (rand() >> 4) % (CARDS - pos) + pos; + turnover = deck[i]; + addmsg(quiet ? "I cut " : "I cut the "); + msgcard(turnover, FALSE); + endmsg(); + if (turnover.rank == JACK) { + msg("You get two for his heels"); + win = chkscr(&pscore, 2); + } + } + makeknown(&turnover, 1); + prcrib(mycrib, FALSE); + return win; +} + +/* + * prcrib: + * Print out the turnover card with crib indicator + */ +prcrib(mycrib, blank) +BOOLEAN mycrib, blank; +{ + register int y, cardx; + + if (mycrib) + cardx = CRIB_X; + else + cardx = 0; + + mvaddstr(CRIB_Y, cardx + 1, "CRIB"); + prcard(stdscr, CRIB_Y + 1, cardx, turnover, blank); + + if (mycrib) + cardx = 0; + else + cardx = CRIB_X; + + for (y = CRIB_Y; y <= CRIB_Y + 5; y++) + mvaddstr(y, cardx, " "); +} + +/* + * peg: + * Handle all the pegging... + */ + +static CARD Table[14]; + +static int Tcnt; + +peg(mycrib) +BOOLEAN mycrib; +{ + static CARD ch[CINHAND], ph[CINHAND]; + CARD crd; + register int i, j, k; + register int l; + register int cnum, pnum, sum; + register BOOLEAN myturn, mego, ugo, last, played; + + cnum = pnum = CINHAND; + for (i = 0; i < CINHAND; i++) { /* make copies of hands */ + ch[i] = chand[i]; + ph[i] = phand[i]; + } + Tcnt = 0; /* index to table of cards played */ + sum = 0; /* sum of cards played */ + mego = ugo = FALSE; + myturn = !mycrib; + for (;;) { + last = TRUE; /* enable last flag */ + prhand(ph, pnum, Playwin, FALSE); + prhand(ch, cnum, Compwin, TRUE); + prtable(sum); + if (myturn) { /* my tyrn to play */ + if (!anymove(ch, cnum, sum)) { /* if no card to play */ + if (!mego && cnum) { /* go for comp? */ + msg("GO"); + mego = TRUE; + } + if (anymove(ph, pnum, sum)) /* can player move? */ + myturn = !myturn; + else { /* give him his point */ + msg(quiet ? "You get one" : "You get one point"); + if (chkscr(&pscore, 1)) + return TRUE; + sum = 0; + mego = ugo = FALSE; + Tcnt = 0; + } + } + else { + played = TRUE; + j = -1; + k = 0; + for (i = 0; i < cnum; i++) { /* maximize score */ + l = pegscore(ch[i], Table, Tcnt, sum); + if (l > k) { + k = l; + j = i; + } + } + if (j < 0) /* if nothing scores */ + j = cchose(ch, cnum, sum); + crd = ch[j]; + cremove(crd, ch, cnum--); + sum += VAL(crd.rank); + Table[Tcnt++] = crd; + if (k > 0) { + addmsg(quiet ? "I get %d playing " : + "I get %d points playing ", k); + msgcard(crd, FALSE); + endmsg(); + if (chkscr(&cscore, k)) + return TRUE; + } + myturn = !myturn; + } + } + else { + if (!anymove(ph, pnum, sum)) { /* can player move? */ + if (!ugo && pnum) { /* go for player */ + msg("You have a GO"); + ugo = TRUE; + } + if (anymove(ch, cnum, sum)) /* can computer play? */ + myturn = !myturn; + else { + msg(quiet ? "I get one" : "I get one point"); + do_wait(); + if (chkscr(&cscore, 1)) + return TRUE; + sum = 0; + mego = ugo = FALSE; + Tcnt = 0; + } + } + else { /* player plays */ + played = FALSE; + if (pnum == 1) { + crd = ph[0]; + msg("You play your last card"); + } + else + for (;;) { + prhand(ph, pnum, Playwin, FALSE); + crd = ph[infrom(ph, pnum, "Your play: ")]; + if (sum + VAL(crd.rank) <= 31) + break; + else + msg("Total > 31 -- try again"); + } + makeknown(&crd, 1); + cremove(crd, ph, pnum--); + i = pegscore(crd, Table, Tcnt, sum); + sum += VAL(crd.rank); + Table[Tcnt++] = crd; + if (i > 0) { + msg(quiet ? "You got %d" : "You got %d points", i); + if (chkscr(&pscore, i)) + return TRUE; + } + myturn = !myturn; + } + } + if (sum >= 31) { + if (!myturn) + do_wait(); + sum = 0; + mego = ugo = FALSE; + Tcnt = 0; + last = FALSE; /* disable last flag */ + } + if (!pnum && !cnum) + break; /* both done */ + } + prhand(ph, pnum, Playwin, FALSE); + prhand(ch, cnum, Compwin, TRUE); + prtable(sum); + if (last) + if (played) { + msg(quiet ? "I get one for last" : "I get one point for last"); + do_wait(); + if (chkscr(&cscore, 1)) + return TRUE; + } + else { + msg(quiet ? "You get one for last" : + "You get one point for last"); + if (chkscr(&pscore, 1)) + return TRUE; + } + return FALSE; +} + +/* + * prtable: + * Print out the table with the current score + */ +prtable(score) +int score; +{ + prhand(Table, Tcnt, Tablewin, FALSE); + mvwprintw(Tablewin, (Tcnt + 2) * 2, Tcnt + 1, "%2d", score); + wrefresh(Tablewin); +} + +/* + * score: + * Handle the scoring of the hands + */ +score(mycrib) +BOOLEAN mycrib; +{ + sorthand(crib, CINHAND); + if (mycrib) { + if (plyrhand(phand, "hand")) + return TRUE; + if (comphand(chand, "hand")) + return TRUE; + do_wait(); + if (comphand(crib, "crib")) + return TRUE; + } + else { + if (comphand(chand, "hand")) + return TRUE; + if (plyrhand(phand, "hand")) + return TRUE; + if (plyrhand(crib, "crib")) + return TRUE; + } + return FALSE; +} diff --git a/cribbage/cribbage.6 b/cribbage/cribbage.6 new file mode 100644 index 00000000..59c6500d --- /dev/null +++ b/cribbage/cribbage.6 @@ -0,0 +1,129 @@ +.\" Copyright (c) 1980 Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)cribbage.6 6.5 (Berkeley) 6/23/90 +.\" +.TH CRIBBAGE 6 "June 23, 1990" +.UC 4 +.SH NAME +cribbage \- the card game cribbage +.SH SYNOPSIS +.B /usr/games/cribbage +[ +.B \-req +] +.I name ... +.SH DESCRIPTION +.I Cribbage +plays the card game cribbage, with the program playing one hand +and the user the other. The program will initially ask the user if +the rules of the game are needed \- if so, it will print out +the appropriate section from +.I According to Hoyle +with +.I more (I). +.PP +.I Cribbage +options include: +.TP +.B \-e +When the player makes a mistake scoring his hand or crib, provide an +explanation of the correct score. (This is especially useful for +beginning players.) +.TP +.B \-q +Print a shorter form of all messages \- this is only recommended for +users who have played the game without specifying this option. +.TP +.B \-r +Instead of asking the player to cut the deck, the program will randomly +cut the deck. +.PP +.I Cribbage +first asks the player whether he wishes to play a short game +(\*(lqonce around\*(rq, to 61) or a long game (\*(lqtwice around\*(rq, to 121). A +response of `s' will result in a short game, any other response will +play a long game. +.PP +At the start of the first game, the program +asks the player to cut the deck to determine who gets the +first crib. The user should respond with a number between 0 and +51, indicating how many cards down the deck is to be cut. The player +who cuts the lower ranked card gets the first crib. +If more than one game is played, the +loser of the previous game gets the first crib in the current game. +.PP +For each hand, the program first prints the player's hand, +whose crib it is, and then asks the player +to discard two cards into the crib. The cards are prompted for +one per line, and are typed as explained below. +.PP +After discarding, the program cuts the deck (if it is the player's +crib) or asks the player to cut the deck (if it's its crib); in the latter +case, the appropriate response is a number from 0 to 39 indicating +how far down the remaining 40 cards are to be cut. +.PP +After cutting the deck, play starts with the non-dealer (the person +who doesn't have the crib) leading the first card. +Play continues, as per cribbage, until all cards are exhausted. The +program keeps track of the scoring of all points and the total of +the cards on the table. +.PP +After play, the hands are scored. The program requests the player to +score his hand (and the crib, if it is his) by printing out the +appropriate cards (and the cut card enclosed in brackets). +Play continues until one player reaches the game limit (61 or 121). +.PP +A carriage return when a numeric input is expected is equivalent +to typing the lowest legal value; when cutting the deck this +is equivalent to choosing the top card. +.PP +Cards are specified as rank followed by suit. The ranks may be specified +as one of: +`a', `2', `3', `4', `5', `6', `7', `8', `9', `t', `j', `q', and `k', +or alternatively, one of: \*(lqace\*(rq, \*(lqtwo\*(rq, \*(lqthree\*(rq, \*(lqfour\*(rq, \*(lqfive\*(rq, \*(lqsix\*(rq, +\*(lqseven\*(rq, \*(lqeight\*(rq, \*(lqnine\*(rq, \*(lqten\*(rq, \*(lqjack\*(rq, \*(lqqueen\*(rq, and \*(lqking\*(rq. +Suits may be specified as: `s', `h', `d', and `c', or alternatively as: +\*(lqspades\*(rq, \*(lqhearts\*(rq, \*(lqdiamonds\*(rq, and \*(lqclubs\*(rq. +A card may be specified as: <rank> \*(lq \*(rq <suit>, or: <rank> \*(lq of \*(rq <suit>. +If the single letter rank and suit designations are used, the space +separating the suit and rank may be left out. Also, if only one card +of the desired rank is playable, typing the rank is sufficient. +For example, if your hand was \*(lq2H, 4D, 5C, 6H, JC, KD\*(rq and it was +desired to discard the king of diamonds, any of the following could be typed: +\*(lqk\*(rq, \*(lqking\*(rq, \*(lqkd\*(rq, \*(lqk d\*(rq, \*(lqk of d\*(rq, \*(lqking d\*(rq, \*(lqking of d\*(rq, \*(lqk diamonds\*(rq, +\*(lqk of diamonds\*(rq, \*(lqking diamonds\*(rq, or \*(lqking of diamonds\*(rq. +.SH FILES +.ta 2i +/usr/games/cribbage +.SH AUTHORS +Earl T. Cohen wrote the logic. +Ken Arnold added the screen oriented interface. diff --git a/cribbage/cribbage.h b/cribbage/cribbage.h new file mode 100644 index 00000000..952d79b0 --- /dev/null +++ b/cribbage/cribbage.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cribbage.h 5.4 (Berkeley) 6/1/90 + */ + +extern CARD deck[ CARDS ]; /* a deck */ +extern CARD phand[ FULLHAND ]; /* player's hand */ +extern CARD chand[ FULLHAND ]; /* computer's hand */ +extern CARD crib[ CINHAND ]; /* the crib */ +extern CARD turnover; /* the starter */ + +extern CARD known[ CARDS ]; /* cards we have seen */ +extern int knownum; /* # of cards we know */ + +extern int pscore; /* player's score */ +extern int cscore; /* comp's score */ +extern int glimit; /* points to win game */ + +extern int pgames; /* player's games won */ +extern int cgames; /* comp's games won */ +extern int gamecount; /* # games played */ +extern int Lastscore[2]; /* previous score for each */ + +extern BOOLEAN iwon; /* if comp won last */ +extern BOOLEAN explain; /* player mistakes explained */ +extern BOOLEAN rflag; /* if all cuts random */ +extern BOOLEAN quiet; /* if suppress random mess */ +extern BOOLEAN playing; /* currently playing game */ + +extern char expl[]; /* string for explanation */ + diff --git a/cribbage/cribbage.n b/cribbage/cribbage.n new file mode 100644 index 00000000..084e0917 --- /dev/null +++ b/cribbage/cribbage.n @@ -0,0 +1,226 @@ + + CRIBBAGE + from + According to Hoyle + +Cribbage is believed to have been invented by Sir John Suckling (1609-1642). +Probably it is an elaboration of an older game, Noddy. The original game +was played with hands of five cards; the modern game gives each player +six. That is virtually the only change from Suckling's directions. + +Players: + + Two. There are variants for three and four players, described + later. + +Cards: + + The pack of 52. The cards in each suit rank: K (high), Q, J, 10, +9, 8, 7, 6, 5, 4, 3, 2, A. The counting values are: K, Q, J, 10, each 10 +(wherefore these are called tenth cards); ace, 1; each other card, its +index value. + +Cribbage Board: + + Indispensable to scoring (unless you have a computer!, ed.) is +the device known as the cribbage board. This is a rectangular panel, long +and narrow, in which are four rows of 30 holes each. (See illustration.) +At one end, or in the center, are two or four additional holes, called +game holes. The board is placed between the two players, and each keeps +his own score on the two rows of holes nearest himself. Each is supplied +with two pegs. Before the first hand, the pegs are placed in the game +holes. On making his first score, the player advances one peg an +appropriate number of holes (one per point) away from the game end of the +board. The second score is recorded by placing the second peg an +appropriate distance ahead of the first. For each subsequent score, the +rear peg is jumped ahead of the other, the distance between the two pegs +always showing the amount of this last score. + + The traditional mode of scoring is down (away from the game end) +the outer row, and up the inner row. "Once around" is a game of 61 points. +"Twice around" is a game of 121 points. + +Preliminaries: + + Cards are drawn; the lower deals first. If cards of equal rank +are drawn, both players draw again. Dealer has the right to shuffle last. +Nondealer cuts, and must leave at least four cards in each packet. + +Dealing: + + Each player receives six cards, dealt one at a time face down, +beginning with the nondealer. The turn to deal alternates. The dealer +has an advantage. + +Laying Away: + + After seeing his hand, each player lays away two cards face down. +The four cards laid away, placed in one pile, form the crib. The crib +counts for the dealer. Nondealer therefore tries to lay away balking +cards -- cards that are least likely to create a score in the crib. + +The Starter: + + After both hands have laid away, nondealer lifts off a packet from +the top of the stock (the rest of the pack). Again, each packet must +contain at least four cards. Dealer turns up the top card of the lower +packer, which is then placed on top of the stock when the packets are +reunited. The card thus turned up is called 1 the starter. If it is a +jack, dealer immediately pegs 2, called 2 for his heels. + +The Play: + + Nondealer begins the play by laying a card from his hand face up +on the table, announcing its counting value. Dealer then shows a card, +announcing the total count of the two cards. Play continues in the same +way, by alternate exposure of cards, each player announcing the new total +count. The total may be carried only to 31, no further. If a player adds +a card that brings the total exactly to 31, he pegs 2. If a player is +unable to play another card without exceeding 31, he must say "Go," and +his opponent pegs 1, but before doing so, opponent must lay down any +additional cards he can without exceeding 31. If such additional cards +bring the total to exactly 31, he pegs 2 instead of 1. + + Whenever a go occurs, the opponent of the player who played the +last card must lead for a new count starting at zero. Playing the last +card of all counts as a go. (Since nondealer makes the opening lead, +dealer is bound to peg at least 1 in play.) + + Besides pegging for 31 and go, the player may also peg for certain +combinations made in play, as follows: + + Fifteen: + Making the count total 15 pegs 2. + Pair: + Playing a card of same rank as that previously played pegs + 2. Playing a third card of the same rank makes pair royal + and pegs 6. Playing the fourth card of the same rank + makes double pair royal and pegs 12. + + The tenth cards pair strictly by rank, a king with a king, + a queen with a queen, and so on. (King and jack do not + make a pair, although each has the counting value 10.) + Run: + Playing a card which, with the two or more played + immediately previously, makes a sequence of three or more + cards, pegs 1 for each card in the run. Runs depend on + rank alone; the suits do not matter. Nor does the score + for run depend upon playing the cards in strict sequence, + so long as the three or more last cards played can be + arranged in a run. Example: 7, 6, 8 played in that order + score 3 for run; 5, 2, 4, 3 played in that order score 4 + for run. + + Any of the foregoing combinations count, whether the cards + are played alternately or one player plays several times + in succession in consequence of a go. But a combination + does not score if it is interrupted by a go. + + Showing: + After the play, the hands are shown (counted). Nondealer + shows first, then dealer's hand, then crib. The starter + is deemed to belong to each hand, so that each hand includes + five cards. Combinations of scoring value are as follows: + + Fifteen: + Each combinations of two or more cards that total + fifteen scores 2. + Pair: + Each pair of cards of the same rank scores 2. + + Run: + Each combination of three or more cards in sequence + scores 1 for each card in the run. + Flush: + Four cards of the same suit in hand score 4; four + cards in hand or crib of same suit as the starter + score 5. (No count for four-flush in crib.) + His Nobs: + Jack of same suit as the starter, in hand or crib, + scores 1. + + It is important to note that every separate grouping of cards that +makes a fifteen, pair, or run counts separately. Three of a kind, pair +royal, counts 6 because three sets of pairs can be made; similarly, four +of a kind, double pair royal, contain six pairs and count 12. + + The highest possible hand is J, 5, 5, 5 with the starter the 5 of +the same suit as the jack. There are four fifteens by combining the jack +with a five, four more by combinations of three fives (a total of 16 for +fifteens); the double pair royal adds 12 for a total of 28; and his nobs +adds 1 for a maximum score of 29. (the score of 2 for his heels does not +count in the total of the hand, since it is pegged before the play.) + + A double run is a run with one card duplicated, as 4-3-3-2. +Exclusive of fifteens, a double run of three cards counts 8; of four cards, +10. A triple run is a run of three with one card triplicated, as K-K-K-Q-J. +Exclusive of fifteens, it counts 15. A quadruple run is a run of three +with two different cards duplicated, as the example 8-8-7-6-6 previously +given. Exclusive of fifteens, it counts 16. + + No hand can be constructed that counts 19, 25, 26 or 27. A +time-honored way of showing a hand with not a single counting combination +is to say "I have nineteen." + + The customary order in showing is to count fifteens first, then +runs, then pairs, but there is no compulsion of law. Example: A hand +(with starter) of 9-6-5-4-4 will usually be counted "Fifteen 2, fifteen +4, fifteen 6 and double run makes 14," or simply "Fifteen 6 and 8 is 14." + +Muggins: + + The hands and crib are counted aloud, and if a player claims a +greater total than is due him, his opponent may require correction. In +some localities, if a player claims less than is due, his opponent may +say "Muggins" and himself score the points overlooked. + +Scoring: + + The usual game is 121, but it may be set at 61 by agreement. +Since the player wins who first returns to the game hole by going "twice +around," the scores must be pegged strictly in order: his heels, pegging +in play, non-dealer's hand, dealer's hand, crib. Thus, if nondealer goes +out on showing his hand, he wins, even though dealer might have gone out +with a greater total if allowed to count his hand and crib. + + When the game of 121 is played for a stake, a player wins a single +game if the loser makes 61 points or more. If the loser fails to reach +61, he is lurched, and the other wins a double game. + +Irregularities: + + Misdeal. There must be a new deal by the same dealer if a card +is found faced in the pack, if a card is exposed in dealing, or if the +pack be found imperfect. + + Wrong Number of Cards. If one hand (not crib) is found to have +the wrong number of cards after laying away for the crib, the other hand +and crib being correct, the opponent may either demand a new deal or may +peg 2 and rectify the hand. If the crib is incorrect, both hands being +correct, nondealer pegs 2 and the crib is corrected. + +Error in Pegging: + + If a player places a peg short of the amount to which he is +entitled, he may not correct his error after he has played the next card +or after the cut for the next deal. If he pegs more than his announced +score, the error must be corrected on demand at any time before the cut +for the next deal and his opponent pegs 2. + +Strategy: + + The best balking cards are kings and aces, because they have the +least chance of producing sequences. Tenth cards are generally good, +provided that the two cards laid away are not too near (likely to make a +sequence). When nothing better offers, give two wide cards -- at least +three apart in rank. + + Proverbially the safest lead is a 4. The next card cannot make +a 15. Lower cards are also safe from this point of view, but are better +treasured for go and 31. The most dangerous leads are 7 and 8, but may +be made to trap the opponent when they are backed with other close cards. +Generally speaking, play on (toward a sequence) when you have close cards +and off when you do not. However, the state of the score is a +consideration. If far behind, play on when there is any chance of building +a score for yourself; if well ahead, balk your opponent by playing off +unless you will surely peg as much as he by playing on. diff --git a/cribbage/cribcur.h b/cribbage/cribcur.h new file mode 100644 index 00000000..31f9c51d --- /dev/null +++ b/cribbage/cribcur.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cribcur.h 5.4 (Berkeley) 6/1/90 + */ + +# define PLAY_Y 15 /* size of player's hand window */ +# define PLAY_X 12 +# define TABLE_Y 21 /* size of table window */ +# define TABLE_X 14 +# define COMP_Y 15 /* size of computer's hand window */ +# define COMP_X 12 +# define Y_SCORE_SZ 9 /* Y size of score board */ +# define X_SCORE_SZ 41 /* X size of score board */ +# define SCORE_Y 0 /* starting position of scoring board */ +# define SCORE_X (PLAY_X + TABLE_X + COMP_X) +# define CRIB_Y 17 /* position of crib (cut card) */ +# define CRIB_X (PLAY_X + TABLE_X) +# define MSG_Y (LINES - (Y_SCORE_SZ + 1)) +# define MSG_X (COLS - SCORE_X - 1) +# define Y_MSG_START (Y_SCORE_SZ + 1) + +# define PEG '*' /* what a peg looks like on the board */ + +extern WINDOW *Compwin; /* computer's hand window */ +extern WINDOW *Msgwin; /* message window */ +extern WINDOW *Playwin; /* player's hand window */ +extern WINDOW *Tablewin; /* table window */ diff --git a/cribbage/deck.h b/cribbage/deck.h new file mode 100644 index 00000000..2a20e5af --- /dev/null +++ b/cribbage/deck.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)deck.h 5.4 (Berkeley) 6/1/90 + */ + +/* + * define structure of a deck of cards and other related things + */ + + +#define CARDS 52 /* number cards in deck */ +#define RANKS 13 /* number ranks in deck */ +#define SUITS 4 /* number suits in deck */ + +#define CINHAND 4 /* # cards in cribbage hand */ +#define FULLHAND 6 /* # cards in dealt hand */ + +#define LGAME 121 /* number points in a game */ +#define SGAME 61 /* # points in a short game */ + +#define SPADES 0 /* value of each suit */ +#define HEARTS 1 +#define DIAMONDS 2 +#define CLUBS 3 + +#define ACE 0 /* value of each rank */ +#define TWO 1 +#define THREE 2 +#define FOUR 3 +#define FIVE 4 +#define SIX 5 +#define SEVEN 6 +#define EIGHT 7 +#define NINE 8 +#define TEN 9 +#define JACK 10 +#define QUEEN 11 +#define KING 12 +#define EMPTY 13 + +#define VAL(c) ( (c) < 9 ? (c)+1 : 10 ) /* val of rank */ + + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +typedef struct { + int rank; + int suit; + } CARD; + +typedef char BOOLEAN; + diff --git a/cribbage/extern.c b/cribbage/extern.c new file mode 100644 index 00000000..3fa18ce6 --- /dev/null +++ b/cribbage/extern.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)extern.c 5.4 (Berkeley) 6/1/90"; +#endif /* not lint */ + +# include <curses.h> +# include "deck.h" +# include "cribbage.h" + +bool explain = FALSE; /* player mistakes explained */ +bool iwon = FALSE; /* if comp won last game */ +bool quiet = FALSE; /* if suppress random mess */ +bool rflag = FALSE; /* if all cuts random */ + +char expl[128]; /* explanation */ + +int cgames = 0; /* number games comp won */ +int cscore = 0; /* comp score in this game */ +int gamecount = 0; /* number games played */ +int glimit = LGAME; /* game playe to glimit */ +int knownum = 0; /* number of cards we know */ +int pgames = 0; /* number games player won */ +int pscore = 0; /* player score in this game */ + +CARD chand[FULLHAND]; /* computer's hand */ +CARD crib[CINHAND]; /* the crib */ +CARD deck[CARDS]; /* a deck */ +CARD known[CARDS]; /* cards we have seen */ +CARD phand[FULLHAND]; /* player's hand */ +CARD turnover; /* the starter */ + +WINDOW *Compwin; /* computer's hand window */ +WINDOW *Msgwin; /* messages for the player */ +WINDOW *Playwin; /* player's hand window */ +WINDOW *Tablewin; /* table window */ diff --git a/cribbage/instr.c b/cribbage/instr.c new file mode 100644 index 00000000..d5ffdc0e --- /dev/null +++ b/cribbage/instr.c @@ -0,0 +1,81 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)instr.c 5.2 (Berkeley) 2/28/91"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/errno.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "pathnames.h" + +instructions() +{ + extern int errno; + struct stat sb; + union wait pstat; + pid_t pid; + char *pager, *path; + + if (stat(_PATH_INSTR, &sb)) { + (void)fprintf(stderr, "cribbage: %s: %s.\n", _PATH_INSTR, + strerror(errno)); + exit(1); + } + switch(pid = vfork()) { + case -1: + (void)fprintf(stderr, "cribbage: %s.\n", strerror(errno)); + exit(1); + case 0: + if (!(path = getenv("PAGER"))) + path = _PATH_MORE; + if (pager = rindex(path, '/')) + ++pager; + pager = path; + execlp(path, pager, _PATH_INSTR, (char *)NULL); + (void)fprintf(stderr, "cribbage: %s.\n", strerror(errno)); + _exit(1); + default: + do { + pid = waitpid(pid, (int *)&pstat, 0); + } while (pid == -1 && errno == EINTR); + if (pid == -1 || pstat.w_status) + exit(1); + } +} diff --git a/cribbage/io.c b/cribbage/io.c new file mode 100644 index 00000000..ef99246b --- /dev/null +++ b/cribbage/io.c @@ -0,0 +1,615 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)io.c 5.8 (Berkeley) 2/28/91"; +#endif /* not lint */ + +# include <curses.h> +# include <ctype.h> +# include <signal.h> +# include <stdarg.h> +# include "deck.h" +# include "cribbage.h" +# include "cribcur.h" + +# define LINESIZE 128 + +# ifdef CTRL +# undef CTRL +# endif +# define CTRL(X) ('X' - 'A' + 1) + +# ifdef notdef /* defined in curses.h */ +# define erasechar() _tty.sg_erase +# define killchar() _tty.sg_kill +# endif + +char linebuf[ LINESIZE ]; + +char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR", + "FIVE", "SIX", "SEVEN", "EIGHT", + "NINE", "TEN", "JACK", "QUEEN", + "KING" }; + +char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7", + "8", "9", "T", "J", "Q", "K" }; + +char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS", + "CLUBS" }; + +char *suitchar[ SUITS ] = { "S", "H", "D", "C" }; + + + +/* + * msgcard: + * Call msgcrd in one of two forms + */ +msgcard(c, brief) +CARD c; +BOOLEAN brief; +{ + if (brief) + return msgcrd(c, TRUE, (char *) NULL, TRUE); + else + return msgcrd(c, FALSE, " of ", FALSE); +} + + + +/* + * msgcrd: + * Print the value of a card in ascii + */ +msgcrd(c, brfrank, mid, brfsuit) +CARD c; +char *mid; +BOOLEAN brfrank, brfsuit; +{ + if (c.rank == EMPTY || c.suit == EMPTY) + return FALSE; + if (brfrank) + addmsg("%1.1s", rankchar[c.rank]); + else + addmsg(rankname[c.rank]); + if (mid != NULL) + addmsg(mid); + if (brfsuit) + addmsg("%1.1s", suitchar[c.suit]); + else + addmsg(suitname[c.suit]); + return TRUE; +} + +/* + * printcard: + * Print out a card. + */ +printcard(win, cardno, c, blank) +WINDOW *win; +int cardno; +CARD c; +BOOLEAN blank; +{ + prcard(win, cardno * 2, cardno, c, blank); +} + +/* + * prcard: + * Print out a card on the window at the specified location + */ +prcard(win, y, x, c, blank) +WINDOW *win; +int y, x; +CARD c; +BOOLEAN blank; +{ + if (c.rank == EMPTY) + return; + mvwaddstr(win, y + 0, x, "+-----+"); + mvwaddstr(win, y + 1, x, "| |"); + mvwaddstr(win, y + 2, x, "| |"); + mvwaddstr(win, y + 3, x, "| |"); + mvwaddstr(win, y + 4, x, "+-----+"); + if (!blank) { + mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]); + waddch(win, suitchar[c.suit][0]); + mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]); + waddch(win, suitchar[c.suit][0]); + } +} + +/* + * prhand: + * Print a hand of n cards + */ +prhand(h, n, win, blank) +CARD h[]; +int n; +WINDOW *win; +BOOLEAN blank; +{ + register int i; + + werase(win); + for (i = 0; i < n; i++) + printcard(win, i, *h++, blank); + wrefresh(win); +} + + + +/* + * infrom: + * reads a card, supposedly in hand, accepting unambigous brief + * input, returns the index of the card found... + */ +infrom(hand, n, prompt) +CARD hand[]; +int n; +char *prompt; +{ + register int i, j; + CARD crd; + + if (n < 1) { + printf("\nINFROM: %d = n < 1!!\n", n); + exit(74); + } + for (;;) { + msg(prompt); + if (incard(&crd)) { /* if card is full card */ + if (!isone(crd, hand, n)) + msg("That's not in your hand"); + else { + for (i = 0; i < n; i++) + if (hand[i].rank == crd.rank && + hand[i].suit == crd.suit) + break; + if (i >= n) { + printf("\nINFROM: isone or something messed up\n"); + exit(77); + } + return i; + } + } + else /* if not full card... */ + if (crd.rank != EMPTY) { + for (i = 0; i < n; i++) + if (hand[i].rank == crd.rank) + break; + if (i >= n) + msg("No such rank in your hand"); + else { + for (j = i + 1; j < n; j++) + if (hand[j].rank == crd.rank) + break; + if (j < n) + msg("Ambiguous rank"); + else + return i; + } + } + else + msg("Sorry, I missed that"); + } + /* NOTREACHED */ +} + + + +/* + * incard: + * Inputs a card in any format. It reads a line ending with a CR + * and then parses it. + */ +incard(crd) +CARD *crd; +{ + char *getline(); + register int i; + int rnk, sut; + char *line, *p, *p1; + BOOLEAN retval; + + retval = FALSE; + rnk = sut = EMPTY; + if (!(line = getline())) + goto gotit; + p = p1 = line; + while( *p1 != ' ' && *p1 != NULL ) ++p1; + *p1++ = NULL; + if( *p == NULL ) goto gotit; + /* IMPORTANT: no real card has 2 char first name */ + if( strlen(p) == 2 ) { /* check for short form */ + rnk = EMPTY; + for( i = 0; i < RANKS; i++ ) { + if( *p == *rankchar[i] ) { + rnk = i; + break; + } + } + if( rnk == EMPTY ) goto gotit; /* it's nothing... */ + ++p; /* advance to next char */ + sut = EMPTY; + for( i = 0; i < SUITS; i++ ) { + if( *p == *suitchar[i] ) { + sut = i; + break; + } + } + if( sut != EMPTY ) retval = TRUE; + goto gotit; + } + rnk = EMPTY; + for( i = 0; i < RANKS; i++ ) { + if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) { + rnk = i; + break; + } + } + if( rnk == EMPTY ) goto gotit; + p = p1; + while( *p1 != ' ' && *p1 != NULL ) ++p1; + *p1++ = NULL; + if( *p == NULL ) goto gotit; + if( !strcmp( "OF", p ) ) { + p = p1; + while( *p1 != ' ' && *p1 != NULL ) ++p1; + *p1++ = NULL; + if( *p == NULL ) goto gotit; + } + sut = EMPTY; + for( i = 0; i < SUITS; i++ ) { + if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) { + sut = i; + break; + } + } + if( sut != EMPTY ) retval = TRUE; +gotit: + (*crd).rank = rnk; + (*crd).suit = sut; + return( retval ); +} + + + +/* + * getuchar: + * Reads and converts to upper case + */ +getuchar() +{ + register int c; + + c = readchar(); + if (islower(c)) + c = toupper(c); + waddch(Msgwin, c); + return c; +} + +/* + * number: + * Reads in a decimal number and makes sure it is between "lo" and + * "hi" inclusive. + */ +number(lo, hi, prompt) +int lo, hi; +char *prompt; +{ + char *getline(); + register char *p; + register int sum; + + sum = 0; + for (;;) { + msg(prompt); + if(!(p = getline()) || *p == NULL) { + msg(quiet ? "Not a number" : "That doesn't look like a number"); + continue; + } + sum = 0; + + if (!isdigit(*p)) + sum = lo - 1; + else + while (isdigit(*p)) { + sum = 10 * sum + (*p - '0'); + ++p; + } + + if (*p != ' ' && *p != '\t' && *p != NULL) + sum = lo - 1; + if (sum >= lo && sum <= hi) + return sum; + if (sum == lo - 1) + msg("that doesn't look like a number, try again --> "); + else + msg("%d is not between %d and %d inclusive, try again --> ", + sum, lo, hi); + } +} + +/* + * msg: + * Display a message at the top of the screen. + */ +char Msgbuf[BUFSIZ] = { '\0' }; + +int Mpos = 0; + +static int Newpos = 0; + +/* VARARGS1 */ +msg(fmt) + char *fmt; +{ + va_list ap; + + va_start(ap, fmt); + (void)vsprintf(&Msgbuf[Newpos], fmt, ap); + va_end(ap); + endmsg(); +} + +/* + * addmsg: + * Add things to the current message + */ +/* VARARGS1 */ +addmsg(fmt) + char *fmt; +{ + va_list ap; + + va_start(ap, fmt); + (void)vsprintf(&Msgbuf[Newpos], fmt, ap); + va_end(ap); +} + +/* + * endmsg: + * Display a new msg. + */ + +int Lineno = 0; + +endmsg() +{ + register int len; + register char *mp, *omp; + static int lastline = 0; + + /* + * All messages should start with uppercase + */ + mvaddch(lastline + Y_MSG_START, SCORE_X, ' '); + if (islower(Msgbuf[0]) && Msgbuf[1] != ')') + Msgbuf[0] = toupper(Msgbuf[0]); + mp = Msgbuf; + len = strlen(mp); + if (len / MSG_X + Lineno >= MSG_Y) { + while (Lineno < MSG_Y) { + wmove(Msgwin, Lineno++, 0); + wclrtoeol(Msgwin); + } + Lineno = 0; + } + mvaddch(Lineno + Y_MSG_START, SCORE_X, '*'); + lastline = Lineno; + do { + mvwaddstr(Msgwin, Lineno, 0, mp); + if ((len = strlen(mp)) > MSG_X) { + omp = mp; + for (mp = &mp[MSG_X-1]; *mp != ' '; mp--) + continue; + while (*mp == ' ') + mp--; + mp++; + wmove(Msgwin, Lineno, mp - omp); + wclrtoeol(Msgwin); + } + if (++Lineno >= MSG_Y) + Lineno = 0; + } while (len > MSG_X); + wclrtoeol(Msgwin); + Mpos = len; + Newpos = 0; + wrefresh(Msgwin); + refresh(); + wrefresh(Msgwin); +} + +#ifdef notdef +/* + * doadd: + * Perform an add onto the message buffer + */ +doadd(fmt, args) +char *fmt; +int *args; +{ + static FILE junk; + + /* + * Do the printf into Msgbuf + */ + junk._flag = _IOWRT + _IOSTRG; + junk._ptr = &Msgbuf[Newpos]; + junk._cnt = 32767; + _doprnt(fmt, args, &junk); + putc('\0', &junk); + Newpos = strlen(Msgbuf); +} +#endif + +/* + * do_wait: + * Wait for the user to type ' ' before doing anything else + */ +do_wait() +{ + register int line; + static char prompt[] = { '-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0' }; + + if (Mpos + sizeof prompt < MSG_X) + wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos); + else { + mvwaddch(Msgwin, Lineno, 0, ' '); + wclrtoeol(Msgwin); + if (++Lineno >= MSG_Y) + Lineno = 0; + } + waddstr(Msgwin, prompt); + wrefresh(Msgwin); + wait_for(' '); +} + +/* + * wait_for + * Sit around until the guy types the right key + */ +wait_for(ch) +register char ch; +{ + register char c; + + if (ch == '\n') + while ((c = readchar()) != '\n') + continue; + else + while (readchar() != ch) + continue; +} + +/* + * readchar: + * Reads and returns a character, checking for gross input errors + */ +readchar() +{ + register int cnt, y, x; + auto char c; + +over: + cnt = 0; + while (read(0, &c, 1) <= 0) + if (cnt++ > 100) { /* if we are getting infinite EOFs */ + bye(); /* quit the game */ + exit(1); + } + if (c == CTRL(L)) { + wrefresh(curscr); + goto over; + } + if (c == '\r') + return '\n'; + else + return c; +} + +/* + * getline: + * Reads the next line up to '\n' or EOF. Multiple spaces are + * compressed to one space; a space is inserted before a ',' + */ +char * +getline() +{ + register char *sp; + register int c, oy, ox; + register WINDOW *oscr; + + oscr = stdscr; + stdscr = Msgwin; + getyx(stdscr, oy, ox); + refresh(); + /* + * loop reading in the string, and put it in a temporary buffer + */ + for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) { + if (c == -1) + continue; + else if (c == erasechar()) { /* process erase character */ + if (sp > linebuf) { + register int i; + + sp--; + for (i = strlen(unctrl(*sp)); i; i--) + addch('\b'); + } + continue; + } + else if (c == killchar()) { /* process kill character */ + sp = linebuf; + move(oy, ox); + continue; + } + else if (sp == linebuf && c == ' ') + continue; + if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' ')) + putchar(CTRL(G)); + else { + if (islower(c)) + c = toupper(c); + *sp++ = c; + addstr(unctrl(c)); + Mpos++; + } + } + *sp = '\0'; + stdscr = oscr; + return linebuf; +} + +rint() +{ + bye(); + exit(1); +} + +/* + * bye: + * Leave the program, cleaning things up as we go. + */ +bye() +{ + signal(SIGINT, SIG_IGN); + mvcur(0, COLS - 1, LINES - 1, 0); + fflush(stdout); + endwin(); + putchar('\n'); +} diff --git a/cribbage/pathnames.h b/cribbage/pathnames.h new file mode 100644 index 00000000..908b05cc --- /dev/null +++ b/cribbage/pathnames.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 5.1 (Berkeley) 5/1/90 + */ + +#define _PATH_LOG "/var/games/criblog" +#define _PATH_MORE "/usr/bin/more" +#define _PATH_INSTR "/usr/share/games/cribbage.instr" diff --git a/cribbage/score.c b/cribbage/score.c new file mode 100644 index 00000000..be3ca3fd --- /dev/null +++ b/cribbage/score.c @@ -0,0 +1,364 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)score.c 5.5 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include <stdio.h> +#include "deck.h" +#include "cribbage.h" + + +/* + * the following arrays give the sum of the scores of the (50 2)*48 = 58800 + * hands obtainable for the crib given the two cards whose ranks index the + * array. the two arrays are for the case where the suits are equal and + * not equal respectively + */ + +long crbescr[ 169 ] = { + -10000, 271827, 278883, 332319, 347769, 261129, 250653, 253203, 248259, + 243435, 256275, 237435, 231051, -10000, -10000, 412815, 295707, 349497, + 267519, 262521, 259695, 254019, 250047, 262887, 244047, 237663, -10000, + -10000, -10000, 333987, 388629, 262017, 266787, 262971, 252729, 254475, + 267315, 248475, 242091, -10000, -10000, -10000, -10000, 422097, 302787, + 256437, 263751, 257883, 254271, 267111, 248271, 241887, -10000, -10000, + -10000, -10000, -10000, 427677, 387837, 349173, 347985, 423861, 436701, + 417861, 411477, -10000, -10000, -10000, -10000, -10000, -10000, 336387, + 298851, 338667, 236487, 249327, 230487, 224103, -10000, -10000, -10000, + -10000, -10000, -10000, -10000, 408483, 266691, 229803, 246195, 227355, + 220971, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, + 300675, 263787, 241695, 226407, 220023, -10000, -10000, -10000, -10000, + -10000, -10000, -10000, -10000, -10000, 295635, 273543, 219771, 216939, + -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, + -10000, 306519, 252747, 211431, -10000, -10000, -10000, -10000, -10000, + -10000, -10000, -10000, -10000, -10000, -10000, 304287, 262971, -10000, + -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, + -10000, -10000, 244131, -10000, -10000, -10000, -10000, -10000, -10000, + -10000, -10000, -10000, -10000, -10000, -10000, -10000 }; + +long crbnescr[ 169 ] = { + 325272, 260772, 267828, 321264, 336714, 250074, 239598, 242148, 237204, + 232380, 246348, 226380, 219996, -10000, 342528, 401760, 284652, 338442, + 256464, 251466, 248640, 242964, 238992, 252960, 232992, 226608, -10000, + -10000, 362280, 322932, 377574, 250962, 255732, 251916, 241674, 243420, + 257388, 237420, 231036, -10000, -10000, -10000, 360768, 411042, 291732, + 245382, 252696, 246828, 243216, 257184, 237216, 230832, -10000, -10000, + -10000, -10000, 528768, 416622, 376782, 338118, 336930, 412806, 426774, + 406806, 400422, -10000, -10000, -10000, -10000, -10000, 369864, 325332, + 287796, 327612, 225432, 239400, 219432, 213048, -10000, -10000, -10000, + -10000, -10000, -10000, 359160, 397428, 255636, 218748, 236268, 216300, + 209916, -10000, -10000, -10000, -10000, -10000, -10000, -10000, 331320, + 289620, 252732, 231768, 215352, 208968, -10000, -10000, -10000, -10000, + -10000, -10000, -10000, -10000, 325152, 284580, 263616, 208716, 205884, + -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, + 321240, 296592, 241692, 200376, -10000, -10000, -10000, -10000, -10000, + -10000, -10000, -10000, -10000, -10000, 348600, 294360, 253044, -10000, + -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, -10000, + -10000, 308664, 233076, -10000, -10000, -10000, -10000, -10000, -10000, + -10000, -10000, -10000, -10000, -10000, -10000, 295896 }; + + +static int ichoose2[ 5 ] = { 0, 0, 2, 6, 12 }; +static int pairpoints, runpoints; /* globals from pairuns */ + + +/* + * scorehand: + * Score the given hand of n cards and the starter card. + * n must be <= 4 + */ +scorehand(hand, starter, n, crb, do_explain) +register CARD hand[]; +CARD starter; +int n; +BOOLEAN crb; /* true if scoring crib */ +BOOLEAN do_explain; /* true if must explain this hand */ +{ + CARD h[(CINHAND + 1)]; + register int i, k; + register int score; + register BOOLEAN flag; + char buf[32]; + + expl[0] = NULL; /* initialize explanation */ + score = 0; + flag = TRUE; + k = hand[0].suit; + for (i = 0; i < n; i++) { /* check for flush */ + flag = (flag && (hand[i].suit == k)); + if (hand[i].rank == JACK) /* check for his nibs */ + if (hand[i].suit == starter.suit) { + score++; + if (do_explain) + strcat(expl, "His Nobs"); + } + h[i] = hand[i]; + } + + if (flag && n >= CINHAND) { + if (do_explain && expl[0] != NULL) + strcat(expl, ", "); + if (starter.suit == k) { + score += 5; + if (do_explain) + strcat(expl, "Five-flush"); + } + else if (!crb) { + score += 4; + if (do_explain && expl[0] != NULL) + strcat(expl, ", Four-flush"); + else + strcpy(expl, "Four-flush"); + } + } + + if (do_explain && expl[0] != NULL) + strcat(expl, ", "); + h[n] = starter; + sorthand(h, n + 1); /* sort by rank */ + i = 2 * fifteens(h, n + 1); + score += i; + if (do_explain) + if (i > 0) { + (void)sprintf(buf, "%d points in fifteens", i); + strcat(expl, buf); + } + else + strcat(expl, "No fifteens"); + i = pairuns(h, n + 1); + score += i; + if (do_explain) + if (i > 0) { + (void)sprintf(buf, ", %d points in pairs, %d in runs", + pairpoints, runpoints); + strcat(expl, buf); + } + else + strcat(expl, ", No pairs/runs"); + return score; +} + +/* + * fifteens: + * Return number of fifteens in hand of n cards + */ +fifteens(hand, n) +register CARD hand[]; +int n; +{ + register int *sp, *np; + register int i; + register CARD *endp; + static int sums[15], nsums[15]; + + np = nsums; + sp = sums; + i = 16; + while (--i) { + *np++ = 0; + *sp++ = 0; + } + for (endp = &hand[n]; hand < endp; hand++) { + i = hand->rank + 1; + if (i > 10) + i = 10; + np = &nsums[i]; + np[-1]++; /* one way to make this */ + sp = sums; + while (i < 15) { + *np++ += *sp++; + i++; + } + sp = sums; + np = nsums; + i = 16; + while (--i) + *sp++ = *np++; + } + return sums[14]; +} + + + +/* + * pairuns returns the number of points in the n card sorted hand + * due to pairs and runs + * this routine only works if n is strictly less than 6 + * sets the globals pairpoints and runpoints appropriately + */ + +pairuns( h, n ) + + CARD h[]; + int n; +{ + register int i; + int runlength, runmult, lastmult, curmult; + int mult1, mult2, pair1, pair2; + BOOLEAN run; + + run = TRUE; + runlength = 1; + mult1 = 1; + pair1 = -1; + mult2 = 1; + pair2 = -1; + curmult = runmult = 1; + for( i = 1; i < n; i++ ) { + lastmult = curmult; + if( h[i].rank == h[i - 1].rank ) { + if( pair1 < 0 ) { + pair1 = h[i].rank; + mult1 = curmult = 2; + } + else { + if( h[i].rank == pair1 ) { + curmult = ++mult1; + } + else { + if( pair2 < 0 ) { + pair2 = h[i].rank; + mult2 = curmult = 2; + } + else { + curmult = ++mult2; + } + } + } + if( i == (n - 1) && run ) { + runmult *= curmult; + } + } + else { + curmult = 1; + if( h[i].rank == h[i - 1].rank + 1 ) { + if( run ) { + ++runlength; + } + else { + if( runlength < 3 ) { /* only if old short */ + run = TRUE; + runlength = 2; + runmult = 1; + } + } + runmult *= lastmult; + } + else { + if( run ) runmult *= lastmult; /* if just ended */ + run = FALSE; + } + } + } + pairpoints = ichoose2[ mult1 ] + ichoose2[ mult2 ]; + runpoints = ( runlength >= 3 ? runlength*runmult : 0 ); + return( pairpoints + runpoints ); +} + + + +/* + * pegscore tells how many points crd would get if played after + * the n cards in tbl during pegging + */ + +pegscore( crd, tbl, n, sum ) + + CARD crd, tbl[]; + int n; + int sum; +{ + BOOLEAN got[ RANKS ]; + register int i, j, scr; + int k, lo, hi; + + sum += VAL( crd.rank ); + if( sum > 31 ) return( -1 ); + if( sum == 31 || sum == 15 ) scr = 2; + else scr = 0; + if( !n ) return( scr ); + j = 1; + while( ( crd.rank == tbl[n - j].rank ) && ( n - j >= 0 ) ) ++j; + if( j > 1 ) return( scr + ichoose2[j] ); + if( n < 2 ) return( scr ); + lo = hi = crd.rank; + for( i = 0; i < RANKS; i++ ) got[i] = FALSE; + got[ crd.rank ] = TRUE; + k = -1; + for( i = n - 1; i >= 0; --i ) { + if( got[ tbl[i].rank ] ) break; + got[ tbl[i].rank ] = TRUE; + if( tbl[i].rank < lo ) lo = tbl[i].rank; + if( tbl[i].rank > hi ) hi = tbl[i].rank; + for( j = lo; j <= hi; j++ ) if( !got[j] ) break; + if( j > hi ) k = hi - lo + 1; + } + if( k >= 3 ) return( scr + k ); + else return( scr ); +} + + + +/* + * adjust takes a two card hand that will be put in the crib + * and returns an adjusted normalized score for the number of + * points such a crib will get. + */ + +adjust( cb, tnv ) + + CARD cb[], tnv; +{ + int i, c0, c1; + long scr; + + c0 = cb[0].rank; + c1 = cb[1].rank; + if( c0 > c1 ) { + i = c0; + c0 = c1; + c1 = i; + } + if( cb[0].suit != cb[1].suit ) scr = crbnescr[ RANKS*c0 + c1 ]; + else scr = crbescr[ RANKS*c0 + c1 ]; + if( scr <= 0 ) { + printf( "\nADJUST: internal error %d %d\n", c0, c1 ); + exit( 93 ); + } + return( (scr + 29400)/58800 ); +} + + + diff --git a/cribbage/support.c b/cribbage/support.c new file mode 100644 index 00000000..b617296e --- /dev/null +++ b/cribbage/support.c @@ -0,0 +1,357 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)support.c 5.6 (Berkeley) 2/28/91"; +#endif /* not lint */ + +#include <curses.h> +#include "deck.h" +#include "cribbage.h" +#include "cribcur.h" + + +#define NTV 10 /* number scores to test */ + +/* score to test reachability of, and order to test them in */ +int tv[ NTV ] = { 8, 7, 9, 6, 11, 12, 13, 14, 10, 5 }; + + +/* + * computer chooses what to play in pegging... + * only called if no playable card will score points + */ + +cchose( h, n, s ) + + CARD h[]; + int n; + int s; +{ + register int i, j, l; + + if( n <= 1 ) return( 0 ); + if( s < 4 ) { /* try for good value */ + if( ( j = anysumto(h, n, s, 4) ) >= 0 ) return( j ); + if( ( j = anysumto(h, n, s, 3) ) >= 0 && s == 0 ) + return( j ); + } + if( s > 0 && s < 20 ) { + for( i = 1; i <= 10; i++ ) { /* try for retaliation to 31 */ + if( ( j = anysumto(h, n, s, 21-i) ) >= 0 ) { + if( ( l = numofval(h, n, i) ) > 0 ) { + if( l > 1 || VAL( h[j].rank ) != i ) return( j ); + } + } + } + } + if( s < 15 ) { + for( i = 0; i < NTV; i++ ) { /* for retaliation after 15 */ + if( ( j = anysumto(h, n, s, tv[i]) ) >= 0 ) { + if( ( l = numofval(h, n, 15-tv[i]) ) > 0 ) { + if( l > 1 || VAL( h[j].rank ) != 15-tv[i] ) return( j ); + } + } + } + } + j = -1; + for( i = n - 1; i >= 0; --i ) { /* remember: h is sorted */ + l = s + VAL( h[i].rank ); + if( l > 31 ) continue; + if( l != 5 && l != 10 && l != 21 ) { + j = i; + break; + } + } + if( j >= 0 ) return( j ); + for( i = n - 1; i >= 0; --i ) { + l = s + VAL( h[i].rank ); + if( l > 31 ) continue; + if( j < 0 ) j = i; + if( l != 5 && l != 21 ) { + j = i; + break; + } + } + return( j ); +} + + + +/* + * plyrhand: + * Evaluate and score a player hand or crib + */ +plyrhand(hand, s) +CARD hand[]; +char *s; +{ + register int i, j; + register BOOLEAN win; + static char prompt[BUFSIZ]; + + prhand(hand, CINHAND, Playwin, FALSE); + (void)sprintf(prompt, "Your %s scores ", s); + i = scorehand(hand, turnover, CINHAND, strcmp(s, "crib") == 0, explain); + if ((j = number(0, 29, prompt)) == 19) + j = 0; + if (i != j) { + if (i < j) { + win = chkscr(&pscore, i); + msg("It's really only %d points; I get %d", i, 2); + if (!win) + win = chkscr(&cscore, 2); + } + else { + win = chkscr(&pscore, j); + msg("You should have taken %d, not %d!", i, j); + } + if (explain) + msg("Explanation: %s", expl); + do_wait(); + } + else + win = chkscr(&pscore, i); + return win; +} + +/* + * comphand: + * Handle scoring and displaying the computers hand + */ +comphand(h, s) +CARD h[]; +char *s; +{ + register int j; + + j = scorehand(h, turnover, CINHAND, strcmp(s, "crib") == 0, FALSE); + prhand(h, CINHAND, Compwin, FALSE); + msg("My %s scores %d", s, (j == 0 ? 19 : j)); + return chkscr(&cscore, j); +} + +/* + * chkscr: + * Add inc to scr and test for > glimit, printing on the scoring + * board while we're at it. + */ + +int Lastscore[2] = {-1, -1}; + +chkscr(scr, inc) +int *scr, inc; +{ + BOOLEAN myturn; + + myturn = (scr == &cscore); + if (inc != 0) { + prpeg(Lastscore[myturn], '.', myturn); + Lastscore[myturn] = *scr; + *scr += inc; + prpeg(*scr, PEG, myturn); + refresh(); + } + return (*scr >= glimit); +} + +/* + * prpeg: + * Put out the peg character on the score board and put the + * score up on the board. + */ +prpeg(score, peg, myturn) +register int score; +char peg; +BOOLEAN myturn; +{ + register int y, x; + + if (!myturn) + y = SCORE_Y + 2; + else + y = SCORE_Y + 5; + + if (score <= 0 || score >= glimit) { + if (peg == '.') + peg = ' '; + if (score == 0) + x = SCORE_X + 2; + else { + x = SCORE_X + 2; + y++; + } + } + else { + x = (score - 1) % 30; + if (score > 90 || (score > 30 && score <= 60)) { + y++; + x = 29 - x; + } + x += x / 5; + x += SCORE_X + 3; + } + mvaddch(y, x, peg); + mvprintw(SCORE_Y + (myturn ? 7 : 1), SCORE_X + 10, "%3d", score); +} + +/* + * cdiscard -- the computer figures out what is the best discard for + * the crib and puts the best two cards at the end + */ + +cdiscard( mycrib ) + + BOOLEAN mycrib; +{ + CARD d[ CARDS ], h[ FULLHAND ], cb[ 2 ]; + register int i, j, k; + int nc, ns; + long sums[ 15 ]; + static int undo1[15] = {0,0,0,0,0,1,1,1,1,2,2,2,3,3,4}; + static int undo2[15] = {1,2,3,4,5,2,3,4,5,3,4,5,4,5,5}; + + makedeck( d ); + nc = CARDS; + for( i = 0; i < knownum; i++ ) { /* get all other cards */ + cremove( known[i], d, nc-- ); + } + for( i = 0; i < 15; i++ ) sums[i] = 0L; + ns = 0; + for( i = 0; i < (FULLHAND - 1); i++ ) { + cb[0] = chand[i]; + for( j = i + 1; j < FULLHAND; j++ ) { + cb[1] = chand[j]; + for( k = 0; k < FULLHAND; k++ ) h[k] = chand[k]; + cremove( chand[i], h, FULLHAND ); + cremove( chand[j], h, FULLHAND - 1 ); + for( k = 0; k < nc; k++ ) { + sums[ns] += scorehand( h, d[k], CINHAND, TRUE, FALSE ); + if( mycrib ) sums[ns] += adjust( cb, d[k] ); + else sums[ns] -= adjust( cb, d[k] ); + } + ++ns; + } + } + j = 0; + for( i = 1; i < 15; i++ ) if( sums[i] > sums[j] ) j = i; + for( k = 0; k < FULLHAND; k++ ) h[k] = chand[k]; + cremove( h[ undo1[j] ], chand, FULLHAND ); + cremove( h[ undo2[j] ], chand, FULLHAND - 1 ); + chand[4] = h[ undo1[j] ]; + chand[5] = h[ undo2[j] ]; +} + + + +/* + * returns true if some card in hand can be played without exceeding 31 + */ + +anymove( hand, n, sum ) + + CARD hand[]; + int n; + int sum; +{ + register int i, j; + + if( n < 1 ) return( FALSE ); + j = hand[0].rank; + for( i = 1; i < n; i++ ) { + if( hand[i].rank < j ) j = hand[i].rank; + } + return( sum + VAL( j ) <= 31 ); +} + + + +/* + * anysumto returns the index (0 <= i < n) of the card in hand that brings + * the s up to t, or -1 if there is none + */ + +anysumto( hand, n, s, t ) + + CARD hand[]; + int n; + int s, t; +{ + register int i; + + for( i = 0; i < n; i++ ) { + if( s + VAL( hand[i].rank ) == t ) return( i ); + } + return( -1 ); +} + + + + +/* + * return the number of cards in h having the given rank value + */ + +numofval( h, n, v ) + + CARD h[]; + int n; + int v; +{ + register int i, j; + + j = 0; + for( i = 0; i < n; i++ ) { + if( VAL( h[i].rank ) == v ) ++j; + } + return( j ); +} + + + +/* + * makeknown remembers all n cards in h for future recall + */ + +makeknown( h, n ) + + CARD h[]; + int n; +{ + register int i; + + for( i = 0; i < n; i++ ) { + known[ knownum++ ] = h[i]; + } +} + |