BSD 4_3 development
[unix-history] / usr / src / games / hunt / playit.c
CommitLineData
db16ccc5
C
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
21int input();
22static int nchar_send;
23static int in = FREAD;
24char screen[24][80], blanks[80];
25int cur_row, cur_col;
26# ifdef OTTO
27int Otto_count;
28int Otto_mode;
29static int otto_y, otto_x;
30static 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 */
40static 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 */
49playit()
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 }
161out:
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 */
172getchr(fd)
173register 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
186one_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 */
209send_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 */
256quit()
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
291put_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
309put_str(s)
310 char *s;
311{
312 while (*s)
313 put_ch(*s++);
314}
315
316clear_screen()
317{
318 register int i;
319
320 if (blanks[0] == '\0')
321 for (i = 0; i < 80; i++)
322 blanks[i] = ' ';
323
324 if (CL != NULL) {
325 tputs(CL, LINES, _putchar);
326 for (i = 0; i < 24; i++)
327 bcopy(blanks, screen[i], 80);
328 } else {
329 for (i = 0; i < 24; i++) {
330 mvcur(cur_row, cur_col, i, 0);
331 cur_row = i;
332 cur_col = 0;
333 clear_eol();
334 }
335 mvcur(cur_row, cur_col, 0, 0);
336 }
337 cur_row = cur_col = 0;
338}
339
340clear_eol()
341{
342 if (CE != NULL)
343 tputs(CE, 1, _putchar);
344 else {
345 fwrite(blanks, sizeof (char), 80 - cur_col, stdout);
346 if (COLS != 80)
347 mvcur(cur_row, 80, cur_row, cur_col);
348 else if (AM)
349 mvcur(cur_row + 1, 0, cur_row, cur_col);
350 else
351 mvcur(cur_row, 79, cur_row, cur_col);
352 }
353 bcopy(blanks, &screen[cur_row][cur_col], 80 - cur_col);
354}
355
356redraw_screen()
357{
358 register int i;
359 static int first = 1;
360
361 if (first) {
362 if ((curscr = newwin(24, 80, 0, 0)) == NULL) {
363 fprintf(stderr, "Can't create curscr\n");
364 exit(1);
365 }
366 for (i = 0; i < 24; i++)
367 curscr->_y[i] = screen[i];
368 first = 0;
369 }
370 curscr->_cury = cur_row;
371 curscr->_curx = cur_col;
372 wrefresh(curscr);
373#ifdef NOCURSES
374 mvcur(cur_row, cur_col, 0, 0);
375 for (i = 0; i < 23; i++) {
376 fwrite(screen[i], sizeof (char), 80, stdout);
377 if (COLS > 80 || (COLS == 80 && !AM))
378 putchar('\n');
379 }
380 fwrite(screen[23], sizeof (char), 79, stdout);
381 mvcur(23, 79, cur_row, cur_col);
382#endif
383}