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