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