Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 19 Mar 1995 21:56:18 -0800 (PST)
From:      Tom Gray - DCA <dcasba@rain.org>
To:        Hackers@FreeBSD.org
Subject:   pacman
Message-ID:  <199503200556.VAA25783@coyote.rain.org>

next in thread | raw e-mail | index | archive | help
Here's a terminal-based pacman for FreeBSD. The source is quite dated
but the code compiles and runs okay.

John

John Poplett
dcasba@pacrain.com

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	.
#	./Makefile
#	./monster.c
#	./pacdefs.h
#	./pacman.c
#	./rain.c
#	./util.c
#	./pacman.6
#
echo c - .
mkdir -p . > /dev/null 2>&1
echo x - ./Makefile
sed 's/^X//' >./Makefile << 'END-of-./Makefile'
X#	@(#)Makefile	8.1 (Berkeley) 5/31/93
X
XPROG=	pacman
XSRCS= pacman.c monster.c util.c
XMAN6=	pacman.6
XCFLAGS += -DNODELAY -DHAVE_TERMIOS -DHAVE_USLEEP
XDPADD= ${LIBTERMLIB}
XLDADD= -ltermlib 
X#HIDEGAME=hidegame
X
X.include <bsd.prog.mk>
END-of-./Makefile
echo x - ./monster.c
sed 's/^X//' >./monster.c << 'END-of-./monster.c'
X#include <stdio.h>
X#include	"pacdefs.h"
X
Xextern char
X	*vs_cm;
X
Xextern char
X	brd[BRDY][BRDX],
X	display[BRDY][BRDX];
X
Xextern int
X	putch();
X
Xextern char
X	*tgoto();
X
Xextern int
X	delay,
X	game,
X	killflg,
X	potion,
X	rounds;
X
Xextern unsigned
X	pscore;
X
Xextern struct pac
X	*pacptr;
X
Xint	rscore[MAXMONSTER];
X
Xstruct pac
X	monst[MAXMONSTER];
X
Xstartmonst()
X{
X	register struct pac *mptr;
X	register int monstnum;
X
X	if (potion == TRUE)
X	{
X		/* don't start if potion active */
X		return;
X	};
X
X	for (mptr = &monst[0], monstnum = 0; monstnum < MAXMONSTER; mptr++, monstnum++)
X	{
X		if (mptr->stat == START)
X		{
X			rscore[monstnum] = 1;
X
X			/* clear home */
X			PLOT(mptr->ypos, mptr->xpos, VACANT);
X
X			/* initialize moving monster */
X			mptr->ypos = MBEGINY;
X			mptr->xpos = MBEGINX;
X			mptr->speed = SLOW;
X			mptr->danger = TRUE;
X			mptr->stat = RUN;
X			PLOT(MBEGINY, MBEGINX, MONSTER);
X
X			/* DRIGHT or DLEFT? */
X			mptr->dirn = getrand(2) + DLEFT;
X			break;
X		};
X	};
X}
X
Xmonster(mnum)
X	int mnum;
X{
X	register int newx,newy;
X	register int tmpx, tmpy;
X	struct pac *mptr;
X	int gmod2;
X
X	mptr = &monst[mnum];
X
X	/* remember monster's current position */
X	tmpx = mptr->xpos;
X	tmpy = mptr->ypos;
X
X	/* if we can, let's move a monster */
X	if (mptr->stat == RUN)
X	{
X		gmod2 = game % 2;
X		/* if a monster was displayed ... */
X		if ((gmod2 == 1) ||
X			((gmod2 == 0) &&
X			(( (rounds - 1) % rscore[mnum]) == 0)))
X		{
X			/* replace display character */
X			PLOT(tmpy, tmpx, display[tmpy][tmpx]);
X		};
X
X		/* get a new direction */
X		mptr->dirn = which(mptr, tmpx, tmpy);
X		switch (mptr->dirn)
X		{
X		case DUP:
X			newy = tmpy + UPINT;
X			newx = tmpx;
X			break;
X
X		case DDOWN:
X			newy = tmpy + DOWNINT;
X			newx = tmpx;
X			break;
X
X		case DLEFT:
X			newx = tmpx + LEFTINT;
X			newy = tmpy;
X			if (newx <= 0)
X				newx = XWRAP;	/* wrap around */
X			break;
X
X		case DRIGHT:
X			newx = tmpx + RIGHTINT;
X			newy = tmpy;
X			if (newx >= XWRAP)
X				newx = 0;	/* wrap around */
X			break;
X		}
X
X		/* use brd to determine if this was a valid direction */
X		switch (brd[newy][newx])
X		{
X		case GOLD:
X		case VACANT:
X		case POTION:
X		case TREASURE:
X		case CHOICE:
X			/* set new position */
X			mptr->xpos = newx;
X			mptr->ypos = newy;
X
X			/* run into a pacman? */
X			if ((newy == pacptr->ypos) &&
X				(newx == pacptr->xpos))
X			{
X				killflg = dokill(mnum);
X			};
X			rscore[mnum] = pscore / 100 + 1;
X			if ((gmod2 == 1) || (killflg == TURKEY) ||
X				( (gmod2 == 0) &&
X				((rounds % rscore[mnum]) == 0)))
X			{
X
X				if (mptr->danger == TRUE)
X				{
X					PLOT(newy, newx, MONSTER);
X				}
X				else if (killflg != GOTONE)
X				{
X					PLOT(newy, newx, RUNNER);
X				};
X			};
X			break;
X
X		default:
X			errgen("bad direction");
X			break;
X		};
X	}
X}
X
Xwhich(mptr, x, y)	/* which directions are available ? */
X	struct pac *mptr;
X	int x, y;
X{
X	register int movecnt;
X	register int submovecnt;
X	register int next;
X	int moves[4];
X	int submoves[4];
X	int nydirn, nxdirn;
X	int goodmoves;
X	int offx, offy;
X	int tmpdirn;
X	char *brdptr;
X
X	/*
X	 * As a general rule: determine the set of all
X	 * possible moves, but select only those moves
X	 * that don't require a monster to backtrack.
X	 */
X	movecnt = 0;
X	brdptr = &(brd[y][x]);
X	if (((tmpdirn = mptr->dirn) != DDOWN) &&
X		((next = *(brdptr + (BRDX * UPINT))) != WALL) &&
X		(next != GATE))
X	{
X		moves[movecnt++] = DUP;
X	};
X	if ((tmpdirn != DUP) &&
X		((next = *(brdptr + (BRDX * DOWNINT))) != WALL) &&
X		(next != GATE))
X	{
X		moves[movecnt++] = DDOWN;
X	};
X	if ((tmpdirn != DRIGHT) &&
X		((next = *(brdptr + LEFTINT)) != WALL) &&
X		(next != GATE))
X	{
X		moves[movecnt++] = DLEFT;
X	};
X	if ((tmpdirn != DLEFT) &&
X		((next = *(brdptr + RIGHTINT)) != WALL) &&
X		(next != GATE))
X	{
X		moves[movecnt++] = DRIGHT;
X	};
X
X	/*
X	 * If the player requested intelligent monsters and
X	 * the player is scoring high ...
X	 */
X	if (((game == 3) || (game == 4)) && (getrand(1000) < pscore))
X	{
X		/* make monsters intelligent */
X		if (pacptr->danger == TRUE)
X		{
X			/*
X			 * Holy Cow!! The pacman is dangerous,
X			 * permit monsters to reverse direction
X			 */
X			switch (tmpdirn)
X			{
X			case DUP:
X				if ((*(brdptr + (BRDX * DOWNINT)) != WALL) &&
X					(*(brdptr + (BRDX * DOWNINT)) != GATE))
X				{
X					moves[movecnt++] = DDOWN;
X				};
X				break;
X
X			case DDOWN:
X				if ((*(brdptr + (BRDX * UPINT)) != WALL) &&
X					(*(brdptr + (BRDX * UPINT)) != GATE))
X				{
X					moves[movecnt++] = DUP;
X				};
X				break;
X
X			case DRIGHT:
X				if ((*(brdptr + LEFTINT) != WALL) &&
X					(*(brdptr + LEFTINT) != GATE))
X				{
X					moves[movecnt++] = DLEFT;
X				};
X				break;
X
X			case DLEFT:
X				if ((*(brdptr + RIGHTINT) != WALL) &&
X					(*(brdptr + RIGHTINT) != GATE))
X				{
X					moves[movecnt++] = DRIGHT;
X				};
X				break;
X			};
X		};
X
X		/* determine the offset from the pacman */
X		offx = x - pacptr->xpos;
X		offy = y - pacptr->ypos;
X		if (offx > 0)
X		{
X			/*need to go left */
X			nxdirn = DLEFT;
X		}
X		else
X		{
X			if (offx < 0)
X			{
X				nxdirn = DRIGHT;
X			}
X			else
X			{
X				/*need to stay here */
X				nxdirn = DNULL;
X			};
X		};
X		if (offy > 0)
X		{
X			/*need to go up */
X			nydirn = DUP;
X		}
X		else
X		{
X			if (offy < 0)
X			{
X				/* need to go down */
X				nydirn = DDOWN;
X			}
X			else
X			{
X				/* need to stay here */
X				nydirn = DNULL;
X			};
X		};
X		goodmoves = 0;
X		for (submovecnt = 0; submovecnt < movecnt; submovecnt++)
X		{
X			if (pacptr->danger == FALSE)
X			{
X				if ((moves[submovecnt] == nydirn) ||
X					(moves[submovecnt] == nxdirn))
X				{
X					submoves[goodmoves++] = moves[submovecnt];
X				};
X			}
X			else
X			{
X				if ((moves[submovecnt] != nydirn) &&
X					(moves[submovecnt] != nxdirn))
X				{
X					submoves[goodmoves++] = moves[submovecnt];
X				};
X			};
X		};
X		if (goodmoves > 0)
X		{
X			return(submoves[getrand(goodmoves)]);
X		};
X	};
X	return(moves[getrand(movecnt)]);
X}
END-of-./monster.c
echo x - ./pacdefs.h
sed 's/^X//' >./pacdefs.h << 'END-of-./pacdefs.h'
X/* dfp #define POS(row,col)    fputs(tgoto(vs_cm,(col),(row)),stdout)*/
X#define POS(row,col)	tputs(tgoto(vs_cm,(col),(row)),1,putch)
X/* dfp */
X#define	PLOT(A,B,C)	POS(A,B);putchar(C)
X#define	SPLOT(A,B,S)	POS(A,B);(void)fprintf(stdout, "%s", S)
X#define TMPF	"/usr/tmp/pacmanXXXXXX"
X#define GAME1	'1'
X#define GAME2	'2'
X#define GAME3	'3'
X#define GAME4	'4'
X
X/* #define MAXSCORE	"/usr/games/lib/paclog" */
X#define MAXSCORE	"/var/games/pacman.scores"
X
X#define MSSAVE	5	/* maximum scores saved per game type */
X#define MGTYPE	4	/* Maximum game types */
X#define	MAXPAC	3	/* maximum number of pacmen to start */
X#define	MAXMONSTER	4	/* max number of monsters */
X#define EMPTY	'E'
X#define FULL	'F'
X#define LEFT	'h'
X#define RIGHT	'l'
X#define	NORTH	'k'	/* means UP, but UP defined in vsinit() */
X#define NNORTH	'w'
X#define	DOWN	'j'
X#define NDOWN	'x'
X#define HALT	' '
X#define DELETE	'\177'
X#define ABORT	'\34'
X#define QUIT	'q'
X#define CNTLS	'\23'
X#define BUF_SIZE	32
X#define	TRUE	1
X#define	FALSE	0
X#define	UPINT	(-1)
X#define	DOWNINT	1
X#define	LEFTINT	(-2)
X#define	RIGHTINT	2
X#define	PACMAN	'@'
X#define	MONSTER	'M'
X#define	RUNNER	'S'
X#define	TREASURE	'$'
X#define	CHOICE		'*'
X#define	GOLD		'+'
X#define	POTION		'X'
X#define	VACANT		' '	/* space */
X#define	WALL		'O'
X#define	GATE		'-'
X#define	START	0
X#define	RUN	1
X#define	FAST	1
X#define	SLOW	0
X#define	PSTARTX	18
X#define	PSTARTY	17
X#define	MSTARTX	16	/* monster starting position */
X#define	MSTARTY	10	/* monster starting position */
X#define	MBEGINX	18	/* monster beginning position */
X#define	MBEGINY	7	/* monster beginning position */
X#define	TRYPOS	13
X#define	TRXPOS	20
X#define	GOTONE	1
X#define	TURKEY	(-1)
X#define	DUP	1
X#define	DDOWN	4
X#define	DRIGHT	3
X#define	DLEFT	2
X#define	DNULL	0
X#define	BRDX	40
X#define	BRDY	23
X#define XWRAP	38
X#define	TREASVAL	20
X#define	KILLSCORE	10
X#define	BEEP		''	/* ctrl-g */
X#define	MSTARTINTVL	10
X#define	POTINTVL	25
X#define GOLDCNT	185
X#define PUP	'^'
X#define PDOWN	'v'
X#define PLEFT	'<'
X#define PRIGHT	'>'
X
Xstruct	pac
X{
X	int	xpos;	/* horizontal position */
X	int	ypos;	/* vertical   position */
X	int	dirn;	/* direction of travel */
X	int	speed;	/* FAST/SLOW	       */
X	int	danger;	/* TRUE if can eat     */
X	int	stat;	/* status		*/
X};
END-of-./pacdefs.h
echo x - ./pacman.c
sed 's/^X//' >./pacman.c << 'END-of-./pacman.c'
X/*
X/* PACMAN  - written by Dave Nixon, AGS Computers Inc., July, 1981.
X/*
X/* Terminal handling for video games taken from aliens
X/*      the original version  of aliens is from 
X/*      Fall 1979                      Cambridge               Jude Miller
X/*
X/* Score keeping modified and general terminal handling (termcap routines
X/* from UCB's ex) added by Rob Coben, BTL, June, 1980.
X/*
X/* If MSG is defined, the program uses the inter-process message facility
X/* of UNIX/TS Augmented to optimize reading the tty while updating the
X/* screen. Otherwise, the child process (reading the tty) writes
X/* a temporary communications file, which the parent (updating the screen)
X/* is constantly seeking to the beginning of and re-reading. (UGH!)
X/* If your system has a non-blocking read (read-without-wait), it should
X/* be implemented, and the child process could be dispensed with entirely.
X*/
X#include <stdio.h>
X#include	"pacdefs.h"
X 
X/*
X * global variables
X */
X
Xextern char
X	*vs_cm;
X
Xextern int
X	putch();
X
Xextern char
X	*tgoto();
X
Xextern char
X	message[];
X
Xextern char
X	initbrd[BRDY][BRDX],
X	display[BRDY][BRDX];
X
Xextern unsigned
X	pscore;
X
Xextern struct pac
X	monst[];
X
Xint	pacsymb = PACMAN,
X	rounds,		/* time keeping mechanism */
X	killflg,
X	delay,
X	potion,
X	goldcnt,		/* no. of gold pieces remaining */
X	potioncnt;
X
Xstruct pac
X	pac;
X
Xstruct pac
X	pacstart =
X{
X	PSTARTX,
X	PSTARTY,
X	DNULL,
X	SLOW,
X	FALSE
X};
X
Xstruct pac
X	*pacptr = &pac;
X
Xmain()
X{
X	register int tmp;		/* temp variables */
X	register int pac_cnt;
X	register int monstcnt;	/* monster number */
X	struct pac *mptr;
X	char gcnt[10];
X
X	init();		/* global init */
X	for (pac_cnt = MAXPAC; pac_cnt > 0; pac_cnt--)
X	{
Xredraw:
X		clr();
X		SPLOT(0, 45, "SCORE: ");
X		SPLOT(21, 45, "gold left = ");
X		(void) sprintf(gcnt, "%6d", goldcnt);
X		SPLOT(21, 57, gcnt);
X		if (potion == TRUE)
X		{
X			SPLOT(3, 45, "COUNTDOWN: ");
X		};
X		pacsymb = PACMAN;
X		killflg = FALSE;
X		(void) sprintf(message, "delay = %6d", delay);
X		SPLOT(22, 45, message);
X		/*
X		 * PLOT maze
X		 */
X		for (tmp = 0; tmp < BRDY; tmp++)
X		{
X			SPLOT(tmp, 0, &(display[tmp][0]));
X		};
X		/* initialize a pacman */
X		pac = pacstart;
X		PLOT(pacptr->ypos, pacptr->xpos, pacsymb);
X		/* display remaining pacmen */
X		for (tmp = 0; tmp < pac_cnt - 1; tmp++)
X		{
X			PLOT(23, (MAXPAC * tmp), PACMAN);
X		};
X		/*
X		 * Init. monsters
X	 	 */
X		for (mptr = &monst[0], monstcnt = 0; monstcnt < MAXMONSTER; mptr++, monstcnt++)
X		{
X			mptr->xpos = MSTARTX + (2 * monstcnt);
X			mptr->ypos = MSTARTY;
X			mptr->speed = SLOW;
X			mptr->dirn = DNULL;
X			mptr->danger = FALSE;
X			mptr->stat = START;
X			PLOT(mptr->ypos, mptr->xpos, MONSTER);
X		};
X		rounds = 0;	/* timing mechanism */
X
X		/* main game loop */
X		do
X		{
X			if (rounds++ % MSTARTINTVL == 0)
X			{
X				startmonst();
X			};
X			pacman();
X			if (killflg == TURKEY)
X				break;
X			for (monstcnt = 0; monstcnt < (MAXMONSTER / 2); monstcnt++)
X			{
X				monster(monstcnt);	/* next monster */
X			};
X			if (killflg == TURKEY)
X				break;
X			if (pacptr->speed == FAST)
X			{
X				pacman();
X				if (killflg == TURKEY)
X					break;
X			};
X			for (monstcnt = (MAXMONSTER / 2); monstcnt < MAXMONSTER; monstcnt++)
X			{
X				monster(monstcnt);	/* next monster */
X			};
X			if (killflg == TURKEY)
X				break;
X			if (potion == TRUE)
X			{
X				(void) sprintf(message, "%2d%c", potioncnt,
X					((potioncnt == 10) ? BEEP : ' '));
X				SPLOT(3, 60, message);
X				if (--potioncnt <= 0)
X				{
X					SPLOT(3, 45, "                        ");
X					potion = FALSE;
X					pacptr->speed = SLOW;
X					pacptr->danger = FALSE;
X					for (monstcnt = 0; monstcnt < MAXMONSTER; monstcnt++)
X					{
X						monst[monstcnt].danger = TRUE;
X					};
X				};
X			};
X			update();	/* score display etc */
X			if (goldcnt <= 0)
X			{
X				reinit();
X				goto redraw;
X			};
X		} while (killflg != TURKEY);
X		SPLOT(5, 45, "YOU ARE BEING EATEN");
X		SPLOT(6, 45, "THIS TAKES ABOUT 2 SECONDS");
X		sleep(2);
X	};
X	SPLOT(8, 45, "THE MONSTERS ALWAYS TRIUMPH");
X	SPLOT(9, 45, "IN THE END!");
X	over();
X}
X
Xpacman()
X{
X	register int sqtype;
X	register int mcnt;
X	register int tmpx, tmpy;
X	int deltat;
X	struct pac *mptr;
X
X	/* pause; wait for the player to hit a key */
X	for (deltat = delay; deltat > 0; deltat--);
X
X	/* get instructions from player, but don't wait */
X	poll(0);
X
X	/* remember current pacman position */
X	tmpx = pacptr->xpos;
X	tmpy = pacptr->ypos;
X
X	/* "eat" any gold */
X	/* update display array to reflect what is on terminal */
X	display[tmpy][tmpx] = VACANT;
X
X	/* what next? */
X	switch (pacptr->dirn)
X	{
X	case DUP:
X		pacsymb = PUP;
X		switch (sqtype = display[tmpy + UPINT][tmpx])
X		{
X		case GOLD:
X		case VACANT:
X		case CHOICE:
X		case POTION:
X		case TREASURE:
X
X			/* erase where the pacman went */
X			PLOT(tmpy, tmpx, VACANT);
X			pacptr->ypos += UPINT;
X			break;
X
X		default:
X			pacptr->dirn = DNULL;
X			break;
X		};
X		break;
X	case DDOWN:
X		pacsymb = PDOWN;
X		switch (sqtype = display[tmpy + DOWNINT][tmpx])
X		{
X		case GOLD:
X		case VACANT:
X		case CHOICE:
X		case POTION:
X		case TREASURE:
X
X			/* erase where the pacman went */
X			PLOT(tmpy, tmpx, VACANT);
X			pacptr->ypos += DOWNINT;
X			break;
X
X		default:
X			pacptr->dirn = DNULL;
X			break;
X		};
X		break;
X	case DLEFT:
X		if(tmpx == 0)
X		{
X			/* erase where the pacman went */
X			PLOT(tmpy, tmpx, VACANT);
X			pacptr->xpos = XWRAP;
X			sqtype = VACANT;
X			break;
X		};
X		pacsymb = PLEFT;
X		switch (sqtype = display[tmpy][tmpx + LEFTINT])
X		{
X		case GOLD:
X		case VACANT:
X		case CHOICE:
X		case POTION:
X		case TREASURE:
X
X			/* erase where the pacman went */
X			PLOT(tmpy, tmpx, VACANT);
X			pacptr->xpos += LEFTINT;
X			break;
X		
X		default:
X			pacptr->dirn = DNULL;
X			break;
X		};
X		break;
X	case DRIGHT:
X		if(tmpx == XWRAP)
X		{
X			/* erase where the pacman went */
X			PLOT(tmpy, tmpx, VACANT);
X			pacptr->xpos = 0;
X			sqtype = VACANT;
X			break;
X		};
X		pacsymb = PRIGHT;
X		switch (sqtype = display[tmpy][tmpx + RIGHTINT])
X		{
X		case GOLD:
X		case VACANT:
X		case CHOICE:
X		case POTION:
X		case TREASURE:
X
X			/* erase where the pacman went */
X			PLOT(tmpy, tmpx, VACANT);
X			pacptr->xpos += RIGHTINT;
X			break;
X
X		default:
X			pacptr->dirn = DNULL;
X			break;
X		};
X		break;
X	};
X
X	/* did the pacman get any points or eat a potion? */
X	switch (sqtype)
X	{
X	case CHOICE:
X	case GOLD:
X		pscore++;
X		goldcnt--;
X		break;
X
X	case TREASURE:
X		pscore += TREASVAL;
X		break;
X
X	case POTION:
X		SPLOT(3, 45, "COUNTDOWN: ");
X		potion = TRUE;
X		potioncnt = POTINTVL;
X		pacptr->speed = FAST;
X		pacptr->danger = TRUE;
X
X		/* slow down monsters and make them harmless */
X		mptr = &monst[0];
X		for (mcnt = 0; mcnt < MAXMONSTER; mcnt++)
X		{
X			if (mptr->stat == RUN)
X			{
X				mptr->speed = SLOW;
X				mptr->danger = FALSE;
X			};
X			mptr++;
X		};
X		break;
X	};
X
X	/* did the pacman run into a monster? */
X	for (mptr = &monst[0], mcnt = 0; mcnt < MAXMONSTER; mptr++, mcnt++)
X	{
X		if ((mptr->xpos == pacptr->xpos) &&
X			(mptr->ypos == pacptr->ypos))
X		{
X
X			killflg = dokill(mcnt);
X		}
X		else
X		{
X			killflg = FALSE;
X		};
X	};
X	if (killflg != TURKEY)
X	{
X		PLOT(pacptr->ypos, pacptr->xpos, pacsymb);
X	};
X}
END-of-./pacman.c
echo x - ./rain.c
sed 's/^X//' >./rain.c << 'END-of-./rain.c'
X
Xstatic char sccsid[] = "	rain.c	4.1	82/10/24	";
X
X#include <stdio.h>
X#include <sgtty.h>
X#include <signal.h>
X/* rain 11/3/1980 EPS/CITHEP */
X/* cc rain.c -o rain -O -ltermlib */
X#define cursor(col,row) tputs(tgoto(CM,col,row),1,outc)
Xoutc(c)
X{
X	putchar(c);
X}
Xextern char *UP;
Xextern short ospeed;
Xstruct sgttyb old_tty;
Xchar *LL, *TE, *TI;
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X    extern fputchar();
X    char *malloc();
X    char *getenv();
X    char *tgetstr(), *tgoto();
X    float ranf();
X    int onsig();
X    register int x, y, j;
X    static int xpos[5], ypos[5];
X    register char *CM, *BC, *DN, *ND;
X    char *tcp;
X    register char *term;
X    char tcb[100];
X    struct sgttyb sg;
X    setbuf(stdout,malloc(BUFSIZ));
X    if (!(term=getenv("TERM"))) {
X	fprintf(stderr,"%s: TERM: parameter not set\n",*argv);
X	exit(1);
X    }
X    if (tgetent(malloc(1024),term)<=0) {
X	fprintf(stderr,"%s: %s: unknown terminal type\n",*argv,term);
X	exit(1);
X    }
X    tcp=tcb;
X    if (!(CM=tgetstr("cm",&tcp))) {
X	fprintf(stderr,"%s: terminal not capable of cursor motion\n",*argv);
X	exit(1);
X    }
X    if (!(BC=tgetstr("bc",&tcp))) BC="\b";
X    if (!(DN=tgetstr("dn",&tcp))) DN="\n";
X    if (!(ND=tgetstr("nd",&tcp))) ND=" ";
X    TE=tgetstr("te",&tcp);
X    TI=tgetstr("ti",&tcp);
X    UP=tgetstr("up",&tcp);
X    if (!(LL=tgetstr("ll",&tcp))) strcpy(LL=malloc(10),tgoto(CM,0,23));
X    gtty(1, &sg);
X    ospeed=sg.sg_ospeed;
X    for (j=SIGHUP;j<=SIGTERM;j++)
X	if (signal(j,SIG_IGN)!=SIG_IGN) signal(j,onsig);
X    gtty(1, &old_tty);	/* save tty bits for exit */
X    gtty(1, &sg);
X    sg.sg_flags&=~(CRMOD|ECHO);
X    stty(1, &sg);
X    if (TI) fputs(TI,stdout);
X    tputs(tgetstr("cl",&tcp),1,fputchar);
X    fflush(stdout);
X    for (j=5;--j>=0;) {
X	xpos[j]=(int)(76.*ranf())+2;
X	ypos[j]=(int)(20.*ranf())+2;
X    }
X    for (j=0;;) {
X	x=(int)(76.*ranf())+2;
X	y=(int)(20.*ranf())+2;
X	cursor(x,y); fputchar('.');
X	cursor(xpos[j],ypos[j]); fputchar('o');
X	if (j==0) j=4; else --j;
X	cursor(xpos[j],ypos[j]); fputchar('O');
X	if (j==0) j=4; else --j;
X	cursor(xpos[j],ypos[j]-1);
X	fputchar('-');
X	fputs(DN,stdout); fputs(BC,stdout); fputs(BC,stdout);
X	fputs("|.|",stdout);
X	fputs(DN,stdout); fputs(BC,stdout); fputs(BC,stdout);
X	fputchar('-');
X	if (j==0) j=4; else --j;
X	cursor(xpos[j],ypos[j]-2); fputchar('-');
X	fputs(DN,stdout); fputs(BC,stdout); fputs(BC,stdout);
X	fputs("/ \\",stdout);
X	cursor(xpos[j]-2,ypos[j]);
X	fputs("| O |",stdout);
X	cursor(xpos[j]-1,ypos[j]+1);
X	fputs("\\ /",stdout);
X	fputs(DN,stdout); fputs(BC,stdout); fputs(BC,stdout);
X	fputchar('-');
X	if (j==0) j=4; else --j;
X	cursor(xpos[j],ypos[j]-2); fputchar(' ');
X	fputs(DN,stdout); fputs(BC,stdout); fputs(BC,stdout);
X	fputchar(' '); fputs(ND,stdout); fputchar(' ');
X	cursor(xpos[j]-2,ypos[j]);
X	fputchar(' '); fputs(ND,stdout); fputchar(' ');
X	fputs(ND,stdout); fputchar(' ');
X	cursor(xpos[j]-1,ypos[j]+1);
X	fputchar(' '); fputs(ND,stdout); fputchar(' ');
X	fputs(DN,stdout); fputs(BC,stdout); fputs(BC,stdout);
X	fputchar(' ');
X	xpos[j]=x; ypos[j]=y;
X	fflush(stdout);
X    }
X}
Xonsig(n)
Xint n;
X{
X    struct sgttyb sg;
X    fputs(LL, stdout);
X    if (TE) fputs(TE, stdout);
X    fflush(stdout);
X    stty(1, &old_tty);
X    kill(getpid(),n);
X    _exit(0);
X}
Xfputchar(c)
Xchar c;
X{
X    putchar(c);
X}
Xfloat ranf() {
X    return((float)rand()/2147483647.);
X}
END-of-./rain.c
echo x - ./util.c
sed 's/^X//' >./util.c << 'END-of-./util.c'
X#include <stdio.h>
X#include <signal.h>
X#ifdef HAVE_TERMIOS
X#include <fcntl.h>
X#include <termios.h>
X#else
X#include <sgtty.h>
X#endif
X#include <pwd.h>
X#include "pacdefs.h"
X
X#ifndef O_RDWR
X#define	O_RDWR	2
X#define	O_CREAT 0
X#define	O_RDONLY 0
X#define	O_NDELAY 0
X#endif
X
X#if !HAVE_SIGSET
X#define sigset signal
X#endif
X
Xextern char
X	*BC,
X	*UP;
X
Xextern int
X	putch();
X
Xextern char
X	*tgoto(),
X	*mktemp();
X
Xextern int
X	delay,
X	errno,
X	goldcnt;
X
Xextern long
X	time();
X
Xextern void 
X	leave();
X
Xextern struct pac
X	*pacptr;
X
Xextern struct pac
X	monst[];
X
X#ifndef MSG
Xint	comfile;
X#else
Xstruct mstruct
X{
X	int     frompid;
X	int     mtype;
X};
X
X#endif
X
X#ifndef NODELAY
X
X#ifndef MSG
Xchar	*fnam;
X#endif
X
X#endif
X
X/*
X * initbrd is used to re-initialize the display
X * array once a new game is started.
X */
Xchar	initbrd[BRDY][BRDX] =
X{
X"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
X"O + + + * + + + + OOO + + + + * + + + O",
X"O X OOO + OOOOO + OOO + OOOOO + OOO X O",
X"O * + + * + * + * + + * + * + * + + * O",
X"O + OOO + O + OOOOOOOOOOO + O + OOO + O",
X"O + + + * O + + + OOO + + + O * + + + O",
X"OOOOOOO + OOOOO + OOO + OOOOO + OOOOOOO",
X"      O + O + + * + + * + + O + O      ",
X"      O + O + OOO - - OOO + O + O      ",
X"OOOOOOO + O + O         O + O + OOOOOOO",
X"        * + * O         O * + *        ",
X"OOOOOOO + O + O         O + O + OOOOOOO",
X"      O + O + OOOOOOOOOOO + O + O      ",
X"      O + O * + + + + + + * O + O      ",
X"OOOOOOO + O + OOOOOOOOOOO + O + OOOOOOO",
X"O + + + * + * + + OOO + + * + * + + + O",
X"O X OOO + OOOOO + OOO + OOOOO + OOO X O",
X"O + + O * + * + * + + * + * + * O + + O",
X"OOO + O + O + OOOOOOOOOOO + O + O + OOO",
X"O + * + + O + + + OOO + + + O + + * + O",
X"O + OOOOOOOOOOO + OOO + OOOOOOOOOOO + O",
X"O + + + + + + + * + + * + + + + + + + O",
X"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
X};
X
X/*
X * brd is kept for historical reasons.
X * It should only be used in the routine "which"
X * to determine the next move for a monster or
X * in the routine "monster" to determine if it
X * was a valid move. Admittedly this is redundant
X * and could be replaced by initbrd, but it is kept
X * so that someday additional intelligence or
X * optimization could be added to the choice of
X * the monster's next move. Hence, note the symbol
X * CHOICE at most points that a move decision
X * logically HAS to be made.
X */
Xchar	brd[BRDY][BRDX] =
X{
X"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
X"O + + + * + + + + OOO + + + + * + + + O",
X"O X OOO + OOOOO + OOO + OOOOO + OOO X O",
X"O * + + * + * + * + + * + * + * + + * O",
X"O + OOO + O + OOOOOOOOOOO + O + OOO + O",
X"O + + + * O + + + OOO + + + O * + + + O",
X"OOOOOOO + OOOOO + OOO + OOOOO + OOOOOOO",
X"      O + O + + * + + * + + O + O      ",
X"      O + O + OOO - - OOO + O + O      ",
X"OOOOOOO + O + O         O + O + OOOOOOO",
X"        * + * O         O * + *        ",
X"OOOOOOO + O + O         O + O + OOOOOOO",
X"      O + O + OOOOOOOOOOO + O + O      ",
X"      O + O * + + + + + + * O + O      ",
X"OOOOOOO + O + OOOOOOOOOOO + O + OOOOOOO",
X"O + + + * + * + + OOO + + * + * + + + O",
X"O X OOO + OOOOO + OOO + OOOOO + OOO X O",
X"O + + O * + * + * + + * + * + * O + + O",
X"OOO + O + O + OOOOOOOOOOO + O + O + OOO",
X"O + * + + O + + + OOO + + + O + + * + O",
X"O + OOOOOOOOOOO + OOO + OOOOOOOOOOO + O",
X"O + + + + + + + * + + * + + + + + + + O",
X"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
X};
X
X/*
X * display reflects the screen on the player's
X * terminal at any point in time.
X */
Xchar	display[BRDY][BRDX] =
X{
X"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
X"O + + + + + + + + OOO + + + + + + + + O",
X"O X OOO + OOOOO + OOO + OOOOO + OOO X O",
X"O + + + + + + + + + + + + + + + + + + O",
X"O + OOO + O + OOOOOOOOOOO + O + OOO + O",
X"O + + + + O + + + OOO + + + O + + + + O",
X"OOOOOOO + OOOOO + OOO + OOOOO + OOOOOOO",
X"      O + O + + + + + + + + O + O      ",
X"      O + O + OOO - - OOO + O + O      ",
X"OOOOOOO + O + O         O + O + OOOOOOO",
X"        + + + O         O + + +        ",
X"OOOOOOO + O + O         O + O + OOOOOOO",
X"      O + O + OOOOOOOOOOO + O + O      ",
X"      O + O + + + + + + + + O + O      ",
X"OOOOOOO + O + OOOOOOOOOOO + O + OOOOOOO",
X"O + + + + + + + + OOO + + + + + + + + O",
X"O X OOO + OOOOO + OOO + OOOOO + OOO X O",
X"O + + O + + + + + + + + + + + + O + + O",
X"OOO + O + O + OOOOOOOOOOO + O + O + OOO",
X"O + + + + O + + + OOO + + + O + + + + O",
X"O + OOOOOOOOOOO + OOO + OOOOOOOOOOO + O",
X"O + + + + + + + + + + + + + + + + + + O",
X"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
X};
X
X/* terminal type from environment and /etc/termcap ala ex & vi */
Xchar    *vs_cl  = "",           /* clear screen sequence */
X	*vs_cm  = "",           /* cursor positioning sequence */
X	*vs_vb  = "";
X
Xchar	combuf[BUFSIZ],
X	message[81],	/* temporary message buffer */
X	inbuf[2];
X
Xint	ppid,
X	cpid,
X	game,
X	killcnt = 0,
X	vs_rows,
X	vs_cols;
X
Xunsigned
X	pscore;
X
Xlong	timein;
X
X#ifdef HAVE_TERMIOS
Xstruct termios
X	savetty,
X	newtty;
X#else
Xstruct sgttyb
X	savetty, newtty;
X#endif
X
Xstruct uscore
X{
X	unsigned score;	/* same type as pscore */
X	int uid;	/* uid of player */
X};
X
Xstruct scorebrd
X{
X	struct uscore entry[MSSAVE];
X} scoresave[MGTYPE] = 
X	{
X		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
X		0, 0, 0, 0, 0, 0, 0, 0, 0, 0
X	};
X
Xvoid nap (int naptime)
X{
X#ifdef HAVE_USLEEP
X	usleep (naptime * 18000);
X#else
X	register int i = naptime * 5000; 
X	while (i--);
X#endif
X}
X
Xupdate()
X{
X	char	str[10];
X
X	(void) sprintf(str, "%6d", pscore);
X	SPLOT(0, 52, str);
X	(void) sprintf(str, "%6d", goldcnt);
X	SPLOT(21, 57, str);
X}
X
Xreinit()
X{
X	register int locx, locy;
X	register char tmp;
X
X	for (locy = 0; locy < BRDY; locy++)
X	{
X		for (locx = 0; locx < BRDX; locx++)
X		{
X			tmp = initbrd[locy][locx];
X			brd[locy][locx] = tmp;
X			if ((display[locy][locx] = tmp) == CHOICE)
X			{
X				display[locy][locx] = GOLD;
X			};
X		};
X	};
X	goldcnt = GOLDCNT;
X	delay -= (delay / 10);	/* hot it up */
X}
X
Xerrgen(string)
Xchar	*string;
X{
X	SPLOT(23,45,string);
X}
X
Xdokill(mnum)
X	int mnum;
X{
X	register struct pac *mptr;
X
X	PLOT(0, 0, BEEP);
X	if (pacptr->danger == TRUE)
X	{
X		if (++killcnt == MAXMONSTER)
X		{
X			if (display[TRYPOS][TRXPOS] == GOLD)
X			{
X				goldcnt--;
X			};
X			display[TRYPOS][TRXPOS] = TREASURE;
X			PLOT(TRYPOS, TRXPOS, TREASURE);
X			killcnt = 0;
X		};
X		SPLOT(5, 45, "MONSTERS KILLED: ");
X		(void) sprintf(message, "%1d", killcnt);
X		SPLOT(5, 62, message);
X		mptr = (&monst[mnum]);
X		mptr->ypos = MSTARTY;
X		mptr->xpos = MSTARTX + (2 * mnum);
X		mptr->stat = START;
X		PLOT(mptr->ypos, mptr->xpos, MONSTER);
X		pscore += KILLSCORE;
X		return(GOTONE);
X	};
X	return(TURKEY);
X}
X
X/*
X/* clr -- issues an escape sequence to clear the display
X*/
X
Xclr()
X{
X	/*						... kre
X	(void) fprintf(stdout, "%s", vs_cl);
X	fflush(stdout);
X	nap(2);
X	*/
X	tputs(vs_cl, vs_rows, putch);
X	fflush(stdout);
X}
X
X/*
X *	display initial instructions
X */
X
Xinstruct()
X{
X	clr();
X	POS(0, 0);
X	(void) fprintf(stdout, "Attention: you are in a dungeon, being chased by monsters!\r\n\n");
X	(void) fprintf(stdout, "There are gold coins scattered uniformly in the dungeon, marked by \"+\".\r\n");
X	(void) fprintf(stdout, "One magic potion is available at each spot marked \"X\". Each potion will\r\n");
X	(void) fprintf(stdout, "enable you to kill monsters by touch for a limited duration. It will also\r\n");
X	(void) fprintf(stdout, "scare them away. When you kill a monster it is regenerated, but this takes\r\n");
X	(void) fprintf(stdout, "time. You can also regenerate yourself %d times. Killing all the monsters\r\n", MAXPAC);
X	(void) fprintf(stdout, "results in further treasure appearing magically somewhere in the dungeon,\r\n");
X	(void) fprintf(stdout, "marked by \"$\". There is a magic tunnel connecting the center left and\r\n");
X	(void) fprintf(stdout, "center right parts of the dungeon. The monsters know about it!\r\n\n");
X	(void) fprintf(stdout, "        Type:   h       to move left\r\n");
X	(void) fprintf(stdout, "                l       to move right\r\n");
X	(void) fprintf(stdout, "                k or w  to move up\r\n");
X	(void) fprintf(stdout, "                j or x  to move down\r\n");
X	(void) fprintf(stdout, "                <space> to halt \r\n");
X	(void) fprintf(stdout, "                q       to quit\r\n\n");
X	(void) fprintf(stdout, "        Type:   1       normal game\r\n");
X	(void) fprintf(stdout, "                2       blinking monsters\r\n");
X	(void) fprintf(stdout, "                3       intelligent monsters\r\n");
X	(void) fprintf(stdout, "                4       blinking intelligent monsters\r\n");
X}
X
X/*
X * over -- game over processing
X */
X
Xover()
X{
X	register int i;
X	register int line;
X	int scorefile = 0;
X	struct passwd *getpwuid(), *p;
X
X	fflush(stdout);
X	sleep(5);	/* for slow readers */
X	poll(0);	/* flush and discard input from player */
X	clr();
X	/* high score to date processing */
X	if (game != 0)
X	{
X		line = 7;
X		POS(line++, 20);
X		(void) fprintf(stdout, " ___________________________ ");
X		POS(line++, 20);
X		(void) fprintf(stdout, "|                           |");
X		POS(line++, 20);
X		(void) fprintf(stdout, "| G A M E   O V E R         |");
X		POS(line++, 20);
X		(void) fprintf(stdout, "|                           |");
X		POS(line++, 20);
X		(void) fprintf(stdout, "| Game type: %1d              |",game);
X		if ((scorefile = open(MAXSCORE, O_RDWR | O_CREAT, 0666)) != -1)
X		{
X			read(scorefile, (char *)scoresave, sizeof(scoresave));
X			for (i = MSSAVE - 1; i >= 0; i--) {
X				if (scoresave[game - 1].entry[i].score < pscore)
X				{
X					if (i < MSSAVE - 1)
X					{
X						scoresave[game - 1].entry[i + 1].score =
X							scoresave[game - 1].entry[i].score;
X						scoresave[game - 1].entry[i + 1].uid =
X							scoresave[game - 1].entry[i].uid;
X					};
X					scoresave[game - 1].entry[i].score = pscore;
X					scoresave[game - 1].entry[i].uid = getuid();
X				};
X			};
X			lseek(scorefile, 0l, 0);
X			write(scorefile, (char *)scoresave, sizeof(scoresave));
X			close(scorefile);
X			POS(line++, 20);
X			(void) fprintf(stdout, "| High Scores to date:      |");
X			for (i = 0; i < MSSAVE; i++)
X			{
X				setpwent();
X				p = getpwuid(scoresave[game - 1].entry[i].uid);
X				POS(line++, 20);
X				(void) fprintf(stdout, "| Player : %-8s  %5u  |", p->pw_name,
X					scoresave[game - 1].entry[i].score);
X			};
X		}
X		else
X		{
X			POS(line++, 20);
X			(void) fprintf(stdout, "|                           |");
X			POS(line++, 20);
X			(void) fprintf(stdout, "| Please create a 'paclog'  |");
X			POS(line++, 20);
X			(void) fprintf(stdout, "| file. See 'MAXSCORE' in   |");
X			POS(line++, 20);
X			(void) fprintf(stdout, "| 'pacdefs.h'.              |");
X		};
X		POS(line++, 20);
X		(void) fprintf(stdout, "|                           |");
X		POS(line++, 20);
X		(void) fprintf(stdout, "| Your score: %-5u         |", pscore);
X		POS(line, 20);
X		(void) fprintf(stdout, "|___________________________|");
X	};
X	leave();
X}
X
X/*
X * leave -- flush buffers,kill the Child, reset tty, and delete tempfile
X */
X
Xvoid leave()
X{
X	POS(23, 0);
X	(void) fflush(stdout);
X	sleep(1);
X
X#ifndef NODELAY
X	kill(cpid, SIGKILL);
X#endif
X
X#ifdef HAVE_TERMIOS
X	tcsetattr (0, TCSANOW, &savetty);
X#else
X	ioctl(0, TIOCSETP, &savetty);
X#endif
X
X#ifndef NODELAY
X
X#ifndef MSG
X	close(comfile);
X	unlink(fnam);
X#endif
X
X#endif
X	exit(0);
X}
X
X/*
X * init -- does global initialization and spawns a child process to read
X *      the input terminal.
X */
X
Xinit()
X{
X	register int tries = 0;
X	static int lastchar = DELETE;
X	extern short ospeed;		/* baud rate for crt (for tputs()) */
X
X	errno = 0;
X	(void) time(&timein);	/* get start time */
X	srand((unsigned)timein);	/* start rand randomly */
X	/*
X	 * verify CRT and get proper cursor control sequence.
X	 */
X
X#ifdef NODELAY
X
X#ifndef BELL30
X	close(0);
X	if (open("/dev/tty", O_RDONLY | O_NDELAY) != 0)
X	{
X		perror("Unable to open /dev/tty");
X		exit(1);
X	};
X#endif
X
X#endif
X	vsinit();
X	/*
X	 * setup raw mode, no echo
X	 */
X#ifdef	SIGTSTP
X	sigset(SIGTSTP, SIG_IGN);	/* ignore ^Z (too hard just now) .. kre */
X#endif
X#ifdef SIG_HOLD
X	sigset(SIGINT, SIG_HOLD);	/* keep ints till we are ready .. kre */
X#endif
X#ifdef HAVE_TERMIOS
X	tcgetattr (0, &savetty);
X	newtty = savetty;
X	if (savetty.c_ospeed >= B9600)
X		delay = 1000 * (getrand(10) + 5);
X	else
X		delay = 1000;
X	ospeed = savetty.c_ospeed; /* for tputs() */
X#ifdef NODELAY
X	newtty.c_cc[VTIME] = 7;
X	newtty.c_cc[VMIN] = 0;
X#else
X	newtty.c_cc[VMIN] = 1;
X#endif
X	newtty.c_iflag = 0;
X	newtty.c_oflag &= ~OPOST;
X	newtty.c_cflag &= ~(PARENB | CSIZE);
X	newtty.c_cflag |= CS8;
X	/* newtty.c_lflag &= ~(ECHO | ECHOE | ISIG | ICANON); */
X	newtty.c_lflag &= ~(ECHO | ECHOE | ICANON); 
X	tcsetattr (0, TCSANOW, &newtty);
X#else
X	ioctl(0, TIOCGETP, &savetty);
X	newtty = savetty;
X	if (savetty.sg_ospeed >= B9600)
X		delay = 1000 * (getrand(10) + 5);
X	else
X		delay = 1000;
X	ospeed = savetty.sg_ospeed;		/* for tputs() */
X	newtty.sg_flags |= CBREAK;
X	newtty.sg_flags &= ~ECHO;
X	ioctl(0, TIOCSETP, &newtty);
X#endif
X
X	/*
X	 * set up communications
X	 */
X
X#ifndef NODELAY
X
X#ifndef MSG
X	fnam = mktemp(TMPF);
X	if ((comfile = creat(fnam, 0666)) == -1)
X	{
X		(void) sprintf(message, "Cannot create %s", fnam);
X		perror(message);
X		leave();
X	};
X	/*
X	 * initialize semaphore
X	 */
X	lseek(comfile, 0l, 0);
X	combuf[1] = EMPTY;
X	write(comfile, combuf, 2);
X	close(comfile);
X#endif
X#endif
X
X#ifndef NODELAY
X	/*
X	 * fork off a child to read the input
X	 */
X	ppid = getpid();
X	if ((cpid = fork()) == 0)
X	{
X#ifndef MSG
X		comfile = open(fnam, O_RDWR);
X#endif
X		for (;;)
X		{
X			read(0, inbuf, 1);
X			if (lastchar != inbuf[0])
X			{
X#ifdef MSG
X				if (inbuf[0] == DELETE || inbuf[0] == ABORT)
X					leave();
X				send(inbuf, 1, ppid, 64);
X#else
X				lseek(comfile, 0l, 0);
X				read(comfile, combuf, 2);
X				if (combuf[1] == EMPTY)
X				{
X					lseek(comfile, 0l, 0);
X					combuf[0] = inbuf[0];
X					combuf[1] = FULL;
X					write(comfile, combuf, 2);
X				};
X#endif
X			};
X			lastchar = DELETE;
X		};
X	};
X
X#ifndef MSG
X	comfile = open(fnam, O_RDWR);
X#else
X	msgenab();
X#endif
X
X#endif
X	sigset(SIGINT, leave);
X	/*
X	 * New game starts here
X	 */
X	game = 0;
X	instruct();
X	while ((game == 0) && (tries++ < 300))
X	{
X		poll(1);
X	};
X	if (tries >= 300)
X	{
X		/* I give up. Let's call it quits. */
X		leave();
X	};
X	goldcnt = GOLDCNT;
X	pscore = 0;
X	clr();
X}
X
X/*
X * poll -- read characters sent by input subprocess and set global flags
X */
X
Xpoll(sltime)
X{
X	int stop;
X	register int charcnt;
X	int junk;
X
X#ifndef NODELAY
X#ifdef MSG
X	struct mstruct msghead;
X#endif
X#endif
X
X	stop = 0;
Xreadin:
X
X#ifdef NODELAY
X	fflush(stdout);
X	charcnt = 0;
X	nap(12);
X#ifdef FIONREAD
X	ioctl(0, FIONREAD, &junk);
X	if (junk)
X#endif
X		charcnt = read(0, combuf, 1);
X	switch (charcnt)
X	{
X
X	case 0:
X		combuf[1] = EMPTY;
X		break;
X
X	case -1:
X		errgen("READ ERROR IN POLL");
X		abort();
X
X	default:
X		combuf[0] = combuf[charcnt-1];
X		combuf[1] = FULL;
X		break;
X	};
X#else
X
X#ifdef MSG
X	combuf[1] = (recv(combuf, 1, &msghead, 0) == -1) ? EMPTY : FULL;
X#else
X	lseek(comfile, 0l, 0);	/* rewind */
X	read(comfile, combuf, 2);	/* read 2 chars */
X#endif
X
X#endif
X	if (combuf[1] == EMPTY) 
X	{
X#ifndef BELL30
X
X#ifndef NODELAY
X		if (sltime > 0)
X		{
X			sleep(sltime);
X		};
X#endif
X
X#endif
X		if (stop)
X		{
X			goto readin;
X		};
X		return;
X	};
X	combuf[1] = EMPTY;
X
X#ifndef NODELAY
X
X#ifndef MSG
X	lseek(comfile, 0l, 0);	/* another rewind */
X	write(comfile, combuf, 2);
X#endif
X#endif
X
X	switch(combuf[0] & 0177)
X	{
X	case LEFT:
X		pacptr->dirn = DLEFT;
X		break;
X
X	case RIGHT:
X		pacptr->dirn = DRIGHT;
X		break;
X
X	case NORTH:
X	case NNORTH:
X		pacptr->dirn = DUP;
X		break;
X
X	case DOWN:
X	case NDOWN:
X		pacptr->dirn = DDOWN;
X		break;
X
X	case HALT:
X		pacptr->dirn = DNULL;
X		break;
X
X	case ABORT:
X	case DELETE:
X	case QUIT:
X		over();
X		break;
X
X	case CNTLS:
X		stop = 1;
X		goto readin;
X
X	case GAME1:
X		game = 1;
X		break;
X
X	case GAME2:
X		game = 2;
X		break;
X
X	case GAME3:
X		game = 3;
X		break;
X
X	case GAME4:
X		game = 4;
X		break;
X
X	default:
X		goto readin;
X	}
X}
X
Xvsinit()
X{
X	char buf[1024], *tp;
X	static char tspace[512];
X	char *aoftspace;
X	char *tgetstr();
X	extern char *UP, *BC;   /* defined in tgoto.c (from ex's termlib */
X	extern char PC;		/* defined in tputs.c (from termlib) */
X
X	tgetent(buf, getenv("TERM"));
X	aoftspace = tspace;
X	vs_cl = tgetstr("cl", &aoftspace);
X	vs_cm = tgetstr("cm", &aoftspace);
X	BC = tgetstr("bc", &aoftspace);
X	UP = tgetstr("up", &aoftspace);
X	if ((tp = tgetstr("pc", &aoftspace)) != NULL)
X		PC = *tp;
X	vs_rows = tgetnum("li");
X	vs_cols = tgetnum("co");
X/* what total crap				.. kre
X	vs_vb = tgetstr("vb", &aoftspace);
X	if ((vs_vb == 0) || (*vs_vb == '\0'))
X	{
X		vs_vb = aoftspace;
X		*vs_vb++ = '';
X		*vs_vb++ = '\0';
X		aoftspace += 2;
X	};
X*/
X	if ((vs_cl == 0) || (*vs_cl == '\0') ||
X		(vs_cm == 0) || (*vs_cm == '\0'))
X	{
X		(void) fprintf(stderr, "\nPacman is designed for CRT's with addressable cursors.\n");
X		(void) fprintf(stderr, "Verify that the TERM environment variable is a proper\n");
X		(void) fprintf(stderr, "type and is export-ed, and try it again...\n\n");
X		exit(2);
X	};
X}
X
Xgetrand(range)
X	int range;
X{
X	register unsigned int q;
X
X	q = rand();
X	return(q % range);
X}
X
X
X/* dfp - real function for tputs function to use */
Xputch( ch )
X	register int ch;
X{
X	putchar( ch );
X}
END-of-./util.c
echo x - ./pacman.6
sed 's/^X//' >./pacman.6 << 'END-of-./pacman.6'
X.\"
X.\"	@(#)pacman.6
X.\"
X.Dd "March 18, 1995"
X.Dt PACMAN 6
X.Os
X.Sh NAME
X.Nm pacman
X.Nd the game of pacman
X.Sh SYNOPSIS
X.Nm
X.Sh DESCRIPTION
XThe
X.Nm
Xcommand runs display-based game which must be played on a CRT terminal.
XThe object is to eat and not get eaten.
X.Pp
XThe default control keys are as follows:
X.Bl -tag -width "<space>" -compact -offset indent
X.It l
Xmove right
X.It h
Xmove left
X.It j
Xmove down
X.It k
Xmove up
X.It <space>
Xpause
X.It q
Xquit
X.El
X.Sh PLAY
XUse the direction keys to move your critter about the maze. Eat
Xas many gold coins as you can. Aim for treasure and eat them for extra
Xpoints. Avoid the monsters. 
X.Sh SCORING
XYou score a point each time your critter eats a gold coin. You score
Xtwenty points for eating treasure and ten points for eating monsters.
X.Sh FILES
X.Bl -tag -width indent
X.It /var/games/pacman.scores
Xhigh score file
X.El
X.Sh BUGS
XThis man page does not completely describe the game.
X.Sh AUTHORS
XOriginally written by Dave Nixon, AGS Computers Inc., July, 1981.
X.Pp
XTerminal handling for video games taken from aliens, written by Jude
XMiller, fall 1979.
X.Pp
XScore keeping modified and general terminal handling from UCB's ex 
Xadded by Rob Coben, BTL, June, 1980.
END-of-./pacman.6
exit





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199503200556.VAA25783>