Home | History | Annotate | Line # | Download | only in huntd
driver.c revision 1.13
      1  1.13  dholland /*	$NetBSD: driver.c,v 1.13 2008/01/28 03:23:29 dholland 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.13  dholland __RCSID("$NetBSD: driver.c,v 1.13 2008/01/28 03:23:29 dholland 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.10       jsm static	void	clear_scores(void);
     72  1.10       jsm static	int	havechar(PLAYER *, int);
     73  1.10       jsm static	void	init(void);
     74  1.10       jsm 	int	main(int, char *[], char *[]);
     75  1.10       jsm static	void	makeboots(void);
     76  1.10       jsm static	void	send_stats(void);
     77  1.10       jsm static	void	zap(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.11       mrg 	socklen_t	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.12      elad 				syslog(LOG_WARNING, "poll: %m");
    139   1.1       mrg # else
    140  1.12      elad 				warn("poll");
    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.11       mrg 	socklen_t	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.12      elad 	 * Initialize minimal poll 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.13  dholland checkdam(ouch, gotcha, credit, amt, this_shot_type)
    468   1.2     lukem 	PLAYER	*ouch, *gotcha;
    469   1.2     lukem 	IDENT	*credit;
    470   1.2     lukem 	int	amt;
    471  1.13  dholland 	char	this_shot_type;
    472   1.1       mrg {
    473  1.13  dholland 	const 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.13  dholland 	if (this_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.13  dholland 	switch (this_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.13  dholland 			(this_shot_type == MINE || this_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.11       mrg 	socklen_t	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