Home | History | Annotate | Line # | Download | only in cribbage
crib.c revision 1.24.6.1
      1  1.24.6.1      yamt /*	$NetBSD: crib.c,v 1.24.6.1 2012/10/30 18:58:19 yamt Exp $	*/
      2       1.5       cgd 
      3       1.5       cgd /*-
      4       1.5       cgd  * Copyright (c) 1980, 1993
      5       1.5       cgd  *	The Regents of the University of California.  All rights reserved.
      6       1.1       cgd  *
      7       1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8       1.1       cgd  * modification, are permitted provided that the following conditions
      9       1.1       cgd  * are met:
     10       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15      1.17       agc  * 3. Neither the name of the University nor the names of its contributors
     16       1.1       cgd  *    may be used to endorse or promote products derived from this software
     17       1.1       cgd  *    without specific prior written permission.
     18       1.1       cgd  *
     19       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29       1.1       cgd  * SUCH DAMAGE.
     30       1.1       cgd  */
     31       1.1       cgd 
     32       1.8     lukem #include <sys/cdefs.h>
     33       1.1       cgd #ifndef lint
     34      1.21     lukem __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
     35      1.21     lukem  The Regents of the University of California.  All rights reserved.");
     36       1.1       cgd #endif /* not lint */
     37       1.1       cgd 
     38       1.1       cgd #ifndef lint
     39       1.5       cgd #if 0
     40       1.5       cgd static char sccsid[] = "@(#)crib.c	8.1 (Berkeley) 5/31/93";
     41       1.5       cgd #else
     42  1.24.6.1      yamt __RCSID("$NetBSD: crib.c,v 1.24.6.1 2012/10/30 18:58:19 yamt Exp $");
     43       1.5       cgd #endif
     44       1.1       cgd #endif /* not lint */
     45       1.1       cgd 
     46       1.5       cgd #include <curses.h>
     47       1.9     lukem #include <err.h>
     48      1.12       jsm #include <fcntl.h>
     49       1.5       cgd #include <signal.h>
     50       1.5       cgd #include <stdlib.h>
     51       1.5       cgd #include <string.h>
     52       1.5       cgd #include <unistd.h>
     53       1.5       cgd 
     54       1.5       cgd #include "deck.h"
     55       1.5       cgd #include "cribbage.h"
     56       1.5       cgd #include "cribcur.h"
     57       1.5       cgd #include "pathnames.h"
     58       1.1       cgd 
     59      1.24  dholland static void makeboard(void);
     60      1.24  dholland static void gamescore(void);
     61      1.24  dholland static void game(void);
     62      1.24  dholland static int playhand(BOOLEAN);
     63      1.24  dholland static int deal(BOOLEAN);
     64      1.24  dholland static void discard(BOOLEAN);
     65      1.24  dholland static int cut(BOOLEAN, int);
     66      1.24  dholland static void prcrib(BOOLEAN, BOOLEAN);
     67      1.24  dholland static int peg(BOOLEAN);
     68      1.24  dholland static void prtable(int);
     69      1.24  dholland static int score(BOOLEAN);
     70      1.24  dholland 
     71       1.5       cgd int
     72      1.20       jmc main(int argc, char *argv[])
     73       1.1       cgd {
     74       1.5       cgd 	BOOLEAN playing;
     75       1.5       cgd 	FILE *f;
     76       1.1       cgd 	int ch;
     77      1.12       jsm 	int fd;
     78      1.12       jsm 	int flags;
     79      1.12       jsm 
     80      1.12       jsm 	f = fopen(_PATH_LOG, "a");
     81      1.12       jsm 	if (f == NULL)
     82      1.12       jsm 		warn("fopen %s", _PATH_LOG);
     83      1.12       jsm 	if (f != NULL && fileno(f) < 3)
     84      1.12       jsm 		exit(1);
     85      1.12       jsm 
     86      1.12       jsm 	/* Revoke setgid privileges */
     87      1.13   mycroft 	setgid(getgid());
     88      1.12       jsm 
     89      1.12       jsm 	/* Set close-on-exec flag on log file */
     90      1.12       jsm 	if (f != NULL) {
     91      1.12       jsm 		fd = fileno(f);
     92      1.12       jsm 		flags = fcntl(fd, F_GETFD);
     93      1.12       jsm 		if (flags < 0)
     94      1.12       jsm 			err(1, "fcntl F_GETFD");
     95      1.12       jsm 		flags |= FD_CLOEXEC;
     96      1.12       jsm 		if (fcntl(fd, F_SETFD, flags) == -1)
     97      1.12       jsm 			err(1, "fcntl F_SETFD");
     98      1.12       jsm 	}
     99       1.1       cgd 
    100       1.8     lukem 	while ((ch = getopt(argc, argv, "eqr")) != -1)
    101       1.5       cgd 		switch (ch) {
    102       1.1       cgd 		case 'e':
    103       1.1       cgd 			explain = TRUE;
    104       1.1       cgd 			break;
    105       1.1       cgd 		case 'q':
    106       1.1       cgd 			quiet = TRUE;
    107       1.1       cgd 			break;
    108       1.1       cgd 		case 'r':
    109       1.1       cgd 			rflag = TRUE;
    110       1.1       cgd 			break;
    111       1.1       cgd 		case '?':
    112       1.1       cgd 		default:
    113       1.1       cgd 			(void) fprintf(stderr, "usage: cribbage [-eqr]\n");
    114       1.1       cgd 			exit(1);
    115       1.1       cgd 		}
    116       1.1       cgd 
    117      1.22  drochner 	if (!initscr())
    118      1.22  drochner 		errx(0, "couldn't initialize screen");
    119      1.18       jsm 	(void)signal(SIGINT, receive_intr);
    120      1.15     blymn 	cbreak();
    121       1.1       cgd 	noecho();
    122       1.5       cgd 
    123       1.1       cgd 	Playwin = subwin(stdscr, PLAY_Y, PLAY_X, 0, 0);
    124       1.1       cgd 	Tablewin = subwin(stdscr, TABLE_Y, TABLE_X, 0, PLAY_X);
    125       1.1       cgd 	Compwin = subwin(stdscr, COMP_Y, COMP_X, 0, TABLE_X + PLAY_X);
    126       1.1       cgd 	Msgwin = subwin(stdscr, MSG_Y, MSG_X, Y_MSG_START, SCORE_X + 1);
    127       1.1       cgd 	leaveok(Playwin, TRUE);
    128       1.1       cgd 	leaveok(Tablewin, TRUE);
    129       1.1       cgd 	leaveok(Compwin, TRUE);
    130       1.1       cgd 	clearok(stdscr, FALSE);
    131       1.1       cgd 
    132       1.1       cgd 	if (!quiet) {
    133       1.5       cgd 		msg("Do you need instructions for cribbage? ");
    134       1.5       cgd 		if (getuchar() == 'Y') {
    135       1.5       cgd 			endwin();
    136       1.5       cgd 			clear();
    137       1.5       cgd 			mvcur(0, COLS - 1, LINES - 1, 0);
    138       1.5       cgd 			fflush(stdout);
    139       1.5       cgd 			instructions();
    140      1.16     blymn 			cbreak();
    141       1.5       cgd 			noecho();
    142       1.5       cgd 			clear();
    143       1.5       cgd 			refresh();
    144       1.5       cgd 			msg("For cribbage rules, use \"man cribbage\"");
    145       1.5       cgd 		}
    146       1.1       cgd 	}
    147       1.1       cgd 	playing = TRUE;
    148       1.1       cgd 	do {
    149       1.5       cgd 		wclrtobot(Msgwin);
    150       1.5       cgd 		msg(quiet ? "L or S? " : "Long (to 121) or Short (to 61)? ");
    151       1.5       cgd 		if (glimit == SGAME)
    152       1.5       cgd 			glimit = (getuchar() == 'L' ? LGAME : SGAME);
    153       1.5       cgd 		else
    154       1.5       cgd 			glimit = (getuchar() == 'S' ? SGAME : LGAME);
    155       1.5       cgd 		game();
    156       1.5       cgd 		msg("Another game? ");
    157       1.5       cgd 		playing = (getuchar() == 'Y');
    158       1.1       cgd 	} while (playing);
    159       1.1       cgd 
    160      1.12       jsm 	if (f != NULL) {
    161       1.1       cgd 		(void)fprintf(f, "%s: won %5.5d, lost %5.5d\n",
    162       1.5       cgd 		    getlogin(), cgames, pgames);
    163       1.5       cgd 		(void) fclose(f);
    164       1.1       cgd 	}
    165       1.1       cgd 	bye();
    166       1.1       cgd 	exit(0);
    167       1.1       cgd }
    168       1.1       cgd 
    169       1.1       cgd /*
    170       1.1       cgd  * makeboard:
    171       1.1       cgd  *	Print out the initial board on the screen
    172       1.1       cgd  */
    173      1.24  dholland static void
    174      1.20       jmc makeboard(void)
    175       1.1       cgd {
    176       1.5       cgd 	mvaddstr(SCORE_Y + 0, SCORE_X,
    177       1.5       cgd 	    "+---------------------------------------+");
    178       1.5       cgd 	mvaddstr(SCORE_Y + 1, SCORE_X,
    179       1.5       cgd 	    "|  Score:   0     YOU                   |");
    180       1.5       cgd 	mvaddstr(SCORE_Y + 2, SCORE_X,
    181       1.5       cgd 	    "| *.....:.....:.....:.....:.....:.....  |");
    182       1.5       cgd 	mvaddstr(SCORE_Y + 3, SCORE_X,
    183       1.5       cgd 	    "| *.....:.....:.....:.....:.....:.....  |");
    184       1.5       cgd 	mvaddstr(SCORE_Y + 4, SCORE_X,
    185       1.5       cgd 	    "|                                       |");
    186       1.5       cgd 	mvaddstr(SCORE_Y + 5, SCORE_X,
    187       1.5       cgd 	    "| *.....:.....:.....:.....:.....:.....  |");
    188       1.5       cgd 	mvaddstr(SCORE_Y + 6, SCORE_X,
    189       1.5       cgd 	    "| *.....:.....:.....:.....:.....:.....  |");
    190       1.5       cgd 	mvaddstr(SCORE_Y + 7, SCORE_X,
    191       1.5       cgd 	    "|  Score:   0      ME                   |");
    192       1.5       cgd 	mvaddstr(SCORE_Y + 8, SCORE_X,
    193       1.5       cgd 	    "+---------------------------------------+");
    194       1.5       cgd 	gamescore();
    195       1.1       cgd }
    196       1.1       cgd 
    197       1.1       cgd /*
    198       1.1       cgd  * gamescore:
    199       1.1       cgd  *	Print out the current game score
    200       1.1       cgd  */
    201      1.24  dholland static void
    202      1.20       jmc gamescore(void)
    203       1.1       cgd {
    204       1.5       cgd 	if (pgames || cgames) {
    205       1.5       cgd 		mvprintw(SCORE_Y + 1, SCORE_X + 28, "Games: %3d", pgames);
    206       1.5       cgd 		mvprintw(SCORE_Y + 7, SCORE_X + 28, "Games: %3d", cgames);
    207       1.5       cgd 	}
    208       1.5       cgd 	Lastscore[0] = -1;
    209       1.5       cgd 	Lastscore[1] = -1;
    210       1.1       cgd }
    211       1.1       cgd 
    212       1.1       cgd /*
    213       1.1       cgd  * game:
    214       1.1       cgd  *	Play one game up to glimit points.  Actually, we only ASK the
    215       1.1       cgd  *	player what card to turn.  We do a random one, anyway.
    216       1.1       cgd  */
    217      1.24  dholland static void
    218      1.20       jmc game(void)
    219       1.1       cgd {
    220       1.8     lukem 	int i, j;
    221       1.5       cgd 	BOOLEAN flag;
    222       1.5       cgd 	BOOLEAN compcrib;
    223       1.1       cgd 
    224       1.8     lukem 	compcrib = FALSE;
    225       1.1       cgd 	makedeck(deck);
    226       1.1       cgd 	shuffle(deck);
    227       1.1       cgd 	if (gamecount == 0) {
    228       1.5       cgd 		flag = TRUE;
    229       1.5       cgd 		do {
    230       1.5       cgd 			if (!rflag) {			/* player cuts deck */
    231       1.5       cgd 				msg(quiet ? "Cut for crib? " :
    232       1.5       cgd 			    "Cut to see whose crib it is -- low card wins? ");
    233      1.23       roy 				get_line();
    234       1.5       cgd 			}
    235       1.5       cgd 			i = (rand() >> 4) % CARDS;	/* random cut */
    236       1.5       cgd 			do {	/* comp cuts deck */
    237       1.5       cgd 				j = (rand() >> 4) % CARDS;
    238       1.5       cgd 			} while (j == i);
    239       1.5       cgd 			addmsg(quiet ? "You cut " : "You cut the ");
    240       1.5       cgd 			msgcard(deck[i], FALSE);
    241       1.5       cgd 			endmsg();
    242       1.5       cgd 			addmsg(quiet ? "I cut " : "I cut the ");
    243       1.5       cgd 			msgcard(deck[j], FALSE);
    244       1.5       cgd 			endmsg();
    245       1.5       cgd 			flag = (deck[i].rank == deck[j].rank);
    246       1.5       cgd 			if (flag) {
    247       1.5       cgd 				msg(quiet ? "We tied..." :
    248       1.5       cgd 				    "We tied and have to try again...");
    249       1.5       cgd 				shuffle(deck);
    250       1.5       cgd 				continue;
    251       1.5       cgd 			} else
    252       1.5       cgd 				compcrib = (deck[i].rank > deck[j].rank);
    253       1.5       cgd 		} while (flag);
    254       1.6      phil 		do_wait();
    255       1.5       cgd 		clear();
    256       1.5       cgd 		makeboard();
    257       1.5       cgd 		refresh();
    258       1.5       cgd 	} else {
    259       1.6      phil 		makeboard();
    260       1.6      phil 		refresh();
    261       1.5       cgd 		werase(Tablewin);
    262       1.5       cgd 		wrefresh(Tablewin);
    263       1.5       cgd 		werase(Compwin);
    264       1.5       cgd 		wrefresh(Compwin);
    265       1.5       cgd 		msg("Loser (%s) gets first crib", (iwon ? "you" : "me"));
    266       1.5       cgd 		compcrib = !iwon;
    267       1.1       cgd 	}
    268       1.1       cgd 
    269       1.1       cgd 	pscore = cscore = 0;
    270       1.1       cgd 	flag = TRUE;
    271       1.1       cgd 	do {
    272       1.5       cgd 		shuffle(deck);
    273       1.5       cgd 		flag = !playhand(compcrib);
    274       1.5       cgd 		compcrib = !compcrib;
    275       1.1       cgd 	} while (flag);
    276       1.1       cgd 	++gamecount;
    277       1.1       cgd 	if (cscore < pscore) {
    278       1.5       cgd 		if (glimit - cscore > 60) {
    279       1.5       cgd 			msg("YOU DOUBLE SKUNKED ME!");
    280       1.5       cgd 			pgames += 4;
    281       1.5       cgd 		} else
    282       1.5       cgd 			if (glimit - cscore > 30) {
    283       1.5       cgd 				msg("YOU SKUNKED ME!");
    284       1.5       cgd 				pgames += 2;
    285       1.5       cgd 			} else {
    286       1.5       cgd 				msg("YOU WON!");
    287       1.5       cgd 				++pgames;
    288       1.5       cgd 			}
    289       1.5       cgd 		iwon = FALSE;
    290       1.5       cgd 	} else {
    291       1.5       cgd 		if (glimit - pscore > 60) {
    292       1.5       cgd 			msg("I DOUBLE SKUNKED YOU!");
    293       1.5       cgd 			cgames += 4;
    294       1.5       cgd 		} else
    295       1.5       cgd 			if (glimit - pscore > 30) {
    296       1.5       cgd 				msg("I SKUNKED YOU!");
    297       1.5       cgd 				cgames += 2;
    298       1.5       cgd 			} else {
    299       1.5       cgd 				msg("I WON!");
    300       1.5       cgd 				++cgames;
    301       1.5       cgd 			}
    302       1.5       cgd 		iwon = TRUE;
    303       1.1       cgd 	}
    304       1.1       cgd 	gamescore();
    305       1.1       cgd }
    306       1.1       cgd 
    307       1.1       cgd /*
    308       1.1       cgd  * playhand:
    309       1.1       cgd  *	Do up one hand of the game
    310       1.1       cgd  */
    311      1.24  dholland static int
    312      1.20       jmc playhand(BOOLEAN mycrib)
    313       1.1       cgd {
    314       1.8     lukem 	int deckpos;
    315       1.1       cgd 
    316       1.1       cgd 	werase(Compwin);
    317       1.6      phil 	wrefresh(Compwin);
    318       1.6      phil 	werase(Tablewin);
    319       1.6      phil 	wrefresh(Tablewin);
    320       1.1       cgd 
    321       1.1       cgd 	knownum = 0;
    322       1.1       cgd 	deckpos = deal(mycrib);
    323       1.1       cgd 	sorthand(chand, FULLHAND);
    324       1.1       cgd 	sorthand(phand, FULLHAND);
    325       1.1       cgd 	makeknown(chand, FULLHAND);
    326       1.1       cgd 	prhand(phand, FULLHAND, Playwin, FALSE);
    327       1.1       cgd 	discard(mycrib);
    328       1.1       cgd 	if (cut(mycrib, deckpos))
    329       1.5       cgd 		return TRUE;
    330       1.1       cgd 	if (peg(mycrib))
    331       1.5       cgd 		return TRUE;
    332       1.1       cgd 	werase(Tablewin);
    333       1.1       cgd 	wrefresh(Tablewin);
    334       1.1       cgd 	if (score(mycrib))
    335       1.5       cgd 		return TRUE;
    336       1.1       cgd 	return FALSE;
    337       1.1       cgd }
    338       1.1       cgd 
    339       1.1       cgd /*
    340       1.1       cgd  * deal cards to both players from deck
    341       1.1       cgd  */
    342      1.24  dholland static int
    343      1.20       jmc deal(BOOLEAN mycrib)
    344       1.5       cgd {
    345       1.8     lukem 	int i, j;
    346       1.5       cgd 
    347       1.5       cgd 	for (i = j = 0; i < FULLHAND; i++) {
    348       1.5       cgd 		if (mycrib) {
    349       1.5       cgd 			phand[i] = deck[j++];
    350       1.5       cgd 			chand[i] = deck[j++];
    351       1.5       cgd 		} else {
    352       1.5       cgd 			chand[i] = deck[j++];
    353       1.5       cgd 			phand[i] = deck[j++];
    354       1.5       cgd 		}
    355       1.1       cgd 	}
    356       1.5       cgd 	return (j);
    357       1.1       cgd }
    358       1.1       cgd 
    359       1.1       cgd /*
    360       1.1       cgd  * discard:
    361       1.1       cgd  *	Handle players discarding into the crib...
    362       1.1       cgd  * Note: we call cdiscard() after prining first message so player doesn't wait
    363       1.1       cgd  */
    364      1.24  dholland static void
    365      1.20       jmc discard(BOOLEAN mycrib)
    366       1.1       cgd {
    367      1.11       jsm 	const char *prompt;
    368       1.5       cgd 	CARD crd;
    369       1.1       cgd 
    370       1.1       cgd 	prcrib(mycrib, TRUE);
    371       1.1       cgd 	prompt = (quiet ? "Discard --> " : "Discard a card --> ");
    372       1.5       cgd 	cdiscard(mycrib);	/* puts best discard at end */
    373       1.1       cgd 	crd = phand[infrom(phand, FULLHAND, prompt)];
    374       1.1       cgd 	cremove(crd, phand, FULLHAND);
    375       1.1       cgd 	prhand(phand, FULLHAND, Playwin, FALSE);
    376       1.1       cgd 	crib[0] = crd;
    377       1.5       cgd 
    378       1.5       cgd 	/* Next four lines same as last four except for cdiscard(). */
    379       1.1       cgd 	crd = phand[infrom(phand, FULLHAND - 1, prompt)];
    380       1.1       cgd 	cremove(crd, phand, FULLHAND - 1);
    381       1.1       cgd 	prhand(phand, FULLHAND, Playwin, FALSE);
    382       1.1       cgd 	crib[1] = crd;
    383       1.1       cgd 	crib[2] = chand[4];
    384       1.1       cgd 	crib[3] = chand[5];
    385       1.1       cgd 	chand[4].rank = chand[4].suit = chand[5].rank = chand[5].suit = EMPTY;
    386       1.1       cgd }
    387       1.1       cgd 
    388       1.1       cgd /*
    389       1.1       cgd  * cut:
    390       1.1       cgd  *	Cut the deck and set turnover.  Actually, we only ASK the
    391       1.1       cgd  *	player what card to turn.  We do a random one, anyway.
    392       1.1       cgd  */
    393      1.24  dholland static int
    394      1.20       jmc cut(BOOLEAN mycrib, int  pos)
    395       1.1       cgd {
    396       1.8     lukem 	int i;
    397       1.5       cgd 	BOOLEAN win;
    398       1.1       cgd 
    399       1.5       cgd 	win = FALSE;
    400       1.1       cgd 	if (mycrib) {
    401       1.5       cgd 		if (!rflag) {	/* random cut */
    402       1.5       cgd 			msg(quiet ? "Cut the deck? " :
    403       1.5       cgd 		    "How many cards down do you wish to cut the deck? ");
    404      1.23       roy 			get_line();
    405       1.5       cgd 		}
    406       1.5       cgd 		i = (rand() >> 4) % (CARDS - pos);
    407       1.5       cgd 		turnover = deck[i + pos];
    408       1.5       cgd 		addmsg(quiet ? "You cut " : "You cut the ");
    409       1.5       cgd 		msgcard(turnover, FALSE);
    410       1.5       cgd 		endmsg();
    411       1.5       cgd 		if (turnover.rank == JACK) {
    412       1.5       cgd 			msg("I get two for his heels");
    413       1.5       cgd 			win = chkscr(&cscore, 2);
    414       1.5       cgd 		}
    415       1.5       cgd 	} else {
    416       1.5       cgd 		i = (rand() >> 4) % (CARDS - pos) + pos;
    417       1.5       cgd 		turnover = deck[i];
    418       1.5       cgd 		addmsg(quiet ? "I cut " : "I cut the ");
    419       1.5       cgd 		msgcard(turnover, FALSE);
    420       1.5       cgd 		endmsg();
    421       1.5       cgd 		if (turnover.rank == JACK) {
    422       1.5       cgd 			msg("You get two for his heels");
    423       1.5       cgd 			win = chkscr(&pscore, 2);
    424       1.5       cgd 		}
    425       1.1       cgd 	}
    426       1.1       cgd 	makeknown(&turnover, 1);
    427       1.1       cgd 	prcrib(mycrib, FALSE);
    428       1.5       cgd 	return (win);
    429       1.1       cgd }
    430       1.1       cgd 
    431       1.1       cgd /*
    432       1.1       cgd  * prcrib:
    433       1.1       cgd  *	Print out the turnover card with crib indicator
    434       1.1       cgd  */
    435      1.24  dholland static void
    436      1.20       jmc prcrib(BOOLEAN mycrib, BOOLEAN blank)
    437       1.1       cgd {
    438       1.8     lukem 	int y, cardx;
    439       1.1       cgd 
    440       1.1       cgd 	if (mycrib)
    441       1.5       cgd 		cardx = CRIB_X;
    442       1.1       cgd 	else
    443       1.5       cgd 		cardx = 0;
    444       1.1       cgd 
    445       1.1       cgd 	mvaddstr(CRIB_Y, cardx + 1, "CRIB");
    446       1.1       cgd 	prcard(stdscr, CRIB_Y + 1, cardx, turnover, blank);
    447       1.1       cgd 
    448       1.1       cgd 	if (mycrib)
    449       1.5       cgd 		cardx = 0;
    450       1.1       cgd 	else
    451       1.5       cgd 		cardx = CRIB_X;
    452       1.1       cgd 
    453       1.1       cgd 	for (y = CRIB_Y; y <= CRIB_Y + 5; y++)
    454       1.5       cgd 		mvaddstr(y, cardx, "       ");
    455       1.6      phil 	refresh();
    456       1.1       cgd }
    457       1.1       cgd 
    458       1.1       cgd /*
    459       1.1       cgd  * peg:
    460       1.1       cgd  *	Handle all the pegging...
    461       1.1       cgd  */
    462       1.5       cgd static CARD Table[14];
    463  1.24.6.1      yamt static unsigned Tcnt;
    464       1.1       cgd 
    465      1.24  dholland static int
    466      1.20       jmc peg(BOOLEAN mycrib)
    467       1.1       cgd {
    468       1.5       cgd 	static CARD ch[CINHAND], ph[CINHAND];
    469       1.8     lukem 	int i, j, k;
    470       1.8     lukem 	int l;
    471       1.8     lukem 	int cnum, pnum, sum;
    472       1.8     lukem 	BOOLEAN myturn, mego, ugo, last, played;
    473       1.5       cgd 	CARD crd;
    474       1.1       cgd 
    475       1.8     lukem 	played = FALSE;
    476       1.1       cgd 	cnum = pnum = CINHAND;
    477       1.5       cgd 	for (i = 0; i < CINHAND; i++) {	/* make copies of hands */
    478       1.5       cgd 		ch[i] = chand[i];
    479       1.5       cgd 		ph[i] = phand[i];
    480       1.1       cgd 	}
    481       1.5       cgd 	Tcnt = 0;		/* index to table of cards played */
    482       1.5       cgd 	sum = 0;		/* sum of cards played */
    483       1.1       cgd 	mego = ugo = FALSE;
    484       1.1       cgd 	myturn = !mycrib;
    485       1.1       cgd 	for (;;) {
    486       1.5       cgd 		last = TRUE;	/* enable last flag */
    487       1.5       cgd 		prhand(ph, pnum, Playwin, FALSE);
    488       1.5       cgd 		prhand(ch, cnum, Compwin, TRUE);
    489       1.5       cgd 		prtable(sum);
    490       1.5       cgd 		if (myturn) {	/* my tyrn to play */
    491       1.5       cgd 			if (!anymove(ch, cnum, sum)) {	/* if no card to play */
    492       1.5       cgd 				if (!mego && cnum) {	/* go for comp? */
    493       1.5       cgd 					msg("GO");
    494       1.5       cgd 					mego = TRUE;
    495       1.5       cgd 				}
    496       1.5       cgd 							/* can player move? */
    497       1.5       cgd 				if (anymove(ph, pnum, sum))
    498       1.5       cgd 					myturn = !myturn;
    499       1.5       cgd 				else {			/* give him his point */
    500       1.5       cgd 					msg(quiet ? "You get one" :
    501       1.5       cgd 					    "You get one point");
    502       1.6      phil 					do_wait();
    503       1.5       cgd 					if (chkscr(&pscore, 1))
    504       1.5       cgd 						return TRUE;
    505       1.5       cgd 					sum = 0;
    506       1.5       cgd 					mego = ugo = FALSE;
    507       1.5       cgd 					Tcnt = 0;
    508       1.5       cgd 				}
    509       1.5       cgd 			} else {
    510       1.5       cgd 				played = TRUE;
    511       1.5       cgd 				j = -1;
    512       1.5       cgd 				k = 0;
    513       1.5       cgd 							/* maximize score */
    514       1.5       cgd 				for (i = 0; i < cnum; i++) {
    515       1.5       cgd 					l = pegscore(ch[i], Table, Tcnt, sum);
    516       1.5       cgd 					if (l > k) {
    517       1.5       cgd 						k = l;
    518       1.5       cgd 						j = i;
    519       1.5       cgd 					}
    520       1.5       cgd 				}
    521       1.5       cgd 				if (j < 0)		/* if nothing scores */
    522       1.5       cgd 					j = cchose(ch, cnum, sum);
    523       1.5       cgd 				crd = ch[j];
    524       1.5       cgd 				cremove(crd, ch, cnum--);
    525       1.5       cgd 				sum += VAL(crd.rank);
    526       1.5       cgd 				Table[Tcnt++] = crd;
    527       1.5       cgd 				if (k > 0) {
    528       1.5       cgd 					addmsg(quiet ? "I get %d playing " :
    529       1.5       cgd 					    "I get %d points playing ", k);
    530       1.5       cgd 					msgcard(crd, FALSE);
    531       1.5       cgd 					endmsg();
    532       1.5       cgd 					if (chkscr(&cscore, k))
    533       1.5       cgd 						return TRUE;
    534       1.5       cgd 				}
    535       1.5       cgd 				myturn = !myturn;
    536       1.5       cgd 			}
    537       1.5       cgd 		} else {
    538       1.5       cgd 			if (!anymove(ph, pnum, sum)) {	/* can player move? */
    539       1.5       cgd 				if (!ugo && pnum) {	/* go for player */
    540       1.5       cgd 					msg("You have a GO");
    541       1.5       cgd 					ugo = TRUE;
    542       1.5       cgd 				}
    543       1.5       cgd 							/* can computer play? */
    544       1.5       cgd 				if (anymove(ch, cnum, sum))
    545       1.5       cgd 					myturn = !myturn;
    546       1.5       cgd 				else {
    547       1.5       cgd 					msg(quiet ? "I get one" :
    548       1.5       cgd 					    "I get one point");
    549       1.5       cgd 					do_wait();
    550       1.5       cgd 					if (chkscr(&cscore, 1))
    551       1.5       cgd 						return TRUE;
    552       1.5       cgd 					sum = 0;
    553       1.5       cgd 					mego = ugo = FALSE;
    554       1.5       cgd 					Tcnt = 0;
    555       1.5       cgd 				}
    556       1.5       cgd 			} else {			/* player plays */
    557       1.5       cgd 				played = FALSE;
    558       1.5       cgd 				if (pnum == 1) {
    559       1.5       cgd 					crd = ph[0];
    560       1.5       cgd 					msg("You play your last card");
    561       1.5       cgd 				} else
    562       1.5       cgd 					for (;;) {
    563       1.5       cgd 						prhand(ph,
    564       1.5       cgd 						    pnum, Playwin, FALSE);
    565       1.5       cgd 						crd = ph[infrom(ph,
    566       1.5       cgd 						    pnum, "Your play: ")];
    567       1.5       cgd 						if (sum + VAL(crd.rank) <= 31)
    568       1.5       cgd 							break;
    569       1.5       cgd 						else
    570       1.5       cgd 					msg("Total > 31 -- try again");
    571       1.5       cgd 					}
    572       1.5       cgd 				makeknown(&crd, 1);
    573       1.5       cgd 				cremove(crd, ph, pnum--);
    574       1.5       cgd 				i = pegscore(crd, Table, Tcnt, sum);
    575       1.5       cgd 				sum += VAL(crd.rank);
    576       1.5       cgd 				Table[Tcnt++] = crd;
    577       1.5       cgd 				if (i > 0) {
    578       1.5       cgd 					msg(quiet ? "You got %d" :
    579       1.5       cgd 					    "You got %d points", i);
    580       1.6      phil 					if (pnum == 0)
    581       1.6      phil 						do_wait();
    582       1.5       cgd 					if (chkscr(&pscore, i))
    583       1.5       cgd 						return TRUE;
    584       1.5       cgd 				}
    585       1.5       cgd 				myturn = !myturn;
    586       1.1       cgd 			}
    587       1.1       cgd 		}
    588       1.5       cgd 		if (sum >= 31) {
    589       1.5       cgd 			if (!myturn)
    590       1.5       cgd 				do_wait();
    591       1.1       cgd 			sum = 0;
    592       1.1       cgd 			mego = ugo = FALSE;
    593       1.1       cgd 			Tcnt = 0;
    594       1.5       cgd 			last = FALSE;			/* disable last flag */
    595       1.1       cgd 		}
    596       1.5       cgd 		if (!pnum && !cnum)
    597       1.5       cgd 			break;				/* both done */
    598       1.1       cgd 	}
    599       1.1       cgd 	prhand(ph, pnum, Playwin, FALSE);
    600       1.1       cgd 	prhand(ch, cnum, Compwin, TRUE);
    601       1.1       cgd 	prtable(sum);
    602      1.10     veego 	if (last) {
    603       1.5       cgd 		if (played) {
    604       1.5       cgd 			msg(quiet ? "I get one for last" :
    605       1.5       cgd 			    "I get one point for last");
    606       1.5       cgd 			do_wait();
    607       1.5       cgd 			if (chkscr(&cscore, 1))
    608       1.5       cgd 				return TRUE;
    609       1.5       cgd 		} else {
    610       1.5       cgd 			msg(quiet ? "You get one for last" :
    611       1.1       cgd 			    "You get one point for last");
    612       1.6      phil 			do_wait();
    613       1.5       cgd 			if (chkscr(&pscore, 1))
    614       1.5       cgd 				return TRUE;
    615       1.5       cgd 		}
    616      1.10     veego 	}
    617       1.5       cgd 	return (FALSE);
    618       1.1       cgd }
    619       1.1       cgd 
    620       1.1       cgd /*
    621       1.1       cgd  * prtable:
    622       1.1       cgd  *	Print out the table with the current score
    623       1.1       cgd  */
    624      1.24  dholland static void
    625      1.20       jmc prtable(int curscore)
    626       1.1       cgd {
    627       1.1       cgd 	prhand(Table, Tcnt, Tablewin, FALSE);
    628      1.20       jmc 	mvwprintw(Tablewin, (Tcnt + 2) * 2, Tcnt + 1, "%2d", curscore);
    629       1.1       cgd 	wrefresh(Tablewin);
    630       1.1       cgd }
    631       1.1       cgd 
    632       1.1       cgd /*
    633       1.1       cgd  * score:
    634       1.1       cgd  *	Handle the scoring of the hands
    635       1.1       cgd  */
    636      1.24  dholland static int
    637      1.20       jmc score(BOOLEAN mycrib)
    638       1.1       cgd {
    639       1.1       cgd 	sorthand(crib, CINHAND);
    640       1.1       cgd 	if (mycrib) {
    641       1.5       cgd 		if (plyrhand(phand, "hand"))
    642       1.5       cgd 			return (TRUE);
    643       1.5       cgd 		if (comphand(chand, "hand"))
    644       1.5       cgd 			return (TRUE);
    645       1.5       cgd 		do_wait();
    646       1.5       cgd 		if (comphand(crib, "crib"))
    647       1.5       cgd 			return (TRUE);
    648       1.6      phil 		do_wait();
    649       1.5       cgd 	} else {
    650       1.5       cgd 		if (comphand(chand, "hand"))
    651       1.5       cgd 			return (TRUE);
    652       1.5       cgd 		if (plyrhand(phand, "hand"))
    653       1.5       cgd 			return (TRUE);
    654       1.5       cgd 		if (plyrhand(crib, "crib"))
    655       1.5       cgd 			return (TRUE);
    656       1.1       cgd 	}
    657       1.5       cgd 	return (FALSE);
    658       1.1       cgd }
    659