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