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