add primes
[unix-history] / usr / src / games / cribbage / io.c
CommitLineData
6cca9b39
KM
1/*
2 * Copyright (c) 1980 Regents of the University of California.
bf870064
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
b8c620d6
KB
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.
6cca9b39
KM
16 */
17
18#ifndef lint
b8c620d6 19static char sccsid[] = "@(#)io.c 5.4 (Berkeley) %G%";
bf870064 20#endif /* not lint */
9a6fbd6d 21
5836528f
KA
22# include <curses.h>
23# include <ctype.h>
f870d435 24# include <signal.h>
5836528f
KA
25# include "deck.h"
26# include "cribbage.h"
39911be8 27# include "cribcur.h"
cd994cb6 28
5836528f 29# define LINESIZE 128
cd994cb6 30
39911be8
KA
31# ifdef CTRL
32# undef CTRL
33# endif
5836528f
KA
34# define CTRL(X) ('X' - 'A' + 1)
35
23fac13b 36# ifdef notdef /* defined in curses.h */
5836528f
KA
37# define erasechar() _tty.sg_erase
38# define killchar() _tty.sg_kill
23fac13b 39# endif
cd994cb6
KA
40
41char linebuf[ LINESIZE ];
42
43char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR",
5836528f
KA
44 "FIVE", "SIX", "SEVEN", "EIGHT",
45 "NINE", "TEN", "JACK", "QUEEN",
46 "KING" };
cd994cb6
KA
47
48char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7",
5836528f 49 "8", "9", "T", "J", "Q", "K" };
cd994cb6
KA
50
51char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS",
5836528f 52 "CLUBS" };
cd994cb6
KA
53
54char *suitchar[ SUITS ] = { "S", "H", "D", "C" };
55
56
57
58/*
5836528f
KA
59 * msgcard:
60 * Call msgcrd in one of two forms
cd994cb6 61 */
5836528f
KA
62msgcard(c, brief)
63CARD c;
64BOOLEAN brief;
cd994cb6 65{
5836528f
KA
66 if (brief)
67 return msgcrd(c, TRUE, (char *) NULL, TRUE);
68 else
69 return msgcrd(c, FALSE, " of ", FALSE);
cd994cb6
KA
70}
71
72
73
74/*
5836528f
KA
75 * msgcrd:
76 * Print the value of a card in ascii
cd994cb6 77 */
5836528f
KA
78msgcrd(c, brfrank, mid, brfsuit)
79CARD c;
80char *mid;
81BOOLEAN brfrank, brfsuit;
cd994cb6 82{
5836528f
KA
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;
cd994cb6
KA
96}
97
cd994cb6 98/*
5836528f
KA
99 * printcard:
100 * Print out a card.
cd994cb6 101 */
5dc185f5 102printcard(win, cardno, c, blank)
5836528f
KA
103WINDOW *win;
104int cardno;
105CARD c;
5dc185f5 106BOOLEAN blank;
5836528f 107{
5dc185f5 108 prcard(win, cardno * 2, cardno, c, blank);
5836528f 109}
cd994cb6 110
5836528f
KA
111/*
112 * prcard:
113 * Print out a card on the window at the specified location
114 */
f62fed8c 115prcard(win, y, x, c, blank)
5836528f
KA
116WINDOW *win;
117int y, x;
118CARD c;
f62fed8c 119BOOLEAN blank;
5836528f
KA
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, "+-----+");
f62fed8c
KA
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 }
5836528f 134}
cd994cb6 135
5836528f
KA
136/*
137 * prhand:
138 * Print a hand of n cards
139 */
5dc185f5 140prhand(h, n, win, blank)
5836528f
KA
141CARD h[];
142int n;
143WINDOW *win;
5dc185f5 144BOOLEAN blank;
cd994cb6 145{
5836528f
KA
146 register int i;
147
148 werase(win);
149 for (i = 0; i < n; i++)
5dc185f5 150 printcard(win, i, *h++, blank);
5836528f 151 wrefresh(win);
cd994cb6
KA
152}
153
154
155
156/*
5836528f
KA
157 * infrom:
158 * reads a card, supposedly in hand, accepting unambigous brief
159 * input, returns the index of the card found...
cd994cb6 160 */
5836528f
KA
161infrom(hand, n, prompt)
162CARD hand[];
163int n;
164char *prompt;
cd994cb6 165{
5836528f
KA
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 (;;) {
59d2ab16 174 msg(prompt);
5836528f
KA
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");
5836528f
KA
209 }
210 /* NOTREACHED */
cd994cb6
KA
211}
212
213
214
215/*
5836528f
KA
216 * incard:
217 * Inputs a card in any format. It reads a line ending with a CR
218 * and then parses it.
cd994cb6 219 */
5836528f
KA
220incard(crd)
221CARD *crd;
cd994cb6 222{
5836528f
KA
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;
cd994cb6 284gotit:
5836528f
KA
285 (*crd).rank = rnk;
286 (*crd).suit = sut;
287 return( retval );
cd994cb6
KA
288}
289
290
291
292/*
5836528f
KA
293 * getuchar:
294 * Reads and converts to upper case
cd994cb6 295 */
cd994cb6
KA
296getuchar()
297{
5836528f 298 register int c;
cd994cb6 299
5836528f
KA
300 c = readchar();
301 if (islower(c))
302 c = toupper(c);
39911be8 303 waddch(Msgwin, c);
5836528f 304 return c;
cd994cb6
KA
305}
306
cd994cb6 307/*
d864f6e8
KA
308 * number:
309 * Reads in a decimal number and makes sure it is between "lo" and
310 * "hi" inclusive.
cd994cb6 311 */
d864f6e8
KA
312number(lo, hi, prompt)
313int lo, hi;
314char *prompt;
cd994cb6 315{
d864f6e8
KA
316 char *getline();
317 register char *p;
318 register int sum;
5836528f
KA
319
320 sum = 0;
d864f6e8
KA
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 }
5836528f 327 sum = 0;
d864f6e8
KA
328
329 if (!isdigit(*p))
5836528f 330 sum = lo - 1;
d864f6e8
KA
331 else
332 while (isdigit(*p)) {
333 sum = 10 * sum + (*p - '0');
5836528f 334 ++p;
d864f6e8
KA
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 }
cd994cb6
KA
347}
348
5836528f
KA
349/*
350 * msg:
351 * Display a message at the top of the screen.
352 */
62136f2a 353char Msgbuf[BUFSIZ] = { '\0' };
5836528f
KA
354
355int Mpos = 0;
cd994cb6 356
5836528f
KA
357static int Newpos = 0;
358
359/* VARARGS1 */
360msg(fmt, args)
361char *fmt;
362int args;
363{
5836528f
KA
364 doadd(fmt, &args);
365 endmsg();
366}
cd994cb6
KA
367
368/*
5836528f
KA
369 * addmsg:
370 * Add things to the current message
cd994cb6 371 */
5836528f
KA
372/* VARARGS1 */
373addmsg(fmt, args)
374char *fmt;
375int args;
376{
377 doadd(fmt, &args);
378}
cd994cb6 379
5836528f
KA
380/*
381 * endmsg:
39911be8 382 * Display a new msg.
5836528f 383 */
f6867294
KA
384
385int Lineno = 0;
386
5836528f 387endmsg()
cd994cb6 388{
39911be8
KA
389 register int len;
390 register char *mp, *omp;
f6867294 391 static int lastline = 0;
39911be8 392
5836528f 393 /*
f6867294 394 * All messages should start with uppercase
5836528f 395 */
f6867294 396 mvaddch(lastline + Y_MSG_START, SCORE_X, ' ');
5836528f
KA
397 if (islower(Msgbuf[0]) && Msgbuf[1] != ')')
398 Msgbuf[0] = toupper(Msgbuf[0]);
39911be8
KA
399 mp = Msgbuf;
400 len = strlen(mp);
ecbc5dbf
KA
401 if (len / MSG_X + Lineno >= MSG_Y) {
402 while (Lineno < MSG_Y) {
403 wmove(Msgwin, Lineno++, 0);
404 wclrtoeol(Msgwin);
405 }
f6867294 406 Lineno = 0;
ecbc5dbf 407 }
f6867294
KA
408 mvaddch(Lineno + Y_MSG_START, SCORE_X, '*');
409 lastline = Lineno;
39911be8 410 do {
f6867294 411 mvwaddstr(Msgwin, Lineno, 0, mp);
39911be8
KA
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++;
f6867294 419 wmove(Msgwin, Lineno, mp - omp);
39911be8
KA
420 wclrtoeol(Msgwin);
421 }
f6867294
KA
422 if (++Lineno >= MSG_Y)
423 Lineno = 0;
39911be8
KA
424 } while (len > MSG_X);
425 wclrtoeol(Msgwin);
ecbc5dbf 426 Mpos = len;
5836528f 427 Newpos = 0;
39911be8 428 wrefresh(Msgwin);
5836528f 429 refresh();
39911be8 430 wrefresh(Msgwin);
cd994cb6
KA
431}
432
5836528f
KA
433/*
434 * doadd:
435 * Perform an add onto the message buffer
436 */
437doadd(fmt, args)
438char *fmt;
439int *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}
cd994cb6 453
f6867294
KA
454/*
455 * do_wait:
456 * Wait for the user to type ' ' before doing anything else
457 */
458do_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
5836528f
KA
476/*
477 * wait_for
478 * Sit around until the guy types the right key
479 */
480wait_for(ch)
481register 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}
cd994cb6 492
5836528f
KA
493/*
494 * readchar:
495 * Reads and returns a character, checking for gross input errors
496 */
497readchar()
498{
499 register int cnt, y, x;
500 auto char c;
501
502over:
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 }
5836528f
KA
511 if (c == '\r')
512 return '\n';
513 else
514 return c;
515}
cd994cb6 516
5836528f
KA
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 */
522char *
523getline()
524{
525 register char *sp;
526 register int c, oy, ox;
39911be8 527 register WINDOW *oscr;
5836528f 528
39911be8
KA
529 oscr = stdscr;
530 stdscr = Msgwin;
5836528f
KA
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));
5836528f
KA
563 Mpos++;
564 }
565 }
566 *sp = '\0';
39911be8 567 stdscr = oscr;
5836528f
KA
568 return linebuf;
569}
f870d435
KA
570
571/*
572 * bye:
573 * Leave the program, cleaning things up as we go.
574 */
575bye()
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}