123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988 |
- /* $NetBSD: driver.c,v 1.10 2004/01/27 20:30:29 jsm Exp $ */
- /*
- * Copyright (c) 1983-2003, Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * + Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * + Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * + Neither the name of the University of California, San Francisco nor
- * the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <sys/cdefs.h>
- #ifndef lint
- __RCSID("$NetBSD: driver.c,v 1.10 2004/01/27 20:30:29 jsm Exp $");
- #endif /* not lint */
- # include <sys/ioctl.h>
- # include <sys/stat.h>
- # include <sys/time.h>
- # include <err.h>
- # include <errno.h>
- # include <signal.h>
- # include <stdlib.h>
- # include <time.h>
- # include <unistd.h>
- # include "hunt.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
- static void clear_scores(void);
- static int havechar(PLAYER *, int);
- static void init(void);
- int main(int, char *[], char *[]);
- static void makeboots(void);
- static void send_stats(void);
- static void zap(PLAYER *, FLAG, int);
- /*
- * main:
- * The main program.
- */
- int
- main(ac, av, ep)
- int ac;
- char **av, **ep;
- {
- PLAYER *pp;
- # ifdef INTERNET
- u_short msg;
- short port_num, reply;
- int namelen;
- SOCKET test;
- # endif
- static FLAG first = TRUE;
- static FLAG server = FALSE;
- int c, i;
- const int linger = 90 * 1000;
- 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:")) != -1) {
- 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();
- again:
- do {
- errno = 0;
- while (poll(fdset, 3+MAXPL+MAXMON, INFTIM) < 0)
- {
- if (errno != EINTR)
- # ifdef LOG
- syslog(LOG_WARNING, "select: %m");
- # else
- warn("select");
- # endif
- errno = 0;
- }
- # ifdef INTERNET
- if (fdset[2].revents & POLLIN) {
- 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 (pp = Player, i = 0; pp < End_player; pp++, i++)
- if (havechar(pp, i + 3)) {
- execute(pp);
- pp->p_nexec++;
- }
- # ifdef MONITOR
- for (pp = Monitor, i = 0; pp < End_monitor; pp++, i++)
- if (havechar(pp, i + MAXPL + 3)) {
- mon_execute(pp);
- pp->p_nexec++;
- }
- # endif
- moveshots();
- for (pp = Player, i = 0; pp < End_player; )
- if (pp->p_death[0] != '\0')
- zap(pp, TRUE, i + 3);
- else
- pp++, i++;
- # ifdef MONITOR
- for (pp = Monitor, i = 0; pp < End_monitor; )
- if (pp->p_death[0] != '\0')
- zap(pp, FALSE, i + MAXPL + 3);
- else
- pp++, i++;
- # endif
- }
- if (fdset[0].revents & POLLIN)
- if (answer()) {
- # ifdef INTERNET
- if (first && standard_port)
- faketalk();
- # endif
- first = FALSE;
- }
- if (fdset[1].revents & POLLIN)
- send_stats();
- for (pp = Player, i = 0; pp < End_player; pp++, i++) {
- if (fdset[i + 3].revents & POLLIN)
- sendcom(pp, READY, pp->p_nexec);
- pp->p_nexec = 0;
- (void) fflush(pp->p_output);
- }
- # ifdef MONITOR
- for (pp = Monitor, i = 0; pp < End_monitor; pp++, i++) {
- if (fdset[i + MAXPL + 3].revents & POLLIN)
- sendcom(pp, READY, pp->p_nexec);
- pp->p_nexec = 0;
- (void) fflush(pp->p_output);
- }
- # endif
- } while (Nplayer > 0);
- if (poll(fdset, 3+MAXPL+MAXMON, linger) > 0) {
- goto again;
- }
- if (server) {
- clear_scores();
- makemaze();
- clearwalls();
- # ifdef BOOTS
- makeboots();
- # endif
- first = TRUE;
- goto again;
- }
- # ifdef MONITOR
- for (pp = Monitor, i = 0; pp < End_monitor; i++)
- zap(pp, FALSE, i + MAXPL + 3);
- # endif
- cleanup(0);
- /* NOTREACHED */
- return(0);
- }
- /*
- * init:
- * Initialize the global parameters.
- */
- static void
- init()
- {
- int i;
- # ifdef INTERNET
- SOCKET test_port;
- int msg;
- int len;
- # endif
- # ifndef DEBUG
- switch (fork()) {
- case -1:
- err(1, "fork");
- case 0:
- break; /* child */
- default:
- exit(0); /* parent */
- }
- if (setsid() == -1)
- err(1, "setsid");
- (void) signal(SIGHUP, SIG_IGN);
- (void) signal(SIGINT, SIG_IGN);
- (void) signal(SIGQUIT, SIG_IGN);
- (void) signal(SIGTERM, cleanup);
- # endif
- (void) chdir("/var/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("huntd", LOG_PID, LOG_DAEMON);
- # endif
- # ifdef SYSLOG_42
- openlog("huntd", 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
- warn("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
- warn("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;
- #ifdef SO_USELOOPBACK
- if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, &msg, sizeof msg)<0)
- # ifdef LOG
- syslog(LOG_WARNING, "setsockopt loopback %m");
- # else
- warn("setsockopt loopback");
- # endif
- #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
- warn("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
- warn("getsockname");
- # endif
- exit(1);
- }
- sock_port = ntohs(Daemon.sin_port);
- # endif
- /*
- * Initialize minimal select mask
- */
- fdset[0].fd = Socket;
- fdset[0].events = POLLIN;
- fdset[1].fd = Status;
- fdset[1].events = POLLIN;
- # 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
- warn("bind");
- # endif
- exit(1);
- }
- (void) listen(Test_socket, 5);
- }
- fdset[2].fd = Test_socket;
- fdset[2].events = POLLIN;
- # else
- fdset[2].fd = -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
- */
- static void
- makeboots()
- {
- int x, y;
- 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
- */
- void
- checkdam(ouch, gotcha, credit, amt, shot_type)
- PLAYER *ouch, *gotcha;
- IDENT *credit;
- int amt;
- char shot_type;
- {
- const 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.
- */
- static void
- zap(pp, was_player, i)
- PLAYER *pp;
- FLAG was_player;
- int i;
- {
- int n, len;
- BULLET *bp;
- PLAYER *np;
- int x, y;
- int savefd;
- 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 (n = 1; n < len; n++)
- pp->p_death[n] = '-';
- 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;
- # 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;
- }
- n = rand_num(pp->p_ammo);
- x = rand_num(pp->p_ammo);
- if (x > n)
- n = x;
- if (pp->p_ammo == 0)
- x = 0;
- else if (n == pp->p_ammo - 1) {
- x = pp->p_ammo;
- len = SLIME;
- }
- else {
- for (x = MAXBOMB - 1; x > 0; x--)
- if (n >= shot_req[x])
- break;
- for (y = MAXSLIME - 1; y > 0; y--)
- if (n >= 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])
- err(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));
- fdset[i] = fdset[End_player - Player + 3];
- fdset[End_player - Player + 3].fd = -1;
- (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);
- n = STAT_PLAY_ROW + 1 + (pp - Player);
- for (np = Player; np < End_player; np++) {
- cgoto(np, n, STAT_NAME_COL);
- outstr(np, Buf, STAT_NAME_LEN);
- }
- # ifdef MONITOR
- for (np = Monitor; np < End_monitor; np++) {
- cgoto(np, n, STAT_NAME_COL);
- outstr(np, Buf, STAT_NAME_LEN);
- }
- # endif
- } else
- fdset[i].fd = -1;
- /* Erase the last player */
- n = STAT_PLAY_ROW + 1 + Nplayer;
- for (np = Player; np < End_player; np++) {
- cgoto(np, n, STAT_NAME_COL);
- ce(np);
- }
- # ifdef MONITOR
- for (np = Monitor; np < End_monitor; np++) {
- cgoto(np, n, 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));
- fdset[i] = fdset[End_monitor - Monitor + MAXPL + 3];
- fdset[End_monitor - Monitor + MAXPL + 3].fd = -1;
- (void) sprintf(Buf, "%5.5s %-10.10s %c", " ",
- pp->p_ident->i_name, pp->p_ident->i_team);
- n = STAT_MON_ROW + 1 + (pp - Player);
- for (np = Player; np < End_player; np++) {
- cgoto(np, n, STAT_NAME_COL);
- outstr(np, Buf, STAT_NAME_LEN);
- }
- for (np = Monitor; np < End_monitor; np++) {
- cgoto(np, n, STAT_NAME_COL);
- outstr(np, Buf, STAT_NAME_LEN);
- }
- } else
- fdset[i].fd = -1;
- /* Erase the last monitor */
- n = STAT_MON_ROW + 1 + (End_monitor - Monitor);
- for (np = Player; np < End_player; np++) {
- cgoto(np, n, STAT_NAME_COL);
- ce(np);
- }
- for (np = Monitor; np < End_monitor; np++) {
- cgoto(np, n, STAT_NAME_COL);
- ce(np);
- }
- }
- # endif
- }
- /*
- * rand_num:
- * Return a random number in a given range.
- */
- int
- 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.
- */
- static int
- havechar(pp, i)
- PLAYER *pp;
- int i;
- {
- if (pp->p_ncount < pp->p_nchar)
- return TRUE;
- if (!(fdset[i].revents & POLLIN))
- return FALSE;
- 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;
- {
- 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
- */
- static void
- send_stats()
- {
- IDENT *ip;
- 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_WARNING, "accept: %m");
- # else
- warn("accept");
- # endif
- return;
- }
- fp = fdopen(s, "w");
- if (fp == NULL) {
- # ifdef LOG
- syslog(LOG_WARNING, "fdopen: %m");
- # else
- warn("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
- */
- static void
- clear_scores()
- {
- IDENT *ip, *nextip;
- for (ip = Scores; ip != NULL; ip = nextip) {
- nextip = ip->i_next;
- (void) free((char *) ip);
- }
- Scores = NULL;
- }
|