|
|
1.1 ! root 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 "hunt.h" ! 12: # include <signal.h> ! 13: # include <errno.h> ! 14: # include <sys/ioctl.h> ! 15: # ifndef HPUX ! 16: # include <sys/time.h> ! 17: # else ! 18: # include <time.h> ! 19: # endif ! 20: ! 21: # ifndef pdp11 ! 22: # define RN (((Seed = Seed * 11109 + 13849) >> 16) & 0xffff) ! 23: # else pdp11 ! 24: # define RN ((Seed = Seed * 11109 + 13849) & 0x7fff) ! 25: # endif pdp11 ! 26: ! 27: int Seed = 0; ! 28: ! 29: ! 30: SOCKET Daemon; ! 31: char *First_arg; /* pointer to argv[0] */ ! 32: char *Last_arg; /* pointer to end of argv/environ */ ! 33: # ifdef INTERNET ! 34: int Test_socket; /* test socket to answer datagrams */ ! 35: FLAG inetd_spawned; /* invoked via inetd */ ! 36: FLAG standard_port = TRUE; /* true if listening on standard port */ ! 37: u_short sock_port; /* port # of tcp listen socket */ ! 38: u_short stat_port; /* port # of statistics tcp socket */ ! 39: # define DAEMON_SIZE (sizeof Daemon) ! 40: # else INTERNET ! 41: # define DAEMON_SIZE (sizeof Daemon - 1) ! 42: # endif INTERNET ! 43: ! 44: /* ! 45: * main: ! 46: * The main program. ! 47: */ ! 48: main(ac, av, ep) ! 49: int ac; ! 50: char **av, **ep; ! 51: { ! 52: register PLAYER *pp; ! 53: register int had_char; ! 54: # ifdef INTERNET ! 55: register long test_mask; ! 56: u_short msg; ! 57: short port_num, reply; ! 58: int namelen; ! 59: SOCKET test; ! 60: # endif INTERNET ! 61: static long read_fds; ! 62: static FLAG first = TRUE; ! 63: static FLAG server = FALSE; ! 64: extern int optind; ! 65: extern char *optarg; ! 66: int c; ! 67: static struct timeval linger = { 90, 0 }; ! 68: ! 69: First_arg = av[0]; ! 70: if (ep == NULL || *ep == NULL) ! 71: ep = av + ac; ! 72: while (*ep) ! 73: ep++; ! 74: Last_arg = ep[-1] + strlen(ep[-1]); ! 75: ! 76: while ((c = getopt(ac, av, "sp:")) != EOF) { ! 77: switch (c) { ! 78: case 's': ! 79: server = TRUE; ! 80: break; ! 81: # ifdef INTERNET ! 82: case 'p': ! 83: standard_port = FALSE; ! 84: Test_port = atoi(optarg); ! 85: break; ! 86: # endif ! 87: default: ! 88: erred: ! 89: fprintf(stderr, "Usage: %s [-s] [-p port]\n", av[0]); ! 90: exit(1); ! 91: } ! 92: } ! 93: if (optind < ac) ! 94: goto erred; ! 95: ! 96: init(); ! 97: Sock_mask = (1 << Socket); ! 98: Stat_mask = (1 << Status); ! 99: # ifdef INTERNET ! 100: test_mask = (1 << Test_socket); ! 101: # endif INTERNET ! 102: ! 103: ! 104: again: ! 105: do { ! 106: read_fds = Fds_mask; ! 107: errno = 0; ! 108: while (select(Num_fds, &read_fds, (int *) NULL, ! 109: (int *) NULL, (struct timeval *) NULL) < 0) ! 110: { ! 111: if (errno != EINTR) ! 112: # ifdef LOG ! 113: syslog(LOG_WARNING, "select: %m"); ! 114: # else LOG ! 115: perror("select"); ! 116: # endif LOG ! 117: errno = 0; ! 118: } ! 119: Have_inp = read_fds; ! 120: # ifdef INTERNET ! 121: if (read_fds & test_mask) { ! 122: namelen = DAEMON_SIZE; ! 123: port_num = htons(sock_port); ! 124: (void) recvfrom(Test_socket, (char *) &msg, sizeof msg, ! 125: 0, (struct sockaddr *) &test, &namelen); ! 126: switch (ntohs(msg)) { ! 127: case C_MESSAGE: ! 128: if (Nplayer <= 0) ! 129: break; ! 130: reply = htons((u_short) Nplayer); ! 131: (void) sendto(Test_socket, (char *) &reply, ! 132: sizeof reply, 0, ! 133: (struct sockaddr *) &test, DAEMON_SIZE); ! 134: break; ! 135: case C_SCORES: ! 136: reply = htons(stat_port); ! 137: (void) sendto(Test_socket, (char *) &reply, ! 138: sizeof reply, 0, ! 139: (struct sockaddr *) &test, DAEMON_SIZE); ! 140: break; ! 141: case C_PLAYER: ! 142: case C_MONITOR: ! 143: if (msg == C_MONITOR && Nplayer <= 0) ! 144: break; ! 145: reply = htons(sock_port); ! 146: (void) sendto(Test_socket, (char *) &reply, ! 147: sizeof reply, 0, ! 148: (struct sockaddr *) &test, DAEMON_SIZE); ! 149: break; ! 150: } ! 151: } ! 152: # endif INTERNET ! 153: for (;;) { ! 154: had_char = FALSE; ! 155: for (pp = Player; pp < End_player; pp++) ! 156: if (havechar(pp)) { ! 157: execute(pp); ! 158: pp->p_nexec++; ! 159: had_char++; ! 160: } ! 161: # ifdef MONITOR ! 162: for (pp = Monitor; pp < End_monitor; pp++) ! 163: if (havechar(pp)) { ! 164: mon_execute(pp); ! 165: pp->p_nexec++; ! 166: had_char++; ! 167: } ! 168: # endif MONITOR ! 169: if (!had_char) ! 170: break; ! 171: moveshots(); ! 172: for (pp = Player; pp < End_player; ) ! 173: if (pp->p_death[0] != '\0') ! 174: zap(pp, TRUE); ! 175: else ! 176: pp++; ! 177: # ifdef MONITOR ! 178: for (pp = Monitor; pp < End_monitor; ) ! 179: if (pp->p_death[0] != '\0') ! 180: zap(pp, FALSE); ! 181: else ! 182: pp++; ! 183: # endif MONITOR ! 184: } ! 185: if (read_fds & Sock_mask) ! 186: if (answer()) { ! 187: # ifdef INTERNET ! 188: if (first && standard_port) ! 189: faketalk(); ! 190: # endif ! 191: first = FALSE; ! 192: } ! 193: if (read_fds & Stat_mask) ! 194: send_stats(); ! 195: for (pp = Player; pp < End_player; pp++) { ! 196: if (read_fds & pp->p_mask) ! 197: sendcom(pp, READY, pp->p_nexec); ! 198: pp->p_nexec = 0; ! 199: (void) fflush(pp->p_output); ! 200: } ! 201: # ifdef MONITOR ! 202: for (pp = Monitor; pp < End_monitor; pp++) { ! 203: if (read_fds & pp->p_mask) ! 204: sendcom(pp, READY, pp->p_nexec); ! 205: pp->p_nexec = 0; ! 206: (void) fflush(pp->p_output); ! 207: } ! 208: # endif MONITOR ! 209: } while (Nplayer > 0); ! 210: ! 211: read_fds = Fds_mask; ! 212: if (select(Num_fds, &read_fds, (int *) NULL, (int *) NULL, ! 213: &linger) > 0) { ! 214: goto again; ! 215: } ! 216: if (server) { ! 217: clear_scores(); ! 218: makemaze(); ! 219: clearwalls(); ! 220: # ifdef BOOTS ! 221: makeboots(); ! 222: # endif BOOTS ! 223: first = TRUE; ! 224: goto again; ! 225: } ! 226: ! 227: # ifdef MONITOR ! 228: for (pp = Monitor; pp < End_monitor; ) ! 229: zap(pp, FALSE); ! 230: # endif MONITOR ! 231: cleanup(0); ! 232: } ! 233: ! 234: /* ! 235: * init: ! 236: * Initialize the global parameters. ! 237: */ ! 238: init() ! 239: { ! 240: register int i; ! 241: # ifdef INTERNET ! 242: auto SOCKET test_port; ! 243: auto int msg; ! 244: auto int len; ! 245: # endif INTERNET ! 246: ! 247: # ifndef DEBUG ! 248: # ifdef TIOCNOTTY ! 249: (void) ioctl(fileno(stdout), TIOCNOTTY, NULL); ! 250: # endif ! 251: (void) setpgrp(getpid(), getpid()); ! 252: (void) signal(SIGHUP, SIG_IGN); ! 253: (void) signal(SIGINT, SIG_IGN); ! 254: (void) signal(SIGQUIT, SIG_IGN); ! 255: (void) signal(SIGTERM, cleanup); ! 256: # endif DEBUG ! 257: ! 258: (void) chdir("/usr/tmp"); /* just in case it core dumps */ ! 259: (void) umask(0); /* No privacy at all! */ ! 260: (void) signal(SIGPIPE, SIG_IGN); ! 261: ! 262: # ifdef LOG ! 263: # ifdef SYSLOG_43 ! 264: openlog("HUNT", LOG_PID, LOG_DAEMON); ! 265: # endif ! 266: # ifdef SYSLOG_42 ! 267: openlog("HUNT", LOG_PID); ! 268: # endif ! 269: # endif ! 270: ! 271: /* ! 272: * Initialize statistics socket ! 273: */ ! 274: # ifdef INTERNET ! 275: Daemon.sin_family = SOCK_FAMILY; ! 276: Daemon.sin_addr.s_addr = INADDR_ANY; ! 277: Daemon.sin_port = 0; ! 278: # else INTERNET ! 279: Daemon.sun_family = SOCK_FAMILY; ! 280: (void) strcpy(Daemon.sun_path, Stat_name); ! 281: # endif INTERNET ! 282: ! 283: Status = socket(SOCK_FAMILY, SOCK_STREAM, 0); ! 284: if (bind(Status, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) { ! 285: if (errno == EADDRINUSE) ! 286: exit(0); ! 287: else { ! 288: # ifdef LOG ! 289: syslog(LOG_ERR, "bind: %m"); ! 290: # else LOG ! 291: perror("bind"); ! 292: # endif LOG ! 293: cleanup(1); ! 294: } ! 295: } ! 296: (void) listen(Status, 5); ! 297: ! 298: # ifdef INTERNET ! 299: len = sizeof (SOCKET); ! 300: if (getsockname(Status, (struct sockaddr *) &Daemon, &len) < 0) { ! 301: # ifdef LOG ! 302: syslog(LOG_ERR, "getsockname: %m"); ! 303: # else LOG ! 304: perror("getsockname"); ! 305: # endif LOG ! 306: exit(1); ! 307: } ! 308: stat_port = ntohs(Daemon.sin_port); ! 309: # endif INTERNET ! 310: ! 311: /* ! 312: * Initialize main socket ! 313: */ ! 314: # ifdef INTERNET ! 315: Daemon.sin_family = SOCK_FAMILY; ! 316: Daemon.sin_addr.s_addr = INADDR_ANY; ! 317: Daemon.sin_port = 0; ! 318: # else INTERNET ! 319: Daemon.sun_family = SOCK_FAMILY; ! 320: (void) strcpy(Daemon.sun_path, Sock_name); ! 321: # endif INTERNET ! 322: ! 323: Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0); ! 324: # if defined(INTERNET) ! 325: msg = 1; ! 326: if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, &msg, sizeof msg)<0) ! 327: # ifdef LOG ! 328: syslog(LOG_WARNING, "setsockopt loopback %m"); ! 329: # else LOG ! 330: perror("setsockopt loopback"); ! 331: # endif LOG ! 332: # endif INTERNET ! 333: if (bind(Socket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) { ! 334: if (errno == EADDRINUSE) ! 335: exit(0); ! 336: else { ! 337: # ifdef LOG ! 338: syslog(LOG_ERR, "bind: %m"); ! 339: # else LOG ! 340: perror("bind"); ! 341: # endif LOG ! 342: cleanup(1); ! 343: } ! 344: } ! 345: (void) listen(Socket, 5); ! 346: ! 347: # ifdef INTERNET ! 348: len = sizeof (SOCKET); ! 349: if (getsockname(Socket, (struct sockaddr *) &Daemon, &len) < 0) { ! 350: # ifdef LOG ! 351: syslog(LOG_ERR, "getsockname: %m"); ! 352: # else LOG ! 353: perror("getsockname"); ! 354: # endif LOG ! 355: exit(1); ! 356: } ! 357: sock_port = ntohs(Daemon.sin_port); ! 358: # endif INTERNET ! 359: ! 360: /* ! 361: * Initialize minimal select mask ! 362: */ ! 363: Fds_mask = (1 << Socket) | (1 << Status); ! 364: Num_fds = ((Socket > Status) ? Socket : Status) + 1; ! 365: ! 366: # ifdef INTERNET ! 367: len = sizeof (SOCKET); ! 368: if (getsockname(0, (struct sockaddr *) &test_port, &len) >= 0 ! 369: && test_port.sin_family == AF_INET) { ! 370: inetd_spawned = TRUE; ! 371: Test_socket = 0; ! 372: if (test_port.sin_port != htons((u_short) Test_port)) { ! 373: standard_port = FALSE; ! 374: Test_port = ntohs(test_port.sin_port); ! 375: } ! 376: } else { ! 377: test_port = Daemon; ! 378: test_port.sin_port = htons((u_short) Test_port); ! 379: ! 380: Test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0); ! 381: if (bind(Test_socket, (struct sockaddr *) &test_port, ! 382: DAEMON_SIZE) < 0) { ! 383: # ifdef LOG ! 384: syslog(LOG_ERR, "bind: %m"); ! 385: # else LOG ! 386: perror("bind"); ! 387: # endif LOG ! 388: exit(1); ! 389: } ! 390: (void) listen(Test_socket, 5); ! 391: } ! 392: ! 393: Fds_mask |= (1 << Test_socket); ! 394: if (Test_socket + 1 > Num_fds) ! 395: Num_fds = Test_socket + 1; ! 396: # endif INTERNET ! 397: ! 398: Seed = getpid() + time((time_t *) NULL); ! 399: makemaze(); ! 400: # ifdef BOOTS ! 401: makeboots(); ! 402: # endif BOOTS ! 403: ! 404: for (i = 0; i < NASCII; i++) ! 405: See_over[i] = TRUE; ! 406: See_over[DOOR] = FALSE; ! 407: See_over[WALL1] = FALSE; ! 408: See_over[WALL2] = FALSE; ! 409: See_over[WALL3] = FALSE; ! 410: # ifdef REFLECT ! 411: See_over[WALL4] = FALSE; ! 412: See_over[WALL5] = FALSE; ! 413: # endif REFLECT ! 414: ! 415: } ! 416: ! 417: # ifdef BOOTS ! 418: /* ! 419: * makeboots: ! 420: * Put the boots in the maze ! 421: */ ! 422: makeboots() ! 423: { ! 424: register int x, y; ! 425: register PLAYER *pp; ! 426: ! 427: do { ! 428: x = rand_num(WIDTH - 1) + 1; ! 429: y = rand_num(HEIGHT - 1) + 1; ! 430: } while (Maze[y][x] != SPACE); ! 431: Maze[y][x] = BOOT_PAIR; ! 432: for (pp = Boot; pp < &Boot[NBOOTS]; pp++) ! 433: pp->p_flying = -1; ! 434: } ! 435: # endif ! 436: ! 437: ! 438: /* ! 439: * checkdam: ! 440: * Check the damage to the given player, and see if s/he is killed ! 441: */ ! 442: checkdam(ouch, gotcha, credit, amt, shot_type) ! 443: register PLAYER *ouch, *gotcha; ! 444: register IDENT *credit; ! 445: int amt; ! 446: char shot_type; ! 447: { ! 448: register char *cp; ! 449: ! 450: if (ouch->p_death[0] != '\0') ! 451: return; ! 452: # ifdef BOOTS ! 453: if (shot_type == SLIME) ! 454: switch (ouch->p_nboots) { ! 455: default: ! 456: break; ! 457: case 1: ! 458: amt = (amt + 1) / 2; ! 459: break; ! 460: case 2: ! 461: if (gotcha != NULL) ! 462: message(gotcha, "He has boots on!"); ! 463: return; ! 464: } ! 465: # endif ! 466: ouch->p_damage += amt; ! 467: if (ouch->p_damage <= ouch->p_damcap) { ! 468: (void) sprintf(Buf, "%2d", ouch->p_damage); ! 469: cgoto(ouch, STAT_DAM_ROW, STAT_VALUE_COL); ! 470: outstr(ouch, Buf, 2); ! 471: return; ! 472: } ! 473: ! 474: /* Someone DIED */ ! 475: switch (shot_type) { ! 476: default: ! 477: cp = "Killed"; ! 478: break; ! 479: # ifdef FLY ! 480: case FALL: ! 481: cp = "Killed on impact"; ! 482: break; ! 483: # endif FLY ! 484: case KNIFE: ! 485: cp = "Stabbed to death"; ! 486: ouch->p_ammo = 0; /* No exploding */ ! 487: break; ! 488: case SHOT: ! 489: cp = "Shot to death"; ! 490: break; ! 491: case GRENADE: ! 492: case SATCHEL: ! 493: case BOMB: ! 494: cp = "Bombed"; ! 495: break; ! 496: case MINE: ! 497: case GMINE: ! 498: cp = "Blown apart"; ! 499: break; ! 500: # ifdef OOZE ! 501: case SLIME: ! 502: cp = "Slimed"; ! 503: if (credit != NULL) ! 504: credit->i_slime++; ! 505: break; ! 506: # endif OOZE ! 507: # ifdef VOLCANO ! 508: case LAVA: ! 509: cp = "Baked"; ! 510: break; ! 511: # endif VOLCANO ! 512: # ifdef DRONE ! 513: case DSHOT: ! 514: cp = "Eliminated"; ! 515: break; ! 516: # endif DRONE ! 517: } ! 518: if (credit == NULL) { ! 519: (void) sprintf(ouch->p_death, "| %s by %s |", cp, ! 520: (shot_type == MINE || shot_type == GMINE) ? ! 521: "a mine" : "act of God"); ! 522: return; ! 523: } ! 524: ! 525: (void) sprintf(ouch->p_death, "| %s by %s |", cp, credit->i_name); ! 526: ! 527: if (ouch == gotcha) { /* No use killing yourself */ ! 528: credit->i_kills--; ! 529: credit->i_bkills++; ! 530: } ! 531: else if (ouch->p_ident->i_team == ' ' ! 532: || ouch->p_ident->i_team != credit->i_team) { ! 533: credit->i_kills++; ! 534: credit->i_gkills++; ! 535: } ! 536: else { ! 537: credit->i_kills--; ! 538: credit->i_bkills++; ! 539: } ! 540: credit->i_score = credit->i_kills / (double) credit->i_entries; ! 541: ouch->p_ident->i_deaths++; ! 542: if (ouch->p_nchar == 0) ! 543: ouch->p_ident->i_stillb++; ! 544: if (gotcha == NULL) ! 545: return; ! 546: gotcha->p_damcap += STABDAM; ! 547: gotcha->p_damage -= STABDAM; ! 548: if (gotcha->p_damage < 0) ! 549: gotcha->p_damage = 0; ! 550: (void) sprintf(Buf, "%2d/%2d", gotcha->p_damage, gotcha->p_damcap); ! 551: cgoto(gotcha, STAT_DAM_ROW, STAT_VALUE_COL); ! 552: outstr(gotcha, Buf, 5); ! 553: (void) sprintf(Buf, "%3d", (gotcha->p_damcap - MAXDAM) / 2); ! 554: cgoto(gotcha, STAT_KILL_ROW, STAT_VALUE_COL); ! 555: outstr(gotcha, Buf, 3); ! 556: (void) sprintf(Buf, "%5.2f", gotcha->p_ident->i_score); ! 557: for (ouch = Player; ouch < End_player; ouch++) { ! 558: cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player), ! 559: STAT_NAME_COL); ! 560: outstr(ouch, Buf, 5); ! 561: } ! 562: # ifdef MONITOR ! 563: for (ouch = Monitor; ouch < End_monitor; ouch++) { ! 564: cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player), ! 565: STAT_NAME_COL); ! 566: outstr(ouch, Buf, 5); ! 567: } ! 568: # endif MONITOR ! 569: } ! 570: ! 571: /* ! 572: * zap: ! 573: * Kill off a player and take him out of the game. ! 574: */ ! 575: zap(pp, was_player) ! 576: register PLAYER *pp; ! 577: FLAG was_player; ! 578: { ! 579: register int i, len; ! 580: register BULLET *bp; ! 581: register PLAYER *np; ! 582: register int x, y; ! 583: int savefd, savemask; ! 584: ! 585: if (was_player) { ! 586: if (pp->p_undershot) ! 587: fixshots(pp->p_y, pp->p_x, pp->p_over); ! 588: drawplayer(pp, FALSE); ! 589: Nplayer--; ! 590: } ! 591: ! 592: len = strlen(pp->p_death); /* Display the cause of death */ ! 593: x = (WIDTH - len) / 2; ! 594: cgoto(pp, HEIGHT / 2, x); ! 595: outstr(pp, pp->p_death, len); ! 596: for (i = 1; i < len; i++) ! 597: pp->p_death[i] = '-'; ! 598: pp->p_death[0] = '+'; ! 599: pp->p_death[len - 1] = '+'; ! 600: cgoto(pp, HEIGHT / 2 - 1, x); ! 601: outstr(pp, pp->p_death, len); ! 602: cgoto(pp, HEIGHT / 2 + 1, x); ! 603: outstr(pp, pp->p_death, len); ! 604: cgoto(pp, HEIGHT, 0); ! 605: ! 606: savefd = pp->p_fd; ! 607: savemask = pp->p_mask; ! 608: ! 609: # ifdef MONITOR ! 610: if (was_player) { ! 611: # endif MONITOR ! 612: for (bp = Bullets; bp != NULL; bp = bp->b_next) { ! 613: if (bp->b_owner == pp) ! 614: bp->b_owner = NULL; ! 615: if (bp->b_x == pp->p_x && bp->b_y == pp->p_y) ! 616: bp->b_over = SPACE; ! 617: } ! 618: ! 619: i = rand_num(pp->p_ammo); ! 620: x = rand_num(pp->p_ammo); ! 621: if (x > i) ! 622: i = x; ! 623: if (pp->p_ammo == 0) ! 624: x = 0; ! 625: else if (i == pp->p_ammo - 1) { ! 626: x = pp->p_ammo; ! 627: len = SLIME; ! 628: } ! 629: else { ! 630: for (x = MAXBOMB - 1; x > 0; x--) ! 631: if (i >= shot_req[x]) ! 632: break; ! 633: for (y = MAXSLIME - 1; y > 0; y--) ! 634: if (i >= slime_req[y]) ! 635: break; ! 636: if (y >= 0 && slime_req[y] > shot_req[x]) { ! 637: x = slime_req[y]; ! 638: len = SLIME; ! 639: } ! 640: else if (x != 0) { ! 641: len = shot_type[x]; ! 642: x = shot_req[x]; ! 643: } ! 644: } ! 645: if (x > 0) { ! 646: (void) add_shot(len, pp->p_y, pp->p_x, pp->p_face, x, ! 647: (PLAYER *) NULL, TRUE, SPACE); ! 648: (void) sprintf(Buf, "%s detonated.", ! 649: pp->p_ident->i_name); ! 650: for (np = Player; np < End_player; np++) ! 651: message(np, Buf); ! 652: # ifdef MONITOR ! 653: for (np = Monitor; np < End_monitor; np++) ! 654: message(np, Buf); ! 655: # endif MONITOR ! 656: # ifdef BOOTS ! 657: while (pp->p_nboots-- > 0) { ! 658: for (np = Boot; np < &Boot[NBOOTS]; np++) ! 659: if (np->p_flying < 0) ! 660: break; ! 661: if (np >= &Boot[NBOOTS]) ! 662: abort(1, "Too many boots"); ! 663: np->p_undershot = FALSE; ! 664: np->p_x = pp->p_x; ! 665: np->p_y = pp->p_y; ! 666: np->p_flying = rand_num(20); ! 667: np->p_flyx = 2 * rand_num(6) - 5; ! 668: np->p_flyy = 2 * rand_num(6) - 5; ! 669: np->p_over = SPACE; ! 670: np->p_face = BOOT; ! 671: showexpl(np->p_y, np->p_x, BOOT); ! 672: } ! 673: # endif BOOTS ! 674: } ! 675: # ifdef BOOTS ! 676: else if (pp->p_nboots > 0) { ! 677: if (pp->p_nboots == 2) ! 678: Maze[pp->p_y][pp->p_x] = BOOT_PAIR; ! 679: else ! 680: Maze[pp->p_y][pp->p_x] = BOOT; ! 681: if (pp->p_undershot) ! 682: fixshots(pp->p_y, pp->p_x, ! 683: Maze[pp->p_y][pp->p_x]); ! 684: } ! 685: # endif BOOTS ! 686: ! 687: # ifdef VOLCANO ! 688: volcano += pp->p_ammo - x; ! 689: if (rand_num(100) < volcano / 50) { ! 690: do { ! 691: x = rand_num(WIDTH / 2) + WIDTH / 4; ! 692: y = rand_num(HEIGHT / 2) + HEIGHT / 4; ! 693: } while (Maze[y][x] != SPACE); ! 694: (void) add_shot(LAVA, y, x, LEFTS, volcano, ! 695: (PLAYER *) NULL, TRUE, SPACE); ! 696: for (np = Player; np < End_player; np++) ! 697: message(np, "Volcano eruption."); ! 698: volcano = 0; ! 699: } ! 700: # endif VOLCANO ! 701: ! 702: # ifdef DRONE ! 703: if (rand_num(100) < 2) { ! 704: do { ! 705: x = rand_num(WIDTH / 2) + WIDTH / 4; ! 706: y = rand_num(HEIGHT / 2) + HEIGHT / 4; ! 707: } while (Maze[y][x] != SPACE); ! 708: add_shot(DSHOT, y, x, rand_dir(), ! 709: shot_req[MINDSHOT + ! 710: rand_num(MAXBOMB - MINDSHOT)], ! 711: (PLAYER *) NULL, FALSE, SPACE); ! 712: } ! 713: # endif DRONE ! 714: ! 715: sendcom(pp, ENDWIN); ! 716: (void) fclose(pp->p_output); ! 717: ! 718: End_player--; ! 719: if (pp != End_player) { ! 720: bcopy((char *) End_player, (char *) pp, ! 721: sizeof (PLAYER)); ! 722: (void) sprintf(Buf, "%5.2f%c%-10.10s %c", ! 723: pp->p_ident->i_score, stat_char(pp), ! 724: pp->p_ident->i_name, pp->p_ident->i_team); ! 725: i = STAT_PLAY_ROW + 1 + (pp - Player); ! 726: for (np = Player; np < End_player; np++) { ! 727: cgoto(np, i, STAT_NAME_COL); ! 728: outstr(np, Buf, STAT_NAME_LEN); ! 729: } ! 730: # ifdef MONITOR ! 731: for (np = Monitor; np < End_monitor; np++) { ! 732: cgoto(np, i, STAT_NAME_COL); ! 733: outstr(np, Buf, STAT_NAME_LEN); ! 734: } ! 735: # endif MONITOR ! 736: } ! 737: ! 738: /* Erase the last player */ ! 739: i = STAT_PLAY_ROW + 1 + Nplayer; ! 740: for (np = Player; np < End_player; np++) { ! 741: cgoto(np, i, STAT_NAME_COL); ! 742: ce(np); ! 743: } ! 744: # ifdef MONITOR ! 745: for (np = Monitor; np < End_monitor; np++) { ! 746: cgoto(np, i, STAT_NAME_COL); ! 747: ce(np); ! 748: } ! 749: } ! 750: else { ! 751: sendcom(pp, ENDWIN); ! 752: (void) putc(LAST_PLAYER, pp->p_output); ! 753: (void) fclose(pp->p_output); ! 754: ! 755: End_monitor--; ! 756: if (pp != End_monitor) { ! 757: bcopy((char *) End_monitor, (char *) pp, ! 758: sizeof (PLAYER)); ! 759: (void) sprintf(Buf, "%5.5s %-10.10s %c", " ", ! 760: pp->p_ident->i_name, pp->p_ident->i_team); ! 761: i = STAT_MON_ROW + 1 + (pp - Player); ! 762: for (np = Player; np < End_player; np++) { ! 763: cgoto(np, i, STAT_NAME_COL); ! 764: outstr(np, Buf, STAT_NAME_LEN); ! 765: } ! 766: for (np = Monitor; np < End_monitor; np++) { ! 767: cgoto(np, i, STAT_NAME_COL); ! 768: outstr(np, Buf, STAT_NAME_LEN); ! 769: } ! 770: } ! 771: ! 772: /* Erase the last monitor */ ! 773: i = STAT_MON_ROW + 1 + (End_monitor - Monitor); ! 774: for (np = Player; np < End_player; np++) { ! 775: cgoto(np, i, STAT_NAME_COL); ! 776: ce(np); ! 777: } ! 778: for (np = Monitor; np < End_monitor; np++) { ! 779: cgoto(np, i, STAT_NAME_COL); ! 780: ce(np); ! 781: } ! 782: ! 783: } ! 784: # endif MONITOR ! 785: ! 786: Fds_mask &= ~savemask; ! 787: if (Num_fds == savefd + 1) { ! 788: Num_fds = Socket; ! 789: # ifdef INTERNET ! 790: if (Test_socket > Socket) ! 791: Num_fds = Test_socket; ! 792: # endif INTERNET ! 793: for (np = Player; np < End_player; np++) ! 794: if (np->p_fd > Num_fds) ! 795: Num_fds = np->p_fd; ! 796: # ifdef MONITOR ! 797: for (np = Monitor; np < End_monitor; np++) ! 798: if (np->p_fd > Num_fds) ! 799: Num_fds = np->p_fd; ! 800: # endif MONITOR ! 801: Num_fds++; ! 802: } ! 803: } ! 804: ! 805: /* ! 806: * rand_num: ! 807: * Return a random number in a given range. ! 808: */ ! 809: rand_num(range) ! 810: int range; ! 811: { ! 812: return (range == 0 ? 0 : RN % range); ! 813: } ! 814: ! 815: /* ! 816: * havechar: ! 817: * Check to see if we have any characters in the input queue; if ! 818: * we do, read them, stash them away, and return TRUE; else return ! 819: * FALSE. ! 820: */ ! 821: havechar(pp) ! 822: register PLAYER *pp; ! 823: { ! 824: extern int errno; ! 825: ! 826: if (pp->p_ncount < pp->p_nchar) ! 827: return TRUE; ! 828: if (!(Have_inp & pp->p_mask)) ! 829: return FALSE; ! 830: Have_inp &= ~pp->p_mask; ! 831: check_again: ! 832: errno = 0; ! 833: if ((pp->p_nchar = read(pp->p_fd, pp->p_cbuf, sizeof pp->p_cbuf)) <= 0) ! 834: { ! 835: if (errno == EINTR) ! 836: goto check_again; ! 837: pp->p_cbuf[0] = 'q'; ! 838: } ! 839: pp->p_ncount = 0; ! 840: return TRUE; ! 841: } ! 842: ! 843: /* ! 844: * cleanup: ! 845: * Exit with the given value, cleaning up any droppings lying around ! 846: */ ! 847: cleanup(eval) ! 848: int eval; ! 849: { ! 850: register PLAYER *pp; ! 851: ! 852: for (pp = Player; pp < End_player; pp++) { ! 853: cgoto(pp, HEIGHT, 0); ! 854: sendcom(pp, ENDWIN); ! 855: (void) putc(LAST_PLAYER, pp->p_output); ! 856: (void) fclose(pp->p_output); ! 857: } ! 858: # ifdef MONITOR ! 859: for (pp = Monitor; pp < End_monitor; pp++) { ! 860: cgoto(pp, HEIGHT, 0); ! 861: sendcom(pp, ENDWIN); ! 862: (void) putc(LAST_PLAYER, pp->p_output); ! 863: (void) fclose(pp->p_output); ! 864: } ! 865: # endif MONITOR ! 866: (void) close(Socket); ! 867: # ifdef AF_UNIX_HACK ! 868: (void) unlink(Sock_name); ! 869: # endif AF_UNIX_HACK ! 870: ! 871: exit(eval); ! 872: } ! 873: ! 874: /* ! 875: * send_stats: ! 876: * Print stats to requestor ! 877: */ ! 878: send_stats() ! 879: { ! 880: register IDENT *ip; ! 881: register FILE *fp; ! 882: int s; ! 883: SOCKET sockstruct; ! 884: int socklen; ! 885: ! 886: /* ! 887: * Get the output stream ready ! 888: */ ! 889: # ifdef INTERNET ! 890: socklen = sizeof sockstruct; ! 891: # else ! 892: socklen = sizeof sockstruct - 1; ! 893: # endif INTERNET ! 894: s = accept(Status, (struct sockaddr *) &sockstruct, &socklen); ! 895: if (s < 0) { ! 896: if (errno == EINTR) ! 897: return; ! 898: # ifdef LOG ! 899: syslog(LOG_ERR, "accept: %m"); ! 900: # else LOG ! 901: perror("accept"); ! 902: # endif LOG ! 903: return; ! 904: } ! 905: fp = fdopen(s, "w"); ! 906: if (fp == NULL) { ! 907: # ifdef LOG ! 908: syslog(LOG_ERR, "fdopen: %m"); ! 909: # else ! 910: perror("fdopen"); ! 911: # endif ! 912: (void) close(s); ! 913: return; ! 914: } ! 915: ! 916: /* ! 917: * Send output to requestor ! 918: */ ! 919: fputs("Name\t\tScore\tDucked\tAbsorb\tFaced\tShot\tRobbed\tMissed\tSlimeK\n", fp); ! 920: for (ip = Scores; ip != NULL; ip = ip->i_next) { ! 921: fprintf(fp, "%s\t", ip->i_name); ! 922: if (strlen(ip->i_name) < 8) ! 923: putc('\t', fp); ! 924: fprintf(fp, "%.2f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", ! 925: ip->i_score, ip->i_ducked, ip->i_absorbed, ! 926: ip->i_faced, ip->i_shot, ip->i_robbed, ! 927: ip->i_missed, ip->i_slime); ! 928: } ! 929: fputs("\n\nName\t\tEnemy\tFriend\tDeaths\tStill\tSaved\n", fp); ! 930: for (ip = Scores; ip != NULL; ip = ip->i_next) { ! 931: if (ip->i_team == ' ') { ! 932: fprintf(fp, "%s\t", ip->i_name); ! 933: if (strlen(ip->i_name) < 8) ! 934: putc('\t', fp); ! 935: } ! 936: else { ! 937: fprintf(fp, "%s[%c]\t", ip->i_name, ip->i_team); ! 938: if (strlen(ip->i_name) + 3 < 8) ! 939: putc('\t', fp); ! 940: } ! 941: fprintf(fp, "%d\t%d\t%d\t%d\t%d\n", ! 942: ip->i_gkills, ip->i_bkills, ip->i_deaths, ! 943: ip->i_stillb, ip->i_saved); ! 944: } ! 945: ! 946: (void) fclose(fp); ! 947: } ! 948: ! 949: /* ! 950: * clear_scores: ! 951: * Clear out the scores so the next session start clean ! 952: */ ! 953: clear_scores() ! 954: { ! 955: register IDENT *ip, *nextip; ! 956: ! 957: for (ip = Scores; ip != NULL; ip = nextip) { ! 958: nextip = ip->i_next; ! 959: (void) free((char *) ip); ! 960: } ! 961: Scores = NULL; ! 962: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.