4.1cBSD/usr/src/games/cribbage/crib.c

Compare this file to the similar file:
Show the results in this format:

static char sccsid[] = "	crib.c	1.1	82/05/12	";

#include	<stdio.h>
#include	"deck.h"


#define		LOGFILE		"/usr/games/lib/criblog"
#define		INSTRCMD	"ul /usr/games/lib/crib.instr | more -f"


CARD		deck[ CARDS ];			/* a deck */
CARD		phand[ FULLHAND ];		/* player's hand */
CARD		chand[ FULLHAND ];		/* computer's hand */
CARD		crib[ CINHAND ];		/* the crib */
CARD		turnover;			/* the starter */

CARD		known[ CARDS ];			/* cards we have seen */
int		knownum		= 0;		/* number of cards we know */

int		pscore		= 0;		/* player score in current game */
int		cscore		= 0;		/* comp score in current game */
int		pgames		= 0;		/* number games player won */
int		cgames		= 0;		/* number games comp won */
int		gamecount	= 0;		/* number games played */
int		glimit		= LGAME;	/* game playe to glimit */

BOOLEAN		iwon		= FALSE;	/* if comp won last game */
BOOLEAN		explain		= FALSE;	/* player mistakes explained */
BOOLEAN		rflag		= FALSE;	/* if all cuts random */
BOOLEAN		quiet		= FALSE;	/* if suppress random mess */

char		expl[ 128 ];			/* explanation */


main( argc, argv )

    int		argc;
    char	*argv[];
{
	FILE			*fopen();
	FILE			*f;
	char			*getline();
	register  char		*p;
	BOOLEAN			playing;
	char			*s;		/* for reading arguments */
	char			bust;		/* flag for arg reader */

	while( --argc > 0 )  {
	    if(  (*++argv)[0] != '-'  )  {
		fprintf( stderr, "\n\ncribbage: usage is 'cribbage [-eqr]'\n" );
		exit( 1 );
	    }
	    bust = FALSE;
	    for( s = argv[0] + 1; *s != NULL; s++ ) {
		switch( *s )  {

		    case  'e':
			explain = TRUE;
			break;

		    case  'q':
			quiet = TRUE;
			break;

		    case  'r':
			rflag = TRUE;
			break;

		    default:
			fprintf( stderr, "\n\ncribbage: usage is 'cribbage [-eqr]'\n" );
			exit( 2 );
			break;
		}
		if( bust )  break;
	    }
	}
	if( !quiet )  {
	    printf( "\nDo you need instructions for cribbage? " );
	    p = getline();
	    if(  *p == 'Y'  )  {
		system( INSTRCMD );
		printf( "\nFor the rules of this game, do 'man cribbage'\n" );
	    }
	}
	playing = TRUE;
	do  {
	    printf( quiet ? "\nL or S? " :
				"\nLong (to 121) or Short (to 61)? " );
	    p = getline();
	    glimit = ( *p == 'S' ? SGAME : LGAME );
	    game();
	    printf( "\nAnother game? " );
	    p = getline();
	    playing = (*p == 'Y');
	}  while( playing );
	if(  ( f = fopen(LOGFILE, "a") ) != NULL  )  {
	    fprintf( f, "Won %5.5d, Lost %5.5d\n",  cgames, pgames );
	    fclose( f );
	}
}



/*
 * play one game up to glimit points
 */

game()
{
	register  int		i, j;
	BOOLEAN			flag;
	BOOLEAN			compcrib;

	makedeck( deck );
	shuffle( deck );
	if( gamecount == 0 )  {
	    flag = TRUE;
	    do  {
		if( rflag )  {				/* player cuts deck */
		    i = ( rand() >>4 ) % CARDS;		/* random cut */
		}
		else  {
		    printf( quiet ? "\nCut for crib? " :
			"\nCut to see whose crib it is -- low card wins? " );
		    i = number( 0, CARDS - 1 );
		}
		do  {					/* comp cuts deck */
		    j = ( rand() >> 4 ) % CARDS;
		}  while( j == i );
		printf( quiet ? "You cut " : "You cut the " );
		printcard( deck[i], FALSE );
		printf( quiet ? ", I cut " : ",  I cut the " );
		printcard( deck[j], FALSE );
		printf( ".\n" );
		flag = ( deck[i].rank == deck[j].rank );
		if( flag )  {
		    printf( quiet ? "We tied...\n" :
				"We tied and have to try again...\n" );
		    shuffle( deck );
		    continue;
		}
		else  {
		    compcrib = deck[i].rank > deck[j].rank;
		}
	    }  while( flag );
	}
	else  {
	    printf( "Loser (%s) gets first crib.\n",  (iwon ? "you" : "me") );
	    compcrib = !iwon;
	}
	pscore = cscore = 0;
	flag = TRUE;
	do  {
	    shuffle( deck );
	    flag = !playhand( compcrib );
	    compcrib = !compcrib;
	    printf( "\nYou have %d points, I have %d.\n", pscore, cscore );
	}  while( flag );
	++gamecount;
	if(  cscore < pscore  )  {
	    if(  glimit - cscore > 30  )  {
		if(  glimit - cscore > 60  )  {
		    printf( "\nYOU DOUBLE SKUNKED ME!\n\n" );
		    pgames += 4;
		}
		else  {
		    printf( "\nYOU SKUNKED ME!\n\n" );
		    pgames += 2;
		}
	    }
	    else  {
		printf( "\nYOU WON!\n\n" );
		++pgames;
	    }
	    iwon = FALSE;
	}
	else  {
	    if(  glimit - pscore > 30  )  {
		if(  glimit - pscore > 60  )  {
		    printf( "\nI DOUBLE SKUNKED YOU!\n\n" );
		    cgames += 4;
		}
		else  {
		    printf( "\nI SKUNKED YOU!\n\n" );
		    cgames += 2;
		}
	    }
	    else  {
		printf( "\nI WON!\n\n" );
		++cgames;
	    }
	    iwon = TRUE;
	}
	printf( "\nI have won %d games, you have won %d\n", cgames, pgames );
}



/*
 * hand does up one hand of the game
 */

playhand( mycrib )

    BOOLEAN		mycrib;
{
	register  int			deckpos;

	knownum = 0;
	deckpos = deal( mycrib );
	sorthand( chand, FULLHAND );
	sorthand( phand, FULLHAND );
	makeknown( chand, FULLHAND );
	printf( "\nYour hand is: " );
	prhand( phand, FULLHAND, TRUE );
	printf( ".\n" );
	discard( mycrib );
	if(  cut( mycrib, deckpos )  )  return( TRUE );
	if(  peg( mycrib )  )  return( TRUE );
	if(  score( mycrib )  )  return( TRUE );
	return( FALSE );
}



/*
 * deal cards to both players from deck
 */

deal( mycrib )
{
	register  int		i, j;

	j = 0;
	for( i = 0; i < FULLHAND; i++ )  {
	    if( mycrib )  {
		phand[i] = deck[j++];
		chand[i] = deck[j++];
	    }
	    else  {
		chand[i] = deck[j++];
		phand[i] = deck[j++];
	    }
	}
	return( j );
}



/*
 * handle players discarding into the crib...
 * note: we call cdiscard() after prining first message so player doesn't wait
 */

discard( mycrib )

    BOOLEAN		mycrib;
{

	CARD			crd;

	printf( "It's %s crib...\n", (mycrib ? "my" : "your") );
	printf( quiet ? "Discard --> " : "Discard a card --> " );
	cdiscard( mycrib );			/* puts best discard at end */
	crd = phand[ infrom(phand, FULLHAND) ];
	remove( crd, phand, FULLHAND);
	crib[0] = crd;
    /* next four lines same as last four except for cdiscard() */
	printf( quiet ? "Discard --> " : "Discard a card --> " );
	crd = phand[ infrom(phand, FULLHAND - 1) ];
	remove( crd, phand, FULLHAND - 1 );
	crib[1] = crd;
	crib[2] = chand[4];
	crib[3] = chand[5];
	chand[4].rank = chand[4].suit = chand[5].rank = chand[5].suit = -1;
}



/*
 * cut the deck and set turnover
 */

cut( mycrib, pos )

    BOOLEAN		mycrib;
    int			pos;
{
	register  int		i;
	BOOLEAN			win = FALSE;

	if( mycrib )  {
	    if( rflag )  {			/* random cut */
		i = ( rand() >> 4 ) % (CARDS - pos);
	    }
	    else  {
		printf( quiet ? "Cut the deck? " :
			"How many cards down do you wish to cut the deck? " );
		i = number( 0, CARDS - pos - 1 );
	    }
	    turnover = deck[i + pos];
	    printf( quiet ? "You cut " : "You cut the " );
	    printcard( turnover, FALSE );
	    printf( ".\n" );
	    if(  turnover.rank == JACK  )  {
		printf( "I get two for his heels.\n" );
		win = chkscr( &cscore, 2 );
	    }
	}
	else  {
	    i = ( rand() >> 4 ) % (CARDS - pos)  +  pos;
	    turnover = deck[i];
	    printf( quiet ? "I cut " : "I cut the " );
	    printcard( turnover, FALSE );
	    printf( ".\n" );
	    if(  turnover.rank == JACK  )  {
		printf( "You get two for his heels.\n" );
		win = chkscr( &pscore, 2 );
	    }
	}
	makeknown( &turnover, 1 );
	return( win );
}



/*
 * handle all the pegging...
 */

peg( mycrib )

    BOOLEAN		mycrib;
{
	static  CARD		ch[ CINHAND ],  ph[ CINHAND ];
	static  CARD		table[ 14 ];
	CARD			crd;
	register  int		i, j, k;
	int			l;
	int			cnum, pnum, tcnt, sum;
	BOOLEAN			myturn, mego, ugo, last, played;

	cnum = pnum = CINHAND;
	for( i = 0; i < CINHAND; i++ )  {	/* make copies of hands */
	    ch[i] = chand[i];
	    ph[i] = phand[i];
	}
	tcnt = 0;			/* index to table of cards played */
	sum = 0;			/* sum of cards played */
	mego = ugo = FALSE;
	myturn = !mycrib;
	do  {
	    last = TRUE;				/* enable last flag */
	    if(  myturn  )  {				/* my tyrn to play */
		if(  !anymove( ch, cnum, sum )  )  {	/* if no card to play */
		    if(  !mego  &&  cnum  )  {		/* go for comp? */
			printf( "GO.\n" );
			mego = TRUE;
		    }
		    if(  anymove( ph, pnum, sum )  )  {	/* can player move? */
			myturn = !myturn;
		    }
		    else  {				/* give him his point */
			printf( quiet ? "You get one.\n" :
					"You get one point.\n" );
			if(  chkscr( &pscore, 1 )  )  return( TRUE );
			sum = 0;
			mego = ugo = FALSE;
			tcnt = 0;
		    }
		}
		else  {
		    played = TRUE;
		    j = -1;
		    k = 0;
		    for( i = 0; i < cnum; i++ )  {	/* maximize score */
			l = pegscore( ch[i], table, tcnt, sum );
			if(  l > k  )  {
			    k = l;
			    j = i;
			}
		    }
		    if(  j < 0  )  {			/* if nothing scores */
			j = cchose( ch, cnum, sum );
		    }
		    crd = ch[j];
		    printf( quiet ? "I play " : "I play the " );
		    printcard( crd, FALSE );
		    remove( crd, ch, cnum-- );
		    sum += VAL( crd.rank );
		    table[ tcnt++ ] = crd;
		    printf( ".  Total is %d", sum );
		    if( k > 0 )  {
			printf( quiet ? ".  I got %d" :
						".  I got %d points", k );
			if(  chkscr( &cscore, k )  )  return( TRUE );
		    }
		    printf( ".\n" );
		    myturn = !myturn;
		}
	    }
	    else  {
		if(  !anymove( ph, pnum, sum )  )  {	/* can player move? */
		    if(  !ugo  &&  pnum  )  {		/* go for player */
			printf( "You have a GO.\n" );
			ugo = TRUE;
		    }
		    if(  anymove( ch, cnum, sum )  )  {	/* can computer play? */
			myturn = !myturn;
		    }
		    else  {
			printf( quiet ? "I get one.\n" : "I get one point.\n" );
			if(  chkscr( &cscore, 1 )  )  return( TRUE );
			sum = 0;
			mego = ugo = FALSE;
			tcnt = 0;
		    }
		}
		else  {					/* player plays */
		    played = FALSE;
		    if(  pnum == 1  )  {
			crd = ph[0];
			printf( "You play your last card, the " );
			printcard( crd, TRUE );
			printf( ".  " );
		    }
		    else  {
			do  {
			    printf( "Your play ( " );
			    prhand( ph, pnum, TRUE );
			    printf( " ): " );
			    crd = ph[ infrom(ph, pnum) ];
			    if(  sum + VAL( crd.rank )  <=  31  )  {
				break;
			    }
			    else  {
				printf( "Total > 31 -- try again.\n" );
			    }
			}  while( TRUE );
		    }
		    makeknown( &crd, 1 );
		    remove( crd, ph, pnum-- );
		    i = pegscore( crd, table, tcnt, sum );
		    sum += VAL( crd.rank );
		    table[ tcnt++ ] = crd;
		    printf( "Total is %d", sum );
		    if( i > 0 )  {
			printf( quiet ? ".  You got %d" :
						".  You got %d points", i );
			if(  chkscr( &pscore, i )  )  return( TRUE );
		    }
		    printf( ".\n" );
		    myturn = !myturn;
		}
	    }
	    if(  sum >= 31  )  {
		sum = 0;
		mego = ugo = FALSE;
		tcnt = 0;
		last = FALSE;				/* disable last flag */
	    }
	    if(  !pnum  &&  !cnum  )  break;		/* both done */
	}  while( TRUE );
	if( last )  {
	    if( played )  {
		printf( quiet ? "I get one for last.\n" :
					"I get one point for last.\n" );
		if(  chkscr( &cscore, 1 )  )  return( TRUE );
	    }
	    else  {
		printf( quiet ? "You get one for last.\n" :
					"You get one point for last.\n" );
		if(  chkscr( &pscore, 1 )  )  return( TRUE );
	    }
	}
	return( FALSE );
}



/*
 * handle the scoring of the hands
 */

score( mycrib )

    BOOLEAN		mycrib;
{
	if(  mycrib  )  {
	    if(  plyrhand( phand, "hand" )  )  return( TRUE );
	    if(  comphand( chand, "hand" )  )  return( TRUE );
	    if(  comphand( crib, "crib" )  )  return( TRUE );
	}
	else  {
	    if(  comphand( chand, "hand" )  )  return( TRUE );
	    if(  plyrhand( phand, "hand" )  )  return( TRUE );
	    if(  plyrhand( crib, "crib" )  )  return( TRUE );
	}
	return( FALSE );
}