|
|
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: static char sccsid[] = "@(#)io.c 5.4 (Berkeley) 6/18/88";
20: #endif /* not lint */
21:
22: # include <curses.h>
23: # include <ctype.h>
24: # include <signal.h>
25: # include "deck.h"
26: # include "cribbage.h"
27: # include "cribcur.h"
28:
29: # define LINESIZE 128
30:
31: # ifdef CTRL
32: # undef CTRL
33: # endif
34: # define CTRL(X) ('X' - 'A' + 1)
35:
36: # ifdef notdef /* defined in curses.h */
37: # define erasechar() _tty.sg_erase
38: # define killchar() _tty.sg_kill
39: # endif
40:
41: char linebuf[ LINESIZE ];
42:
43: char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR",
44: "FIVE", "SIX", "SEVEN", "EIGHT",
45: "NINE", "TEN", "JACK", "QUEEN",
46: "KING" };
47:
48: char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7",
49: "8", "9", "T", "J", "Q", "K" };
50:
51: char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS",
52: "CLUBS" };
53:
54: char *suitchar[ SUITS ] = { "S", "H", "D", "C" };
55:
56:
57:
58: /*
59: * msgcard:
60: * Call msgcrd in one of two forms
61: */
62: msgcard(c, brief)
63: CARD c;
64: BOOLEAN brief;
65: {
66: if (brief)
67: return msgcrd(c, TRUE, (char *) NULL, TRUE);
68: else
69: return msgcrd(c, FALSE, " of ", FALSE);
70: }
71:
72:
73:
74: /*
75: * msgcrd:
76: * Print the value of a card in ascii
77: */
78: msgcrd(c, brfrank, mid, brfsuit)
79: CARD c;
80: char *mid;
81: BOOLEAN brfrank, brfsuit;
82: {
83: if (c.rank == EMPTY || c.suit == EMPTY)
84: return FALSE;
85: if (brfrank)
86: addmsg("%1.1s", rankchar[c.rank]);
87: else
88: addmsg(rankname[c.rank]);
89: if (mid != NULL)
90: addmsg(mid);
91: if (brfsuit)
92: addmsg("%1.1s", suitchar[c.suit]);
93: else
94: addmsg(suitname[c.suit]);
95: return TRUE;
96: }
97:
98: /*
99: * printcard:
100: * Print out a card.
101: */
102: printcard(win, cardno, c, blank)
103: WINDOW *win;
104: int cardno;
105: CARD c;
106: BOOLEAN blank;
107: {
108: prcard(win, cardno * 2, cardno, c, blank);
109: }
110:
111: /*
112: * prcard:
113: * Print out a card on the window at the specified location
114: */
115: prcard(win, y, x, c, blank)
116: WINDOW *win;
117: int y, x;
118: CARD c;
119: BOOLEAN blank;
120: {
121: if (c.rank == EMPTY)
122: return;
123: mvwaddstr(win, y + 0, x, "+-----+");
124: mvwaddstr(win, y + 1, x, "| |");
125: mvwaddstr(win, y + 2, x, "| |");
126: mvwaddstr(win, y + 3, x, "| |");
127: mvwaddstr(win, y + 4, x, "+-----+");
128: if (!blank) {
129: mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]);
130: waddch(win, suitchar[c.suit][0]);
131: mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]);
132: waddch(win, suitchar[c.suit][0]);
133: }
134: }
135:
136: /*
137: * prhand:
138: * Print a hand of n cards
139: */
140: prhand(h, n, win, blank)
141: CARD h[];
142: int n;
143: WINDOW *win;
144: BOOLEAN blank;
145: {
146: register int i;
147:
148: werase(win);
149: for (i = 0; i < n; i++)
150: printcard(win, i, *h++, blank);
151: wrefresh(win);
152: }
153:
154:
155:
156: /*
157: * infrom:
158: * reads a card, supposedly in hand, accepting unambigous brief
159: * input, returns the index of the card found...
160: */
161: infrom(hand, n, prompt)
162: CARD hand[];
163: int n;
164: char *prompt;
165: {
166: register int i, j;
167: CARD crd;
168:
169: if (n < 1) {
170: printf("\nINFROM: %d = n < 1!!\n", n);
171: exit(74);
172: }
173: for (;;) {
174: msg(prompt);
175: if (incard(&crd)) { /* if card is full card */
176: if (!isone(crd, hand, n))
177: msg("That's not in your hand");
178: else {
179: for (i = 0; i < n; i++)
180: if (hand[i].rank == crd.rank &&
181: hand[i].suit == crd.suit)
182: break;
183: if (i >= n) {
184: printf("\nINFROM: isone or something messed up\n");
185: exit(77);
186: }
187: return i;
188: }
189: }
190: else /* if not full card... */
191: if (crd.rank != EMPTY) {
192: for (i = 0; i < n; i++)
193: if (hand[i].rank == crd.rank)
194: break;
195: if (i >= n)
196: msg("No such rank in your hand");
197: else {
198: for (j = i + 1; j < n; j++)
199: if (hand[j].rank == crd.rank)
200: break;
201: if (j < n)
202: msg("Ambiguous rank");
203: else
204: return i;
205: }
206: }
207: else
208: msg("Sorry, I missed that");
209: }
210: /* NOTREACHED */
211: }
212:
213:
214:
215: /*
216: * incard:
217: * Inputs a card in any format. It reads a line ending with a CR
218: * and then parses it.
219: */
220: incard(crd)
221: CARD *crd;
222: {
223: char *getline();
224: register int i;
225: int rnk, sut;
226: char *line, *p, *p1;
227: BOOLEAN retval;
228:
229: retval = FALSE;
230: rnk = sut = EMPTY;
231: if (!(line = getline()))
232: goto gotit;
233: p = p1 = line;
234: while( *p1 != ' ' && *p1 != NULL ) ++p1;
235: *p1++ = NULL;
236: if( *p == NULL ) goto gotit;
237: /* IMPORTANT: no real card has 2 char first name */
238: if( strlen(p) == 2 ) { /* check for short form */
239: rnk = EMPTY;
240: for( i = 0; i < RANKS; i++ ) {
241: if( *p == *rankchar[i] ) {
242: rnk = i;
243: break;
244: }
245: }
246: if( rnk == EMPTY ) goto gotit; /* it's nothing... */
247: ++p; /* advance to next char */
248: sut = EMPTY;
249: for( i = 0; i < SUITS; i++ ) {
250: if( *p == *suitchar[i] ) {
251: sut = i;
252: break;
253: }
254: }
255: if( sut != EMPTY ) retval = TRUE;
256: goto gotit;
257: }
258: rnk = EMPTY;
259: for( i = 0; i < RANKS; i++ ) {
260: if( !strcmp( p, rankname[i] ) || !strcmp( p, rankchar[i] ) ) {
261: rnk = i;
262: break;
263: }
264: }
265: if( rnk == EMPTY ) goto gotit;
266: p = p1;
267: while( *p1 != ' ' && *p1 != NULL ) ++p1;
268: *p1++ = NULL;
269: if( *p == NULL ) goto gotit;
270: if( !strcmp( "OF", p ) ) {
271: p = p1;
272: while( *p1 != ' ' && *p1 != NULL ) ++p1;
273: *p1++ = NULL;
274: if( *p == NULL ) goto gotit;
275: }
276: sut = EMPTY;
277: for( i = 0; i < SUITS; i++ ) {
278: if( !strcmp( p, suitname[i] ) || !strcmp( p, suitchar[i] ) ) {
279: sut = i;
280: break;
281: }
282: }
283: if( sut != EMPTY ) retval = TRUE;
284: gotit:
285: (*crd).rank = rnk;
286: (*crd).suit = sut;
287: return( retval );
288: }
289:
290:
291:
292: /*
293: * getuchar:
294: * Reads and converts to upper case
295: */
296: getuchar()
297: {
298: register int c;
299:
300: c = readchar();
301: if (islower(c))
302: c = toupper(c);
303: waddch(Msgwin, c);
304: return c;
305: }
306:
307: /*
308: * number:
309: * Reads in a decimal number and makes sure it is between "lo" and
310: * "hi" inclusive.
311: */
312: number(lo, hi, prompt)
313: int lo, hi;
314: char *prompt;
315: {
316: char *getline();
317: register char *p;
318: register int sum;
319:
320: sum = 0;
321: for (;;) {
322: msg(prompt);
323: if(!(p = getline()) || *p == NULL) {
324: msg(quiet ? "Not a number" : "That doesn't look like a number");
325: continue;
326: }
327: sum = 0;
328:
329: if (!isdigit(*p))
330: sum = lo - 1;
331: else
332: while (isdigit(*p)) {
333: sum = 10 * sum + (*p - '0');
334: ++p;
335: }
336:
337: if (*p != ' ' && *p != '\t' && *p != NULL)
338: sum = lo - 1;
339: if (sum >= lo && sum <= hi)
340: return sum;
341: if (sum == lo - 1)
342: msg("that doesn't look like a number, try again --> ");
343: else
344: msg("%d is not between %d and %d inclusive, try again --> ",
345: sum, lo, hi);
346: }
347: }
348:
349: /*
350: * msg:
351: * Display a message at the top of the screen.
352: */
353: char Msgbuf[BUFSIZ] = { '\0' };
354:
355: int Mpos = 0;
356:
357: static int Newpos = 0;
358:
359: /* VARARGS1 */
360: msg(fmt, args)
361: char *fmt;
362: int args;
363: {
364: doadd(fmt, &args);
365: endmsg();
366: }
367:
368: /*
369: * addmsg:
370: * Add things to the current message
371: */
372: /* VARARGS1 */
373: addmsg(fmt, args)
374: char *fmt;
375: int args;
376: {
377: doadd(fmt, &args);
378: }
379:
380: /*
381: * endmsg:
382: * Display a new msg.
383: */
384:
385: int Lineno = 0;
386:
387: endmsg()
388: {
389: register int len;
390: register char *mp, *omp;
391: static int lastline = 0;
392:
393: /*
394: * All messages should start with uppercase
395: */
396: mvaddch(lastline + Y_MSG_START, SCORE_X, ' ');
397: if (islower(Msgbuf[0]) && Msgbuf[1] != ')')
398: Msgbuf[0] = toupper(Msgbuf[0]);
399: mp = Msgbuf;
400: len = strlen(mp);
401: if (len / MSG_X + Lineno >= MSG_Y) {
402: while (Lineno < MSG_Y) {
403: wmove(Msgwin, Lineno++, 0);
404: wclrtoeol(Msgwin);
405: }
406: Lineno = 0;
407: }
408: mvaddch(Lineno + Y_MSG_START, SCORE_X, '*');
409: lastline = Lineno;
410: do {
411: mvwaddstr(Msgwin, Lineno, 0, mp);
412: if ((len = strlen(mp)) > MSG_X) {
413: omp = mp;
414: for (mp = &mp[MSG_X-1]; *mp != ' '; mp--)
415: continue;
416: while (*mp == ' ')
417: mp--;
418: mp++;
419: wmove(Msgwin, Lineno, mp - omp);
420: wclrtoeol(Msgwin);
421: }
422: if (++Lineno >= MSG_Y)
423: Lineno = 0;
424: } while (len > MSG_X);
425: wclrtoeol(Msgwin);
426: Mpos = len;
427: Newpos = 0;
428: wrefresh(Msgwin);
429: refresh();
430: wrefresh(Msgwin);
431: }
432:
433: /*
434: * doadd:
435: * Perform an add onto the message buffer
436: */
437: doadd(fmt, args)
438: char *fmt;
439: int *args;
440: {
441: static FILE junk;
442:
443: /*
444: * Do the printf into Msgbuf
445: */
446: junk._flag = _IOWRT + _IOSTRG;
447: junk._ptr = &Msgbuf[Newpos];
448: junk._cnt = 32767;
449: _doprnt(fmt, args, &junk);
450: putc('\0', &junk);
451: Newpos = strlen(Msgbuf);
452: }
453:
454: /*
455: * do_wait:
456: * Wait for the user to type ' ' before doing anything else
457: */
458: do_wait()
459: {
460: register int line;
461: static char prompt[] = { '-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0' };
462:
463: if (Mpos + sizeof prompt < MSG_X)
464: wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos);
465: else {
466: mvwaddch(Msgwin, Lineno, 0, ' ');
467: wclrtoeol(Msgwin);
468: if (++Lineno >= MSG_Y)
469: Lineno = 0;
470: }
471: waddstr(Msgwin, prompt);
472: wrefresh(Msgwin);
473: wait_for(' ');
474: }
475:
476: /*
477: * wait_for
478: * Sit around until the guy types the right key
479: */
480: wait_for(ch)
481: register char ch;
482: {
483: register char c;
484:
485: if (ch == '\n')
486: while ((c = readchar()) != '\n')
487: continue;
488: else
489: while (readchar() != ch)
490: continue;
491: }
492:
493: /*
494: * readchar:
495: * Reads and returns a character, checking for gross input errors
496: */
497: readchar()
498: {
499: register int cnt, y, x;
500: auto char c;
501:
502: over:
503: cnt = 0;
504: while (read(0, &c, 1) <= 0)
505: if (cnt++ > 100) /* if we are getting infinite EOFs */
506: bye(); /* quit the game */
507: if (c == CTRL(L)) {
508: wrefresh(curscr);
509: goto over;
510: }
511: if (c == '\r')
512: return '\n';
513: else
514: return c;
515: }
516:
517: /*
518: * getline:
519: * Reads the next line up to '\n' or EOF. Multiple spaces are
520: * compressed to one space; a space is inserted before a ','
521: */
522: char *
523: getline()
524: {
525: register char *sp;
526: register int c, oy, ox;
527: register WINDOW *oscr;
528:
529: oscr = stdscr;
530: stdscr = Msgwin;
531: getyx(stdscr, oy, ox);
532: refresh();
533: /*
534: * loop reading in the string, and put it in a temporary buffer
535: */
536: for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) {
537: if (c == -1)
538: continue;
539: else if (c == erasechar()) { /* process erase character */
540: if (sp > linebuf) {
541: register int i;
542:
543: sp--;
544: for (i = strlen(unctrl(*sp)); i; i--)
545: addch('\b');
546: }
547: continue;
548: }
549: else if (c == killchar()) { /* process kill character */
550: sp = linebuf;
551: move(oy, ox);
552: continue;
553: }
554: else if (sp == linebuf && c == ' ')
555: continue;
556: if (sp >= &linebuf[LINESIZE-1] || !(isprint(c) || c == ' '))
557: putchar(CTRL(G));
558: else {
559: if (islower(c))
560: c = toupper(c);
561: *sp++ = c;
562: addstr(unctrl(c));
563: Mpos++;
564: }
565: }
566: *sp = '\0';
567: stdscr = oscr;
568: return linebuf;
569: }
570:
571: /*
572: * bye:
573: * Leave the program, cleaning things up as we go.
574: */
575: bye()
576: {
577: signal(SIGINT, SIG_IGN);
578: mvcur(0, COLS - 1, LINES - 1, 0);
579: fflush(stdout);
580: endwin();
581: putchar('\n');
582: exit(1);
583: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.