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: 18: # undef CTRL 19: # define CTRL(x) ('x' & 037) 20: 21: int input(); 22: static int nchar_send; 23: static int in = FREAD; 24: char screen[24][80], blanks[80]; 25: int cur_row, cur_col; 26: # ifdef OTTO 27: int Otto_count; 28: int Otto_mode; 29: static int otto_y, otto_x; 30: static char otto_face; 31: # endif OTTO 32: 33: # define MAX_SEND 5 34: 35: /* 36: * ibuf is the input buffer used for the stream from the driver. 37: * It is small because we do not check for user input when there 38: * are characters in the input buffer. 39: */ 40: static char ibuf[20]; 41: 42: #define GETCHR(fd) (--(fd)->_cnt >= 0 ? *(fd)->_ptr++&0377 : getchr(fd)) 43: 44: /* 45: * playit: 46: * Play a given game, handling all the curses commands from 47: * the driver. 48: */ 49: playit() 50: { 51: register FILE *inf; 52: register int ch; 53: register unsigned int y, x; 54: extern int Master_pid; 55: extern int errno; 56: extern int _putchar(); 57: 58: errno = 0; 59: while ((inf = fdopen(Socket, "r")) == NULL) 60: if (errno == EINTR) 61: errno = 0; 62: else { 63: perror("fdopen of socket"); 64: exit(1); 65: } 66: setbuffer(inf, ibuf, sizeof ibuf); 67: Master_pid = getw(inf); 68: if (Master_pid == 0 || Master_pid == EOF) { 69: bad_con(); 70: /* NOTREACHED */ 71: } 72: # ifdef OTTO 73: Otto_count = 0; 74: # endif OTTO 75: nchar_send = MAX_SEND; 76: while ((ch = GETCHR(inf)) != EOF) { 77: # ifdef DEBUG 78: fputc(ch, stderr); 79: # endif DEBUG 80: switch (ch & 0377) { 81: case MOVE: 82: y = GETCHR(inf); 83: x = GETCHR(inf); 84: mvcur(cur_row, cur_col, y, x); 85: cur_row = y; 86: cur_col = x; 87: break; 88: case ADDCH: 89: ch = GETCHR(inf); 90: # ifdef OTTO 91: switch (ch) { 92: 93: case '<': 94: case '>': 95: case '^': 96: case 'v': 97: otto_face = ch; 98: getyx(stdscr, otto_y, otto_x); 99: break; 100: } 101: # endif OTTO 102: put_ch(ch); 103: break; 104: case CLRTOEOL: 105: clear_eol(); 106: break; 107: case CLEAR: 108: clear_screen(); 109: break; 110: case REFRESH: 111: fflush(stdout); 112: break; 113: case REDRAW: 114: redraw_screen(); 115: fflush(stdout); 116: break; 117: case ENDWIN: 118: fflush(stdout); 119: if ((ch = GETCHR(inf)) == LAST_PLAYER) 120: Last_player = TRUE; 121: ch = EOF; 122: goto out; 123: case BELL: 124: putchar(CTRL(G)); 125: break; 126: case READY: 127: (void) fflush(stdout); 128: if (nchar_send < 0) 129: (void) ioctl(fileno(stdin), TIOCFLUSH, &in); 130: nchar_send = MAX_SEND; 131: # ifndef OTTO 132: (void) GETCHR(inf); 133: # else OTTO 134: Otto_count -= (GETCHR(inf) & 255); 135: if (!Am_monitor) { 136: # ifdef DEBUG 137: fputc('0' + Otto_count, stderr); 138: # endif DEBUG 139: if (Otto_count == 0 && Otto_mode) 140: otto(otto_y, otto_x, otto_face); 141: } 142: # endif OTTO 143: break; 144: default: 145: # ifdef OTTO 146: switch (ch) { 147: 148: case '<': 149: case '>': 150: case '^': 151: case 'v': 152: otto_face = ch; 153: getyx(stdscr, otto_y, otto_x); 154: break; 155: } 156: # endif OTTO 157: put_ch(ch); 158: break; 159: } 160: } 161: out: 162: (void) fclose(inf); 163: } 164: 165: /* 166: * getchr: 167: * Grab input and pass it along to the driver 168: * Return any characters from the driver 169: * When this routine is called by GETCHR, we already know there are 170: * no characters in the input buffer. 171: */ 172: getchr(fd) 173: register FILE *fd; 174: { 175: long nchar; 176: long readfds, s_readfds; 177: int driver_mask, stdin_mask; 178: int nfds, s_nfds; 179: 180: driver_mask = 1L << fileno(fd); 181: stdin_mask = 1L << fileno(stdin); 182: s_readfds = driver_mask | stdin_mask; 183: s_nfds = (driver_mask > stdin_mask) ? driver_mask : stdin_mask; 184: s_nfds++; 185: 186: one_more_time: 187: do { 188: errno = 0; 189: readfds = s_readfds; 190: nfds = s_nfds; 191: # ifndef OLDIPC 192: nfds = select(nfds, &readfds, NULL, NULL, NULL); 193: # else OLDIPC 194: nfds = select(nfds, &readfds, (int *) NULL, 32767); 195: # endif OLDIPC 196: } while (nfds <= 0 && errno == EINTR); 197: 198: if (readfds & stdin_mask) 199: send_stuff(); 200: if ((readfds & driver_mask) == 0) 201: goto one_more_time; 202: return _filbuf(fd); 203: } 204: 205: /* 206: * send_stuff: 207: * Send standard input characters to the driver 208: */ 209: send_stuff() 210: { 211: register int count; 212: register char *sp, *nsp; 213: static char inp[sizeof Buf]; 214: extern char map_key[256]; 215: 216: count = read(fileno(stdin), Buf, sizeof Buf); 217: if (count <= 0) 218: return; 219: if (nchar_send <= 0) { 220: (void) write(1, "\7", 1); 221: return; 222: } 223: 224: /* 225: * look for 'q'uit commands; if we find one, 226: * confirm it. If it is not confirmed, strip 227: * it out of the input 228: */ 229: Buf[count] = '\0'; 230: nsp = inp; 231: for (sp = Buf; *sp != '\0'; sp++) 232: if ((*nsp = map_key[*sp]) == 'q') 233: intr(); 234: # ifdef OTTO 235: else if (*nsp == CTRL(O)) 236: Otto_mode = !Otto_mode; 237: # endif OTTO 238: else 239: nsp++; 240: count = nsp - inp; 241: if (count) { 242: # ifdef OTTO 243: Otto_count += count; 244: # endif OTTO 245: nchar_send -= count; 246: if (nchar_send < 0) 247: count += nchar_send; 248: (void) write(Socket, inp, count); 249: } 250: } 251: 252: /* 253: * quit: 254: * Handle the end of the game when the player dies 255: */ 256: quit() 257: { 258: register int explain, ch; 259: 260: if (Last_player) 261: return TRUE; 262: # ifdef OTTO 263: if (Otto_mode) 264: return FALSE; 265: # endif OTTO 266: mvcur(cur_row, cur_col, HEIGHT, 0); 267: cur_row = HEIGHT; 268: cur_col = 0; 269: put_str("Re-enter game? "); 270: clear_eol(); 271: fflush(stdout); 272: explain = FALSE; 273: for (;;) { 274: if (isupper(ch = getchar())) 275: ch = tolower(ch); 276: if (ch == 'y') { 277: sleep(2); 278: return FALSE; 279: } 280: else if (ch == 'n') 281: return TRUE; 282: (void) putchar(CTRL(G)); 283: if (!explain) { 284: put_str("(Y or N) "); 285: explain = TRUE; 286: } 287: fflush(stdout); 288: } 289: } 290: 291: put_ch(ch) 292: char ch; 293: { 294: if (!isprint(ch)) { 295: fprintf(stderr, "r,c,ch: %d,%d,%d", cur_row, cur_col, ch); 296: return; 297: } 298: screen[cur_row][cur_col] = ch; 299: putchar(ch); 300: if (++cur_col >= COLS) { 301: if (!AM || XN) 302: putchar('\n'); 303: cur_col = 0; 304: if (++cur_row >= LINES) 305: cur_row = LINES; 306: } 307: } 308: 309: put_str(s) 310: char *s; 311: { 312: while (*s) 313: put_ch(*s++); 314: } 315: 316: clear_screen() 317: { 318: register int i; 319: int _putchar(); 320: 321: if (blanks[0] == '\0') 322: for (i = 0; i < 80; i++) 323: blanks[i] = ' '; 324: 325: if (CL != NULL) { 326: tputs(CL, LINES, _putchar); 327: for (i = 0; i < 24; i++) 328: bcopy(blanks, screen[i], 80); 329: } else { 330: for (i = 0; i < 24; i++) { 331: mvcur(cur_row, cur_col, i, 0); 332: cur_row = i; 333: cur_col = 0; 334: clear_eol(); 335: } 336: mvcur(cur_row, cur_col, 0, 0); 337: } 338: cur_row = cur_col = 0; 339: } 340: 341: clear_eol() 342: { 343: int _putchar(); 344: 345: if (CE != NULL) 346: tputs(CE, 1, _putchar); 347: else { 348: fwrite(blanks, sizeof (char), 80 - cur_col, stdout); 349: if (COLS != 80) 350: mvcur(cur_row, 80, cur_row, cur_col); 351: else if (AM) 352: mvcur(cur_row + 1, 0, cur_row, cur_col); 353: else 354: mvcur(cur_row, 79, cur_row, cur_col); 355: } 356: bcopy(blanks, &screen[cur_row][cur_col], 80 - cur_col); 357: } 358: 359: redraw_screen() 360: { 361: register int i; 362: static int first = 1; 363: 364: if (first) { 365: if ((curscr = newwin(24, 80, 0, 0)) == NULL) { 366: fprintf(stderr, "Can't create curscr\n"); 367: exit(1); 368: } 369: for (i = 0; i < 24; i++) 370: curscr->_y[i] = screen[i]; 371: first = 0; 372: } 373: curscr->_cury = cur_row; 374: curscr->_curx = cur_col; 375: wrefresh(curscr); 376: #ifdef NOCURSES 377: mvcur(cur_row, cur_col, 0, 0); 378: for (i = 0; i < 23; i++) { 379: fwrite(screen[i], sizeof (char), 80, stdout); 380: if (COLS > 80 || (COLS == 80 && !AM)) 381: putchar('\n'); 382: } 383: fwrite(screen[23], sizeof (char), 79, stdout); 384: mvcur(23, 79, cur_row, cur_col); 385: #endif 386: }