Initial revision

git-svn-id: file:///srv/svn/joey/bsdgames-trunk@5086 a4a2c43b-8ac3-0310-8836-e0e880c912e2
This commit is contained in:
joey
1999-09-08 23:56:51 +00:00
commit 03272d67da
623 changed files with 243457 additions and 0 deletions

15
cribbage/Makefile.bsd Normal file
View File

@@ -0,0 +1,15 @@
# $NetBSD: Makefile,v 1.10 1998/02/18 22:37:31 jtc Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= cribbage
DPADD= ${LIBCURSES}
LDADD= -lcurses
SRCS= extern.c crib.c cards.c instr.c io.c score.c support.c
MAN= cribbage.6
HIDEGAME=hidegame
SETGIDGAME=yes
FILES= cribbage.n
FILESNAME=cribbage.instr
FILESDIR=/usr/share/games
.include <bsd.prog.mk>

12
cribbage/Makefrag Normal file
View File

@@ -0,0 +1,12 @@
# Makefrag - makefile fragment for cribbage
cribbage_DIRS := $(GAMESDIR) $(MAN6DIR) $(shell dirname $(CRIBBAGE_INSTRFILE))
cribbage_all: cribbage/cribbage cribbage/cribbage.n cribbage/cribbage.6
cribbage_install: cribbage_all
$(INSTALL_SCORE_GAME) cribbage/cribbage $(INSTALL_PREFIX)$(GAMESDIR)/cribbage
$(HIDE_GAME) cribbage
$(INSTALL_DATA) cribbage/cribbage.n $(INSTALL_PREFIX)$(CRIBBAGE_INSTRFILE)
$(INSTALL_SCORE_FILE) $(CRIBBAGE_SCOREFILE)
$(INSTALL_MANUAL) cribbage/cribbage.6

157
cribbage/cards.c Normal file
View File

@@ -0,0 +1,157 @@
/* $NetBSD: cards.c,v 1.4 1997/10/10 12:32:22 lukem Exp $ */
/*-
* Copyright (c) 1980, 1993
* 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)cards.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: cards.c,v 1.4 1997/10/10 12:32:22 lukem Exp $");
#endif
#endif /* not lint */
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "deck.h"
#include "cribbage.h"
/*
* Initialize a deck of cards to contain one of each type.
*/
void
makedeck(d)
CARD d[];
{
int i, j, k;
i = time(NULL);
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.
*/
void
shuffle(d)
CARD d[];
{
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...
*/
int
eq(a, b)
CARD a, b;
{
return ((a.rank == b.rank) && (a.suit == b.suit));
}
/*
* is_one returns TRUE if a is in the set of cards b
*/
int
is_one(a, b, n)
CARD a;
const CARD b[];
int n;
{
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
*/
void
cremove(a, d, n)
CARD a, d[];
int n;
{
int i, j;
for (i = j = 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
*/
void
sorthand(h, n)
CARD h[];
int n;
{
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;
}
}

662
cribbage/crib.c Normal file
View File

@@ -0,0 +1,662 @@
/* $NetBSD: crib.c,v 1.10 1998/08/30 09:19:37 veego Exp $ */
/*-
* Copyright (c) 1980, 1993
* 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
The Regents of the University of California. All rights reserved.\n");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)crib.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: crib.c,v 1.10 1998/08/30 09:19:37 veego Exp $");
#endif
#endif /* not lint */
#include <curses.h>
#include <err.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "deck.h"
#include "cribbage.h"
#include "cribcur.h"
#include "pathnames.h"
int main __P((int, char *[]));
int
main(argc, argv)
int argc;
char *argv[];
{
BOOLEAN playing;
FILE *f;
int ch;
int fd;
int flags;
f = fopen(_PATH_LOG, "a");
if (f == NULL)
warn("fopen %s", _PATH_LOG);
/* Revoke setgid privileges */
setregid(getgid(), getgid());
/* Set close-on-exec flag on log file */
if (f != NULL) {
fd = fileno(f);
flags = fcntl(fd, F_GETFD);
if (flags < 0)
err(1, "fcntl F_GETFD");
flags |= FD_CLOEXEC;
if (fcntl(fd, F_SETFD, flags) == -1)
err(1, "fcntl F_SETFD");
}
while ((ch = getopt(argc, argv, "eqr")) != -1)
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();
(void)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 cribbage rules, use \"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 != NULL) {
(void)fprintf(f, "%s: won %5.5d, lost %5.5d\n",
getlogin(), cgames, pgames);
(void) fclose(f);
}
bye();
exit(0);
}
/*
* makeboard:
* Print out the initial board on the screen
*/
void
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
*/
void
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.
*/
void
game()
{
int i, j;
BOOLEAN flag;
BOOLEAN compcrib;
compcrib = FALSE;
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);
do_wait();
clear();
makeboard();
refresh();
} else {
makeboard();
refresh();
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
*/
int
playhand(mycrib)
BOOLEAN mycrib;
{
int deckpos;
werase(Compwin);
wrefresh(Compwin);
werase(Tablewin);
wrefresh(Tablewin);
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
*/
int
deal(mycrib)
BOOLEAN mycrib;
{
int i, j;
for (i = j = 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
*/
void
discard(mycrib)
BOOLEAN mycrib;
{
const 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.
*/
int
cut(mycrib, pos)
BOOLEAN mycrib;
int pos;
{
int i;
BOOLEAN win;
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
*/
void
prcrib(mycrib, blank)
BOOLEAN mycrib, blank;
{
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, " ");
refresh();
}
/*
* peg:
* Handle all the pegging...
*/
static CARD Table[14];
static int Tcnt;
int
peg(mycrib)
BOOLEAN mycrib;
{
static CARD ch[CINHAND], ph[CINHAND];
int i, j, k;
int l;
int cnum, pnum, sum;
BOOLEAN myturn, mego, ugo, last, played;
CARD crd;
played = FALSE;
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;
}
/* can player move? */
if (anymove(ph, pnum, sum))
myturn = !myturn;
else { /* give him his point */
msg(quiet ? "You get one" :
"You get one point");
do_wait();
if (chkscr(&pscore, 1))
return TRUE;
sum = 0;
mego = ugo = FALSE;
Tcnt = 0;
}
} else {
played = TRUE;
j = -1;
k = 0;
/* maximize score */
for (i = 0; i < cnum; i++) {
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;
}
/* can computer play? */
if (anymove(ch, cnum, sum))
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 (pnum == 0)
do_wait();
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");
do_wait();
if (chkscr(&pscore, 1))
return TRUE;
}
}
return (FALSE);
}
/*
* prtable:
* Print out the table with the current score
*/
void
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
*/
int
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);
do_wait();
} else {
if (comphand(chand, "hand"))
return (TRUE);
if (plyrhand(phand, "hand"))
return (TRUE);
if (plyrhand(crib, "crib"))
return (TRUE);
}
return (FALSE);
}

187
cribbage/cribbage.6.in Normal file
View File

@@ -0,0 +1,187 @@
.\" $NetBSD: cribbage.6,v 1.5 1997/10/10 12:32:26 lukem Exp $
.\"
.\" Copyright (c) 1980, 1993
.\" 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.
.\"
.\" @(#)cribbage.6 8.1 (Berkeley) 5/31/93
.\"
.Dd May 31, 1993
.Dt CRIBBAGE 6
.Os
.Sh NAME
.Nm cribbage
.Nd the card game cribbage
.Sh SYNOPSIS
.Nm
.Op Fl eqr
.Sh DESCRIPTION
.Nm
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
.Em According to Hoyle
with
.Xr more 1 .
.Pp
.Nm
options include:
.Bl -tag -width indent
.It Fl 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.)
.It Fl q
Print a shorter form of all messages \- this is only recommended for
users who have played the game without specifying this option.
.It Fl r
Instead of asking the player to cut the deck, the program will randomly
cut the deck.
.El
.Pp
.Nm
first asks the player whether he wishes to play a short game (
.Dq once around ,
to 61) or a long game (
.Dq twice around ,
to 121). A
response of
.Sq Ic 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:
.Sq a ,
.Sq 2 ,
.Sq 3 ,
.Sq 4 ,
.Sq 5 ,
.Sq 6 ,
.Sq 7 ,
.Sq 8 ,
.Sq 9 ,
.Sq t ,
.Sq j ,
.Sq q ,
and
.Sq k ,
or alternatively, one of:
.Sq ace ,
.Sq two ,
.Sq three ,
.Sq four ,
.Sq five ,
.Sq six ,
.Sq seven ,
.Sq eight ,
.Sq nine ,
.Sq ten ,
.Sq jack ,
.Sq queen ,
and
.Sq king .
Suits may be specified as:
.Sq s ,
.Sq h ,
.Sq d ,
and
.Sq c ,
or alternatively as:
.Sq spades ,
.Sq hearts ,
.Sq diamonds ,
and
.Sq clubs .
A card may be specified as:
.Dq Ao rank Ac \ Aq suit ,
or:
.Dq Ao rank Ac of Aq 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
.Dq 2H, 4D, 5C, 6H, JC, and KD
and it was desired to discard the king of diamonds, any of
the following could be typed:
.Sq k ,
.Sq king ,
.Sq kd ,
.Sq k d ,
.Sq k of d ,
.Sq king d ,
.Sq king of d ,
.Sq k diamonds ,
.Sq k of diamonds ,
.Sq king diamonds ,
.Sq king of diamonds .
.Sh FILES
.Bl -tag -width @gamesdir@/cribbage -compact
.It Pa @gamesdir@/cribbage
.It Pa @cribbage_scorefile@
.It Pa @cribbage_instrfile@
.El
.Sh AUTHORS
Earl T. Cohen wrote the logic.
Ken Arnold added the screen oriented interface.

114
cribbage/cribbage.h Normal file
View File

@@ -0,0 +1,114 @@
/* $NetBSD: cribbage.h,v 1.4 1998/09/13 15:27:27 hubertf Exp $ */
/*
* Copyright (c) 1980, 1993
* 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.
*
* @(#)cribbage.h 8.1 (Berkeley) 5/31/93
*/
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 */
void addmsg __P((const char *, ...));
int adjust __P((const CARD [], CARD));
int anymove __P((const CARD [], int, int));
int anysumto __P((const CARD [], int, int, int));
void bye __P((void));
int cchose __P((const CARD [], int, int));
void cdiscard __P((BOOLEAN));
int chkscr __P((int *, int));
int comphand __P((const CARD [], const char *));
void cremove __P((CARD, CARD [], int));
int cut __P((BOOLEAN, int));
int deal __P((int));
void discard __P((BOOLEAN));
void do_wait __P((void));
void endmsg __P((void));
int eq __P((CARD, CARD));
int fifteens __P((const CARD [], int));
void game __P((void));
void gamescore __P((void));
char *getline __P((void));
int getuchar __P((void));
int incard __P((CARD *));
int infrom __P((const CARD [], int, const char *));
void instructions __P((void));
int is_one __P((CARD, const CARD [], int));
void makeboard __P((void));
void makedeck __P((CARD []));
void makeknown __P((const CARD [], int));
void msg __P((const char *, ...));
int msgcard __P((CARD, BOOLEAN));
int msgcrd __P((CARD, BOOLEAN, const char *, BOOLEAN));
int number __P((int, int, const char *));
int numofval __P((const CARD [], int, int));
int pairuns __P((const CARD [], int));
int peg __P((BOOLEAN));
int pegscore __P((CARD, const CARD [], int, int));
int playhand __P((BOOLEAN));
int plyrhand __P((const CARD [], const char *));
void prcard __P((WINDOW *, int, int, CARD, BOOLEAN));
void prcrib __P((BOOLEAN, BOOLEAN));
void prhand __P((const CARD [], int, WINDOW *, BOOLEAN));
void printcard __P((WINDOW *, int, CARD, BOOLEAN));
void prpeg __P((int, int, BOOLEAN));
void prtable __P((int));
int readchar __P((void));
void rint __P((int)) __attribute__((__noreturn__));
int score __P((BOOLEAN));
int scorehand __P((const CARD [], CARD, int, BOOLEAN, BOOLEAN));
void shuffle __P((CARD []));
void sorthand __P((CARD [], int));
void wait_for __P((int));

226
cribbage/cribbage.n Normal file
View File

@@ -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.

59
cribbage/cribcur.h Normal file
View File

@@ -0,0 +1,59 @@
/* $NetBSD: cribcur.h,v 1.3 1995/03/21 15:08:48 cgd Exp $ */
/*
* Copyright (c) 1980, 1993
* 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.
*
* @(#)cribcur.h 8.1 (Berkeley) 5/31/93
*/
# 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 */

87
cribbage/deck.h Normal file
View File

@@ -0,0 +1,87 @@
/* $NetBSD: deck.h,v 1.3 1995/03/21 15:08:49 cgd Exp $ */
/*
* Copyright (c) 1980, 1993
* 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.
*
* @(#)deck.h 8.1 (Berkeley) 5/31/93
*/
/*
* 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;

75
cribbage/extern.c Normal file
View File

@@ -0,0 +1,75 @@
/* $NetBSD: extern.c,v 1.4 1997/10/10 12:32:29 lukem Exp $ */
/*-
* Copyright (c) 1980, 1993
* 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)extern.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: extern.c,v 1.4 1997/10/10 12:32:29 lukem Exp $");
#endif
#endif /* not lint */
#include <curses.h>
#include "deck.h"
#include "cribbage.h"
BOOLEAN explain = FALSE; /* player mistakes explained */
BOOLEAN iwon = FALSE; /* if comp won last game */
BOOLEAN quiet = FALSE; /* if suppress random mess */
BOOLEAN 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 */

102
cribbage/instr.c Normal file
View File

@@ -0,0 +1,102 @@
/* $NetBSD: instr.c,v 1.7 1997/10/11 02:44:31 lukem Exp $ */
/*-
* Copyright (c) 1990, 1993
* 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)instr.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: instr.c,v 1.7 1997/10/11 02:44:31 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <curses.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "deck.h"
#include "cribbage.h"
#include "pathnames.h"
void
instructions()
{
int pstat;
int fd;
pid_t pid;
const char *path;
switch (pid = vfork()) {
case -1:
err(1, "vfork");
case 0:
/* Follow the same behaviour for pagers as defined in POSIX.2
* for mailx and man. We only use a pager if stdout is
* a terminal, and we pass the file on stdin to sh -c pager.
*/
if (!isatty(1))
path = "cat";
else {
if (!(path = getenv("PAGER")) || (*path == 0))
path = _PATH_MORE;
}
if ((fd = open(_PATH_INSTR, O_RDONLY)) == -1) {
warn("open %s", _PATH_INSTR);
_exit(1);
}
if (dup2(fd, 0) == -1) {
warn("dup2");
_exit(1);
}
execl("/bin/sh", "sh", "-c", path, NULL);
warn("%s", "");
_exit(1);
default:
do {
pid = waitpid(pid, &pstat, 0);
} while (pid == -1 && errno == EINTR);
if (pid == -1 || WEXITSTATUS(pstat))
exit(1);
}
}

633
cribbage/io.c Normal file
View File

@@ -0,0 +1,633 @@
/* $NetBSD: io.c,v 1.10 1997/10/10 12:32:32 lukem Exp $ */
/*-
* Copyright (c) 1980, 1993
* 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: io.c,v 1.10 1997/10/10 12:32:32 lukem Exp $");
#endif
#endif /* not lint */
#include <ctype.h>
#include <curses.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include "deck.h"
#include "cribbage.h"
#include "cribcur.h"
#define LINESIZE 128
#ifdef CTRL
#undef CTRL
#endif
#define CTRL(X) (X - 'A' + 1)
char linebuf[LINESIZE];
const char *const rankname[RANKS] = {
"ACE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
"EIGHT", "NINE", "TEN", "JACK", "QUEEN", "KING"
};
const char *const rankchar[RANKS] = {
"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"
};
const char *const suitname[SUITS] = {"SPADES", "HEARTS", "DIAMONDS", "CLUBS"};
const char *const suitchar[SUITS] = {"S", "H", "D", "C"};
/*
* msgcard:
* Call msgcrd in one of two forms
*/
int
msgcard(c, brief)
CARD c;
BOOLEAN brief;
{
if (brief)
return (msgcrd(c, TRUE, NULL, TRUE));
else
return (msgcrd(c, FALSE, " of ", FALSE));
}
/*
* msgcrd:
* Print the value of a card in ascii
*/
int
msgcrd(c, brfrank, mid, brfsuit)
CARD c;
BOOLEAN brfrank, brfsuit;
const char *mid;
{
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.
*/
void
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
*/
void
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
*/
void
prhand(h, n, win, blank)
const CARD h[];
int n;
WINDOW *win;
BOOLEAN blank;
{
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...
*/
int
infrom(hand, n, prompt)
const CARD hand[];
int n;
const char *prompt;
{
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 (!is_one(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: is_one 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.
*/
int
incard(crd)
CARD *crd;
{
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 != '\0')
++p1;
*p1++ = '\0';
if (*p == '\0')
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 != '\0')
++p1;
*p1++ = '\0';
if (*p == '\0')
goto gotit;
if (!strcmp("OF", p)) {
p = p1;
while (*p1 != ' ' && *p1 != '\0')
++p1;
*p1++ = '\0';
if (*p == '\0')
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
*/
int
getuchar()
{
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.
*/
int
number(lo, hi, prompt)
int lo, hi;
const char *prompt;
{
char *p;
int sum;
for (sum = 0;;) {
msg(prompt);
if (!(p = getline()) || *p == '\0') {
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 != '\0')
sum = lo - 1;
if (sum >= lo && sum <= hi)
break;
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);
}
return (sum);
}
/*
* msg:
* Display a message at the top of the screen.
*/
char Msgbuf[BUFSIZ] = {'\0'};
int Mpos = 0;
static int Newpos = 0;
void
#if __STDC__
msg(const char *fmt, ...)
#else
msg(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
(void)vsprintf(&Msgbuf[Newpos], fmt, ap);
Newpos = strlen(Msgbuf);
va_end(ap);
endmsg();
}
/*
* addmsg:
* Add things to the current message
*/
void
#if __STDC__
addmsg(const char *fmt, ...)
#else
addmsg(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
(void)vsprintf(&Msgbuf[Newpos], fmt, ap);
Newpos = strlen(Msgbuf);
va_end(ap);
}
/*
* endmsg:
* Display a new msg.
*/
int Lineno = 0;
void
endmsg()
{
static int lastline = 0;
int len;
char *mp, *omp;
/* 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);
}
/*
* do_wait:
* Wait for the user to type ' ' before doing anything else
*/
void
do_wait()
{
static const char prompt[] = {'-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0'};
if ((int)(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
*/
void
wait_for(ch)
int ch;
{
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
*/
int
readchar()
{
int cnt;
char c;
over:
cnt = 0;
while (read(STDIN_FILENO, &c, sizeof(char)) <= 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()
{
char *sp;
int c, oy, ox;
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) {
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);
}
void
rint(signo)
int signo __attribute__((unused));
{
bye();
exit(1);
}
/*
* bye:
* Leave the program, cleaning things up as we go.
*/
void
bye()
{
signal(SIGINT, SIG_IGN);
mvcur(0, COLS - 1, LINES - 1, 0);
fflush(stdout);
endwin();
putchar('\n');
}

40
cribbage/pathnames.h.in Normal file
View File

@@ -0,0 +1,40 @@
/* $NetBSD: pathnames.h,v 1.3 1995/03/21 15:08:56 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993
* 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 8.1 (Berkeley) 5/31/93
*/
#define _PATH_INSTR "@cribbage_instrfile@"
#define _PATH_LOG "@cribbage_scorefile@"
#define _PATH_MORE "@pager@"

378
cribbage/score.c Normal file
View File

@@ -0,0 +1,378 @@
/* $NetBSD: score.c,v 1.6 1998/08/30 09:19:37 veego Exp $ */
/*-
* Copyright (c) 1980, 1993
* 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)score.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: score.c,v 1.6 1998/08/30 09:19:37 veego Exp $");
#endif
#endif /* not lint */
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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
*/
const 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
};
const 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 const 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
*/
int
scorehand(hand, starter, n, crb, do_explain)
const CARD hand[];
CARD starter;
int n;
BOOLEAN crb; /* true if scoring crib */
BOOLEAN do_explain; /* true if must explain this hand */
{
int i, k;
int score;
BOOLEAN flag;
CARD h[(CINHAND + 1)];
char buf[32];
expl[0] = '\0'; /* 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] != '\0')
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] != '\0')
strcat(expl, ", Four-flush");
else
strcpy(expl, "Four-flush");
}
}
if (do_explain && expl[0] != '\0')
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
*/
int
fifteens(hand, n)
const CARD hand[];
int n;
{
int *sp, *np;
int i;
const 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
*/
int
pairuns(h, n)
const CARD h[];
int n;
{
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 {
/* only if old short */
if (runlength < 3) {
run = TRUE;
runlength = 2;
runmult = 1;
}
}
runmult *= lastmult;
} else {
/* if just ended */
if (run)
runmult *= lastmult;
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
*/
int
pegscore(crd, tbl, n, sum)
CARD crd;
const CARD tbl[];
int n, sum;
{
BOOLEAN got[RANKS];
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.
*/
int
adjust(cb, tnv)
const CARD cb[];
CARD tnv __attribute__((unused));
{
long scr;
int i, c0, c1;
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);
}

365
cribbage/support.c Normal file
View File

@@ -0,0 +1,365 @@
/* $NetBSD: support.c,v 1.4 1997/10/10 12:32:36 lukem Exp $ */
/*-
* Copyright (c) 1980, 1993
* 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: support.c,v 1.4 1997/10/10 12:32:36 lukem Exp $");
#endif
#endif /* not lint */
#include <curses.h>
#include <string.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 */
const 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
*/
int
cchose(h, n, s)
const CARD h[];
int n, s;
{
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) {
/* try for retaliation to 31 */
for (i = 1; i <= 10; i++) {
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 retaliation after 15 */
for (i = 0; i < NTV; i++) {
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;
/* remember: h is sorted */
for (i = n - 1; i >= 0; --i) {
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
*/
int
plyrhand(hand, s)
const CARD hand[];
const char *s;
{
static char prompt[BUFSIZ];
int i, j;
BOOLEAN win;
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
*/
int
comphand(h, s)
const CARD h[];
const char *s;
{
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};
int
chkscr(scr, inc)
int *scr, inc;
{
BOOLEAN myturn;
myturn = (scr == &cscore);
if (inc != 0) {
prpeg(Lastscore[(int)myturn], '.', myturn);
Lastscore[(int)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.
*/
void
prpeg(score, peg, myturn)
int score;
int peg;
BOOLEAN myturn;
{
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
*/
void
cdiscard(mycrib)
BOOLEAN mycrib;
{
CARD d[CARDS], h[FULLHAND], cb[2];
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
*/
int
anymove(hand, n, sum)
const CARD hand[];
int n, sum;
{
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
*/
int
anysumto(hand, n, s, t)
const CARD hand[];
int n, s, t;
{
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
*/
int
numofval(h, n, v)
const CARD h[];
int n, v;
{
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
*/
void
makeknown(h, n)
const CARD h[];
int n;
{
int i;
for (i = 0; i < n; i++)
known[knownum++] = h[i];
}