|
|
1.1 root 1: /*
2: * Hunt
3: * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
4: * San Francisco, California
5: *
6: * Copyright (c) 1985 Regents of the University of California.
7: * All rights reserved. The Berkeley software License Agreement
8: * specifies the terms and conditions for redistribution.
9: */
10:
11: # include <curses.h>
12: # include <ctype.h>
13: # include <signal.h>
14: # include <errno.h>
15: # include "hunt.h"
16: # include <sys/file.h>
17: # ifdef TERMINFO
18: # include <term.h>
19:
20: # define AM auto_right_margin
21: # define XN eat_newline_glitch
22: # define CL clear_screen
23: # define CE clr_eol
24: # define _putchar _outchar
25: # endif
26:
27: int input();
28: static int nchar_send;
29: static int in = FREAD;
30: char screen[SCREEN_HEIGHT][SCREEN_WIDTH2], blanks[SCREEN_WIDTH];
31: int cur_row, cur_col;
32: # ifdef OTTO
33: int Otto_count;
34: int Otto_mode;
35: static int otto_y, otto_x;
36: static char otto_face;
37: # endif OTTO
38:
39: # define MAX_SEND 5
40:
41: /*
42: * ibuf is the input buffer used for the stream from the driver.
43: * It is small because we do not check for user input when there
44: * are characters in the input buffer.
45: */
46: static char ibuf[20];
47:
48: #define GETCHR(fd) (--(fd)->_cnt < 0 ? getchr(fd) \
49: : *((unsigned char *) (fd)->_ptr++))
50:
51: /*
52: * playit:
53: * Play a given game, handling all the curses commands from
54: * the driver.
55: */
56: playit()
57: {
58: register FILE *inf;
59: register int ch;
60: register int y, x;
61: extern int errno;
62: extern int _putchar();
63: long version;
64:
65: if (read(Socket, (char *) &version, LONGLEN) != LONGLEN) {
66: bad_con();
67: /* NOTREACHED */
68: }
69: if (ntohl(version) != HUNT_VERSION) {
70: bad_ver();
71: /* NOTREACHED */
72: }
73: errno = 0;
74: while ((inf = fdopen(Socket, "r")) == NULL)
75: if (errno == EINTR)
76: errno = 0;
77: else {
78: perror("fdopen of socket");
79: exit(1);
80: }
81: # ifdef L_ctermid
82: setvbuf(inf, ibuf, _IOFBF, sizeof ibuf);
83: # else
84: setbuffer(inf, ibuf, sizeof ibuf);
85: # endif
86: # ifdef OTTO
87: Otto_count = 0;
88: # endif OTTO
89: nchar_send = MAX_SEND;
90: while ((ch = GETCHR(inf)) != EOF) {
91: # ifdef DEBUG
92: fputc(ch, stderr);
93: # endif DEBUG
94: switch (ch & 0377) {
95: case MOVE:
96: y = GETCHR(inf);
97: x = GETCHR(inf);
98: mvcur(cur_row, cur_col, y, x);
99: cur_row = y;
100: cur_col = x;
101: break;
102: case ADDCH:
103: ch = GETCHR(inf);
104: # ifdef OTTO
105: switch (ch) {
106:
107: case '<':
108: case '>':
109: case '^':
110: case 'v':
111: otto_face = ch;
112: otto_y = cur_row;
113: otto_x = cur_col;
114: break;
115: }
116: # endif OTTO
117: put_ch(ch);
118: break;
119: case CLRTOEOL:
120: clear_eol();
121: break;
122: case CLEAR:
123: clear_the_screen();
124: break;
125: case REFRESH:
126: fflush(stdout);
127: break;
128: case REDRAW:
129: redraw_screen();
130: fflush(stdout);
131: break;
132: case ENDWIN:
133: fflush(stdout);
134: if ((ch = GETCHR(inf)) == LAST_PLAYER)
135: Last_player = TRUE;
136: ch = EOF;
137: goto out;
138: case BELL:
139: putchar(CTRL(G));
140: break;
141: case READY:
142: (void) fflush(stdout);
143: if (nchar_send < 0)
144: # ifndef TCFLSH
145: (void) ioctl(fileno(stdin), TIOCFLUSH, &in);
146: # else
147: (void) ioctl(fileno(stdin), TCFLSH, 0);
148: # endif
149: nchar_send = MAX_SEND;
150: # ifndef OTTO
151: (void) GETCHR(inf);
152: # else OTTO
153: Otto_count -= (GETCHR(inf) & 255);
154: if (!Am_monitor) {
155: # ifdef DEBUG
156: fputc('0' + Otto_count, stderr);
157: # endif DEBUG
158: if (Otto_count == 0 && Otto_mode)
159: otto(otto_y, otto_x, otto_face);
160: }
161: # endif OTTO
162: break;
163: default:
164: # ifdef OTTO
165: switch (ch) {
166:
167: case '<':
168: case '>':
169: case '^':
170: case 'v':
171: otto_face = ch;
172: otto_y = cur_row;
173: otto_x = cur_col;
174: break;
175: }
176: # endif OTTO
177: put_ch(ch);
178: break;
179: }
180: }
181: out:
182: (void) fclose(inf);
183: }
184:
185: /*
186: * getchr:
187: * Grab input and pass it along to the driver
188: * Return any characters from the driver
189: * When this routine is called by GETCHR, we already know there are
190: * no characters in the input buffer.
191: */
192: getchr(fd)
193: register FILE *fd;
194: {
195: long readfds, s_readfds;
196: int driver_mask, stdin_mask;
197: int nfds, s_nfds;
198:
199: driver_mask = 1L << fileno(fd);
200: stdin_mask = 1L << fileno(stdin);
201: s_readfds = driver_mask | stdin_mask;
202: s_nfds = (fileno(fd) > fileno(stdin)) ? fileno(fd) : fileno(stdin);
203: s_nfds++;
204:
205: one_more_time:
206: do {
207: errno = 0;
208: readfds = s_readfds;
209: nfds = s_nfds;
210: nfds = select(nfds, &readfds, NULL, NULL, NULL);
211: } while (nfds <= 0 && errno == EINTR);
212:
213: if (readfds & stdin_mask)
214: send_stuff();
215: if ((readfds & driver_mask) == 0)
216: goto one_more_time;
217: return _filbuf(fd);
218: }
219:
220: /*
221: * send_stuff:
222: * Send standard input characters to the driver
223: */
224: send_stuff()
225: {
226: register int count;
227: register char *sp, *nsp;
228: static char inp[sizeof Buf];
229:
230: count = read(fileno(stdin), Buf, sizeof Buf);
231: if (count <= 0)
232: return;
233: if (nchar_send <= 0 && !no_beep) {
234: (void) write(1, "\7", 1); /* CTRL(G) */
235: return;
236: }
237:
238: /*
239: * look for 'q'uit commands; if we find one,
240: * confirm it. If it is not confirmed, strip
241: * it out of the input
242: */
243: Buf[count] = '\0';
244: nsp = inp;
245: for (sp = Buf; *sp != '\0'; sp++)
246: if ((*nsp = map_key[*sp]) == 'q')
247: intr();
248: else
249: nsp++;
250: count = nsp - inp;
251: if (count) {
252: # ifdef OTTO
253: Otto_count += count;
254: # endif OTTO
255: nchar_send -= count;
256: if (nchar_send < 0)
257: count += nchar_send;
258: (void) write(Socket, inp, count);
259: }
260: }
261:
262: /*
263: * quit:
264: * Handle the end of the game when the player dies
265: */
266: long
267: quit(old_status)
268: long old_status;
269: {
270: register int explain, ch;
271:
272: if (Last_player)
273: return Q_QUIT;
274: # ifdef OTTO
275: if (Otto_mode)
276: return Q_CLOAK;
277: # endif OTTO
278: mvcur(cur_row, cur_col, HEIGHT, 0);
279: cur_row = HEIGHT;
280: cur_col = 0;
281: put_str("Re-enter game [ynwo]? ");
282: clear_eol();
283: fflush(stdout);
284: explain = FALSE;
285: for (;;) {
286: if (isupper(ch = getchar()))
287: ch = tolower(ch);
288: if (ch == 'y')
289: return old_status;
290: else if (ch == 'o')
291: break;
292: else if (ch == 'n') {
293: # ifndef INTERNET
294: return Q_QUIT;
295: # else
296: mvcur(cur_row, cur_col, HEIGHT, 0);
297: cur_row = HEIGHT;
298: cur_col = 0;
299: put_str("Write a parting message [yn]? ");
300: clear_eol();
301: for (;;) {
302: if (isupper(ch = getchar()))
303: ch = tolower(ch);
304: if (ch == 'y')
305: goto get_message;
306: if (ch == 'n')
307: return Q_QUIT;
308: }
309: # endif
310: }
311: # ifdef INTERNET
312: else if (ch == 'w') {
313: static char buf[WIDTH + WIDTH % 2];
314: char *cp, c;
315:
316: get_message:
317: c = ch; /* save how we got here */
318: mvcur(cur_row, cur_col, HEIGHT, 0);
319: cur_row = HEIGHT;
320: cur_col = 0;
321: put_str("Message: ");
322: clear_eol();
323: cp = buf;
324: while ((ch = getchar()) != '\n' && ch != '\r') {
325: # ifdef TERMINFO
326: if (ch == erasechar())
327: # else
328: if (ch == _tty.sg_erase)
329: # endif
330: {
331: if (cp > buf) {
332: mvcur(cur_row, cur_col, cur_row,
333: cur_col - 1);
334: cur_col -= 1;
335: cp -= 1;
336: clear_eol();
337: }
338: continue;
339: # ifdef TERMINFO
340: } else if (ch == killchar()) {
341: # else
342: } else if (ch == _tty.sg_kill) {
343: # endif
344: mvcur(cur_row, cur_col, cur_row,
345: cur_col - (cp - buf));
346: cur_col -= cp - buf;
347: cp = buf;
348: clear_eol();
349: continue;
350: }
351: put_ch(ch);
352: *cp++ = ch;
353: if (cp + 1 >= buf + sizeof buf)
354: break;
355: }
356: *cp = '\0';
357: Send_message = buf;
358: return (c == 'w') ? old_status : Q_MESSAGE;
359: }
360: # endif INTERNET
361: (void) putchar(CTRL(G));
362: if (!explain) {
363: put_str("(Yes, No, Write message, or Options) ");
364: explain = TRUE;
365: }
366: fflush(stdout);
367: }
368:
369: mvcur(cur_row, cur_col, HEIGHT, 0);
370: cur_row = HEIGHT;
371: cur_col = 0;
372: # ifdef FLY
373: put_str("Scan, Cloak, Flying, or Quit? ");
374: # else
375: put_str("Scan, Cloak, or Quit? ");
376: # endif FLY
377: clear_eol();
378: fflush(stdout);
379: explain = FALSE;
380: for (;;) {
381: if (isupper(ch = getchar()))
382: ch = tolower(ch);
383: if (ch == 's')
384: return Q_SCAN;
385: else if (ch == 'c')
386: return Q_CLOAK;
387: # ifdef FLY
388: else if (ch == 'f')
389: return Q_FLY;
390: # endif FLY
391: else if (ch == 'q')
392: return Q_QUIT;
393: (void) putchar(CTRL(G));
394: if (!explain) {
395: # ifdef FLY
396: put_str("[SCFQ] ");
397: # else
398: put_str("[SCQ] ");
399: # endif FLY
400: explain = TRUE;
401: }
402: fflush(stdout);
403: }
404: }
405:
406: put_ch(ch)
407: char ch;
408: {
409: if (!isprint(ch)) {
410: fprintf(stderr, "r,c,ch: %d,%d,%d", cur_row, cur_col, ch);
411: return;
412: }
413: screen[cur_row][cur_col] = ch;
414: putchar(ch);
415: if (++cur_col >= COLS) {
416: if (!AM || XN)
417: putchar('\n');
418: cur_col = 0;
419: if (++cur_row >= LINES)
420: cur_row = LINES;
421: }
422: }
423:
424: put_str(s)
425: char *s;
426: {
427: while (*s)
428: put_ch(*s++);
429: }
430:
431: clear_the_screen()
432: {
433: register int i;
434:
435: if (blanks[0] == '\0')
436: for (i = 0; i < SCREEN_WIDTH; i++)
437: blanks[i] = ' ';
438:
439: if (CL != NULL) {
440: tputs(CL, LINES, _putchar);
441: for (i = 0; i < SCREEN_HEIGHT; i++)
442: bcopy(blanks, screen[i], SCREEN_WIDTH);
443: } else {
444: for (i = 0; i < SCREEN_HEIGHT; i++) {
445: mvcur(cur_row, cur_col, i, 0);
446: cur_row = i;
447: cur_col = 0;
448: clear_eol();
449: }
450: mvcur(cur_row, cur_col, 0, 0);
451: }
452: cur_row = cur_col = 0;
453: #ifdef TERMINFO
454: move(0, 0);
455: refresh();
456: #endif
457: }
458:
459: clear_eol()
460: {
461: if (CE != NULL)
462: tputs(CE, 1, _putchar);
463: else {
464: fwrite(blanks, sizeof (char), SCREEN_WIDTH - cur_col, stdout);
465: if (COLS != SCREEN_WIDTH)
466: mvcur(cur_row, SCREEN_WIDTH, cur_row, cur_col);
467: else if (AM)
468: mvcur(cur_row + 1, 0, cur_row, cur_col);
469: else
470: mvcur(cur_row, SCREEN_WIDTH - 1, cur_row, cur_col);
471: }
472: bcopy(blanks, &screen[cur_row][cur_col], SCREEN_WIDTH - cur_col);
473: }
474:
475: redraw_screen()
476: {
477: register int i;
478: # ifndef NOCURSES
479: static int first = 1;
480:
481: if (first) {
482: curscr = newwin(SCREEN_HEIGHT, SCREEN_WIDTH, 0, 0);
483: if (curscr == NULL) {
484: fprintf(stderr, "Can't create curscr\n");
485: exit(1);
486: }
487: for (i = 0; i < SCREEN_HEIGHT; i++)
488: curscr->_y[i] = screen[i];
489: first = 0;
490: }
491: curscr->_cury = cur_row;
492: curscr->_curx = cur_col;
493: clearok(curscr, TRUE);
494: touchwin(curscr);
495: wrefresh(curscr);
496: #else
497: mvcur(cur_row, cur_col, 0, 0);
498: for (i = 0; i < SCREEN_HEIGHT - 1; i++) {
499: fwrite(screen[i], sizeof (char), SCREEN_WIDTH, stdout);
500: if (COLS > SCREEN_WIDTH || (COLS == SCREEN_WIDTH && !AM))
501: putchar('\n');
502: }
503: fwrite(screen[SCREEN_HEIGHT - 1], sizeof (char), SCREEN_WIDTH - 1,
504: stdout);
505: mvcur(SCREEN_HEIGHT - 1, SCREEN_WIDTH - 1, cur_row, cur_col);
506: #endif
507: }
508:
509: /*
510: * do_message:
511: * Send a message to the driver and return
512: */
513: do_message()
514: {
515: extern int errno;
516: long version;
517:
518: if (read(Socket, (char *) &version, LONGLEN) != LONGLEN) {
519: bad_con();
520: /* NOTREACHED */
521: }
522: if (ntohl(version) != HUNT_VERSION) {
523: bad_ver();
524: /* NOTREACHED */
525: }
526: # ifdef INTERNET
527: if (write(Socket, Send_message, strlen(Send_message)) < 0) {
528: bad_con();
529: /* NOTREACHED */
530: }
531: # endif
532: (void) close(Socket);
533: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.