Commit | Line | Data |
---|---|---|
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 | |
16 | char linebuf[ LINESIZE ]; | |
17 | ||
18 | char *rankname[ RANKS ] = { "ACE", "TWO", "THREE", "FOUR", | |
5836528f KA |
19 | "FIVE", "SIX", "SEVEN", "EIGHT", |
20 | "NINE", "TEN", "JACK", "QUEEN", | |
21 | "KING" }; | |
cd994cb6 KA |
22 | |
23 | char *rankchar[ RANKS ] = { "A", "2", "3", "4", "5", "6", "7", | |
5836528f | 24 | "8", "9", "T", "J", "Q", "K" }; |
cd994cb6 KA |
25 | |
26 | char *suitname[ SUITS ] = { "SPADES", "HEARTS", "DIAMONDS", | |
5836528f | 27 | "CLUBS" }; |
cd994cb6 KA |
28 | |
29 | char *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 |
37 | msgcard(c, brief) |
38 | CARD c; | |
39 | BOOLEAN 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 |
53 | msgcrd(c, brfrank, mid, brfsuit) |
54 | CARD c; | |
55 | char *mid; | |
56 | BOOLEAN 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 |
77 | printcard(win, cardno, c) |
78 | WINDOW *win; | |
79 | int cardno; | |
80 | CARD 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 | */ | |
89 | prcard(win, y, x, c) | |
90 | WINDOW *win; | |
91 | int y, x; | |
92 | CARD 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 | */ | |
111 | prhand(h, n, win) | |
112 | CARD h[]; | |
113 | int n; | |
114 | WINDOW *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 |
131 | infrom(hand, n, prompt) |
132 | CARD hand[]; | |
133 | int n; | |
134 | char *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 |
190 | incard(crd) |
191 | CARD *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 | 254 | gotit: |
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 |
266 | getuchar() |
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 | ||
285 | number( 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 | */ | |
325 | char Msgbuf[BUFSIZ] = ""; | |
326 | ||
327 | int Mpos = 0; | |
cd994cb6 | 328 | |
5836528f KA |
329 | static int Newpos = 0; |
330 | ||
331 | /* VARARGS1 */ | |
332 | msg(fmt, args) | |
333 | char *fmt; | |
334 | int 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 */ |
358 | addmsg(fmt, args) | |
359 | char *fmt; | |
360 | int 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 | */ | |
370 | endmsg() | |
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 | */ | |
396 | doadd(fmt, args) | |
397 | char *fmt; | |
398 | int *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 | */ | |
417 | wait_for(ch) | |
418 | register 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 | */ | |
434 | readchar() | |
435 | { | |
436 | register int cnt, y, x; | |
437 | auto char c; | |
438 | ||
439 | over: | |
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 | */ | |
460 | char * | |
461 | getline() | |
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 | } |