/* * Hunt * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold * San Francisco, California * * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ # include # include # include # include # include "hunt.h" # include # undef CTRL # define CTRL(x) ('x' & 037) int input(); static int nchar_send; static int in = FREAD; char screen[24][80], blanks[80]; int cur_row, cur_col; # ifdef OTTO int Otto_count; int Otto_mode; static int otto_y, otto_x; static char otto_face; # endif OTTO # define MAX_SEND 5 /* * ibuf is the input buffer used for the stream from the driver. * It is small because we do not check for user input when there * are characters in the input buffer. */ static char ibuf[20]; #define GETCHR(fd) (--(fd)->_cnt >= 0 ? *(fd)->_ptr++&0377 : getchr(fd)) /* * playit: * Play a given game, handling all the curses commands from * the driver. */ playit() { register FILE *inf; register int ch; register unsigned int y, x; extern int Master_pid; extern int errno; extern int _putchar(); errno = 0; while ((inf = fdopen(Socket, "r")) == NULL) if (errno == EINTR) errno = 0; else { perror("fdopen of socket"); exit(1); } setbuffer(inf, ibuf, sizeof ibuf); Master_pid = getw(inf); if (Master_pid == 0 || Master_pid == EOF) { bad_con(); /* NOTREACHED */ } # ifdef OTTO Otto_count = 0; # endif OTTO nchar_send = MAX_SEND; while ((ch = GETCHR(inf)) != EOF) { # ifdef DEBUG fputc(ch, stderr); # endif DEBUG switch (ch & 0377) { case MOVE: y = GETCHR(inf); x = GETCHR(inf); mvcur(cur_row, cur_col, y, x); cur_row = y; cur_col = x; break; case ADDCH: ch = GETCHR(inf); # ifdef OTTO switch (ch) { case '<': case '>': case '^': case 'v': otto_face = ch; getyx(stdscr, otto_y, otto_x); break; } # endif OTTO put_ch(ch); break; case CLRTOEOL: clear_eol(); break; case CLEAR: clear_screen(); break; case REFRESH: fflush(stdout); break; case REDRAW: redraw_screen(); fflush(stdout); break; case ENDWIN: fflush(stdout); if ((ch = GETCHR(inf)) == LAST_PLAYER) Last_player = TRUE; ch = EOF; goto out; case BELL: putchar(CTRL(G)); break; case READY: (void) fflush(stdout); if (nchar_send < 0) (void) ioctl(fileno(stdin), TIOCFLUSH, &in); nchar_send = MAX_SEND; # ifndef OTTO (void) GETCHR(inf); # else OTTO Otto_count -= (GETCHR(inf) & 255); if (!Am_monitor) { # ifdef DEBUG fputc('0' + Otto_count, stderr); # endif DEBUG if (Otto_count == 0 && Otto_mode) otto(otto_y, otto_x, otto_face); } # endif OTTO break; default: # ifdef OTTO switch (ch) { case '<': case '>': case '^': case 'v': otto_face = ch; getyx(stdscr, otto_y, otto_x); break; } # endif OTTO put_ch(ch); break; } } out: (void) fclose(inf); } /* * getchr: * Grab input and pass it along to the driver * Return any characters from the driver * When this routine is called by GETCHR, we already know there are * no characters in the input buffer. */ getchr(fd) register FILE *fd; { long nchar; long readfds, s_readfds; int driver_mask, stdin_mask; int nfds, s_nfds; driver_mask = 1L << fileno(fd); stdin_mask = 1L << fileno(stdin); s_readfds = driver_mask | stdin_mask; s_nfds = (driver_mask > stdin_mask) ? driver_mask : stdin_mask; s_nfds++; one_more_time: do { errno = 0; readfds = s_readfds; nfds = s_nfds; # ifndef OLDIPC nfds = select(nfds, &readfds, NULL, NULL, NULL); # else OLDIPC nfds = select(nfds, &readfds, (int *) NULL, 32767); # endif OLDIPC } while (nfds <= 0 && errno == EINTR); if (readfds & stdin_mask) send_stuff(); if ((readfds & driver_mask) == 0) goto one_more_time; return _filbuf(fd); } /* * send_stuff: * Send standard input characters to the driver */ send_stuff() { register int count; register char *sp, *nsp; static char inp[sizeof Buf]; extern char map_key[256]; count = read(fileno(stdin), Buf, sizeof Buf); if (count <= 0) return; if (nchar_send <= 0) { (void) write(1, "\7", 1); return; } /* * look for 'q'uit commands; if we find one, * confirm it. If it is not confirmed, strip * it out of the input */ Buf[count] = '\0'; nsp = inp; for (sp = Buf; *sp != '\0'; sp++) if ((*nsp = map_key[*sp]) == 'q') intr(); # ifdef OTTO else if (*nsp == CTRL(O)) Otto_mode = !Otto_mode; # endif OTTO else nsp++; count = nsp - inp; if (count) { # ifdef OTTO Otto_count += count; # endif OTTO nchar_send -= count; if (nchar_send < 0) count += nchar_send; (void) write(Socket, inp, count); } } /* * quit: * Handle the end of the game when the player dies */ quit() { register int explain, ch; if (Last_player) return TRUE; # ifdef OTTO if (Otto_mode) return FALSE; # endif OTTO mvcur(cur_row, cur_col, HEIGHT, 0); cur_row = HEIGHT; cur_col = 0; put_str("Re-enter game? "); clear_eol(); fflush(stdout); explain = FALSE; for (;;) { if (isupper(ch = getchar())) ch = tolower(ch); if (ch == 'y') { sleep(2); return FALSE; } else if (ch == 'n') return TRUE; (void) putchar(CTRL(G)); if (!explain) { put_str("(Y or N) "); explain = TRUE; } fflush(stdout); } } put_ch(ch) char ch; { if (!isprint(ch)) { fprintf(stderr, "r,c,ch: %d,%d,%d", cur_row, cur_col, ch); return; } screen[cur_row][cur_col] = ch; putchar(ch); if (++cur_col >= COLS) { if (!AM || XN) putchar('\n'); cur_col = 0; if (++cur_row >= LINES) cur_row = LINES; } } put_str(s) char *s; { while (*s) put_ch(*s++); } clear_screen() { register int i; if (blanks[0] == '\0') for (i = 0; i < 80; i++) blanks[i] = ' '; if (CL != NULL) { tputs(CL, LINES, _putchar); for (i = 0; i < 24; i++) bcopy(blanks, screen[i], 80); } else { for (i = 0; i < 24; i++) { mvcur(cur_row, cur_col, i, 0); cur_row = i; cur_col = 0; clear_eol(); } mvcur(cur_row, cur_col, 0, 0); } cur_row = cur_col = 0; } clear_eol() { if (CE != NULL) tputs(CE, 1, _putchar); else { fwrite(blanks, sizeof (char), 80 - cur_col, stdout); if (COLS != 80) mvcur(cur_row, 80, cur_row, cur_col); else if (AM) mvcur(cur_row + 1, 0, cur_row, cur_col); else mvcur(cur_row, 79, cur_row, cur_col); } bcopy(blanks, &screen[cur_row][cur_col], 80 - cur_col); } redraw_screen() { register int i; static int first = 1; if (first) { if ((curscr = newwin(24, 80, 0, 0)) == NULL) { fprintf(stderr, "Can't create curscr\n"); exit(1); } for (i = 0; i < 24; i++) curscr->_y[i] = screen[i]; first = 0; } curscr->_cury = cur_row; curscr->_curx = cur_col; wrefresh(curscr); #ifdef NOCURSES mvcur(cur_row, cur_col, 0, 0); for (i = 0; i < 23; i++) { fwrite(screen[i], sizeof (char), 80, stdout); if (COLS > 80 || (COLS == 80 && !AM)) putchar('\n'); } fwrite(screen[23], sizeof (char), 79, stdout); mvcur(23, 79, cur_row, cur_col); #endif }