diff options
author | mrg <mrg@NetBSD.org> | 1997-10-04 09:00:13 +0000 |
---|---|---|
committer | mrg <mrg@NetBSD.org> | 1997-10-04 09:00:13 +0000 |
commit | e9152f6d21d5a8b1e02922e0fc95b71fc21cbd92 (patch) | |
tree | 3e1b32f0c0c61414ebd853c92584cd9d95a99acc /hunt/huntd/driver.c | |
parent | 6f367f8f8be268d527e585867c1c42ffbb07668c (diff) | |
download | bsdgames-darwin-e9152f6d21d5a8b1e02922e0fc95b71fc21cbd92.tar.gz bsdgames-darwin-e9152f6d21d5a8b1e02922e0fc95b71fc21cbd92.tar.zst bsdgames-darwin-e9152f6d21d5a8b1e02922e0fc95b71fc21cbd92.zip |
hunt version 1993-07-17
Diffstat (limited to 'hunt/huntd/driver.c')
-rw-r--r-- | hunt/huntd/driver.c | 956 |
1 files changed, 956 insertions, 0 deletions
diff --git a/hunt/huntd/driver.c b/hunt/huntd/driver.c new file mode 100644 index 00000000..f7f0c9d6 --- /dev/null +++ b/hunt/huntd/driver.c @@ -0,0 +1,956 @@ +/* + * Hunt + * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold + * San Francisco, California + */ + +# include "hunt.h" +# include <signal.h> +# include <errno.h> +# include <sys/ioctl.h> +# include <sys/time.h> + +# ifndef pdp11 +# define RN (((Seed = Seed * 11109 + 13849) >> 16) & 0xffff) +# else +# define RN ((Seed = Seed * 11109 + 13849) & 0x7fff) +# endif + +int Seed = 0; + + +SOCKET Daemon; +char *First_arg; /* pointer to argv[0] */ +char *Last_arg; /* pointer to end of argv/environ */ +# ifdef INTERNET +int Test_socket; /* test socket to answer datagrams */ +FLAG inetd_spawned; /* invoked via inetd */ +FLAG standard_port = TRUE; /* true if listening on standard port */ +u_short sock_port; /* port # of tcp listen socket */ +u_short stat_port; /* port # of statistics tcp socket */ +# define DAEMON_SIZE (sizeof Daemon) +# else +# define DAEMON_SIZE (sizeof Daemon - 1) +# endif + +extern SIGNAL_TYPE cleanup(); + +/* + * main: + * The main program. + */ +main(ac, av, ep) +int ac; +char **av, **ep; +{ + register PLAYER *pp; + register int had_char; +# ifdef INTERNET + register long test_mask; + u_short msg; + short port_num, reply; + int namelen; + SOCKET test; +# endif + static long read_fds; + static FLAG first = TRUE; + static FLAG server = FALSE; + extern int optind; + extern char *optarg; + int c; + static struct timeval linger = { 90, 0 }; + + First_arg = av[0]; + if (ep == NULL || *ep == NULL) + ep = av + ac; + while (*ep) + ep++; + Last_arg = ep[-1] + strlen(ep[-1]); + + while ((c = getopt(ac, av, "sp:")) != EOF) { + switch (c) { + case 's': + server = TRUE; + break; +# ifdef INTERNET + case 'p': + standard_port = FALSE; + Test_port = atoi(optarg); + break; +# endif + default: +erred: + fprintf(stderr, "Usage: %s [-s] [-p port]\n", av[0]); + exit(1); + } + } + if (optind < ac) + goto erred; + + init(); + Sock_mask = (1 << Socket); + Stat_mask = (1 << Status); +# ifdef INTERNET + test_mask = (1 << Test_socket); +# endif + + +again: + do { + read_fds = Fds_mask; + errno = 0; + while (select(Num_fds, &read_fds, (int *) NULL, + (int *) NULL, (struct timeval *) NULL) < 0) + { + if (errno != EINTR) +# ifdef LOG + syslog(LOG_WARNING, "select: %m"); +# else + perror("select"); +# endif + errno = 0; + } + Have_inp = read_fds; +# ifdef INTERNET + if (read_fds & test_mask) { + namelen = DAEMON_SIZE; + port_num = htons(sock_port); + (void) recvfrom(Test_socket, (char *) &msg, sizeof msg, + 0, (struct sockaddr *) &test, &namelen); + switch (ntohs(msg)) { + case C_MESSAGE: + if (Nplayer <= 0) + break; + reply = htons((u_short) Nplayer); + (void) sendto(Test_socket, (char *) &reply, + sizeof reply, 0, + (struct sockaddr *) &test, DAEMON_SIZE); + break; + case C_SCORES: + reply = htons(stat_port); + (void) sendto(Test_socket, (char *) &reply, + sizeof reply, 0, + (struct sockaddr *) &test, DAEMON_SIZE); + break; + case C_PLAYER: + case C_MONITOR: + if (msg == C_MONITOR && Nplayer <= 0) + break; + reply = htons(sock_port); + (void) sendto(Test_socket, (char *) &reply, + sizeof reply, 0, + (struct sockaddr *) &test, DAEMON_SIZE); + break; + } + } +# endif + for (;;) { + had_char = FALSE; + for (pp = Player; pp < End_player; pp++) + if (havechar(pp)) { + execute(pp); + pp->p_nexec++; + had_char++; + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) + if (havechar(pp)) { + mon_execute(pp); + pp->p_nexec++; + had_char++; + } +# endif + if (!had_char) + break; + moveshots(); + for (pp = Player; pp < End_player; ) + if (pp->p_death[0] != '\0') + zap(pp, TRUE); + else + pp++; +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; ) + if (pp->p_death[0] != '\0') + zap(pp, FALSE); + else + pp++; +# endif + } + if (read_fds & Sock_mask) + if (answer()) { +# ifdef INTERNET + if (first && standard_port) + faketalk(); +# endif + first = FALSE; + } + if (read_fds & Stat_mask) + send_stats(); + for (pp = Player; pp < End_player; pp++) { + if (read_fds & pp->p_mask) + sendcom(pp, READY, pp->p_nexec); + pp->p_nexec = 0; + (void) fflush(pp->p_output); + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) { + if (read_fds & pp->p_mask) + sendcom(pp, READY, pp->p_nexec); + pp->p_nexec = 0; + (void) fflush(pp->p_output); + } +# endif + } while (Nplayer > 0); + + read_fds = Fds_mask; + if (select(Num_fds, &read_fds, (int *) NULL, (int *) NULL, + &linger) > 0) { + goto again; + } + if (server) { + clear_scores(); + makemaze(); + clearwalls(); +# ifdef BOOTS + makeboots(); +# endif + first = TRUE; + goto again; + } + +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; ) + zap(pp, FALSE); +# endif + cleanup(0); +} + +/* + * init: + * Initialize the global parameters. + */ +init() +{ + register int i; +# ifdef INTERNET + auto SOCKET test_port; + auto int msg; + auto int len; +# endif + +# ifndef DEBUG +# ifdef TIOCNOTTY + (void) ioctl(fileno(stdout), TIOCNOTTY, NULL); +# endif + (void) setpgrp(getpid(), getpid()); + (void) signal(SIGHUP, SIG_IGN); + (void) signal(SIGINT, SIG_IGN); + (void) signal(SIGQUIT, SIG_IGN); + (void) signal(SIGTERM, cleanup); +# endif + + (void) chdir("/usr/tmp"); /* just in case it core dumps */ + (void) umask(0); /* No privacy at all! */ + (void) signal(SIGPIPE, SIG_IGN); + +# ifdef LOG +# ifdef SYSLOG_43 + openlog("HUNT", LOG_PID, LOG_DAEMON); +# endif +# ifdef SYSLOG_42 + openlog("HUNT", LOG_PID); +# endif +# endif + + /* + * Initialize statistics socket + */ +# ifdef INTERNET + Daemon.sin_family = SOCK_FAMILY; + Daemon.sin_addr.s_addr = INADDR_ANY; + Daemon.sin_port = 0; +# else + Daemon.sun_family = SOCK_FAMILY; + (void) strcpy(Daemon.sun_path, Stat_name); +# endif + + Status = socket(SOCK_FAMILY, SOCK_STREAM, 0); + if (bind(Status, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) { + if (errno == EADDRINUSE) + exit(0); + else { +# ifdef LOG + syslog(LOG_ERR, "bind: %m"); +# else + perror("bind"); +# endif + cleanup(1); + } + } + (void) listen(Status, 5); + +# ifdef INTERNET + len = sizeof (SOCKET); + if (getsockname(Status, (struct sockaddr *) &Daemon, &len) < 0) { +# ifdef LOG + syslog(LOG_ERR, "getsockname: %m"); +# else + perror("getsockname"); +# endif + exit(1); + } + stat_port = ntohs(Daemon.sin_port); +# endif + + /* + * Initialize main socket + */ +# ifdef INTERNET + Daemon.sin_family = SOCK_FAMILY; + Daemon.sin_addr.s_addr = INADDR_ANY; + Daemon.sin_port = 0; +# else + Daemon.sun_family = SOCK_FAMILY; + (void) strcpy(Daemon.sun_path, Sock_name); +# endif + + Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0); +# if defined(INTERNET) + msg = 1; + if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, &msg, sizeof msg)<0) +# ifdef LOG + syslog(LOG_WARNING, "setsockopt loopback %m"); +# else + perror("setsockopt loopback"); +# endif +# endif + if (bind(Socket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) { + if (errno == EADDRINUSE) + exit(0); + else { +# ifdef LOG + syslog(LOG_ERR, "bind: %m"); +# else + perror("bind"); +# endif + cleanup(1); + } + } + (void) listen(Socket, 5); + +# ifdef INTERNET + len = sizeof (SOCKET); + if (getsockname(Socket, (struct sockaddr *) &Daemon, &len) < 0) { +# ifdef LOG + syslog(LOG_ERR, "getsockname: %m"); +# else + perror("getsockname"); +# endif + exit(1); + } + sock_port = ntohs(Daemon.sin_port); +# endif + + /* + * Initialize minimal select mask + */ + Fds_mask = (1 << Socket) | (1 << Status); + Num_fds = ((Socket > Status) ? Socket : Status) + 1; + +# ifdef INTERNET + len = sizeof (SOCKET); + if (getsockname(0, (struct sockaddr *) &test_port, &len) >= 0 + && test_port.sin_family == AF_INET) { + inetd_spawned = TRUE; + Test_socket = 0; + if (test_port.sin_port != htons((u_short) Test_port)) { + standard_port = FALSE; + Test_port = ntohs(test_port.sin_port); + } + } else { + test_port = Daemon; + test_port.sin_port = htons((u_short) Test_port); + + Test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0); + if (bind(Test_socket, (struct sockaddr *) &test_port, + DAEMON_SIZE) < 0) { +# ifdef LOG + syslog(LOG_ERR, "bind: %m"); +# else + perror("bind"); +# endif + exit(1); + } + (void) listen(Test_socket, 5); + } + + Fds_mask |= (1 << Test_socket); + if (Test_socket + 1 > Num_fds) + Num_fds = Test_socket + 1; +# endif + + Seed = getpid() + time((time_t *) NULL); + makemaze(); +# ifdef BOOTS + makeboots(); +# endif + + for (i = 0; i < NASCII; i++) + See_over[i] = TRUE; + See_over[DOOR] = FALSE; + See_over[WALL1] = FALSE; + See_over[WALL2] = FALSE; + See_over[WALL3] = FALSE; +# ifdef REFLECT + See_over[WALL4] = FALSE; + See_over[WALL5] = FALSE; +# endif + +} + +# ifdef BOOTS +/* + * makeboots: + * Put the boots in the maze + */ +makeboots() +{ + register int x, y; + register PLAYER *pp; + + do { + x = rand_num(WIDTH - 1) + 1; + y = rand_num(HEIGHT - 1) + 1; + } while (Maze[y][x] != SPACE); + Maze[y][x] = BOOT_PAIR; + for (pp = Boot; pp < &Boot[NBOOTS]; pp++) + pp->p_flying = -1; +} +# endif + + +/* + * checkdam: + * Check the damage to the given player, and see if s/he is killed + */ +checkdam(ouch, gotcha, credit, amt, shot_type) +register PLAYER *ouch, *gotcha; +register IDENT *credit; +int amt; +char shot_type; +{ + register char *cp; + + if (ouch->p_death[0] != '\0') + return; +# ifdef BOOTS + if (shot_type == SLIME) + switch (ouch->p_nboots) { + default: + break; + case 1: + amt = (amt + 1) / 2; + break; + case 2: + if (gotcha != NULL) + message(gotcha, "He has boots on!"); + return; + } +# endif + ouch->p_damage += amt; + if (ouch->p_damage <= ouch->p_damcap) { + (void) sprintf(Buf, "%2d", ouch->p_damage); + cgoto(ouch, STAT_DAM_ROW, STAT_VALUE_COL); + outstr(ouch, Buf, 2); + return; + } + + /* Someone DIED */ + switch (shot_type) { + default: + cp = "Killed"; + break; +# ifdef FLY + case FALL: + cp = "Killed on impact"; + break; +# endif + case KNIFE: + cp = "Stabbed to death"; + ouch->p_ammo = 0; /* No exploding */ + break; + case SHOT: + cp = "Shot to death"; + break; + case GRENADE: + case SATCHEL: + case BOMB: + cp = "Bombed"; + break; + case MINE: + case GMINE: + cp = "Blown apart"; + break; +# ifdef OOZE + case SLIME: + cp = "Slimed"; + if (credit != NULL) + credit->i_slime++; + break; +# endif +# ifdef VOLCANO + case LAVA: + cp = "Baked"; + break; +# endif +# ifdef DRONE + case DSHOT: + cp = "Eliminated"; + break; +# endif + } + if (credit == NULL) { + (void) sprintf(ouch->p_death, "| %s by %s |", cp, + (shot_type == MINE || shot_type == GMINE) ? + "a mine" : "act of God"); + return; + } + + (void) sprintf(ouch->p_death, "| %s by %s |", cp, credit->i_name); + + if (ouch == gotcha) { /* No use killing yourself */ + credit->i_kills--; + credit->i_bkills++; + } + else if (ouch->p_ident->i_team == ' ' + || ouch->p_ident->i_team != credit->i_team) { + credit->i_kills++; + credit->i_gkills++; + } + else { + credit->i_kills--; + credit->i_bkills++; + } + credit->i_score = credit->i_kills / (double) credit->i_entries; + ouch->p_ident->i_deaths++; + if (ouch->p_nchar == 0) + ouch->p_ident->i_stillb++; + if (gotcha == NULL) + return; + gotcha->p_damcap += STABDAM; + gotcha->p_damage -= STABDAM; + if (gotcha->p_damage < 0) + gotcha->p_damage = 0; + (void) sprintf(Buf, "%2d/%2d", gotcha->p_damage, gotcha->p_damcap); + cgoto(gotcha, STAT_DAM_ROW, STAT_VALUE_COL); + outstr(gotcha, Buf, 5); + (void) sprintf(Buf, "%3d", (gotcha->p_damcap - MAXDAM) / 2); + cgoto(gotcha, STAT_KILL_ROW, STAT_VALUE_COL); + outstr(gotcha, Buf, 3); + (void) sprintf(Buf, "%5.2f", gotcha->p_ident->i_score); + for (ouch = Player; ouch < End_player; ouch++) { + cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player), + STAT_NAME_COL); + outstr(ouch, Buf, 5); + } +# ifdef MONITOR + for (ouch = Monitor; ouch < End_monitor; ouch++) { + cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player), + STAT_NAME_COL); + outstr(ouch, Buf, 5); + } +# endif +} + +/* + * zap: + * Kill off a player and take him out of the game. + */ +zap(pp, was_player) +register PLAYER *pp; +FLAG was_player; +{ + register int i, len; + register BULLET *bp; + register PLAYER *np; + register int x, y; + int savefd, savemask; + + if (was_player) { + if (pp->p_undershot) + fixshots(pp->p_y, pp->p_x, pp->p_over); + drawplayer(pp, FALSE); + Nplayer--; + } + + len = strlen(pp->p_death); /* Display the cause of death */ + x = (WIDTH - len) / 2; + cgoto(pp, HEIGHT / 2, x); + outstr(pp, pp->p_death, len); + for (i = 1; i < len; i++) + pp->p_death[i] = '-'; + pp->p_death[0] = '+'; + pp->p_death[len - 1] = '+'; + cgoto(pp, HEIGHT / 2 - 1, x); + outstr(pp, pp->p_death, len); + cgoto(pp, HEIGHT / 2 + 1, x); + outstr(pp, pp->p_death, len); + cgoto(pp, HEIGHT, 0); + + savefd = pp->p_fd; + savemask = pp->p_mask; + +# ifdef MONITOR + if (was_player) { +# endif + for (bp = Bullets; bp != NULL; bp = bp->b_next) { + if (bp->b_owner == pp) + bp->b_owner = NULL; + if (bp->b_x == pp->p_x && bp->b_y == pp->p_y) + bp->b_over = SPACE; + } + + i = rand_num(pp->p_ammo); + x = rand_num(pp->p_ammo); + if (x > i) + i = x; + if (pp->p_ammo == 0) + x = 0; + else if (i == pp->p_ammo - 1) { + x = pp->p_ammo; + len = SLIME; + } + else { + for (x = MAXBOMB - 1; x > 0; x--) + if (i >= shot_req[x]) + break; + for (y = MAXSLIME - 1; y > 0; y--) + if (i >= slime_req[y]) + break; + if (y >= 0 && slime_req[y] > shot_req[x]) { + x = slime_req[y]; + len = SLIME; + } + else if (x != 0) { + len = shot_type[x]; + x = shot_req[x]; + } + } + if (x > 0) { + (void) add_shot(len, pp->p_y, pp->p_x, pp->p_face, x, + (PLAYER *) NULL, TRUE, SPACE); + (void) sprintf(Buf, "%s detonated.", + pp->p_ident->i_name); + for (np = Player; np < End_player; np++) + message(np, Buf); +# ifdef MONITOR + for (np = Monitor; np < End_monitor; np++) + message(np, Buf); +# endif +# ifdef BOOTS + while (pp->p_nboots-- > 0) { + for (np = Boot; np < &Boot[NBOOTS]; np++) + if (np->p_flying < 0) + break; + if (np >= &Boot[NBOOTS]) + abort(1, "Too many boots"); + np->p_undershot = FALSE; + np->p_x = pp->p_x; + np->p_y = pp->p_y; + np->p_flying = rand_num(20); + np->p_flyx = 2 * rand_num(6) - 5; + np->p_flyy = 2 * rand_num(6) - 5; + np->p_over = SPACE; + np->p_face = BOOT; + showexpl(np->p_y, np->p_x, BOOT); + } +# endif + } +# ifdef BOOTS + else if (pp->p_nboots > 0) { + if (pp->p_nboots == 2) + Maze[pp->p_y][pp->p_x] = BOOT_PAIR; + else + Maze[pp->p_y][pp->p_x] = BOOT; + if (pp->p_undershot) + fixshots(pp->p_y, pp->p_x, + Maze[pp->p_y][pp->p_x]); + } +# endif + +# ifdef VOLCANO + volcano += pp->p_ammo - x; + if (rand_num(100) < volcano / 50) { + do { + x = rand_num(WIDTH / 2) + WIDTH / 4; + y = rand_num(HEIGHT / 2) + HEIGHT / 4; + } while (Maze[y][x] != SPACE); + (void) add_shot(LAVA, y, x, LEFTS, volcano, + (PLAYER *) NULL, TRUE, SPACE); + for (np = Player; np < End_player; np++) + message(np, "Volcano eruption."); + volcano = 0; + } +# endif + +# ifdef DRONE + if (rand_num(100) < 2) { + do { + x = rand_num(WIDTH / 2) + WIDTH / 4; + y = rand_num(HEIGHT / 2) + HEIGHT / 4; + } while (Maze[y][x] != SPACE); + add_shot(DSHOT, y, x, rand_dir(), + shot_req[MINDSHOT + + rand_num(MAXBOMB - MINDSHOT)], + (PLAYER *) NULL, FALSE, SPACE); + } +# endif + + sendcom(pp, ENDWIN); + (void) putc(' ', pp->p_output); + (void) fclose(pp->p_output); + + End_player--; + if (pp != End_player) { + memcpy(pp, End_player, sizeof (PLAYER)); + (void) sprintf(Buf, "%5.2f%c%-10.10s %c", + pp->p_ident->i_score, stat_char(pp), + pp->p_ident->i_name, pp->p_ident->i_team); + i = STAT_PLAY_ROW + 1 + (pp - Player); + for (np = Player; np < End_player; np++) { + cgoto(np, i, STAT_NAME_COL); + outstr(np, Buf, STAT_NAME_LEN); + } +# ifdef MONITOR + for (np = Monitor; np < End_monitor; np++) { + cgoto(np, i, STAT_NAME_COL); + outstr(np, Buf, STAT_NAME_LEN); + } +# endif + } + + /* Erase the last player */ + i = STAT_PLAY_ROW + 1 + Nplayer; + for (np = Player; np < End_player; np++) { + cgoto(np, i, STAT_NAME_COL); + ce(np); + } +# ifdef MONITOR + for (np = Monitor; np < End_monitor; np++) { + cgoto(np, i, STAT_NAME_COL); + ce(np); + } + } + else { + sendcom(pp, ENDWIN); + (void) putc(LAST_PLAYER, pp->p_output); + (void) fclose(pp->p_output); + + End_monitor--; + if (pp != End_monitor) { + memcpy(pp, End_monitor, sizeof (PLAYER)); + (void) sprintf(Buf, "%5.5s %-10.10s %c", " ", + pp->p_ident->i_name, pp->p_ident->i_team); + i = STAT_MON_ROW + 1 + (pp - Player); + for (np = Player; np < End_player; np++) { + cgoto(np, i, STAT_NAME_COL); + outstr(np, Buf, STAT_NAME_LEN); + } + for (np = Monitor; np < End_monitor; np++) { + cgoto(np, i, STAT_NAME_COL); + outstr(np, Buf, STAT_NAME_LEN); + } + } + + /* Erase the last monitor */ + i = STAT_MON_ROW + 1 + (End_monitor - Monitor); + for (np = Player; np < End_player; np++) { + cgoto(np, i, STAT_NAME_COL); + ce(np); + } + for (np = Monitor; np < End_monitor; np++) { + cgoto(np, i, STAT_NAME_COL); + ce(np); + } + + } +# endif + + Fds_mask &= ~savemask; + if (Num_fds == savefd + 1) { + Num_fds = Socket; +# ifdef INTERNET + if (Test_socket > Socket) + Num_fds = Test_socket; +# endif + for (np = Player; np < End_player; np++) + if (np->p_fd > Num_fds) + Num_fds = np->p_fd; +# ifdef MONITOR + for (np = Monitor; np < End_monitor; np++) + if (np->p_fd > Num_fds) + Num_fds = np->p_fd; +# endif + Num_fds++; + } +} + +/* + * rand_num: + * Return a random number in a given range. + */ +rand_num(range) +int range; +{ + return (range == 0 ? 0 : RN % range); +} + +/* + * havechar: + * Check to see if we have any characters in the input queue; if + * we do, read them, stash them away, and return TRUE; else return + * FALSE. + */ +havechar(pp) +register PLAYER *pp; +{ + extern int errno; + + if (pp->p_ncount < pp->p_nchar) + return TRUE; + if (!(Have_inp & pp->p_mask)) + return FALSE; + Have_inp &= ~pp->p_mask; +check_again: + errno = 0; + if ((pp->p_nchar = read(pp->p_fd, pp->p_cbuf, sizeof pp->p_cbuf)) <= 0) + { + if (errno == EINTR) + goto check_again; + pp->p_cbuf[0] = 'q'; + } + pp->p_ncount = 0; + return TRUE; +} + +/* + * cleanup: + * Exit with the given value, cleaning up any droppings lying around + */ +SIGNAL_TYPE +cleanup(eval) +int eval; +{ + register PLAYER *pp; + + for (pp = Player; pp < End_player; pp++) { + cgoto(pp, HEIGHT, 0); + sendcom(pp, ENDWIN); + (void) putc(LAST_PLAYER, pp->p_output); + (void) fclose(pp->p_output); + } +# ifdef MONITOR + for (pp = Monitor; pp < End_monitor; pp++) { + cgoto(pp, HEIGHT, 0); + sendcom(pp, ENDWIN); + (void) putc(LAST_PLAYER, pp->p_output); + (void) fclose(pp->p_output); + } +# endif + (void) close(Socket); +# ifdef AF_UNIX_HACK + (void) unlink(Sock_name); +# endif + + exit(eval); +} + +/* + * send_stats: + * Print stats to requestor + */ +send_stats() +{ + register IDENT *ip; + register FILE *fp; + int s; + SOCKET sockstruct; + int socklen; + + /* + * Get the output stream ready + */ +# ifdef INTERNET + socklen = sizeof sockstruct; +# else + socklen = sizeof sockstruct - 1; +# endif + s = accept(Status, (struct sockaddr *) &sockstruct, &socklen); + if (s < 0) { + if (errno == EINTR) + return; +# ifdef LOG + syslog(LOG_ERR, "accept: %m"); +# else + perror("accept"); +# endif + return; + } + fp = fdopen(s, "w"); + if (fp == NULL) { +# ifdef LOG + syslog(LOG_ERR, "fdopen: %m"); +# else + perror("fdopen"); +# endif + (void) close(s); + return; + } + + /* + * Send output to requestor + */ + fputs("Name\t\tScore\tDucked\tAbsorb\tFaced\tShot\tRobbed\tMissed\tSlimeK\n", fp); + for (ip = Scores; ip != NULL; ip = ip->i_next) { + fprintf(fp, "%s\t", ip->i_name); + if (strlen(ip->i_name) < 8) + putc('\t', fp); + fprintf(fp, "%.2f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + ip->i_score, ip->i_ducked, ip->i_absorbed, + ip->i_faced, ip->i_shot, ip->i_robbed, + ip->i_missed, ip->i_slime); + } + fputs("\n\nName\t\tEnemy\tFriend\tDeaths\tStill\tSaved\n", fp); + for (ip = Scores; ip != NULL; ip = ip->i_next) { + if (ip->i_team == ' ') { + fprintf(fp, "%s\t", ip->i_name); + if (strlen(ip->i_name) < 8) + putc('\t', fp); + } + else { + fprintf(fp, "%s[%c]\t", ip->i_name, ip->i_team); + if (strlen(ip->i_name) + 3 < 8) + putc('\t', fp); + } + fprintf(fp, "%d\t%d\t%d\t%d\t%d\n", + ip->i_gkills, ip->i_bkills, ip->i_deaths, + ip->i_stillb, ip->i_saved); + } + + (void) fclose(fp); +} + +/* + * clear_scores: + * Clear out the scores so the next session start clean + */ +clear_scores() +{ + register IDENT *ip, *nextip; + + for (ip = Scores; ip != NULL; ip = nextip) { + nextip = ip->i_next; + (void) free((char *) ip); + } + Scores = NULL; +} |