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