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