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