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