|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)crib.c 5.1 (Berkeley) 5/30/85";
15: #endif not lint
16:
17: # include <curses.h>
18: # include <signal.h>
19: # include "deck.h"
20: # include "cribbage.h"
21: # include "cribcur.h"
22:
23:
24: # define LOGFILE "/usr/games/lib/criblog"
25: # define INSTRCMD "ul /usr/games/lib/crib.instr | more -f"
26:
27:
28: main(argc, argv)
29: int argc;
30: char *argv[];
31: {
32: register char *p;
33: BOOLEAN playing;
34: char *s; /* for reading arguments */
35: char bust; /* flag for arg reader */
36: FILE *f;
37: FILE *fopen();
38: char *getline();
39: int bye();
40:
41: while (--argc > 0) {
42: if ((*++argv)[0] != '-') {
43: fprintf(stderr, "\n\ncribbage: usage is 'cribbage [-eqr]'\n");
44: exit(1);
45: }
46: bust = FALSE;
47: for (s = argv[0] + 1; *s != NULL; s++) {
48: switch (*s) {
49: case 'e':
50: explain = TRUE;
51: break;
52: case 'q':
53: quiet = TRUE;
54: break;
55: case 'r':
56: rflag = TRUE;
57: break;
58: default:
59: fprintf(stderr, "\n\ncribbage: usage is 'cribbage [-eqr]'\n");
60: exit(2);
61: break;
62: }
63: if (bust)
64: break;
65: }
66: }
67:
68: initscr();
69: signal(SIGINT, bye);
70: crmode();
71: noecho();
72: Playwin = subwin(stdscr, PLAY_Y, PLAY_X, 0, 0);
73: Tablewin = subwin(stdscr, TABLE_Y, TABLE_X, 0, PLAY_X);
74: Compwin = subwin(stdscr, COMP_Y, COMP_X, 0, TABLE_X + PLAY_X);
75: Msgwin = subwin(stdscr, MSG_Y, MSG_X, Y_MSG_START, SCORE_X + 1);
76: leaveok(Playwin, TRUE);
77: leaveok(Tablewin, TRUE);
78: leaveok(Compwin, TRUE);
79: clearok(stdscr, FALSE);
80:
81: if (!quiet) {
82: msg("Do you need instructions for cribbage? ");
83: if (getuchar() == 'Y') {
84: endwin();
85: fflush(stdout);
86: system(INSTRCMD);
87: crmode();
88: noecho();
89: clear();
90: refresh();
91: msg("For the rules of this program, do \"man cribbage\"");
92: }
93: }
94: playing = TRUE;
95: do {
96: wclrtobot(Msgwin);
97: msg(quiet ? "L or S? " : "Long (to 121) or Short (to 61)? ");
98: if (glimit == SGAME)
99: glimit = (getuchar() == 'L' ? LGAME : SGAME);
100: else
101: glimit = (getuchar() == 'S' ? SGAME : LGAME);
102: game();
103: msg("Another game? ");
104: playing = (getuchar() == 'Y');
105: } while (playing);
106:
107: if ((f = fopen(LOGFILE, "a")) != NULL) {
108: fprintf(f, "Won %5.5d, Lost %5.5d\n", cgames, pgames);
109: fclose(f);
110: }
111:
112: bye();
113: }
114:
115: /*
116: * makeboard:
117: * Print out the initial board on the screen
118: */
119: makeboard()
120: {
121: mvaddstr(SCORE_Y + 0, SCORE_X, "+---------------------------------------+");
122: mvaddstr(SCORE_Y + 1, SCORE_X, "| Score: 0 YOU |");
123: mvaddstr(SCORE_Y + 2, SCORE_X, "| *.....:.....:.....:.....:.....:..... |");
124: mvaddstr(SCORE_Y + 3, SCORE_X, "| *.....:.....:.....:.....:.....:..... |");
125: mvaddstr(SCORE_Y + 4, SCORE_X, "| |");
126: mvaddstr(SCORE_Y + 5, SCORE_X, "| *.....:.....:.....:.....:.....:..... |");
127: mvaddstr(SCORE_Y + 6, SCORE_X, "| *.....:.....:.....:.....:.....:..... |");
128: mvaddstr(SCORE_Y + 7, SCORE_X, "| Score: 0 ME |");
129: mvaddstr(SCORE_Y + 8, SCORE_X, "+---------------------------------------+");
130: gamescore();
131: }
132:
133: /*
134: * gamescore:
135: * Print out the current game score
136: */
137: gamescore()
138: {
139: extern int Lastscore[];
140:
141: if (pgames || cgames) {
142: mvprintw(SCORE_Y + 1, SCORE_X + 28, "Games: %3d", pgames);
143: mvprintw(SCORE_Y + 7, SCORE_X + 28, "Games: %3d", cgames);
144: }
145: Lastscore[0] = -1;
146: Lastscore[1] = -1;
147: }
148:
149: /*
150: * game:
151: * Play one game up to glimit points. Actually, we only ASK the
152: * player what card to turn. We do a random one, anyway.
153: */
154: game()
155: {
156: register int i, j;
157: BOOLEAN flag;
158: BOOLEAN compcrib;
159:
160: makeboard();
161: refresh();
162: makedeck(deck);
163: shuffle(deck);
164: if (gamecount == 0) {
165: flag = TRUE;
166: do {
167: if (!rflag) { /* player cuts deck */
168: msg(quiet ? "Cut for crib? " :
169: "Cut to see whose crib it is -- low card wins? ");
170: getline();
171: }
172: i = (rand() >> 4) % CARDS; /* random cut */
173: do { /* comp cuts deck */
174: j = (rand() >> 4) % CARDS;
175: } while (j == i);
176: addmsg(quiet ? "You cut " : "You cut the ");
177: msgcard(deck[i], FALSE);
178: endmsg();
179: addmsg(quiet ? "I cut " : "I cut the ");
180: msgcard(deck[j], FALSE);
181: endmsg();
182: flag = (deck[i].rank == deck[j].rank);
183: if (flag) {
184: msg(quiet ? "We tied..." :
185: "We tied and have to try again...");
186: shuffle(deck);
187: continue;
188: }
189: else
190: compcrib = (deck[i].rank > deck[j].rank);
191: } while (flag);
192: }
193: else {
194: werase(Tablewin);
195: wrefresh(Tablewin);
196: werase(Compwin);
197: wrefresh(Compwin);
198: msg("Loser (%s) gets first crib", (iwon ? "you" : "me"));
199: compcrib = !iwon;
200: }
201:
202: pscore = cscore = 0;
203: flag = TRUE;
204: do {
205: shuffle(deck);
206: flag = !playhand(compcrib);
207: compcrib = !compcrib;
208: } while (flag);
209: ++gamecount;
210: if (cscore < pscore) {
211: if (glimit - cscore > 60) {
212: msg("YOU DOUBLE SKUNKED ME!");
213: pgames += 4;
214: }
215: else if (glimit - cscore > 30) {
216: msg("YOU SKUNKED ME!");
217: pgames += 2;
218: }
219: else {
220: msg("YOU WON!");
221: ++pgames;
222: }
223: iwon = FALSE;
224: }
225: else {
226: if (glimit - pscore > 60) {
227: msg("I DOUBLE SKUNKED YOU!");
228: cgames += 4;
229: }
230: else if (glimit - pscore > 30) {
231: msg("I SKUNKED YOU!");
232: cgames += 2;
233: }
234: else {
235: msg("I WON!");
236: ++cgames;
237: }
238: iwon = TRUE;
239: }
240: gamescore();
241: }
242:
243: /*
244: * playhand:
245: * Do up one hand of the game
246: */
247: playhand(mycrib)
248: BOOLEAN mycrib;
249: {
250: register int deckpos;
251: extern char Msgbuf[];
252:
253: werase(Compwin);
254:
255: knownum = 0;
256: deckpos = deal(mycrib);
257: sorthand(chand, FULLHAND);
258: sorthand(phand, FULLHAND);
259: makeknown(chand, FULLHAND);
260: prhand(phand, FULLHAND, Playwin, FALSE);
261: discard(mycrib);
262: if (cut(mycrib, deckpos))
263: return TRUE;
264: if (peg(mycrib))
265: return TRUE;
266: werase(Tablewin);
267: wrefresh(Tablewin);
268: if (score(mycrib))
269: return TRUE;
270: return FALSE;
271: }
272:
273:
274:
275: /*
276: * deal cards to both players from deck
277: */
278:
279: deal( mycrib )
280: {
281: register int i, j;
282:
283: j = 0;
284: for( i = 0; i < FULLHAND; i++ ) {
285: if( mycrib ) {
286: phand[i] = deck[j++];
287: chand[i] = deck[j++];
288: }
289: else {
290: chand[i] = deck[j++];
291: phand[i] = deck[j++];
292: }
293: }
294: return( j );
295: }
296:
297: /*
298: * discard:
299: * Handle players discarding into the crib...
300: * Note: we call cdiscard() after prining first message so player doesn't wait
301: */
302: discard(mycrib)
303: BOOLEAN mycrib;
304: {
305: register char *prompt;
306: CARD crd;
307:
308: prcrib(mycrib, TRUE);
309: prompt = (quiet ? "Discard --> " : "Discard a card --> ");
310: cdiscard(mycrib); /* puts best discard at end */
311: crd = phand[infrom(phand, FULLHAND, prompt)];
312: remove(crd, phand, FULLHAND);
313: prhand(phand, FULLHAND, Playwin, FALSE);
314: crib[0] = crd;
315: /* next four lines same as last four except for cdiscard() */
316: crd = phand[infrom(phand, FULLHAND - 1, prompt)];
317: remove(crd, phand, FULLHAND - 1);
318: prhand(phand, FULLHAND, Playwin, FALSE);
319: crib[1] = crd;
320: crib[2] = chand[4];
321: crib[3] = chand[5];
322: chand[4].rank = chand[4].suit = chand[5].rank = chand[5].suit = EMPTY;
323: }
324:
325: /*
326: * cut:
327: * Cut the deck and set turnover. Actually, we only ASK the
328: * player what card to turn. We do a random one, anyway.
329: */
330: cut(mycrib, pos)
331: BOOLEAN mycrib;
332: int pos;
333: {
334: register int i, cardx;
335: BOOLEAN win = FALSE;
336:
337: if (mycrib) {
338: if (!rflag) { /* random cut */
339: msg(quiet ? "Cut the deck? " :
340: "How many cards down do you wish to cut the deck? ");
341: getline();
342: }
343: i = (rand() >> 4) % (CARDS - pos);
344: turnover = deck[i + pos];
345: addmsg(quiet ? "You cut " : "You cut the ");
346: msgcard(turnover, FALSE);
347: endmsg();
348: if (turnover.rank == JACK) {
349: msg("I get two for his heels");
350: win = chkscr(&cscore,2 );
351: }
352: }
353: else {
354: i = (rand() >> 4) % (CARDS - pos) + pos;
355: turnover = deck[i];
356: addmsg(quiet ? "I cut " : "I cut the ");
357: msgcard(turnover, FALSE);
358: endmsg();
359: if (turnover.rank == JACK) {
360: msg("You get two for his heels");
361: win = chkscr(&pscore, 2);
362: }
363: }
364: makeknown(&turnover, 1);
365: prcrib(mycrib, FALSE);
366: return win;
367: }
368:
369: /*
370: * prcrib:
371: * Print out the turnover card with crib indicator
372: */
373: prcrib(mycrib, blank)
374: BOOLEAN mycrib, blank;
375: {
376: register int y, cardx;
377:
378: if (mycrib)
379: cardx = CRIB_X;
380: else
381: cardx = 0;
382:
383: mvaddstr(CRIB_Y, cardx + 1, "CRIB");
384: prcard(stdscr, CRIB_Y + 1, cardx, turnover, blank);
385:
386: if (mycrib)
387: cardx = 0;
388: else
389: cardx = CRIB_X;
390:
391: for (y = CRIB_Y; y <= CRIB_Y + 5; y++)
392: mvaddstr(y, cardx, " ");
393: }
394:
395: /*
396: * peg:
397: * Handle all the pegging...
398: */
399:
400: static CARD Table[14];
401:
402: static int Tcnt;
403:
404: peg(mycrib)
405: BOOLEAN mycrib;
406: {
407: static CARD ch[CINHAND], ph[CINHAND];
408: CARD crd;
409: register int i, j, k;
410: register int l;
411: register int cnum, pnum, sum;
412: register BOOLEAN myturn, mego, ugo, last, played;
413:
414: cnum = pnum = CINHAND;
415: for (i = 0; i < CINHAND; i++) { /* make copies of hands */
416: ch[i] = chand[i];
417: ph[i] = phand[i];
418: }
419: Tcnt = 0; /* index to table of cards played */
420: sum = 0; /* sum of cards played */
421: mego = ugo = FALSE;
422: myturn = !mycrib;
423: for (;;) {
424: last = TRUE; /* enable last flag */
425: prhand(ph, pnum, Playwin, FALSE);
426: prhand(ch, cnum, Compwin, TRUE);
427: prtable(sum);
428: if (myturn) { /* my tyrn to play */
429: if (!anymove(ch, cnum, sum)) { /* if no card to play */
430: if (!mego && cnum) { /* go for comp? */
431: msg("GO");
432: mego = TRUE;
433: }
434: if (anymove(ph, pnum, sum)) /* can player move? */
435: myturn = !myturn;
436: else { /* give him his point */
437: msg(quiet ? "You get one" : "You get one point");
438: if (chkscr(&pscore, 1))
439: return TRUE;
440: sum = 0;
441: mego = ugo = FALSE;
442: Tcnt = 0;
443: }
444: }
445: else {
446: played = TRUE;
447: j = -1;
448: k = 0;
449: for (i = 0; i < cnum; i++) { /* maximize score */
450: l = pegscore(ch[i], Table, Tcnt, sum);
451: if (l > k) {
452: k = l;
453: j = i;
454: }
455: }
456: if (j < 0) /* if nothing scores */
457: j = cchose(ch, cnum, sum);
458: crd = ch[j];
459: remove(crd, ch, cnum--);
460: sum += VAL(crd.rank);
461: Table[Tcnt++] = crd;
462: if (k > 0) {
463: addmsg(quiet ? "I get %d playing " :
464: "I get %d points playing ", k);
465: msgcard(crd, FALSE);
466: endmsg();
467: if (chkscr(&cscore, k))
468: return TRUE;
469: }
470: myturn = !myturn;
471: }
472: }
473: else {
474: if (!anymove(ph, pnum, sum)) { /* can player move? */
475: if (!ugo && pnum) { /* go for player */
476: msg("You have a GO");
477: ugo = TRUE;
478: }
479: if (anymove(ch, cnum, sum)) /* can computer play? */
480: myturn = !myturn;
481: else {
482: msg(quiet ? "I get one" : "I get one point");
483: do_wait();
484: if (chkscr(&cscore, 1))
485: return TRUE;
486: sum = 0;
487: mego = ugo = FALSE;
488: Tcnt = 0;
489: }
490: }
491: else { /* player plays */
492: played = FALSE;
493: if (pnum == 1) {
494: crd = ph[0];
495: msg("You play your last card");
496: }
497: else
498: for (;;) {
499: prhand(ph, pnum, Playwin, FALSE);
500: crd = ph[infrom(ph, pnum, "Your play: ")];
501: if (sum + VAL(crd.rank) <= 31)
502: break;
503: else
504: msg("Total > 31 -- try again");
505: }
506: makeknown(&crd, 1);
507: remove(crd, ph, pnum--);
508: i = pegscore(crd, Table, Tcnt, sum);
509: sum += VAL(crd.rank);
510: Table[Tcnt++] = crd;
511: if (i > 0) {
512: msg(quiet ? "You got %d" : "You got %d points", i);
513: if (chkscr(&pscore, i))
514: return TRUE;
515: }
516: myturn = !myturn;
517: }
518: }
519: if (sum >= 31) {
520: if (!myturn)
521: do_wait();
522: sum = 0;
523: mego = ugo = FALSE;
524: Tcnt = 0;
525: last = FALSE; /* disable last flag */
526: }
527: if (!pnum && !cnum)
528: break; /* both done */
529: }
530: prhand(ph, pnum, Playwin, FALSE);
531: prhand(ch, cnum, Compwin, TRUE);
532: prtable(sum);
533: if (last)
534: if (played) {
535: msg(quiet ? "I get one for last" : "I get one point for last");
536: do_wait();
537: if (chkscr(&cscore, 1))
538: return TRUE;
539: }
540: else {
541: msg(quiet ? "You get one for last" :
542: "You get one point for last");
543: if (chkscr(&pscore, 1))
544: return TRUE;
545: }
546: return FALSE;
547: }
548:
549: /*
550: * prtable:
551: * Print out the table with the current score
552: */
553: prtable(score)
554: int score;
555: {
556: prhand(Table, Tcnt, Tablewin, FALSE);
557: mvwprintw(Tablewin, (Tcnt + 2) * 2, Tcnt + 1, "%2d", score);
558: wrefresh(Tablewin);
559: }
560:
561: /*
562: * score:
563: * Handle the scoring of the hands
564: */
565: score(mycrib)
566: BOOLEAN mycrib;
567: {
568: sorthand(crib, CINHAND);
569: if (mycrib) {
570: if (plyrhand(phand, "hand"))
571: return TRUE;
572: if (comphand(chand, "hand"))
573: return TRUE;
574: do_wait();
575: if (comphand(crib, "crib"))
576: return TRUE;
577: }
578: else {
579: if (comphand(chand, "hand"))
580: return TRUE;
581: if (plyrhand(phand, "hand"))
582: return TRUE;
583: if (plyrhand(crib, "crib"))
584: return TRUE;
585: }
586: return FALSE;
587: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.