games: Remove (void) casts.
[dragonfly.git] / games / hunt / hunt / playit.c
blobc5a673e72c579a1eb2b586ee2c1a545375776f27
1 /*-
2 * Copyright (c) 1983-2003, Regents of the University of California.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University of California, San Francisco nor
15 * the names of its contributors may be used to endorse or promote
16 * products derived from this software without specific prior written
17 * permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * $OpenBSD: playit.c,v 1.8 2003/06/11 08:45:25 pjanzen Exp $
32 * $NetBSD: playit.c,v 1.4 1997/10/20 00:37:15 lukem Exp $
35 #include <sys/types.h>
36 #include <sys/file.h>
37 #include <arpa/inet.h>
39 #include <err.h>
40 #include <errno.h>
41 #include <ctype.h>
42 #include <termios.h>
43 #include <signal.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <stdio.h>
47 #include "hunt.h"
48 #include "display.h"
49 #include "client.h"
51 static int nchar_send;
52 static FLAG Last_player;
53 static int Otto_expect;
55 # define MAX_SEND 5
58 * ibuf is the input buffer used for the stream from the driver.
59 * It is small because we do not check for user input when there
60 * are characters in the input buffer.
62 static int icnt = 0;
63 static unsigned char ibuf[256], *iptr = ibuf;
65 #define GETCHR() (--icnt < 0 ? getchr() : *iptr++)
67 static unsigned char getchr(void);
68 static void send_stuff(void);
71 * playit:
72 * Play a given game, handling all the curses commands from
73 * the driver.
75 void
76 playit(void)
78 int ch;
79 int y, x;
80 u_int32_t version;
81 int otto_y, otto_x;
82 char otto_face = ' ';
83 int chars_processed;
85 if (read(Socket, &version, sizeof version) != sizeof version) {
86 bad_con();
87 /* NOTREACHED */
89 if (ntohl(version) != (unsigned int)HUNT_VERSION) {
90 bad_ver();
91 /* NOTREACHED */
93 errno = 0;
94 nchar_send = MAX_SEND;
95 Otto_expect = 0;
96 while ((ch = GETCHR()) != EOF) {
97 switch (ch & 0377) {
98 case MOVE:
99 y = GETCHR();
100 x = GETCHR();
101 display_move(y, x);
102 break;
104 case CLRTOEOL:
105 display_clear_eol();
106 break;
107 case CLEAR:
108 display_clear_the_screen();
109 break;
110 case REFRESH:
111 display_refresh();
112 break;
113 case REDRAW:
114 display_redraw_screen();
115 display_refresh();
116 break;
117 case ENDWIN:
118 display_refresh();
119 if ((ch = GETCHR()) == LAST_PLAYER)
120 Last_player = TRUE;
121 ch = EOF;
122 goto out;
123 case BELL:
124 display_beep();
125 break;
126 case READY:
127 chars_processed = GETCHR();
128 display_refresh();
129 if (nchar_send < 0)
130 tcflush(STDIN_FILENO, TCIFLUSH);
131 nchar_send = MAX_SEND;
132 if (Otto_mode) {
134 * The driver returns the number of keypresses
135 * that it has processed. Use this to figure
136 * out if otto's commands have completed.
138 Otto_expect -= chars_processed;
139 if (Otto_expect == 0) {
140 /* not very fair! */
141 static char buf[MAX_SEND * 2];
142 int len;
144 /* Ask otto what it wants to do: */
145 len = otto(otto_y, otto_x, otto_face,
146 buf, sizeof buf);
147 if (len) {
148 /* Pass it on to the driver: */
149 write(Socket, buf, len);
150 /* Update expectations: */
151 Otto_expect += len;
155 break;
156 case ADDCH:
157 ch = GETCHR();
158 /* FALLTHROUGH */
159 default:
160 if (!isprint(ch))
161 ch = ' ';
162 display_put_ch(ch);
163 if (Otto_mode)
164 switch (ch) {
165 case '<':
166 case '>':
167 case '^':
168 case 'v':
169 otto_face = ch;
170 display_getyx(&otto_y, &otto_x);
171 otto_x--;
172 break;
174 break;
177 out:
178 close(Socket);
182 * getchr:
183 * Grab input and pass it along to the driver
184 * Return any characters from the driver
185 * When this routine is called by GETCHR, we already know there are
186 * no characters in the input buffer.
188 static unsigned char
189 getchr(void)
191 fd_set readfds, s_readfds;
192 int nfds, s_nfds;
194 FD_ZERO(&s_readfds);
195 FD_SET(Socket, &s_readfds);
196 FD_SET(STDIN_FILENO, &s_readfds);
197 s_nfds = (Socket > STDIN_FILENO) ? Socket : STDIN_FILENO;
198 s_nfds++;
200 one_more_time:
201 do {
202 errno = 0;
203 readfds = s_readfds;
204 nfds = s_nfds;
205 nfds = select(nfds, &readfds, NULL, NULL, NULL);
206 } while (nfds <= 0 && errno == EINTR);
208 if (FD_ISSET(STDIN_FILENO, &readfds))
209 send_stuff();
210 if (!FD_ISSET(Socket, &readfds))
211 goto one_more_time;
212 icnt = read(Socket, ibuf, sizeof ibuf);
213 if (icnt <= 0) {
214 bad_con();
215 /* NOTREACHED */
217 iptr = ibuf;
218 icnt--;
219 return *iptr++;
223 * send_stuff:
224 * Send standard input characters to the driver
226 static void
227 send_stuff(void)
229 int count;
230 char *sp, *nsp;
231 static char inp[BUFSIZ];
232 static char Buf[BUFSIZ];
234 /* Drain the user's keystrokes: */
235 count = read(STDIN_FILENO, Buf, sizeof Buf);
236 if (count < 0)
237 err(1, "read");
238 if (count == 0)
239 return;
241 if (nchar_send <= 0 && !no_beep) {
242 display_beep();
243 return;
247 * look for 'q'uit commands; if we find one,
248 * confirm it. If it is not confirmed, strip
249 * it out of the input
251 Buf[count] = '\0';
252 for (sp = Buf, nsp = inp; *sp != '\0'; sp++, nsp++) {
253 *nsp = map_key[(int)*sp];
254 if (*nsp == 'q')
255 intr(0);
257 count = nsp - inp;
258 if (count) {
259 nchar_send -= count;
260 if (nchar_send < 0)
261 count += nchar_send;
262 write(Socket, inp, count);
263 if (Otto_mode) {
265 * The user can insert commands over otto.
266 * So, otto shouldn't be alarmed when the
267 * server processes more than otto asks for.
269 Otto_expect += count;
275 * quit:
276 * Handle the end of the game when the player dies
279 quit(int old_status)
281 int explain, ch;
283 if (Last_player)
284 return Q_QUIT;
285 if (Otto_mode)
286 return otto_quit(old_status);
287 display_move(HEIGHT, 0);
288 display_put_str("Re-enter game [ynwo]? ");
289 display_clear_eol();
290 explain = FALSE;
291 for (;;) {
292 display_refresh();
293 if (isupper(ch = getchar()))
294 ch = tolower(ch);
295 if (ch == 'y')
296 return old_status;
297 else if (ch == 'o')
298 break;
299 else if (ch == 'n') {
300 display_move(HEIGHT, 0);
301 display_put_str("Write a parting message [yn]? ");
302 display_clear_eol();
303 display_refresh();
304 for (;;) {
305 if (isupper(ch = getchar()))
306 ch = tolower(ch);
307 if (ch == 'y')
308 goto get_message;
309 if (ch == 'n')
310 return Q_QUIT;
313 else if (ch == 'w') {
314 static char buf[WIDTH + WIDTH % 2];
315 char *cp, c;
317 get_message:
318 c = ch; /* save how we got here */
319 display_move(HEIGHT, 0);
320 display_put_str("Message: ");
321 display_clear_eol();
322 display_refresh();
323 cp = buf;
324 for (;;) {
325 display_refresh();
326 if ((ch = getchar()) == '\n' || ch == '\r')
327 break;
328 if (display_iserasechar(ch))
330 if (cp > buf) {
331 int y, x;
333 display_getyx(&y, &x);
334 display_move(y, x - 1);
335 cp -= 1;
336 display_clear_eol();
338 continue;
340 else if (display_iskillchar(ch))
342 int y, x;
344 display_getyx(&y, &x);
345 display_move(y, x - (cp - buf));
346 cp = buf;
347 display_clear_eol();
348 continue;
349 } else if (!isprint(ch)) {
350 display_beep();
351 continue;
353 display_put_ch(ch);
354 *cp++ = ch;
355 if (cp + 1 >= buf + sizeof buf)
356 break;
358 *cp = '\0';
359 Send_message = buf;
360 return (c == 'w') ? old_status : Q_MESSAGE;
362 display_beep();
363 if (!explain) {
364 display_put_str("(Yes, No, Write message, or Options) ");
365 explain = TRUE;
369 display_move(HEIGHT, 0);
370 display_put_str("Scan, Cloak, Flying, or Quit? ");
371 display_clear_eol();
372 display_refresh();
373 explain = FALSE;
374 for (;;) {
375 if (isupper(ch = getchar()))
376 ch = tolower(ch);
377 if (ch == 's')
378 return Q_SCAN;
379 else if (ch == 'c')
380 return Q_CLOAK;
381 else if (ch == 'f')
382 return Q_FLY;
383 else if (ch == 'q')
384 return Q_QUIT;
385 display_beep();
386 if (!explain) {
387 display_put_str("[SCFQ] ");
388 explain = TRUE;
390 display_refresh();
395 * do_message:
396 * Send a message to the driver and return
398 void
399 do_message(void)
401 u_int32_t version;
403 if (read(Socket, &version, sizeof version) != sizeof version) {
404 bad_con();
405 /* NOTREACHED */
407 if (ntohl(version) != (unsigned int)HUNT_VERSION) {
408 bad_ver();
409 /* NOTREACHED */
411 if (write(Socket, Send_message, strlen(Send_message)) < 0) {
412 bad_con();
413 /* NOTREACHED */
415 close(Socket);