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