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

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

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



#! /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 3 (of 4)."
# Contents:  Makefile answer.c connect.c draw.c expl.c extern.c
#   faketalk.c get_names.c hunt.h huntd.6 makemaze.c
# Wrapped by billr@saab on Wed Oct 19 09:23:34 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(4672 characters\)
sed "s/^X//" >'Makefile' <<'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#
XSHELL=		/bin/sh
XHDR=		hunt.h bsd.h
XDSRC=		answer.c driver.c draw.c execute.c expl.c makemaze.c \
X		shots.c terminal.c extern.c pathname.c \
X		faketalk.c ctl.c ctl_transact.c get_names.c
XDOBJ=		answer.o driver.o draw.o execute.o expl.o makemaze.o \
X		shots.o terminal.o extern.o \
X		faketalk.o ctl.o ctl_transact.o get_names.o
XPSRC=		hunt.c connect.c playit.c pathname.c
XPOBJ=		hunt.o connect.o playit.o
XDSRC1=		answer.c driver.c draw.c execute.c expl.c makemaze.c
XDSRC2=		shots.c terminal.c extern.c faketalk.c \
X		ctl.c ctl_transact.c get_names.c
X
X#
X# Game parameter flags are:
X#	RANDOM	Include doors which disperse shots randomly
X#	REFLECT	Include diagonal walls that reflect shots
X#	MONITOR	Include code for watching the game from the sidelines
X#	OOZE	Include slime shots
X#	FLY	Make people fly when walls regenerate under them
X#	VOLCANO	Include occasional large slime explosions
X#	DRONE	Include occasional drone shots
X#	BOOTS	Include boots (which makes you immune to slime)
X#	OTTO	Reserved for CGL use
X#
XGAME_PARAM=	-DRANDOM -DREFLECT -DMONITOR -DOOZE -DFLY -DBOOTS
X
X#
X# System parameter flags are:
X#	DEBUG		Don't trust everything in the code
X#	INTERNET	Use the Internet domain IPC instead of UNIX domain
X#	LOG		Use syslog error-logging in driver (needs SYSLOG_42 or
X#			or SYSLOG_43)
X#	OLDIPC		Use 4.1a internet system calls (must also define
X#			INTERNET)
X#	TERMINFO	Use terminfo instead of termcap
X#	TALK_42		Support fake 4.2 BSD talk requests
X#	TALK_43		Support fake 4.2 BSD talk requests
X#	SYSLOG_42	Use 4.2 BSD syslog(3)
X#	SYSLOG_43	Use 4.2 BSD syslog(3)
X#	LOG		Use syslog(3) for logging errors
X#	BSD		Which version of BSD distribution
X#			42 is 4.2BSD (implies TALK_42, SYSLOG_42)
X#			43 is 4.3BSD (implies BROADCAST, TALK_43, SYSLOG_43)
X#	NOCURSES	Don't use curses to redraw the screen
X#	HPUX		A Hewlett-Packard special
X#
X# NOTE: if you change the domain (INTERNET vs UNIX) then "make newdomain"
X#
XDEFS_43=	-DINTERNET -DLOG -DBSD=43
XDEFS_SUN=	-DINTERNET -DLOG -DBSD=42 -DBROADCAST
XDEFS_ULTRIX=	-DINTERNET -DLOG -DBSD=42
XDEFS_HPUX=	-DINTERNET -DTERMINFO -DNOCURSES -DHPUX
XDEFS_CONVEX=	-DINTERNET -DBSD=42
XDEFS_SGI=	-DINTERNET -DLOG -DTERMINFO -DSYSLOG_43 -DBROADCAST -DNOCURSES
X
X#
X# The following flags are used for system specific compilation arguments.
X# Change them to include the appropriate arguments.  For example, on SGI
X# machines, they should look like
X# SYSCFLAGS=	-I/usr/include/bsd
X# SYSLIBS=	-lbsd
X#
XSYSCFLAGS=
XSYSLIBS=
X
X#
X# Generic definitions
X#
XDEFS=		$(GAME_PARAM) $(DEFS_43)
XCFLAGS=		-O $(SYSCFLAGS) $(DEFS)
X
X#
X# Normal targets
X#
Xall:	hunt huntd
X
Xhunt:	$(POBJ) pathname.o
X	$(CC) -o hunt $(POBJ) pathname.o -lcurses -ltermcap $(SYSLIBS)
X
Xhuntd:	$(DOBJ) pathname.o
X	$(CC) -o huntd $(DOBJ) pathname.o $(SYSLIBS)
X
Xdebug:	hunt.dbg huntd.dbg
X
Xhunt.dbg:	$(POBJ) pathname.dbg.o
X	$(CC) -o hunt.dbg $(POBJ) pathname.dbg.o -lcurses -ltermcap $(SYSLIBS)
X
Xhuntd.dbg: $(DOBJ) pathname.dbg.o
X	$(CC) -o huntd.dbg $(DOBJ) pathname.dbg.o $(SYSLIBS)
X
X#
X# Source distribution in three files to a particular person
X#
Xmail.msg:
X	-@if test x${MAIL} = x ; then\
X		/bin/echo MAIL not set ;\
X	fi
Xmail.quit:
X	@test x$mail != x
Xmail:	mail.msg mail.quit
X	shar -a README hunt.6 huntd.6 Makefile ${HDR} ${PSRC} |\
X	Mail -s "Hunt (part 1 of 3)" ${MAIL}
X	shar -a ${DSRC1} | Mail -s "Hunt (part 2 of 3)" ${MAIL}
X	shar -a ${DSRC2} talk_ctl.h | Mail -s "Hunt (part 3 of 3)" ${MAIL}
X
X#
X# System installation
X#
Xinstall:	standard
X	-cmp -s huntd /usr/games/lib/huntd \
X		|| install -c huntd /usr/games/lib/huntd
X	-cmp -s hunt /usr/games/hunt \
X		|| install -c hunt /usr/games/hunt
X	-cmp -s hunt.6 /usr/man/man6/hunt.6\
X		|| install -c hunt.6 /usr/man/man6/hunt.6
X	-cmp -s huntd.6 /usr/man/man6/huntd.6\
X		|| install -c huntd.6 /usr/man/man6/huntd.6
X
X#
X# Object file dependencies
X#
X$(POBJ): $(HDR)
X
X$(DOBJ): $(HDR)
X	$(CC) $(CFLAGS) -c $*.c
X
Xpathname.dbg.o: pathname.c
X	@echo $(CC) $(CFLAGS) -DDEBUG -c pathname.c -o pathname.dbg.o
X	@rm -f x.c
X	@ln pathname.c x.c
X	@$(CC) $(CFLAGS) -DDEBUG -c x.c
X	@mv x.o pathname.dbg.o
X	@rm -f x.c
X
X#
X# Miscellaneous functions
X#
Xlint:	$(DSRC) $(PSRC)
X	lint $(DEFS) $(DSRC) 2>&1 > driver.lint
X	lint $(DEFS) $(PSRC) -lcurses 2>&1 > hunt.lint
X
Xtags:	$(DSRC) $(PSRC)
X	ctags $(DSRC) $(PSRC)
X
Xclean:
X	rm -f $(POBJ) $(DOBJ) pathname.o pathname.dbg.o errs hunt.dbg \
X	huntd.dbg hunt huntd hunt.lint driver.lint
X
Xnewdomain:
X	rm hunt.o extern.o driver.o
END_OF_FILE
if test 4672 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'answer.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'answer.c'\"
else
echo shar: Extracting \"'answer.c'\" \(8627 characters\)
sed "s/^X//" >'answer.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	<ctype.h>
X# include	<errno.h>
X# include	<fcntl.h>
X
X# define	SCOREDECAY	15
X
Xstatic char	Ttyname[NAMELEN];
X
Xanswer()
X{
X	register PLAYER		*pp;
X	register int		newsock;
X	static u_long		mode;
X	static char		name[NAMELEN];
X	static char		team;
X	static int		enter_status;
X	static int		socklen;
X	static u_long		machine;
X	static u_long		uid;
X	static SOCKET		sockstruct;
X	register char	*cp1, *cp2;
X	int			flags;
X	long			version;
X
X# ifdef INTERNET
X	socklen = sizeof sockstruct;
X# else
X	socklen = sizeof sockstruct - 1;
X# endif INTERNET
X	errno = 0;
X	newsock = accept(Socket, (struct sockaddr *) &sockstruct, &socklen);
X	if (newsock < 0)
X	{
X		if (errno == EINTR)
X			return FALSE;
X# ifdef LOG
X		syslog(LOG_ERR, "accept: %m");
X# else LOG
X		perror("accept");
X# endif LOG
X		cleanup(1);
X	}
X
X# ifdef INTERNET
X	machine = ntohl(((struct sockaddr_in *) &sockstruct)->sin_addr.s_addr);
X# else INTERNET
X	if (machine == 0)
X		machine = gethostid();
X# endif INTERNET
X	version = htonl((unsigned long) HUNT_VERSION);
X	(void) write(newsock, (char *) &version, LONGLEN);
X	(void) read(newsock, (char *) &uid, LONGLEN);
X	uid = ntohl((unsigned long) uid);
X	(void) read(newsock, name, NAMELEN);
X	(void) read(newsock, &team, 1);
X	(void) read(newsock, (char *) &enter_status, LONGLEN);
X	enter_status = ntohl((unsigned long) enter_status);
X	(void) read(newsock, Ttyname, NAMELEN);
X	(void) read(newsock, (char *) &mode, sizeof mode);
X	mode = ntohl(mode);
X
X	/*
X	 * Turn off blocking I/O, so a slow or dead terminal won't stop
X	 * the game.  All subsequent reads check how many bytes they read.
X	 */
X	flags = fcntl(newsock, F_GETFL, 0);
X	flags |= O_NDELAY;
X	(void) fcntl(newsock, F_SETFL, flags);
X
X	/*
X	 * Make sure the name contains only printable characters
X	 * since we use control characters for cursor control
X	 * between driver and player processes
X	 */
X	for (cp1 = cp2 = name; *cp1 != '\0'; cp1++)
X		if (isprint(*cp1) || *cp1 == ' ')
X			*cp2++ = *cp1;
X	*cp2 = '\0';
X
X# ifdef INTERNET
X	if (mode == C_MESSAGE) {
X		char	buf[BUFSIZ + 1];
X		int	n;
X
X		if (team == ' ')
X			(void) sprintf(buf, "%s: ", name);
X		else
X			(void) sprintf(buf, "%s[%c]: ", name, team);
X		n = strlen(buf);
X		for (pp = Player; pp < End_player; pp++) {
X			cgoto(pp, HEIGHT, 0);
X			outstr(pp, buf, n);
X		}
X		while ((n = read(newsock, buf, BUFSIZ)) > 0)
X			for (pp = Player; pp < End_player; pp++)
X				outstr(pp, buf, n);
X		for (pp = Player; pp < End_player; pp++) {
X			ce(pp);
X			sendcom(pp, REFRESH);
X			sendcom(pp, READY, 0);
X			(void) fflush(pp->p_output);
X		}
X		(void) close(newsock);
X		return FALSE;
X	}
X	else
X# endif
X# ifdef MONITOR
X	if (mode == C_MONITOR)
X		if (End_monitor < &Monitor[MAXMON])
X			pp = End_monitor++;
X		else {
X			socklen = 0;
X			(void) write(newsock, (char *) &socklen,
X				sizeof socklen);
X			(void) close(newsock);
X			return FALSE;
X		}
X	else
X# endif MONITOR
X		if (End_player < &Player[MAXPL])
X			pp = End_player++;
X		else {
X			socklen = 0;
X			(void) write(newsock, (char *) &socklen,
X				sizeof socklen);
X			(void) close(newsock);
X			return FALSE;
X		}
X
X#ifdef MONITOR
X	if (mode == C_MONITOR && team == ' ')
X		team = '*';
X#endif
X	pp->p_ident = get_ident(machine, uid, name, team);
X	pp->p_output = fdopen(newsock, "w");
X	pp->p_death[0] = '\0';
X	pp->p_fd = newsock;
X	pp->p_mask = (1 << pp->p_fd);
X	Fds_mask |= pp->p_mask;
X	if (pp->p_fd >= Num_fds)
X		Num_fds = pp->p_fd + 1;
X
X	pp->p_y = 0;
X	pp->p_x = 0;
X
X# ifdef MONITOR
X	if (mode == C_MONITOR)
X		stmonitor(pp);
X	else
X# endif MONITOR
X		stplayer(pp, enter_status);
X	return TRUE;
X}
X
X# ifdef MONITOR
Xstmonitor(pp)
Xregister PLAYER	*pp;
X{
X	register int	line;
X	register PLAYER	*npp;
X
X	bcopy((char *) Maze, (char *) pp->p_maze, sizeof Maze);
X
X	drawmaze(pp);
X
X	(void) sprintf(Buf, "%5.5s%c%-10.10s %c", " ", stat_char(pp),
X		pp->p_ident->i_name, pp->p_ident->i_team);
X	line = STAT_MON_ROW + 1 + (pp - Monitor);
X	for (npp = Player; npp < End_player; npp++) {
X		cgoto(npp, line, STAT_NAME_COL);
X		outstr(npp, Buf, STAT_NAME_LEN);
X	}
X	for (npp = Monitor; npp < End_monitor; npp++) {
X		cgoto(npp, line, STAT_NAME_COL);
X		outstr(npp, Buf, STAT_NAME_LEN);
X	}
X
X	sendcom(pp, REFRESH);
X	sendcom(pp, READY, 0);
X	(void) fflush(pp->p_output);
X}
X# endif MONITOR
X
Xstplayer(newpp, enter_status)
Xregister PLAYER	*newpp;
Xint		enter_status;
X{
X	register int	x, y;
X	register PLAYER	*pp;
X
X	Nplayer++;
X
X	for (y = 0; y < UBOUND; y++)
X		for (x = 0; x < WIDTH; x++)
X			newpp->p_maze[y][x] = Maze[y][x];
X	for (     ; y < DBOUND; y++) {
X		for (x = 0; x < LBOUND; x++)
X			newpp->p_maze[y][x] = Maze[y][x];
X		for (     ; x < RBOUND; x++)
X			newpp->p_maze[y][x] = SPACE;
X		for (     ; x < WIDTH;  x++)
X			newpp->p_maze[y][x] = Maze[y][x];
X	}
X	for (     ; y < HEIGHT; y++)
X		for (x = 0; x < WIDTH; x++)
X			newpp->p_maze[y][x] = Maze[y][x];
X
X	do {
X		x = rand_num(WIDTH - 1) + 1;
X		y = rand_num(HEIGHT - 1) + 1;
X	} while (Maze[y][x] != SPACE);
X	newpp->p_over = SPACE;
X	newpp->p_x = x;
X	newpp->p_y = y;
X	newpp->p_undershot = FALSE;
X
X# ifdef FLY
X	if (enter_status == Q_FLY) {
X		newpp->p_flying = rand_num(20);
X		newpp->p_flyx = 2 * rand_num(6) - 5;
X		newpp->p_flyy = 2 * rand_num(6) - 5;
X		newpp->p_face = FLYER;
X	}
X	else
X# endif FLY
X	{
X		newpp->p_flying = -1;
X		newpp->p_face = rand_dir();
X	}
X	newpp->p_damage = 0;
X	newpp->p_damcap = MAXDAM;
X	newpp->p_nchar = 0;
X	newpp->p_ncount = 0;
X	newpp->p_nexec = 0;
X	newpp->p_ammo = ISHOTS;
X# ifdef BOOTS
X	newpp->p_nboots = 0;
X# endif	BOOTS
X	if (enter_status == Q_SCAN) {
X		newpp->p_scan = SCANLEN;
X		newpp->p_cloak = 0;
X	}
X	else {
X		newpp->p_scan = 0;
X		newpp->p_cloak = CLOAKLEN;
X	}
X	newpp->p_ncshot = 0;
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] = GMINE;
X# ifdef MONITOR
X	for (pp = Monitor; pp < End_monitor; pp++)
X		check(pp, y, x);
X# endif MONITOR
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] = MINE;
X# ifdef MONITOR
X	for (pp = Monitor; pp < End_monitor; pp++)
X		check(pp, y, x);
X# endif MONITOR
X
X	(void) sprintf(Buf, "%5.2f%c%-10.10s %c", newpp->p_ident->i_score,
X		stat_char(newpp), newpp->p_ident->i_name,
X		newpp->p_ident->i_team);
X	y = STAT_PLAY_ROW + 1 + (newpp - Player);
X	for (pp = Player; pp < End_player; pp++) {
X		if (pp != newpp) {
X			char	smallbuf[10];
X
X			pp->p_ammo += NSHOTS;
X			newpp->p_ammo += NSHOTS;
X			cgoto(pp, y, STAT_NAME_COL);
X			outstr(pp, Buf, STAT_NAME_LEN);
X			(void) sprintf(smallbuf, "%3d", pp->p_ammo);
X			cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
X			outstr(pp, smallbuf, 3);
X		}
X	}
X# ifdef MONITOR
X	for (pp = Monitor; pp < End_monitor; pp++) {
X		cgoto(pp, y, STAT_NAME_COL);
X		outstr(pp, Buf, STAT_NAME_LEN);
X	}
X# endif MONITOR
X
X	drawmaze(newpp);
X	drawplayer(newpp, TRUE);
X	look(newpp);
X# ifdef	FLY
X	if (enter_status == Q_FLY)
X		/* Make sure that the position you enter in will be erased */
X		showexpl(newpp->p_y, newpp->p_x, FLYER);
X# endif
X	sendcom(newpp, REFRESH);
X	sendcom(newpp, READY, 0);
X	(void) fflush(newpp->p_output);
X}
X
X/*
X * rand_dir:
X *	Return a random direction
X */
Xrand_dir()
X{
X	switch (rand_num(4)) {
X	  case 0:
X		return LEFTS;
X	  case 1:
X		return RIGHT;
X	  case 2:
X		return BELOW;
X	  case 3:
X		return ABOVE;
X	}
X	/* NOTREACHED */
X}
X
X/*
X * get_ident:
X *	Get the score structure of a player
X */
XIDENT *
Xget_ident(machine, uid, name, team)
Xu_long	machine;
Xu_long	uid;
Xchar	*name;
Xchar	team;
X{
X	register IDENT	*ip;
X	static IDENT	punt;
X
X	for (ip = Scores; ip != NULL; ip = ip->i_next)
X		if (ip->i_machine == machine
X		&&  ip->i_uid == uid
X		&&  ip->i_team == team
X		&&  strncmp(ip->i_name, name, NAMELEN) == 0)
X			break;
X
X	if (ip != NULL) {
X		if (ip->i_entries < SCOREDECAY)
X			ip->i_entries++;
X		else
X			ip->i_kills = (ip->i_kills * (SCOREDECAY - 1))
X				/ SCOREDECAY;
X		ip->i_score = ip->i_kills / (double) ip->i_entries;
X	}
X	else {
X		ip = (IDENT *) malloc(sizeof (IDENT));
X		if (ip == NULL) {
X			/* Fourth down, time to punt */
X			ip = &punt;
X		}
X		ip->i_machine = machine;
X		ip->i_team = team;
X		ip->i_uid = uid;
X		strncpy(ip->i_name, name, NAMELEN);
X		ip->i_kills = 0;
X		ip->i_entries = 1;
X		ip->i_score = 0;
X		ip->i_absorbed = 0;
X		ip->i_faced = 0;
X		ip->i_shot = 0;
X		ip->i_robbed = 0;
X		ip->i_slime = 0;
X		ip->i_missed = 0;
X		ip->i_ducked = 0;
X		ip->i_gkills = ip->i_bkills = ip->i_deaths = 0;
X		ip->i_stillb = ip->i_saved = 0;
X		ip->i_next = Scores;
X		Scores = ip;
X	}
X
X	return ip;
X}
END_OF_FILE
if test 8627 -ne `wc -c <'answer.c'`; then
    echo shar: \"'answer.c'\" unpacked with wrong size!
fi
# end of 'answer.c'
fi
if test -f 'connect.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'connect.c'\"
else
echo shar: Extracting \"'connect.c'\" \(1085 characters\)
sed "s/^X//" >'connect.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
Xdo_connect(name, team, enter_status)
Xchar	*name;
Xchar	team;
Xlong	enter_status;
X{
X	static long	uid;
X	static long	mode;
X	extern char	*ttyname();
X
X	if (uid == 0)
X		uid = htonl(getuid());
X	(void) write(Socket, (char *) &uid, LONGLEN);
X	(void) write(Socket, name, NAMELEN);
X	(void) write(Socket, &team, 1);
X	enter_status = htonl(enter_status);
X	(void) write(Socket, (char *) &enter_status, LONGLEN);
X	(void) strcpy(Buf, ttyname(fileno(stderr)));
X	(void) write(Socket, Buf, NAMELEN);
X# ifdef INTERNET
X	if (Send_message != NULL)
X		mode = C_MESSAGE;
X	else
X# endif
X# ifdef MONITOR
X	if (Am_monitor)
X		mode = C_MONITOR;
X	else
X# endif MONITOR
X		mode = C_PLAYER;
X	mode = htonl(mode);
X	(void) write(Socket, (char *) &mode, sizeof mode);
X}
END_OF_FILE
if test 1085 -ne `wc -c <'connect.c'`; then
    echo shar: \"'connect.c'\" unpacked with wrong size!
fi
# end of 'connect.c'
fi
if test -f 'draw.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'draw.c'\"
else
echo shar: Extracting \"'draw.c'\" \(6943 characters\)
sed "s/^X//" >'draw.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
Xdrawmaze(pp)
Xregister PLAYER	*pp;
X{
X	register int	x;
X	register char	*sp;
X	register int	y;
X	register char	*endp;
X
X	clrscr(pp);
X	outstr(pp, pp->p_maze[0], WIDTH);
X	for (y = 1; y < HEIGHT - 1; y++) {
X		endp = &pp->p_maze[y][WIDTH];
X		for (x = 0, sp = pp->p_maze[y]; sp < endp; x++, sp++)
X			if (*sp != SPACE) {
X				cgoto(pp, y, x);
X				if (pp->p_x == x && pp->p_y == y)
X					outch(pp, translate(*sp));
X				else if (isplayer(*sp))
X					outch(pp, player_sym(pp, y, x));
X				else
X					outch(pp, *sp);
X			}
X	}
X	cgoto(pp, HEIGHT - 1, 0);
X	outstr(pp, pp->p_maze[HEIGHT - 1], WIDTH);
X	drawstatus(pp);
X}
X
X/*
X * drawstatus - put up the status lines (this assumes the screen
X *		size is 80x24 with the maze being 64x24)
X */
Xdrawstatus(pp)
Xregister PLAYER	*pp;
X{
X	register int	i;
X	register PLAYER	*np;
X
X	cgoto(pp, STAT_AMMO_ROW, STAT_LABEL_COL);
X	outstr(pp, "Ammo:", 5);
X	(void) sprintf(Buf, "%3d", pp->p_ammo);
X	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
X	outstr(pp, Buf, 3);
X
X	cgoto(pp, STAT_GUN_ROW, STAT_LABEL_COL);
X	outstr(pp, "Gun:", 4);
X	cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
X	outstr(pp, (pp->p_ncshot < MAXNCSHOT) ? " ok" : "   ", 3);
X
X	cgoto(pp, STAT_DAM_ROW, STAT_LABEL_COL);
X	outstr(pp, "Damage:", 7);
X	(void) sprintf(Buf, "%2d/%2d", pp->p_damage, pp->p_damcap);
X	cgoto(pp, STAT_DAM_ROW, STAT_VALUE_COL);
X	outstr(pp, Buf, 5);
X
X	cgoto(pp, STAT_KILL_ROW, STAT_LABEL_COL);
X	outstr(pp, "Kills:", 6);
X	(void) sprintf(Buf, "%3d", (pp->p_damcap - MAXDAM) / 2);
X	cgoto(pp, STAT_KILL_ROW, STAT_VALUE_COL);
X	outstr(pp, Buf, 3);
X
X	cgoto(pp, STAT_PLAY_ROW, STAT_LABEL_COL);
X	outstr(pp, "Player:", 7);
X	for (i = STAT_PLAY_ROW + 1, np = Player; np < End_player; np++) {
X		(void) sprintf(Buf, "%5.2f%c%-10.10s %c", np->p_ident->i_score,
X			stat_char(np), np->p_ident->i_name,
X			np->p_ident->i_team);
X		cgoto(pp, i++, STAT_NAME_COL);
X		outstr(pp, Buf, STAT_NAME_LEN);
X	}
X
X# ifdef MONITOR
X	cgoto(pp, STAT_MON_ROW, STAT_LABEL_COL);
X	outstr(pp, "Monitor:", 8);
X	for (i = STAT_MON_ROW + 1, np = Monitor; np < End_monitor; np++) {
X		(void) sprintf(Buf, "%5.5s %-10.10s %c", " ",
X			np->p_ident->i_name, np->p_ident->i_team);
X		cgoto(pp, i++, STAT_NAME_COL);
X		outstr(pp, Buf, STAT_NAME_LEN);
X	}
X# endif MONITOR
X}
X
Xlook(pp)
Xregister PLAYER	*pp;
X{
X	register int	x, y;
X
X	x = pp->p_x;
X	y = pp->p_y;
X
X	check(pp, y - 1, x - 1);
X	check(pp, y - 1, x    );
X	check(pp, y - 1, x + 1);
X	check(pp, y    , x - 1);
X	check(pp, y    , x    );
X	check(pp, y    , x + 1);
X	check(pp, y + 1, x - 1);
X	check(pp, y + 1, x    );
X	check(pp, y + 1, x + 1);
X
X	switch (pp->p_face) {
X	  case LEFTS:
X		see(pp, LEFTS);
X		see(pp, ABOVE);
X		see(pp, BELOW);
X		break;
X	  case RIGHT:
X		see(pp, RIGHT);
X		see(pp, ABOVE);
X		see(pp, BELOW);
X		break;
X	  case ABOVE:
X		see(pp, ABOVE);
X		see(pp, LEFTS);
X		see(pp, RIGHT);
X		break;
X	  case BELOW:
X		see(pp, BELOW);
X		see(pp, LEFTS);
X		see(pp, RIGHT);
X		break;
X# ifdef FLY
X	  case FLYER:
X		break;
X# endif FLY
X	}
X	cgoto(pp, y, x);
X}
X
Xsee(pp, face)
Xregister PLAYER	*pp;
Xint		face;
X{
X	register char	*sp;
X	register int	y, x, i, cnt;
X
X	x = pp->p_x;
X	y = pp->p_y;
X
X	switch (face) {
X	  case LEFTS:
X		sp = &Maze[y][x];
X		for (i = 0; See_over[*--sp]; i++)
X			continue;
X
X		if (i == 0)
X			break;
X
X		cnt = i;
X		x = pp->p_x - 1;
X		--y;
X		while (i--)
X			check(pp, y, --x);
X		i = cnt;
X		x = pp->p_x - 1;
X		++y;
X		while (i--)
X			check(pp, y, --x);
X		i = cnt;
X		x = pp->p_x - 1;
X		++y;
X		while (i--)
X			check(pp, y, --x);
X		break;
X	  case RIGHT:
X		sp = &Maze[y][++x];
X		for (i = 0; See_over[*sp++]; i++)
X			continue;
X
X		if (i == 0)
X			break;
X
X		cnt = i;
X		x = pp->p_x + 1;
X		--y;
X		while (i--)
X			check(pp, y, ++x);
X		i = cnt;
X		x = pp->p_x + 1;
X		++y;
X		while (i--)
X			check(pp, y, ++x);
X		i = cnt;
X		x = pp->p_x + 1;
X		++y;
X		while (i--)
X			check(pp, y, ++x);
X		break;
X	  case ABOVE:
X		sp = &Maze[--y][x];
X		if (!See_over[*sp])
X			break;
X		do {
X			--y;
X			sp -= sizeof Maze[0];
X			check(pp, y, x - 1);
X			check(pp, y, x    );
X			check(pp, y, x + 1);
X		} while (See_over[*sp]);
X		break;
X	  case BELOW:
X		sp = &Maze[++y][x];
X		if (!See_over[*sp])
X			break;
X		do {
X			y++;
X			sp += sizeof Maze[0];
X			check(pp, y, x - 1);
X			check(pp, y, x    );
X			check(pp, y, x + 1);
X		} while (See_over[*sp]);
X		break;
X	}
X}
X
Xcheck(pp, y, x)
XPLAYER	*pp;
Xint	y, x;
X{
X	register int	index;
X	register int	ch;
X	register PLAYER	*rpp;
X
X	index = y * sizeof Maze[0] + x;
X	ch = ((char *) Maze)[index];
X	if (ch != ((char *) pp->p_maze)[index]) {
X		rpp = pp;
X		cgoto(rpp, y, x);
X		if (x == rpp->p_x && y == rpp->p_y)
X			outch(rpp, translate(ch));
X		else if (isplayer(ch))
X			outch(rpp, player_sym(rpp, y, x));
X		else
X			outch(rpp, ch);
X		((char *) rpp->p_maze)[index] = ch;
X	}
X}
X
X/*
X * showstat
X *	Update the status of players
X */
Xshowstat(pp)
Xregister PLAYER	*pp;
X{
X	register PLAYER	*np;
X	register int	y;
X	register char	c;
X
X	y = STAT_PLAY_ROW + 1 + (pp - Player);
X	c = stat_char(pp);
X# ifdef MONITOR
X	for (np = Monitor; np < End_monitor; np++) {
X		cgoto(np, y, STAT_SCAN_COL);
X		outch(np, c);
X	}
X# endif MONITOR
X	for (np = Player; np < End_player; np++) {
X		cgoto(np, y, STAT_SCAN_COL);
X		outch(np, c);
X	}
X}
X
X/*
X * drawplayer:
X *	Draw the player on the screen and show him to everyone who's scanning
X *	unless he is cloaked.
X */
Xdrawplayer(pp, draw)
XPLAYER	*pp;
XFLAG	draw;
X{
X	register PLAYER	*newp;
X	register int	x, y;
X
X	x = pp->p_x;
X	y = pp->p_y;
X	Maze[y][x] = draw ? pp->p_face : pp->p_over;
X
X# ifdef MONITOR
X	for (newp = Monitor; newp < End_monitor; newp++)
X		check(newp, y, x);
X# endif MONITOR
X
X	for (newp = Player; newp < End_player; newp++) {
X		if (!draw || newp == pp) {
X			check(newp, y, x);
X			continue;
X		}
X		if (newp->p_scan == 0) {
X			newp->p_scan--;
X			showstat(newp);
X		}
X		else if (newp->p_scan > 0) {
X			if (pp->p_cloak < 0)
X				check(newp, y, x);
X			newp->p_scan--;
X		}
X	}
X	if (!draw || pp->p_cloak < 0)
X		return;
X	if (pp->p_cloak-- == 0)
X		showstat(pp);
X}
X
Xmessage(pp, s)
Xregister PLAYER	*pp;
Xchar		*s;
X{
X	cgoto(pp, HEIGHT, 0);
X	outstr(pp, s, strlen(s));
X	ce(pp);
X}
X
X/*
X * translate:
X *	Turn a character into the right direction character if we are
X *	looking at the current player.
X */
Xtranslate(ch)
Xchar	ch;
X{
X	switch (ch) {
X	  case LEFTS:
X		return '<';
X	  case RIGHT:
X		return '>';
X	  case ABOVE:
X		return '^';
X	  case BELOW:
X		return 'v';
X	}
X	return ch;
X}
X
X/*
X * player_sym:
X *	Return the player symbol
X */
Xplayer_sym(pp, y, x)
XPLAYER	*pp;
Xint	y, x;
X{
X	register PLAYER	*npp;
X
X	npp = play_at(y, x);
X	if (npp->p_ident->i_team == ' ')
X		return Maze[y][x];
X#ifdef MONITOR
X	if (pp->p_ident->i_team == '*')
X		return npp->p_ident->i_team;
X#endif
X	if (pp->p_ident->i_team != npp->p_ident->i_team)
X		return Maze[y][x];
X	return pp->p_ident->i_team;
X}
END_OF_FILE
if test 6943 -ne `wc -c <'draw.c'`; then
    echo shar: \"'draw.c'\" unpacked with wrong size!
fi
# end of 'draw.c'
fi
if test -f 'expl.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'expl.c'\"
else
echo shar: Extracting \"'expl.c'\" \(4435 characters\)
sed "s/^X//" >'expl.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/*
X * showexpl:
X *	Show the explosions as they currently are
X */
Xshowexpl(y, x, type)
Xregister int	y, x;
Xchar		type;
X{
X	register PLAYER	*pp;
X	register EXPL	*ep;
X
X	if (y < 0 || y >= HEIGHT)
X		return;
X	if (x < 0 || x >= WIDTH)
X		return;
X	ep = (EXPL *) malloc(sizeof (EXPL));	/* NOSTRICT */
X	ep->e_y = y;
X	ep->e_x = x;
X	ep->e_char = type;
X	ep->e_next = NULL;
X	if (Last_expl == NULL)
X		Expl[0] = ep;
X	else
X		Last_expl->e_next = ep;
X	Last_expl = ep;
X	for (pp = Player; pp < End_player; pp++) {
X		if (pp->p_maze[y][x] == type)
X			continue;
X		pp->p_maze[y][x] = type;
X		cgoto(pp, y, x);
X		outch(pp, type);
X	}
X# ifdef MONITOR
X	for (pp = Monitor; pp < End_monitor; pp++) {
X		if (pp->p_maze[y][x] == type)
X			continue;
X		pp->p_maze[y][x] = type;
X		cgoto(pp, y, x);
X		outch(pp, type);
X	}
X# endif MONITOR
X	switch (Maze[y][x]) {
X	  case WALL1:
X	  case WALL2:
X	  case WALL3:
X# ifdef RANDOM
X	  case DOOR:
X# endif RANDOM
X# ifdef REFLECT
X	  case WALL4:
X	  case WALL5:
X# endif REFLECT
X		if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND)
X			remove_wall(y, x);
X		break;
X	}
X}
X
X/*
X * rollexpl:
X *	Roll the explosions over, so the next one in the list is at the
X *	top
X */
Xrollexpl()
X{
X	register EXPL	*ep;
X	register PLAYER	*pp;
X	register int	y, x;
X	register char	c;
X	register EXPL	*nextep;
X
X	for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) {
X		nextep = ep->e_next;
X		y = ep->e_y;
X		x = ep->e_x;
X		if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND)
X			c = Maze[y][x];
X		else
X			c = SPACE;
X		for (pp = Player; pp < End_player; pp++)
X			if (pp->p_maze[y][x] == ep->e_char) {
X				pp->p_maze[y][x] = c;
X				cgoto(pp, y, x);
X				outch(pp, c);
X			}
X# ifdef MONITOR
X		for (pp = Monitor; pp < End_monitor; pp++)
X			check(pp, y, x);
X# endif MONITOR
X		free((char *) ep);
X	}
X	for (x = EXPLEN - 1; x > 0; x--)
X		Expl[x] = Expl[x - 1];
X	Last_expl = Expl[0] = NULL;
X}
X
X/* There's about 700 walls in the initial maze.  So we pick a number
X * that keeps the maze relatively full. */
X# define MAXREMOVE	40
X
Xstatic	REGEN	removed[MAXREMOVE];
Xstatic	REGEN	*rem_index = removed;
X
X/*
X * remove_wall - add a location where the wall was blown away.
X *		 if there is no space left over, put the a wall at
X *		 the location currently pointed at.
X */
Xremove_wall(y, x)
Xint	y, x;
X{
X	register REGEN	*r;
X# if defined(MONITOR) || defined(FLY)
X	register PLAYER	*pp;
X# endif MONITOR || FLY
X# ifdef	FLY
X	register char	save_char;
X# endif	FLY
X
X	r = rem_index;
X	while (r->r_y != 0) {
X# ifdef FLY
X		switch (Maze[r->r_y][r->r_x]) {
X		  case SPACE:
X		  case LEFTS:
X		  case RIGHT:
X		  case ABOVE:
X		  case BELOW:
X		  case FLYER:
X			save_char = Maze[r->r_y][r->r_x];
X			goto found;
X		}
X# else FLY
X		if (Maze[r->r_y][r->r_x] == SPACE)
X			break;
X# endif FLY
X		if (++r >= &removed[MAXREMOVE])
X			r = removed;
X	}
X
Xfound:
X	if (r->r_y != 0) {
X		/* Slot being used, put back this wall */
X# ifdef FLY
X		if (save_char == SPACE)
X			Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
X		else {
X			pp = play_at(r->r_y, r->r_x);
X			if (pp->p_flying >= 0)
X				pp->p_flying += rand_num(10);
X			else {
X				pp->p_flying = rand_num(20);
X				pp->p_flyx = 2 * rand_num(6) - 5;
X				pp->p_flyy = 2 * rand_num(6) - 5;
X			}
X			pp->p_over = Orig_maze[r->r_y][r->r_x];
X			pp->p_face = FLYER;
X			Maze[r->r_y][r->r_x] = FLYER;
X			showexpl(r->r_y, r->r_x, FLYER);
X		}
X# else FLY
X		Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
X# endif FLY
X# ifdef RANDOM
X		if (rand_num(100) == 0)
X			Maze[r->r_y][r->r_x] = DOOR;
X# endif RANDOM
X# ifdef REFLECT
X		if (rand_num(100) == 0)		/* one percent of the time */
X			Maze[r->r_y][r->r_x] = WALL4;
X# endif REFLECT
X# ifdef MONITOR
X		for (pp = Monitor; pp < End_monitor; pp++)
X			check(pp, r->r_y, r->r_x);
X# endif MONITOR
X	}
X
X	r->r_y = y;
X	r->r_x = x;
X	if (++r >= &removed[MAXREMOVE])
X		rem_index = removed;
X	else
X		rem_index = r;
X
X	Maze[y][x] = SPACE;
X# ifdef MONITOR
X	for (pp = Monitor; pp < End_monitor; pp++)
X		check(pp, y, x);
X# endif MONITOR
X}
X
X/*
X * clearwalls:
X *	Clear out the walls array
X */
Xclearwalls()
X{
X	register REGEN	*rp;
X
X	for (rp = removed; rp < &removed[MAXREMOVE]; rp++)
X		rp->r_y = 0;
X	rem_index = removed;
X}
END_OF_FILE
if test 4435 -ne `wc -c <'expl.c'`; then
    echo shar: \"'expl.c'\" unpacked with wrong size!
fi
# end of 'expl.c'
fi
if test -f 'extern.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'extern.c'\"
else
echo shar: Extracting \"'extern.c'\" \(1942 characters\)
sed "s/^X//" >'extern.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# ifdef MONITOR
XFLAG	Am_monitor = FALSE;		/* current process is a monitor */
X# endif MONITOR
X
Xchar	Buf[BUFSIZ];			/* general scribbling buffer */
Xchar	Maze[HEIGHT][WIDTH2];		/* the maze */
Xchar	Orig_maze[HEIGHT][WIDTH2];	/* the original maze */
X
Xlong	Fds_mask;			/* mask for the file descriptors */
Xint	Have_inp;			/* which file descriptors have input */
Xint	Nplayer = 0;			/* number of players */
Xint	Num_fds;			/* number of maximum file descriptor */
Xint	Socket;				/* main socket */
Xlong	Sock_mask;			/* select mask for main socket */
Xint	See_over[NASCII];		/* lookup table for determining whether
X					 * character represents "transparent"
X					 * item */
X
XBULLET	*Bullets = NULL;		/* linked list of bullets */
X
XEXPL	*Expl[EXPLEN];			/* explosion lists */
XEXPL	*Last_expl;			/* last explosion on Expl[0] */
X
XPLAYER	Player[MAXPL];			/* all the players */
XPLAYER	*End_player = Player;		/* last active player slot */
X# ifdef BOOTS
XPLAYER	Boot[NBOOTS];			/* all the boots */
X# endif BOOTS
XIDENT	*Scores;			/* score cache */
X# ifdef MONITOR
XPLAYER	Monitor[MAXMON];		/* all the monitors */
XPLAYER	*End_monitor = Monitor;		/* last active monitor slot */
X# endif MONITOR
X
X# ifdef VOLCANO
Xint	volcano = 0;			/* Explosion size */
X# endif VOLCANO
X
Xint	shot_req[MAXBOMB]	= {
X				BULREQ, GRENREQ, SATREQ,
X				BOMB7REQ, BOMB9REQ, BOMB11REQ,
X				BOMB13REQ, BOMB15REQ, BOMB17REQ,
X				BOMB19REQ, BOMB21REQ,
X			};
Xint	shot_type[MAXBOMB]	= {
X				SHOT, GRENADE, SATCHEL,
X				BOMB, BOMB, BOMB,
X				BOMB, BOMB, BOMB,
X				BOMB, BOMB,
X			};
X
Xint	slime_req[MAXSLIME]	= {
X				SLIMEREQ, SSLIMEREQ, SLIME2REQ, SLIME3REQ,
X			};
END_OF_FILE
if test 1942 -ne `wc -c <'extern.c'`; then
    echo shar: \"'extern.c'\" unpacked with wrong size!
fi
# end of 'extern.c'
fi
if test -f 'faketalk.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'faketalk.c'\"
else
echo shar: Extracting \"'faketalk.c'\" \(4604 characters\)
sed "s/^X//" >'faketalk.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 "bsd.h"
X
X#if	defined(TALK_43) || defined(TALK_42)
X
X# include	<stdio.h>
X# include	<netdb.h>
X# include	"talk_ctl.h"
X# include	<ctype.h>
X# include	<signal.h>
X# include	<sys/time.h>
Xextern	int	errno;
X
Xextern	char	*index(), *rindex();
X
X# define	TRUE		1
X# define	FALSE		0
X
X/* defines for fake talk message to announce start of game */
X# ifdef TALK_43
X# define	MASQUERADE	"\"Hunt Game\""
X# else
X# define	MASQUERADE	"HuntGame"
X# endif
X# define	RENDEZVOUS	"hunt-players"
X# define	ARGV0		"HUNT-ANNOUNCE"
X
Xextern	char		*my_machine_name;
Xextern	char		*First_arg, *Last_arg;
X
X/*
X *	exorcise - disspell zombies
X */
X
Xexorcise()
X{
X	(void) wait(0);
X}
X
X/*
X *	query the local SMTP daemon to expand the RENDEZVOUS mailing list
X *	and fake a talk request to each address thus found.
X */
X
Xfaketalk()
X{
X	struct	servent		*sp;
X	char			buf[BUFSIZ];
X	FILE			*f;
X	int			service;	/* socket of service */
X	struct	sockaddr_in	des;		/* address of destination */
X	char			*a, *b;
X	extern	char		**environ;
X
X	(void) signal(SIGCHLD, exorcise);
X
X	if (fork() != 0)
X		return;
X
X	(void) signal(SIGINT, SIG_IGN);
X	(void) signal(SIGPIPE, SIG_IGN);
X
X	/*
X	 *	change argv so that a ps shows ARGV0
X	 */
X	*environ = NULL;
X	for (a = First_arg, b = ARGV0; a < Last_arg; a++) {
X		if (*b)
X			*a = *b++;
X		else
X			*a = ' ';
X	}
X
X	/*
X	 *	initialize "talk"
X	 */
X	get_local_name(MASQUERADE);
X	open_ctl();
X
X	/*
X	 *	start fetching addresses
X	 */
X
X	if ((sp = getservbyname("smtp", (char *) NULL)) == NULL) {
X# ifdef LOG
X		syslog(LOG_ERR, "faketalk: smtp protocol not supported\n");
X# else LOG
X		fprintf(stderr, "faketalk: stmp protocol not supported\n");
X# endif LOG
X		_exit(1);
X	}
X
X	bzero((char *) &des, sizeof (des));
X	des.sin_family = AF_INET;
X	des.sin_addr = my_machine_addr;
X	des.sin_port = sp->s_port;
X
X	if ((service = socket(des.sin_family, SOCK_STREAM, 0)) < 0) {
X# ifdef LOG
X		syslog(LOG_ERR, "falktalk:  socket");
X# else LOG
X		perror("falktalk:  socket");
X# endif LOG
X		_exit(-1);
X	}
X
X	if (connect(service, (struct sockaddr *) &des, sizeof(des)) != 0) {
X# ifdef LOG
X		syslog(LOG_ERR, "faketalk:  connect");
X# else LOG
X		perror("faketalk:  connect");
X# endif LOG
X		_exit(-1);
X	}
X	if ((f = fdopen(service, "r")) == NULL) {
X# ifdef LOG
X		syslog(LOG_ERR, "fdopen failed\n");
X# else LOG
X		fprintf(stderr, "fdopen failed\n");
X# endif LOG
X		_exit(-2);
X	}
X
X	(void) fgets(buf, BUFSIZ, f);
X	(void) sprintf(buf, "HELO HuntGame@%s\r\n", my_machine_name);
X	(void) write(service, buf, strlen(buf));
X	(void) fgets(buf, BUFSIZ, f);
X	(void) sprintf(buf, "EXPN %s@%s\r\n", RENDEZVOUS, my_machine_name);
X	(void) write(service, buf, strlen(buf));
X	while (fgets(buf, BUFSIZ, f) != NULL) {
X		char	*s, *t;
X
X		if (buf[0] != '2' || buf[1] != '5' || buf[2] != '0')
X			break;
X		if ((s = index(buf + 4, '<')) == NULL)
X			s = buf + 4, t = buf + strlen(buf) - 1;
X		else {
X			s += 1;
X			if ((t = rindex(s, '>')) == NULL)
X				t = s + strlen(s) - 1;
X			else
X				t -= 1;
X		}
X		while (isspace(*s))
X			s += 1;
X		if (*s == '\\')
X			s += 1;
X		while (isspace(*t))
X			t -= 1;
X		*(t + 1) = '\0';
X		do_announce(s);		/* construct and send talk request */
X		if (buf[3] == ' ')
X			break;
X	}
X	(void) shutdown(service, 2);
X	(void) close(service);
X	_exit(0);
X}
X
X/*
X * The msg.id's for the invitations on the local and remote machines.
X * These are used to delete the invitations.
X */
X
Xdo_announce(s)
X	char	*s;
X{
X	CTL_RESPONSE			response;
X	extern	struct	sockaddr_in	ctl_addr;
X
X	get_remote_name(s);	/* setup his_machine_addr, msg.r_name */
X
X# ifdef TALK_43
X	msg.ctl_addr = *(struct sockaddr *) &ctl_addr;
X	msg.ctl_addr.sa_family = htons(msg.ctl_addr.sa_family);
X# else
X	msg.ctl_addr = ctl_addr;
X	msg.ctl_addr.sin_family = htons(msg.ctl_addr.sin_family);
X# endif
X	msg.id_num = (int) htonl((u_long) -1);	/* an impossible id_num */
X	ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
X	if (response.answer != SUCCESS)
X		return;
X
X	/*
X	 * Have the daemons delete the invitations now that we
X	 * have announced.
X	 */
X
X	/* we don't care if cleanup doesn't make it. */
X	msg.type = DELETE;
X	msg.id_num = (int) htonl(response.id_num);
X	daemon_addr.sin_addr = his_machine_addr;
X	if (sendto(ctl_sockt, (char *) &msg, sizeof (msg), 0,
X			(struct sockaddr *) &daemon_addr, sizeof(daemon_addr))
X			!= sizeof(msg))
X		p_error("send delete remote");
X}
X#else
Xfaketalk()
X{
X	return;
X}
X#endif
END_OF_FILE
if test 4604 -ne `wc -c <'faketalk.c'`; then
    echo shar: \"'faketalk.c'\" unpacked with wrong size!
fi
# end of 'faketalk.c'
fi
if test -f 'get_names.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'get_names.c'\"
else
echo shar: Extracting \"'get_names.c'\" \(3145 characters\)
sed "s/^X//" >'get_names.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# include	<stdio.h>
X# include	"talk_ctl.h"
X# include	<sys/param.h>
X# include	<netdb.h>
X
Xextern	char	*rindex(), *strncpy();
X
Xextern	CTL_MSG	msg;
X
Xstruct	hostent	*gethostbyname();
Xstruct	servent	*getservbyname();
X
Xstatic	char	hostname[MAXHOSTNAMELEN];
Xchar		*my_machine_name;
X
X/*
X * Determine the local user and machine
X */
Xget_local_name(my_name)
X	char	*my_name;
X{
X	struct	hostent	*hp;
X	struct	servent	*sp;
X
X	/* Load these useful values into the standard message header */
X	msg.id_num = 0;
X	(void) strncpy(msg.l_name, my_name, NAME_SIZE);
X	msg.l_name[NAME_SIZE - 1] = '\0';
X	msg.r_tty[0] = '\0';
X	msg.pid = getpid();
X# ifdef TALK_43
X	msg.vers = TALK_VERSION;
X	msg.addr.sa_family = htons(AF_INET);
X	msg.ctl_addr.sa_family = htons(AF_INET);
X# else
X	msg.addr.sin_family = htons(AF_INET);
X	msg.ctl_addr.sin_family = htons(AF_INET);
X# endif
X
X	(void) gethostname(hostname, sizeof (hostname));
X	my_machine_name = hostname;
X	/* look up the address of the local host */
X	hp = gethostbyname(my_machine_name);
X	if (hp == (struct hostent *) 0) {
X		printf("This machine doesn't exist. Boy, am I confused!\n");
X		exit(-1);
X	}
X	bcopy(hp->h_addr, (char *) &my_machine_addr, hp->h_length);
X	/* find the daemon portal */
X# ifdef TALK_43
X	sp = getservbyname("ntalk", "udp");
X# else
X	sp = getservbyname("talk", "udp");
X# endif
X	if (sp == 0) {
X# ifdef LOG
X		syslog(LOG_ERR, "This machine doesn't support talk");
X# else
X		perror("This machine doesn't support talk");
X# endif
X		exit(-1);
X	}
X	daemon_port = sp->s_port;
X}
X
X/*
X * Determine the remote user and machine
X */
Xget_remote_name(his_address)
X	char	*his_address;
X{
X	char		*his_name;
X	char		*his_machine_name;
X	char		*ptr;
X	struct	hostent	*hp;
X
X
X	/* check for, and strip out, the machine name of the target */
X	for (ptr = his_address; *ptr != '\0' && *ptr != '@' && *ptr != ':'
X					&& *ptr != '!' && *ptr != '.'; ptr++)
X		continue;
X	if (*ptr == '\0') {
X		/* this is a local to local talk */
X		his_name = his_address;
X		his_machine_name = my_machine_name;
X	} else {
X		if (*ptr == '@') {
X			/* user@host */
X			his_name = his_address;
X			his_machine_name = ptr + 1;
X		} else {
X			/* host.user or host!user or host:user */
X			his_name = ptr + 1;
X			his_machine_name = his_address;
X		}
X		*ptr = '\0';
X	}
X	/* Load these useful values into the standard message header */
X	(void) strncpy(msg.r_name, his_name, NAME_SIZE);
X	msg.r_name[NAME_SIZE - 1] = '\0';
X
X	/* if he is on the same machine, then simply copy */
X	if (bcmp((char *) &his_machine_name, (char *) &my_machine_name,
X						sizeof(his_machine_name)) == 0)
X		bcopy((char *) &my_machine_addr, (char *) &his_machine_addr,
X						sizeof(his_machine_name));
X	else {
X		/* look up the address of the recipient's machine */
X		hp = gethostbyname(his_machine_name);
X		if (hp == (struct hostent *) 0)
X			return 0;			/* unknown host */
X		bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length);
X	}
X	return 1;
X}
X#endif
END_OF_FILE
if test 3145 -ne `wc -c <'get_names.c'`; then
    echo shar: \"'get_names.c'\" unpacked with wrong size!
fi
# end of 'get_names.c'
fi
if test -f 'hunt.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hunt.h'\"
else
echo shar: Extracting \"'hunt.h'\" \(7879 characters\)
sed "s/^X//" >'hunt.h' <<'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 "bsd.h"
X
X# ifndef BSD
X# define	index		strchr
X# define	rindex		strrchr
X# define	bcopy(s,d,c)	memcpy(d,s,c)
X# endif
X
X# include	<stdio.h>
X# ifdef LOG
X# include	<syslog.h>
X# endif LOG
X# ifndef TERMINFO
X# include	<sgtty.h>
X# else
X# include	<sys/ioctl.h>
X# endif
X# include	<sys/types.h>
X# include	<sys/uio.h>
X# include	<sys/socket.h>
X# ifdef	INTERNET
X# include	<netinet/in.h>
X# include	<netdb.h>
X# ifndef HPUX
X# include	<arpa/inet.h>
X# else
Xextern	char	*inet_ntoa();
X# endif
X# ifdef BROADCAST
X# include	<net/if.h>
X# endif BROADCAST
X# else	INTERNET
X# include	<sys/un.h>
X# endif	INTERNET
X
X# ifdef	INTERNET
X# define	SOCK_FAMILY	AF_INET
X# else	INTERNET
X# define	SOCK_FAMILY	AF_UNIX
X# define	AF_UNIX_HACK		/* 4.2 hack; leaves files around */
X# endif	INTERNET
X
X/*
X * Preprocessor define dependencies
X */
X# if defined(VOLCANO) && !defined(SLIME)
X# define SLIME
X# endif
X# if defined(BOOTS) && !defined(FLY)
X# define FLY
X# endif
X# if !defined(REFLECT) && !defined(RANDOM)
X# define RANDOM
X# endif
X
X/* decrement version number for each change in startup protocol */
X# define	HUNT_VERSION		-1
X
X# define	ADDCH		('a' | 0200)
X# define	MOVE		('m' | 0200)
X# define	REFRESH		('r' | 0200)
X# define	CLRTOEOL	('c' | 0200)
X# define	ENDWIN		('e' | 0200)
X# define	CLEAR		('C' | 0200)
X# define	REDRAW		('R' | 0200)
X# define	LAST_PLAYER	('l' | 0200)
X# define	BELL		('b' | 0200)
X# define	READY		('g' | 0200)
X
X/*
X * Choose MAXPL and MAXMON carefully.  The screen is assumed to be
X * 23 lines high and will only tolerate (MAXPL == 17 && MAXMON == 0)
X * or (MAXPL + MAXMON <= 16).
X */
X# ifdef MONITOR
X# define	MAXPL		15
X# define	MAXMON		1
X# else
X# define	MAXPL		17
X# endif MONITOR
X# define	SHORTLEN	2		/* sizeof (network short) */
X# define	LONGLEN		4		/* sizeof (network long) */
X# define	NAMELEN		20
X# define	MSGLEN		SCREEN_WIDTH
X# define	DECAY		50.0
X
X# define	NASCII		128
X
X# define	WIDTH	51
X# define	WIDTH2	64	/* Next power of 2 >= WIDTH (for fast access) */
X# define	HEIGHT	23
X# define	UBOUND	1
X# define	DBOUND	(HEIGHT - 1)
X# define	LBOUND	1
X# define	RBOUND	(WIDTH - 1)
X
X# define	SCREEN_HEIGHT	24
X# define	SCREEN_WIDTH	80
X# define	SCREEN_WIDTH2	128	/* Next power of 2 >= SCREEN_WIDTH */
X
X# define	STAT_LABEL_COL	60
X# define	STAT_VALUE_COL	74
X# define	STAT_NAME_COL	61
X# define	STAT_SCAN_COL	(STAT_NAME_COL + 5)
X# define	STAT_AMMO_ROW	0
X# define	STAT_GUN_ROW	1
X# define	STAT_DAM_ROW	2
X# define	STAT_KILL_ROW	3
X# define	STAT_PLAY_ROW	5
X# ifdef MONITOR
X# define	STAT_MON_ROW	(STAT_PLAY_ROW + MAXPL + 1)
X# endif MONITOR
X# define	STAT_NAME_LEN	18
X
X# define	DOOR	'#'
X# define	WALL1	'-'
X# define	WALL2	'|'
X# define	WALL3	'+'
X# ifdef REFLECT
X# define	WALL4	'/'
X# define	WALL5	'\\'
X# endif REFLECT
X# define	KNIFE	'K'
X# define	SHOT	':'
X# define	GRENADE	'o'
X# define	SATCHEL	'O'
X# define	BOMB	'@'
X# define	MINE	';'
X# define	GMINE	'g'
X# ifdef	OOZE
X# define	SLIME	'$'
X# endif	OOZE
X# ifdef	VOLCANO
X# define	LAVA	'~'
X# endif	VOLCANO
X# ifdef DRONE
X# define	DSHOT	'?'
X# endif	DRONE
X# ifdef FLY
X# define	FALL	'F'
X# endif FLY
X# ifdef BOOTS
X# define	NBOOTS		2
X# define	BOOT		'b'
X# define	BOOT_PAIR	'B'
X# endif
X# define	SPACE	' '
X
X# define	ABOVE	'i'
X# define	BELOW	'!'
X# define	RIGHT	'}'
X# define	LEFTS	'{'
X# ifdef FLY
X# define	FLYER	'&'
X# define	isplayer(c)	(c == LEFTS || c == RIGHT ||\
X				c == ABOVE || c == BELOW || c == FLYER)
X# else
X# define	isplayer(c)	(c == LEFTS || c == RIGHT ||\
X				c == ABOVE || c == BELOW)
X# endif FLY
X
X# define	NORTH	01
X# define	SOUTH	02
X# define	EAST	010
X# define	WEST	020
X
X# ifndef TRUE
X# define	TRUE	1
X# define	FALSE	0
X# endif TRUE
X# undef CTRL
X# define	CTRL(x)	('x' & 037)
X
X# define	BULSPD		5		/* bullets movement speed */
X# define	ISHOTS		15
X# define	NSHOTS		5
X# define	MAXNCSHOT	2
X# define	MAXDAM		10
X# define	MINDAM		5
X# define	STABDAM		2
X
X# define	BULREQ		1
X# define	GRENREQ		9
X# define	SATREQ		25
X# define	BOMB7REQ	49
X# define	BOMB9REQ	81
X# define	BOMB11REQ	121
X# define	BOMB13REQ	169
X# define	BOMB15REQ	225
X# define	BOMB17REQ	289
X# define	BOMB19REQ	361
X# define	BOMB21REQ	441
X# define	MAXBOMB		11
X# ifdef DRONE
X# define	MINDSHOT	2	/* At least a satchel bomb */
X# endif
Xextern int	shot_req[];
Xextern int	shot_type[];
X# ifdef	OOZE
X# define	SLIME_FACTOR	3
X# define	SLIMEREQ	5
X# define	SSLIMEREQ	10
X# define	SLIME2REQ	15
X# define	SLIME3REQ	20
X# define	MAXSLIME	4
X# define	SLIMESPEED	5
Xextern int	slime_req[];
X# endif	OOZE
X# ifdef	VOLCANO
X# define	LAVASPEED	1
X# endif VOLCANO
X
X# define	CLOAKLEN	20
X# define	SCANLEN		(Nplayer * 20)
X# define	EXPLEN		4
X
X# define	Q_QUIT		0
X# define	Q_CLOAK		1
X# define	Q_FLY		2
X# define	Q_SCAN		3
X# define	Q_MESSAGE	4
X
X# define	C_PLAYER	0
X# define	C_MONITOR	1
X# define	C_MESSAGE	2
X
X# ifdef FLY
X# define	_scan_char(pp)	(((pp)->p_scan < 0) ? ' ' : '*')
X# define	_cloak_char(pp)	(((pp)->p_cloak < 0) ? _scan_char(pp) : '+')
X# define	stat_char(pp)	(((pp)->p_flying < 0) ? _cloak_char(pp) : FLYER)
X# else FLY
X# define	_scan_char(pp)	(((pp)->p_scan < 0) ? ' ' : '*')
X# define	stat_char(pp)	(((pp)->p_cloak < 0) ? _scan_char(pp) : '+')
X# endif FLY
X
Xtypedef int			FLAG;
Xtypedef struct bullet_def	BULLET;
Xtypedef struct expl_def		EXPL;
Xtypedef struct player_def	PLAYER;
Xtypedef struct ident_def	IDENT;
Xtypedef struct regen_def	REGEN;
X# ifdef	INTERNET
Xtypedef struct sockaddr_in	SOCKET;
X# else	INTERNET
Xtypedef struct sockaddr_un	SOCKET;
X# endif	INTERNET
Xtypedef struct sgttyb		TTYB;
X
Xstruct ident_def {
X	char	i_name[NAMELEN];
X	char	i_team;
X	long	i_machine;
X	long	i_uid;
X	float	i_kills;
X	int	i_entries;
X	float	i_score;
X	int	i_absorbed;
X	int	i_faced;
X	int	i_shot;
X	int	i_robbed;
X	int	i_slime;
X	int	i_missed;
X	int	i_ducked;
X	int	i_gkills, i_bkills, i_deaths, i_stillb, i_saved;
X	IDENT	*i_next;
X};
X
Xstruct player_def {
X	IDENT	*p_ident;
X	char	p_over;
X	int	p_face;
X	int	p_undershot;
X# ifdef	FLY
X	int	p_flying;
X	int	p_flyx, p_flyy;
X# endif FLY
X# ifdef	BOOTS
X	int	p_nboots;
X# endif
X	FILE	*p_output;
X	int	p_fd;
X	int	p_mask;
X	int	p_damage;
X	int	p_damcap;
X	int	p_ammo;
X	int	p_ncshot;
X	int	p_scan;
X	int	p_cloak;
X	int	p_x, p_y;
X	int	p_ncount;
X	int	p_nexec;
X	long	p_nchar;
X	char	p_death[MSGLEN];
X	char	p_maze[HEIGHT][WIDTH2];
X	int	p_curx, p_cury;
X	int	p_lastx, p_lasty;
X	char	p_cbuf[BUFSIZ];
X};
X
Xstruct bullet_def {
X	int	b_x, b_y;
X	int	b_face;
X	int	b_charge;
X	char	b_type;
X	char	b_size;
X	char	b_over;
X	PLAYER	*b_owner;
X	IDENT	*b_score;
X	FLAG	b_expl;
X	BULLET	*b_next;
X};
X
Xstruct expl_def {
X	int	e_x, e_y;
X	char	e_char;
X	EXPL	*e_next;
X};
X
Xstruct regen_def {
X	int	r_x, r_y;
X	REGEN	*r_next;
X};
X
X/*
X * external variables
X */
X
Xextern FLAG	Last_player;
X
Xextern char	Buf[BUFSIZ], Maze[HEIGHT][WIDTH2], Orig_maze[HEIGHT][WIDTH2];
X
Xextern char	*Sock_name, *Driver;
X
Xextern int	errno, Have_inp, Nplayer, Num_fds, Socket;
Xextern long	Fds_mask, Sock_mask;
X
X# ifdef INTERNET
Xextern int	Test_port;
X# else INTERNET
Xextern char	*Sock_name;
X# endif INTERNET
X
X# ifdef VOLCANO
Xextern int	volcano;
X# endif	VOLCANO
X
Xextern int	See_over[NASCII];
X
Xextern BULLET	*Bullets;
X
Xextern EXPL	*Expl[EXPLEN];
Xextern EXPL	*Last_expl;
X
Xextern IDENT	*Scores;
X
Xextern PLAYER	Player[MAXPL], *End_player;
X# ifdef BOOTS
Xextern PLAYER	Boot[NBOOTS];
X# endif BOOTS
X
X# ifdef MONITOR
Xextern FLAG	Am_monitor;
Xextern PLAYER	Monitor[MAXMON], *End_monitor;
X# endif MONITOR
X
X# ifdef INTERNET
Xextern char	*Send_message;
X# endif
X
Xextern char	map_key[256];
Xextern FLAG	no_beep;
X
X/*
X * function types
X */
X
Xextern char	*getenv(), *malloc(), *strcpy(), *strncpy();
X
X# ifndef htons
Xextern unsigned short	htons(), ntohs();
X# endif
X# ifndef htonl
Xextern unsigned long	htonl(), ntohl();
X# endif
X
Xextern IDENT	*get_ident();
X
Xextern int	moveshots();
X
Xextern BULLET	*is_bullet(), *create_shot();
X
Xextern PLAYER	*play_at();
END_OF_FILE
if test 7879 -ne `wc -c <'hunt.h'`; then
    echo shar: \"'hunt.h'\" unpacked with wrong size!
fi
# end of 'hunt.h'
fi
if test -f 'huntd.6' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'huntd.6'\"
else
echo shar: Extracting \"'huntd.6'\" \(2218 characters\)
sed "s/^X//" >'huntd.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 HUNTD 6 "21 August 1986"
X.UC 4
X.SH NAME
Xhuntd \- hunt daemon, back-end for hunt game
X.SH SYNOPSIS
X\fB/usr/games/lib/huntd\fP [ \fB\-s\fP ] [ \fB\-p\fP port ]
X.SH DESCRIPTION
X.PP
X.I huntd
Xcontrols the multi-player
X.IR hunt (6)
Xgame.
XWhen it starts up, it tries to notify all members of the
X.I hunt-players
Xmailing list (see
X.IR sendmail (8))
Xby faking a
X.IR talk (1)
Xrequest from user ``Hunt Game''.
X.PP
XThe
X.B \-s
Xoption is for running
X.I huntd
Xforever (server mode).
XThis is similar to running it under the control of
X.I inetd
X(see below),
Xbut it consumes a process table entry when no one is playing.
X.PP
XThe
X.B \-p
Xoption changes the udp port number used to rendezvous with the player
Xprocess and thus allows for private games of hunt.
XThis option turns off the notification of players on the
X.I hunt-players
Xmailing list.
X.SH INETD
X.PP
XTo run
X.I huntd
Xfrom
X.IR inetd ,
Xyou'll need to put the
X.I hunt
Xservice in
X.BR /etc/services :
X.IP
Xhunt 26740/udp		# multi-player/multi-host mazewars
X.LP
Xand add a line in
X.BR /etc/inetd.conf :
X.IP
Xhunt dgram udp wait nobody /usr/games/lib/huntd HUNT
X.LP
Xexcept for Suns which use
X.BR /etc/servers :
X.IP
Xhunt udp /usr/games/lib/huntd
X.LP
XDo not use any of the command line options \(em if you want
X.I inetd
Xto start up
X.I huntd
Xon a private port, change the port listed in
X.BR /etc/services .
X.SH "NETWORK RENDEZVOUS"
XWhen
X.IR hunt (6)
Xstarts up, it broadcasts on the local area net
X(using the broadcast address for each interface) to find a
X.I hunt
Xgame in progress.
XIf a
X.I huntd
Xhears the request, it sends back the port number for the
X.I hunt
Xprocess to connect to.
XOtherwise, the
X.I hunt
Xprocess starts up a
X.I huntd
Xon the local machine and trys to rendezvous with it.
X.SH "SEE ALSO"
Xhunt(6), talk(1), sendmail(8)
X.SH AUTHORS
XConrad Huang, Ken Arnold, and Greg Couch;
X.br
XUniversity of California, San Francisco, Computer Graphics Lab
X.\"SH BUGS
END_OF_FILE
if test 2218 -ne `wc -c <'huntd.6'`; then
    echo shar: \"'huntd.6'\" unpacked with wrong size!
fi
# end of 'huntd.6'
fi
if test -f 'makemaze.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makemaze.c'\"
else
echo shar: Extracting \"'makemaze.c'\" \(3745 characters\)
sed "s/^X//" >'makemaze.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# define	ISCLEAR(y,x)	(Maze[y][x] == SPACE)
X# define	ODD(n)		((n) & 01)
X
Xmakemaze()
X{
X	register char	*sp;
X	register int	y, x;
X
X	/*
X	 * fill maze with walls
X	 */
X	sp = &Maze[0][0];
X	while (sp < &Maze[HEIGHT - 1][WIDTH])
X		*sp++ = DOOR;
X
X	x = rand_num(WIDTH / 2) * 2 + 1;
X	y = rand_num(HEIGHT / 2) * 2 + 1;
X	dig_maze(x, y);
X	remap();
X}
X
X# define	NPERM	24
X# define	NDIR	4
X
Xint	dirs[NPERM][NDIR] = {
X		{0,1,2,3},	{3,0,1,2},	{0,2,3,1},	{0,3,2,1},
X		{1,0,2,3},	{2,3,0,1},	{0,2,1,3},	{2,3,1,0},
X		{1,0,3,2},	{1,2,0,3},	{3,1,2,0},	{2,0,3,1},
X		{1,3,0,2},	{0,3,1,2},	{1,3,2,0},	{2,0,1,3},
X		{0,1,3,2},	{3,1,0,2},	{2,1,0,3},	{1,2,3,0},
X		{2,1,3,0},	{3,0,2,1},	{3,2,0,1},	{3,2,1,0}
X	};
X
Xint	incr[NDIR][2] = {
X		{0, 1}, {1, 0}, {0, -1}, {-1, 0}
X	};
X
Xdig(y, x)
Xint	y, x;
X{
X	register int	*dp;
X	register int	*ip;
X	register int	ny, nx;
X	register int	*endp;
X
X	Maze[y][x] = SPACE;			/* Clear this spot */
X	dp = dirs[rand_num(NPERM)];
X	endp = &dp[NDIR];
X	while (dp < endp) {
X		ip = &incr[*dp++][0];
X		ny = y + *ip++;
X		nx = x + *ip;
X		if (candig(ny, nx))
X			dig(ny, nx);
X	}
X}
X
X/*
X * candig:
X *	Is it legal to clear this spot?
X */
Xcandig(y, x)
Xregister int	y, x;
X{
X	register int	i;
X
X	if (ODD(x) && ODD(y))
X		return FALSE;		/* can't touch ODD spots */
X
X	if (y < UBOUND || y >= DBOUND)
X		return FALSE;		/* Beyond vertical bounds, NO */
X	if (x < LBOUND || x >= RBOUND)
X		return FALSE;		/* Beyond horizontal bounds, NO */
X
X	if (ISCLEAR(y, x))
X		return FALSE;		/* Already clear, NO */
X
X	i = ISCLEAR(y, x + 1);
X	i += ISCLEAR(y, x - 1);
X	if (i > 1)
X		return FALSE;		/* Introduces cycle, NO */
X	i += ISCLEAR(y + 1, x);
X	if (i > 1)
X		return FALSE;		/* Introduces cycle, NO */
X	i += ISCLEAR(y - 1, x);
X	if (i > 1)
X		return FALSE;		/* Introduces cycle, NO */
X
X	return TRUE;			/* OK */
X}
X
Xdig_maze(x, y)
Xint	x, y;
X{
X	register int	tx, ty;
X	register int	i, j;
X	int		order[4];
X#define	MNORTH	0x1
X#define	MSOUTH	0x2
X#define	MEAST	0x4
X#define	MWEST	0x8
X
X	Maze[y][x] = SPACE;
X	order[0] = MNORTH;
X	for (i = 1; i < 4; i++) {
X		j = rand_num(i + 1);
X		order[i] = order[j];
X		order[j] = 0x1 << i;
X	}
X	for (i = 0; i < 4; i++) {
X		switch (order[i]) {
X		  case MNORTH:
X			tx = x;
X			ty = y - 2;
X			break;
X		  case MSOUTH:
X			tx = x;
X			ty = y + 2;
X			break;
X		  case MEAST:
X			tx = x + 2;
X			ty = y;
X			break;
X		  case MWEST:
X			tx = x - 2;
X			ty = y;
X			break;
X		}
X		if (tx < 0 || ty < 0 || tx >= WIDTH || ty >= HEIGHT)
X			continue;
X		if (Maze[ty][tx] == SPACE)
X			continue;
X		Maze[(y + ty) / 2][(x + tx) / 2] = SPACE;
X		dig_maze(tx, ty);
X	}
X}
X
Xremap()
X{
X	register int	y, x;
X	register char	*sp;
X	register int	stat;
X
X	for (y = 0; y < HEIGHT; y++)
X		for (x = 0; x < WIDTH; x++) {
X			sp = &Maze[y][x];
X			if (*sp == SPACE)
X				continue;
X			stat = 0;
X			if (y - 1 >= 0 && Maze[y - 1][x] != SPACE)
X				stat |= NORTH;
X			if (y + 1 < HEIGHT && Maze[y + 1][x] != SPACE)
X				stat |= SOUTH;
X			if (x + 1 < WIDTH && Maze[y][x + 1] != SPACE)
X				stat |= EAST;
X			if (x - 1 >= 0 && Maze[y][x - 1] != SPACE)
X				stat |= WEST;
X			switch (stat) {
X			  case WEST | EAST:
X			  case EAST:
X			  case WEST:
X				*sp = WALL1;
X				break;
X			  case NORTH | SOUTH:
X			  case NORTH:
X			  case SOUTH:
X				*sp = WALL2;
X				break;
X			  case 0:
X# ifdef RANDOM
X				*sp = DOOR;
X# endif RANDOM
X# ifdef REFLECT
X				*sp = rand_num(2) ? WALL4 : WALL5;
X# endif REFLECT
X				break;
X			  default:
X				*sp = WALL3;
X				break;
X			}
X		}
X	bcopy((char *) Maze, (char *) Orig_maze, sizeof Maze);
X}
END_OF_FILE
if test 3745 -ne `wc -c <'makemaze.c'`; then
    echo shar: \"'makemaze.c'\" unpacked with wrong size!
fi
# end of 'makemaze.c'
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
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