[comp.sources.games] v11i093: larn - dungeon type adventure game, Part10/11

billr@saab.CNA.TEK.COM (Bill Randle) (12/19/90)

Submitted-by: routley@tle.ENET.DEC.COM (Kevin Routley)
Posting-number: Volume 11, Issue 93
Archive-name: larn/Part10
Environment: Unix, VMS, MS-DOS, termcap



#! /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 10 (of 11)."
# Contents:  larnhlp.txt msdos.c spheres.c tgoto.c tok.c tputs.c vms.c
# Wrapped by billr@saab on Tue Dec 18 10:14:23 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'larnhlp.txt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'larnhlp.txt'\"
else
echo shar: Extracting \"'larnhlp.txt'\" \(8052 characters\)
sed "s/^X//" >'larnhlp.txt' <<'END_OF_FILE'
X7    Welcome to the game of Larn.  At this moment, you face a great problem.
XYour daughter has contracted a strange disease, and none of your home remedies
Xseem to have any effect.  You sense that she is in mortal danger, and you must
Xtry to save her.  Time ago you heard of a land of great danger and opportunity.
XPerhaps here is the solution you need.
X
X    It has been said that there once was a great magician who called himself
XPolinneaus.  Many years ago, after having many miraculous successes, Polinneaus
Xretired to the caverns of Larn, where he devoted most of his time to the
Xcreation of magic.   Rumors have it that one day Polinneaus set out to dispel
Xan attacking army in a forest some distance to the north.  It is believed that
Xhere he met his demise.
X
X    The caverns of Larn, it is thought, must be magnificent in design,
Xand contain much magic and treasure.  One option you have is to undertake a
Xjourney into these caverns.
X
X
X    Good Luck!  You're going to need it!
X
X
X
X
X                Help File for The Caverns of Larn, Prompt Mode
X
Xb  move southwest          B  run southwest            S  save the game
Xh  move left               H  run left                 .  stay here
Xj  move down               J  run down                 ^  identify a trap
Xk  move up                 K  run up                   T  take off armor
Xl  move right              L  run right
Xn  move southeast          N  run southeast
Xu  move northeast          U  run northeast
Xy  move northwest          Y  run northwest            ^L redraw the screen
Xc  cast a spell            Z  teleport yourself
Xd  drop an item            e  eat something
Xg  get present pack weight P  give tax status
Xi  inventory your pockets  I  list all items found     ?  this help screen
Xq  quaff a potion          Q  quit the game
Xr  read a scroll           v  print program version
Xw  weild a weapon          W  wear armor               ^L redraw the screen
X
X
X
X
X
X
X                Help File for The Caverns of Larn, Command Mode
X
Xb  move southwest          B  run southwest            A  desecrate an altar
Xc  cast a spell            C  close a door             Z  teleport yourself
Xd  drop an item            D  drink at a fountain      <  go up stairs or
Xe  eat something           E  enter a store, dungeon      volcanic shaft
Xg  get present pack weight G  give the stairs a kick   >  go down stairs or
Xh  move left               H  run left                    volcanic shaft
Xi  inventory your pockets  I  list all items found     ?  this help screen
Xj  move down               J  run down                 ^  identify a trap
Xk  move up                 K  run up                   ,  pick up item
Xl  move right              L  run right                :  look at object
Xn  move southeast          N  run southeast
X                           O  open a door or chest     .  stay here
Xp  pray at an altar        P  give tax status
Xq  quaff a potion          Q  quit the game
Xr  read a scroll           R  remove gems from throne
Xs  sit on a throne         S  save the game
Xt  tidy up at a fountain   T  take off armor
Xu  move northeast          U  run northeast
Xv  print program version
Xw  weild a weapon          W  wear armor
Xy  move northwest          Y  run northwest            ^L redraw the screen
X                Special Notes
X
XWhen dropping gold, if you type '*' as your amount, all your gold gets dropped.
XIn general, typing in '*' means all of what your interested in.  This is true
Xwhen visiting the bank, or when contributing at altars.
X
XLarn needs the ANSI.SYS (or preferably, the NANSI.SYS) device driver installed
Xin your CONFIG.SYS file.  The supplied "termcap" file describes the escape
Xsequences to change video modes (see ch 13 of the DOS 2.0 manual).  See the
X"TERMCAP" section in LARN.DOC for further details.
X
XWhen in the store, trading post, school, or home, an m<escape> will get you out.
X
XWhen casting a spell, if you need a list of spells you can cast, type 'D' as
Xthe first letter of your spell.  The available list of spells will be shown,
Xafter which you may enter the spell code.  This only works on the 1st letter
Xof the spell you are casting.
X
XThe Author of Larn is Noah Morgan (1982-3), Copying for Profit is Prohibited
XCopyright 1986 by Noah Morgan, All Rights Reserved.
X
X
X
X                        Larn Command Line Options
X
Xlarn ++                 restore checkpointed game
Xlarn -s                 list the scoreboard
Xlarn -i                 list scores with inventories
Xlarn -n                 suppress welcome message when beginning a game
Xlarn -h                 print out all the command line options
Xlarn -<number>          specify difficulty of the game (may be used with -n)
Xlarn -o<optsfile>       specify the option file to be used
Xlarn -c                 create new scoreboards -- prompts for a password
Xlarn -l                 print out the larn log file 
Xlarn -p                 play in prompt mode
X
X
X
X
X
X
X
X
X
X
X
X            Background Information for Larn
X
X    Welcome to the game of Larn.  At this moment, you face a great problem.
XYour daughter has contracted a strange disease, and none of your home remedies
Xseem to have any effect.  You sense that she is in mortal danger, and you must
Xtry to save her.  Time ago you heard of a land of great danger and opportunity.
XPerhaps here is the solution you need.
X
X    It has been said that there once was a great magician who called himself
XPolinneaus.  Many years ago, after having many miraculous successes, Polinneaus
Xretired to the caverns of Larn, where he devoted most of his time to the
Xcreation of magic.   Rumors have it that one day Polinneaus set out to dispel
Xan attacking army in a forest some distance to the north.  It is believed that
Xhere he met his demise.
X
X    The caverns of Larn, it is thought, must be magnificent in design,
Xand contain much magic and treasure.  One option you have is to undertake a
Xjourney into these caverns.
X
X    Good Luck!  You're going to need it!
X
X
X
X            How to use the larn.opt option file
X
XThe file "larn.opt", if used, should be in a directory along your PATH.
XA sequence of words terminated by whitespace is used to specify options.
X
X    Word                     Meaning
X    cursor:   lowscan highscan  change the shape of the cursor
X    DECRainbow          tell LARN you have that computer
X    enable-checkpointing    turn on periodic checkpointing
X    graphics: wallc floorc  select graphics maze characters
X    keypad          enable the numeric keypad for moving
X    larndir:  directory     the directory to use for larn files
X    monster:  "monst name"  choose a name for a monster
X    name:     "your name"   choose your playing name
X    no-beep         disable beeping of the terminal
X    no-introduction     do not display intro message
X    savefile: save-file-name    define what the savegame filename will be
X    swapfile: swap-file-name    define the name of the swapfile
X
XYour name and monster names must be enclosed in double quotation marks and may
Xbe up to 34 characters long.  Longer names are truncated.  Anything enclosed in
Xquotation marks is considered one word, and must be separated from other words
Xby whitespace.
X           Explanation of the Larn scoreboard facility
X
X    Larn supports TWO scoreboards, one for winners, and one for deceased
Xcharacters.  Each player (by userid or playerid, see UIDSCORE in Makefile)
Xis allowed one slot on each scoreboard, if the score is in the top ten for
Xthat scoreboard.  This design helps insure that frequent players of Larn
Xdo not hog the scoreboard, and gives more players a chance for glory.  Level
Xof difficulty is also noted on the scoreboards, and this takes precedence
Xover score for determining what entry is on the scoreboard.  For example:
Xif "Yar, the Bug Slayer" has a score of 128003 on the scoreboard at diff 0,
Xthen a game at diff 1 and a score of 4112 would replace the previous
Xentry on the scoreboard.  Note that when a player dies, the inventory is
Xstored in the scoreboard so that everyone can see what items the player had
Xat the time of death.
X
X
X
X
END_OF_FILE
if test 8052 -ne `wc -c <'larnhlp.txt'`; then
    echo shar: \"'larnhlp.txt'\" unpacked with wrong size!
fi
# end of 'larnhlp.txt'
fi
if test -f 'msdos.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'msdos.c'\"
else
echo shar: Extracting \"'msdos.c'\" \(8879 characters\)
sed "s/^X//" >'msdos.c' <<'END_OF_FILE'
X# ifdef MSDOS
X# include <stdio.h>
X# include <process.h>
X# include <dos.h>
X# include <fcntl.h>
X# include <sys/types.h>
X# include <sys/stat.h>
X# include "header.h"
X
X# define DEVICE		0x80
X# define RAW		0x20
X# define IOCTL		0x44
X# define STDIN		0
X# define STDOUT		1
X# define GETBITS	0
X# define SETBITS	1
X# define PATHSEP	';'
X
X
X# ifdef DGK
X
X/* Normal characters are output when the shift key is not pushed.
X * Shift characters are output when either shift key is pushed.
X */
X#  define KEYPADHI	83
X#  define KEYPADLOW	71
X#  define iskeypad(x)	(KEYPADLOW <= (x) && (x) <= KEYPADHI)
Xstatic struct {
X	char normal, shift;
X	} pad[KEYPADHI - KEYPADLOW + 1] = {
X			{'y', 'Y'},		/* 7 */
X			{'k', 'K'},		/* 8 */
X			{'u', 'U'},		/* 9 */
X			{' ', ' '},		/* - */
X			{'h', 'H'},		/* 4 */
X			{' ', ' '},		/* 5 */
X			{'l', 'L'},		/* 6 */
X			{' ', ' '},		/* + */
X			{'b', 'B'},		/* 1 */
X			{'j', 'J'},		/* 2 */
X			{'n', 'N'},		/* 3 */
X			{'i', 'i'},		/* Ins */
X			{'.', '.'}		/* Del */
X};
X
X/* BIOSgetch gets keys directly with a BIOS call.
X */
X#  define SHIFT		(0x1 | 0x2)
X#  define KEYBRD_BIOS	0x16
X
Xstatic char
XBIOSgetch() {
X	unsigned char scan, shift, ch;
X	union REGS regs;
X
X	/* Get scan code.
X	 */
X	regs.h.ah = 0;
X	int86(KEYBRD_BIOS, &regs, &regs);
X	ch = regs.h.al;
X	scan = regs.h.ah;
X
X	/* Get shift status.
X	 */
X	regs.h.ah = 2;
X	int86(KEYBRD_BIOS, &regs, &regs);
X	shift = regs.h.al;
X
X	/* If scan code is for the keypad, translate it.
X	 */
X	if (iskeypad(scan)) {
X		if (shift & SHIFT)
X			ch = pad[scan - KEYPADLOW].shift;
X		else
X			ch = pad[scan - KEYPADLOW].normal;
X	}
X	return ch;
X}
X# endif
X
Xkgetch()
X{
X# ifdef DGK
X	/* BIOSgetch can use the numeric key pad on IBM compatibles. */
X	if (keypad)
X		return BIOSgetch();
X	else
X# endif
X		return getch();
X}
X
Xdoshell()
X{
X	char *comspec = getenv("COMSPEC");
X
X	clear();
X	lflush();
X	if (comspec == NULL
X	|| (spawnl(P_WAIT, comspec, comspec, NULL) < 0)) {
X		write(2, "A> ", 3);
X		while (getche() != '\r')
X			;
X	}
X}
X
Xstatic	unsigned	old_stdin, old_stdout, ioctl();
X
Xstatic unsigned
Xioctl(handle, mode, setvalue)
Xunsigned setvalue;
X{
X	union REGS regs;
X
X	regs.h.ah = IOCTL;
X	regs.h.al = mode;
X	regs.x.bx = handle;
X	regs.h.dl = setvalue;
X	regs.h.dh = 0;			/* Zero out dh */
X	intdos(&regs, &regs);
X	return (regs.x.dx);
X}
X
Xint rawio;
Xvoid
Xsetraw()
X{
X	if (!rawio)
X		return;
X	old_stdin = ioctl(STDIN, GETBITS, 0);
X	old_stdout = ioctl(STDOUT, GETBITS, 0);
X	if (old_stdin & DEVICE)
X		(void) ioctl(STDIN, SETBITS, old_stdin | RAW);
X	if (old_stdout & DEVICE)
X		(void) ioctl(STDOUT, SETBITS, old_stdout | RAW);
X}
X
Xvoid
Xunsetraw()
X{
X	if (!rawio)
X		return;
X	if (old_stdin)
X		(void) ioctl(STDIN, SETBITS, old_stdin);
X	if (old_stdout)
X		(void) ioctl(STDOUT, SETBITS, old_stdout);
X}
X
X
X/* Add a backslash to any name not ending in /, \ or :   There must
X * be room for the \
X */
Xvoid
Xappend_slash(name)
Xchar *name;
X{
X	char *ptr;
X
X	if (!*name)
X		return;
X	ptr = name + (strlen(name) - 1);
X	if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
X		*++ptr = '\\';
X		*++ptr = '\0';
X	}
X}
X
X#ifndef KBR
X/* Pause for secs -- sounds good ...
X */
Xsleep(secs)
Xint secs;
X{
X	long time(), waittill;
X
X	waittill = time((long *) NULL) + secs;
X	while (waittill > time((long *) NULL))
X		;
X}
X#endif
X
X/* Lopen a file somewhere along the PATH
X */
Xplopen(name)
Xchar	*name;
X{
X	char	buf[PATHLEN], *bp, *pp, lastch, *strchr();
X	int	fd;
X
X	/* Try the default directory first.  Then look along PATH unless
X	 * the name has path components.
X	 */
X	if ((fd = lopen(name)) >= 0)
X		return fd;
X	else if (strpbrk(name, "\\/:") == NULL) {
X		pp = getenv("PATH");
X		while (pp && *pp) {
X			bp = buf;
X			while (*pp && *pp != PATHSEP)
X				lastch = *bp++ = *pp++;
X			if (strchr("\\/:", lastch) == NULL)
X				*bp++ = '\\';
X			strcpy(bp, name);
X			if ((fd = lopen(buf)) >= 0)
X				return fd;
X			if (*pp)
X				pp++;
X		}
X	}
X	return -1;
X}
X
X
X/* Follow the PATH, trying to fopen the file.  Takes one additional
X * argument which can be NULL.  Otherwise this argument gets filled
X * in the full path to the file.  Returns as does fopen().
X */
XFILE *
Xfopenp(name, mode, pathname)
Xchar *name, *mode, *pathname;
X{
X	char buffer[BUFSIZ], *buf, *bufp, *pathp, *getenv(), lastch;
X	FILE *fp;
X
X	/* If pathname is given, use it instead of buf so the calling
X	 * process knows the path we found name under
X	 */
X	if (pathname)
X		buf = pathname;
X	else
X		buf = buffer;
X
X	/* Try the default directory first.  If the file can't be opened,
X	 * start looking along the path.
X	 */
X	strcpy(buf, name);
X	if (fp = fopen(buf, mode))
X		return fp;
X	else if (strpbrk(name, "\\/:") == NULL) {
X		pathp = getenv("PATH");
X		while (pathp && *pathp) {
X			bufp = buf;
X			while (*pathp && *pathp != PATHSEP)
X				lastch = *bufp++ = *pathp++;
X			if (lastch != '\\' && lastch != '/')
X				*bufp++ = '\\';
X			strcpy(bufp, name);
X			if (fp = fopen(buf, mode))
X				return fp;
X			if (*pathp)
X				pathp++;
X		}
X	}
X	return NULL;
X}
X
X/* Diagnositic information about the disposition of levels between ram
X * and disk.
X */
Xlevelinfo()
X{
X	DISKBLOCK	*dp;
X	RAMBLOCK	*rp;
X
X	cursors();
X	lflush();
X	fprintf(stderr, "\nRAM:\n");
X	for (rp = ramblks; rp; rp = rp->next)
X		fprintf(stderr, "%4d  gt:%6ld\n", rp->level, rp->gtime);
X	fprintf(stderr, "\nDISK:\n");
X	for (dp = diskblks; dp; dp = dp->next)
X		fprintf(stderr, "%4d  gt:%6ld  fpos:%ld\n",
X		dp->level, dp->gtime, dp->fpos);
X	nomove=1;
X	return (yrepcount = 0);
X}
X
Xint swapfd = 0;	/* file descriptor for the swap file */
Xint ramlevels = MAXLEVEL + MAXVLEVEL;	/* the maximum */
X
X
X/* Allocate as many levels as possible, then check that the swap file
X * will have enough storage for the overflow.  You must be able to allocate
X * at least one level or there will be nowhere to swap to/from.  If a swap
X * file is opened it remains open for the whole game.
X */
Xallocate_memory()
X{
X	register int	i;
X	DISKBLOCK	*dp, *dp2;
X	RAMBLOCK	*rp;
X
X	/* First allocate the maximum number of disk blocks, some of which
X	 * may not be used, but must do the allocation now since we don't
X	 * yet know how many levels will be allocatable.
X	 */
X	for (i = 0; i < MAXLEVEL + MAXVLEVEL; i++) {
X		if ((dp = (DISKBLOCK *) malloc(sizeof(DISKBLOCK))) == NULL)
X			died(-285);
X		dp->next = diskblks;
X		diskblks = dp;
X	}
X	dp = diskblks;		/* Move this along in the next loop */
X
X	/* Now allocate ram storage, up to ramlevels in count.
X	 */
X	for (i = 0; i < MAXLEVEL + MAXVLEVEL; i++) {
X		if (i < ramlevels)
X			rp = (RAMBLOCK *) malloc(sizeof(RAMBLOCK));
X		else
X			rp = NULL;
X		if (rp == NULL) {
X			if (i == 0)
X				died(-285);	/* have to have at least one */
X
X			/* Open the swap file if not yet done so
X			 */
X			if (swapfd == 0) {
X				swapfd = open(swapfile,
X					O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
X					S_IWRITE | S_IREAD);
X				if (swapfd < 0)
X					error("Can't open swapfile `%s'\n",
X					swapfile);
X
X				/* First block is FREE and will be used to
X				 * swap out the first level.  When another
X				 * level gets swapped in, its block will be
X				 * FREE.
X				 */
X				if (dp == NULL)
X					error("NULL1 disk pointer?\n");
X				dp->level = FREEBLOCK;
X				dp->fpos = 0;
X				dp->gtime = 0;
X				lseek(swapfd, (long) sizeof rp->cell, 0);
X			}
X
X			/* And try to seek the size of this level
X			 */
X			dp = dp->next;
X			if (dp == NULL)
X			 	error("NULL2 disk pointer?\n");
X			dp->level = FREEBLOCK;
X			dp->gtime = 0;
X			dp->fpos = tell(swapfd);
X			if (lseek(swapfd, (long) sizeof rp->cell, 1) < 0L)
X				error("Not enough disk space for swapfile `%s'\n",
X				swapfile);
X		} else {
X			rp->next = ramblks;
X			ramblks = rp;
X			rp->level = FREEBLOCK;
X			rp->gtime = 0;
X		}
X	}
X
X	/* dp now points to the last diskblock used.  Truncate the diskblock
X	 * list here and free up the other blocks (for what it's worth ...)
X	 */
X	dp2 = dp->next;
X	dp->next = NULL;
X	dp = dp2;
X	while (dp) {
X		dp2 = dp->next;
X		free((char *) dp);
X		dp = dp2;
X	}
X}
X
X
X/* VARARGS1 */
Xwarn(format, a1, a2, a3)
Xchar *format;
Xlong a1, a2, a3;
X{
X	fprintf(stderr, format, a1, a2, a3);
X}
X
X/* VARARGS1 */
Xerror(format, a1, a2, a3, a4)
Xchar *format;
Xlong a1, a2, a3, a4;
X{
X	unsetraw();
X	resetcursor();
X	fputc('\n', stderr);
X	fprintf(stderr, format, a1, a2, a3, a4);
X	sleep(5);
X	exit(1);
X}
X
Xstatic unsigned char ocursorstart, ocursorend;
Xunsigned char cursorstart, cursorend;
Xint cursorset;
X
X/* Save the old value of the cursor then put in the new value.
X */
X# define READCURSORPOS	0x03
X# define SETCURSORTYPE	0x01
X# define BIOSVIDEO	0x10
Xsetcursor()
X{
X	union	REGS	regs;
X
X	if (cursorset == 0)
X		return;
X
X	regs.h.ah = READCURSORPOS;
X	regs.h.bh = 0;
X	int86(BIOSVIDEO, &regs, &regs);
X	ocursorstart = regs.h.ch;
X	ocursorend = regs.h.cl;
X
X	regs.h.ah = SETCURSORTYPE;
X	regs.h.bh = 0;
X	regs.h.ch = cursorstart;
X	regs.h.cl = cursorend;
X	int86(BIOSVIDEO, &regs, &regs);
X}
X
X/* Restore the old cursor upon exit
X */
Xresetcursor()
X{
X	union	REGS	regs;
X
X	if (cursorset == 0)
X		return;
X	regs.h.ah = SETCURSORTYPE;
X	regs.h.bh = 0;
X	regs.h.ch = ocursorstart;
X	regs.h.cl = ocursorend;
X	int86(BIOSVIDEO, &regs, &regs);
X}
X# endif	/* MSDOS */
END_OF_FILE
if test 8879 -ne `wc -c <'msdos.c'`; then
    echo shar: \"'msdos.c'\" unpacked with wrong size!
fi
# end of 'msdos.c'
fi
if test -f 'spheres.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'spheres.c'\"
else
echo shar: Extracting \"'spheres.c'\" \(6647 characters\)
sed "s/^X//" >'spheres.c' <<'END_OF_FILE'
X/*
X  newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
X  rmsphere(x,y)      Function to delete a sphere of annihilation from list
X  sphboom(x,y)       Function to perform the effects of a sphere detonation
X  movsphere()        Function to look for and move spheres of annihilation
X*/
X#include "header.h"
X
X#define min(x,y) (((x)>(y))?(y):(x))
X#define max(x,y) (((x)>(y))?(x):(y))
X
X/*
X *  newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
X *      int x,y,dir,lifetime;
X *
X *  Enter with the coordinates of the sphere in x,y
X *    the direction (0-8 diroffx format) in dir, and the lifespan of the
X *    sphere in lifetime (in turns)
X *  Returns the number of spheres currently in existence
X */
Xnewsphere(x,y,dir,life)
X    int x,y,dir,life;
X    {
X    int m;
X    struct sphere *sp;
X    if (((sp=(struct sphere *)malloc(sizeof(struct sphere)))) == 0)
X        return(c[SPHCAST]); /* can't malloc, therefore failure */
X    if (dir>=9) dir=0;  /* no movement if direction not found */
X    if (level==0) vxy(&x,&y);   /* don't go out of bounds */
X    else
X        {
X        if (x<1) x=1;  if (x>=MAXX-1) x=MAXX-2;
X        if (y<1) y=1;  if (y>=MAXY-1) y=MAXY-2;
X        }
X    if ((m=mitem[x][y]) >= DEMONLORD+4) /* demons dispel spheres */
X        {
X# ifdef DGK
X        show1cell(x,y);     /* show the demon (ha ha) */
X# else
X        know[x][y]=1; show1cell(x,y);   /* show the demon (ha ha) */
X# endif
X        cursors(); lprintf("\nThe %s dispels the sphere!",monster[m].name);
X        beep(); rmsphere(x,y);  /* remove any spheres that are here */
X        return(c[SPHCAST]);
X        }
X    if (m==DISENCHANTRESS) /* disenchantress cancels spheres */
X        {
X        cursors(); lprintf("\nThe %s causes cancellation of the sphere!",monster[m].name); beep();
Xboom:   sphboom(x,y);   /* blow up stuff around sphere */
X        rmsphere(x,y);  /* remove any spheres that are here */
X        return(c[SPHCAST]);
X        }
X    if (c[CANCELLATION]) /* cancellation cancels spheres */
X        {
X        cursors(); lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!"); beep();
X        goto boom;
X        }
X    if (item[x][y]==OANNIHILATION) /* collision of spheres detonates spheres */
X        {
X        cursors(); lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!"); beep();
X        rmsphere(x,y);
X        goto boom;
X        }
X    if (playerx==x && playery==y) /* collision of sphere and player! */
X        {
X        cursors();
X        lprcat("\nYou have been enveloped by the zone of nothingness!\n");
X        beep(); rmsphere(x,y);  /* remove any spheres that are here */
X        nap(4000);  died(258);
X        }
X    item[x][y]=OANNIHILATION;  mitem[x][y]=0;  know[x][y]=1;
X    show1cell(x,y); /* show the new sphere */
X    sp->x=x;  sp->y=y;  sp->lev=level;  sp->dir=dir;  sp->lifetime=life;  sp->p=0;
X    if (spheres==0) spheres=sp; /* if first node in the sphere list */
X    else    /* add sphere to beginning of linked list */
X        {
X        sp->p = spheres;    spheres = sp;
X        }
X    return(++c[SPHCAST]);   /* one more sphere in the world */
X    }
X
X/*
X *  rmsphere(x,y)       Function to delete a sphere of annihilation from list
X *      int x,y;
X *
X *  Enter with the coordinates of the sphere (on current level)
X *  Returns the number of spheres currently in existence
X */
Xrmsphere(x,y)
X    int x,y;
X    {
X    register struct sphere *sp,*sp2=0;
X    for (sp=spheres; sp; sp2=sp,sp=sp->p)
X      if (level==sp->lev)   /* is sphere on this level? */
X        if ((x==sp->x) && (y==sp->y))   /* locate sphere at this location */
X            {
X            item[x][y]=mitem[x][y]=0;  know[x][y]=1;
X            show1cell(x,y); /* show the now missing sphere */
X            --c[SPHCAST];   
X            if (sp==spheres) { sp2=sp; spheres=sp->p; free((char*)sp2); }
X            else
X                { sp2->p = sp->p;  free((char*)sp); }
X            break;
X            }
X    return(c[SPHCAST]); /* return number of spheres in the world */
X    }
X
X/*
X *  sphboom(x,y)    Function to perform the effects of a sphere detonation
X *      int x,y;
X *
X *  Enter with the coordinates of the blast, Returns no value
X */
Xstatic sphboom(x,y)
X    int x,y;
X    {
X    register int i,j;
X    if (c[HOLDMONST]) c[HOLDMONST]=1;
X    if (c[CANCELLATION]) c[CANCELLATION]=1;
X    for (j=max(1,x-2); j<min(x+3,MAXX-1); j++)
X      for (i=max(1,y-2); i<min(y+3,MAXY-1); i++)
X        {
X        item[j][i]=mitem[j][i]=0;
X        show1cell(j,i);
X        if (playerx==j && playery==i)
X            {
X            cursors(); beep();
X            lprcat("\nYou were too close to the sphere!");
X            nap(3000);
X            died(283); /* player killed in explosion */
X            }
X        }
X    }
X
X/*
X *  movsphere()     Function to look for and move spheres of annihilation
X *
X *  This function works on the sphere linked list, first duplicating the list
X *  (the act of moving changes the list), then processing each sphere in order
X *  to move it.  They eat anything in their way, including stairs, volcanic
X *  shafts, potions, etc, except for upper level demons, who can dispel
X *  spheres.
X *  No value is returned.
X */
X#define SPHMAX 20   /* maximum number of spheres movsphere can handle */
Xmovsphere()
X    {
X    register int x,y,dir,len;
X    register struct sphere *sp,*sp2;
X    struct sphere sph[SPHMAX];
X
X    /* first duplicate sphere list */
X    for (sp=0,x=0,sp2=spheres; sp2; sp2=sp2->p) /* look through sphere list */
X      if (sp2->lev == level)    /* only if this level */
X        {
X        sph[x] = *sp2;  sph[x++].p = 0;  /* copy the struct */
X        if (x>1)  sph[x-2].p = &sph[x-1]; /* link pointers */
X        }
X    if (x) sp= sph; /* if any spheres, point to them */
X        else return;    /* no spheres */
X
X    for (sp=sph; sp; sp=sp->p)  /* look through sphere list */
X        {
X        x = sp->x;    y = sp->y;
X        if (item[x][y]!=OANNIHILATION) continue;    /* not really there */
X        if (--(sp->lifetime) < 0)   /* has sphere run out of gas? */
X            {
X            rmsphere(x,y); /* delete sphere */
X            continue;
X            }
X        switch(rnd((int)max(7,c[INTELLIGENCE]>>1))) /* time to move the sphere */
X            {
X            case 1:
X            case 2:     /* change direction to a random one */
X                        sp->dir = rnd(8);
X            default:    /* move in normal direction */
X                        dir = sp->dir;      len = sp->lifetime;
X                        rmsphere(x,y);
X                        newsphere(x+diroffx[dir],y+diroffy[dir],dir,len);
X            };
X        }
X    }
END_OF_FILE
if test 6647 -ne `wc -c <'spheres.c'`; then
    echo shar: \"'spheres.c'\" unpacked with wrong size!
fi
# end of 'spheres.c'
fi
if test -f 'tgoto.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tgoto.c'\"
else
echo shar: Extracting \"'tgoto.c'\" \(5750 characters\)
sed "s/^X//" >'tgoto.c' <<'END_OF_FILE'
X/************************************************************************
X *									*
X *			Copyright (c) 1982, Fred Fish			*
X *			    All Rights Reserved				*
X *									*
X *	This software and/or documentation is released for public	*
X *	distribution for personal, non-commercial use only.		*
X *	Limited rights to use, modify, and redistribute are hereby	*
X *	granted for non-commercial purposes, provided that all		*
X *	copyright notices remain intact and all changes are clearly	*
X *	documented.  The author makes no warranty of any kind with	*
X *	respect to this product and explicitly disclaims any implied	*
X *	warranties of merchantability or fitness for any particular	*
X *	purpose.							*
X *									*
X ************************************************************************
X */
X
X
X/*
X *  LIBRARY FUNCTION
X *
X *	tgoto   expand cursor addressing string from cm capability
X *
X *  KEY WORDS
X *
X *	termcap
X *
X *  SYNOPSIS
X *
X *	char *tgoto(cm,destcol,destline)
X *	char *cm;
X *	int destcol;
X *	int destline;
X *
X *  DESCRIPTION
X *
X *	Returns cursor addressing string, decoded from the cm
X *	capability string, to move cursor to column destcol on
X *	line destline.
X *
X *	The following sequences uses one input argument, either
X *	line or column, and place the appropriate substitution
X *	in the output string:
X *
X *		%d	substitute decimal value (in ASCII)
X *		%2	like %d but forces field width to 2
X *		%3	like %d but forces field width to 3
X *		%.	like %c
X *		%+x	like %c but adds ASCII value of x
X *
X *	The following sequences cause processing modifications
X *	but do not "use up" one of the arguments.  If they
X *	act on an argument they act on the next one to
X *	be converted.
X *
X *		%>xy	if next value to be converted is
X *			greater than value of ASCII char x
X *			then add value of ASCII char y.
X *		%r	reverse substitution of line
X *			and column (line is substituted
X *			first by default).
X *		%i	causes input values destcol and
X *			destline to be incremented.
X *		%%	gives single % character in output.
X *
X *  BUGS
X *
X *	Does not implement some of the more arcane sequences for
X *	radically weird terminals (specifically %n, %B, & %D).
X *	If you have one of these you deserve whatever happens.
X *
X */
X
X/*
X *	Miscellaneous stuff
X */
X
X#include <stdio.h>
X
X#define MAXARGS 2
X
Xstatic char *in;		/* Internal copy of input string pointer */
Xstatic char *out;		/* Pointer to output array */
Xstatic int args[MAXARGS];	/* Maximum number of args to convert */
Xstatic int pcount;		/* Count of args processed */
Xstatic char output[64];		/* Converted string */
X
X
X/*
X *  PSEUDO CODE
X *
X *	Begin tgoto
X *	    If no string to process then
X *		Return pointer to error string.
X *	    Else
X *		Initialize pointer to input string.
X *		Initialize pointer to result string.
X *		First arg is line number by default.
X *		Second arg is col number by default.
X *		No arguments processed yet.
X *		While there is another character to process
X *		    If character is a not a % character then
X *			Simply copy to output.
X *		    Else
X *			Process the control sequence.
X *		    End if
X *		End while
X *		TERMINATE STRING!  (rde)
X *		Return pointer to static output string.
X *	    End if
X *	End tgoto
X *
X */
X
Xchar *tgoto(cm,destcol,destline)
Xchar *cm;
Xint destcol;
Xint destline;
X{
X    if (cm == NULL) {
X	return("OOPS");
X    } else {
X	in = cm;
X	out = output;
X	args[0] = destline;
X	args[1] = destcol;
X	pcount = 0;
X	while (*in != NULL) {
X	    if (*in != '%') {
X		*out++ = *in++;
X	    } else {
X		process();
X	    }
X	}
X	*out = '\0';	/* rde 18-DEC-86: don't assume out was all zeros */
X	return(output);
X    }
X}
X
X/*
X *  INTERNAL FUNCTION
X *
X *	process   process the conversion/command sequence
X *
X *  SYNOPSIS
X *
X *	static process()
X *
X *  DESCRIPTION
X *
X *	Processes the sequence beginning with the % character.
X *	Directly manipulates the input string pointer, the
X *	output string pointer, and the arguments.  Leaves
X *	the input string pointer pointing to the next character
X *	to be processed, and the output string pointer pointing
X *	to the next output location.  If conversion of
X *	one of the numeric arguments occurs, then the pcount
X *	is incremented.
X *
X */
X
X/*
X *  PSEUDO CODE
X *
X *	Begin process
X *	    Skip over the % character.
X *	    Switch on next character after %
X *	    Case 'd':
X *		Process %d type conversion (variable width).
X *		Reinitialize output pointer.
X *		Break;
X *	    Case '2':
X *		Process %d type conversion (width 2).
X *		Reinitialize output pointer.
X *		Break;
X *	    Case '3':
X *		Process %d type conversion (width 3).
X *		Reinitialize output pointer.
X *		Break;
X *	    Case '.'
X *		Process %c type conversion.
X *		Break;
X *	    Case '+':
X *		Process %c type conversion with offset.
X *		Break;
X *	    Case '>':
X *		Process argument modification.
X *		Break;
X *	    Case 'r':
X *		Process argument reversal.
X *		Break;
X *	    Case 'i':
X *		Increment argument values.
X *		Break;
X *	    Case '%':
X *		Copy to output, incrementing pointers.
X *		Break;
X *	    End switch
X *	End process
X *
X */
X
X
Xstatic process()
X{
X    int temp;
X
X    in++;
X    switch(*in++) {
X    case 'd':
X	sprintf(out,"%d",args[pcount++]);
X	out = &output[strlen(output)];	
X	break;
X    case '2':
X	sprintf(out,"%02d",args[pcount++]);
X	out = &output[strlen(output)];
X	break;
X    case '3':
X	sprintf(out,"%03d",args[pcount++]);
X	out = &output[strlen(output)];
X	break;
X    case '.':
X	*out++ = args[pcount++];
X	break;
X    case '+':
X	*out++ = args[pcount++] + *in++;
X	break;
X    case '>':
X	if (args[pcount] > *in++) {
X	    args[pcount] += *in++;
X	} else {
X	    in++;
X	}
X	break;
X    case 'r':
X	temp = args[pcount];
X	args[pcount] = args[pcount+1];
X	args[pcount+1] = temp;
X	break;
X    case 'i':
X	args[pcount]++;
X	args[pcount+1]++;
X	break;
X    case '%':
X	*out++ = '%';
X	break;
X    }
X}
END_OF_FILE
if test 5750 -ne `wc -c <'tgoto.c'`; then
    echo shar: \"'tgoto.c'\" unpacked with wrong size!
fi
# end of 'tgoto.c'
fi
if test -f 'tok.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tok.c'\"
else
echo shar: Extracting \"'tok.c'\" \(8964 characters\)
sed "s/^X//" >'tok.c' <<'END_OF_FILE'
X/* tok.c		Larn is copyrighted 1986 by Noah Morgan. */
X/*
X   yylex()
X   flushall()
X   sethard()
X   readopts()
X*/
X#ifdef VMS
X#include <types.h>
X#include <file.h>
X#include <iodef.h>
X#else VMS
X#include <sys/types.h>
X#ifdef SYSV
X#include <fcntl.h>
X# ifndef MSDOS
X#   include <termio.h>
X# endif
X#else SYSV
X# ifndef MSDOS
X#   include <sys/ioctl.h>
X# endif
X#endif SYSV
X#endif VMS
X#include <ctype.h>
X#include "header.h"
X
X# define CHKPTINT	400
X
Xstatic char lastok=0;
Xint yrepcount=0,dayplay=0;
X#ifndef FLUSHNO
X#define FLUSHNO 5
X#endif FLUSHNO
Xstatic int flushno=FLUSHNO;	/* input queue flushing threshold */
X#define MAXUM 52	/* maximum number of user re-named monsters */
X#define MAXMNAME 40	/* max length of a monster re-name */
Xstatic char usermonster[MAXUM][MAXMNAME]; /* the user named monster name goes here */
Xstatic char usermpoint=0;			/* the user monster pointer */
X#ifdef DGK_MSDOS
X extern int rawio;
X#endif
X
X/*
X	lexical analyzer for larn
X */
Xyylex()
X	{
X	char cc;
X	int ic;
X	if (hit2flag) { hit2flag=0;  yrepcount=0;  return(' '); }
X	if (yrepcount>0)	{ --yrepcount;  return(lastok);	} else yrepcount=0;
X	if (yrepcount==0) { bottomdo(); showplayer(); }	/*	show where the player is	*/
X	lflush();  
X	while (1)
X		{
X		c[BYTESIN]++;
X		if (ckpflag)
X		  if ((c[BYTESIN] % CHKPTINT) == 0)	/* check for periodic checkpointing */
X			{
X#ifndef DOCHECKPOINTS
X#ifdef MSDOS
X			cursors();
X			lprcat("\nCheckpointing . . .");
X			savegame(ckpfile);
X			lprcat("\nDone\n");
X			showplayer();
X			lflush();
X			flushall();	/* Kill any stored key strokes */
X#else
X#ifdef VMS
X			savegame(ckpfile);
X#else
X			wait(0);	/* wait for other forks to finish */
X			if (fork() == 0) { savegame(ckpfile); exit(); }
X#endif
X#endif
X#else
X#ifdef VMS
X			savegame(ckpfile);
X#else
X			wait(0);	/* wait for other forks to finish */
X			if (fork() == 0) { savegame(ckpfile); exit(); }
X#endif
X#endif
X
X#ifdef TIMECHECK
X			if (dayplay==0)
X			  if (playable())
X				{
X				cursor(1,19);
X				lprcat("\nSorry, but it is now time for work.  Your game has been saved.\n"); beep();
X				lflush();
X				savegame(savefilename);
X				wizard=nomove=1;
X				sleep(4);
X				died(-257);
X				}
X#endif TIMECHECK
X
X			}
X
X# ifndef MSDOS
X# ifdef VMS
X		/* If keyboard input buffer is too big then flush some? RDE */
X		/* Check this! but for now just ignore it... */
X# else
X		do /* if keyboard input buffer is too big, flush some of it */
X			{
X			ioctl(0,FIONREAD,&ic);
X			if (ic>flushno)   read(0,&cc,1);
X			}
X		while (ic>flushno);
X# endif VMS
X# endif MSDOS
X
X# ifdef MSDOS
X		cc = ttgetch();
X# else MSDOS
X# ifdef VMS
X		cc = ttgetch();
X# else
X		if (read(0,&cc,1) != 1) return(lastok = -1);
X# endif VMS
X# endif MSDOS
X		if (cc == '!')		/* ! shell escape */
X			{
X			resetscroll();  /* scrolling region, home, clear, no attributes */
X			clear();
X# ifdef MSDOS
X			doshell();
X# else MSDOS
X# ifdef VMS
X			lflush();
X			sncbr();
X			oneliner("");
X			scbr();
X# else VMS
X			if ((ic=fork())==0) /* child */
X				{
X				execl("/bin/csh",0);	exit();
X				wait(0);
X				}
X			if (ic<0) /* error */
X				{
X				write(2,"Can't fork off a shell!\n",25); sleep(2);
X				}
X# endif VMS
X# endif MSDOS
X			setscroll();
X			return(lastok = 'L'-64);	/* redisplay screen */
X			}
X		
X		if ((cc <= '9') && (cc >= '0'))
X			{ yrepcount = yrepcount*10 + cc - '0'; }
X		else	{ if (yrepcount>0) --yrepcount;  return(lastok = cc); }
X		}
X	}
X
X/*
X *	flushall()	Function to flush all type-ahead in the input buffer
X */
Xflushall()
X	{
X# ifdef MSDOS
X	while (kbhit())
X		getch();
X# else MSDOS
X# ifdef VMS
X	/* Flush all type-ahead -- RDE */
X	extern int	iochan;		/* defined in IO.C	*/
X	int		c;
X
X	SYS$QIOW(0,iochan,IO$_READLBLK|IO$M_TIMED|IO$M_PURGE,0,0,0,&c,1,0,0,0,0);
X
X# else VMS
X	char cc;
X	int ic;
X	for (;;) {		/* if keyboard input buffer is too big, flush some of it */
X		ioctl(0,FIONREAD,&ic);
X		if (ic<=0)
X			return;
X		while (ic>0) {
X			read(0,&cc,1);
X			--ic;
X		} /* gobble up the byte */
X	}
X# endif VMS
X# endif MSDOS
X}
X
X/*
X	function to set the desired hardness 
X	enter with hard= -1 for default hardness, else any desired hardness
X */
Xsethard(hard)
Xint hard;
X{
X	register int	j,k;
X	long		i;
X	struct monst	*mp;
X
X	j=c[HARDGAME]; hashewon(); 
X	if (restorflag==0)	/* don't set c[HARDGAME] if restoring game */
X		{
X		if (hard >= 0) c[HARDGAME]= hard;
X		}
X	else c[HARDGAME]=j; /* set c[HARDGAME] to proper value if restoring game */
X
X	if (k=c[HARDGAME])
X	  for (j=0; j<=MAXMONST+8; j++) {
X	  	mp = &monster[j];
X		i = ((6+k) * mp->hitpoints + 1)/6;
X		mp->hitpoints = (i<0) ? 32767 : i;
X		i = ((6+k) * mp->damage + 1) / 5;
X		mp->damage = (i>127) ? 127 : i;
X		i = (10 * mp->gold)/(10+k);
X		mp->gold = (i>32767) ? 32767 : i;
X		i = mp->armorclass - k;
X		mp->armorclass = (i< -127) ? -127 : i;
X		i = (7*mp->experience)/(7+k) + 1;
X		mp->experience = (i<=0) ? 1 : i;
X	}
X}
X
X
X/*
X	function to read and process the larn options file
X */
Xreadopts()
X	{
X	register char *i;
X	register int j,k;
X	char original_objects = FALSE ;
X	int flag = 1;		/* set to 0 if a name is specified */
X
X# ifdef DGK_MSDOS
X	if (plopen(optsfile) < 0)
X# else
X	if (lopen(optsfile) < 0)
X# endif
X		{
X		strcpy(logname,loginname);
X		lprintf("Can't open options file \"%s\"\n", optsfile);
X		lflush();
X		sleep(2);
X		return; /* user name if no character name */
X		}
X	i = " ";
X	while (*i)
X	  {
X	  if ((i=(char *)lgetw()) == 0) break; /* check for EOF */
X	  while (*i && ((*i==' ') || (*i=='\t'))) i++; /* eat leading whitespace */
X		if (strcmp(i,"bold-objects") == 0)
X		    boldon=1;
X		else if (strcmp(i,"enable-checkpointing") == 0)
X		    ckpflag=1;
X		else if (strcmp(i,"inverse-objects") == 0)
X		    boldon=0;
X		else if (strcmp(i,"prompt-on-objects") == 0 )
X		    prompt_mode = TRUE ;
X		else if (strcmp(i,"auto-pickup") == 0 )
X		    auto_pickup = TRUE ;
X		else if (strcmp(i,"highlight-objects") == 0 )
X		    boldobjects = TRUE ;
X		else if (strcmp(i,"original-objects") == 0 )
X		    original_objects = TRUE ;
X		else if (strcmp(i,"female") == 0)
X		    sex=0; /* male or female */
X# ifdef DGK_MSDOS
X		else if (strcmp(i, "graphics:") == 0)
X		    {
X		    wallc = atoi(lgetw());
X		    floorc = atoi(lgetw());
X		    }
X		else if (strcmp(i, "larndir:") == 0) {
X			if ((i=lgetw())==0)
X				break;
X			strncpy(larndir, i, DIRLEN);
X			larndir[DIRLEN - 1] = 0;
X		}
X		else if (strcmp(i, "rawio") == 0)
X			rawio = 1;
X		else if (strcmp(i, "swapfile:") == 0) {
X			if ((i = lgetw()) == 0)
X				break;
X			strncpy(swapfile, i, PATHLEN);
X			swapfile[PATHLEN - 1] = 0;
X		}
X		else if (strcmp(i, "ramlevels:") == 0)
X			ramlevels = atoi(lgetw());
X		else if (strcmp(i, "cursor:") == 0) {
X			cursorset = 1;
X			cursorstart = (unsigned char) atoi(lgetw());
X			cursorend = (unsigned char) atoi(lgetw());
X		}
X		else if (strcmp(i, "keypad") == 0)
X			keypad = 1;
X		else if (strcmp(i, "DECRainbow") == 0)
X			DECRainbow = 1;
X# endif
X		else if (strcmp(i,"monster:")== 0)   /* name favorite monster */
X			{
X			if ((i=lgetw())==0) break;
X			if (strlen(i)>=MAXMNAME) i[MAXMNAME-1]=0;
X			strcpy(usermonster[usermpoint],i); 
X			if (usermpoint >= MAXUM) break; /* defined all of em */
X			if (isalpha(j=usermonster[usermpoint][0]))
X				{
X				for (k=1; k<MAXMONST+8; k++) /* find monster */
X				  if (monstnamelist[k] == j)
X					{
X					monster[k].name = &usermonster[usermpoint++][0];
X					break;
X					}
X				}
X			}
X		else if (strcmp(i,"male") == 0)	sex=1;
X		else if (strcmp(i,"name:") == 0) /* defining players name */
X			{
X			if ((i=lgetw())==0) break;
X			if (strlen(i)>=LOGNAMESIZE) i[LOGNAMESIZE-1]=0;
X			strcpy(logname,i); flag=0;
X# ifdef MSDOS
X			strcpy(loginname,i);
X# endif
X			}
X		else if (strcmp(i,"no-introduction") == 0) nowelcome=1;
X		else if (strcmp(i,"no-beep") == 0) nobeep=1;
X# ifndef MSDOS
X		else if (strcmp(i,"process-name:")== 0) 
X			{
X			if ((i=lgetw())==0) break;
X			if (strlen(i)>=PSNAMESIZE) i[PSNAMESIZE-1]=0;
X			strcpy(psname,i);
X			}
X		else if (strcmp(i,"play-day-play") == 0)  dayplay=1;
X# endif
X		else if (strcmp(i,"savefile:") == 0) /* defining savefilename */
X			{
X			if ((i=lgetw())==0) break;
X			if (strlen(i)>=SAVEFILENAMESIZE) /* avoid overflow */
X				i[SAVEFILENAMESIZE-1]=0;
X			strcpy(savefilename,i); flag=0;
X			}
X		else {
X			lprintf("Unknown option \"%s\"\n", i);
X			lflush();
X			sleep(1);
X		}
X	  }
X	if (flag)
X	    strcpy(logname,loginname);
X
X	/* original objects require object highlighting to be ON (in order
X	   to distinguish between objects and monsters.  set up object list
X	   properly.
X	*/
X	if (original_objects)
X	    {
X	    boldobjects = TRUE ;
X	    strncpy( objnamelist, original_objnamelist, MAXOBJECT );
X	    }
X	else
X	    strncpy( objnamelist, hacklike_objnamelist, MAXOBJECT );
X	objnamelist[MAXOBJECT] = '\0' ;
X
X	/* now set all the invisible objects and monsters to have the
X	   same appearance as the floor (as defined by the user)
X	*/
X	objnamelist[OWALL] = wallc;
X
X	objnamelist[0]		  =
X	objnamelist[OIVTELETRAP]  =
X	objnamelist[OTRAPARROWIV] =
X	objnamelist[OIVDARTRAP]	  =
X	objnamelist[OIVTRAPDOOR]  = floorc;
X	monstnamelist[0] =
X	monstnamelist[INVISIBLESTALKER] = floorc;
X	for (j=DEMONLORD; j<=DEMONPRINCE; j++)
X		monstnamelist[j] = floorc;
X
X	}
END_OF_FILE
if test 8964 -ne `wc -c <'tok.c'`; then
    echo shar: \"'tok.c'\" unpacked with wrong size!
fi
# end of 'tok.c'
fi
if test -f 'tputs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tputs.c'\"
else
echo shar: Extracting \"'tputs.c'\" \(5233 characters\)
sed "s/^X//" >'tputs.c' <<'END_OF_FILE'
X/************************************************************************
X *									*
X *			Copyright (c) 1982, Fred Fish			*
X *			    All Rights Reserved				*
X *									*
X *	This software and/or documentation is released for public	*
X *	distribution for personal, non-commercial use only.		*
X *	Limited rights to use, modify, and redistribute are hereby	*
X *	granted for non-commercial purposes, provided that all		*
X *	copyright notices remain intact and all changes are clearly	*
X *	documented.  The author makes no warranty of any kind with	*
X *	respect to this product and explicitly disclaims any implied	*
X *	warranties of merchantability or fitness for any particular	*
X *	purpose.							*
X *									*
X ************************************************************************
X */
X
X
X/*
X *  LIBRARY FUNCTION
X *
X *	tputs     output string with appropriate padding
X *
X *  KEY WORDS
X *
X *	termcap
X *
X *  SYNOPSIS
X *
X *	tputs(cp,affcnt,outc)
X *	char *cp;
X *	int affcnt;
X *	int (*outc)();
X *
X *  DESCRIPTION
X *
X *	Outputs string pointed to by cp, using function outc, and
X *	following it with the appropriate number of padding characters.
X *	Affcnt contains the number of lines affected, which is used
X *	as a multiplier for the specified per line pad time.  If
X *	per line pad count is not applicable, affcnt should be 1,
X *	NOT zero.
X *
X *	The format of the string pointed to by cp is:
X *
X *		[pad time][*]<string to send>
X *
X *		where:	pad time => time to delay in milliseconds
X *			* => specifies that time is per line
X *			
X *	The pad character is assumed to reside in the external
X *	variable "PC".  Also, the external variable "ospeed"
X *	should contain the output speed of the terminal as
X *	encoded in /usr/include/sgtty.h  (B0-B9600).
X *
X *  BUGS
X *
X *	Digit conversion is based on native character set
X *	being ASCII.
X *
X */
X
X/*
X *	Miscellaneous stuff
X */
X
X#include <stdio.h>
X#include <ctype.h>
X
X# ifndef MSDOS
Xextern char PC;			/* Pad character to use */
Xextern char ospeed;		/* Encoding of output speed */
X
Xstatic int times[] = {
X    0,				/* Tenths of ms per char 0 baud */
X    2000,			/* Tenths of ms per char 50 baud */
X    1333,			/* Tenths of ms per char 75 baud */
X    909,			/* Tenths of ms per char 110 baud */
X    743,			/* Tenths of ms per char 134 baud */
X    666,			/* Tenths of ms per char 150 baud */
X    500,			/* Tenths of ms per char 200 baud */
X    333,			/* Tenths of ms per char 300 baud */
X    166,			/* Tenths of ms per char 600 baud */
X    83,				/* Tenths of ms per char 1200 baud */
X    55,				/* Tenths of ms per char 1800 baud */
X    41,				/* Tenths of ms per char 2400 baud */
X    20,				/* Tenths of ms per char 4800 baud */
X    10				/* Tenths of ms per char 9600 baud */
X};
X# endif
X
X
X/*
X *  PSEUDO CODE
X *
X *	Begin tgoto
X *	    If string pointer is invalid then
X *		Return without doing anything.
X *	    Else
X *		For each pad digit (if any)
X *		    Do decimal left shift.
X *		    Accumulate the lower digit.
X *		End for
X *		Adjust scale to tenths of milliseconds
X *		If there is a fractional field
X *		    Skip the decimal point.
X *		    If there is a valid tenths digit
X *			Accumulate the tenths.
X *		    End if
X *		    Discard remaining digits.
X *		End if
X *		If per line is specified then
X *		    Adjust the pad time.
X *		    Discard the per line flag char.
X *		End if
X *		While there are any characters left
X *		    Send them out via output function.
X *		End while
X *		Transmit any padding required.
X *	    End if
X *	End tgoto
X *
X */
X
Xtputs(cp,affcnt,outc)
Xchar *cp;
Xint affcnt;
Xint (*outc)();
X{
X    int ptime;			/* Pad time in tenths of milliseconds */
X
X    if (cp == NULL || *cp == NULL) {
X	return;
X    } else {
X	for (ptime = 0; isdigit(*cp); cp++) {
X	    ptime *= 10;
X	    ptime += (*cp - '0');
X	}
X	ptime *= 10;
X	if (*cp == '.') {
X	    cp++;
X	    if (isdigit(*cp)) {
X		ptime += (*cp++ - '0');
X	    }
X	    while (isdigit(*cp)) {cp++;}
X	}
X	if (*cp == '*') {
X	    ptime *= affcnt;
X	    cp++;
X	}
X	while (*cp != NULL) {
X	    (*outc)(*cp++);
X	}
X# ifndef MSDOS
X# ifndef VMS
X	do_padding(ptime,outc);
X# endif
X# endif
X    }
X}
X
X# ifndef MSDOS
X/*
X *  FUNCTION
X *
X *	do_padding    transmit any pad characters required
X *
X *  SYNOPSIS
X *
X *	static do_padding(ptime,outc)
X *	int ptime;
X *	int (*outc)();
X *
X *  DESCRIPTION
X *
X *	Does any padding required as specified by ptime (in tenths
X *	of milliseconds), the output speed given in the external
X *	variable ospeed, and the pad character given in the
X *	external variable PC.
X *
X */
X
X/*
X *  PSEUDO CODE
X *
X *	Begin do_padding
X *	    If there is a non-zero pad time then
X *		If the external speed is in range then
X *		    Look up the delay per pad character.
X *		    Round pad time up by half a character.
X *		    Compute number of characters to send.
X *		    For each pad character to send
X *			Transmit the pad character.
X *		    End for
X *		End if
X *	    End if
X *	End do_padding
X *
X */
X
Xstatic do_padding(ptime,outc)
Xint ptime;
Xint (*outc)();
X{
X    register int nchars;
X    register int tpc;
X
X    if (ptime != 0) {
X	if (ospeed > 0 && ospeed <= (sizeof(times)/ sizeof(int))) {
X	    tpc = times[ospeed];
X	    ptime += (tpc / 2);
X	    nchars = ptime / tpc;
X	    for ( ; nchars > 0; --nchars) {
X		(*outc)(PC);
X	    }
X	}
X    }
X}
X# endif
END_OF_FILE
if test 5233 -ne `wc -c <'tputs.c'`; then
    echo shar: \"'tputs.c'\" unpacked with wrong size!
fi
# end of 'tputs.c'
fi
if test -f 'vms.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'vms.c'\"
else
echo shar: Extracting \"'vms.c'\" \(6436 characters\)
sed "s/^X//" >'vms.c' <<'END_OF_FILE'
X#ifdef VMS
X#include "header.h"
X
X#include <file.h>
X#include <stat.h>
X#include <stdio.h>
X#include <stsdef.h>
X#include <ssdef.h>
X#include <descrip.h>
X#include <iodef.h>
X#include <ttdef.h>
X#include <tt2def.h>
X
X/*
X * Read until end of file or until buffer is full.
X * don't let the vms read (which stops once per record)
X * fool the program.
X */
Xvread(fd, buf, size)
Xint	fd;
Xchar	*buf;
Xint	size;
X{
X	int	csize;		/* cumulative size	*/
X	int	isize;		/* incremental size	*/
X
X	csize = 0;
X	do {
X		isize = read(fd, buf, size);
X		if (isize > 0) {
X			csize += isize;
X			buf   += isize;
X			size  -= isize;
X		}
X	} while (isize > 0);
X	return (csize);
X}
X
X#else VMS
X
X#ifndef vread		/* if not done as a macro in header.h */
Xvread(fd, buf, size)
Xint	fd;
Xchar	*buf;
Xint	size;
X{
X	return (read(fd, buf, size));
X}
X#endif vread
X#endif VMS
X
X#ifdef VMS
X/*
X * Run a command in a subjob.  Used for mailing the winners congratulations,
X * tax bills, etc.  Used for the shell escape command (!).  Conditionalized
X * for VMS wherever used (un*x has the right primitives).
X */
Xlong
Xoneliner(cstr)
Xchar	*cstr;
X{
X	struct	dsc$descriptor	cdsc;
X	register long		sts;
X	register long		pstat;
X
X	cdsc.dsc$a_pointer = cstr;
X	cdsc.dsc$w_length  = strlen(cstr);
X	cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
X	cdsc.dsc$b_class   = DSC$K_CLASS_S;
X	sts = LIB$SPAWN(&cdsc, 0, 0, 0, 0, 0, &pstat, 0, 0, 0, 0, 0);
X	if (sts != SS$_NORMAL)
X		return (sts);
X	else
X		return (pstat);
X}
X
X/*
X  Data to convert the escape codes produced by VT style keypad keys to things
X  that LARN will understand.
X*/
X#define MAX_KP_CONV 19
Xstruct 
X    {
X    char *inp_str;
X    char *out_str;
X    } keypad_conv[MAX_KP_CONV] = { { "\x1BOp", "i" },      /* KP0 */
X                                   { "\x1BOq", "b" },      /* KP1 */
X                                   { "\x1BOr", "j" },      /* KP2 */
X                                   { "\x1BOs", "n" },      /* KP3 */
X                                   { "\x1BOt", "h" },      /* KP4 */
X                                   { "\x1BOu", "." },      /* KP5 */
X                                   { "\x1BOv", "l" },      /* KP6 */
X                                   { "\x1BOw", "y" },      /* KP7 */
X                                   { "\x1BOx", "k" },      /* KP8 */
X                                   { "\x1BOy", "u" },      /* KP9 */
X				   { "\x1BOn", "." },      /* KP. */
X				   { "\x1BOl", "," },      /* KP, */
X				   { "\x1B[A", "K" },      /* uparrow */
X				   { "\x1B[B", "J" },      /* downarrow*/
X				   { "\x1B[C", "L" },      /* right arrow */
X				   { "\x1B[D", "H" },      /* left arrow */
X				   { "\x1BOP", "m" },      /* PF1 */
X				   { "\x1BOS", "@" },      /* PF4 */
X                                   { "\x1B[23~", "\x1B" }  /* (ESC) */
X                                 };
X
X/*
X  VMS-specific terminal character read.  Gets a character from the terminal,
X  translating keypad as necessary.  Assumes VT-class terminals.
X*/
Xvms_ttgetch()
X    {
X
X#define BUFFLEN 10
X
X    char           *i;
X    int            j;
X    register int   incount;
X    static char    buffer[BUFFLEN];
X    static char    *bufptr = buffer;
X    static char    *bufend = buffer;
X
X    lflush();		/* be sure output buffer is flushed */
X
X    /* Read the first char from the user
X    */
X    if (bufptr >= bufend) 
X        {
X        bufptr = bufend = buffer;
X        incount = vmsread(buffer, BUFFLEN, 0);
X        while ( incount <= 0 )
X            incount = vmsread(buffer, 1, 2);
X        bufend = &buffer[incount];
X        }
X
X    /* If the first char was an ESCAPE, get the characters from an
X       escape sequence (eg pressing a key that generates such a
X       sequence).  If it was a plain old escape, the vmsread() call
X       will return TIMEOUT.
X    */
X    if (*bufptr == '\x1B' )
X        {
X        incount = vmsread( bufend, (BUFFLEN - 1), 0 );
X        if (incount >= 0)
X	    bufend += incount ;
X	}
X
X    /* Make sure the buffer is zero-terminated, since vmsread() 
X       doesn't zero-terminate the characters read.
X    */
X    *bufend = '\0' ;
X
X    /* run through the keypad conversion table to convert keypad
X       keys (escape sequences) and other supported escape sequences
X       to Larn command characters.
X    */
X    for ( j = 0; j < MAX_KP_CONV ; j++ )
X        if (strcmp( &buffer, keypad_conv[j].inp_str ) == 0 )
X            {
X	    strcpy( &buffer, keypad_conv[j].out_str );
X	    bufend = &buffer[strlen(&buffer)];
X	    break;
X	    }
X
X    /* If after running through the table the first character is still
X       ESCAPE, then we probably didn't get a match.  Force unsupported
X       keys that generate escape sequences to just return an ESCAPE.
X       Effectively prevents key translations that generate escape
X       sequences.
X    */
X    if (*bufptr == '\x1B' )
X        {
X	bufend = &buffer[1] ;
X	}
X    *bufend = '\0' ;
X
X    if (*bufptr == '\r')
X        *bufptr = '\n';
X
X    return (*bufptr++ & 0xFF);
X    }
X
Xtypedef struct 
X    {
X    short int    status;
X    short int    term_offset;
X    short int    terminator;
X    short int    term_size;
X    } IOSTAB;
X
Xint vmsread(buffer, size, timeout)
Xchar       *buffer;
Xint        size;
Xint        timeout;
X    {
X
X#define TIMEOUT (-2)
X#define ERROR   (-1)
X
X    extern int        iochan;
X
X    register int      status;
X    IOSTAB            iostab;
X    static long       termset[2] = { 0, 0 };      /* No terminator    */
X
X    status = SYS$QIOW( 
X            0,               /* Event flag             */
X            iochan,          /* Input channel        */
X            IO$_READLBLK | IO$M_NOFILTR | IO$M_TIMED,
X                             /* Read, no echo, no translate    */
X            &iostab,         /* I/O status block        */
X            NULL,            /* AST block (none)        */
X            0,               /* AST parameter        */
X            buffer,          /* P1 - input buffer        */
X            size,            /* P2 - buffer length        */
X            timeout,         /* P3 - timeout            */
X            &termset,        /* P4 - terminator set        */
X            NULL,            /* P5 - ignored (prompt buffer)    */
X            0                /* P6 - ignored (prompt size)    */
X            );
X    if (status == SS$_TIMEOUT)
X        return (TIMEOUT);
X    else if (status != SS$_NORMAL)
X        return (ERROR);
X    else 
X        {
X        if ((status = iostab.term_offset + iostab.term_size) > 0)
X            return (status);
X        return (TIMEOUT);
X        }
X    }
X
X#endif VMS
END_OF_FILE
if test 6436 -ne `wc -c <'vms.c'`; then
    echo shar: \"'vms.c'\" unpacked with wrong size!
fi
# end of 'vms.c'
fi
echo shar: End of archive 10 \(of 11\).
cp /dev/null ark10isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 11 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0