Home | History | Annotate | Line # | Download | only in huntd
answer.c revision 1.2
      1  1.1  mrg /*
      2  1.1  mrg  *  Hunt
      3  1.1  mrg  *  Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
      4  1.1  mrg  *  San Francisco, California
      5  1.1  mrg  */
      6  1.1  mrg 
      7  1.1  mrg # include	"hunt.h"
      8  1.1  mrg # include	<ctype.h>
      9  1.1  mrg # include	<errno.h>
     10  1.1  mrg # include	<fcntl.h>
     11  1.1  mrg 
     12  1.1  mrg # define	SCOREDECAY	15
     13  1.1  mrg 
     14  1.1  mrg static char	Ttyname[NAMELEN];
     15  1.1  mrg 
     16  1.1  mrg answer()
     17  1.1  mrg {
     18  1.1  mrg 	register PLAYER		*pp;
     19  1.1  mrg 	register int		newsock;
     20  1.1  mrg 	static u_long		mode;
     21  1.1  mrg 	static char		name[NAMELEN];
     22  1.1  mrg 	static char		team;
     23  1.1  mrg 	static int		enter_status;
     24  1.1  mrg 	static int		socklen;
     25  1.1  mrg 	static u_long		machine;
     26  1.1  mrg 	static u_long		uid;
     27  1.1  mrg 	static SOCKET		sockstruct;
     28  1.1  mrg 	register char	*cp1, *cp2;
     29  1.1  mrg 	int			flags;
     30  1.1  mrg 	long			version;
     31  1.1  mrg 
     32  1.1  mrg # ifdef INTERNET
     33  1.1  mrg 	socklen = sizeof sockstruct;
     34  1.1  mrg # else
     35  1.1  mrg 	socklen = sizeof sockstruct - 1;
     36  1.1  mrg # endif
     37  1.1  mrg 	errno = 0;
     38  1.1  mrg 	newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen);
     39  1.1  mrg 	if (newsock < 0)
     40  1.1  mrg 	{
     41  1.1  mrg 		if (errno == EINTR)
     42  1.1  mrg 			return FALSE;
     43  1.1  mrg # ifdef LOG
     44  1.1  mrg 		syslog(LOG_ERR, "accept: %m");
     45  1.1  mrg # else
     46  1.1  mrg 		perror("accept");
     47  1.1  mrg # endif
     48  1.1  mrg 		cleanup(1);
     49  1.1  mrg 	}
     50  1.1  mrg 
     51  1.1  mrg # ifdef INTERNET
     52  1.1  mrg 	machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr);
     53  1.1  mrg # else
     54  1.1  mrg 	if (machine == 0)
     55  1.1  mrg 		machine = gethostid();
     56  1.1  mrg # endif
     57  1.2  mrg 	version = htonl((u_int32_t) HUNT_VERSION);
     58  1.1  mrg 	(void) write(newsock, (char *) &version, LONGLEN);
     59  1.1  mrg 	(void) read(newsock, (char *) &uid, LONGLEN);
     60  1.1  mrg 	uid = ntohl((unsigned long) uid);
     61  1.1  mrg 	(void) read(newsock, name, NAMELEN);
     62  1.1  mrg 	(void) read(newsock, &team, 1);
     63  1.1  mrg 	(void) read(newsock, (char *) &enter_status, LONGLEN);
     64  1.1  mrg 	enter_status = ntohl((unsigned long) enter_status);
     65  1.1  mrg 	(void) read(newsock, Ttyname, NAMELEN);
     66  1.1  mrg 	(void) read(newsock, (char *) &mode, sizeof mode);
     67  1.1  mrg 	mode = ntohl(mode);
     68  1.1  mrg 
     69  1.1  mrg 	/*
     70  1.1  mrg 	 * Turn off blocking I/O, so a slow or dead terminal won't stop
     71  1.1  mrg 	 * the game.  All subsequent reads check how many bytes they read.
     72  1.1  mrg 	 */
     73  1.1  mrg 	flags = fcntl(newsock, F_GETFL, 0);
     74  1.1  mrg 	flags |= O_NDELAY;
     75  1.1  mrg 	(void) fcntl(newsock, F_SETFL, flags);
     76  1.1  mrg 
     77  1.1  mrg 	/*
     78  1.1  mrg 	 * Make sure the name contains only printable characters
     79  1.1  mrg 	 * since we use control characters for cursor control
     80  1.1  mrg 	 * between driver and player processes
     81  1.1  mrg 	 */
     82  1.1  mrg 	for (cp1 = cp2 = name; *cp1 != '\0'; cp1++)
     83  1.1  mrg 		if (isprint(*cp1) || *cp1 == ' ')
     84  1.1  mrg 			*cp2++ = *cp1;
     85  1.1  mrg 	*cp2 = '\0';
     86  1.1  mrg 
     87  1.1  mrg # ifdef INTERNET
     88  1.1  mrg 	if (mode == C_MESSAGE) {
     89  1.1  mrg 		char	buf[BUFSIZ + 1];
     90  1.1  mrg 		int	n;
     91  1.1  mrg 
     92  1.1  mrg 		if (team == ' ')
     93  1.1  mrg 			(void) sprintf(buf, "%s: ", name);
     94  1.1  mrg 		else
     95  1.1  mrg 			(void) sprintf(buf, "%s[%c]: ", name, team);
     96  1.1  mrg 		n = strlen(buf);
     97  1.1  mrg 		for (pp = Player; pp < End_player; pp++) {
     98  1.1  mrg 			cgoto(pp, HEIGHT, 0);
     99  1.1  mrg 			outstr(pp, buf, n);
    100  1.1  mrg 		}
    101  1.1  mrg 		while ((n = read(newsock, buf, BUFSIZ)) > 0)
    102  1.1  mrg 			for (pp = Player; pp < End_player; pp++)
    103  1.1  mrg 				outstr(pp, buf, n);
    104  1.1  mrg 		for (pp = Player; pp < End_player; pp++) {
    105  1.1  mrg 			ce(pp);
    106  1.1  mrg 			sendcom(pp, REFRESH);
    107  1.1  mrg 			sendcom(pp, READY, 0);
    108  1.1  mrg 			(void) fflush(pp->p_output);
    109  1.1  mrg 		}
    110  1.1  mrg 		(void) close(newsock);
    111  1.1  mrg 		return FALSE;
    112  1.1  mrg 	}
    113  1.1  mrg 	else
    114  1.1  mrg # endif
    115  1.1  mrg # ifdef MONITOR
    116  1.1  mrg 	if (mode == C_MONITOR)
    117  1.1  mrg 		if (End_monitor < &Monitor[MAXMON])
    118  1.1  mrg 			pp = End_monitor++;
    119  1.1  mrg 		else {
    120  1.1  mrg 			socklen = 0;
    121  1.1  mrg 			(void) write(newsock, (char *) &socklen,
    122  1.1  mrg 				sizeof socklen);
    123  1.1  mrg 			(void) close(newsock);
    124  1.1  mrg 			return FALSE;
    125  1.1  mrg 		}
    126  1.1  mrg 	else
    127  1.1  mrg # endif
    128  1.1  mrg 		if (End_player < &Player[MAXPL])
    129  1.1  mrg 			pp = End_player++;
    130  1.1  mrg 		else {
    131  1.1  mrg 			socklen = 0;
    132  1.1  mrg 			(void) write(newsock, (char *) &socklen,
    133  1.1  mrg 				sizeof socklen);
    134  1.1  mrg 			(void) close(newsock);
    135  1.1  mrg 			return FALSE;
    136  1.1  mrg 		}
    137  1.1  mrg 
    138  1.1  mrg #ifdef MONITOR
    139  1.1  mrg 	if (mode == C_MONITOR && team == ' ')
    140  1.1  mrg 		team = '*';
    141  1.1  mrg #endif
    142  1.1  mrg 	pp->p_ident = get_ident(machine, uid, name, team);
    143  1.1  mrg 	pp->p_output = fdopen(newsock, "w");
    144  1.1  mrg 	pp->p_death[0] = '\0';
    145  1.1  mrg 	pp->p_fd = newsock;
    146  1.1  mrg 	pp->p_mask = (1 << pp->p_fd);
    147  1.1  mrg 	Fds_mask |= pp->p_mask;
    148  1.1  mrg 	if (pp->p_fd >= Num_fds)
    149  1.1  mrg 		Num_fds = pp->p_fd + 1;
    150  1.1  mrg 
    151  1.1  mrg 	pp->p_y = 0;
    152  1.1  mrg 	pp->p_x = 0;
    153  1.1  mrg 
    154  1.1  mrg # ifdef MONITOR
    155  1.1  mrg 	if (mode == C_MONITOR)
    156  1.1  mrg 		stmonitor(pp);
    157  1.1  mrg 	else
    158  1.1  mrg # endif
    159  1.1  mrg 		stplayer(pp, enter_status);
    160  1.1  mrg 	return TRUE;
    161  1.1  mrg }
    162  1.1  mrg 
    163  1.1  mrg # ifdef MONITOR
    164  1.1  mrg stmonitor(pp)
    165  1.1  mrg register PLAYER	*pp;
    166  1.1  mrg {
    167  1.1  mrg 	register int	line;
    168  1.1  mrg 	register PLAYER	*npp;
    169  1.1  mrg 
    170  1.1  mrg 	memcpy(pp->p_maze, Maze, sizeof Maze);
    171  1.1  mrg 
    172  1.1  mrg 	drawmaze(pp);
    173  1.1  mrg 
    174  1.1  mrg 	(void) sprintf(Buf, "%5.5s%c%-10.10s %c", " ", stat_char(pp),
    175  1.1  mrg 		pp->p_ident->i_name, pp->p_ident->i_team);
    176  1.1  mrg 	line = STAT_MON_ROW + 1 + (pp - Monitor);
    177  1.1  mrg 	for (npp = Player; npp < End_player; npp++) {
    178  1.1  mrg 		cgoto(npp, line, STAT_NAME_COL);
    179  1.1  mrg 		outstr(npp, Buf, STAT_NAME_LEN);
    180  1.1  mrg 	}
    181  1.1  mrg 	for (npp = Monitor; npp < End_monitor; npp++) {
    182  1.1  mrg 		cgoto(npp, line, STAT_NAME_COL);
    183  1.1  mrg 		outstr(npp, Buf, STAT_NAME_LEN);
    184  1.1  mrg 	}
    185  1.1  mrg 
    186  1.1  mrg 	sendcom(pp, REFRESH);
    187  1.1  mrg 	sendcom(pp, READY, 0);
    188  1.1  mrg 	(void) fflush(pp->p_output);
    189  1.1  mrg }
    190  1.1  mrg # endif
    191  1.1  mrg 
    192  1.1  mrg stplayer(newpp, enter_status)
    193  1.1  mrg register PLAYER	*newpp;
    194  1.1  mrg int		enter_status;
    195  1.1  mrg {
    196  1.1  mrg 	register int	x, y;
    197  1.1  mrg 	register PLAYER	*pp;
    198  1.1  mrg 
    199  1.1  mrg 	Nplayer++;
    200  1.1  mrg 
    201  1.1  mrg 	for (y = 0; y < UBOUND; y++)
    202  1.1  mrg 		for (x = 0; x < WIDTH; x++)
    203  1.1  mrg 			newpp->p_maze[y][x] = Maze[y][x];
    204  1.1  mrg 	for (     ; y < DBOUND; y++) {
    205  1.1  mrg 		for (x = 0; x < LBOUND; x++)
    206  1.1  mrg 			newpp->p_maze[y][x] = Maze[y][x];
    207  1.1  mrg 		for (     ; x < RBOUND; x++)
    208  1.1  mrg 			newpp->p_maze[y][x] = SPACE;
    209  1.1  mrg 		for (     ; x < WIDTH;  x++)
    210  1.1  mrg 			newpp->p_maze[y][x] = Maze[y][x];
    211  1.1  mrg 	}
    212  1.1  mrg 	for (     ; y < HEIGHT; y++)
    213  1.1  mrg 		for (x = 0; x < WIDTH; x++)
    214  1.1  mrg 			newpp->p_maze[y][x] = Maze[y][x];
    215  1.1  mrg 
    216  1.1  mrg 	do {
    217  1.1  mrg 		x = rand_num(WIDTH - 1) + 1;
    218  1.1  mrg 		y = rand_num(HEIGHT - 1) + 1;
    219  1.1  mrg 	} while (Maze[y][x] != SPACE);
    220  1.1  mrg 	newpp->p_over = SPACE;
    221  1.1  mrg 	newpp->p_x = x;
    222  1.1  mrg 	newpp->p_y = y;
    223  1.1  mrg 	newpp->p_undershot = FALSE;
    224  1.1  mrg 
    225  1.1  mrg # ifdef FLY
    226  1.1  mrg 	if (enter_status == Q_FLY) {
    227  1.1  mrg 		newpp->p_flying = rand_num(20);
    228  1.1  mrg 		newpp->p_flyx = 2 * rand_num(6) - 5;
    229  1.1  mrg 		newpp->p_flyy = 2 * rand_num(6) - 5;
    230  1.1  mrg 		newpp->p_face = FLYER;
    231  1.1  mrg 	}
    232  1.1  mrg 	else
    233  1.1  mrg # endif
    234  1.1  mrg 	{
    235  1.1  mrg 		newpp->p_flying = -1;
    236  1.1  mrg 		newpp->p_face = rand_dir();
    237  1.1  mrg 	}
    238  1.1  mrg 	newpp->p_damage = 0;
    239  1.1  mrg 	newpp->p_damcap = MAXDAM;
    240  1.1  mrg 	newpp->p_nchar = 0;
    241  1.1  mrg 	newpp->p_ncount = 0;
    242  1.1  mrg 	newpp->p_nexec = 0;
    243  1.1  mrg 	newpp->p_ammo = ISHOTS;
    244  1.1  mrg # ifdef BOOTS
    245  1.1  mrg 	newpp->p_nboots = 0;
    246  1.1  mrg # endif
    247  1.1  mrg 	if (enter_status == Q_SCAN) {
    248  1.1  mrg 		newpp->p_scan = SCANLEN;
    249  1.1  mrg 		newpp->p_cloak = 0;
    250  1.1  mrg 	}
    251  1.1  mrg 	else {
    252  1.1  mrg 		newpp->p_scan = 0;
    253  1.1  mrg 		newpp->p_cloak = CLOAKLEN;
    254  1.1  mrg 	}
    255  1.1  mrg 	newpp->p_ncshot = 0;
    256  1.1  mrg 
    257  1.1  mrg 	do {
    258  1.1  mrg 		x = rand_num(WIDTH - 1) + 1;
    259  1.1  mrg 		y = rand_num(HEIGHT - 1) + 1;
    260  1.1  mrg 	} while (Maze[y][x] != SPACE);
    261  1.1  mrg 	Maze[y][x] = GMINE;
    262  1.1  mrg # ifdef MONITOR
    263  1.1  mrg 	for (pp = Monitor; pp < End_monitor; pp++)
    264  1.1  mrg 		check(pp, y, x);
    265  1.1  mrg # endif
    266  1.1  mrg 
    267  1.1  mrg 	do {
    268  1.1  mrg 		x = rand_num(WIDTH - 1) + 1;
    269  1.1  mrg 		y = rand_num(HEIGHT - 1) + 1;
    270  1.1  mrg 	} while (Maze[y][x] != SPACE);
    271  1.1  mrg 	Maze[y][x] = MINE;
    272  1.1  mrg # ifdef MONITOR
    273  1.1  mrg 	for (pp = Monitor; pp < End_monitor; pp++)
    274  1.1  mrg 		check(pp, y, x);
    275  1.1  mrg # endif
    276  1.1  mrg 
    277  1.1  mrg 	(void) sprintf(Buf, "%5.2f%c%-10.10s %c", newpp->p_ident->i_score,
    278  1.1  mrg 		stat_char(newpp), newpp->p_ident->i_name,
    279  1.1  mrg 		newpp->p_ident->i_team);
    280  1.1  mrg 	y = STAT_PLAY_ROW + 1 + (newpp - Player);
    281  1.1  mrg 	for (pp = Player; pp < End_player; pp++) {
    282  1.1  mrg 		if (pp != newpp) {
    283  1.1  mrg 			char	smallbuf[10];
    284  1.1  mrg 
    285  1.1  mrg 			pp->p_ammo += NSHOTS;
    286  1.1  mrg 			newpp->p_ammo += NSHOTS;
    287  1.1  mrg 			cgoto(pp, y, STAT_NAME_COL);
    288  1.1  mrg 			outstr(pp, Buf, STAT_NAME_LEN);
    289  1.1  mrg 			(void) sprintf(smallbuf, "%3d", pp->p_ammo);
    290  1.1  mrg 			cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
    291  1.1  mrg 			outstr(pp, smallbuf, 3);
    292  1.1  mrg 		}
    293  1.1  mrg 	}
    294  1.1  mrg # ifdef MONITOR
    295  1.1  mrg 	for (pp = Monitor; pp < End_monitor; pp++) {
    296  1.1  mrg 		cgoto(pp, y, STAT_NAME_COL);
    297  1.1  mrg 		outstr(pp, Buf, STAT_NAME_LEN);
    298  1.1  mrg 	}
    299  1.1  mrg # endif
    300  1.1  mrg 
    301  1.1  mrg 	drawmaze(newpp);
    302  1.1  mrg 	drawplayer(newpp, TRUE);
    303  1.1  mrg 	look(newpp);
    304  1.1  mrg # ifdef	FLY
    305  1.1  mrg 	if (enter_status == Q_FLY)
    306  1.1  mrg 		/* Make sure that the position you enter in will be erased */
    307  1.1  mrg 		showexpl(newpp->p_y, newpp->p_x, FLYER);
    308  1.1  mrg # endif
    309  1.1  mrg 	sendcom(newpp, REFRESH);
    310  1.1  mrg 	sendcom(newpp, READY, 0);
    311  1.1  mrg 	(void) fflush(newpp->p_output);
    312  1.1  mrg }
    313  1.1  mrg 
    314  1.1  mrg /*
    315  1.1  mrg  * rand_dir:
    316  1.1  mrg  *	Return a random direction
    317  1.1  mrg  */
    318  1.1  mrg rand_dir()
    319  1.1  mrg {
    320  1.1  mrg 	switch (rand_num(4)) {
    321  1.1  mrg 	  case 0:
    322  1.1  mrg 		return LEFTS;
    323  1.1  mrg 	  case 1:
    324  1.1  mrg 		return RIGHT;
    325  1.1  mrg 	  case 2:
    326  1.1  mrg 		return BELOW;
    327  1.1  mrg 	  case 3:
    328  1.1  mrg 		return ABOVE;
    329  1.1  mrg 	}
    330  1.1  mrg 	/* NOTREACHED */
    331  1.1  mrg }
    332  1.1  mrg 
    333  1.1  mrg /*
    334  1.1  mrg  * get_ident:
    335  1.1  mrg  *	Get the score structure of a player
    336  1.1  mrg  */
    337  1.1  mrg IDENT *
    338  1.1  mrg get_ident(machine, uid, name, team)
    339  1.1  mrg u_long	machine;
    340  1.1  mrg u_long	uid;
    341  1.1  mrg char	*name;
    342  1.1  mrg char	team;
    343  1.1  mrg {
    344  1.1  mrg 	register IDENT	*ip;
    345  1.1  mrg 	static IDENT	punt;
    346  1.1  mrg 
    347  1.1  mrg 	for (ip = Scores; ip != NULL; ip = ip->i_next)
    348  1.1  mrg 		if (ip->i_machine == machine
    349  1.1  mrg 		&&  ip->i_uid == uid
    350  1.1  mrg 		&&  ip->i_team == team
    351  1.1  mrg 		&&  strncmp(ip->i_name, name, NAMELEN) == 0)
    352  1.1  mrg 			break;
    353  1.1  mrg 
    354  1.1  mrg 	if (ip != NULL) {
    355  1.1  mrg 		if (ip->i_entries < SCOREDECAY)
    356  1.1  mrg 			ip->i_entries++;
    357  1.1  mrg 		else
    358  1.1  mrg 			ip->i_kills = (ip->i_kills * (SCOREDECAY - 1))
    359  1.1  mrg 				/ SCOREDECAY;
    360  1.1  mrg 		ip->i_score = ip->i_kills / (double) ip->i_entries;
    361  1.1  mrg 	}
    362  1.1  mrg 	else {
    363  1.1  mrg 		ip = (IDENT *) malloc(sizeof (IDENT));
    364  1.1  mrg 		if (ip == NULL) {
    365  1.1  mrg 			/* Fourth down, time to punt */
    366  1.1  mrg 			ip = &punt;
    367  1.1  mrg 		}
    368  1.1  mrg 		ip->i_machine = machine;
    369  1.1  mrg 		ip->i_team = team;
    370  1.1  mrg 		ip->i_uid = uid;
    371  1.1  mrg 		strncpy(ip->i_name, name, NAMELEN);
    372  1.1  mrg 		ip->i_kills = 0;
    373  1.1  mrg 		ip->i_entries = 1;
    374  1.1  mrg 		ip->i_score = 0;
    375  1.1  mrg 		ip->i_absorbed = 0;
    376  1.1  mrg 		ip->i_faced = 0;
    377  1.1  mrg 		ip->i_shot = 0;
    378  1.1  mrg 		ip->i_robbed = 0;
    379  1.1  mrg 		ip->i_slime = 0;
    380  1.1  mrg 		ip->i_missed = 0;
    381  1.1  mrg 		ip->i_ducked = 0;
    382  1.1  mrg 		ip->i_gkills = ip->i_bkills = ip->i_deaths = 0;
    383  1.1  mrg 		ip->i_stillb = ip->i_saved = 0;
    384  1.1  mrg 		ip->i_next = Scores;
    385  1.1  mrg 		Scores = ip;
    386  1.1  mrg 	}
    387  1.1  mrg 
    388  1.1  mrg 	return ip;
    389  1.1  mrg }
    390