[comp.sources.games] v05i076: hunt2 - multi-player maze exploration

games@tekred.TEK.COM (10/19/88)

Submitted by: conrad@cgl.ucsf.edu
Comp.sources.games: Volume 5, Issue 76
Archive-name: hunt2/Part02



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 4)."
# Contents:  ctl.c driver.c execute.c hunt.6 playit.c
# Wrapped by billr@saab on Wed Oct 19 09:23:33 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ctl.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ctl.c'\"
else
echo shar: Extracting \"'ctl.c'\" \(1262 characters\)
sed "s/^X//" >'ctl.c' <<'END_OF_FILE'
X/*
X * Copyright (c) 1983 Regents of the University of California.
X * All rights reserved.  The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X */
X
X#include "bsd.h"
X
X#if	defined(TALK_43) || defined(TALK_42) 
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)ctl.c	5.2 (Berkeley) 3/13/86";
X#endif not lint
X
X/*
X * This file handles haggling with the various talk daemons to
X * get a socket to talk to. sockt is opened and connected in
X * the progress
X */
X
X#include "talk_ctl.h"
X
Xstruct	sockaddr_in daemon_addr = { AF_INET };
Xstruct	sockaddr_in ctl_addr = { AF_INET };
X
X	/* inet addresses of the two machines */
Xstruct	in_addr my_machine_addr;
Xstruct	in_addr his_machine_addr;
X
Xu_short daemon_port;	/* port number of the talk daemon */
X
Xint	ctl_sockt;
X
XCTL_MSG msg;
X
X/* open the ctl socket */
Xopen_ctl() 
X{
X	int length;
X
X	ctl_addr.sin_port = 0;
X	ctl_addr.sin_addr = my_machine_addr;
X	ctl_sockt = socket(AF_INET, SOCK_DGRAM, 0);
X	if (ctl_sockt <= 0)
X		p_error("Bad socket");
X	if (bind(ctl_sockt, &ctl_addr, sizeof(ctl_addr)) != 0)
X		p_error("Couldn't bind to control socket");
X	length = sizeof(ctl_addr);
X	if (getsockname(ctl_sockt, (struct sockaddr *) &ctl_addr, &length) < 0)
X		p_error("Bad address for ctl socket");
X}
X#endif
END_OF_FILE
if test 1262 -ne `wc -c <'ctl.c'`; then
    echo shar: \"'ctl.c'\" unpacked with wrong size!
fi
# end of 'ctl.c'
fi
if test -f 'driver.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'driver.c'\"
else
echo shar: Extracting \"'driver.c'\" \(18735 characters\)
sed "s/^X//" >'driver.c' <<'END_OF_FILE'
X/*
X *  Hunt
X *  Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
X *  San Francisco, California
X *
X *  Copyright (c) 1985 Regents of the University of California.
X *  All rights reserved.  The Berkeley software License Agreement
X *  specifies the terms and conditions for redistribution.
X */
X
X# include	"hunt.h"
X# include	<signal.h>
X# include	<errno.h>
X# include	<sys/ioctl.h>
X# ifndef HPUX
X# include	<sys/time.h>
X# else
X# include	<time.h>
X# endif
X
X# ifndef pdp11
X# define	RN	(((Seed = Seed * 11109 + 13849) >> 16) & 0xffff)
X# else pdp11
X# define	RN	((Seed = Seed * 11109 + 13849) & 0x7fff)
X# endif pdp11
X
Xint	Seed = 0;
X
X
XSOCKET	Daemon;
Xchar	*First_arg;		/* pointer to argv[0] */
Xchar	*Last_arg;		/* pointer to end of argv/environ */
X# ifdef	INTERNET
Xint	Test_socket;		/* test socket to answer datagrams */
XFLAG	inetd_spawned;		/* invoked via inetd */
XFLAG	standard_port = TRUE;	/* true if listening on standard port */
Xu_short	sock_port;		/* port # of tcp listen socket */
X# define	DAEMON_SIZE	(sizeof Daemon)
X# else INTERNET
X# define	DAEMON_SIZE	(sizeof Daemon - 1)
X# endif	INTERNET
X
X/*
X * main:
X *	The main program.
X */
Xmain(ac, av, ep)
Xint	ac;
Xchar	**av, **ep;
X{
X	register PLAYER	*pp;
X	register int	had_char;
X# ifdef INTERNET
X	register long	test_mask;
X	u_short		msg;
X	short		port_num, reply;
X	int		namelen;
X	SOCKET		test;
X# endif INTERNET
X	static long	read_fds;
X	static FLAG	first = TRUE;
X	static FLAG	server = FALSE;
X	extern int	optind;
X	extern char	*optarg;
X	int		c;
X	static struct timeval	linger = {	90, 0	};
X
X	First_arg = av[0];
X	if (ep == NULL || *ep == NULL)
X		ep = av + ac;
X	while (*ep)
X		ep++;
X	Last_arg = ep[-1] + strlen(ep[-1]);
X
X	while ((c = getopt(ac, av, "sp:")) != EOF) {
X		switch (c) {
X		  case 's':
X			server = TRUE;
X			break;
X		  case 'p':
X			standard_port = FALSE;
X			Test_port = atoi(optarg);
X			break;
X		  default:
Xerred:
X			fprintf(stderr, "Usage: %s [-s] [-p port]\n", av[0]);
X			exit(1);
X		}
X	}
X	if (optind < ac)
X		goto erred;
X
X	init();
X	Sock_mask = (1 << Socket);
X# ifdef INTERNET
X	test_mask = (1 << Test_socket);
X# endif INTERNET
X
X
Xagain:
X	do {
X		read_fds = Fds_mask;
X		errno = 0;
X		while (select(Num_fds, &read_fds, (int *) NULL,
X		    (int *) NULL, (struct timeval *) NULL) < 0)
X		{
X			if (errno != EINTR)
X# ifdef LOG
X				syslog(LOG_WARNING, "select: %m");
X# else LOG
X				perror("select");
X# endif LOG
X			errno = 0;
X		}
X		Have_inp = read_fds;
X# ifdef INTERNET
X		if (read_fds & test_mask) {
X			namelen = DAEMON_SIZE;
X			port_num = htons(sock_port);
X			(void) recvfrom(Test_socket, (char *) &msg, sizeof msg,
X				0, (struct sockaddr *) &test, &namelen);
X			msg = ntohs(msg);
X			if (msg == C_MESSAGE)
X				reply = htons((u_short) Nplayer);
X			else
X				reply = port_num;
X			if (msg == C_PLAYER || Nplayer > 0)
X				(void) sendto(Test_socket, (char *) &reply,
X					sizeof reply, 0,
X					(struct sockaddr *) &test, DAEMON_SIZE);
X		}
X# endif INTERNET
X		for (;;) {
X			had_char = FALSE;
X			for (pp = Player; pp < End_player; pp++)
X				if (havechar(pp)) {
X					execute(pp);
X					pp->p_nexec++;
X					had_char++;
X				}
X# ifdef MONITOR
X			for (pp = Monitor; pp < End_monitor; pp++)
X				if (havechar(pp)) {
X					mon_execute(pp);
X					pp->p_nexec++;
X					had_char++;
X				}
X# endif MONITOR
X			if (!had_char)
X				break;
X			moveshots();
X			for (pp = Player; pp < End_player; )
X				if (pp->p_death[0] != '\0')
X					zap(pp, TRUE);
X				else
X					pp++;
X# ifdef MONITOR
X			for (pp = Monitor; pp < End_monitor; )
X				if (pp->p_death[0] != '\0')
X					zap(pp, FALSE);
X				else
X					pp++;
X# endif MONITOR
X		}
X		if (read_fds & Sock_mask)
X			if (answer()) {
X				if (first && standard_port)
X					faketalk();
X				first = FALSE;
X			}
X		for (pp = Player; pp < End_player; pp++) {
X			if (read_fds & pp->p_mask)
X				sendcom(pp, READY, pp->p_nexec);
X			pp->p_nexec = 0;
X			(void) fflush(pp->p_output);
X		}
X# ifdef MONITOR
X		for (pp = Monitor; pp < End_monitor; pp++) {
X			if (read_fds & pp->p_mask)
X				sendcom(pp, READY, pp->p_nexec);
X			pp->p_nexec = 0;
X			(void) fflush(pp->p_output);
X		}
X# endif MONITOR
X	} while (Nplayer > 0);
X
X	read_fds = Fds_mask;
X	if (select(Num_fds, &read_fds, (int *) NULL, (int *) NULL,
X		   &linger) > 0) {
X		goto again;
X	}
X	if (server) {
X		clear_scores();
X		makemaze();
X		clearwalls();
X# ifdef BOOTS
X		makeboots();
X# endif BOOTS
X		first = TRUE;
X		goto again;
X	}
X
X# ifdef MONITOR
X	for (pp = Monitor; pp < End_monitor; )
X		zap(pp, FALSE);
X# endif MONITOR
X	cleanup(0);
X}
X
X/*
X * init:
X *	Initialize the global parameters.
X */
Xinit()
X{
X	register int	i;
X# ifdef	INTERNET
X	auto SOCKET	test_port;
X	auto int	msg;
X	auto int	len;
X# endif	INTERNET
X
X# ifndef DEBUG
X# ifdef TIOCNOTTY
X	(void) ioctl(fileno(stdout), TIOCNOTTY, NULL);
X# endif
X	(void) setpgrp(getpid(), getpid());
X	(void) signal(SIGHUP, SIG_IGN);
X	(void) signal(SIGINT, SIG_IGN);
X	(void) signal(SIGQUIT, SIG_IGN);
X	(void) signal(SIGTERM, cleanup);
X# endif DEBUG
X
X	(void) chdir("/usr/tmp");	/* just in case it core dumps */
X	(void) umask(0);		/* No privacy at all! */
X	(void) signal(SIGPIPE, SIG_IGN);
X
X# ifdef LOG
X# ifdef	SYSLOG_43
X	openlog("HUNT", LOG_PID, LOG_DAEMON);
X# endif
X# ifdef	SYSLOG_42
X	openlog("HUNT", LOG_PID);
X# endif
X# endif
X
X# ifdef	INTERNET
X	Daemon.sin_family = SOCK_FAMILY;
X	Daemon.sin_addr.s_addr = INADDR_ANY;
X	Daemon.sin_port = 0;
X# else INTERNET
X	Daemon.sun_family = SOCK_FAMILY;
X	(void) strcpy(Daemon.sun_path, Sock_name);
X# endif INTERNET
X
X	Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0);
X# if defined(INTERNET)
X	msg = 1;
X	if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, &msg, sizeof msg)<0)
X# ifdef LOG
X		syslog(LOG_WARNING, "setsockopt loopback %m");
X# else LOG
X		perror("setsockopt loopback");
X# endif LOG
X# endif INTERNET
X	if (bind(Socket, (struct sockaddr *) &Daemon, DAEMON_SIZE) < 0) {
X		if (errno == EADDRINUSE)
X			exit(0);
X		else {
X# ifdef LOG
X			syslog(LOG_ERR, "bind: %m");
X# else LOG
X			perror("bind");
X# endif LOG
X			cleanup(1);
X		}
X	}
X	(void) listen(Socket, 5);
X
X# ifdef INTERNET
X	len = sizeof (SOCKET);
X	if (getsockname(Socket, (struct sockaddr *) &Daemon, &len) < 0)  {
X# ifdef LOG
X		syslog(LOG_ERR, "getsockname: %m");
X# else LOG
X		perror("getsockname");
X# endif LOG
X		exit(1);
X	}
X	sock_port = ntohs(Daemon.sin_port);
X# endif INTERNET
X	Fds_mask = (1 << Socket);
X	Num_fds = Socket + 1;
X
X# ifdef INTERNET
X	len = sizeof (SOCKET);
X	if (getsockname(0, (struct sockaddr *) &test_port, &len) >= 0
X	&& test_port.sin_family == AF_INET) {
X		inetd_spawned = TRUE;
X		Test_socket = 0;
X		if (test_port.sin_port != htons((u_short) Test_port)) {
X			standard_port = FALSE;
X			Test_port = ntohs(test_port.sin_port);
X		}
X	} else {
X		test_port = Daemon;
X		test_port.sin_port = htons((u_short) Test_port);
X
X		Test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0);
X		if (bind(Test_socket, (struct sockaddr *) &test_port,
X		    DAEMON_SIZE) < 0) {
X# ifdef LOG
X			syslog(LOG_ERR, "bind: %m");
X# else LOG
X			perror("bind");
X# endif LOG
X			exit(1);
X		}
X		(void) listen(Test_socket, 5);
X	}
X
X	Fds_mask |= (1 << Test_socket);
X	if (Test_socket > Socket)
X		Num_fds = Test_socket + 1;
X# endif	INTERNET
X
X	Seed = getpid() + time((time_t *) NULL);
X	makemaze();
X# ifdef BOOTS
X	makeboots();
X# endif BOOTS
X
X	for (i = 0; i < NASCII; i++)
X		See_over[i] = TRUE;
X	See_over[DOOR] = FALSE;
X	See_over[WALL1] = FALSE;
X	See_over[WALL2] = FALSE;
X	See_over[WALL3] = FALSE;
X# ifdef REFLECT
X	See_over[WALL4] = FALSE;
X	See_over[WALL5] = FALSE;
X# endif REFLECT
X
X}
X
X# ifdef BOOTS
X/*
X * makeboots:
X *	Put the boots in the maze
X */
Xmakeboots()
X{
X	register int	x, y;
X	register PLAYER	*pp;
X
X	do {
X		x = rand_num(WIDTH - 1) + 1;
X		y = rand_num(HEIGHT - 1) + 1;
X	} while (Maze[y][x] != SPACE);
X	Maze[y][x] = BOOT_PAIR;
X	for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
X		pp->p_flying = -1;
X}
X# endif
X
X
X/*
X * checkdam:
X *	Check the damage to the given player, and see if s/he is killed
X */
Xcheckdam(ouch, gotcha, credit, amt, shot_type)
Xregister PLAYER	*ouch, *gotcha;
Xregister IDENT	*credit;
Xint		amt;
Xchar		shot_type;
X{
X	register char	*cp;
X
X	if (ouch->p_death[0] != '\0')
X		return;
X# ifdef BOOTS
X	if (shot_type == SLIME)
X		switch (ouch->p_nboots) {
X		  default:
X			break;
X		  case 1:
X			amt = (amt + 1) / 2;
X			break;
X		  case 2:
X			if (gotcha != NULL)
X				message(gotcha, "He has boots on!");
X			return;
X		}
X# endif
X	ouch->p_damage += amt;
X	if (ouch->p_damage <= ouch->p_damcap) {
X		(void) sprintf(Buf, "%2d", ouch->p_damage);
X		cgoto(ouch, STAT_DAM_ROW, STAT_VALUE_COL);
X		outstr(ouch, Buf, 2);
X		return;
X	}
X
X	/* Someone DIED */
X	switch (shot_type) {
X	  default:
X		cp = "Killed";
X		break;
X# ifdef FLY
X	  case FALL:
X		cp = "Killed on impact";
X		break;
X# endif FLY
X	  case KNIFE:
X		cp = "Stabbed to death";
X		ouch->p_ammo = 0;		/* No exploding */
X		break;
X	  case SHOT:
X		cp = "Shot to death";
X		break;
X	  case GRENADE:
X	  case SATCHEL:
X	  case BOMB:
X		cp = "Bombed";
X		break;
X	  case MINE:
X	  case GMINE:
X		cp = "Blown apart";
X		break;
X# ifdef	OOZE
X	  case SLIME:
X		cp = "Slimed";
X		if (credit != NULL)
X			credit->i_slime++;
X		break;
X# endif OOZE
X# ifdef	VOLCANO
X	  case LAVA:
X		cp = "Baked";
X		break;
X# endif VOLCANO
X# ifdef DRONE
X	  case DSHOT:
X		cp = "Eliminated";
X		break;
X# endif DRONE
X	}
X	if (credit == NULL) {
X		(void) sprintf(ouch->p_death, "| %s by %s |", cp,
X			(shot_type == MINE || shot_type == GMINE) ?
X			"a mine" : "act of God");
X		return;
X	}
X
X	(void) sprintf(ouch->p_death, "| %s by %s |", cp, credit->i_name);
X
X	if (ouch == gotcha) {		/* No use killing yourself */
X		credit->i_kills--;
X		credit->i_bkills++;
X	}
X	else if (ouch->p_ident->i_team == ' '
X	|| ouch->p_ident->i_team != credit->i_team) {
X		credit->i_kills++;
X		credit->i_gkills++;
X	}
X	else {
X		credit->i_kills--;
X		credit->i_bkills++;
X	}
X	credit->i_score = credit->i_kills / (double) credit->i_entries;
X	ouch->p_ident->i_deaths++;
X	if (ouch->p_nchar == 0)
X		ouch->p_ident->i_stillb++;
X	if (gotcha == NULL)
X		return;
X	gotcha->p_damcap += STABDAM;
X	gotcha->p_damage -= STABDAM;
X	if (gotcha->p_damage < 0)
X		gotcha->p_damage = 0;
X	(void) sprintf(Buf, "%2d/%2d", gotcha->p_damage, gotcha->p_damcap);
X	cgoto(gotcha, STAT_DAM_ROW, STAT_VALUE_COL);
X	outstr(gotcha, Buf, 5);
X	(void) sprintf(Buf, "%3d", (gotcha->p_damcap - MAXDAM) / 2);
X	cgoto(gotcha, STAT_KILL_ROW, STAT_VALUE_COL);
X	outstr(gotcha, Buf, 3);
X	(void) sprintf(Buf, "%5.2f", gotcha->p_ident->i_score);
X	for (ouch = Player; ouch < End_player; ouch++) {
X		cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player),
X			STAT_NAME_COL);
X		outstr(ouch, Buf, 5);
X	}
X# ifdef MONITOR
X	for (ouch = Monitor; ouch < End_monitor; ouch++) {
X		cgoto(ouch, STAT_PLAY_ROW + 1 + (gotcha - Player),
X			STAT_NAME_COL);
X		outstr(ouch, Buf, 5);
X	}
X# endif MONITOR
X}
X
X/*
X * zap:
X *	Kill off a player and take him out of the game.
X */
Xzap(pp, was_player)
Xregister PLAYER	*pp;
XFLAG		was_player;
X{
X	register int	i, len;
X	register BULLET	*bp;
X	register PLAYER	*np;
X	register int	x, y;
X	int		savefd, savemask;
X
X	if (was_player) {
X		if (pp->p_undershot)
X			fixshots(pp->p_y, pp->p_x, pp->p_over);
X		drawplayer(pp, FALSE);
X		Nplayer--;
X	}
X
X	len = strlen(pp->p_death);	/* Display the cause of death */
X	x = (WIDTH - len) / 2;
X	cgoto(pp, HEIGHT / 2, x);
X	outstr(pp, pp->p_death, len);
X	for (i = 1; i < len; i++)
X		pp->p_death[i] = '-';
X	pp->p_death[0] = '+';
X	pp->p_death[len - 1] = '+';
X	cgoto(pp, HEIGHT / 2 - 1, x);
X	outstr(pp, pp->p_death, len);
X	cgoto(pp, HEIGHT / 2 + 1, x);
X	outstr(pp, pp->p_death, len);
X	cgoto(pp, HEIGHT, 0);
X
X	savefd = pp->p_fd;
X	savemask = pp->p_mask;
X
X# ifdef MONITOR
X	if (was_player) {
X# endif MONITOR
X		dump_stats();
X		for (bp = Bullets; bp != NULL; bp = bp->b_next) {
X			if (bp->b_owner == pp)
X				bp->b_owner = NULL;
X			if (bp->b_x == pp->p_x && bp->b_y == pp->p_y)
X				bp->b_over = SPACE;
X		}
X
X		i = rand_num(pp->p_ammo);
X		x = rand_num(pp->p_ammo);
X		if (x > i)
X			i = x;
X		if (pp->p_ammo == 0)
X			x = 0;
X		else if (i == pp->p_ammo - 1) {
X			x = pp->p_ammo;
X			len = SLIME;
X		}
X		else {
X			for (x = MAXBOMB - 1; x > 0; x--)
X				if (i >= shot_req[x])
X					break;
X			for (y = MAXSLIME - 1; y > 0; y--)
X				if (i >= slime_req[y])
X					break;
X			if (y >= 0 && slime_req[y] > shot_req[x]) {
X				x = slime_req[y];
X				len = SLIME;
X			}
X			else if (x != 0) {
X				len = shot_type[x];
X				x = shot_req[x];
X			}
X		}
X		if (x > 0) {
X			(void) add_shot(len, pp->p_y, pp->p_x, pp->p_face, x,
X				(PLAYER *) NULL, TRUE, SPACE);
X			(void) sprintf(Buf, "%s detonated.",
X				pp->p_ident->i_name);
X			for (np = Player; np < End_player; np++)
X				message(np, Buf);
X# ifdef MONITOR
X			for (np = Monitor; np < End_monitor; np++)
X				message(np, Buf);
X# endif MONITOR
X# ifdef BOOTS
X			while (pp->p_nboots-- > 0) {
X				for (np = Boot; np < &Boot[NBOOTS]; np++)
X					if (np->p_flying < 0)
X						break;
X				if (np >= &Boot[NBOOTS])
X					abort(1, "Too many boots");
X				np->p_undershot = FALSE;
X				np->p_x = pp->p_x;
X				np->p_y = pp->p_y;
X				np->p_flying = rand_num(20);
X				np->p_flyx = 2 * rand_num(6) - 5;
X				np->p_flyy = 2 * rand_num(6) - 5;
X				np->p_over = SPACE;
X				np->p_face = BOOT;
X				showexpl(np->p_y, np->p_x, BOOT);
X			}
X# endif BOOTS
X		}
X# ifdef BOOTS
X		else if (pp->p_nboots > 0) {
X			if (pp->p_nboots == 2)
X				Maze[pp->p_y][pp->p_x] = BOOT_PAIR;
X			else
X				Maze[pp->p_y][pp->p_x] = BOOT;
X			if (pp->p_undershot)
X				fixshots(pp->p_y, pp->p_x,
X					Maze[pp->p_y][pp->p_x]);
X		}
X# endif BOOTS
X
X# ifdef VOLCANO
X		volcano += pp->p_ammo - x;
X		if (rand_num(100) < volcano / 50) {
X			do {
X				x = rand_num(WIDTH / 2) + WIDTH / 4;
X				y = rand_num(HEIGHT / 2) + HEIGHT / 4;
X			} while (Maze[y][x] != SPACE);
X			(void) add_shot(LAVA, y, x, LEFTS, volcano,
X				(PLAYER *) NULL, TRUE, SPACE);
X			for (np = Player; np < End_player; np++)
X				message(np, "Volcano eruption.");
X			volcano = 0;
X		}
X# endif VOLCANO
X
X# ifdef	DRONE
X		if (rand_num(100) < 2) {
X			do {
X				x = rand_num(WIDTH / 2) + WIDTH / 4;
X				y = rand_num(HEIGHT / 2) + HEIGHT / 4;
X			} while (Maze[y][x] != SPACE);
X			add_shot(DSHOT, y, x, rand_dir(),
X				shot_req[MINDSHOT +
X				rand_num(MAXBOMB - MINDSHOT)],
X				(PLAYER *) NULL, FALSE, SPACE);
X		}
X# endif	DRONE
X
X		sendcom(pp, ENDWIN);
X		(void) fclose(pp->p_output);
X
X		End_player--;
X		if (pp != End_player) {
X			bcopy((char *) End_player, (char *) pp,
X				sizeof (PLAYER));
X			(void) sprintf(Buf, "%5.2f%c%-10.10s %c",
X				pp->p_ident->i_score, stat_char(pp),
X				pp->p_ident->i_name, pp->p_ident->i_team);
X			i = STAT_PLAY_ROW + 1 + (pp - Player);
X			for (np = Player; np < End_player; np++) {
X				cgoto(np, i, STAT_NAME_COL);
X				outstr(np, Buf, STAT_NAME_LEN);
X			}
X# ifdef MONITOR
X			for (np = Monitor; np < End_monitor; np++) {
X				cgoto(np, i, STAT_NAME_COL);
X				outstr(np, Buf, STAT_NAME_LEN);
X			}
X# endif MONITOR
X		}
X
X		/* Erase the last player */
X		i = STAT_PLAY_ROW + 1 + Nplayer;
X		for (np = Player; np < End_player; np++) {
X			cgoto(np, i, STAT_NAME_COL);
X			ce(np);
X		}
X# ifdef MONITOR
X		for (np = Monitor; np < End_monitor; np++) {
X			cgoto(np, i, STAT_NAME_COL);
X			ce(np);
X		}
X	}
X	else {
X		sendcom(pp, ENDWIN);
X		(void) putc(LAST_PLAYER, pp->p_output);
X		(void) fclose(pp->p_output);
X
X		End_monitor--;
X		if (pp != End_monitor) {
X			bcopy((char *) End_monitor, (char *) pp,
X				sizeof (PLAYER));
X			(void) sprintf(Buf, "%5.5s %-10.10s %c", " ",
X				pp->p_ident->i_name, pp->p_ident->i_team);
X			i = STAT_MON_ROW + 1 + (pp - Player);
X			for (np = Player; np < End_player; np++) {
X				cgoto(np, i, STAT_NAME_COL);
X				outstr(np, Buf, STAT_NAME_LEN);
X			}
X			for (np = Monitor; np < End_monitor; np++) {
X				cgoto(np, i, STAT_NAME_COL);
X				outstr(np, Buf, STAT_NAME_LEN);
X			}
X		}
X
X		/* Erase the last monitor */
X		i = STAT_MON_ROW + 1 + (End_monitor - Monitor);
X		for (np = Player; np < End_player; np++) {
X			cgoto(np, i, STAT_NAME_COL);
X			ce(np);
X		}
X		for (np = Monitor; np < End_monitor; np++) {
X			cgoto(np, i, STAT_NAME_COL);
X			ce(np);
X		}
X
X	}
X# endif MONITOR
X
X	Fds_mask &= ~savemask;
X	if (Num_fds == savefd + 1) {
X		Num_fds = Socket;
X# ifdef INTERNET
X		if (Test_socket > Socket)
X			Num_fds = Test_socket;
X# endif INTERNET
X		for (np = Player; np < End_player; np++)
X			if (np->p_fd > Num_fds)
X				Num_fds = np->p_fd;
X# ifdef MONITOR
X		for (np = Monitor; np < End_monitor; np++)
X			if (np->p_fd > Num_fds)
X				Num_fds = np->p_fd;
X# endif MONITOR
X		Num_fds++;
X	}
X}
X
X/*
X * rand_num:
X *	Return a random number in a given range.
X */
Xrand_num(range)
Xint	range;
X{
X	return (range == 0 ? 0 : RN % range);
X}
X
X/*
X * havechar:
X *	Check to see if we have any characters in the input queue; if
X *	we do, read them, stash them away, and return TRUE; else return
X *	FALSE.
X */
Xhavechar(pp)
Xregister PLAYER	*pp;
X{
X	extern int	errno;
X
X	if (pp->p_ncount < pp->p_nchar)
X		return TRUE;
X	if (!(Have_inp & pp->p_mask))
X		return FALSE;
X	Have_inp &= ~pp->p_mask;
Xcheck_again:
X	errno = 0;
X	if ((pp->p_nchar = read(pp->p_fd, pp->p_cbuf, sizeof pp->p_cbuf)) <= 0)
X	{
X		if (errno == EINTR)
X			goto check_again;
X		pp->p_cbuf[0] = 'q';
X	}
X	pp->p_ncount = 0;
X	return TRUE;
X}
X
X/*
X * cleanup:
X *	Exit with the given value, cleaning up any droppings lying around
X */
Xcleanup(eval)
Xint	eval;
X{
X	register PLAYER	*pp;
X
X	for (pp = Player; pp < End_player; pp++) {
X		cgoto(pp, HEIGHT, 0);
X		sendcom(pp, ENDWIN);
X		(void) putc(LAST_PLAYER, pp->p_output);
X		(void) fclose(pp->p_output);
X	}
X# ifdef MONITOR
X	for (pp = Monitor; pp < End_monitor; pp++) {
X		cgoto(pp, HEIGHT, 0);
X		sendcom(pp, ENDWIN);
X		(void) putc(LAST_PLAYER, pp->p_output);
X		(void) fclose(pp->p_output);
X	}
X# endif MONITOR
X	(void) close(Socket);
X# ifdef AF_UNIX_HACK
X	(void) unlink(Sock_name);
X# endif AF_UNIX_HACK
X
X	dump_stats();
X	exit(eval);
X}
X
X/*
X * dump_stats:
X *	Print absorption stats
X */
Xdump_stats()
X{
X	register IDENT	*ip;
X	register FILE	*fp;
X	extern char	*Stat_file;
X
X	if ((fp = fopen(Stat_file, "w")) != NULL) {
X		fputs("Name\t\tScore\tDucked\tAbsorb\tFaced\tShot\tRobbed\tMissed\tSlimeK\n", fp);
X		for (ip = Scores; ip != NULL; ip = ip->i_next) {
X			fprintf(fp, "%s\t", ip->i_name);
X			if (strlen(ip->i_name) < 8)
X				putc('\t', fp);
X			fprintf(fp, "%.2f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
X				ip->i_score, ip->i_ducked, ip->i_absorbed,
X				ip->i_faced, ip->i_shot, ip->i_robbed,
X				ip->i_missed, ip->i_slime);
X		}
X		fputs("\n\nName\t\tEnemy\tFriend\tDeaths\tStill\tSaved\n", fp);
X		for (ip = Scores; ip != NULL; ip = ip->i_next) {
X			if (ip->i_team == ' ') {
X				fprintf(fp, "%s\t", ip->i_name);
X				if (strlen(ip->i_name) < 8)
X					putc('\t', fp);
X			}
X			else {
X				fprintf(fp, "%s[%c]\t", ip->i_name, ip->i_team);
X				if (strlen(ip->i_name) + 3 < 8)
X					putc('\t', fp);
X			}
X			fprintf(fp, "%d\t%d\t%d\t%d\t%d\n",
X				ip->i_gkills, ip->i_bkills, ip->i_deaths,
X				ip->i_stillb, ip->i_saved);
X		}
X		(void) fclose(fp);
X	}
X}
X
X/*
X * clear_scores:
X *	Clear out the scores so the next session start clean
X */
Xclear_scores()
X{
X	register IDENT	*ip, *nextip;
X
X	for (ip = Scores; ip != NULL; ip = nextip) {
X		nextip = ip->i_next;
X		(void) free((char *) ip);
X	}
X	Scores = NULL;
X}
END_OF_FILE
if test 18735 -ne `wc -c <'driver.c'`; then
    echo shar: \"'driver.c'\" unpacked with wrong size!
fi
# end of 'driver.c'
fi
if test -f 'execute.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'execute.c'\"
else
echo shar: Extracting \"'execute.c'\" \(9940 characters\)
sed "s/^X//" >'execute.c' <<'END_OF_FILE'
X/*
X *  Hunt
X *  Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
X *  San Francisco, California
X *
X *  Copyright (c) 1985 Regents of the University of California.
X *  All rights reserved.  The Berkeley software License Agreement
X *  specifies the terms and conditions for redistribution.
X */
X
X# include	"hunt.h"
X
X# undef CTRL
X# define	CTRL(x)	('x' & 037)
X
X# ifdef MONITOR
X/*
X * mon_execute:
X *	Execute a single monitor command
X */
Xmon_execute(pp)
Xregister PLAYER	*pp;
X{
X	register char	ch;
X
X	ch = pp->p_cbuf[pp->p_ncount++];
X	switch (ch) {
X	  case CTRL(L):
X		sendcom(pp, REDRAW);
X		break;
X	  case 'q':
X		(void) strcpy(pp->p_death, "| Quit |");
X		break;
X	}
X}
X# endif MONITOR
X
X/*
X * execute:
X *	Execute a single command
X */
Xexecute(pp)
Xregister PLAYER	*pp;
X{
X	register char	ch;
X
X	ch = pp->p_cbuf[pp->p_ncount++];
X
X# ifdef	FLY
X	if (pp->p_flying >= 0) {
X		switch (ch) {
X		  case CTRL(L):
X			sendcom(pp, REDRAW);
X			break;
X		  case 'q':
X			(void) strcpy(pp->p_death, "| Quit |");
X			break;
X		}
X		return;
X	}
X# endif	FLY
X
X	switch (ch) {
X	  case CTRL(L):
X		sendcom(pp, REDRAW);
X		break;
X	  case 'h':
X		move(pp, LEFTS);
X		break;
X	  case 'H':
X		face(pp, LEFTS);
X		break;
X	  case 'j':
X		move(pp, BELOW);
X		break;
X	  case 'J':
X		face(pp, BELOW);
X		break;
X	  case 'k':
X		move(pp, ABOVE);
X		break;
X	  case 'K':
X		face(pp, ABOVE);
X		break;
X	  case 'l':
X		move(pp, RIGHT);
X		break;
X	  case 'L':
X		face(pp, RIGHT);
X		break;
X	  case 'f':
X	  case '1':
X		fire(pp, 0);		/* SHOT */
X		break;
X	  case 'g':
X	  case '2':
X		fire(pp, 1);		/* GRENADE */
X		break;
X	  case 'F':
X	  case '3':
X		fire(pp, 2);		/* SATCHEL */
X		break;
X	  case 'G':
X	  case '4':
X		fire(pp, 3);		/* 7x7 BOMB */
X		break;
X	  case '5':
X		fire(pp, 4);		/* 9x9 BOMB */
X		break;
X	  case '6':
X		fire(pp, 5);		/* 11x11 BOMB */
X		break;
X	  case '7':
X		fire(pp, 6);		/* 13x13 BOMB */
X		break;
X	  case '8':
X		fire(pp, 7);		/* 15x15 BOMB */
X		break;
X	  case '9':
X		fire(pp, 8);		/* 17x17 BOMB */
X		break;
X	  case '0':
X		fire(pp, 9);		/* 19x19 BOMB */
X		break;
X	  case '@':
X		fire(pp, 10);		/* 21x21 BOMB */
X		break;
X# ifdef	OOZE
X	  case 'o':
X		fire_slime(pp, 0);	/* SLIME */
X		break;
X	  case 'O':
X		fire_slime(pp, 1);	/* SSLIME */
X		break;
X	  case 'p':
X		fire_slime(pp, 2);
X		break;
X	  case 'P':
X		fire_slime(pp, 3);
X		break;
X# endif	OOZE
X	  case 's':
X		scan(pp);
X		break;
X	  case 'c':
X		cloak(pp);
X		break;
X	  case 'q':
X		(void) strcpy(pp->p_death, "| Quit |");
X		break;
X	}
X}
X
X/*
X * move:
X *	Execute a move in the given direction
X */
Xmove(pp, dir)
Xregister PLAYER	*pp;
Xint		dir;
X{
X	register PLAYER	*newp;
X	register int	x, y;
X	register FLAG	moved;
X	register BULLET	*bp;
X
X	y = pp->p_y;
X	x = pp->p_x;
X
X	switch (dir) {
X	  case LEFTS:
X		x--;
X		break;
X	  case RIGHT:
X		x++;
X		break;
X	  case ABOVE:
X		y--;
X		break;
X	  case BELOW:
X		y++;
X		break;
X	}
X
X	moved = FALSE;
X	switch (Maze[y][x]) {
X	  case SPACE:
X# ifdef RANDOM
X	  case DOOR:
X# endif RANDOM
X		moved = TRUE;
X		break;
X	  case WALL1:
X	  case WALL2:
X	  case WALL3:
X# ifdef REFLECT
X	  case WALL4:
X	  case WALL5:
X# endif REFLECT
X		break;
X	  case MINE:
X	  case GMINE:
X		if (dir == pp->p_face)
X			pickup(pp, y, x, 2, Maze[y][x]);
X		else if (opposite(dir, pp->p_face))
X			pickup(pp, y, x, 95, Maze[y][x]);
X		else
X			pickup(pp, y, x, 50, Maze[y][x]);
X		Maze[y][x] = SPACE;
X		moved = TRUE;
X		break;
X	  case SHOT:
X	  case GRENADE:
X	  case SATCHEL:
X	  case BOMB:
X# ifdef OOZE
X	  case SLIME:
X# endif OOZE
X# ifdef DRONE
X	  case DSHOT:
X# endif DRONE
X		bp = is_bullet(y, x);
X		if (bp != NULL)
X			bp->b_expl = TRUE;
X		Maze[y][x] = SPACE;
X		moved = TRUE;
X		break;
X	  case LEFTS:
X	  case RIGHT:
X	  case ABOVE:
X	  case BELOW:
X		if (dir != pp->p_face)
X			sendcom(pp, BELL);
X		else {
X			newp = play_at(y, x);
X			checkdam(newp, pp, pp->p_ident, STABDAM, KNIFE);
X		}
X		break;
X# ifdef FLY
X	  case FLYER:
X		newp = play_at(y, x);
X		message(newp, "Oooh, there's a short guy waving at you!");
X		message(pp, "You couldn't quite reach him!");
X		break;
X# endif FLY
X# ifdef BOOTS
X	  case BOOT:
X	  case BOOT_PAIR:
X		if (Maze[y][x] == BOOT)
X			pp->p_nboots++;
X		else
X			pp->p_nboots += 2;
X		for (newp = Boot; newp < &Boot[NBOOTS]; newp++) {
X			if (newp->p_flying < 0)
X				continue;
X			if (newp->p_y == y && newp->p_x == x) {
X				newp->p_flying = -1;
X				if (newp->p_undershot)
X					fixshots(y, x, newp->p_over);
X			}
X		}
X		if (pp->p_nboots == 2)
X			message(pp, "Wow!  A pair of boots!");
X		else
X			message(pp, "You can hobble around on one boot.");
X		Maze[y][x] = SPACE;
X		moved = TRUE;
X		break;
X# endif BOOTS
X	}
X	if (moved) {
X		if (pp->p_ncshot > 0)
X			if (--pp->p_ncshot == MAXNCSHOT) {
X				cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
X				outstr(pp, " ok", 3);
X			}
X		if (pp->p_undershot) {
X			fixshots(pp->p_y, pp->p_x, pp->p_over);
X			pp->p_undershot = FALSE;
X		}
X		drawplayer(pp, FALSE);
X		pp->p_over = Maze[y][x];
X		pp->p_y = y;
X		pp->p_x = x;
X		drawplayer(pp, TRUE);
X	}
X}
X
X/*
X * face:
X *	Change the direction the player is facing
X */
Xface(pp, dir)
Xregister PLAYER	*pp;
Xregister int	dir;
X{
X	if (pp->p_face != dir) {
X		pp->p_face = dir;
X		drawplayer(pp, TRUE);
X	}
X}
X
X/*
X * fire:
X *	Fire a shot of the given type in the given direction
X */
Xfire(pp, req_index)
Xregister PLAYER	*pp;
Xregister int	req_index;
X{
X	if (pp == NULL)
X		return;
X# ifdef DEBUG
X	if (req_index < 0 || req_index >= MAXBOMB)
X		message(pp, "What you do?");
X# endif DEBUG
X	while (req_index >= 0 && pp->p_ammo < shot_req[req_index])
X		req_index--;
X	if (req_index < 0) {
X		message(pp, "Not enough charges.");
X		return;
X	}
X	if (pp->p_ncshot > MAXNCSHOT)
X		return;
X	if (pp->p_ncshot++ == MAXNCSHOT) {
X		cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
X		outstr(pp, "   ", 3);
X	}
X	pp->p_ammo -= shot_req[req_index];
X	(void) sprintf(Buf, "%3d", pp->p_ammo);
X	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
X	outstr(pp, Buf, 3);
X
X	add_shot(shot_type[req_index], pp->p_y, pp->p_x, pp->p_face,
X		shot_req[req_index], pp, FALSE, pp->p_face);
X	pp->p_undershot = TRUE;
X
X	/*
X	 * Show the object to everyone
X	 */
X	showexpl(pp->p_y, pp->p_x, shot_type[req_index]);
X	for (pp = Player; pp < End_player; pp++)
X		sendcom(pp, REFRESH);
X# ifdef MONITOR
X	for (pp = Monitor; pp < End_monitor; pp++)
X		sendcom(pp, REFRESH);
X# endif MONITOR
X}
X
X# ifdef	OOZE
X/*
X * fire_slime:
X *	Fire a slime shot in the given direction
X */
Xfire_slime(pp, req_index)
Xregister PLAYER	*pp;
Xregister int	req_index;
X{
X	if (pp == NULL)
X		return;
X# ifdef DEBUG
X	if (req_index < 0 || req_index >= MAXSLIME)
X		message(pp, "What you do?");
X# endif DEBUG
X	while (req_index >= 0 && pp->p_ammo < slime_req[req_index])
X		req_index--;
X	if (req_index < 0) {
X		message(pp, "Not enough charges.");
X		return;
X	}
X	if (pp->p_ncshot > MAXNCSHOT)
X		return;
X	if (pp->p_ncshot++ == MAXNCSHOT) {
X		cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
X		outstr(pp, "   ", 3);
X	}
X	pp->p_ammo -= slime_req[req_index];
X	(void) sprintf(Buf, "%3d", pp->p_ammo);
X	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
X	outstr(pp, Buf, 3);
X
X	add_shot(SLIME, pp->p_y, pp->p_x, pp->p_face,
X		slime_req[req_index] * SLIME_FACTOR, pp, FALSE, pp->p_face);
X	pp->p_undershot = TRUE;
X
X	/*
X	 * Show the object to everyone
X	 */
X	showexpl(pp->p_y, pp->p_x, SLIME);
X	for (pp = Player; pp < End_player; pp++)
X		sendcom(pp, REFRESH);
X# ifdef MONITOR
X	for (pp = Monitor; pp < End_monitor; pp++)
X		sendcom(pp, REFRESH);
X# endif MONITOR
X}
X# endif	OOZE
X
X/*
X * add_shot:
X *	Create a shot with the given properties
X */
Xadd_shot(type, y, x, face, charge, owner, expl, over)
Xint	type;
Xint	y, x;
Xchar	face;
Xint	charge;
XPLAYER	*owner;
Xint	expl;
Xchar	over;
X{
X	register BULLET	*bp;
X	register int	size;
X
X	switch (type) {
X	  case SHOT:
X	  case MINE:
X		size = 1;
X		break;
X	  case GRENADE:
X	  case GMINE:
X		size = 2;
X		break;
X	  case SATCHEL:
X		size = 3;
X		break;
X	  case BOMB:
X		for (size = 3; size < MAXBOMB; size++)
X			if (shot_req[size] >= charge)
X				break;
X		size++;
X		break;
X	  default:
X		size = 0;
X		break;
X	}
X
X	bp = create_shot(type, y, x, face, charge, size, owner,
X		(owner == NULL) ? NULL : owner->p_ident, expl, over);
X	bp->b_next = Bullets;
X	Bullets = bp;
X}
X
XBULLET *
Xcreate_shot(type, y, x, face, charge, size, owner, score, expl, over)
Xint	type;
Xint	y, x;
Xchar	face;
Xint	charge;
Xint	size;
XPLAYER	*owner;
XIDENT	*score;
Xint	expl;
Xchar	over;
X{
X	register BULLET	*bp;
X
X	bp = (BULLET *) malloc(sizeof (BULLET));	/* NOSTRICT */
X	if (bp == NULL) {
X		if (owner != NULL)
X			message(owner, "Out of memory");
X		return NULL;
X	}
X
X	bp->b_face = face;
X	bp->b_x = x;
X	bp->b_y = y;
X	bp->b_charge = charge;
X	bp->b_owner = owner;
X	bp->b_score = score;
X	bp->b_type = type;
X	bp->b_size = size;
X	bp->b_expl = expl;
X	bp->b_over = over;
X	bp->b_next = NULL;
X
X	return bp;
X}
X
X/*
X * cloak:
X *	Turn on or increase length of a cloak
X */
Xcloak(pp)
Xregister PLAYER	*pp;
X{
X	if (pp->p_ammo <= 0) {
X		message(pp, "No more charges");
X		return;
X	}
X# ifdef BOOTS
X	if (pp->p_nboots > 0) {
X		message(pp, "Boots are too noisy to cloak!");
X		return;
X	}
X# endif BOOTS
X	(void) sprintf(Buf, "%3d", --pp->p_ammo);
X	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
X	outstr(pp, Buf, 3);
X
X	pp->p_cloak += CLOAKLEN;
X
X	if (pp->p_scan >= 0)
X		pp->p_scan = -1;
X
X	showstat(pp);
X}
X
X/*
X * scan:
X *	Turn on or increase length of a scan
X */
Xscan(pp)
Xregister PLAYER	*pp;
X{
X	if (pp->p_ammo <= 0) {
X		message(pp, "No more charges");
X		return;
X	}
X	(void) sprintf(Buf, "%3d", --pp->p_ammo);
X	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
X	outstr(pp, Buf, 3);
X
X	pp->p_scan += SCANLEN;
X
X	if (pp->p_cloak >= 0)
X		pp->p_cloak = -1;
X
X	showstat(pp);
X}
X
X/*
X * pickup:
X *	check whether the object blew up or whether he picked it up
X */
Xpickup(pp, y, x, prob, obj)
Xregister PLAYER	*pp;
Xregister int	y, x;
Xint		prob;
Xint		obj;
X{
X	register int	req;
X
X	switch (obj) {
X	  case MINE:
X		req = BULREQ;
X		break;
X	  case GMINE:
X		req = GRENREQ;
X		break;
X	  default:
X		abort();
X	}
X	if (rand_num(100) < prob)
X		add_shot(obj, y, x, LEFTS, req, (PLAYER *) NULL,
X			TRUE, pp->p_face);
X	else {
X		pp->p_ammo += req;
X		(void) sprintf(Buf, "%3d", pp->p_ammo);
X		cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
X		outstr(pp, Buf, 3);
X	}
X}
END_OF_FILE
if test 9940 -ne `wc -c <'execute.c'`; then
    echo shar: \"'execute.c'\" unpacked with wrong size!
fi
# end of 'execute.c'
fi
if test -f 'hunt.6' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hunt.6'\"
else
echo shar: Extracting \"'hunt.6'\" \(10501 characters\)
sed "s/^X//" >'hunt.6' <<'END_OF_FILE'
X.\"  hunt
X.\"  Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
X.\"  San Francisco, California
X.\"
X.\"  Copyright (c) 1985 Regents of the University of California.
X.\"  All rights reserved.  The Berkeley software License Agreement
X.\"  specifies the terms and conditions for redistribution.
X.\"
X.TH HUNT 6 "21 August 1986"
X.UC 4
X.SH NAME
Xhunt \- a multi-player multi-terminal game
X.SH SYNOPSIS
X\fB/usr/games/hunt\fP [ \fB\-qmcsfb\fP ] [ \fB\-n\fP name ] [ \fB\-t\fP team ] [ \fB\-p\fP port ] [ \fB\-w\fP message ] [ host ]
X.SH DESCRIPTION
XThe object of the game
X.I hunt
Xis to kill off the other players.
XThere are no rooms, no treasures, and no monsters.
XInstead, you wander around a maze, find grenades, trip mines, and shoot down
Xwalls and players.
XThe more players you kill before you die, the better your score is.
XIf the
X.B \-m
Xflag is given,
Xyou enter the game as a monitor
X(you can see the action but you cannot play).
X.PP
X.I Hunt
Xnormally looks for an active game on the local network;
Xif none is found, it starts one up on the local host.
XThe location of the game may be specified by giving the
X.I host
Xargument.
XThis presupposes that a hunt game is already running on that host, see
X.IR huntd (6)
Xfor details on how to setup a game on a specific host.
X.PP
XIf the
X.B \-q
Xflag is given,
X.I hunt
Xqueries the local network (or specific host) and reports if an active game
Xis found.
XThis is useful for shell startup scripts, \fIe.g.\fP csh's .login.
X.PP
XThe player name may be specified on the command line by using the
X.B \-n
Xoption.
X.PP
XThe
X.BR \-c ,
X.BR \-s ,
Xand
X.B \-f
Xoptions are for entering the game cloaked, scanning, or flying respectively.
X.PP
XThe
X.B \-b
Xoption turns off beeping when you reach the typeahead limit.
X.PP
XThe
X.B \-t
Xoption aids team playing by making everyone else on one's team
Xappear as the team name.
XA team name is a single digit to avoid conflicting with other characters
Xused in the game.
X.PP
XThe
X.B \-p
X.I port
Xoption allows the rendezvous port number to be set.
XThis is a useful way for people playing on dialup lines to avoid playing
Xwith people on 9600 baud terminals.
X.PP
XThe
X.B \-w
X.I message
Xoption is the only way to send a message to everyone else's screen when
Xyou start up.
XIt is most often used to say ``eat slime death - NickD's coming in''.
X.PP
XWhen you die and are asked if you wish to re-enter the game,
Xthere are other answers than just yes or no.
XYou can also reply with a
X.B w
Xfor write a message before continuing or
X.B o
Xto change how you enter the game (cloaked, scanning, or flying).
X.PP
XTo be notified automatically when a
X.I hunt
Xstarts up, add your login to the
X.I hunt-players
Xmailing list (see
X.IR huntd (6)).
X.SH "PLAYING HINTS"
X.I Hunt
Xonly works on crt (vdt) terminals with at least 24 lines, 80 columns, and
Xcursor addressing.
XThe screen is divided in to 3 areas.
XOn the right hand side is the status area.
XIt shows damage sustained,
Xcharges remaining,
Xwho's in the game,
Xwho's scanning (the
X.B ``*''
Xin front of the name),
Xwho's cloaked (the
X.B ``+''
Xin front of the name),
Xand other players' scores.
XThe rest of the screen is taken up by your map of the maze.
XThe 24th line
Xis used for longer messages that don't fit in the status area.
X.PP
X.I Hunt
Xuses the same keys to move as
X.IR vi (1)
Xdoes,
X.IR i.e. ,
X.BR h ,
X.BR j ,
X.BR k ,
Xand
X.B l
Xfor left, down, up, right respectively.
XTo change which direction you're facing in the maze,
Xuse the upper case version of the movement key (\c
X.IR i.e. ,
X.BR HJKL ).
XYou can only fire or throw things in the direction you're facing.
X.TP
XOther commands are:
X.sp
X.nf
X.ta
X.ta \w'>\|<\|^\|v\ \ 'u
Xf or 1	\- Fire a bullet (Takes 1 charge)
Xg or 2	\- Throw grenade (Takes 9 charges)
XF or 3	\- Throw satchel charge (Takes 25 charges)
XG or 4	\- Throw bomb (Takes 49 charges)
X5	\- Throw big bomb (Takes 81 charges)
X6	\- Throw even bigger bomb (Takes 121 charges)
X7	\- Throw even more big bomb (Takes 169 charges)
X8	\- Throw even more bigger bomb (Takes 225 charges)
X9	\- Throw very big bomb (Takes 289 charges)
X0	\- Throw very, very big bomb (Takes 361 charges)
X@	\- Throw biggest bomb (Takes 441 charges)
Xo	\- Throw small slime (Takes 15 charges)
XO	\- Throw big slime (Takes 30 charges)
Xp	\- Throw bigger slime (Takes 45 charges)
XP	\- Throw biggest slime (Takes 60 charges)
Xs	\- Scan (show where other players are) (Takes 1 charge)
Xc	\- Cloak (hide from scanners) (Takes 1 charge)
X
X^L	\- Redraw screen
Xq	\- Quit
X.fi
X.TP
XThe symbols on the screen are:
X.sp
X.nf
X.ta
X.ta \w'>\|<\|^\|v\ \ 'u
X\-\||\|+	\- walls
X/\|\\	\- diagonal (deflecting) walls
X#	\- doors (dispersion walls)
X;	\- small mine
Xg	\- large mine
X:	\- bullet
Xo	\- grenade
XO	\- satchel charge
X@	\- bomb
Xs	\- small slime
X$	\- big slime
X>\|<\|^\|v	\- you facing right, left, up, or down
X}\|{\|i\|!	\- other players facing right, left, up, or down
X\(**	\- explosion
X.ne 3
X.cs R 24
X.cs I 24
X\fR\\|/\fP
X.cs R
X\fI\-\(**\-\fP	\- grenade and large mine explosion
X.fl
X.cs R 24
X\fR/|\\\fP
X.cs R
X.cs I
X.fi
X.LP
XOther helpful hints:
X.sp
X.ie n .ds b []
X.el .ds b \(bu
X.ta
X.ta \w'\*b\ \|'u
X.nr In \n(.i
X.de MP
X.br
X.in \n(Inu+\w'\*b\ \|'u
X.ti \n(Inu
X\*b	\c
X..
X.MP
XYou can only fire in the direction you are facing.
X.MP
XYou can only fire three shots in a row, then the gun must cool off.
X.MP
XShots move 5 times faster than you do.
X.MP
XTo stab someone,
Xyou face that player and move at them.
X.MP
XStabbing does 2 points worth of damage and shooting does 5 points.
X.MP
XSlime does 5 points of damage each time it hits.
X.MP
XYou start with 15 charges and get 5 more every time a player enters
Xor re-enters.
X.MP
XGrenade explosions cover a 3 by 3 area, each larger bomb cover a
Xcorrespondingly larger area (ranging from 5 by 5 to 21 by 21).
XAll explosions are centered around the square the shot hits and
Xdo the most damage in the center.
X.MP
XSlime affects all squares it oozes over.
XThe number of squares is equal to the number of charges used.
X.MP
XOne small mine and one large mine is placed in the maze for every new player.
XA mine has a 2% probability of tripping when you walk forward on to it;
X50% when going sideways;
X95% when backing up.
XTripping a mine costs you 5 points or 10 points respectively.
XDefusing a mine is worth 1 charge or 9 charges respectively.
X.MP
XYou cannot see behind you.
X.MP
XCloaking consumes 1 ammo charge per 20 of your moves.
X.MP
XScanning consumes 1 ammo charge per (20 \(mu the number of players)
Xof other player moves.
X.MP
XTurning on cloaking turns off scanning \(em turning on scanning turns off
Xcloaking.
X.MP
XWhen you kill someone,
Xyou get 2 more damage capacity points and 2 damage points get taken away.
X.MP
XMaximum typeahead is 5 characters.
X.MP
XA shot destroys normal (\c
X.IR i.e., 
Xnon-diagonal, non-door) walls.
X.MP
XDiagonal walls deflect shots and change orientation.
X.MP
XDoors disperse shots in random directions (up, down, left, right).
X.MP
XDiagonal walls and doors cannot be destroyed by direct shots but may
Xbe destroyed by an adjacent grenade explosion.
X.MP
XSlime goes around walls, not through them.
X.MP
XWalls regenerate, reappearing in the order they were destroyed.
XOne percent of the regenerated walls will be diagonal walls or doors.
XWhen a wall is generated directly beneath a player, he is thrown in
Xa random direction for a random period of time.  When he lands, he
Xsustains damage (up to 20 percent of the amount of damage already
Xsustained);
X.IR i.e. ,
Xthe less damage he had, the more nimble he is and
Xtherefore less likely to hurt himself on landing.
X.\"MP
X.\"There is a volcano close to the center of the maze which goes off
X.\"close to every 30 deaths.
X.MP
XEvery 30 deaths or so, a
X.B ``?''
Xwill appear.
XIt is a wandering bomb which will explode when it hits someone, or
Xwhen it is slimed.
X.MP
XIf no one moves, everything stands still.
X.MP
XThe environment variable
X.B HUNT
Xis checked to get the player name.
XIf you don't have this variable set,
X.I hunt
Xwill ask you what name you want to play under.
XIf you wish to set other options than just your name,
Xyou can enumerate the options as follows:
X.br
X.ti +1i
Xsetenv HUNT "name=Sneaky,team=1,cloak,mapkey=zoFfGg1f2g3F4G"
X.br
Xsets the player name to Sneaky,
Xsets the team to one,
Xsets the enter game attribute to cloaked,
Xand the maps \fBz\fP to \fBo\fP, \fBF\fP to \fBf\fP, \fBG\fP to \fBg\fP,
X\fB1\fP to \fBf\fP,
X\fB2\fP to \fBg\fP, \fB3\fP to \fBF\fP, and \fB4\fP to \fBG\fP.
XThe \fImapkey\fP option must be last.
XOther options are: scan, fly, nobeep, port=string, host=string,
Xand message=string \(em which correspond to the command line options.
XString options cannot contain commas since commas
Xare used to separate options.
X.MP
XIt's a boring game if you're the only one playing.
X.PP
XYour score is the decayed average of the ratio of number of kills to number
Xof times you entered the game and is only kept for the duration
Xof a single session of \fIhunt\fP.
X.PP
X.I Hunt
Xnormally drives up the load average to be approximately
X(number_of_players + 0.5) greater than it would be without a
X.I hunt 
Xgame executing.
X.SH STATISTICS
XThe
X.I hunt
Xserver keeps track of some game statististics in a file
X.IR /usr/tmp/hunt.stats .
XThe meaning of the column headings are as follows:
X.I score
X\(em the player's last score;
X.I ducked
X\(em
Xhow many shots a player ducked;
X.I absorb
X\(em how many shots a player absorbed;
X.I faced
X\(em how many shots were fired at player's face;
X.I shot
X\(em how many shots were fired at player;
X.I robbed
X\(em how many of player's shots were absorbed;
X.I missed
X\(em how many of player's shots were ducked;
X.I slimeK
X\(em how many slime kills player had;
X.I enemy
X\(em how many enemies were killed;
X.I friend
X\(em how many friends were killed (self and same team);
X.I deaths
X\(em how many times player died;
X.I still
X\(em how many times player died without typing in any commands;
X.I saved
X\(em how many times a shot/bomb would have killed player if he hadn't
Xducked or absorbed it.
X.SH FILES
X.nf
X.ta
X.ta \w'/usr/games/lib/huntd\ \ \ 'u
X/usr/games/lib/huntd	game coordinator
X/usr/tmp/hunt.stats	rudimentary game statistics
X.DT
X.fi
X.SH "SEE ALSO"
Xhuntd(6)
X.SH AUTHORS
XConrad Huang, Ken Arnold, and Greg Couch;
X.br
XUniversity of California, San Francisco, Computer Graphics Lab
X.SH ACKNOWLEDGEMENTS
XWe thank Don Kneller,
XJohn Thomason, Eric Pettersen, Mark Day,
Xand Scott Weiner for providing
Xendless hours of play-testing to improve the character of the game.
XWe hope their significant others will forgive them;
Xwe certainly don't.
X.SH BUGS
XTo keep up the pace, not everything is as realistic as possible.
END_OF_FILE
if test 10501 -ne `wc -c <'hunt.6'`; then
    echo shar: \"'hunt.6'\" unpacked with wrong size!
fi
# end of 'hunt.6'
fi
if test -f 'playit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'playit.c'\"
else
echo shar: Extracting \"'playit.c'\" \(10343 characters\)
sed "s/^X//" >'playit.c' <<'END_OF_FILE'
X/*
X *  Hunt
X *  Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
X *  San Francisco, California
X *
X *  Copyright (c) 1985 Regents of the University of California.
X *  All rights reserved.  The Berkeley software License Agreement
X *  specifies the terms and conditions for redistribution.
X */
X
X# include	<curses.h>
X# include	<ctype.h>
X# include	<signal.h>
X# include	<errno.h>
X# include	"hunt.h"
X# include	<sys/file.h>
X# ifdef TERMINFO
X# include	<term.h>
X
X# define	AM		auto_right_margin
X# define	XN		eat_newline_glitch
X# define	CL		clear_screen
X# define	CE		clr_eol
X# define	_putchar	_outchar
X# endif
X
Xint		input();
Xstatic int	nchar_send;
Xstatic int	in	= FREAD;
Xchar		screen[SCREEN_HEIGHT][SCREEN_WIDTH2], blanks[SCREEN_WIDTH];
Xint		cur_row, cur_col;
X# ifdef OTTO
Xint		Otto_count;
Xint		Otto_mode;
Xstatic int	otto_y, otto_x;
Xstatic char	otto_face;
X# endif OTTO
X
X# define	MAX_SEND	5
X
X/*
X * ibuf is the input buffer used for the stream from the driver.
X * It is small because we do not check for user input when there
X * are characters in the input buffer.
X */
Xstatic char	ibuf[20];
X
X#define	GETCHR(fd)	(--(fd)->_cnt < 0 ? getchr(fd) \
X				: *((unsigned char *) (fd)->_ptr++))
X
X/*
X * playit:
X *	Play a given game, handling all the curses commands from
X *	the driver.
X */
Xplayit()
X{
X	register FILE		*inf;
X	register int		ch;
X	register int		y, x;
X	extern int		errno;
X	extern int		_putchar();
X	long			version;
X
X	if (read(Socket, (char *) &version, LONGLEN) != LONGLEN) {
X		bad_con();
X		/* NOTREACHED */
X	}
X	if (ntohl(version) != HUNT_VERSION) {
X		bad_ver();
X		/* NOTREACHED */
X	}
X	errno = 0;
X	while ((inf = fdopen(Socket, "r")) == NULL)
X		if (errno == EINTR)
X			errno = 0;
X		else {
X			perror("fdopen of socket");
X			exit(1);
X		}
X# ifdef L_ctermid
X	setvbuf(inf, ibuf, _IOFBF, sizeof ibuf);
X# else
X	setbuffer(inf, ibuf, sizeof ibuf);
X# endif
X# ifdef OTTO
X	Otto_count = 0;
X# endif OTTO
X	nchar_send = MAX_SEND;
X	while ((ch = GETCHR(inf)) != EOF) {
X# ifdef DEBUG
X		fputc(ch, stderr);
X# endif DEBUG
X		switch (ch & 0377) {
X		  case MOVE:
X			y = GETCHR(inf);
X			x = GETCHR(inf);
X			mvcur(cur_row, cur_col, y, x);
X			cur_row = y;
X			cur_col = x;
X			break;
X		  case ADDCH:
X			ch = GETCHR(inf);
X# ifdef OTTO
X			switch (ch) {
X
X			case '<':
X			case '>':
X			case '^':
X			case 'v':
X				otto_face = ch;
X				otto_y = cur_row;
X				otto_x = cur_col;
X				break;
X			}
X# endif OTTO
X			put_ch(ch);
X			break;
X		  case CLRTOEOL:
X			clear_eol();
X			break;
X		  case CLEAR:
X			clear_the_screen();
X			break;
X		  case REFRESH:
X			fflush(stdout);
X			break;
X		  case REDRAW:
X			redraw_screen();
X			fflush(stdout);
X			break;
X		  case ENDWIN:
X			fflush(stdout);
X			if ((ch = GETCHR(inf)) == LAST_PLAYER)
X				Last_player = TRUE;
X			ch = EOF;
X			goto out;
X		  case BELL:
X			putchar(CTRL(G));
X			break;
X		  case READY:
X			(void) fflush(stdout);
X			if (nchar_send < 0)
X# ifndef TCFLSH
X				(void) ioctl(fileno(stdin), TIOCFLUSH, &in);
X# else
X				(void) ioctl(fileno(stdin), TCFLSH, 0);
X# endif
X			nchar_send = MAX_SEND;
X# ifndef OTTO
X			(void) GETCHR(inf);
X# else OTTO
X			Otto_count -= (GETCHR(inf) & 255);
X			if (!Am_monitor) {
X# ifdef DEBUG
X				fputc('0' + Otto_count, stderr);
X# endif DEBUG
X				if (Otto_count == 0 && Otto_mode)
X					otto(otto_y, otto_x, otto_face);
X			}
X# endif OTTO
X			break;
X		  default:
X# ifdef OTTO
X			switch (ch) {
X
X			case '<':
X			case '>':
X			case '^':
X			case 'v':
X				otto_face = ch;
X				otto_y = cur_row;
X				otto_x = cur_col;
X				break;
X			}
X# endif OTTO
X			put_ch(ch);
X			break;
X		}
X	}
Xout:
X	(void) fclose(inf);
X}
X
X/*
X * getchr:
X *	Grab input and pass it along to the driver
X *	Return any characters from the driver
X *	When this routine is called by GETCHR, we already know there are
X *	no characters in the input buffer.
X */
Xgetchr(fd)
Xregister FILE	*fd;
X{
X	long	readfds, s_readfds;
X	int	driver_mask, stdin_mask;
X	int	nfds, s_nfds;
X
X	driver_mask = 1L << fileno(fd);
X	stdin_mask = 1L << fileno(stdin);
X	s_readfds = driver_mask | stdin_mask;
X	s_nfds = (fileno(fd) > fileno(stdin)) ? fileno(fd) : fileno(stdin);
X	s_nfds++;
X
Xone_more_time:
X	do {
X		errno = 0;
X		readfds = s_readfds;
X		nfds = s_nfds;
X		nfds = select(nfds, &readfds, NULL, NULL, NULL);
X	} while (nfds <= 0 && errno == EINTR);
X
X	if (readfds & stdin_mask)
X		send_stuff();
X	if ((readfds & driver_mask) == 0)
X		goto one_more_time;
X	return _filbuf(fd);
X}
X
X/*
X * send_stuff:
X *	Send standard input characters to the driver
X */
Xsend_stuff()
X{
X	register int	count;
X	register char	*sp, *nsp;
X	static char	inp[sizeof Buf];
X
X	count = read(fileno(stdin), Buf, sizeof Buf);
X	if (count <= 0)
X		return;
X	if (nchar_send <= 0 && !no_beep) {
X		(void) write(1, "\7", 1);	/* CTRL(G) */
X		return;
X	}
X
X	/*
X	 * look for 'q'uit commands; if we find one,
X	 * confirm it.  If it is not confirmed, strip
X	 * it out of the input
X	 */
X	Buf[count] = '\0';
X	nsp = inp;
X	for (sp = Buf; *sp != '\0'; sp++)
X		if ((*nsp = map_key[*sp]) == 'q')
X			intr();
X# ifdef OTTO
X		else if (*nsp == CTRL(O))
X			Otto_mode = !Otto_mode;
X# endif OTTO
X		else
X			nsp++;
X	count = nsp - inp;
X	if (count) {
X# ifdef OTTO
X		Otto_count += count;
X# endif OTTO
X		nchar_send -= count;
X		if (nchar_send < 0)
X			count += nchar_send;
X		(void) write(Socket, inp, count);
X	}
X}
X
X/*
X * quit:
X *	Handle the end of the game when the player dies
X */
Xlong
Xquit(old_status)
Xlong	old_status;
X{
X	register int	explain, ch;
X
X	if (Last_player)
X		return Q_QUIT;
X# ifdef OTTO
X	if (Otto_mode)
X		return Q_CLOAK;
X# endif OTTO
X	mvcur(cur_row, cur_col, HEIGHT, 0);
X	cur_row = HEIGHT;
X	cur_col = 0;
X	put_str("Re-enter game [ynwo]? ");
X	clear_eol();
X	fflush(stdout);
X	explain = FALSE;
X	for (;;) {
X		if (isupper(ch = getchar()))
X			ch = tolower(ch);
X		if (ch == 'y')
X			return old_status;
X		else if (ch == 'o')
X			break;
X		else if (ch == 'n') {
X# ifndef INTERNET
X			return Q_QUIT;
X# else
X			mvcur(cur_row, cur_col, HEIGHT, 0);
X			cur_row = HEIGHT;
X			cur_col = 0;
X			put_str("Write a parting message [yn]? ");
X			clear_eol();
X			for (;;) {
X				if (isupper(ch = getchar()))
X					ch = tolower(ch);
X				if (ch == 'y')
X					goto get_message;
X				if (ch == 'n')
X					return Q_QUIT;
X			}
X# endif
X		}
X# ifdef INTERNET
X		else if (ch == 'w') {
X			static	char	buf[WIDTH + WIDTH % 2];
X			char		*cp, c;
X
Xget_message:
X			c = ch;		/* save how we got here */
X			mvcur(cur_row, cur_col, HEIGHT, 0);
X			cur_row = HEIGHT;
X			cur_col = 0;
X			put_str("Message: ");
X			clear_eol();
X			cp = buf;
X			while ((ch = getchar()) != '\n' && ch != '\r') {
X# ifdef TERMINFO
X				if (ch == erasechar())
X# else
X				if (ch == _tty.sg_erase)
X# endif
X				{
X					if (cp > buf) {
X						mvcur(cur_row, cur_col, cur_row,
X								cur_col - 1);
X						cur_col -= 1;
X						cp -= 1;
X						clear_eol();
X					}
X					continue;
X# ifdef TERMINFO
X				} else if (ch == killchar()) {
X# else
X				} else if (ch == _tty.sg_kill) {
X# endif
X					mvcur(cur_row, cur_col, cur_row,
X							cur_col - (cp - buf));
X					cur_col -= cp - buf;
X					cp = buf;
X					clear_eol();
X					continue;
X				}
X				put_ch(ch);
X				*cp++ = ch;
X				if (cp + 1 >= buf + sizeof buf)
X					break;
X			}
X			*cp = '\0';
X			Send_message = buf;
X			return (c == 'w') ? old_status : Q_MESSAGE;
X		}
X# endif INTERNET
X		(void) putchar(CTRL(G));
X		if (!explain) {
X			put_str("(Yes, No, Write message, or Options) ");
X			explain = TRUE;
X		}
X		fflush(stdout);
X	}
X
X	mvcur(cur_row, cur_col, HEIGHT, 0);
X	cur_row = HEIGHT;
X	cur_col = 0;
X# ifdef FLY
X	put_str("Scan, Cloak, Flying, or Quit? ");
X# else
X	put_str("Scan, Cloak, or Quit? ");
X# endif FLY
X	clear_eol();
X	fflush(stdout);
X	explain = FALSE;
X	for (;;) {
X		if (isupper(ch = getchar()))
X			ch = tolower(ch);
X		if (ch == 's')
X			return Q_SCAN;
X		else if (ch == 'c')
X			return Q_CLOAK;
X# ifdef FLY
X		else if (ch == 'f')
X			return Q_FLY;
X# endif FLY
X		else if (ch == 'q')
X			return Q_QUIT;
X		(void) putchar(CTRL(G));
X		if (!explain) {
X# ifdef FLY
X			put_str("[SCFQ] ");
X# else
X			put_str("[SCQ] ");
X# endif FLY
X			explain = TRUE;
X		}
X		fflush(stdout);
X	}
X}
X
Xput_ch(ch)
X	char	ch;
X{
X	if (!isprint(ch)) {
X		fprintf(stderr, "r,c,ch: %d,%d,%d", cur_row, cur_col, ch);
X		return;
X	}
X	screen[cur_row][cur_col] = ch;
X	putchar(ch);
X	if (++cur_col >= COLS) {
X		if (!AM || XN)
X			putchar('\n');
X		cur_col = 0;
X		if (++cur_row >= LINES)
X			cur_row = LINES;
X	}
X}
X
Xput_str(s)
X	char	*s;
X{
X	while (*s)
X		put_ch(*s++);
X}
X
Xclear_the_screen()
X{
X	register int	i;
X
X	if (blanks[0] == '\0')
X		for (i = 0; i < SCREEN_WIDTH; i++)
X			blanks[i] = ' ';
X
X	if (CL != NULL) {
X		tputs(CL, LINES, _putchar);
X		for (i = 0; i < SCREEN_HEIGHT; i++)
X			bcopy(blanks, screen[i], SCREEN_WIDTH);
X	} else {
X		for (i = 0; i < SCREEN_HEIGHT; i++) {
X			mvcur(cur_row, cur_col, i, 0);
X			cur_row = i;
X			cur_col = 0;
X			clear_eol();
X		}
X		mvcur(cur_row, cur_col, 0, 0);
X	}
X	cur_row = cur_col = 0;
X#ifdef TERMINFO
X	move(0, 0);
X	refresh();
X#endif
X}
X
Xclear_eol()
X{
X	if (CE != NULL)
X		tputs(CE, 1, _putchar);
X	else {
X		fwrite(blanks, sizeof (char), SCREEN_WIDTH - cur_col, stdout);
X		if (COLS != SCREEN_WIDTH)
X			mvcur(cur_row, SCREEN_WIDTH, cur_row, cur_col);
X		else if (AM)
X			mvcur(cur_row + 1, 0, cur_row, cur_col);
X		else
X			mvcur(cur_row, SCREEN_WIDTH - 1, cur_row, cur_col);
X	}
X	bcopy(blanks, &screen[cur_row][cur_col], SCREEN_WIDTH - cur_col);
X}
X
Xredraw_screen()
X{
X	register int	i;
X# ifndef NOCURSES
X	static int	first = 1;
X
X	if (first) {
X		curscr = newwin(SCREEN_HEIGHT, SCREEN_WIDTH, 0, 0);
X		if (curscr == NULL) {
X			fprintf(stderr, "Can't create curscr\n");
X			exit(1);
X		}
X		for (i = 0; i < SCREEN_HEIGHT; i++)
X			curscr->_y[i] = screen[i];
X		first = 0;
X	}
X	curscr->_cury = cur_row;
X	curscr->_curx = cur_col;
X	clearok(curscr, TRUE);
X	touchwin(curscr);
X	wrefresh(curscr);
X#else
X	mvcur(cur_row, cur_col, 0, 0);
X	for (i = 0; i < SCREEN_HEIGHT - 1; i++) {
X		fwrite(screen[i], sizeof (char), SCREEN_WIDTH, stdout);
X		if (COLS > SCREEN_WIDTH || (COLS == SCREEN_WIDTH && !AM))
X			putchar('\n');
X	}
X	fwrite(screen[SCREEN_HEIGHT - 1], sizeof (char), SCREEN_WIDTH - 1,
X		stdout);
X	mvcur(SCREEN_HEIGHT - 1, SCREEN_WIDTH - 1, cur_row, cur_col);
X#endif
X}
X
X/*
X * do_message:
X *	Send a message to the driver and return
X */
Xdo_message()
X{
X	extern int	errno;
X	long		version;
X
X	if (read(Socket, (char *) &version, LONGLEN) != LONGLEN) {
X		bad_con();
X		/* NOTREACHED */
X	}
X	if (ntohl(version) != HUNT_VERSION) {
X		bad_ver();
X		/* NOTREACHED */
X	}
X	if (write(Socket, Send_message, strlen(Send_message)) < 0) {
X		bad_con();
X		/* NOTREACHED */
X	}
X	(void) close(Socket);
X}
END_OF_FILE
if test 10343 -ne `wc -c <'playit.c'`; then
    echo shar: \"'playit.c'\" unpacked with wrong size!
fi
# end of 'playit.c'
fi
echo shar: End of archive 2 \(of 4\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0