games: Massive style(9) cleanup commit. Reduces differences to NetBSD.
[dragonfly.git] / games / hunt / hunt / playit.c
blob5e5de042d1e3b2b54ed70e49757d49aab9a98bf1
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 $
33 * $DragonFly: src/games/hunt/hunt/playit.c,v 1.2 2008/09/04 16:12:51 swildner Exp $
36 #include <sys/types.h>
37 #include <sys/file.h>
38 #include <arpa/inet.h>
40 #include <err.h>
41 #include <errno.h>
42 #include <ctype.h>
43 #include <termios.h>
44 #include <signal.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <stdio.h>
48 #include "hunt.h"
49 #include "display.h"
50 #include "client.h"
52 static int nchar_send;
53 static FLAG Last_player;
54 static int Otto_expect;
56 # define MAX_SEND 5
59 * ibuf is the input buffer used for the stream from the driver.
60 * It is small because we do not check for user input when there
61 * are characters in the input buffer.
63 static int icnt = 0;
64 static unsigned char ibuf[256], *iptr = ibuf;
66 #define GETCHR() (--icnt < 0 ? getchr() : *iptr++)
68 static unsigned char getchr(void);
69 static void send_stuff(void);
72 * playit:
73 * Play a given game, handling all the curses commands from
74 * the driver.
76 void
77 playit(void)
79 int ch;
80 int y, x;
81 u_int32_t version;
82 int otto_y, otto_x;
83 char otto_face = ' ';
84 int chars_processed;
86 if (read(Socket, &version, sizeof version) != sizeof version) {
87 bad_con();
88 /* NOTREACHED */
90 if (ntohl(version) != (unsigned int)HUNT_VERSION) {
91 bad_ver();
92 /* NOTREACHED */
94 errno = 0;
95 nchar_send = MAX_SEND;
96 Otto_expect = 0;
97 while ((ch = GETCHR()) != EOF) {
98 switch (ch & 0377) {
99 case MOVE:
100 y = GETCHR();
101 x = GETCHR();
102 display_move(y, x);
103 break;
105 case CLRTOEOL:
106 display_clear_eol();
107 break;
108 case CLEAR:
109 display_clear_the_screen();
110 break;
111 case REFRESH:
112 display_refresh();
113 break;
114 case REDRAW:
115 display_redraw_screen();
116 display_refresh();
117 break;
118 case ENDWIN:
119 display_refresh();
120 if ((ch = GETCHR()) == LAST_PLAYER)
121 Last_player = TRUE;
122 ch = EOF;
123 goto out;
124 case BELL:
125 display_beep();
126 break;
127 case READY:
128 chars_processed = GETCHR();
129 display_refresh();
130 if (nchar_send < 0)
131 tcflush(STDIN_FILENO, TCIFLUSH);
132 nchar_send = MAX_SEND;
133 if (Otto_mode) {
135 * The driver returns the number of keypresses
136 * that it has processed. Use this to figure
137 * out if otto's commands have completed.
139 Otto_expect -= chars_processed;
140 if (Otto_expect == 0) {
141 /* not very fair! */
142 static char buf[MAX_SEND * 2];
143 int len;
145 /* Ask otto what it wants to do: */
146 len = otto(otto_y, otto_x, otto_face,
147 buf, sizeof buf);
148 if (len) {
149 /* Pass it on to the driver: */
150 write(Socket, buf, len);
151 /* Update expectations: */
152 Otto_expect += len;
156 break;
157 case ADDCH:
158 ch = GETCHR();
159 /* FALLTHROUGH */
160 default:
161 if (!isprint(ch))
162 ch = ' ';
163 display_put_ch(ch);
164 if (Otto_mode)
165 switch (ch) {
166 case '<':
167 case '>':
168 case '^':
169 case 'v':
170 otto_face = ch;
171 display_getyx(&otto_y, &otto_x);
172 otto_x--;
173 break;
175 break;
178 out:
179 (void) close(Socket);
183 * getchr:
184 * Grab input and pass it along to the driver
185 * Return any characters from the driver
186 * When this routine is called by GETCHR, we already know there are
187 * no characters in the input buffer.
189 static unsigned char
190 getchr(void)
192 fd_set readfds, s_readfds;
193 int nfds, s_nfds;
195 FD_ZERO(&s_readfds);
196 FD_SET(Socket, &s_readfds);
197 FD_SET(STDIN_FILENO, &s_readfds);
198 s_nfds = (Socket > STDIN_FILENO) ? Socket : STDIN_FILENO;
199 s_nfds++;
201 one_more_time:
202 do {
203 errno = 0;
204 readfds = s_readfds;
205 nfds = s_nfds;
206 nfds = select(nfds, &readfds, NULL, NULL, NULL);
207 } while (nfds <= 0 && errno == EINTR);
209 if (FD_ISSET(STDIN_FILENO, &readfds))
210 send_stuff();
211 if (!FD_ISSET(Socket, &readfds))
212 goto one_more_time;
213 icnt = read(Socket, ibuf, sizeof ibuf);
214 if (icnt <= 0) {
215 bad_con();
216 /* NOTREACHED */
218 iptr = ibuf;
219 icnt--;
220 return *iptr++;
224 * send_stuff:
225 * Send standard input characters to the driver
227 static void
228 send_stuff(void)
230 int count;
231 char *sp, *nsp;
232 static char inp[BUFSIZ];
233 static char Buf[BUFSIZ];
235 /* Drain the user's keystrokes: */
236 count = read(STDIN_FILENO, Buf, sizeof Buf);
237 if (count < 0)
238 err(1, "read");
239 if (count == 0)
240 return;
242 if (nchar_send <= 0 && !no_beep) {
243 display_beep();
244 return;
248 * look for 'q'uit commands; if we find one,
249 * confirm it. If it is not confirmed, strip
250 * it out of the input
252 Buf[count] = '\0';
253 for (sp = Buf, nsp = inp; *sp != '\0'; sp++, nsp++) {
254 *nsp = map_key[(int)*sp];
255 if (*nsp == 'q')
256 intr(0);
258 count = nsp - inp;
259 if (count) {
260 nchar_send -= count;
261 if (nchar_send < 0)
262 count += nchar_send;
263 (void) write(Socket, inp, count);
264 if (Otto_mode) {
266 * The user can insert commands over otto.
267 * So, otto shouldn't be alarmed when the
268 * server processes more than otto asks for.
270 Otto_expect += count;
276 * quit:
277 * Handle the end of the game when the player dies
280 quit(int old_status)
282 int explain, ch;
284 if (Last_player)
285 return Q_QUIT;
286 if (Otto_mode)
287 return otto_quit(old_status);
288 display_move(HEIGHT, 0);
289 display_put_str("Re-enter game [ynwo]? ");
290 display_clear_eol();
291 explain = FALSE;
292 for (;;) {
293 display_refresh();
294 if (isupper(ch = getchar()))
295 ch = tolower(ch);
296 if (ch == 'y')
297 return old_status;
298 else if (ch == 'o')
299 break;
300 else if (ch == 'n') {
301 display_move(HEIGHT, 0);
302 display_put_str("Write a parting message [yn]? ");
303 display_clear_eol();
304 display_refresh();
305 for (;;) {
306 if (isupper(ch = getchar()))
307 ch = tolower(ch);
308 if (ch == 'y')
309 goto get_message;
310 if (ch == 'n')
311 return Q_QUIT;
314 else if (ch == 'w') {
315 static char buf[WIDTH + WIDTH % 2];
316 char *cp, c;
318 get_message:
319 c = ch; /* save how we got here */
320 display_move(HEIGHT, 0);
321 display_put_str("Message: ");
322 display_clear_eol();
323 display_refresh();
324 cp = buf;
325 for (;;) {
326 display_refresh();
327 if ((ch = getchar()) == '\n' || ch == '\r')
328 break;
329 if (display_iserasechar(ch))
331 if (cp > buf) {
332 int y, x;
334 display_getyx(&y, &x);
335 display_move(y, x - 1);
336 cp -= 1;
337 display_clear_eol();
339 continue;
341 else if (display_iskillchar(ch))
343 int y, x;
345 display_getyx(&y, &x);
346 display_move(y, x - (cp - buf));
347 cp = buf;
348 display_clear_eol();
349 continue;
350 } else if (!isprint(ch)) {
351 display_beep();
352 continue;
354 display_put_ch(ch);
355 *cp++ = ch;
356 if (cp + 1 >= buf + sizeof buf)
357 break;
359 *cp = '\0';
360 Send_message = buf;
361 return (c == 'w') ? old_status : Q_MESSAGE;
363 display_beep();
364 if (!explain) {
365 display_put_str("(Yes, No, Write message, or Options) ");
366 explain = TRUE;
370 display_move(HEIGHT, 0);
371 display_put_str("Scan, Cloak, Flying, or Quit? ");
372 display_clear_eol();
373 display_refresh();
374 explain = FALSE;
375 for (;;) {
376 if (isupper(ch = getchar()))
377 ch = tolower(ch);
378 if (ch == 's')
379 return Q_SCAN;
380 else if (ch == 'c')
381 return Q_CLOAK;
382 else if (ch == 'f')
383 return Q_FLY;
384 else if (ch == 'q')
385 return Q_QUIT;
386 display_beep();
387 if (!explain) {
388 display_put_str("[SCFQ] ");
389 explain = TRUE;
391 display_refresh();
396 * do_message:
397 * Send a message to the driver and return
399 void
400 do_message(void)
402 u_int32_t version;
404 if (read(Socket, &version, sizeof version) != sizeof version) {
405 bad_con();
406 /* NOTREACHED */
408 if (ntohl(version) != (unsigned int)HUNT_VERSION) {
409 bad_ver();
410 /* NOTREACHED */
412 if (write(Socket, Send_message, strlen(Send_message)) < 0) {
413 bad_con();
414 /* NOTREACHED */
416 (void) close(Socket);