1*7706Sarnold 2*7706Sarnold #include <stdio.h> 3*7706Sarnold #include "deck.h" 4*7706Sarnold 5*7706Sarnold 6*7706Sarnold #define LOGFILE "/usr/games/lib/criblog" 7*7706Sarnold #define INSTRCMD "ul /usr/games/lib/crib.instr | more -f" 8*7706Sarnold 9*7706Sarnold 10*7706Sarnold CARD deck[ CARDS ]; /* a deck */ 11*7706Sarnold CARD phand[ FULLHAND ]; /* player's hand */ 12*7706Sarnold CARD chand[ FULLHAND ]; /* computer's hand */ 13*7706Sarnold CARD crib[ CINHAND ]; /* the crib */ 14*7706Sarnold CARD turnover; /* the starter */ 15*7706Sarnold 16*7706Sarnold CARD known[ CARDS ]; /* cards we have seen */ 17*7706Sarnold int knownum = 0; /* number of cards we know */ 18*7706Sarnold 19*7706Sarnold int pscore = 0; /* player score in current game */ 20*7706Sarnold int cscore = 0; /* comp score in current game */ 21*7706Sarnold int pgames = 0; /* number games player won */ 22*7706Sarnold int cgames = 0; /* number games comp won */ 23*7706Sarnold int gamecount = 0; /* number games played */ 24*7706Sarnold int glimit = LGAME; /* game playe to glimit */ 25*7706Sarnold 26*7706Sarnold BOOLEAN iwon = FALSE; /* if comp won last game */ 27*7706Sarnold BOOLEAN explain = FALSE; /* player mistakes explained */ 28*7706Sarnold BOOLEAN rflag = FALSE; /* if all cuts random */ 29*7706Sarnold BOOLEAN quiet = FALSE; /* if suppress random mess */ 30*7706Sarnold 31*7706Sarnold char expl[ 128 ]; /* explanation */ 32*7706Sarnold 33*7706Sarnold 34*7706Sarnold main( argc, argv ) 35*7706Sarnold 36*7706Sarnold int argc; 37*7706Sarnold char *argv[]; 38*7706Sarnold { 39*7706Sarnold FILE *fopen(); 40*7706Sarnold FILE *f; 41*7706Sarnold char *getline(); 42*7706Sarnold register char *p; 43*7706Sarnold BOOLEAN playing; 44*7706Sarnold char *s; /* for reading arguments */ 45*7706Sarnold char bust; /* flag for arg reader */ 46*7706Sarnold 47*7706Sarnold while( --argc > 0 ) { 48*7706Sarnold if( (*++argv)[0] != '-' ) { 49*7706Sarnold fprintf( stderr, "\n\ncribbage: usage is 'cribbage [-eqr]'\n" ); 50*7706Sarnold exit( 1 ); 51*7706Sarnold } 52*7706Sarnold bust = FALSE; 53*7706Sarnold for( s = argv[0] + 1; *s != NULL; s++ ) { 54*7706Sarnold switch( *s ) { 55*7706Sarnold 56*7706Sarnold case 'e': 57*7706Sarnold explain = TRUE; 58*7706Sarnold break; 59*7706Sarnold 60*7706Sarnold case 'q': 61*7706Sarnold quiet = TRUE; 62*7706Sarnold break; 63*7706Sarnold 64*7706Sarnold case 'r': 65*7706Sarnold rflag = TRUE; 66*7706Sarnold break; 67*7706Sarnold 68*7706Sarnold default: 69*7706Sarnold fprintf( stderr, "\n\ncribbage: usage is 'cribbage [-eqr]'\n" ); 70*7706Sarnold exit( 2 ); 71*7706Sarnold break; 72*7706Sarnold } 73*7706Sarnold if( bust ) break; 74*7706Sarnold } 75*7706Sarnold } 76*7706Sarnold if( !quiet ) { 77*7706Sarnold printf( "\nDo you need instructions for cribbage? " ); 78*7706Sarnold p = getline(); 79*7706Sarnold if( *p == 'Y' ) { 80*7706Sarnold system( INSTRCMD ); 81*7706Sarnold printf( "\nFor the rules of this game, do 'man cribbage'\n" ); 82*7706Sarnold } 83*7706Sarnold } 84*7706Sarnold playing = TRUE; 85*7706Sarnold do { 86*7706Sarnold printf( quiet ? "\nL or S? " : 87*7706Sarnold "\nLong (to 121) or Short (to 61)? " ); 88*7706Sarnold p = getline(); 89*7706Sarnold glimit = ( *p == 'S' ? SGAME : LGAME ); 90*7706Sarnold game(); 91*7706Sarnold printf( "\nAnother game? " ); 92*7706Sarnold p = getline(); 93*7706Sarnold playing = (*p == 'Y'); 94*7706Sarnold } while( playing ); 95*7706Sarnold if( ( f = fopen(LOGFILE, "a") ) != NULL ) { 96*7706Sarnold fprintf( f, "Won %5.5d, Lost %5.5d\n", cgames, pgames ); 97*7706Sarnold fclose( f ); 98*7706Sarnold } 99*7706Sarnold } 100*7706Sarnold 101*7706Sarnold 102*7706Sarnold 103*7706Sarnold /* 104*7706Sarnold * play one game up to glimit points 105*7706Sarnold */ 106*7706Sarnold 107*7706Sarnold game() 108*7706Sarnold { 109*7706Sarnold register int i, j; 110*7706Sarnold BOOLEAN flag; 111*7706Sarnold BOOLEAN compcrib; 112*7706Sarnold 113*7706Sarnold makedeck( deck ); 114*7706Sarnold shuffle( deck ); 115*7706Sarnold if( gamecount == 0 ) { 116*7706Sarnold flag = TRUE; 117*7706Sarnold do { 118*7706Sarnold if( rflag ) { /* player cuts deck */ 119*7706Sarnold i = ( rand() >>4 ) % CARDS; /* random cut */ 120*7706Sarnold } 121*7706Sarnold else { 122*7706Sarnold printf( quiet ? "\nCut for crib? " : 123*7706Sarnold "\nCut to see whose crib it is -- low card wins? " ); 124*7706Sarnold i = number( 0, CARDS - 1 ); 125*7706Sarnold } 126*7706Sarnold do { /* comp cuts deck */ 127*7706Sarnold j = ( rand() >> 4 ) % CARDS; 128*7706Sarnold } while( j == i ); 129*7706Sarnold printf( quiet ? "You cut " : "You cut the " ); 130*7706Sarnold printcard( deck[i], FALSE ); 131*7706Sarnold printf( quiet ? ", I cut " : ", I cut the " ); 132*7706Sarnold printcard( deck[j], FALSE ); 133*7706Sarnold printf( ".\n" ); 134*7706Sarnold flag = ( deck[i].rank == deck[j].rank ); 135*7706Sarnold if( flag ) { 136*7706Sarnold printf( quiet ? "We tied...\n" : 137*7706Sarnold "We tied and have to try again...\n" ); 138*7706Sarnold shuffle( deck ); 139*7706Sarnold continue; 140*7706Sarnold } 141*7706Sarnold else { 142*7706Sarnold compcrib = deck[i].rank > deck[j].rank; 143*7706Sarnold } 144*7706Sarnold } while( flag ); 145*7706Sarnold } 146*7706Sarnold else { 147*7706Sarnold printf( "Loser (%s) gets first crib.\n", (iwon ? "you" : "me") ); 148*7706Sarnold compcrib = !iwon; 149*7706Sarnold } 150*7706Sarnold pscore = cscore = 0; 151*7706Sarnold flag = TRUE; 152*7706Sarnold do { 153*7706Sarnold shuffle( deck ); 154*7706Sarnold flag = !playhand( compcrib ); 155*7706Sarnold compcrib = !compcrib; 156*7706Sarnold printf( "\nYou have %d points, I have %d.\n", pscore, cscore ); 157*7706Sarnold } while( flag ); 158*7706Sarnold ++gamecount; 159*7706Sarnold if( cscore < pscore ) { 160*7706Sarnold if( glimit - cscore > 30 ) { 161*7706Sarnold if( glimit - cscore > 60 ) { 162*7706Sarnold printf( "\nYOU DOUBLE SKUNKED ME!\n\n" ); 163*7706Sarnold pgames += 4; 164*7706Sarnold } 165*7706Sarnold else { 166*7706Sarnold printf( "\nYOU SKUNKED ME!\n\n" ); 167*7706Sarnold pgames += 2; 168*7706Sarnold } 169*7706Sarnold } 170*7706Sarnold else { 171*7706Sarnold printf( "\nYOU WON!\n\n" ); 172*7706Sarnold ++pgames; 173*7706Sarnold } 174*7706Sarnold iwon = FALSE; 175*7706Sarnold } 176*7706Sarnold else { 177*7706Sarnold if( glimit - pscore > 30 ) { 178*7706Sarnold if( glimit - pscore > 60 ) { 179*7706Sarnold printf( "\nI DOUBLE SKUNKED YOU!\n\n" ); 180*7706Sarnold cgames += 4; 181*7706Sarnold } 182*7706Sarnold else { 183*7706Sarnold printf( "\nI SKUNKED YOU!\n\n" ); 184*7706Sarnold cgames += 2; 185*7706Sarnold } 186*7706Sarnold } 187*7706Sarnold else { 188*7706Sarnold printf( "\nI WON!\n\n" ); 189*7706Sarnold ++cgames; 190*7706Sarnold } 191*7706Sarnold iwon = TRUE; 192*7706Sarnold } 193*7706Sarnold printf( "\nI have won %d games, you have won %d\n", cgames, pgames ); 194*7706Sarnold } 195*7706Sarnold 196*7706Sarnold 197*7706Sarnold 198*7706Sarnold /* 199*7706Sarnold * hand does up one hand of the game 200*7706Sarnold */ 201*7706Sarnold 202*7706Sarnold playhand( mycrib ) 203*7706Sarnold 204*7706Sarnold BOOLEAN mycrib; 205*7706Sarnold { 206*7706Sarnold register int deckpos; 207*7706Sarnold 208*7706Sarnold knownum = 0; 209*7706Sarnold deckpos = deal( mycrib ); 210*7706Sarnold sorthand( chand, FULLHAND ); 211*7706Sarnold sorthand( phand, FULLHAND ); 212*7706Sarnold makeknown( chand, FULLHAND ); 213*7706Sarnold printf( "\nYour hand is: " ); 214*7706Sarnold prhand( phand, FULLHAND, TRUE ); 215*7706Sarnold printf( ".\n" ); 216*7706Sarnold discard( mycrib ); 217*7706Sarnold if( cut( mycrib, deckpos ) ) return( TRUE ); 218*7706Sarnold if( peg( mycrib ) ) return( TRUE ); 219*7706Sarnold if( score( mycrib ) ) return( TRUE ); 220*7706Sarnold return( FALSE ); 221*7706Sarnold } 222*7706Sarnold 223*7706Sarnold 224*7706Sarnold 225*7706Sarnold /* 226*7706Sarnold * deal cards to both players from deck 227*7706Sarnold */ 228*7706Sarnold 229*7706Sarnold deal( mycrib ) 230*7706Sarnold { 231*7706Sarnold register int i, j; 232*7706Sarnold 233*7706Sarnold j = 0; 234*7706Sarnold for( i = 0; i < FULLHAND; i++ ) { 235*7706Sarnold if( mycrib ) { 236*7706Sarnold phand[i] = deck[j++]; 237*7706Sarnold chand[i] = deck[j++]; 238*7706Sarnold } 239*7706Sarnold else { 240*7706Sarnold chand[i] = deck[j++]; 241*7706Sarnold phand[i] = deck[j++]; 242*7706Sarnold } 243*7706Sarnold } 244*7706Sarnold return( j ); 245*7706Sarnold } 246*7706Sarnold 247*7706Sarnold 248*7706Sarnold 249*7706Sarnold /* 250*7706Sarnold * handle players discarding into the crib... 251*7706Sarnold * note: we call cdiscard() after prining first message so player doesn't wait 252*7706Sarnold */ 253*7706Sarnold 254*7706Sarnold discard( mycrib ) 255*7706Sarnold 256*7706Sarnold BOOLEAN mycrib; 257*7706Sarnold { 258*7706Sarnold 259*7706Sarnold CARD crd; 260*7706Sarnold 261*7706Sarnold printf( "It's %s crib...\n", (mycrib ? "my" : "your") ); 262*7706Sarnold printf( quiet ? "Discard --> " : "Discard a card --> " ); 263*7706Sarnold cdiscard( mycrib ); /* puts best discard at end */ 264*7706Sarnold crd = phand[ infrom(phand, FULLHAND) ]; 265*7706Sarnold remove( crd, phand, FULLHAND); 266*7706Sarnold crib[0] = crd; 267*7706Sarnold /* next four lines same as last four except for cdiscard() */ 268*7706Sarnold printf( quiet ? "Discard --> " : "Discard a card --> " ); 269*7706Sarnold crd = phand[ infrom(phand, FULLHAND - 1) ]; 270*7706Sarnold remove( crd, phand, FULLHAND - 1 ); 271*7706Sarnold crib[1] = crd; 272*7706Sarnold crib[2] = chand[4]; 273*7706Sarnold crib[3] = chand[5]; 274*7706Sarnold chand[4].rank = chand[4].suit = chand[5].rank = chand[5].suit = -1; 275*7706Sarnold } 276*7706Sarnold 277*7706Sarnold 278*7706Sarnold 279*7706Sarnold /* 280*7706Sarnold * cut the deck and set turnover 281*7706Sarnold */ 282*7706Sarnold 283*7706Sarnold cut( mycrib, pos ) 284*7706Sarnold 285*7706Sarnold BOOLEAN mycrib; 286*7706Sarnold int pos; 287*7706Sarnold { 288*7706Sarnold register int i; 289*7706Sarnold BOOLEAN win = FALSE; 290*7706Sarnold 291*7706Sarnold if( mycrib ) { 292*7706Sarnold if( rflag ) { /* random cut */ 293*7706Sarnold i = ( rand() >> 4 ) % (CARDS - pos); 294*7706Sarnold } 295*7706Sarnold else { 296*7706Sarnold printf( quiet ? "Cut the deck? " : 297*7706Sarnold "How many cards down do you wish to cut the deck? " ); 298*7706Sarnold i = number( 0, CARDS - pos - 1 ); 299*7706Sarnold } 300*7706Sarnold turnover = deck[i + pos]; 301*7706Sarnold printf( quiet ? "You cut " : "You cut the " ); 302*7706Sarnold printcard( turnover, FALSE ); 303*7706Sarnold printf( ".\n" ); 304*7706Sarnold if( turnover.rank == JACK ) { 305*7706Sarnold printf( "I get two for his heels.\n" ); 306*7706Sarnold win = chkscr( &cscore, 2 ); 307*7706Sarnold } 308*7706Sarnold } 309*7706Sarnold else { 310*7706Sarnold i = ( rand() >> 4 ) % (CARDS - pos) + pos; 311*7706Sarnold turnover = deck[i]; 312*7706Sarnold printf( quiet ? "I cut " : "I cut the " ); 313*7706Sarnold printcard( turnover, FALSE ); 314*7706Sarnold printf( ".\n" ); 315*7706Sarnold if( turnover.rank == JACK ) { 316*7706Sarnold printf( "You get two for his heels.\n" ); 317*7706Sarnold win = chkscr( &pscore, 2 ); 318*7706Sarnold } 319*7706Sarnold } 320*7706Sarnold makeknown( &turnover, 1 ); 321*7706Sarnold return( win ); 322*7706Sarnold } 323*7706Sarnold 324*7706Sarnold 325*7706Sarnold 326*7706Sarnold /* 327*7706Sarnold * handle all the pegging... 328*7706Sarnold */ 329*7706Sarnold 330*7706Sarnold peg( mycrib ) 331*7706Sarnold 332*7706Sarnold BOOLEAN mycrib; 333*7706Sarnold { 334*7706Sarnold static CARD ch[ CINHAND ], ph[ CINHAND ]; 335*7706Sarnold static CARD table[ 14 ]; 336*7706Sarnold CARD crd; 337*7706Sarnold register int i, j, k; 338*7706Sarnold int l; 339*7706Sarnold int cnum, pnum, tcnt, sum; 340*7706Sarnold BOOLEAN myturn, mego, ugo, last, played; 341*7706Sarnold 342*7706Sarnold cnum = pnum = CINHAND; 343*7706Sarnold for( i = 0; i < CINHAND; i++ ) { /* make copies of hands */ 344*7706Sarnold ch[i] = chand[i]; 345*7706Sarnold ph[i] = phand[i]; 346*7706Sarnold } 347*7706Sarnold tcnt = 0; /* index to table of cards played */ 348*7706Sarnold sum = 0; /* sum of cards played */ 349*7706Sarnold mego = ugo = FALSE; 350*7706Sarnold myturn = !mycrib; 351*7706Sarnold do { 352*7706Sarnold last = TRUE; /* enable last flag */ 353*7706Sarnold if( myturn ) { /* my tyrn to play */ 354*7706Sarnold if( !anymove( ch, cnum, sum ) ) { /* if no card to play */ 355*7706Sarnold if( !mego && cnum ) { /* go for comp? */ 356*7706Sarnold printf( "GO.\n" ); 357*7706Sarnold mego = TRUE; 358*7706Sarnold } 359*7706Sarnold if( anymove( ph, pnum, sum ) ) { /* can player move? */ 360*7706Sarnold myturn = !myturn; 361*7706Sarnold } 362*7706Sarnold else { /* give him his point */ 363*7706Sarnold printf( quiet ? "You get one.\n" : 364*7706Sarnold "You get one point.\n" ); 365*7706Sarnold if( chkscr( &pscore, 1 ) ) return( TRUE ); 366*7706Sarnold sum = 0; 367*7706Sarnold mego = ugo = FALSE; 368*7706Sarnold tcnt = 0; 369*7706Sarnold } 370*7706Sarnold } 371*7706Sarnold else { 372*7706Sarnold played = TRUE; 373*7706Sarnold j = -1; 374*7706Sarnold k = 0; 375*7706Sarnold for( i = 0; i < cnum; i++ ) { /* maximize score */ 376*7706Sarnold l = pegscore( ch[i], table, tcnt, sum ); 377*7706Sarnold if( l > k ) { 378*7706Sarnold k = l; 379*7706Sarnold j = i; 380*7706Sarnold } 381*7706Sarnold } 382*7706Sarnold if( j < 0 ) { /* if nothing scores */ 383*7706Sarnold j = cchose( ch, cnum, sum ); 384*7706Sarnold } 385*7706Sarnold crd = ch[j]; 386*7706Sarnold printf( quiet ? "I play " : "I play the " ); 387*7706Sarnold printcard( crd, FALSE ); 388*7706Sarnold remove( crd, ch, cnum-- ); 389*7706Sarnold sum += VAL( crd.rank ); 390*7706Sarnold table[ tcnt++ ] = crd; 391*7706Sarnold printf( ". Total is %d", sum ); 392*7706Sarnold if( k > 0 ) { 393*7706Sarnold printf( quiet ? ". I got %d" : 394*7706Sarnold ". I got %d points", k ); 395*7706Sarnold if( chkscr( &cscore, k ) ) return( TRUE ); 396*7706Sarnold } 397*7706Sarnold printf( ".\n" ); 398*7706Sarnold myturn = !myturn; 399*7706Sarnold } 400*7706Sarnold } 401*7706Sarnold else { 402*7706Sarnold if( !anymove( ph, pnum, sum ) ) { /* can player move? */ 403*7706Sarnold if( !ugo && pnum ) { /* go for player */ 404*7706Sarnold printf( "You have a GO.\n" ); 405*7706Sarnold ugo = TRUE; 406*7706Sarnold } 407*7706Sarnold if( anymove( ch, cnum, sum ) ) { /* can computer play? */ 408*7706Sarnold myturn = !myturn; 409*7706Sarnold } 410*7706Sarnold else { 411*7706Sarnold printf( quiet ? "I get one.\n" : "I get one point.\n" ); 412*7706Sarnold if( chkscr( &cscore, 1 ) ) return( TRUE ); 413*7706Sarnold sum = 0; 414*7706Sarnold mego = ugo = FALSE; 415*7706Sarnold tcnt = 0; 416*7706Sarnold } 417*7706Sarnold } 418*7706Sarnold else { /* player plays */ 419*7706Sarnold played = FALSE; 420*7706Sarnold if( pnum == 1 ) { 421*7706Sarnold crd = ph[0]; 422*7706Sarnold printf( "You play your last card, the " ); 423*7706Sarnold printcard( crd, TRUE ); 424*7706Sarnold printf( ". " ); 425*7706Sarnold } 426*7706Sarnold else { 427*7706Sarnold do { 428*7706Sarnold printf( "Your play ( " ); 429*7706Sarnold prhand( ph, pnum, TRUE ); 430*7706Sarnold printf( " ): " ); 431*7706Sarnold crd = ph[ infrom(ph, pnum) ]; 432*7706Sarnold if( sum + VAL( crd.rank ) <= 31 ) { 433*7706Sarnold break; 434*7706Sarnold } 435*7706Sarnold else { 436*7706Sarnold printf( "Total > 31 -- try again.\n" ); 437*7706Sarnold } 438*7706Sarnold } while( TRUE ); 439*7706Sarnold } 440*7706Sarnold makeknown( &crd, 1 ); 441*7706Sarnold remove( crd, ph, pnum-- ); 442*7706Sarnold i = pegscore( crd, table, tcnt, sum ); 443*7706Sarnold sum += VAL( crd.rank ); 444*7706Sarnold table[ tcnt++ ] = crd; 445*7706Sarnold printf( "Total is %d", sum ); 446*7706Sarnold if( i > 0 ) { 447*7706Sarnold printf( quiet ? ". You got %d" : 448*7706Sarnold ". You got %d points", i ); 449*7706Sarnold if( chkscr( &pscore, i ) ) return( TRUE ); 450*7706Sarnold } 451*7706Sarnold printf( ".\n" ); 452*7706Sarnold myturn = !myturn; 453*7706Sarnold } 454*7706Sarnold } 455*7706Sarnold if( sum >= 31 ) { 456*7706Sarnold sum = 0; 457*7706Sarnold mego = ugo = FALSE; 458*7706Sarnold tcnt = 0; 459*7706Sarnold last = FALSE; /* disable last flag */ 460*7706Sarnold } 461*7706Sarnold if( !pnum && !cnum ) break; /* both done */ 462*7706Sarnold } while( TRUE ); 463*7706Sarnold if( last ) { 464*7706Sarnold if( played ) { 465*7706Sarnold printf( quiet ? "I get one for last.\n" : 466*7706Sarnold "I get one point for last.\n" ); 467*7706Sarnold if( chkscr( &cscore, 1 ) ) return( TRUE ); 468*7706Sarnold } 469*7706Sarnold else { 470*7706Sarnold printf( quiet ? "You get one for last.\n" : 471*7706Sarnold "You get one point for last.\n" ); 472*7706Sarnold if( chkscr( &pscore, 1 ) ) return( TRUE ); 473*7706Sarnold } 474*7706Sarnold } 475*7706Sarnold return( FALSE ); 476*7706Sarnold } 477*7706Sarnold 478*7706Sarnold 479*7706Sarnold 480*7706Sarnold /* 481*7706Sarnold * handle the scoring of the hands 482*7706Sarnold */ 483*7706Sarnold 484*7706Sarnold score( mycrib ) 485*7706Sarnold 486*7706Sarnold BOOLEAN mycrib; 487*7706Sarnold { 488*7706Sarnold if( mycrib ) { 489*7706Sarnold if( plyrhand( phand, "hand" ) ) return( TRUE ); 490*7706Sarnold if( comphand( chand, "hand" ) ) return( TRUE ); 491*7706Sarnold if( comphand( crib, "crib" ) ) return( TRUE ); 492*7706Sarnold } 493*7706Sarnold else { 494*7706Sarnold if( comphand( chand, "hand" ) ) return( TRUE ); 495*7706Sarnold if( plyrhand( phand, "hand" ) ) return( TRUE ); 496*7706Sarnold if( plyrhand( crib, "crib" ) ) return( TRUE ); 497*7706Sarnold } 498*7706Sarnold return( FALSE ); 499*7706Sarnold } 500*7706Sarnold 501