BSD 4_3 development
[unix-history] / usr / src / games / hunt / playit.c
/*
* 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 <curses.h>
# include <ctype.h>
# include <signal.h>
# include <errno.h>
# include "hunt.h"
# include <sys/file.h>
# 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
}