[net.sources.games] VMS Larn 12.0 is here!

u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)

Hello all!  This is a port of Larn v12.0 to VAX/VMS.  Now everyone can save
his/her daughter!!  Just unpack using /bin/sh and read readme.txt.

                                                - Mark Nagel

P.S.  Thanks to Lord Kahless for letting me post this!



-------------------------------cut here-------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	bill.c
#	changes.txt
#	create.c
#	data.c
# This archive created: Sat Aug 30 14:43:16 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'bill.c'" '(6254 characters)'
if test -f 'bill.c'
then
	echo shar: will not over-write existing file "'bill.c'"
else
cat << \SHAR_EOF > 'bill.c'

#include "header.h"

/* bill.c		 "Larn is copyrighted 1986 by Noah Morgan. */

static char mail600[40];

/*
 *	function to create the tax bill for the user
 */
static int pid;

static letter1()
{
    sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);	/* prepare path */
    if (lcreat(mail600) < 0) {
	write(1, "can't write 600 letter\n", 23);
	return(0);
    }
    lprcat("\n\n\n\n\n\n\n\n\n\n\n\n");
    standout("From:");
    lprcat("  the LRS(Larn Revenue Service)\n");
    standout("\nSubject:");
    lprcat("  undeclared income\n");
    lprcat("\n   We heard you survived the caverns of Larn.  Let me be the");
    lprcat("\nfirst to congratulate you on your success.  It is quite a feat.");
    lprcat("\nIt must also have been very profitable for you.");
    lprcat("\n\n   The Dungeon Master has informed us that you brought");
    lprintf("\n%d gold pieces back with you from your journey.  As the",(long) c[GOLD]);
    lprcat("\ncounty of Larn is in dire need of funds, we have spared no time");
    lprintf("\nin preparing your tax bill.  You owe %d gold pieces as",
	   (long) c[GOLD] * TAXRATE);
    lprcat("\nof this notice, and is due within 5 days.  Failure to pay will");
    lprcat("\nmean penalties.  Once again, congratulations, We look forward");
    lprcat("\nto your future successful expeditions.\n");
    lwclose();
    return(1);
}

static  letter2()
{
    sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */
    if (lcreat(mail600) < 0) {
	write(1, "can't write 601 letter\n", 23);
	return(0);
    }
    lprcat("\n\n\n\n\n\n\n\n\n\n\n\n");
    standout("From:");
    lprcat("  His Majesty King Wilfred of Larndom\n");
    standout("\nSubject:");
    lprcat("  a noble deed\n");
    lprcat("\n   I have heard of your magnificent feat, and I, King Wilfred,");
    lprcat("\nforthwith declare today to be a national holiday.  Furthermore,");
    lprcat("\nhence three days, Ye be invited to the castle to receive the");
    lprcat("\nhonour of Knight of the realm.  Upon thy name shall it be written. . .");
    lprcat("\nBravery and courage be yours.");
    lprcat("\nMay you live in happiness forevermore . . .\n");
    lwclose();
    return(1);
}

static letter3()
{
    sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */
    if (lcreat(mail600) < 0) {
	write(1, "can't write 602 letter\n", 23);
	return(0);
    }
    lprcat("\n\n\n\n\n\n\n\n\n\n\n\n");
    standout("From:");
    lprcat("  Count Endelford\n");
    standout("\nSubject:");
    lprcat("  You Bastard!\n");
    lprcat("\n   I heard(from sources) of your journey.  Congratulations!");
    lprcat("\nYou Bastard!  With several attempts I have yet to endure the");
    lprcat(" caves,\nand you, a nobody, makes the journey!  From this time");
    lprcat(" onward, bewarned\nupon our meeting you shall pay the price!\n");
    lwclose();
    return(1);
}

static letter4()
{
    sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */
    if (lcreat(mail600) < 0) {
	write(1, "can't write 603 letter\n", 23);
	return(0);
    }
    lprcat("\n\n\n\n\n\n\n\n\n\n\n\n");
    standout("From:");
    lprcat("  Mainair, Duke of Larnty\n");
    standout("\nSubject:");
    lprcat("  High Praise\n");
    lprcat("\n   With a certainty a hero I declare to be amongst us!  A nod of");
    lprcat("\nfavour I send to thee.  Me thinks Count Endelford this day of");
    lprcat("\nright breath'eth fire as of dragon of whom ye are slayer.  I");
    lprcat("\nyearn to behold his anger and jealously.  Should ye choose to");
    lprcat("\nunleash some of thy wealth upon those who be unfortunate, I,");
    lprcat("\nDuke Mainair, Shall equal thy gift also.\n");
    lwclose();
    return(1);
}

static letter5()
{
    sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */
    if (lcreat(mail600) < 0) {
	write(1, "can't write 604 letter\n", 23);
	return(0);
    }
    lprcat("\n\n\n\n\n\n\n\n\n\n\n\n");
    standout("From:");
    lprcat("  St. Mary's Children's Home\n");
    standout("\nSubject:");
    lprcat("  these poor children\n");
    lprcat("\n   News of your great conquests has spread to all of Larndom.");
    lprcat("\nMight I have a moment of a great man's time.  We here at St.");
    lprcat("\nMary's Children's Home are very poor, and many children are");
    lprcat("\nstarving.  Disease is widespread and very often fatal without");
    lprcat("\ngood food.  Could you possibly find it in your heart to help us");
    lprcat("\nin our plight?  Whatever you could give will help much.");
    lprcat("\n(your gift is tax deductible)\n");
    lwclose();
    return(1);
}

static letter6()
{
    sprintf(mail600, "SYS$SCRATCH:%dmail600.txt", pid);/* prepare path */
    if (lcreat(mail600) < 0) {
	write(1, "can't write 605 letter\n", 23);
	return(0);
    }
    lprcat("\n\n\n\n\n\n\n\n\n\n\n\n");
    standout("From:");
    lprcat("  The National Cancer Society of Larn\n");
    standout("\nSubject:");
    lprcat("  hope\n");
    lprcat("\nCongratulations on your successful expedition.  We are sure much");
    lprcat("\ncourage and determination were needed on your quest.  There are");
    lprcat("\nmany though, that could never hope to undertake such a journey");
    lprcat("\ndue to an enfeebling disease -- cancer.  We at the National");
    lprcat("\nCancer Society of Larn wish to appeal to your philanthropy in");
    lprcat("\norder to save many good people -- possibly even yourself a few");
    lprcat("\nyears from now.  Much work needs to be done in researching this");
    lprcat("\ndreaded disease, and you can help today.  Could you please see it");
    lprcat("\nin your heart to give generously?  Your continued good health");
    lprcat("\ncan be your everlasting reward.\n");
    lwclose();
    return(1);
}


/*
 *	function to mail the letters to the player if a winner
 */
static int (*pfn[])() =
{
    letter1, letter2, letter3, letter4, letter5, letter6
};

mailbill()
{
    register int i;
    char buf[128];

    pid = getpid();
    resetscroll();
    for (i = 0; i < sizeof(pfn) / sizeof(int (*)()); i++)
	if ((*pfn[i])()) {
	    sleep(10);
	    sprintf(buf, "MAIL /SUBJECT=LARN %s %s",mail600,loginname);
	    system(buf);
	    delete(mail600);
	}
    exit();
}
SHAR_EOF
if test 6254 -ne "`wc -c < 'bill.c'`"
then
	echo shar: error transmitting "'bill.c'" '(should have been 6254 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'changes.txt'" '(11826 characters)'
if test -f 'changes.txt'
then
	echo shar: will not over-write existing file "'changes.txt'"
else
cat << \SHAR_EOF > 'changes.txt'


This is a list of the fixes/enhancements made to larn V11.0 in Version 12.0.
(Version numbers consist of 2 parts: ver.subver.  When the save file format
changes, ver must be bumped.  This is why the next release of Larn is 12.0
and not 11.1. This is used in the savefile routines to check for out-of-date
save files).  This list was mainly meant to be a record of what changed,
for my own sanity.  It's included for your benefit (Warning: SPOILER!):

0.	lprintf() in fileio.c (now called io.c) has been changed to use varargs
	so that its variable number of arguments usage is now portable.  Pyramids
	primarily had this problem.

1.	Panic handler was added to signal.c.  This routine catches fatal errors
	like segmentation faults, bus errors, illegal instructions, etc., and
	trys to performs a savegame() before dumping core.  This helps prevent
	the loss of a good game due to a game malfunction.  Also, the name of the
	signal received is printed, instead of just its number.

2.	The version number of the program is now selectable from the Makefile.
	see the symbols VER and SUBVER.

3.	When at an altar, pray and donate 3000000000 gp. and ye used to receive
	a whopping amount of gold due to a wraparound problem with the signed 
	ints.  This has been fixed by using unsigned longs when asking for money
	amounts.

4.	It was possible that when compiled with work hours checking, checkpointing
	enabled, and having "play-day-play" in the LARN12.OPT file a segmentation
	fault would occur at its first attempt to do a checkpoint.  This was due
	to an improperly declared savefilename array in tok.c.  This has been fixed.

5.	on level H, casting a missile weapon (mle cld ssp bal lit) off the edge of
	the level would mess up the display, as it didn't know when to stop.  This
	is needless to say, fixed.  Absolute bounds are now in effect for missile
	type spells, see godirect() in monster.c.

6.	The create monster routine will now create monsters in random positions
	around the player.  Before, the 1st one would always be created to the
	upper left.

7.	If you vpr or lit at a throne, it would summon a gnome king that you
	would have to deal with.  However, as each throne has only one king with it,
	successive vpr's should not create more gnome kings.  Presently, successive
	vpr's will create more kings.  This has been fixed.

8.	The mechanism to manage spheres of annihilation has been reworked to provide
	a cleaner design and to eliminate some possible problems.

9.	The spell gen (genocide monsters) has been implemented.

10.	When dropping a ring of strength and having been weakened to STR=3 the
	player might end up with a negative strength.  Strength is now stored
	in 2 variables, real strength, and strength bonuses.  Only real strength
	can now be weakened down to a minimum of 3, so unless you have a ring of
	strength -3 or less, strengths below 3 should not occur.

11.	larn -h will now print out a list of all available command line options.

12.	larn -o<optsfile> now lets you specify a LARN12.OPT file on the command
	line.  This was necessary as part of the solution to number 14 below.

13.	The "savefile:" statement has been aded to the LARN12.OPT format to allow
	specifying the savefilename (full path) for the savegame operation.
	This too was needed as part of # 14 below.

14.	A player id facility has been added to larn.  The complaint was that
	the game used the userid to order the scoreboard, thus only one scoreboard
	entry was allowed for each userid.  If the compile time symbol UIDSCORE
	is defined at compilation time (see Makefile), this will still be true.
	However, if this define is omitted, the game will create and manage a
	file called ".playerids" where names are taken from the specified
	LARN12.OPT file (now a command line option) and assigned a unique playerid.
	playerid's will now be used to govern scoreboard entry posting.  This
	feature makes it easy for one person to have many characters, each
	appearing on the scoreboard.  Be kind to your fellow players!
	The philosophy of one score per player gives more players the opportunity
	to bask in glory for all to see!

15.	It is no longer required that the player be WIZID to create the scoreboard
	or to examine the logfile.  Anyone with the correct wizard's password can
	now use these command line options (password is only needed to create/clear
	the scoreboard).  If you want to prevent players from zeroing the 
	scoreboard, change the wizard's password. (in config.c) By the way, wizards
	may be alot of fun, but they are prevented from being placed on any
	scoreboard. (for clarification)

16.	Monsters now have intelligence, that is some of them.  This determines if
	the monster moves using the previously stupid movement method, or by using
	the new IMM (intelligent monster movement) algorithm.  With IMM, monsters
	will move around corners, avoid pits, traps, etc.  With increasing levels
	of difficulty, more monsters will be using IMM.  Beware of IMM when 
	aggravated!  Those little beasties can really find you!

17.	Added the scroll of life protection.

18.	Larn now consults the file ".holiday" to check for holidays if the TIMECHECK
	option (no playing during working hours) is enabled.  Before, larn knew
	nothing about holidays.  It should now let people play if it is a holiday.
	The format for a .holiday entry is: "mmm dd yyyy comments . . .".

19.	In nap() and napms() it is possible that with nap(0) or napms(0) there
	would be an infinite loop and the game would hang.  The case of nap(0)
	is now looked for.

20.	The granularity of gold piles has been increased.  iarg[] has been changed
	from char's to short's, so instead of 255 x 10^n granularity we now have
	32767 x 10^n granularity.  This also means more than 255000 gp can be
	dropped in one place.  Not realistic, but it prevents a worthless
	annoyance.  Who said games were supposed to be realistic?

21.	Termcap capability has been added to larn.  If the symbol VT100 is defined
	in the makefile, the game will be compiled to use only VT100 compatible
	terminals (Much more efficient).  If the symbol VT100 is omitted, the game
	will be compiled to use the termcap entry for whatever terminal you are
	using.  This involves an extra layer of output interpretation, as every
	byte sent to the terminal must be inspected for control tokens.
	Only 3 termcap entries need be found for the game to be functional:
	CM (cursor movement), CE (clear to end of line), and CL (clear screen).
	For a better display, the following are optional: AL (insert line), DL
	(delete line), SO (Standout begin), SE (Standout end), and CD (clear to end
	of screen).  The .larn.help file was left as is, with VT100 escape
	sequences in it.  If the termcap version of larn reads it, it is translated
	for the desired terminal type.  The .mail60* files have been removed, and
	their text is now included in bill.c so it can be used with any terminal.
	Note:  If compiled for termcap, and using a VT100, the display will act
	a little different.  This is because the VT100 does not have insert line/
	delete line codes, and the scrolling region must be simulated with vertical
	wraparound instead of scrolling.  Thanks goes to Michiel Huisjes for the
	original termcap patch.

22.	When playing as wizard, if you go down stairs on 10 or V3, or up stairs
	on H, 1, or V1, etc. you would be placed in a phantom zone where the display
	was really weird ([-1] subscripting), and would eventually lead to a
	segmentation fault.  Stairs and volcano shafts now check for the level
	they are being used on.

23.	In response to some sites having only unsigned chars (flame the
	manufacturer), the chars that were used to store positive and negative
	numbers have been changed to shorts.  This includes diroffx[], diroffy[],
	iarg[][][], ivenarg[], and some others.  I believe the changes are correct,
	but I have none of these machines to try it out on. (Volunteers?)

24.	The function fullhit(n) in monster.c was supposed to return the damage
	done by n full hits on a monster.  It only returned the damage for ONE hit,
	thus severely limiting the usefulness of the web and sle spells.

25.	Someone said that they were getting segmentation faults when they were
	reading scrolls as the wizard.  I couldn't find the problem, which may
	have had something to do with the signed char problem mentioned above.
	However, I've added a check in read_scroll() and quaff_potion() to trap
	any scroll or potion types that are not in the game.

26.	"vt125" has been added to the acceptable terminal list
	(checked only if compiled with -DVT100).

27.	In savegame() and restoregame(), there was a 6 hardwired into the i/o
	statements which assumed the size of struct cel was 6.  On some machines
	this caused the rightmost part of each level to not be saved in a savefile.
	These 6's have been replaced with sizeof(struct cel), and should now be
	portable.

28.	The option "no-beep" has been added to the LARN12.OPT file.  When specified,
	beeping is inhibited at the terminal.

29.	When becoming wizard, no longer to you wear the ring of protection, and
	null scrolls and potions are no longer created.

30.	Many spelling errors have been fixed, both in player messages, and in the
	code itself.  A thanks goes to Mars Gralia who sent me a detailed list of
	the mistakes.

31.	When a player wins a game, if getlogin() fails, a segmentation fault will
	result, because the NULL returned from getlogin() is used as a pointer.
	This call has been replaced (now using loginname already determined).
	Also, the mail creation upon winning has been rewritten, mainly to allow
	termcapping of the text.

32.	The Larn Revenue Service will now always appear on level H.  Before, it
	was only created if the player had outstanding taxes.  In that multiple
	save files per player are now more possible, this was seen as incorrect.

33.	Input buffer flushing is now in effect.  If the input char queue exceeds
	5 bytes, the excess is discarded.  Also, if the player hits or gets hit
	all input bytes are flushed (within 1).  This relieves the situation
	where many moves have been typed ahead of the display and the player keeps
	getting hit while the queue of moves is processed.

34.	When a savefile has been altered, a warning message is displayed to the
	effect that you've cheated, and you will not be placed on the normal
	scoreboard.  If you then save the game, and start 'er up again, memory 
	of the cheating was lost.  This has been fixed, by letting the scoreboard
	routines consult the cheating flag.  Also, the I node number of the
	savefile is written into the savefile, so cp'ing, etc., will avail the
	cheater not.  If high security is needed, the game should be run suid.
	This suid mode has not been made the default because most installations
	do not want to install it that way.

35.	The sources have been run through lint, and most of lint's complaints have
	been taken care of.  An attempt was made to adjust the code for 16 bit int
	machines.  Many casts to long have been put in.  I don't know if it will
	run on a 16 bitter, but it should be closer to that end.

36.	When larn starts up, if it can't find the scoreboard, it will now make a
	blank one instead of complaining that there is no scoreboard.  It is not
	necessary to do "larn -c" to initially create the scoreboard.

37.	When listing out the logfile (larn -l), the error message "error reading
	from input file" has been fixed.  Also, the date & time of a player's
	demise is now included in the logfile.

38.	When casting web or sle into a mirror, the game will no longer bash the
	player.  Instead, the player will either fall asleep or get stuck in his
	web.

39.	Items like cookies, books, chests, swords of slashing, and Bessmann's
	flailing hammer can now be sold at the trading post.

SHAR_EOF
if test 11826 -ne "`wc -c < 'changes.txt'`"
then
	echo shar: error transmitting "'changes.txt'" '(should have been 11826 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'create.c'" '(14156 characters)'
if test -f 'create.c'
then
	echo shar: will not over-write existing file "'create.c'"
else
cat << \SHAR_EOF > 'create.c'

/*	create.c		Larn is copyrighted 1986 by Noah Morgan. */

#include "header.h"

/*
  makeplayer()

  subroutine to create the player and the players attributes
  this is called at the beginning of a game and at no other time
 */
makeplayer()
{
    register int i;

    scbr();
    clear();
    c[HPMAX] = c[HP] = 10;	/* start player off with 10 hit points */
    c[LEVEL] = 1;		/* player starts at level one */
    c[SPELLMAX] = c[SPELLS] = 1;  /* total # spells starts off as 1 */
    c[REGENCOUNTER] = 16;
    c[ECOUNTER] = 96;		/* start regeneration correctly */
    c[SHIELD] = c[WEAR] = c[WIELD] = -1;
    for (i = 0; i < 26; i++)
	iven[i] = 0;
    spelknow[0] = spelknow[1] = 1; /* he knows protection, magic missile */
    if (c[HARDGAME] <= 0) {
	iven[0] = OLEATHER;
	iven[1] = ODAGGER;
	ivenarg[1] = ivenarg[0] = c[WEAR] = 0;
	c[WIELD] = 1;
    }
    playerx = rnd(MAXX - 2);
    playery = rnd(MAXY - 2);
    oldx = 0;
    oldy = 25;
    gtime = 0;			/* 	time clock starts at zero	 */
    cbak[SPELLS] = -50;
    for (i = 0; i < 6; i++)
	c[i] = 12;	/* make the attributes, ie str, int, etc. */
    recalc();
}


/*
    newcavelevel(level)
    int level;

    function to enter a new level.  This routine must be called anytime the
    player changes levels.  If that level is unknown it will be created.
    A new set of monsters will be created for a new level, and existing
    levels will get a few more monsters.
    Note that it is here we remove genocided monsters from the present level.
 */
newcavelevel(x)
register int x;
{
    register int i,j;

    if (beenhere[level])
	savelevel();	/* put the level back into storage */
    level = x;		/* get the new level and put in working storage */
    if (beenhere[x] == 0)
	for (i = 0; i < MAXY; i++)
	    for (j = 0; j < MAXX; j++)
		know[j][i] = mitem[j][i] = 0;
    else {
	getlevel();
	sethp(0);
	goto chgn;
    }
    makemaze(x);
    makeobject(x);
    beenhere[x] = 1;
    sethp(1);

#if WIZID
    if (wizard || x == 0)
#else
    if (x == 0)
#endif
	for (j = 0; j < MAXY; j++)
	    for (i = 0; i < MAXX; i++)
		know[i][j] = 1;
chgn: 
    checkgen();		/* wipe out any genocided monsters */
}


/*
	makemaze(level)
	int level;

	subroutine to make the caverns for a given level.  only walls are made.
 */
static int  mx,mxl,mxh,my,myl,myh,tmp2;

makemaze(k)
int k;
{
    register int i,j,tmp;
    int z;

    if (k > 1 &&(rnd(17) <= 4 || k == MAXLEVEL - 1 || k == MAXLEVEL + MAXVLEVEL - 1)) {
	if (cannedlevel(k));
	return;			/* read maze from data file */
    }
    if (k == 0)
	tmp = 0;
    else
	tmp = OWALL;
    for (i = 0; i < MAXY; i++)
	for (j = 0;
		j < MAXX;
		j++)
	    item[j][i] = tmp;
    if (k == 0)
	return;
    eat(1, 1);
    if (k == 1)
	item[33][MAXY - 1] = 0;	/* exit from dungeon */

 /* now for open spaces -- not on level 10 */
    if (k != MAXLEVEL - 1) {
	tmp2 = rnd(3) + 3;
	for (tmp = 0; tmp < tmp2; tmp++) {
	    my = rnd(11) + 2;
	    myl = my - rnd(2);
	    myh = my + rnd(2);
	    if (k < MAXLEVEL) {
		mx = rnd(44) + 5;
		mxl = mx - rnd(4);
		mxh = mx + rnd(12) + 3;
		z = 0;
	    } else {
		mx = rnd(60) + 3;
		mxl = mx - rnd(2);
		mxh = mx + rnd(2);
		z = makemonst(k);
	    }
	    for (i = mxl; i < mxh; i++)
		for (j = myl;
			j < myh;
			j++) {
		    item[i][j] = 0;
		    if ((mitem[i][j] = z))
			hitp[i][j] = monster[z].hitpoints;
		}
	}
    }
    if (k != MAXLEVEL - 1) {
	my = rnd(MAXY - 2);
	for (i = 1; i < MAXX - 1; i++)
	    item[i][my] = 0;
    }
    if (k > 1)
	treasureroom(k);
}


/*
	function to eat away a filled in maze
 */
eat(xx, yy)
register int xx,yy;
{
    register int dir,try;

    dir = rnd(4);
    try = 2;
    while (try) {
	switch(dir) {
	    case 1: 
		if (xx <= 2)
		    break;	/* west */
		if ((item[xx - 1][yy] != OWALL) ||(item[xx - 2][yy] != OWALL))
		    break;
		item[xx - 1][yy] = item[xx - 2][yy] = 0;
		eat(xx - 2, yy);
		break;

	    case 2: 
		if (xx >= MAXX - 3)
		    break;	/* east */
		if ((item[xx + 1][yy] != OWALL) ||(item[xx + 2][yy] != OWALL))
		    break;
		item[xx + 1][yy] = item[xx + 2][yy] = 0;
		eat(xx + 2, yy);
		break;

	    case 3: 
		if (yy <= 2)
		    break;	/* south */
		if ((item[xx][yy - 1] != OWALL) ||(item[xx][yy - 2] != OWALL))
		    break;
		item[xx][yy - 1] = item[xx][yy - 2] = 0;
		eat(xx, yy - 2);
		break;

	    case 4: 
		if (yy >= MAXY - 3)
		    break;	/* north */
		if ((item[xx][yy + 1] != OWALL) ||(item[xx][yy + 2] != OWALL))
		    break;
		item[xx][yy + 1] = item[xx][yy + 2] = 0;
		eat(xx, yy + 2);
		break;
	};
	if (++dir > 4) {
	    dir = 1;
	    --try;
	}
    }
}


/*
 *  function to read in a maze from a data file
 *
 *  Format of maze data file:  1st character = # of mazes in file(ascii digit)
 *	For each maze: 18 lines(1st 17 used) 67 characters per line
 *
 *  Special characters in maze data file:
 *
 *  #	wall		D	door			.	random monster
 *  ~	eye of larn	!	cure dianthroritis
 *  -	random object
 */
cannedlevel(k)
int     k;
{
    char   *row,*lgetl();
    register int i,j;
    int     it,arg,mit,marg;

    if (lopen(larnlevels) < 0) {
	write(1, "Can't open the maze data file\n", 30);
	died(-282);
	return(0);
    }
    i = lgetc();
    if (i <= '0') {
	died(-282);
	return(0);
    }
    for (i = 18 * rund(i - '0'); i > 0; i--)
	lgetl();		/* advance to desired maze */
    for (i = 0; i < MAXY; i++) {
	row = lgetl();
	for (j = 0; j < MAXX; j++) {
	    it = mit = arg = marg = 0;
	    switch(*row++) {
		case '#': 
		    it = OWALL;
		    break;
		case 'D': 
		    it = OCLOSEDDOOR;
		    arg = rnd(30);
		    break;
		case '~': 
		    if (k != MAXLEVEL - 1)
			break;
		    it = OLARNEYE;
		    mit = rund(8) + DEMONLORD;
		    marg = monster[mit].hitpoints;
		    break;
		case '!': 
		    if (k != MAXLEVEL + MAXVLEVEL - 1)
			break;
		    it = OPOTION;
		    arg = 21;
		    mit = DEMONLORD + 7;
		    marg = monster[mit].hitpoints;
		    break;
		case '.': 
		    if (k < MAXLEVEL)
			break;
		    mit = makemonst(k + 1);
		    marg = monster[mit].hitpoints;
		    break;
		case '-': 
		    it = newobject(k + 1, &arg);
		    break;
	    };
	    item[j][i] = it;
	    iarg[j][i] = arg;
	    mitem[j][i] = mit;
	    hitp[j][i] = marg;

#if WIZID
	    know[j][i] = (wizard) ? 1 : 0;
#else
	    know[j][i] = 0;
#endif
	}
    }
    lrclose();
    return(1);
}

/*
    function to make a treasure room on a level
    level 10's treasure room has the eye in it and demon lords
    level V3 has potion of cure dianthroritis and demon prince
 */
treasureroom(lv)
register int lv;
{
    register int tx,ty,xsize,ysize;

    for (tx = 1 + rnd(10); tx < MAXX - 10; tx += 10)
	if ((lv == MAXLEVEL - 1) ||(lv == MAXLEVEL + MAXVLEVEL - 1) || rnd(13) == 2) {
	    xsize = rnd(6) + 3;
	    ysize = rnd(3) + 3;
	    ty = rnd(MAXY - 9) + 1;/* upper left corner of room */
	    if (lv == MAXLEVEL - 1 || lv == MAXLEVEL + MAXVLEVEL - 1)
		troom(lv, xsize, ysize, tx = tx + rnd(MAXX - 24), ty, rnd(3) + 6);
	    else
		troom(lv, xsize, ysize, tx, ty, rnd(9));
	}
}


/*
 *	subroutine to create a treasure room of any size at a given location 
 *	room is filled with objects and monsters 
 *	the coordinate given is that of the upper left corner of the room
 */
troom(lv, xsize, ysize, tx, ty, glyph)
int lv,xsize,ysize,tx,ty,glyph;
{
    register int i,j;
    int tp1,tp2;

    for (j = ty - 1; j <= ty + ysize; j++)
	for (i = tx - 1; i <= tx + xsize; i++)/* clear out space for room */
	    item[i][j] = 0;
    for (j = ty; j < ty + ysize; j++)
	for (i = tx; i < tx + xsize; i++) {/* now put in the walls */
	    item[i][j] = OWALL;
	    mitem[i][j] = 0;
	}
    for (j = ty + 1; j < ty + ysize - 1; j++)
	for (i = tx + 1; i < tx + xsize - 1; i++)/* now clear out interior */
	    item[i][j] = 0;

    switch(rnd(2)) {		/* locate the door on the treasure room */
	case 1: 
	    item[i = tx + rund(xsize)][j = ty +(ysize - 1) * rund(2)] = OCLOSEDDOOR;
	    iarg[i][j] = glyph;	/* on horizontal walls */
	    break;
	case 2: 
	    item[i = tx +(xsize - 1) * rund(2)][j = ty + rund(ysize)] = OCLOSEDDOOR;
	    iarg[i][j] = glyph;	/* on vertical walls */
	    break;
    };

    tp1 = playerx;
    tp2 = playery;
    playery = ty +(ysize >> 1);
    if (c[HARDGAME] < 2)
	for (playerx = tx + 1; playerx <= tx + xsize - 2; playerx += 2)
	    for (i = 0, j = rnd(6); i <= j; i++) {
		something(lv + 2);
		createmonster(makemonst(lv + 1));
	    }
    else
	for (playerx = tx + 1; playerx <= tx + xsize - 2; playerx += 2)
	    for (i = 0, j = rnd(4); i <= j; i++) {
		something(lv + 2);
		createmonster(makemonst(lv + 3));
	    }

    playerx = tp1;
    playery = tp2;
}


/*
	***********
	MAKE_OBJECT
	***********
	subroutine to create the objects in the maze for the given level
 */
makeobject(j)
register int j;
{
    register int i;

    if (j == 0) {
	fillroom(OENTRANCE, 0); /* entrance to dungeon */
	fillroom(ODNDSTORE, 0); /* the DND STORE */
	fillroom(OSCHOOL, 0);	/* college of Larn */
	fillroom(OBANK, 0);	/* 1st national bank of larn */
	fillroom(OVOLDOWN, 0);	/* volcano shaft to temple */
	fillroom(OHOME, 0);	/* the players home & family */
	fillroom(OTRADEPOST, 0);/* the trading post */
	fillroom(OLRS, 0);	/* the larn revenue service */
	return;
    }

    if (j == MAXLEVEL)
	fillroom(OVOLUP, 0);	/* volcano shaft up from the temple */

    /* make the fixed objects in the maze STAIRS */
    if ((j > 0) &&(j != MAXLEVEL - 1) &&(j != MAXLEVEL + MAXVLEVEL - 1))
	fillroom(OSTAIRSDOWN, 0);
    if ((j > 1) &&(j != MAXLEVEL))
	fillroom(OSTAIRSUP, 0);

    /* make the random objects in the maze */
    fillmroom(rund(3), OBOOK, j);
    fillmroom(rund(3), OALTAR, 0);
    fillmroom(rund(3), OSTATUE, 0);
    fillmroom(rund(3), OPIT, 0);
    fillmroom(rund(3), OFOUNTAIN, 0);
    fillmroom(rnd(3) - 2, OIVTELETRAP, 0);
    fillmroom(rund(2), OTHRONE, 0);
    fillmroom(rund(2), OMIRROR, 0);
    fillmroom(rund(2), OTRAPARROWIV, 0);
    fillmroom(rnd(3) - 2, OIVDARTRAP, 0);
    fillmroom(rund(3), OCOOKIE, 0);
    if (j == 1)
	fillmroom(1, OCHEST, j);
    else
	fillmroom(rund(2), OCHEST, j);
    if ((j != MAXLEVEL - 1) &&(j != MAXLEVEL + MAXVLEVEL - 1))
	fillmroom(rund(2), OIVTRAPDOOR, 0);
    if (j <= 10) {
	fillmroom((rund(2)), ODIAMOND, rnd(10 * j + 1) + 10);
	fillmroom(rund(2), ORUBY, rnd(6 * j + 1) + 6);
	fillmroom(rund(2), OEMERALD, rnd(4 * j + 1) + 4);
	fillmroom(rund(2), OSAPPHIRE, rnd(3 * j + 1) + 2);
    }
    for (i = 0; i < rnd(4) + 3; i++)
	fillroom(OPOTION, newpotion());  /* make a POTION */
    for (i = 0; i < rnd(5) + 3; i++)
	fillroom(OSCROLL, newscroll());  /* make a SCROLL */
    for (i = 0; i < rnd(12) + 11; i++)
	fillroom(OGOLDPILE, 12 * rnd(j + 1) +(j << 3) + 10);  /* make GOLD */
    if (j == 5)
	fillroom(OBANK2, 0);	/* branch office of the bank */
    froom(2, ORING, 0);	/* a ring mail */
    froom(1, OSTUDLEATHER, 0);	/* a studded leather	 */
    froom(3, OSPLINT, 0);	/* a splint mail */
    froom(5, OSHIELD, rund(3));/* a shield */
    froom(2, OBATTLEAXE, rund(3));/* a battle axe */
    froom(5, OLONGSWORD, rund(3));/* a long sword */
    froom(5, OFLAIL, rund(3));/* a flail */
    froom(4, OREGENRING, rund(3));/* ring of regeneration */
    froom(1, OPROTRING, rund(3));/* ring of protection	 */
    froom(2, OSTRRING, 4);	/* ring of strength + 4 */
    froom(7, OSPEAR, rnd(5));	/* a spear */
    froom(3, OORBOFDRAGON, 0);	/* orb of dragon slaying */
    froom(4, OSPIRITSCARAB, 0);/* scarab of negate spirit */
    froom(4, OCUBEofUNDEAD, 0);/* cube of undead control */
    froom(2, ORINGOFEXTRA, 0);	/* ring of extra regen */
    froom(3, ONOTHEFT, 0);	/* device of antitheft */
    froom(2, OSWORDofSLASHING, 0);/* sword of slashing */
    if (c[BESSMANN] == 0) {
	froom(4, OHAMMER, 0);	/* Bessman's flailing hammer */
	c[BESSMANN] = 1;
    }
    if (c[HARDGAME] < 3 ||(rnd(4) == 3)) {
	if (j > 3) {
	    froom(3, OSWORD, 3);/* sunsword + 3 */
	    froom(5, O2SWORD, rnd(4));/* a two handed sword */
	    froom(3, OBELT, 4);/* belt of striking */
	    froom(3, OENERGYRING, 3);/* energy ring */
	    froom(4, OPLATE, 5);/* platemail + 5 */
	}
    }
}

/*
	subroutine to fill in a number of objects of the same kind
 */

fillmroom(n, what, arg)
int n,arg;
char what;
{
    register int i;

    for (i = 0; i < n; i++)
	fillroom(what, arg);
}

froom(n, itm, arg)
int n,arg;
char itm;
{
    if (rnd(151) < n)
	fillroom(itm, arg);
}

/*
 *	subroutine to put an object into an empty room
 *	uses a random walk
 */
static  fillroom(what, arg)
int arg;
char what;
{
    register int x,y;

#ifdef EXTRA
    c[FILLROOM]++;
#endif

    x = rnd(MAXX - 2);
    y = rnd(MAXY - 2);
    while (item[x][y]) {

#ifdef EXTRA
	c[RANDOMWALK]++;	/* count up these random walks */
#endif

	x += rnd(3) - 2;
	y += rnd(3) - 2;
	if (x > MAXX - 2)
	    x = 1;
	if (x < 1)
	    x = MAXX - 2;
	if (y > MAXY - 2)
	    y = 1;
	if (y < 1)
	    y = MAXY - 2;
    }
    item[x][y] = what;
    iarg[x][y] = arg;
}

/*
	subroutine to put monsters into an empty room without walls or other
	monsters
 */
fillmonst(what)
char what;
{
    register int x,y,trys;

    for (trys = 5; trys > 0; --trys) {	/* max # of creation attempts */
	x = rnd(MAXX - 2);
	y = rnd(MAXY - 2);
	if ((item[x][y] == 0) &&(mitem[x][y] == 0) &&((playerx != x) ||(playery != y))) {
	    mitem[x][y] = what;
	    know[x][y] = 0;
	    hitp[x][y] = monster[what].hitpoints;
	    return(0);
	}
    }
    return(-1);		/* creation failure */
}

/*
	creates an entire set of monsters for a level
	must be done when entering a new level
	if sethp(1) then wipe out old monsters else leave them there
 */
sethp(flg)
int flg;
{
    register int i,j;

    if (flg)
	for (i = 0; i < MAXY; i++)
	    for (j = 0; j < MAXX; j++)
		stealth[j][i] = 0;
    if (level == 0) {
	c[TELEFLAG] = 0;
	return;
    }		/* if teleported and found level 1 then know level we are on */
    if (flg)
	j = rnd(12) + 2 +(level >> 1);
    else
	j =(level >> 1) + 1;
    for (i = 0; i < j; i++)
	fillmonst(makemonst(level));
    positionplayer();
}

/*
 *	Function to destroy all genocided monsters on the present level
 */
checkgen()
{
    register int x,y;

    for (y = 0; y < MAXY; y++)
	for (x = 0; x < MAXX; x++)
	    if (monster[mitem[x][y]].genocided)
		mitem[x][y] = 0;	/* no more monster */
}
SHAR_EOF
if test 14156 -ne "`wc -c < 'create.c'`"
then
	echo shar: error transmitting "'create.c'" '(should have been 14156 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'data.c'" '(31933 characters)'
if test -f 'data.c'
then
	echo shar: will not over-write existing file "'data.c'"
else
cat << \SHAR_EOF > 'data.c'

/*	data.c		Larn is copyrighted 1986 by Noah Morgan. */

#define NODEFS

#include "header.h"

/*
	class[c[LEVEL]-1] gives the correct name of the players experience level
 */
static char aa1[] =	" mighty evil master";
static char aa2[] =	"apprentice demi-god";
static char aa3[] =	"  minor demi-god   ";
static char aa4[] =	"  major demi-god   ";
static char aa5[] =	"    minor deity    ";
static char aa6[] =	"    major deity    "; 
static char aa7[] =	"  novice guardian  ";
static char aa8[] =	"apprentice guardian";
static char aa9[] =	"    The Creator    ";
globaldef char *class[]=
{
    "  novice explorer  ", "apprentice explorer", " practiced explorer",/*  -3*/
    "   expert explorer ", "  novice adventurer", "     adventurer    ",/*  -6*/
    "apprentice conjurer", "     conjurer      ", "  master conjurer  ",/*  -9*/
    "  apprentice mage  ", "        mage       ", "  experienced mage ",/* -12*/
    "     master mage   ", " apprentice warlord", "   novice warlord  ",/* -15*/
    "   expert warlord  ", "   master warlord  ", " apprentice gorgon ",/* -18*/
    "       gorgon      ", "  practiced gorgon ", "   master gorgon   ",/* -21*/
    "    demi-gorgon    ", "    evil master    ", " great evil master ",/* -24*/
    aa1       ,   aa1       ,   aa1       ,/* -27*/
    aa1       ,   aa1       ,   aa1       ,/* -30*/
    aa1       ,   aa1       ,   aa1       ,/* -33*/
    aa1       ,   aa1       ,   aa1       ,/* -36*/
    aa1       ,   aa1       ,   aa1       ,/* -39*/
    aa2       ,   aa2       ,   aa2       ,/* -42*/
    aa2       ,   aa2       ,   aa2       ,/* -45*/
    aa2       ,   aa2       ,   aa2       ,/* -48*/
    aa3       ,   aa3       ,   aa3       ,/* -51*/
    aa3       ,   aa3       ,   aa3       ,/* -54*/
    aa3       ,   aa3       ,   aa3       ,/* -57*/
    aa4       ,   aa4       ,   aa4       ,/* -60*/
    aa4       ,   aa4       ,   aa4       ,/* -63*/
    aa4       ,   aa4       ,   aa4       ,/* -66*/
    aa5       ,   aa5       ,   aa5       ,/* -69*/
    aa5       ,   aa5       ,   aa5       ,/* -72*/
    aa5       ,   aa5       ,   aa5       ,/* -75*/
    aa6       ,   aa6       ,   aa6       ,/* -78*/
    aa6       ,   aa6       ,   aa6       ,/* -81*/
    aa6       ,   aa6       ,   aa6       ,/* -84*/
    aa7       ,   aa7       ,   aa7       ,/* -87*/
    aa8       ,   aa8       ,   aa8       ,/* -90*/
    aa8       ,   aa8       ,   aa8       ,/* -93*/
    "  earth guardian   ", "   air guardian    ", "   fire guardian   ",/* -96*/
    "  water guardian   ", "  time guardian    ", " ethereal guardian ",/* -99*/
    aa9       ,   aa9       ,   aa9       ,/* -102*/
};

/*
	table of experience needed to be a certain level of player
	skill[c[LEVEL]] is the experience required to attain the next level
 */
#define MEG 1000000
globaldef long skill[] = {
0, 10, 20, 40, 80, 160, 320, 640, 1280, 2560, 5120,                  /*  1-11 */
10240, 20480, 40960, 100000, 200000, 400000, 700000, 1*MEG,          /* 12-19 */
2*MEG,3*MEG,4*MEG,5*MEG,6*MEG,8*MEG,10*MEG,                          /* 20-26 */
12*MEG,14*MEG,16*MEG,18*MEG,20*MEG,22*MEG,24*MEG,26*MEG,28*MEG,      /* 27-35 */
30*MEG,32*MEG,34*MEG,36*MEG,38*MEG,40*MEG,42*MEG,44*MEG,46*MEG,      /* 36-44 */
48*MEG,50*MEG,52*MEG,54*MEG,56*MEG,58*MEG,60*MEG,62*MEG,64*MEG,      /* 45-53 */
66*MEG,68*MEG,70*MEG,72*MEG,74*MEG,76*MEG,78*MEG,80*MEG,82*MEG,      /* 54-62 */
84*MEG,86*MEG,88*MEG,90*MEG,92*MEG,94*MEG,96*MEG,98*MEG,100*MEG,     /* 63-71 */
105*MEG,110*MEG,115*MEG,120*MEG, 125*MEG, 130*MEG, 135*MEG, 140*MEG, /* 72-79 */
145*MEG,150*MEG,155*MEG,160*MEG, 165*MEG, 170*MEG, 175*MEG, 180*MEG, /* 80-87 */
185*MEG,190*MEG,195*MEG,200*MEG, 210*MEG, 220*MEG, 230*MEG, 240*MEG, /* 88-95 */
250*MEG,260*MEG,270*MEG,280*MEG, 290*MEG, 300*MEG                    /* 96-101*/
};
#undef MEG

globaldef char *lpbuf,*lpnt,*inbuffer,*lpend;	/* input/output pointers to the buffers */
globaldef struct cel cell[(MAXLEVEL+MAXVLEVEL) * MAXX * MAXY];	/* dungeon storage */
globaldef short hitp[MAXX][MAXY];		/* monster hp on level */
globaldef short iarg[MAXX][MAXY];		/* arg for the item array */
globaldef char item[MAXX][MAXY];		/* objects in maze if any */
globaldef char know[MAXX][MAXY];		/* 1 or 0 if here before */
globaldef char mitem[MAXX][MAXY];		/* monster item array */
globaldef char moved[MAXX][MAXY];		/* monster movement flags  */
globaldef char stealth[MAXX][MAXY];	/* 0=sleeping 1=awake monst */
globaldef char iven[26];			/* inventory for player	*/
globaldef short ivenarg[26];		/* inventory for player	*/
globaldef char lastmonst[40];		/* this has the name of the current monster */
globaldef char beenhere[MAXLEVEL+MAXVLEVEL];	/*  1 if have been on this level */
globaldef char VERSION=VER;	/* this is the present version # of the program	*/
globaldef char SUBVERSION=SUBVER;
globaldef char nosignal=0;    /* set to 1 to disable the signals from doing anything */
globaldef char predostuff=0;  /*  2 means that the trap handling routines must do a
			showplayer() after a trap.  0 means don't showplayer()
			0 - we are in create player screen
			1 - we are in welcome screen
			2 - we are in the normal game	*/
globaldef char loginname[20];		/* players login name */
globaldef char logname[LOGNAMESIZE];	/* players name storage for scoring */
globaldef char sex=1;			/* default is a man  0=woman */
globaldef char boldon=1;		/* 1=bold objects  0=inverse objects */
globaldef char ckpflag=0;		/* 1 if want checkpointing of game, 0 otherwise	*/
globaldef char cheat=0;			/* 1 if the player has fudged save file */
globaldef char level=0;			/*  cavelevel player is on = c[CAVELEVEL] */
globaldef char wizard=0;		/* the wizard mode flag	*/
globaldef short lastnum=0;		/* the number of the monster last hitting player */
globaldef short hitflag=0;		/* flag for if player has been hit when running */
globaldef short hit2flag=0;		/* flag for if player has been hit when running */ 
globaldef short hit3flag=0;		/* flag for if player has been hit flush input */
globaldef short playerx,playery;	/* the room on the present level of the player */
globaldef short lastpx,lastpy;		/* 0 --- MAXX-1  or  0 --- MAXY-1 */
globaldef short oldx,oldy;
globaldef short lasthx=0,lasthy=0;	/* location of monster last hit by player */
globaldef short nobeep=0;		/* true if program is not to beep */
globaldef unsigned long rand_x=33601;	/* the random number seed */
globaldef long initialtime=0;		/* time playing began  */
globaldef long gtime=0;			/* the clock for the game */
globaldef long outstanding_taxes=0;	/* present tax bill from score file */
globaldef long c[100],cbak[100];	/* the character description arrays */
globaldef int enable_scroll=0;		/* constant for enabled/disabled scrolling regn */
globaldef char *aborted = " aborted";
globaldef struct sphere *spheres=0; 	/*pointer to linked list for spheres of annihilation*/
globaldef char *levelname[]=
{ " H"," 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10","V1","V2","V3" };

globaldef char objnamelist[]=" ATOP%^F&^+M=%^$$f*OD#~][[)))(((||||||||{?!BC}o:@.<<<<EVV))([[]]](^ [H*** ^^ S tsTLc............................................";
globaldef char monstnamelist[]=" BGHJKOScjtAELNQRZabhiCTYdegmvzFWflorXV pqsyUkMwDDPxnDDuD        ...............................................................";
globaldef char *objectname[]=
{ 0,"a holy altar","a handsome jewel encrusted throne","the orb","a pit",
  "a staircase leading upwards","an elevator going up","a bubbling fountain",
  "a great marble statue","a teleport trap","the college of Larn",
  "a mirror","the DND store","a staircase going down","an elevator going down",
  "the bank of Larn","the 5th branch of the Bank of Larn",
  "a dead fountain","gold","an open door","a closed door",
  "a wall","The Eye of Larn","plate mail","chain mail","leather armor",
  "a sword of slashing","Bessman's flailing hammer","a sunsword",
  "a two handed sword","a spear","a dagger",
  "ring of extra regeneration","a ring of regeneration","a ring of protection",
  "an energy ring","a ring of dexterity","a ring of strength",
  "a ring of cleverness","a ring of increase damage","a belt of striking",
  "a magic scroll","a magic potion","a book","a chest",
  "an amulet of invisibility","an orb of dragon slaying",
  "a scarab of negate spirit","a cube of undead control",
  "device of theft prevention","a brilliant diamond","a ruby",
  "an enchanting emerald","a sparkling sapphire","the dungeon entrance",
  "a volcanic shaft leaning downward","the base of a volcanic shaft",
  "a battle axe","a longsword","a flail","ring mail","studded leather armor",
  "splint mail","plate armor","stainless plate armor","a lance of death",
  "an arrow trap","an arrow trap","a shield","your home",
  "gold","gold","gold","a dart trap",
  "a dart trap","a trapdoor","a trapdoor","the local trading post",
  "a teleport trap", "a massive throne",
  "a sphere of annihilation","a handsome jewel encrusted throne",
  "the Larn Revenue Service","a fortune cookie","","","","","","",
  "","","","","","","","","","","","","","","","","","","",""
 };


/*
 *	for the monster data
 *
 *	array to do rnd() to create monsters <= a given level
 */
globaldef char monstlevel[] = { 5, 11, 17, 22, 27, 33, 39, 42, 46, 50, 53, 56, 59 };

globaldef struct monst monster[] = {
/* NAME			LV	AC	DAM	ATT	DEF	GEN INT GOLD	HP	EXP
------------------------------------------------------------------------------------------------- */
{ "",			0,	0,	0,	0,	0,	 0,  3,   0,	0,	0	},
{ "bat",		1,	0,	1,	0,	0,	 0,  3,   0,	1,	1	},
{ "gnome",		1,	10,	1,	0,	0,	 0,  8,  30,	2,	2	},
{ "hobgoblin",		1,	14,	2,	0,	0,	 0,  5,  25,	3,	2	},
{ "jackal",		1,	17,	1,	0,	0,	 0,  4,   0,	1,	1	},
{ "kobold",		1,	20,	1,	0,	0,	 0,  7,  10,	1,	1	},

{ "orc",		2,	12,	1,	0,	0,	 0,  9,  40,	4,	2	},
{ "snake",		2,	15,	1,	0,	0,	 0,  3,   0,	3,	1	},
{ "giant centipede",	2,	14,	0,	4,	0,	 0,  3,   0,	1,	2	},
{ "jaculi",		2,	20,	1,	0,	0,	 0,  3,   0,	2,	1	},
{ "troglodyte",		2,	10,	2,	0,	0,	 0,  5,  80,	4,	3	},
{ "giant ant",		2,	8,	1,	4,	0,	 0,  4,   0,	5,	5	},

/* NAME			LV	AC	DAM	ATT	DEF	GEN INT GOLD	HP	EXP
------------------------------------------------------------------------------------------------- */

{ "floating eye",	3,	8,	1,	0,	0,	 0,  3,   0,	 5,	 2	},
{ "leprechaun",		3,	3,	0,	8,	0,	 0,  3,1500,    13,	45	},
{ "nymph",		3,	3,	0,	14,	0,	 0,  9,   0,	18,	45	},
{ "quasit",		3,	5,	3,	0,	0,	 0,  3,   0,	10,	15	},
{ "rust monster",	3,	4,	0,	1,	0,	 0,  3,   0,	18,	25	},
{ "zombie",		3,	12,	2,	0,	0,	 0,  3,   0,	 6,	 7	},

{ "assassin bug",	4,	9,	3,	0,	0,	 0,  3,   0,	20,	15	},
{ "bugbear",		4,	5,	4,	15,	0,	 0,  5,  40,	20,	35	},
{ "hell hound",		4,	5,	2,	2,	0,	 0,  6,   0,	16,	35	},
{ "ice lizard",		4,	11,	2,	10,	0,	 0,  6,  50,	16,	25	},
{ "centaur",		4,	6,	4,	0,	0,	 0, 10,  40,	24,	45	},

/* NAME			LV	AC	DAM	ATT	DEF	GEN INT GOLD	HP	EXP
------------------------------------------------------------------------------------------------- */

{ "troll",		5,	4,	5,	0,	0,	 0,  9,  80,	50,	300	},
{ "yeti",		5,	6,	4,	0,	0,	 0,  5,  50, 	35,	100	},
{ "white dragon",	5,	2,	4,	5,	0,	 0, 16, 500,	55,	1000},
{ "elf",		5,	8,	1,	0,	0,	 0, 15,  50,	22,	35	},
{ "gelatinous cube",	5,	9,	1,	0,	0,	 0,  3,   0,	22,	45	},

{ "metamorph",		6,	7,	3,	0,	0,	 0,  3,  0,	30,	40	},
{ "vortex",		6,	4,	3,	0,	0,	 0,  3,  0,	30,	55	},
{ "ziller",		6,	15,	3,	0,	0,	 0,  3,  0,	30,	35	},
{ "violet fungi",	6,	12,	3,	0,	0,	 0,  3,  0, 	38,	100	},
{ "wraith",		6,	3,	1,	6,	0,	 0,  3,  0,	30,	325	},
{ "forvalaka",		6,	2,	5,	0,	0,	 0,  7,  0,	50,	280	},

/* NAME			LV	AC	DAM	ATT	DEF	GEN INT GOLD	HP	EXP
------------------------------------------------------------------------------------------------- */

{ "lama nobe",		7,	7,	3,	0,	0,	 0,  6,  0,	35,	80	},
{ "osequip",		7,	4,	3,	16,	0,	 0,  4,  0,	35,	100	},
{ "rothe",		7,	15,	5,	0,	0,	 0,  3,  100,	50,	250	},
{ "xorn",		7,	0,	6,	0,	0,	 0, 13,  0,	60,	300	},
{ "vampire",		7,	3,	4,	6,	0,	 0, 17,  0,	50,	1000},
{ "invisible stalker",	7,	3,	6,	0,	0,	 0,  5,  0,	50,	350	},

{ "poltergeist",	8,	1,	4,	0,	0,	 0,  3,  0,	50,	450	},
{ "disenchantress",	8,	3,	0,	9,	0,	 0,  3,  0,	50,	500	},
{ "shambling mound",	8,	2,	5,	0,	0,	 0,  6,  0,	45,	400	},
{ "yellow mold",	8,	12,	4,	0,	0,	 0,  3,  0,	35,	250	},
{ "umber hulk",		8,	3,	7,	11,	0,	 0, 14,  0,	65,	600	},

/* NAME			LV	AC	DAM	ATT	DEF	GEN INT GOLD	HP	EXP
------------------------------------------------------------------------------------------------- */

{ "gnome king",		9,	-1,	10,	0,	0,	 0, 18,  2000,	100,	3000	},
{ "mimic",		9,	 5,	6,	0,	0,	 0,  8,  0,	55,	99	},
{ "water lord",		9, 	-10,	15,	7,	0,	 0, 20,  0,	150,	15000	},
{ "bronze dragon",	9,	 2,	9,	3,	0,	 0, 16,  300,	80,	 4000	},
{ "green dragon",	9,	 3,	8,	10,	0,	 0, 15,  200,	70, 	2500	},
{ "purple worm",	9,	-1,	11,	0,	0,	 0,  3,  100,	120,	15000	},
{ "xvart",		9,	-2,	12,	0,	0,	 0, 13,  0,	90,	1000	},

{ "spirit naga",	10,	 -20,	12,	12,	0,	 0, 23,  0,	95,	 20000	},
{ "silver dragon",	10,	-1,	12,	3,	0,	 0, 20,  700,	100,	10000	},
{ "platinum dragon",	10,	-5,	15,	13,	0,	 0, 22,  1000,	130,	24000	},
{ "green urchin",	10,	-3,	12,	0,	0,	 0,  3,  0,	85,	5000	},
{ "red dragon",		10,	-2,	13,	3,	0,	 0, 19,  800,	110,	14000	},

{ "type I demon lord",	12,	-30,	18,	0,	0,	 0, 20,	 0,	140,	50000	},
{ "type II demon lord",	13,	-30,	18,	0,	0, 	 0, 21,  0,	160,	75000	},
{ "type III demon lord",14,	-30,	18,	0,	0, 	 0, 22,  0,	180,	100000	},
{ "type IV demon lord",	15,	-35,	20,	0,	0, 	 0, 23,  0,	200,	125000	},
{ "type V demon lord",	16,	-40,	22,	0,	0, 	 0, 24,  0,	220,	150000	},
{ "type VI demon lord",	17,	-45,	24,	0,	0, 	 0, 25,  0,	240,	175000	},
{ "type VII demon lord",18,	-70,	27,	6,	0, 	 0, 26,  0,	260,	200000	},
{ "demon prince",	25,	-127,	30,	6,	0, 	 0, 28,  0,	345,	300000	}

/* NAME			LV	AC	DAM	ATT	DEF	GEN INT GOLD	HP	EXP
------------------------------------------------------------------------------------------------- */
 };

/*	name array for scrolls		*/

globaldef char *scrollname[] = {
"\0enchant armor",
"\0enchant weapon",
"\0enlightenment",
"\0blank paper",
"\0create monster",
"\0create artifact",
"\0aggravate monsters",
"\0time warp",
"\0teleportation",
"\0expanded awareness",
"\0haste monsters",
"\0monster healing",
"\0spirit protection",
"\0undead protection",
"\0stealth",
"\0magic mapping",
"\0hold monsters",
"\0gem perfection",
"\0spell extension",
"\0identify",
"\0remove curse",
"\0annihilation",
"\0pulverization",
"\0life protection",
"\0 ",
"\0 ",
"\0 ",
"\0 "
 };

/*	name array for magic potions	*/
globaldef char *potionname[] = {
"\0sleep",
"\0healing",
"\0raise level",
"\0increase ability",
"\0wisdom",
"\0strength",
"\0raise charisma",
"\0dizziness",
"\0learning",
"\0gold detection",
"\0monster detection",
"\0forgetfulness",
"\0water",
"\0blindness",
"\0confusion",
"\0heroism",
"\0sturdiness",
"\0giant strength",
"\0fire resistance",
"\0treasure finding",
"\0instant healing",
" cure dianthroritis",
"\0poison",
"\0see invisible",
"\0 ",
"\0 ",
"\0 ",
"\0 ",
"\0 ",
"\0 ",
"\0 ",
"\0 ",
"\0 ",
"\0 ",
"\0 "
 };


/*
	spell data
 */
globaldef char spelknow[SPNUM] = 0;
globaldef char splev[] = { 1, 4, 9, 14, 18, 22, 26, 29, 32, 35, 37, 37, 37, 37, 37 };

globaldef char *spelcode[]={
	"pro",	"mle",	"dex",	"sle",	"chm",	"ssp",
	"web",	"str",	"enl",	"hel",	"cbl",	"cre",	"pha",	"inv",
	"bal",	"cld",	"ply",	"can",	"has",	"ckl",	"vpr",
	"dry",	"lit",	"drl",	"glo",	"flo",	"fgr",
	"sca",	"hld",	"stp",	"tel",	"mfi", /* 31 */
	"sph",	"gen",	"sum",	"wtw",	"alt",	"per"
 };

globaldef char *spelname[]={
	"protection",		"magic missile",		"dexterity",
	"sleep",		"charm monster",		"sonic spear",

	"web",			"strength",			"enlightenment",
	"healing",		"cure blindness",		"create monster",
	"phantasmal forces",	"invisibility",

	"fireball",		"cold",				"polymorph",
	"cancellation",		"haste self",			"cloud kill",
	"vaporize rock",

	"dehydration",		"lightning",			"drain life",
	"invulnerability",	"flood",			"finger of death",

	"scare monster",	"hold monster",			"time stop",
	"teleport away",	"magic fire",

	"sphere of annihilation",	"genocide",		"summon demon",
	"walk through walls",	"alter reality",		"permanence",
	""
 };

globaldef char *speldescript[]={
/* 1 */
	"generates a +2 protection field",
	"creates and hurls a magic missile equivalent to a + 1 magic arrow",
	"adds +2 to the casters dexterity",
	"causes some monsters to go to sleep",
	"some monsters may be awed at your magnificence",
	"causes your hands to emit a screeching sound toward what they point",
/* 7 */
	"causes strands of sticky thread to entangle an enemy",
	"adds +2 to the casters strength for a short term",
	"the caster becomes aware of things around him",
	"restores some hp to the caster",
	"restores sight to one so unfortunate as to be blinded",
	"creates a monster near the caster appropriate for the location",
	"creates illusions, and if believed, monsters die",
	"the caster becomes invisible",
/* 15 */
	"makes a ball of fire that burns on what it hits",
	"sends forth a cone of cold which freezes what it touches",
	"you can find out what this does for yourself",
	"negates the ability of a monster to use his special abilities",
	"speeds up the casters movements",
	"creates a fog of poisonous gas which kills all that is within it",
	"this changes rock to air",
/* 22 */
	"dries up water in the immediate vicinity",
	"you finger will emit a lightning bolt when this spell is cast",
	"subtracts hit points from both you and a monster",
	"this globe helps to protect the player from physical attack",
	"this creates an avalanche of H2O to flood the immediate chamber",
	"this is a holy spell and calls upon your god to back you up",
/* 28 */
	"terrifies the monster so that hopefully he wont hit the magic user",
	"the monster is frozen in his tracks if this is successful",
	"all movement in the caverns ceases for a limited duration",
	"moves a particular monster around in the dungeon (hopefully away from you)",
	"this causes a curtain of fire to appear all around you",
/* 33 */
	"anything caught in this sphere is instantly killed.  Warning -- dangerous",
	"eliminates a species of monster from the game -- use sparingly",
	"summons a demon who hopefully helps you out",
	"allows the player to walk through walls for a short period of time",
	"god only knows what this will do",
	"makes a character spell permanent, i. e. protection, strength, etc.",
	""
};

globaldef char spelweird[MAXMONST+8][SPNUM] = {
/*                      p m d s c s    w s e h c c p i    b c p c h c v    d l d g f f    s h s t m    s g s w a p */
/*                      r l e l h s    e t n e b r h n    a l l a a k p    r i r l l g    c l t e f    p e u t l e */
/*                      o e x e m p    b r l l l e a v    l d y n s l r    y t l o o r    a d p l i    h n m w t r */
	

/*            bat */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*          gnome */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,5,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*      hobgoblin */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*         jackal */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*         kobold */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,5,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*            orc */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   4,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*          snake */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*giant centipede */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*         jaculi */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*     troglodyte */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*      giant ant */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*   floating eye */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*     leprechaun */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*          nymph */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*         quasit */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*   rust monster */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   4,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*         zombie */ {  0,0,0,8,0,4,   0,0,0,0,0,0,0,0,   0,0,0,0,0,4,0,   4,0,0,0,0,4,   0,0,0,0,0,   0,0,0,0,0,0 },
/*   assassin bug */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*        bugbear */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,5,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*     hell hound */ {  0,6,0,0,0,0,   12,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*     ice lizard */ {  0,0,0,0,0,0,   11,0,0,0,0,0,0,0,  0,15,0,0,0,0,0,  0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*        centaur */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*          troll */ {  0,7,0,0,0,0,   0,0,0,0,0,0,0,5,   0,0,0,0,0,0,0,   4,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*           yeti */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,15,0,0,0,0,0,  0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*   white dragon */ {  0,0,0,0,0,0,   0,0,0,0,0,0,14,0,  0,15,0,0,0,0,0,  4,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*            elf */ {  0,0,0,0,0,0,   0,0,0,0,0,0,14,5,  0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*gelatinous cube */ {  0,0,0,0,0,0,   2,0,0,0,0,0,0,0,   0,0,0,0,0,4,0,   0,0,0,0,0,4,   0,0,0,0,0,   0,0,0,0,0,0 },
/*      metamorph */ {  0,13,0,0,0,0,  2,0,0,0,0,0,0,0,   0,0,0,0,0,4,0,   4,0,0,0,0,4,   0,0,0,0,0,   0,0,0,0,0,0 },
/*         vortex */ {  0,13,0,0,0,10, 1,0,0,0,0,0,0,0,   0,0,0,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   0,0,0,0,0,0 },
/*         ziller */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*   violet fungi */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*         wraith */ {  0,0,0,8,0,4,   0,0,0,0,0,0,0,0,   0,0,0,0,0,4,0,   4,0,0,0,0,4,   0,0,0,0,0,   0,0,0,0,0,0 },
/*      forvalaka */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,5,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*      lama nobe */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*        osequip */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*          rothe */ {  0,7,0,0,0,0,   0,0,0,0,0,0,0,5,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*           xorn */ {  0,7,0,0,0,0,   0,0,0,0,0,0,0,5,   0,0,0,0,0,0,0,   4,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*        vampire */ {  0,0,0,8,0,4,   0,0,0,0,0,0,0,0,   0,0,0,0,0,4,0,   0,0,0,0,0,4,   0,0,0,0,0,   0,0,0,0,0,0 },
/*invisible staker*/ {  0,0,0,0,0,0,   1,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*    poltergeist */ {  0,13,0,8,0,4,  1,0,0,0,0,0,0,0,   0,4,0,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   0,0,0,0,0,0 },

/* disenchantress */ {  0,0,0,8,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*shambling mound */ {  0,0,0,0,0,10,  0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*    yellow mold */ {  0,0,0,8,0,0,   1,0,0,0,0,0,4,0,   0,0,0,0,0,4,0,   0,0,0,0,0,4,   0,0,0,0,0,   0,0,0,0,0,0 },
/*     umber hulk */ {  0,7,0,0,0,0,   0,0,0,0,0,0,0,5,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*     gnome king */ {  0,7,0,0,3,0,   0,0,0,0,0,0,0,5,   0,0,9,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*          mimic */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*     water lord */ {  0,13,0,8,3,4,  1,0,0,0,0,0,0,0,   0,0,9,0,0,4,0,   0,0,0,0,16,4,  0,0,0,0,0,   0,0,0,0,0,0 },
/*  bronze dragon */ {  0,7,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*   green dragon */ {  0,7,0,0,0,0,   11,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*    purple worm */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*          xvart */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*    spirit naga */ {  0,13,0,8,3,4,  1,0,0,0,0,0,0,5,   0,4,9,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   0,0,0,0,0,0 },
/*  silver dragon */ {  0,6,0,9,0,0,   12,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*platinum dragon */ {  0,7,0,9,0,0,   11,0,0,0,0,0,14,0, 0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*   green urchin */ {  0,0,0,0,0,0,   0,0,0,0,0,0,0,0,   0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },
/*     red dragon */ {  0,6,0,0,0,0,   12,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,   0,0,0,0,0,0,   0,0,0,0,0,   0,0,0,0,0,0 },

/*                      p m d s c s    w s e h c c p i    b c p c h c v    d l d g f f    s h s t m    s g s w a p */
/*                      r l e l h s    e t n e b r h n    a l l a a k p    r i r l l g    c l t e f    p e u t l e */
/*                      o e x e m p    b r l l l e a v    l d y n s l r    y t l o o r    a d p l i    h n m w t r */

/*     demon lord */ {  0,7,0,4,3,0,   1,0,0,0,0,0,14,5,  0,0,4,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   9,0,0,0,0,0 },
/*     demon lord */ {  0,7,0,4,3,0,   1,0,0,0,0,0,14,5,  0,0,4,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   9,0,0,0,0,0 },
/*     demon lord */ {  0,7,0,4,3,0,   1,0,0,0,0,0,14,5,  0,0,4,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   9,0,0,0,0,0 },
/*     demon lord */ {  0,7,0,4,3,0,   1,0,0,0,0,0,14,5,  0,0,4,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   9,0,0,0,0,0 },
/*     demon lord */ {  0,7,0,4,3,0,   1,0,0,0,0,0,14,5,  0,0,4,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   9,0,0,0,0,0 },
/*     demon lord */ {  0,7,0,4,3,0,   1,0,0,0,0,0,14,5,  0,0,4,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   9,0,0,0,0,0 },
/*     demon lord */ {  0,7,0,4,3,0,   1,0,0,0,0,0,14,5,  0,0,4,0,0,4,0,   4,0,0,0,4,4,   0,0,0,0,0,   9,0,0,0,0,0 },
/*   demon prince */ {  0,7,0,4,3,9,   1,0,0,0,0,0,14,5,  0,0,4,0,0,4,0,   4,0,0,0,4,4,   4,0,0,0,4,   9,0,0,0,0,0 }

 };

globaldef char *spelmes[] = { "",
/*  1 */	"the web had no effect on the %s",
/*  2 */	"the %s changed shape to avoid the web",
/*  3 */	"the %s isn't afraid of you",
/*  4 */	"the %s isn't affected",
/*  5 */	"the %s can see you with his infravision",
/*  6 */	"the %s vaporizes your missile",
/*  7 */	"your missile bounces off the %s",
/*  8 */	"the %s doesn't sleep",
/*  9 */	"the %s resists",
/* 10 */	"the %s can't hear the noise",
/* 11 */	"the %s's tail cuts it free of the web",
/* 12 */	"the %s burns through the web",
/* 13 */	"your missiles pass right through the %s",
/* 14 */	"the %s sees through your illusions",
/* 15 */	"the %s loves the cold!",
/* 16 */	"the %s loves the water!"
 };

globaldef char to_lower[]= /* tolower[character] = lower case converted character */
{
    0000,0001,0002,0003,0004,0005,0006,0007,0010,0011,0012,0013,0014,0015,0016,0017, /* NUL-SI*/
    0020,0021,0022,0023,0024,0025,0026,0027,0030,0031,0032,0033,0034,0035,0036,0037, /* DLE-US*/
    0040,0041,0042,0043,0044,0045,0046,0047,0050,0051,0052,0053,0054,0055,0056,0057, /* SP-/ */
    0060,0061,0062,0063,0064,0065,0066,0067,0070,0071,0072,0073,0074,0075,0076,0077, /* 0-? */
    0100,0141,0142,0143,0144,0145,0146,0147,0150,0151,0152,0153,0154,0155,0156,0157, /* @-O */
    0160,0161,0162,0163,0164,0165,0166,0167,0170,0171,0172,0133,0134,0135,0136,0137, /* P-_ */
    0140,0141,0142,0143,0144,0145,0146,0147,0150,0151,0152,0153,0154,0155,0156,0157, /* `-o */
    0160,0161,0162,0163,0164,0165,0166,0167,0170,0171,0172,0173,0174,0175,0176,0177, /* p-DEL */
};

globaldef char to_upper[]= /* toupper[character] = upper case converted character */
{
    0000,0001,0002,0003,0004,0005,0006,0007,0010,0011,0012,0013,0014,0015,0016,0017, /* NUL-SI*/
    0020,0021,0022,0023,0024,0025,0026,0027,0030,0031,0032,0033,0034,0035,0036,0037, /* DLE-US*/
    0040,0041,0042,0043,0044,0045,0046,0047,0050,0051,0052,0053,0054,0055,0056,0057, /* SP-/ */
    0060,0061,0062,0063,0064,0065,0066,0067,0070,0071,0072,0073,0074,0075,0076,0077, /* 0-? */
    0100,0101,0102,0103,0104,0105,0106,0107,0110,0111,0112,0113,0114,0115,0116,0117, /* @-O */
    0120,0121,0122,0123,0124,0125,0126,0127,0130,0131,0132,0133,0134,0135,0136,0137, /* P-_ */
    0140,0101,0102,0103,0104,0105,0106,0107,0110,0111,0112,0113,0114,0115,0116,0117, /* `-o */
    0120,0121,0122,0123,0124,0125,0126,0127,0130,0131,0132,0173,0174,0175,0176,0177, /* p-DEL */
};

globaldef char is_digit[]=  /* isdigit[character] = TRUE || FALSE */
{
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* NUL-SI*/
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* DLE-US*/
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SP-/ */
    1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, /* 0-? */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* @-O */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* P-_ */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* `-o */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* p-DEL */
};

globaldef char is_alpha[]=  /* isalpha[character] = TRUE || FALSE */
{
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* NUL-SI*/
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* DLE-US*/
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SP-/ */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0-? */
    0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* @-O */
    1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, /* P-_ */
    0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* `-o */
    1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, /* p-DEL */
};


/*
 *	function to create scroll numbers with appropriate probability of 
 *	occurrence
 *
 *	0 - armor		1 - weapon			2 - enlightenment	3 - paper
 *	4 - create monster	5 - create item	6 - aggravate	7 - time warp
 *	8 - teleportation	9 - expanded awareness		10 - haste monst
 *	11 - heal monster	12 - spirit protection		13 - undead protection
 *	14 - stealth		15 - magic mapping		16 - hold monster
 *	17 - gem perfection	18 - spell extension		19 - identify
 *	20 - remove curse	21 - annihilation		22 - pulverization
 *	23 - life protection
 */
globaldef char scprob[]= { 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3,
	3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9,
	9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14,
	15, 15, 16, 16, 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, 20, 20, 21, 22,
	22, 22, 23 };

/*
 *	function to return a potion number created with appropriate probability
 *	of occurrence
 *
 *	0 - sleep			1 - healing			2 - raise level
 *	3 - increase ability		4 - gain wisdom			5 - gain strength
 *	6 - charismatic character	7 - dizziness			8 - learning
 *	9 - gold detection		10 - monster detection		11 - forgetfulness
 *	12 - water			13 - blindness			14 - confusion
 *	15 - heroism			16 - sturdiness			17 - giant strength
 *	18 - fire resistance		19 - treasure finding		20 - instant healing
 *	21 - cure dianthroritis		22 - poison			23 - see invisible
 */
globaldef char potprob[] = { 0, 0, 1, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 20, 22, 22, 23, 23 };

globaldef char nlpts[] = { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7 };
globaldef char nch[] = { 0, 0, 0, 1, 1, 1, 2, 2, 3, 4 };
globaldef char nplt[] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 4 };
globaldef char ndgg[] = { 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5 };
globaldef char nsw[] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3 };
SHAR_EOF
if test 31933 -ne "`wc -c < 'data.c'`"
then
	echo shar: error transmitting "'data.c'" '(should have been 31933 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)

Hello all!  This is a port of Larn v12.0 to VAX/VMS.  Now everyone can save
his/her daughter!!  Just unpack using /bin/sh and read readme.txt.

                                                - Mark Nagel

P.S.  Thanks to Lord Kahless for letting me post this!



-------------------------------cut here-------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	diag.c
#	display.c
#	fortune.c
#	global.c
#	header.h
#	help.c
# This archive created: Sat Aug 30 14:46:47 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'diag.c'" '(11426 characters)'
if test -f 'diag.c'
then
	echo shar: will not over-write existing file "'diag.c'"
else
cat << \SHAR_EOF > 'diag.c'

/*	diag.c		Larn is copyrighted 1986 by Noah Morgan. */

#include <times.h>
#include <stat.h>
#include "header.h"

extern int  rmst,maxitm,lasttime;

static struct tms cputime;
/*
	***************************
	DIAG -- dungeon diagnostics
	***************************

	subroutine to print out data for debugging
 */
#ifdef EXTRA

static int  rndcount[16];

diag()
{
    register int i,j;
    int hit,dam;

    cursors();
    lwclose();
    if (lcreat(diagfile) < 0) {    /* open the diagnostic file */
	lcreat((char *) 0);
	lprcat("\ndiagnostic failure\n");
	return(-1);
    }

    write(1, "\nDiagnosing . . .\n", 18);
    lprcat("\n\nBeginning of DIAG diagnostics ----------\n");

    /* for the character attributes */

    lprintf("\n\nPlayer attributes:\n\nHit points: %2d(%2d)",(long) c[HP],(long) c[HPMAX]);
    lprintf("\ngold: %d  Experience: %d  Character level: %d  Level in caverns: %d",
	   (long) c[GOLD],(long) c[EXPERIENCE],(long) c[LEVEL],(long) level);
    lprintf("\nTotal types of monsters: %d",(long) MAXMONST + 8);

    lprcat("\f\nHere's the dungeon:\n\n");

    i = level;
    for (j = 0; j < MAXLEVEL + MAXVLEVEL; j++) {
	newcavelevel(j);
	lprintf("\nMaze for level %s:\n", levelname[level]);
	diagdrawscreen();
    }
    newcavelevel(i);

    lprcat("\f\nNow for the monster data:\n\n");
    lprcat("   Monster Name      LEV  AC   DAM  ATT  DEF    GOLD   HP     EXP   \n");
    lprcat("--------------------------------------------------------------------------\n");
    for (i = 0; i <= MAXMONST + 8; i++) {
	lprintf("%19s  %2d  %3d ", monster[i].name,(long) monster[i].level,(long) monster[i].armorclass);
	lprintf(" %3d  %3d  %3d  ",(long) monster[i].damage,(long) monster[i].attack,(long) monster[i].defense);
	lprintf("%6d  %3d   %6d\n",(long) monster[i].gold,(long) monster[i].hitpoints,(long) monster[i].experience);
    }

    lprcat("\n\nHere's a Table for the to hit percentages\n");
    lprcat("\n     We will be assuming that players level = 2 * monster level");
    lprcat("\n     and that the players dexterity and strength are 16.");
    lprcat("\n    to hit: if (rnd(22) <(2[monst AC] + your level + dex + WC/8 -1)/2) then hit");
    lprcat("\n    damage = rund(8) + WC/2 + STR - c[HARDGAME] - 4");
    lprcat("\n    to hit:  if rnd(22) < to hit  then player hits\n");
    lprcat("\n    Each entry is as follows:  to hit / damage / number hits to kill\n");
    lprcat("\n          monster     WC = 4         WC = 20        WC = 40");
    lprcat("\n---------------------------------------------------------------");
    for (i = 0; i <= MAXMONST + 8; i++) {
	hit = 2 * monster[i].armorclass + 2 * monster[i].level + 16;
	dam = 16 - c[HARDGAME];
	lprintf("\n%20s   %2d/%2d/%2d       %2d/%2d/%2d       %2d/%2d/%2d",
		monster[i].name,
		(long)(hit / 2),(long) max(0, dam + 2),(long)(monster[i].hitpoints /(dam + 2) + 1),
		(long)((hit + 2) / 2),(long) max(0, dam + 10),(long)(monster[i].hitpoints /(dam + 10) + 1),
		(long)((hit + 5) / 2),(long) max(0, dam + 20),(long)(monster[i].hitpoints /(dam + 20) + 1));
    }

    lprcat("\n\nHere's the list of available potions:\n\n");
    for (i = 0; i < MAXPOTION; i++)
	lprintf("%20s\n", &potionname[i][1]);
    lprcat("\n\nHere's the list of available scrolls:\n\n");
    for (i = 0; i < MAXSCROLL; i++)
	lprintf("%20s\n", &scrollname[i][1]);
    lprcat("\n\nHere's the spell list:\n\n");
    lprcat("spell          name           description\n");
    lprcat("-------------------------------------------------------------------------------------------\n\n");
    for (j = 0; j < SPNUM; j++) {
	lprc(' ');
	lprcat(spelcode[j]);
	lprintf(" %21s  %s\n", spelname[j], speldescript[j]);
    }

    lprcat("\n\nFor the c[] array:\n");
    for (j = 0; j < 100; j += 10) {
	lprintf("\nc[%2d] = ",(long) j);
	for (i = 0; i < 9; i++)
	    lprintf("%5d ",(long) c[i + j]);
    }

    lprcat("\n\nTest of random number generator ----------------");
    lprcat("\n    for 25,000 calls divided into 16 slots\n\n");

    for (i = 0; i < 16; i++)
	rndcount[i] = 0;
    for (i = 0; i < 25000; i++)
	rndcount[rund(16)]++;
    for (i = 0; i < 16; i++) {
	lprintf("  %5d",(long) rndcount[i]);
	if (i == 7)
	    lprc('\n');
    }

    lprcat("\n\n");
    lwclose();
    lcreat((char *) 0);
    lprcat("Done Diagnosing . . .");
    return(0);
}

/*
	subroutine to count the number of occurrences of an object
 */
dcount(l)
int l;
{
    register int i,j,p;
    int k = 0;

    for (i = 0; i < MAXX; i++)
	for (j = 0; j < MAXY; j++)
	    for (p = 0; p < MAXLEVEL; p++)
		if (cell[p * MAXX * MAXY + i * MAXY + j].item == l)
		    k++;
    return(k);
}

/*
	subroutine to draw the whole screen as the player knows it
 */
diagdrawscreen()
{
    register int i,j,k;

    for (i = 0; i < MAXY; i++) {    /* for the east west walls of this line */
	for (j = 0; j < MAXX; j++)
	    if (k = mitem[j][i])
		lprc(monstnamelist[k]);
	    else
		lprc(objnamelist[item[j][i]]);
	lprc('\n');
    }
}
#endif


/*
	to save the game in a file
 */

static long int zzz = 0;

savegame(fname)
char *fname;
{
    register int i,k;
    register struct sphere *sp;
    struct stat statbuf;

    nosignal = 1;
    lflush();
    savelevel();
    ointerest();
    if (lcreat(fname) < 0) {
	lcreat((char *) 0);
	lprintf("\nCan't open file \"%s\" to save game\n", fname);
	nosignal = 0;
	return(-1);
    }

    set_score_output();
    lwrite((char *) beenhere, MAXLEVEL + MAXVLEVEL);
    for (k = 0; k < MAXLEVEL + MAXVLEVEL; k++)
	if (beenhere[k])
	    lwrite((char *) & cell[k * MAXX * MAXY], sizeof(struct cel) * MAXY * MAXX);
    times(&cputime);		/* get cpu time */
    c[CPUTIME] += (cputime.tms_utime + cputime.tms_stime - start_cpu) / 100;
    lwrite((char *) &c[0], 100 * sizeof(long));
    lprint((long) gtime);
    lprc(level);
    lprc(playerx);
    lprc(playery);
    lwrite((char *) iven, 26);
    lwrite((char *) ivenarg, 26 * sizeof(short));
    for (k = 0; k < MAXSCROLL; k++)
	lprc(scrollname[k][0]);
    for (k = 0; k < MAXPOTION; k++)
	lprc(potionname[k][0]);
    lwrite((char *) spelknow, SPNUM);
    lprc(wizard);
    lprc(rmst);	/* random monster generation counter */
    for (i = 0; i < 90; i++)
	lprc(itm[i].qty);
    lwrite((char *) course, 25);
    lprc(cheat);
    lprc(VERSION);
    for (i = 0; i < MAXMONST; i++)
	lprc(monster[i].genocided);/* genocide info */
    for (sp = spheres; sp; sp = sp -> p)
	lwrite((char *) sp, sizeof(struct sphere));/* save spheres of annihilation */
    time(&zzz);
    lprint((long)(zzz - initialtime));
    lwrite((char *) & zzz, sizeof(long));
    if (fstat(lfd, &statbuf) < 0)
	lprint(0L);
    else {
	lprint((long) statbuf.st_ino[0]);    /* inode # */
	lprint((long) statbuf.st_ino[1]);    /* inode # */
	lprint((long) statbuf.st_ino[2]);    /* inode # */
    }	
    lwclose();
    lastmonst[0] = 0;
#ifndef VT100
    setscroll();
#endif VT100
    lcreat((char *) 0);
    nosignal = 0;
    return(0);
}

restoregame(fname)
char   *fname;
{
    register int    i,k;
    register struct sphere *sp,*sp2;
    struct stat filetimes;

    cursors();
    lprcat("\nRestoring . . .");
    lflush();
    if (lopen(fname) <= 0) {
	lcreat((char *) 0);
	lprintf("\nCan't open file \"%s\" to restore game\n", fname);
	nap(2000);
	c[GOLD] = c[BANKACCOUNT] = 0;
	died(-265);
	return;
    }

    lrfill((char *) beenhere, MAXLEVEL + MAXVLEVEL);
    for (k = 0; k < MAXLEVEL + MAXVLEVEL; k++)
	if (beenhere[k])
	    lrfill((char *) & cell[k * MAXX * MAXY], sizeof(struct cel) * MAXY * MAXX);

    lrfill((char *) & c[0], 100 * sizeof(long));
    gtime = lrint();
    level = c[CAVELEVEL] = lgetc();
    playerx = lgetc();
    playery = lgetc();
    lrfill((char *) iven, 26);
    lrfill((char *) ivenarg, 26 * sizeof(short));
    for (k = 0; k < MAXSCROLL; k++)
	scrollname[k][0] = lgetc();
    for (k = 0; k < MAXPOTION; k++)
	potionname[k][0] = lgetc();
    lrfill((char *) spelknow, SPNUM);
    wizard = lgetc();
    rmst = lgetc();		/* random monster creation flag */

    for (i = 0; i < 90; i++)
	itm[i].qty = lgetc();
    lrfill((char *) course, 25);
    cheat = lgetc();
    if (VERSION != lgetc()) {	/* version number */
	cheat = 1;
	lprcat("Sorry, But your save file is for an older version of larn\n");
	nap(2000);
	c[GOLD] = c[BANKACCOUNT] = 0;
	died(-266);
	return;
    }

    for (i = 0; i < MAXMONST; i++)
	monster[i].genocided = lgetc();/* genocide info */
    for (sp = 0, i = 0; i < c[SPHCAST]; i++) {
	sp2 = sp;
	sp =(struct sphere *) malloc(sizeof(struct sphere));
	if (sp == 0) {
	    write(2, "Can't malloc() for sphere space\n", 32);
	    break;
	}
	lrfill((char *) sp, sizeof(struct sphere));/* get spheres of annihilation */
	sp->p = 0;		/* null out pointer */
	if (i == 0)
	    spheres = sp;	/* beginning of list */
	else
	    sp2->p = sp;
    }

    time(&zzz);
    initialtime = zzz - lrint();
    fstat(fd, &filetimes);	/* 	get the creation and modification time of file	 */
    lrfill((char *) & zzz, sizeof(long));
    zzz += 6;
    if (filetimes.st_ctime > zzz)
	fsorry();		/*  file create time */
    else
	if (filetimes.st_mtime > zzz)
	    fsorry();		/* file modify time */
    if (c[HP] < 0) {
	died(284);
	return;
    }				/* died a post mortem death */

    oldx = oldy = 0;
    i = lrint();		/* inode # */
    if (i &&(filetimes.st_ino[0] != i))
	fsorry();
    i = lrint();		/* inode # */
    if (i &&(filetimes.st_ino[1] != i))
	fsorry();
    i = lrint();		/* inode # */
    if (i &&(filetimes.st_ino[2] != i))
	fsorry();
    lrclose();
    if (strcmp(fname, ckpfile) == 0) {
	if (lappend(fname) < 0)
	    fcheat();
	else {
	    lprc(' ');
	    lwclose();
	}
	lcreat((char *) 0);
    } else
	if (delete(fname) < 0)
	    fcheat();		/* can't unlink save file */
     /* for the greedy cheater checker */
    for (k = 0; k < 6; k++)
	if (c[k] > 99)
	    greedy();
    if (c[HPMAX] > 999 || c[SPELLMAX] > 125)
	greedy();
    if (c[LEVEL] == 25 && c[EXPERIENCE] > skill[24]) {/* if patch up lev 25 player */
	long    tmp;
	tmp = c[EXPERIENCE] - skill[24];/* amount to go up */
	c[EXPERIENCE] = skill[24];
	raiseexperience((long) tmp);
    }
    getlevel();
    lasttime = gtime;
}

/*
	subroutine to not allow greedy cheaters
 */
greedy() {
#if WIZID
    if (wizard)
	return;
#endif

    lprcat("\n\nI am so sorry, but your character is a little TOO good!  Since this\n");
    lprcat("cannot normally happen from an honest game, I must assume that you cheated.\n");
    lprcat("In that you are GREEDY as well as a CHEATER, I cannot allow this game\n");
    lprcat("to continue.\n");
    nap(5000);
    c[GOLD] = c[BANKACCOUNT] = 0;
    died(-267);
    return;
}

/*
	subroutine to not allow altered save files and terminate the attempted
	restart
 */
fsorry()
{
    lprcat("\nSorry, but your savefile has been altered.\n");
    lprcat("However, seeing as I am a good sport, I will let you play.\n");
    lprcat("Be advised though, you won't be placed on the normal scoreboard.");
    cheat = 1;
    nap(4000);
}

/*
	subroutine to not allow game if save file can't be deleted
 */
fcheat() {
#if WIZID
    if (wizard)
	return;
#endif

    lprcat("\nSorry, but your savefile can't be deleted.  This can only mean\n");
    lprcat("that you tried to CHEAT by protecting the directory the savefile\n");
    lprcat("is in.  Since this is unfair to the rest of the larn community, I\n");
    lprcat("cannot let you play this game.\n");
    nap(5000);
    c[GOLD] = c[BANKACCOUNT] = 0;
    died(-268);
    return;
}
SHAR_EOF
if test 11426 -ne "`wc -c < 'diag.c'`"
then
	echo shar: error transmitting "'diag.c'" '(should have been 11426 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'display.c'" '(13152 characters)'
if test -f 'display.c'
then
	echo shar: will not over-write existing file "'display.c'"
else
cat << \SHAR_EOF > 'display.c'

/*	display.c		Larn is copyrighted 1986 by Noah Morgan. */

#include "header.h"

#define makecode(_a,_b,_c)(((_a)<<16) +((_b)<<8) +(_c))

static int  minx,maxx,miny,maxy,k,m;
static char bot1f = 0,bot2f = 0,bot3f = 0;

char always = 0;
/*
	bottomline()

	now for the bottom line of the display
 */
bottomline()
{
    recalc();
    bot1f = 1;
}

bottomhp()
{
    bot2f = 1;
}

bottomspell()
{
    bot3f = 1;
}

bottomdo()
{
    if (bot1f) {
	bot3f = bot1f = bot2f = 0;
	bot_linex();
	return;
    }
    if (bot2f) {
	bot2f = 0;
	bot_hpx();
    }
    if (bot3f) {
	bot3f = 0;
	bot_spellx();
    }
}

bot_linex()
{
    register int i;

    if (cbak[SPELLS] <= -50 ||(always)) {
	cursor(1, 18);
	if (c[SPELLMAX] > 99)
	    lprintf("Spells:%3d(%3d)",(long) c[SPELLS],(long) c[SPELLMAX]);
	else
	    lprintf("Spells:%3d(%2d) ",(long) c[SPELLS],(long) c[SPELLMAX]);
	lprintf(" AC: %-3d  WC: %-3d  Level",(long) c[AC],(long) c[WCLASS]);
	if (c[LEVEL] > 99)
	    lprintf("%3d",(long) c[LEVEL]);
	else
	    lprintf(" %-2d",(long) c[LEVEL]);
	lprintf(" Exp: %-9d %s\n",(long) c[EXPERIENCE], class[c[LEVEL] - 1]);
	lprintf("HP: %3d(%3d) STR=%-2d INT=%-2d ",
		(long) c[HP],(long) c[HPMAX],(long)(c[STRENGTH] + c[STREXTRA]),(long) c[INTELLIGENCE]);
	lprintf("WIS=%-2d CON=%-2d DEX=%-2d CHA=%-2d LV:",
		(long) c[WISDOM],(long) c[CONSTITUTION],(long) c[DEXTERITY],(long) c[CHARISMA]);

	if ((level == 0) ||(wizard))
	    c[TELEFLAG] = 0;
	if (c[TELEFLAG])
	    lprcat(" ?");
	else
	    lprcat(levelname[level]);
	lprintf("  Gold: %-6d",(long) c[GOLD]);
	always = 1;
	botside();
	c[TMP] = c[STRENGTH] + c[STREXTRA];
	for (i = 0; i < 100; i++)
	    cbak[i] = c[i];
	return;
    }

    botsub(makecode(SPELLS, 8, 18), "%3d");
    if (c[SPELLMAX] > 99)
	botsub(makecode(SPELLMAX, 12, 18), "%3d)");
    else
	botsub(makecode(SPELLMAX, 12, 18), "%2d) ");
    botsub(makecode(HP, 5, 19), "%3d");
    botsub(makecode(HPMAX, 9, 19), "%3d");
    botsub(makecode(AC, 21, 18), "%-3d");
    botsub(makecode(WCLASS, 30, 18), "%-3d");
    botsub(makecode(EXPERIENCE, 49, 18), "%-9d");
    if (c[LEVEL] != cbak[LEVEL]) {
	cursor(59, 18);
	lprcat(class[c[LEVEL] - 1]);
    }
    if (c[LEVEL] > 99)
	botsub(makecode(LEVEL, 40, 18), "%3d");
    else
	botsub(makecode(LEVEL, 40, 18), " %-2d");
    c[TMP] = c[STRENGTH] + c[STREXTRA];
    botsub(makecode(TMP, 18, 19), "%-2d");
    botsub(makecode(INTELLIGENCE, 25, 19), "%-2d");
    botsub(makecode(WISDOM, 32, 19), "%-2d");
    botsub(makecode(CONSTITUTION, 39, 19), "%-2d");
    botsub(makecode(DEXTERITY, 46, 19), "%-2d");
    botsub(makecode(CHARISMA, 53, 19), "%-2d");
    if ((level != cbak[CAVELEVEL]) ||(c[TELEFLAG] != cbak[TELEFLAG])) {
	if ((level == 0) ||(wizard))
	    c[TELEFLAG] = 0;
	cbak[TELEFLAG] = c[TELEFLAG];
	cbak[CAVELEVEL] = level;
	cursor(59, 19);
	if (c[TELEFLAG])
	    lprcat(" ?");
	else
	    lprcat(levelname[level]);
    }
    botsub(makecode(GOLD, 69, 19), "%-6d");
    botside();
}

/*
	special subroutine to update only the gold number on the bottomlines
	called from ogold()
 */
bottomgold()
{
    botsub(makecode(GOLD, 69, 19), "%-6d");
 /* 	botsub(GOLD,"%-6d",69,19); */
}

/*
	special routine to update hp and level fields on bottom lines
	called in monster.c hitplayer() and spattack()
 */
bot_hpx()
{
    if (c[EXPERIENCE] != cbak[EXPERIENCE]) {
	recalc();
	bot_linex();
    } else
	botsub(makecode(HP, 5, 19), "%3d");
}

/*
	special routine to update number of spells called from regen()
 */
bot_spellx()
{
    botsub(makecode(SPELLS, 9, 18), "%2d");
}

/*
	common subroutine for a more economical bottomline()
 */
static struct bot_side_def {
    int typ;
    char *string;
} bot_data[] =
{
    STEALTH, "stealth", UNDEADPRO, "undead pro", SPIRITPRO, "spirit pro",
    CHARMCOUNT, "Charm", TIMESTOP, "Time Stop", HOLDMONST, "Hold Monst",
    GIANTSTR, "Giant Str", FIRERESISTANCE, "Fire Resit", DEXCOUNT, "Dexterity",
    STRCOUNT, "Strength", SCAREMONST, "Scare", HASTESELF, "Haste Self",
    CANCELLATION, "Cancel", INVISIBILITY, "Invisible", ALTPRO, "Protect 3",
    PROTECTIONTIME, "Protect 2", WTW, "Wall-Walk"
};

botside()
{
    register int i,idx;

    for (i = 0; i < 17; i++) {
	idx = bot_data[i].typ;
	if ((always) ||(c[idx] != cbak[idx])) {
	    if ((always) ||(cbak[idx] == 0)) {
		if (c[idx]) {
		    cursor(70, i + 1);
		    lprcat(bot_data[i].string);
		}
	    } else
		if (c[idx] == 0) {
		    cursor(70, i + 1);
		    lprcat("          ");
		}
	    cbak[idx] = c[idx];
	}
    }
    always = 0;
}

static  botsub(idx, str)
register int idx;
char *str;
{
    register int x,y;

    y = idx & 0xff;
    x =(idx >> 8) & 0xff;
    idx >>= 16;
    if (c[idx] != cbak[idx]) {
	cbak[idx] = c[idx];
	cursor(x, y);
	lprintf(str,(long) c[idx]);
    }
}

/*
 *	subroutine to draw only a section of the screen
 *	only the top section of the screen is updated.  If entire lines
 *	are being drawn, then they will be cleared first.
 */
int d_xmin = 0,d_xmax = MAXX,d_ymin = 0,d_ymax = MAXY; /* for limited screen drawing */
draws(xmin, xmax, ymin, ymax)
int xmin,xmax,ymin,ymax;
{
    register int    i,idx;

    if (xmin == 0 && xmax == MAXX) {	/* clear section of screen as needed */
	if (ymin == 0)
	    cl_up(79, ymax);
	else
	    for (i = ymin; i < ymin; i++)
		cl_line(1, i + 1);
	xmin = -1;
    }
    d_xmin = xmin;
    d_xmax = xmax;
    d_ymin = ymin;
    d_ymax = ymax;		/* for limited screen drawing */
    drawscreen();
    if (xmin <= 0 && xmax == MAXX) {/* draw stuff on right side of screen as needed */
	for (i = ymin; i < ymax; i++) {
	    idx = bot_data[i].typ;
	    if (c[idx]) {
		cursor(70, i + 1);
		lprcat(bot_data[i].string);
	    }
	    cbak[idx] = c[idx];
	}
    }
}

/*
	drawscreen()

	subroutine to redraw the whole screen as the player knows it
 */
globaldef char screen[MAXX][MAXY];	/* template for the screen */
char d_flag;
drawscreen()
{
    register int i,j,k;
    int lastx,lasty;	/* variables used to optimize the object printing */

    if (d_xmin == 0 && d_xmax == MAXX && d_ymin == 0 && d_ymax == MAXY) {
	d_flag = 1;
	clear();		/* clear the screen */
    } else {
	d_flag = 0;
	cursor(1, 1);
    }
    if (d_xmin < 0)
	d_xmin = 0;	/* d_xmin=-1 means display all without bottomline */

    for (i = d_ymin; i < d_ymax; i++)
	for (j = d_xmin; j < d_xmax; j++)
	    if (know[j][i] == 0)
		screen[j][i] = ' ';
	    else if (k = mitem[j][i])
		screen[j][i] = monstnamelist[k];
	    else if ((k = item[j][i]) == OWALL)
		screen[j][i] = '#';
	    else
		screen[j][i] = ' ';

    for (i = d_ymin; i < d_ymax; i++) {
	j = d_xmin;
	while ((screen[j][i] == ' ') &&(j < d_xmax))
	    j++;
    /* was m=0 */
	if (j >= d_xmax)
	    m = d_xmin;		/* don't search backwards if blank line */
	else {			/* search backwards for end of line */
	    m = d_xmax - 1;
	    while ((screen[m][i] == ' ') &&(m > d_xmin))
		--m;
	    if (j <= m)
		cursor(j + 1, i + 1);
	    else
		continue;
	}
	while (j <= m) {
	    if (j <= m - 3) {
		for (k = j; k <= j + 3; k++)
		    if (screen[k][i] != ' ')
			k = 1000;
		if (k < 1000) {
		    while (screen[j][i] == ' ' && j <= m)
			j++;
		    cursor(j + 1, i + 1);
		}
	    }
	    lprc(screen[j++][i]);
	}
    }
    setbold();			/* print out only bold objects now */

    for (lastx = lasty = 127, i = d_ymin; i < d_ymax; i++)
	for (j = d_xmin; j < d_xmax; j++) {
	    if (k = item[j][i])
		if (k != OWALL)
		    if ((know[j][i]) &&(mitem[j][i] == 0))
			if (objnamelist[k] != ' ') {
			    if (lasty != i + 1 || lastx != j)
				cursor(lastx = j + 1, lasty = i + 1);
			    else
				lastx++;
			    lprc(objnamelist[k]);
			}
	}

    resetbold();
    if (d_flag) {
	always = 1;
	botside();
	always = 1;
	bot_linex();
    }
    oldx = 99;
    d_xmin = 0, d_xmax = MAXX, d_ymin = 0, d_ymax = MAXY;/* for limited screen drawing */
}


/*
	showcell(x,y)

	subroutine to display a cell location on the screen
 */
showcell(x, y)
int x,y;
{
    register int i,j,k,m;

    if (c[BLINDCOUNT])
	return;			/* see nothing if blind	*/
    if (c[AWARENESS]) {
	minx = x - 3;
	maxx = x + 3;
	miny = y - 3;
	maxy = y + 3;
    } else {
	minx = x - 1;
	maxx = x + 1;
	miny = y - 1;
	maxy = y + 1;
    }

    if (minx < 0)
	minx = 0;
    if (maxx > MAXX - 1)
	maxx = MAXX - 1;
    if (miny < 0)
	miny = 0;
    if (maxy > MAXY - 1)
	maxy = MAXY - 1;

    for (j = miny; j <= maxy; j++)
	for (m = minx; m <= maxx; m++)
	    if (know[m][j] == 0) {
		cursor(m + 1, j + 1);
		x = maxx;
		while (know[x][j])
		    --x;
		for (i = m; i <= x; i++) {
		    if ((k = mitem[i][j]) != 0)
			lprc(monstnamelist[k]);
		    else
			switch(k = item[i][j]) {
			    case OWALL: 
			    case 0: 
			    case OIVTELETRAP: 
			    case OTRAPARROWIV: 
			    case OIVDARTRAP: 
			    case OIVTRAPDOOR: 
				lprc(objnamelist[k]);
				break;

			    default: 
				setbold();
				lprc(objnamelist[k]);
				resetbold();
			};
		    know[i][j] = 1;
		}
		m = maxx;
	    }
}

/*
	this routine shows only the spot that is given it.  the spaces around
	these coordinated are not shown
	used in godirect() in monster.c for missile weapons display
 */
show1cell(x, y)
int x,y;
{
    if (c[BLINDCOUNT])
	return;			/* see nothing if blind		 */
    cursor(x + 1, y + 1);
    if ((k = mitem[x][y]) != 0)
	lprc(monstnamelist[k]);
    else
	switch(k = item[x][y]) {
	    case OWALL: 
	    case 0: 
	    case OIVTELETRAP: 
	    case OTRAPARROWIV: 
	    case OIVDARTRAP: 
	    case OIVTRAPDOOR: 
		lprc(objnamelist[k]);
		break;

	    default: 
		setbold();
		lprc(objnamelist[k]);
		resetbold();
	};
    know[x][y] |= 1;		/* we end up knowing about it */
}

/*
	showplayer()

	subroutine to show where the player is on the screen
	cursor values start from 1 up
 */
showplayer()
{
    cursor(playerx + 1, playery + 1);
    oldx = playerx;
    oldy = playery;
}

/*
	moveplayer(dir)

	subroutine to move the player from one room to another
	returns 0 if can't move in that direction or hit a monster or on an object
	else returns 1
	nomove is set to 1 to stop the next move(inadvertent monsters hitting
	players when walking into walls) if player walks off screen or into wall
 */
globaldef short diroffx[] = {
    0, 0, 1, 0, -1, 1, -1, 1, -1
};
globaldef short diroffy[] = {
    0, 1, 0, -1, 0, -1, -1, 1, 1
};
moveplayer(dir)
int dir;   /* from = present room #
		direction = [1-north] [2-east] [3-south] [4-west] [5-northeast]
			    [6-northwest] [7-southeast] [8-southwest]
		if direction=0, don't move--just show where he is */
{
    register int k,m,i,j;

    if (c[CONFUSE])
	if (c[LEVEL] < rnd(30))
	    dir = rund(9);	/* if confused any dir */
    k = playerx + diroffx[dir];
    m = playery + diroffy[dir];
    if (k < 0 || k >= MAXX || m < 0 || m >= MAXY) {
	nomove = 1;
	return(yrepcount = 0);
    }
    i = item[k][m];
    j = mitem[k][m];
    if (i == OWALL && c[WTW] == 0) {
	nomove = 1;
	return(yrepcount = 0);
    }				/* hit a wall */
    if (k == 33 && m == MAXY - 1 && level == 1) {
	newcavelevel(0);
	for (k = 0; k < MAXX; k++)
	    for (m = 0; m < MAXY; m++)
		if (item[k][m] == OENTRANCE) {
		    playerx = k;
		    playery = m;
		    positionplayer();
		    drawscreen();
		    return(0);
		}
    }
    if (j > 0) {
	hitmonster(k, m);
	return(yrepcount = 0);
    }				/* hit a monster */
    lastpx = playerx;
    lastpy = playery;
    playerx = k;
    playery = m;
    if (i && i != OTRAPARROWIV && i != OIVTELETRAP && i != OIVDARTRAP && i != OIVTRAPDOOR)
	return(yrepcount = 0);
    else
	return(1);
}


/*
 *	function to show what magic items have been discovered thus far
 *	enter with -1 for just spells, anything else will give scrolls & potions
 */
static int  lincount,count;
seemagic(arg)
int arg;
{
    register int    i,number;

    count = lincount = 0;
    nosignal = 1;

    if (arg == -1) {		/* if display spells while casting one */
	for (number = i = 0; i < SPNUM; i++)
	    if (spelknow[i])
		number++;
	number =(number + 2) / 3 + 4;/* # lines needed to display */
	cl_up(79, number);
	cursor(1, 1);
    } else {
	resetscroll();
	clear();
    }

    lprcat("The magic spells you have discovered thus far:\n\n");
    for (i = 0; i < SPNUM; i++)
	if (spelknow[i]) {
	    lprintf("%s %-20s ", spelcode[i], spelname[i]);
	    seepage();
	}

    if (arg == -1) {
	seepage();
	more();
	nosignal = 0;
	draws(0, MAXX, 0, number);
	return;
    }

    lincount += 3;
    if (count != 0) {
	count = 2;
	seepage();
    }

    lprcat("\nThe magic scrolls you have found to date are:\n\n");
    count = 0;
    for (i = 0; i < MAXSCROLL; i++)
	if (scrollname[i][0])
	    if (scrollname[i][1] != ' ') {
		lprintf("%-26s", &scrollname[i][1]);
		seepage();
	    }

    lincount += 3;
    if (count != 0) {
	count = 2;
	seepage();
    }

    lprcat("\nThe magic potions you have found to date are:\n\n");
    count = 0;
    for (i = 0; i < MAXPOTION; i++)
	if (potionname[i][0])
	    if (potionname[i][1] != ' ') {
		lprintf("%-26s", &potionname[i][1]);
		seepage();
	    }

    if (lincount != 0)
	more();
    nosignal = 0;
    setscroll();
    drawscreen();
}


/*
 *	subroutine to paginate the seemagic function
 */
seepage()
{
    if (++count == 3) {
	lincount++;
	count = 0;
	lprc('\n');
	if (lincount > 17) {
	    lincount = 0;
	    more();
	    clear();
	}
    }
}
SHAR_EOF
if test 13152 -ne "`wc -c < 'display.c'`"
then
	echo shar: error transmitting "'display.c'" '(should have been 13152 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'fortune.c'" '(1991 characters)'
if test -f 'fortune.c'
then
	echo shar: will not over-write existing file "'fortune.c'"
else
cat << \SHAR_EOF > 'fortune.c'

/* fortune.c		 Larn is copyrighted 1986 by Noah Morgan. */

#include <stat.h>
#include <file.h>

#include "header.h"

/*
 *	function to return a random fortune from the fortune file
 */
static char *base = 0;		/* pointer to the fortune text */
static char **flines = 0;	/* array of pointers to each fortune */
static int  fd = 0;		/* true if we have load the fortune info */
static int  nlines = 0;		/* # lines in fortune database */

char *fortune (file)
char *file;
{
    register char *p, *bptr;
    register int lines,tmp,i;
    struct stat stat;
    char *malloc ();

    if (fd == 0) {
	if ((fd = open (file, O_RDONLY)) < 0)/* open the file */
	    return (0);		/* can't find file */

    /* find out how big fortune file is and get memory for it */
	stat.st_size = 16384;
	if ((fstat (fd, &stat) < 0) || ((base = malloc (1 + stat.st_size)) == 0)) {
	    close (fd);
	    fd = -1;
	    free ((char *) base);
	    return (0);		/* can't stat file */
	}

    /* read in the entire fortune file */
	bptr = base;
	while ((i = read(fd,bptr,stat.st_size)) > 0)
	    bptr += i;
	if (bptr == base) {
	    close (fd);
	    fd = -1;
	    free ((char *) base);
	    return (0);		/* can't read file */
	}
	close (fd);
	base[stat.st_size] = 0;	/* final NULL termination */

    /* count up all the lines (and NULL terminate) to know memory needs */
	for (p = base, lines = 0; p < base + stat.st_size; p++)/* count lines */
	    if (*p == '\n')
		*p = 0, lines++;
	nlines = lines;

    /* get memory for array of pointers to each fortune */
	if ((flines = (char **) malloc (nlines * sizeof (char *))) == 0) {
	    free ((char *) base);
	    fd = -1;
	    return (0);		/* malloc() failure */
	}

    /* now assign each pointer to a line */
	for (p = base, tmp = 0; tmp < nlines; tmp++) {
	    flines[tmp] = p;
	    while (*p++);	/* advance to next line */
	}
    }

    if (fd > 2)			/* if we have a database to look at */
	return (flines[rund ((nlines <= 0) ? 1 : nlines)]);
    else
	return (0);
}
SHAR_EOF
if test 1991 -ne "`wc -c < 'fortune.c'`"
then
	echo shar: error transmitting "'fortune.c'" '(should have been 1991 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'global.c'" '(16893 characters)'
if test -f 'global.c'
then
	echo shar: will not over-write existing file "'global.c'"
else
cat << \SHAR_EOF > 'global.c'

/*	global.c 		Larn is copyrighted 1986 by Noah Morgan.
 *
 *	raiselevel()		subroutine to raise the player one level
 *	loselevel()		subroutine to lower the player by one level
 *	raiseexperience(x)	subroutine to increase experience points
 *	loseexperience(x)	subroutine to lose experience points
 *	losehp(x)		subroutine to remove hit points from the player
 *	losemhp(x)		subroutine to remove max # hit points from the player
 *	raisehp(x)		subroutine to gain hit points
 *	raisemhp(x)		subroutine to gain maximum hit points
 *	losespells(x)		subroutine to lose spells
 *	losemspells(x)		subroutine to lose maximum spells
 *	raisespells(x)		subroutine to gain spells
 *	raisemspells(x)		subroutine to gain maximum spells
 *	recalc()		function to recalculate the armor class of the player
 *	makemonst(lev)		function to return monster number for a randomly selected monster
 *	positionplayer()	function to be sure player is not in a wall
 *	quit()			subroutine to ask if the player really wants to quit
 */

#include "header.h"

extern int score[],dropflag;
extern int random;		/* the random number seed */
extern char *what[],*who[];
extern char winner[];
extern char sciv[SCORESIZE + 1][26][2];

/*
	***********
	RAISE LEVEL
	***********
	raiselevel()

	subroutine to raise the player one level
	uses the skill[] array to find level boundarys
	uses c[EXPERIENCE]  c[LEVEL]
 */
raiselevel()
{
    if (c[LEVEL] < MAXPLEVEL)
	raiseexperience((long)(skill[c[LEVEL]] - c[EXPERIENCE]));
}

/*
	***********
	LOOSE LEVEL
	***********
    loselevel()

	subroutine to lower the players character level by one
 */
loselevel()
{
    if (c[LEVEL] > 1)
	loseexperience((long)(c[EXPERIENCE] - skill[c[LEVEL] - 1] + 1));
}

/*
	****************
	RAISE EXPERIENCE
	****************
	raiseexperience(x)

	subroutine to increase experience points
 */
raiseexperience(x)
register long   x;
{
    register int i,tmp;

    i = c[LEVEL];
    c[EXPERIENCE] += x;
    while (c[EXPERIENCE] >= skill[c[LEVEL]] &&(c[LEVEL] < MAXPLEVEL)) {
	tmp =(c[CONSTITUTION] - c[HARDGAME]) >> 1;
	c[LEVEL]++;
	raisemhp((int)(rnd(3) + rnd((tmp > 0) ? tmp : 1)));
	raisemspells((int) rund(3));
	if (c[LEVEL] < 7 - c[HARDGAME])
	    raisemhp((int)(c[CONSTITUTION] >> 2));
    }
    if (c[LEVEL] != i) {
	cursors();
	beep();
	lprintf("\nWelcome to level %d",(long) c[LEVEL]);/* if we changed levels	 */
    }
    bottomline();
}

/*
	****************
	LOOSE EXPERIENCE
	****************
	loseexperience(x)

	subroutine to lose experience points
 */
loseexperience(x)
register long x;
{
    register int i,tmp;

    i = c[LEVEL];
    c[EXPERIENCE] -= x;
    if (c[EXPERIENCE] < 0)
	c[EXPERIENCE] = 0;
    while (c[EXPERIENCE] < skill[c[LEVEL] - 1]) {
	if (--c[LEVEL] <= 1)
	    c[LEVEL] = 1;	/* 	down one level		 */
	tmp =(c[CONSTITUTION] - c[HARDGAME]) >> 1;/* lose hpoints */
	losemhp((int) rnd((tmp > 0) ? tmp : 1));/* lose hpoints */
	if (c[LEVEL] < 7 - c[HARDGAME])
	    losemhp((int)(c[CONSTITUTION] >> 2));
	losemspells((int) rund(3));/* 	lose spells		 */
    }
    if (i != c[LEVEL]) {
	cursors();
	beep();
	lprintf("\nYou went down to level %d!",(long) c[LEVEL]);
    }
    bottomline();
}

/*
	********
	LOOSE HP
	********
	losehp(x)
	losemhp(x)

	subroutine to remove hit points from the player
	warning -- will kill player if hp goes to zero
 */
losehp(x)
register int x;
{
    if ((c[HP] -= x) <= 0) {
	beep();
	lprcat("\n");
	nap(3000);
	died(lastnum);
    }
}

losemhp(x)
register int    x;
{
    c[HP] -= x;
    if (c[HP] < 1)
	c[HP] = 1;
    c[HPMAX] -= x;
    if (c[HPMAX] < 1)
	c[HPMAX] = 1;
}

/*
	********
	RAISE HP
	********
	raisehp(x)
	raisemhp(x)

	subroutine to gain maximum hit points
 */
raisehp(x)
register int    x;
{
    if ((c[HP] += x) > c[HPMAX])
	c[HP] = c[HPMAX];
}

raisemhp(x)
register int    x;
{
    c[HPMAX] += x;
    c[HP] += x;
}

/*
	************
	RAISE SPELLS
	************
	raisespells(x)
	raisemspells(x)

	subroutine to gain maximum spells
 */
raisespells(x)
register int    x;
{
    if ((c[SPELLS] += x) > c[SPELLMAX])
	c[SPELLS] = c[SPELLMAX];
}

raisemspells(x)
register int    x;
{
    c[SPELLMAX] += x;
    c[SPELLS] += x;
}

/*
	************
	LOOSE SPELLS
	************
	losespells(x)
	losemspells(x)

	subroutine to lose maximum spells
 */
losespells(x)
register int    x;
{
    if ((c[SPELLS] -= x) < 0)
	c[SPELLS] = 0;
}

losemspells(x)
register int    x;
{
    if ((c[SPELLMAX] -= x) < 0)
	c[SPELLMAX] = 0;
    if ((c[SPELLS] -= x) < 0)
	c[SPELLS] = 0;
}

/*
	makemonst(lev)
		int lev;

	function to return monster number for a randomly selected monster
		for the given cave level	
 */
makemonst(lev)
register int lev;
{
    register int tmp,x;

    if (lev < 1)
	lev = 1;
    if (lev > 12)
	lev = 12;
    tmp = WATERLORD;
    if (lev < 5)
	while (tmp == WATERLORD)
	    tmp = rnd((x = monstlevel[lev - 1]) ? x : 1);
    else
	while (tmp == WATERLORD)
	    tmp = rnd((x = monstlevel[lev - 1] - monstlevel[lev - 4]) ? x : 1) + monstlevel[lev - 4];

    while (monster[tmp].genocided && tmp < MAXMONST)
	tmp++;			/* genocided? */
    return(tmp);
}

/*
	positionplayer()

	function to be sure player is not in a wall
 */
positionplayer()
{
    int try = 2;

    while ((item[playerx][playery] || mitem[playerx][playery]) &&(try))
	if (++playerx >= MAXX - 1) {
	    playerx = 1;
	    if (++playery >= MAXY - 1) {
		playery = 1;
		--try;
	    }
	}
    if (try == 0)
	lprcat("Failure in positionplayer\n");
}

/*
	recalc()	function to recalculate the armor class of the player
 */
recalc()
{
    register int i,j,k;

    c[AC] = c[MOREDEFENSES];
    if (c[WEAR] >= 0)
	switch(iven[c[WEAR]]) {
	    case OSHIELD: 
		c[AC] += 2 + ivenarg[c[WEAR]];
		break;
	    case OLEATHER: 
		c[AC] += 2 + ivenarg[c[WEAR]];
		break;
	    case OSTUDLEATHER: 
		c[AC] += 3 + ivenarg[c[WEAR]];
		break;
	    case ORING: 
		c[AC] += 5 + ivenarg[c[WEAR]];
		break;
	    case OCHAIN: 
		c[AC] += 6 + ivenarg[c[WEAR]];
		break;
	    case OSPLINT: 
		c[AC] += 7 + ivenarg[c[WEAR]];
		break;
	    case OPLATE: 
		c[AC] += 9 + ivenarg[c[WEAR]];
		break;
	    case OPLATEARMOR: 
		c[AC] += 10 + ivenarg[c[WEAR]];
		break;
	    case OSSPLATE: 
		c[AC] += 12 + ivenarg[c[WEAR]];
		break;
	}

    if (c[SHIELD] >= 0)
	if (iven[c[SHIELD]] == OSHIELD)
	    c[AC] += 2 + ivenarg[c[SHIELD]];
    if (c[WIELD] < 0)
	c[WCLASS] = 0;
    else {
	i = ivenarg[c[WIELD]];
	switch(iven[c[WIELD]]) {
	    case ODAGGER: 
		c[WCLASS] = 3 + i;
		break;
	    case OBELT: 
		c[WCLASS] = 7 + i;
		break;
	    case OSHIELD: 
		c[WCLASS] = 8 + i;
		break;
	    case OSPEAR: 
		c[WCLASS] = 10 + i;
		break;
	    case OFLAIL: 
		c[WCLASS] = 14 + i;
		break;
	    case OBATTLEAXE: 
		c[WCLASS] = 17 + i;
		break;
	    case OLANCE: 
		c[WCLASS] = 19 + i;
		break;
	    case OLONGSWORD: 
		c[WCLASS] = 22 + i;
		break;
	    case O2SWORD: 
		c[WCLASS] = 26 + i;
		break;
	    case OSWORD: 
		c[WCLASS] = 32 + i;
		break;
	    case OSWORDofSLASHING: 
		c[WCLASS] = 30 + i;
		break;
	    case OHAMMER: 
		c[WCLASS] = 35 + i;
		break;
	    default: 
		c[WCLASS] = 0;
	}
    }
    c[WCLASS] += c[MOREDAM];

 /* 	now for regeneration abilities based on rings	 */
    c[REGEN] = 1;
    c[ENERGY] = 0;
    j = 0;
    for (k = 25; k > 0; k--)
	if (iven[k]) {
	    j = k;
	    k = 0;
	}
    for (i = 0; i <= j; i++) {
	switch(iven[i]) {
	    case OPROTRING: 
		c[AC] += ivenarg[i] + 1;
		break;
	    case ODAMRING: 
		c[WCLASS] += ivenarg[i] + 1;
		break;
	    case OBELT: 
		c[WCLASS] +=((ivenarg[i] << 1)) + 2;
		break;

	    case OREGENRING: 
		c[REGEN] += ivenarg[i] + 1;
		break;
	    case ORINGOFEXTRA: 
		c[REGEN] += 5 *(ivenarg[i] + 1);
		break;
	    case OENERGYRING: 
		c[ENERGY] += ivenarg[i] + 1;
		break;
	}
    }
}


/*
	quit()

	subroutine to ask if the player really wants to quit
 */
quit()
{
    register int i, was_on = 1;

    cursors();
    if (!Check_KeySense()) {
	scbr();
	was_on = 0;
    }
    strcpy(lastmonst, "");
    lprcat("\n\nDo you really want to quit?");
    while (1) {
	i = readchar();
	if (i == 'y') {
	    died(300);
	    return;
	}
	if ((i == 'n') ||(i == '\33')) {
	    lprcat(" no");
	    lflush();
	    return;
	}
	lprcat("\n");
	setbold();
	lprcat("Yes");
	resetbold();
	lprcat(" or ");
	setbold();
	lprcat("No");
	resetbold();
	lprcat(" please?   Do you want to quit? ");
    }
    if (!was_on)
	sncbr();
}

/*
	function to ask --more-- then the user must enter a space
 */
more()
{
    lprcat("\n  --- press ");
    standout("space");
    lprcat(" to continue --- ");
    while (readchar() != ' ');
}

/*
	function to put something in the players inventory
	returns 0 if success, 1 if a failure
 */
take(itm, arg)
int itm,arg;
{
    register int i,limit;

    if ((limit = 15 +(c[LEVEL] >> 1)) > 26)
	limit = 26;
    for (i = 0; i < limit; i++)
	if (iven[i] == 0) {
	    iven[i] = itm;
	    ivenarg[i] = arg;
	    limit = 0;
	    switch(itm) {
		case OPROTRING: 
		case ODAMRING: 
		case OBELT: 
		    limit = 1;
		    break;
		case ODEXRING: 
		    c[DEXTERITY] += ivenarg[i] + 1;
		    limit = 1;
		    break;
		case OSTRRING: 
		    c[STREXTRA] += ivenarg[i] + 1;
		    limit = 1;
		    break;
		case OCLEVERRING: 
		    c[INTELLIGENCE] += ivenarg[i] + 1;
		    limit = 1;
		    break;
		case OHAMMER: 
		    c[DEXTERITY] += 10;
		    c[STREXTRA] += 10;
		    c[INTELLIGENCE] -= 10;
		    limit = 1;
		    break;

		case OORBOFDRAGON: 
		    c[SLAYING]++;
		    break;
		case OSPIRITSCARAB: 
		    c[NEGATESPIRIT]++;
		    break;
		case OCUBEofUNDEAD: 
		    c[CUBEofUNDEAD]++;
		    break;
		case ONOTHEFT: 
		    c[NOTHEFT]++;
		    break;
		case OSWORDofSLASHING: 
		    c[DEXTERITY] += 5;
		    limit = 1;
		    break;
	    };
	    lprcat("\nYou pick up:");
	    srcount = 0;
	    show3(i);
	    if (limit)
		bottomline();
	    return(0);
	}
    lprcat("\nYou can't carry anything else");
    return(1);
}

/*
	subroutine to drop an object  returns 1 if something there already else 0
 */
drop_object(k)
int k;
{
    int itm;

    if ((k < 0) ||(k > 25))
	return(0);
    itm = iven[k];
    cursors();
    if (itm == 0) {
	lprintf("\nYou don't have item %c! ", k + 'a');
	return(1);
    }
    if (item[playerx][playery]) {
	beep();
	lprcat("\nThere's something here already");
	return(1);
    }
    if (playery == MAXY - 1 && playerx == 33)
	return(1);		/* not in entrance */
    item[playerx][playery] = itm;
    iarg[playerx][playery] = ivenarg[k];
    srcount = 0;
    lprcat("\n  You drop:");
    show3(k);			/* show what item you dropped */
    know[playerx][playery] = 0;
    iven[k] = 0;
    if (c[WIELD] == k)
	c[WIELD] = -1;
    if (c[WEAR] == k)
	c[WEAR] = -1;
    if (c[SHIELD] == k)
	c[SHIELD] = -1;
    adjustcvalues(itm, ivenarg[k]);
    dropflag = 1;		/* say dropped an item so wont ask to pick it up right away */
    return(0);
}

/*
	function to enchant armor player is currently wearing
 */
enchantarmor()
{
    register int tmp;

    if (c[WEAR] < 0) {
	if (c[SHIELD] < 0) {
	    cursors();
	    beep();
	    lprcat("\nYou feel a sense of loss");
	    return;
	} else {
	    tmp = iven[c[SHIELD]];
	    if (tmp != OSCROLL)
		if (tmp != OPOTION) {
		    ivenarg[c[SHIELD]]++;
		    bottomline();
		}
	}
    }
    tmp = iven[c[WEAR]];
    if (tmp != OSCROLL)
	if (tmp != OPOTION) {
	    ivenarg[c[WEAR]]++;
	    bottomline();
	}
}

/*
	function to enchant a weapon presently being wielded
 */
enchweapon()
{
    register int tmp;

    if (c[WIELD] < 0) {
	cursors();
	beep();
	lprcat("\nYou feel a sense of loss");
	return;
    }
    tmp = iven[c[WIELD]];
    if (tmp != OSCROLL)
	if (tmp != OPOTION) {
	    ivenarg[c[WIELD]]++;
	    if (tmp == OCLEVERRING)
		c[INTELLIGENCE]++;
	    else if (tmp == OSTRRING)
		c[STREXTRA]++;
	    else if (tmp == ODEXRING)
		c[DEXTERITY]++;
	    bottomline();
	}
}

/*
	routine to tell if player can carry one more thing
	returns 1 if pockets are full, else 0
 */
pocketfull()
{
    register int i,limit;

    if ((limit = 15 +(c[LEVEL] >> 1)) > 26)
	limit = 26;
    for (i = 0; i < limit; i++)
	if (iven[i] == 0)
	    return(0);
    return(1);
}

/*
	function to return 1 if a monster is next to the player else returns 0
 */
nearbymonst()
{
    register int tmp,tmp2;

    for (tmp = playerx - 1; tmp < playerx + 2; tmp++)
	for (tmp2 = playery - 1; tmp2 < playery + 2; tmp2++)
	    if (mitem[tmp][tmp2])
		return(1);	/* if monster nearby */
    return(0);
}

/*
	function to steal an item from the players pockets
	returns 1 if steals something else returns 0
 */
stealsomething()
{
    register int i,j = 100;

    while (1) {
	i = rund(26);
	if (iven[i])
	    if (c[WEAR] != i)
		if (c[WIELD] != i)
		    if (c[SHIELD] != i) {
			srcount = 0;
			show3(i);
			adjustcvalues(iven[i], ivenarg[i]);
			iven[i] = 0;
			return(1);
		    }
	if (--j <= 0)
	    return(0);
    }
}

/*
	function to return 1 is player carrys nothing else return 0
 */
emptyhanded()
{
    register int i;

    for (i = 0; i < 26; i++)
	if (iven[i])
	    if (i != c[WIELD])
		if (i != c[WEAR])
		    if (i != c[SHIELD])
			return(0);
    return(1);
}

/*
	function to create a gem on a square near the player
 */
creategem()
{
    register int i,j;

    switch(rnd(4)) {
	case 1: 
	    i = ODIAMOND;
	    j = 50;
	    break;
	case 2: 
	    i = ORUBY;
	    j = 40;
	    break;
	case 3: 
	    i = OEMERALD;
	    j = 30;
	    break;
	default: 
	    i = OSAPPHIRE;
	    j = 20;
	    break;
    };
    createitem(i, rnd(j) + j / 10);
}

/*
	function to change character levels as needed when dropping an object
	that affects these characteristics
 */
adjustcvalues(itm, arg)
int itm,arg;
{
    register int flag = 0;

    switch(itm) {
	case ODEXRING: 
	    c[DEXTERITY] -= arg + 1;
	    flag = 1;
	    break;
	case OSTRRING: 
	    c[STREXTRA] -= arg + 1;
	    flag = 1;
	    break;
	case OCLEVERRING: 
	    c[INTELLIGENCE] -= arg + 1;
	    flag = 1;
	    break;
	case OHAMMER: 
	    c[DEXTERITY] -= 10;
	    c[STREXTRA] -= 10;
	    c[INTELLIGENCE] += 10;
	    flag = 1;
	    break;
	case OSWORDofSLASHING: 
	    c[DEXTERITY] -= 5;
	    flag = 1;
	    break;
	case OORBOFDRAGON: 
	    --c[SLAYING];
	    return;
	case OSPIRITSCARAB: 
	    --c[NEGATESPIRIT];
	    return;
	case OCUBEofUNDEAD: 
	    --c[CUBEofUNDEAD];
	    return;
	case ONOTHEFT: 
	    --c[NOTHEFT];
	    return;
	case OLANCE: 
	    c[LANCEDEATH] = 0;
	    return;
	case OPOTION: 
	case OSCROLL: 
	    return;

	default: 
	    flag = 1;
    };
    if (flag)
	bottomline();
}

/*
	function to read a string from token input "string"
	returns a pointer to the string
 */
gettokstr(str)
register char  *str;
{
    register int i = 50,j;

    while ((readchar() != '"') &&(--i > 0));
    i = 36;
    while (--i > 0) {
	if ((j = readchar()) != '"')
	    *str++ = j;
	else
	    i = 0;
    }
    *str = 0;
    i = 50;
    if (j != '"')
	while ((readchar() != '"') &&(--i > 0));/* if end due to too long, then find closing quote */
}

/*
	function to ask user for a password(no echo)
	returns 1 if entered correctly, 0 if not
 */
static char gpwbuf[33];
getpassword()
{
    register int i,j;
    register char *gpwp;
    globalref char *password;

    scbr();			/* system("stty -echo cbreak"); */
    gpwp = gpwbuf;
    lprcat("\nEnter Password: ");
    lflush();
    i = strlen(password);
    for (j = 0; j < i; j++)
	*(gpwp++) = readchar();
    gpwbuf[i] = 0;
    sncbr();			/* system("stty echo -cbreak"); */
    if (strcmp(gpwbuf, password) != 0) {
	lprcat("\nSorry\n");
	lflush();
	return(0);
    } else
	return(1);
}

/*
	subroutine to get a yes or no response from the user
	returns y or n
 */
getyn()
{
    register int i = 0;

    while (i != 'y' && i != 'n' && i != '\33')
	i = readchar();
    return(i);
}

/*
	function to calculate the pack weight of the player
	returns the number of pounds the player is carrying
 */
packweight()
{
    register int i,j,k;

    k = c[GOLD] / 1000;
    j = 25;
    while ((iven[j] == 0) &&(j > 0))
	--j;
    for (i = 0; i <= j; i++)
	switch(iven[i]) {
	    case 0: 
		break;
	    case OSSPLATE: 
	    case OPLATEARMOR: 
		k += 40;
		break;
	    case OPLATE: 
		k += 35;
		break;
	    case OHAMMER: 
		k += 30;
		break;
	    case OSPLINT: 
		k += 26;
		break;
	    case OSWORDofSLASHING: 
	    case OCHAIN: 
	    case OBATTLEAXE: 
	    case O2SWORD: 
		k += 23;
		break;
	    case OLONGSWORD: 
	    case OSWORD: 
	    case ORING: 
	    case OFLAIL: 
		k += 20;
		break;
	    case OLANCE: 
	    case OSTUDLEATHER: 
		k += 15;
		break;
	    case OLEATHER: 
	    case OSPEAR: 
		k += 8;
		break;
	    case OORBOFDRAGON: 
	    case OBELT: 
		k += 4;
		break;
	    case OSHIELD: 
		k += 7;
		break;
	    case OCHEST: 
		k += 30 + ivenarg[i];
		break;
	    default: 
		k++;
	};
    return(k);
}

#ifndef MACRORND
/* macros to generate random numbers   1<=rnd(N)<=N   0<=rund(N)<=N-1 */
rnd(x)
int x;
{
    return((((rand_x = rand_x * 1103515245 + 12345) >> 7) %(x)) + 1);
}

rund(x)
int x;
{
    return((((rand_x = rand_x * 1103515245 + 12345) >> 7) %(x)));
}
#endif MACRORND
SHAR_EOF
if test 16893 -ne "`wc -c < 'global.c'`"
then
	echo shar: error transmitting "'global.c'" '(should have been 16893 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'header.h'" '(12521 characters)'
if test -f 'header.h'
then
	echo shar: will not over-write existing file "'header.h'"
else
cat << \SHAR_EOF > 'header.h'

/*	header.h		Larn is copyrighted 1986 by Noah Morgan. */

#define SCORENAME	"LARN12.SCR"
#define LOGFNAME	"LARN12.LOG"
#define HELPNAME	"LARN12.HLP"
#define LEVELSNAME	"LARN12.MAZ"
#define FORTSNAME	"LARN12.FTN"
#define PLAYERIDS	"LARN12.IDS"
#define HOLIFILE	"LARN12.HDY"

#define MAXLEVEL 11
	/*	max # levels in the dungeon			*/
#define MAXVLEVEL 3
	/*	max # of levels in the temple of the luran	*/
#define MAXX 67
#define MAXY 17

#define SCORESIZE 10
	/*	this is the number of people on a scoreboard max */
#define MAXPLEVEL 100
	/*	maximum player level allowed		*/
#define MAXMONST 56
	/*	maximum # monsters in the dungeon	*/
#define SPNUM 38
	/*	maximum number of spells in existance	*/
#define MAXSCROLL 28
	/*	maximum number of scrolls that are possible	*/
#define MAXPOTION 35
	/*	maximum number of potions that are possible	*/
#define TIMELIMIT 30000
	/*	the maximum number of moves before the game is called */
#define TAXRATE 1/20
	/*	the tax rate for the LRS */
#define MAXOBJ 93
	/* the maximum number of objects   n < MAXOBJ */

/*	this is the structure definition of the monster data	*/
struct monst
{
    char *name;
    char level;
    short armorclass;
    char damage;
    char attack;
    char defense;
    char genocided;
    char intelligence; /* monsters intelligence -- used to choose movement */
    short gold;
    short hitpoints;
    unsigned long experience;
};

/*	this is the structure definition for the items in the dnd store */
struct _itm
{
    short price;
    char **mem;
    char obj;
    char arg;
    char qty;
};

/*	this is the structure that holds the entire dungeon specifications */
struct cel
{
    short hitp;	/* monster's hit points */
    char mitem;	/* the monster ID */
    char item;	/* the object's ID */
    short iarg;	/* the object's argument */
    char know;	/* have we been here before */
};

/* this is the structure for maintaining & moving the spheres of annihilation */
struct sphere {
    struct sphere *p;	/* pointer to next structure */
    char x,y,lev;	/* location of the sphere */
    char dir;		/* direction sphere is going in */
    char lifetime;	/* duration of the sphere */
};

/*	defines for the character attribute array	c[]	*/
#define STRENGTH 0	/* characters physical strength not due to objects */
#define INTELLIGENCE 1
#define WISDOM 2
#define CONSTITUTION 3
#define DEXTERITY 4
#define CHARISMA 5
#define HPMAX 6
#define HP 7
#define GOLD 8
#define EXPERIENCE 9
#define LEVEL 10
#define REGEN 11
#define WCLASS 12
#define AC 13
#define BANKACCOUNT 14
#define SPELLMAX 15
#define SPELLS 16
#define ENERGY 17
#define ECOUNTER 18
#define MOREDEFENSES 19
#define WEAR 20
#define PROTECTIONTIME 21
#define WIELD 22
#define AMULET 23
#define REGENCOUNTER 24
#define MOREDAM 25
#define DEXCOUNT 26
#define STRCOUNT 27
#define BLINDCOUNT 28
#define CAVELEVEL 29
#define CONFUSE 30
#define ALTPRO 31
#define HERO 32
#define CHARMCOUNT 33
#define INVISIBILITY 34
#define CANCELLATION 35
#define HASTESELF 36
#define EYEOFLARN 37
#define AGGRAVATE 38
#define GLOBE 39
#define TELEFLAG 40
#define SLAYING 41
#define NEGATESPIRIT 42
#define SCAREMONST 43
#define AWARENESS 44
#define HOLDMONST 45
#define TIMESTOP 46
#define HASTEMONST 47
#define CUBEofUNDEAD 48
#define GIANTSTR 49
#define FIRERESISTANCE 50
#define BESSMANN 51
#define NOTHEFT 52
#define HARDGAME 53
#define CPUTIME 54
#define BYTESIN 55
#define BYTESOUT 56
#define MOVESMADE 57
#define MONSTKILLED 58
#define SPELLSCAST 59
#define LANCEDEATH 60
#define SPIRITPRO 61
#define UNDEADPRO 62
#define SHIELD 63
#define STEALTH 64
#define ITCHING 65
#define LAUGHING 66
#define DRAINSTRENGTH 67
#define CLUMSINESS 68
#define INFEEBLEMENT 69
#define HALFDAM 70
#define SEEINVISIBLE 71
#define FILLROOM 72
#define RANDOMWALK 73
#define SPHCAST 74	/* nz if an active sphere of annihilation */
#define WTW 75		/* walk through walls */
#define STREXTRA 76	/* character strength due to objects or enchantments */
#define TMP 77	/* misc scratch space */
#define LIFEPROT 78 /* life protection counter */

/*	defines for the objects in the game		*/

#define OALTAR 1
#define OTHRONE 2
#define OORB 3
#define OPIT 4
#define OSTAIRSUP 5
#define OELEVATORUP 6
#define OFOUNTAIN 7
#define OSTATUE 8
#define OTELEPORTER 9
#define OSCHOOL 10
#define OMIRROR 11
#define ODNDSTORE 12
#define OSTAIRSDOWN 13
#define OELEVATORDOWN 14
#define OBANK2 15
#define OBANK 16
#define ODEADFOUNTAIN 17
#define OMAXGOLD 70
#define OGOLDPILE 18
#define OOPENDOOR 19
#define OCLOSEDDOOR 20
#define OWALL 21
#define OTRAPARROW 66
#define OTRAPARROWIV 67

#define OLARNEYE 22

#define OPLATE 23
#define OCHAIN 24
#define OLEATHER 25
#define ORING 60
#define OSTUDLEATHER 61
#define OSPLINT 62
#define OPLATEARMOR 63
#define OSSPLATE 64
#define OSHIELD 68
#define OELVENCHAIN 92

#define OSWORDofSLASHING 26
#define OHAMMER 27
#define OSWORD 28
#define O2SWORD 29
#define OSPEAR 30
#define ODAGGER 31
#define OBATTLEAXE 57
#define OLONGSWORD 58
#define OFLAIL 59
#define OLANCE 65
#define OVORPAL 90
#define OSLAYER 91

#define ORINGOFEXTRA 32
#define OREGENRING 33
#define OPROTRING 34
#define OENERGYRING 35
#define ODEXRING 36
#define OSTRRING 37
#define OCLEVERRING 38
#define ODAMRING 39

#define OBELT 40

#define OSCROLL 41
#define OPOTION 42
#define OBOOK 43
#define OCHEST 44             
#define OAMULET 45

#define OORBOFDRAGON 46
#define OSPIRITSCARAB 47
#define OCUBEofUNDEAD 48
#define ONOTHEFT 49

#define ODIAMOND 50
#define ORUBY 51
#define OEMERALD 52
#define OSAPPHIRE 53

#define OENTRANCE 54
#define OVOLDOWN 55
#define OVOLUP 56
#define OHOME 69

#define OKGOLD 71
#define ODGOLD 72
#define OIVDARTRAP 73
#define ODARTRAP 74
#define OTRAPDOOR 75
#define OIVTRAPDOOR 76
#define OTRADEPOST 77
#define OIVTELETRAP 78
#define ODEADTHRONE 79
#define OANNIHILATION 80		/* sphere of annihilation */
#define OTHRONE2 81
#define OLRS 82				/* Larn Revenue Service */
#define OCOOKIE 83
#define OURN 84
#define OBRASSLAMP 85
#define OHANDofFEAR 86		/* hand of fear */
#define OSPHTAILSMAN 87		/* tailsman of the sphere */
#define OWWAND 88			/* wand of wonder */
#define OPSTAFF 89			/* staff of power */
/* used up to 92 */

/*	defines for the monsters as objects		*/

#define BAT 1 
#define GNOME 2 
#define HOBGOBLIN 3 
#define JACKAL 4 
#define KOBOLD 5 
#define ORC 6 
#define SNAKE 7
#define CENTIPEDE 8
#define JACULI 9 
#define TROGLODYTE 10 
#define ANT 11 
#define EYE 12 
#define LEPRECHAUN 13
#define NYMPH 14 
#define QUASIT 15 
#define RUSTMONSTER 16 
#define ZOMBIE 17 
#define ASSASSINBUG 18 
#define BUGBEAR 19 
#define HELLHOUND 20 
#define ICELIZARD 21 
#define CENTAUR 22 
#define TROLL 23 
#define YETI 24 
#define WHITEDRAGON 25 
#define ELF 26 
#define CUBE 27 
#define METAMORPH 28 
#define VORTEX 29 
#define ZILLER 30 
#define VIOLETFUNGI 31 
#define WRAITH 32 
#define FORVALAKA 33 
#define LAMANOBE 34 
#define OSEQUIP 35 
#define ROTHE 36 
#define XORN 37 
#define VAMPIRE 38 
#define INVISIBLESTALKER 39 
#define POLTERGEIST 40 
#define DISENCHANTRESS 41 
#define SHAMBLINGMOUND 42 
#define YELLOWMOLD 43
#define UMBERHULK 44
#define GNOMEKING 45
#define MIMIC 46
#define WATERLORD 47
#define BRONZEDRAGON 48
#define GREENDRAGON 49
#define PURPLEWORM 50
#define XVART 51
#define SPIRITNAGA 52
#define SILVERDRAGON 53
#define PLATINUMDRAGON 54
#define GREENURCHIN 55
#define REDDRAGON 56
#define DEMONLORD 57
#define DEMONPRINCE 64

#define NULL 0
#define BUFBIG	4096			/* size of the output buffer */
#define MAXIBUF	4096			/* size of the input buffer */
#define LOGNAMESIZE 40			/* max size of the players name */
#define SAVEFILENAMESIZE 128		/* max size of the savefile path */

#ifndef NODEFS
globalref char VERSION,SUBVERSION;
globalref char *aborted,beenhere[MAXLEVEL+MAXVLEVEL],boldon,cheat,ckpfile[];
globalref char ckpflag;
globalref char *class[],course[],diagfile[],fortfile[],helpfile[],holifile[];
globalref char *inbuffer,is_alpha[],is_digit[];
globalref char item[MAXX][MAXY],iven[],know[MAXX][MAXY],larnlevels[],lastmonst[];
globalref char level,*levelname[],logfile[],loginname[],logname[],*lpbuf,*lpend;
globalref char *lpnt,moved[MAXX][MAXY],mitem[MAXX][MAXY],monstlevel[];
globalref char monstnamelist[],nch[],ndgg[],nlpts[],nomove,nosignal,nowelcome;
globalref char nplt[],nsw[],*objectname[];
globalref char objnamelist[],optsfile[],*potionname[],playerids[],potprob[];
globalref char predostuff,restorflag,savefilename[],scorefile[],scprob[];
globalref char screen[MAXX][MAXY],*scrollname[],sex,*spelcode[];
globalref char *speldescript[],spelknow[],*spelname[],*spelmes[];
globalref char spelweird[MAXMONST+8][SPNUM];
globalref char splev[],stealth[MAXX][MAXY],to_lower[],to_upper[],wizard;
globalref short diroffx[],diroffy[],hitflag,hit2flag,hit3flag,hitp[MAXX][MAXY];
globalref short iarg[MAXX][MAXY],ivenarg[26],lasthx,lasthy,lastnum;
globalref short lastpx,lastpy,nobeep,oldx,oldy,playerx,playery;
globalref int dayplay,enable_scroll,srcount,yrepcount,userid,wisid,lfd,fd;
globalref long initialtime,outstanding_taxes,skill[],gtime,c[100],cbak[100];
globalref long start_cpu;
globalref unsigned long rand_x;
globalref struct cel cell[(MAXLEVEL+MAXVLEVEL) * MAXX * MAXY];
globalref struct monst monster[];
globalref struct sphere *spheres;
globalref struct _itm itm[90];

extern char *fortune(),*malloc(),*getenv(),*getlogin(),*lgetw(),*lgetl(),*ctime();
#ifndef VT100
extern char *tmcapcnv(),*tgetstr(),*tgoto();
#endif VT100
extern long paytaxes(),lgetc(),lrint(),time();
extern unsigned long readnum();

	/* macro to create scroll #'s with probability of occurrence */
#define newscroll() (scprob[rund(81)])
	/* macro to return a potion # created with probability of occurrence */
#define newpotion() (potprob[rund(41)])
	/* macro to return the + points on created leather armor */
#define newleather() (nlpts[rund(c[HARDGAME]?13:15)])
	/* macro to return the + points on chain armor */
#define newchain() (nch[rund(10)])
	/* macro to return + points on plate armor */
#define newplate() (nplt[rund(c[HARDGAME]?4:12)])
	/* macro to return + points on new daggers */
#define newdagger() (ndgg[rund(13)])
	/* macro to return + points on new swords */
#define newsword() (nsw[rund(c[HARDGAME]?6:13)])
	/* macro to destroy object at present location */
#define forget() (item[playerx][playery]=know[playerx][playery]=0)
	/* macro to wipe out a monster at a location */
#define disappear(x,y) (mitem[x][y]=know[x][y]=0)

#ifdef VT100
	/* macro to turn on bold display for the terminal */
#define setbold() (lprcat(boldon?"\33[1m":"\33[7m"))
	/* macro to turn off bold display for the terminal */
#define resetbold() (lprcat("\33[m"))
	/* macro to setup the scrolling region for the terminal */
#define setscroll() (lprcat("\33[20;24r"))
	/* macro to clear the scrolling region for the terminal */
#define resetscroll() (lprcat("\33[;24r"))
	/* macro to clear the screen and home the cursor */
#define clear() (lprcat("\33[2J\33[f"), cbak[SPELLS]= -50)
#define cltoeoln() lprcat("\33[K")
#else VT100
	/* defines below are for use in the termcap mode only */
#define ST_START 1
#define ST_END   2
#define BOLD     3
#define END_BOLD 4
#define CLEAR    5
#define CL_LINE  6
#define CL_DOWN 14
#define CURSOR  15
	/* macro to turn on bold display for the terminal */
#define setbold() (*lpnt++ = ST_START)
	/* macro to turn off bold display for the terminal */
#define resetbold() (*lpnt++ = ST_END)
	/* macro to setup the scrolling region for the terminal */
#define setscroll() enable_scroll=1
	/* macro to clear the scrolling region for the terminal */
#define resetscroll() enable_scroll=0
	/* macro to clear the screen and home the cursor */
#define clear() (*lpnt++ =CLEAR, cbak[SPELLS]= -50)
	/* macro to clear to end of line */
#define cltoeoln() (*lpnt++ = CL_LINE)
#endif VT100

	/* macro to output one byte to the output buffer */
#define lprc(ch) ((lpnt>=lpend)?(*lpnt++ =(ch), lflush()):(*lpnt++ =(ch)))

	/* macro to seed the random number generator */
#define srand(x) (rand_x=x)
#ifdef MACRORND
	/* macros to generate random numbers   1<=rnd(N)<=N   0<=rund(N)<=N-1 */
#define rnd(x)  ((((rand_x=rand_x*1103515245+12345)>>7)%(x))+1)
#define rund(x) ((((rand_x=rand_x*1103515245+12345)>>7)%(x))  )
#endif MACRORND
	/* macros for miscellaneous data conversion */
#define min(x,y) (((x)>(y))?(y):(x))
#define max(x,y) (((x)>(y))?(x):(y))
#define isalpha(x) (is_alpha[x])
#define isdigit(x) (is_digit[x])
#define tolower(x) (to_lower[x])
#define toupper(x) (to_upper[x])
#define lcc(x) (to_lower[x])
#define ucc(x) (to_upper[x])
#endif NODEFS

SHAR_EOF
if test 12521 -ne "`wc -c < 'header.h'`"
then
	echo shar: error transmitting "'header.h'" '(should have been 12521 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'help.c'" '(2367 characters)'
if test -f 'help.c'
then
	echo shar: will not over-write existing file "'help.c'"
else
cat << \SHAR_EOF > 'help.c'

/*	help.c		Larn is copyrighted 1986 by Noah Morgan. */

#include "header.h"

/*
 *	help function to display the help info	
 *
 *	format of the .larn.help file
 *
 *	1st character of file:	# of pages of help available(ascii digit)
 *	page(23 lines) for the introductory message(not counted in above)
 *	pages of help text(23 lines per page)
 */

help()
{
    register int    i,j;
#ifndef VT100
    char    tmbuf[128];  /* intermediate translation buffer when not a VT100 */
#endif VT100

    if ((j = openhelp()) < 0)
	return;		 /* open the help file and get # pages */
    for (i = 0; i < 23; i++)
	lgetl();	 /* skip over intro message */
    for (; j > 0; j--) {
	clear();
	for (i = 0; i < 23; i++)
#ifdef VT100
	    lprcat(lgetl());	/* print out each line that we read in */
#else VT100
	{
	    tmcapcnv(tmbuf, lgetl());
	    lprcat(tmbuf);
	}			/* intercept \33's */
#endif VT100
	if (j > 1) {
	    lprcat("    ---- Press ");
	    standout("return");
	    lprcat(" to exit, ");
	    standout("space");
	    lprcat(" for more help ---- ");
	    i = 0;
	    while ((i != ' ') &&(i != '\n') &&(i != '\33'))
		i = readchar();
	    if ((i == '\n') ||(i == '\33')) {
		lrclose();
		setscroll();
		drawscreen();
		return;
	    }
	}
    }
    lrclose();
    retcont();
    drawscreen();
}

/*
 *  function to display the welcome message and background
 */
welcome()
{
    register int i;
#ifndef VT100
    char    tmbuf[128];  /* intermediate translation buffer when not a VT100 */
#endif VT100

    if (openhelp() < 0)
	return;		 /* open the help file */
    clear();
    for (i = 0; i < 23; i++)
#ifdef VT100
	lprcat(lgetl());	/* print out each line that we read in */
#else VT100
    {
	tmcapcnv(tmbuf, lgetl());
	lprcat(tmbuf);
    }				/* intercept \33's */
#endif VT100
    lrclose();
    retcont();			/* press return to continue */
}


/*
 *	function to say press return to continue and reset scroll when done
 */
retcont()
{
    cursor(1, 24);
    lprcat("Press ");
    standout("return");
    lprcat(" to continue: ");
    while (readchar() != '\n');
    setscroll();
}

/*
 *	routine to open the help file and return the first character - '0'
 */
openhelp()
{
    if (lopen(helpfile) < 0) {
	lprintf("Can't open help file \"%s\" ", helpfile);
	lflush();
	sleep(4);
	drawscreen();
	setscroll();
	return(-1);
    }
    resetscroll();
    return(lgetc() - '0');
}
SHAR_EOF
if test 2367 -ne "`wc -c < 'help.c'`"
then
	echo shar: error transmitting "'help.c'" '(should have been 2367 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)

Hello all!  This is a port of Larn v12.0 to VAX/VMS.  Now everyone can save
his/her daughter!!  Just unpack using /bin/sh and read readme.txt.

                                                - Mark Nagel

P.S.  Thanks to Lord Kahless for letting me post this!



-------------------------------cut here-------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	io.c
#	keysense.c
#	larn.c
#	larn12.ftn
#	larn12.hdy
# This archive created: Sat Aug 30 14:47:38 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'io.c'" '(22021 characters)'
if test -f 'io.c'
then
	echo shar: will not over-write existing file "'io.c'"
else
cat << \SHAR_EOF > 'io.c'

/* io.c			 Larn is copyrighted 1986 by Noah Morgan.
 *
 *	Below are the functions in this file:
 *
 *	setupvt100() 	Subroutine to set up terminal in correct mode for game
 *	clearvt100()  	Subroutine to clean up terminal when the game is over
 *	readchar() 	Routine to read in one character from the terminal
 *	scbr()		Function to set cbreak -echo for the terminal
 *	sncbr()		Function to set -cbreak echo for the terminal
 *	newgame() 	Subroutine to save the initial time and seed rnd()
 *
 *	FILE OUTPUT ROUTINES
 *
 *	lprintf(format,args . . .)	printf to the output buffer
 *	lprint(integer)			send binary integer to output buffer
 *	lwrite(buf,len)			write a buffer to the output buffer
 *	lprcat(str)			sent string to output buffer
 *
 *	FILE OUTPUT MACROS(in header.h)
 *
 *	lprc(character)			put the character into the output buffer
 *
 *	FILE INPUT ROUTINES
 *
 *	long lgetc()			read one character from input buffer
 *	long lrint()			read one integer from input buffer
 *	lrfill(address,number)		put input bytes into a buffer
 *	char *lgetw()			get a whitespace ended word from input
 *	char *lgetl()			get a \n or EOF ended line from input
 *
 *	FILE OPEN / CLOSE ROUTINES
 *
 *	lcreat(filename)		create a new file for write
 *	lopen(filename)			open a file for read
 *	lappend(filename)		open for append to an existing file
 *	lrclose()			close the input file
 *	lwclose()			close output file
 *	lflush()			flush the output buffer
 *
 *	Other Routines
 *
 *	cursor(x,y)		position cursor at [x,y]
 *	cursors()		position cursor at [1,24](saves memory)
 *	cl_line(x,y)        	Clear line at [1,y] and leave cursor at [x,y]
 *	cl_up(x,y)    		Clear screen from [x,1] to current line.
 *	cl_dn(x,y)		Clear screen from [1,y] to end of display. 
 *	standout(str)		Print the string in standout mode.
 *	set_score_output() 	Called when output should be literally printed.
 ** writechar(ch)			Print one character in decoded output buffer.
 ** flush_buf()			Flush buffer with decoded output.
 ** init_term()			Terminal initialization -- setup termcap info
 *	char *tmcapcnv(sd,ss)	Routine to convert VT100 \33's to termcap format
 *	beep()		Routine to emit a beep if enabled(see no-beep in .larnopts)
 *
 * Note: ** entries are available only in termcap mode.
 */

#include "header.h"

#include <stdio.h>
#include <file.h>
#include <varargs.h>

#define LINBUFSIZE 128		/* size of the lgetw() and lgetl() buffer */

globaldef int	lfd,		/* output file numbers */
		fd;		/* input file numbers */

static int ipoint = MAXIBUF, iepoint = MAXIBUF;  /* input buffering pointers */
static char lgetwbuf[LINBUFSIZE];	/* get line(word) buffer */

/*
 * setupvt100() 	Subroutine to set up terminal in correct mode for game
 *
 * Attributes off, clear screen, set scrolling region, set tty mode 
 */
setupvt100()
{
    clear();
    setscroll();
    scbr();			/* system("stty cbreak -echo"); */
}

/*
 * clearvt100() 	Subroutine to clean up terminal when the game is over
 *
 * Attributes off, clear screen, unset scrolling region, restore tty mode 
 */
clearvt100()
{
    resetscroll();
    clear();
    sncbr();			/* system("stty -cbreak echo"); */
}

/*
 * readchar()		Routine to read in one character from the terminal
 */
readchar()
{
#ifdef EXTRA
    c[BYTESIN]++;
#endif
    lflush();			/* be sure output buffer is flushed */
    if (Check_KeySense())
	return(KeySense(1));	/* get byte from terminal */
    else
	return(getchar());
}

/*
 *	scbr()		Function to set cbreak -echo for the terminal
 *
 *	like: system("SET TERM/NOECHO/PASTHRU")
 */
scbr()
{
    KeySense_On();
}

/*
 *	sncbr()		Function to set -cbreak echo for the terminal
 *
 *	like: system("SET TERM/ECHO/NOPASTHRU")
 */
sncbr()
{
    KeySense_Off();
}

/*
 *	newgame()	Subroutine to save the initial time and seed rnd()
 */
newgame()
{
    register long  *p, *pe;

    for(p = c, pe = c + 100; p < pe; *p++ = 0);
    time(&initialtime);
    srand(initialtime);
    lcreat((char *) 0);	/* open buffering for output to terminal */
}


/*
 *	lprintf(format,args . . .)	printf to the output buffer
 *	char *format;
 *	{args . . .}
 *
 *	Enter with the format string in "format", as per printf() usage
 *    and any needed arguments following it
 *	Note: lprintf() only supports %s, %c and %d, with width modifier and
 *    left or right justification.
 *	No correct checking for output buffer overflow is done, but flushes 
 *    are done beforehand if needed.
 *    Returns nothing of value.
 */
lprintf(va_alist)
va_dcl
{
    va_list ap;			/* pointer for variable argument list */
    register char *fmt;
    register char *outb,*tmpb;
    register long wide,left,cont,n;		/* data for lprintf */
    char db[12];		/* %d buffer in lprintf	 */

    va_start(ap);		/* initialize the var args pointer */
    fmt = va_arg(ap, char *);	/* pointer to format string */
    if (lpnt >= lpend)
	lflush();
    outb = lpnt;
    for(;;) {
	while(*fmt != '%')
	    if (*fmt)
		*outb++ = *fmt++;
	    else {
		lpnt = outb;
		return;
	    }
	wide = 0;
	left = 1;
	cont = 1;
	while(cont)
	    switch(*(++fmt)) {
		case 'd': 
		    n = va_arg(ap, long);
		    if (n < 0) {
			n = -n;
			*outb++ = '-';
			if (wide)
			    --wide;
		    }
		    tmpb = db + 11;
		    *tmpb =(char)(n % 10 + '0');
		    while(n > 9)
			*(--tmpb) =(char)((n /= 10) % 10 + '0');
		    if (wide == 0)
			while(tmpb < db + 12)
			    *outb++ = *tmpb++;
		    else {
			wide -= db - tmpb + 12;
			if (left)
			    while(wide-- > 0)
				*outb++ = ' ';
			while(tmpb < db + 12)
			    *outb++ = *tmpb++;
			if (left == 0)
			    while(wide-- > 0)
				*outb++ = ' ';
		    }
		    cont = 0;
		    break;

		case 's': 
		    tmpb = va_arg(ap, char *);
		    if (wide == 0) {
			while(*outb++ = *tmpb++);
			--outb;
		    } else {
			n = wide - strlen(tmpb);
			if (left)
			    while(n-- > 0)
				*outb++ = ' ';
			while(*outb++ = *tmpb++);
			--outb;
			if (left == 0)
			    while(n-- > 0)
				*outb++ = ' ';
		    }
		    cont = 0;
		    break;

		case 'c': 
		    *outb++ = va_arg(ap, int);
		    cont = 0;
		    break;

		case '0': 
		case '1': 
		case '2': 
		case '3': 
		case '4': 
		case '5': 
		case '6': 
		case '7': 
		case '8': 
		case '9': 
		    wide = 10 * wide + *fmt - '0';
		    break;

		case '-': 
		    left = 0;
		    break;

		default: 
		    *outb++ = *fmt;
		    cont = 0;
		    break;
	    };
	fmt++;
    }
    va_end(ap);
}


/*
 *	lprint(long-integer)	send binary integer to output buffer
 *	long integer;
 *
 *	+---------+---------+---------+---------+
 *	|   high  |	    |	      |	  low	|
 *	|  order  |	    |	      |  order	|
 *	|   byte  |	    |	      |	  byte	|
 *	+---------+---------+---------+---------+
 *	31  ---  24 23 --- 16 15 ---  8 7  ---   0
 *
 *	The save order is low order first, to high order(4 bytes total)
 *    and is written to be system independent.
 *	No checking for output buffer overflow is done, but flushes if needed!
 *	Returns nothing of value.
 */
lprint(x)
register long   x;
{
    if (lpnt >= lpend)
	lflush();
    *lpnt++ = 255 & x;
    *lpnt++ = 255 &(x >> 8);
    *lpnt++ = 255 &(x >> 16);
    *lpnt++ = 255 &(x >> 24);
}

/*
 *	lwrite(buf,len)		write a buffer to the output buffer
 *	char *buf;
 *	int len;
 *	
 *	Enter with the address and number of bytes to write out
 *	Returns nothing of value
 */
lwrite(buf, len)
register char  *buf;
int len;
{
    register char *str;
    register int num2;

    if (len > 399) {		/* don't copy data if can just write it */
#ifdef EXTRA
	c[BYTESOUT] += len;
#endif

#ifndef VT100
	for(str = buf; len > 0; --len)
	    lprc(*str++);
#else VT100
	lflush();
	write(lfd, buf, len);
#endif VT100
    }
    else
	while(len) {
	    if (lpnt >= lpend)
		lflush();	/* if buffer is full flush it */
	    num2 = lpbuf + BUFBIG - lpnt;  /* # bytes left in output buffer */
	    if (num2 > len)
		num2 = len;
	    str = lpnt;
	    len -= num2;
	    while(num2--)
		*str++ = *buf++;  /* copy in the bytes */
	    lpnt = str;
	}
}


/*
 *  long lgetc()	Read one character from input buffer
 *
 *  Returns 0 if EOF, otherwise the character
 */
long lgetc()
{
    register int i;

    if (ipoint != iepoint)
	return(inbuffer[ipoint++]);
    /* NOTE: VAX/VMS reads only one line */
    if ((i = read(fd, inbuffer, MAXIBUF)) <= 0) {
	if (i != 0)
	    write(1, "error reading from input file\n", 30);
	iepoint = ipoint = 0;
	return(0);
    }
    ipoint = 1;
    iepoint = i;
    return(*inbuffer);
}


/*
 *	long lrint()	Read one integer from input buffer
 *
 *	+---------+---------+---------+---------+
 *	|   high  |	    |	      |	  low	|
 *	|  order  |	    |	      |  order	|
 *	|   byte  |	    |	      |	  byte	|
 *	+---------+---------+---------+---------+
 *	31  ---  24 23 --- 16 15 ---  8 7  ---   0
 *
 *	The save order is low order first, to high order(4 bytes total)
 *	Returns the int read
 */
long lrint()
{
    register unsigned long  i;

    i = 255 & lgetc();
    i |=(255 & lgetc()) << 8;
    i |=(255 & lgetc()) << 16;
    i |=(255 & lgetc()) << 24;
    return(i);
}


/*
 *  lrfill(address,number)		put input bytes into a buffer
 *  char *address;
 *  int number;
 *
 *  Reads "number" bytes into the buffer pointed to by "address".
 *  Returns nothing of value
 */
lrfill(adr, num)
register char *adr;
int num;
{
    register char  *pnt;
    register int    num2;

    while(num) {
	if (iepoint == ipoint) {
	    if (num > 5) {	/* fast way */
		if (read(fd, adr, num) != num)
		    write(2, "error reading from input file\n", 30);
		num = 0;
	    } else {
		*adr++ = lgetc();
		--num;
	    }
	} else {
	    num2 = iepoint - ipoint;/* 	# of bytes left in the buffer	 */
	    if (num2 > num)
		num2 = num;
	    pnt = inbuffer + ipoint;
	    num -= num2;
	    ipoint += num2;
	    while(num2--)
		*adr++ = *pnt++;
	}
    }
}


/*
 *  char *lgetw()		Get a whitespace ended word from input
 *
 *  Returns pointer to a buffer that contains word.  If EOF, returns a NULL
 */
char *lgetw()
{
    register char *lgp,cc;
    register int n = LINBUFSIZE, quote = 0;

    lgp = lgetwbuf;
    do
	cc = lgetc();
    while((cc <= 32) &&(cc > NULL));	/* eat whitespace */
    for(;; --n, cc = lgetc()) {
	if ((cc == NULL) &&(lgp == lgetwbuf))
	    return(NULL);	/* EOF */
	if ((n <= 1) ||((cc <= 32) &&(quote == 0))) {
	    *lgp = NULL;
	    return(lgetwbuf);
	}
	if (cc != '"')
	    *lgp++ = cc;
	else
	    quote ^= 1;
    }
}


/*
 *  char *lgetl()	Function to read in a line ended by newline or EOF
 *
 *  Returns pointer to a buffer that contains the line.  If EOF,
 *  Returns NULL
 */
char *lgetl()
{
    register int i = LINBUFSIZE,ch;
    register char *str = lgetwbuf;

    for(;; --i) {
	if ((*str++ = ch = lgetc()) == NULL) {
	    if (str == lgetwbuf + 1)
		return(NULL);	/* EOF */
    ot: 
	    *str = NULL;
	    return(lgetwbuf);	/* line ended by EOF */
	}
	if ((ch == '\n') ||(i <= 1))
	    goto ot;		/* line ended by \n */
    }
}


/*
 *  lcreat(filename)	Create a new file for write
 *  char *filename;
 *
 *  lcreat((char*)0); means to the terminal
 *  Returns -1 if error, otherwise the file descriptor opened.
 */
lcreat(str)
char   *str;
{
    lpnt = lpbuf;
    lpend = lpbuf + BUFBIG;
    if (str == NULL)
	return(lfd = 1);
    if ((lfd = creat(str, 0644)) < 0) {
	lfd = 1;
	lprintf("error creating file <%s>\n", str);
	lflush();
	return(-1);
    }
    return(lfd);
}


/*
 *  lopen(filename)		Open a file for read
 *  char *filename;
 *
 *  lopen(0) means from the terminal
 *  Returns -1 if error, otherwise the file descriptor opened.
 */
lopen(str)
char   *str;
{
    ipoint = iepoint = MAXIBUF;
    if (str == NULL)
	return(fd = 0);
    if ((fd = open(str, 0)) < 0) {
	lwclose();
	lfd = 1;
	lpnt = lpbuf;
	return(-1);
    }
    return(fd);
}


/*
 *	lappend(filename)	Open for append to an existing file
 *	char *filename;
 *
 *	lappend(0) means to the terminal
 *	Returns -1 if error, otherwise the file descriptor opened.
 */
lappend(str)
char   *str;
{
    lpnt = lpbuf;
    lpend = lpbuf + BUFBIG;
    if (str == NULL)
	return(lfd = 1);
    if ((lfd = open(str, O_RDWR|O_APPEND)) < 0) {
	lfd = 1;
	return(-1);
    }
    lseek(lfd,0,2);		/* go to the end-of-file */
    return(lfd);
}


/*
 *	lrclose()		close the input file
 *
 *	Returns nothing of value.
 */
lrclose()
{
    if (fd > 0)
	close(fd);
}


/*
 *	lwclose()		close output file flushing if needed
 *
 *	Returns nothing of value.
 */
lwclose()
{
    lflush();
    if (lfd > 2)
	close(lfd);
}


/*
 *	lprcat(string)		append a string to the output buffer
 *				avoids calls to lprintf(time consuming)
 */
lprcat(str)
register char  *str;
{
    register char  *str2;

    if (lpnt >= lpend)
	lflush();
    str2 = lpnt;
    while(*str2++ = *str++);
    lpnt = str2 - 1;
}

#ifdef VT100
/*
 *	cursor(x,y) 		Subroutine to set the cursor position
 *
 *	x and y are the cursor coordinates, and lpbuff is the output buffer where
 *	escape sequence will be placed. 
 */
static char *y_num[] = {
    "\33[", "\33[", "\33[2", "\33[3", "\33[4", "\33[5", "\33[6",
    "\33[7", "\33[8", "\33[9", "\33[10", "\33[11", "\33[12", "\33[13", "\33[14",
    "\33[15", "\33[16", "\33[17", "\33[18", "\33[19", "\33[20", "\33[21", "\33[22",
    "\33[23", "\33[24"
};

static char *x_num[] = {
    "H", "H", ";2H", ";3H", ";4H", ";5H", ";6H", ";7H", ";8H", ";9H",
    ";10H", ";11H", ";12H", ";13H", ";14H", ";15H", ";16H", ";17H", ";18H", ";19H",
    ";20H", ";21H", ";22H", ";23H", ";24H", ";25H", ";26H", ";27H", ";28H", ";29H",
    ";30H", ";31H", ";32H", ";33H", ";34H", ";35H", ";36H", ";37H", ";38H", ";39H",
    ";40H", ";41H", ";42H", ";43H", ";44H", ";45H", ";46H", ";47H", ";48H", ";49H",
    ";50H", ";51H", ";52H", ";53H", ";54H", ";55H", ";56H", ";57H", ";58H", ";59H",
    ";60H", ";61H", ";62H", ";63H", ";64H", ";65H", ";66H", ";67H", ";68H", ";69H",
    ";70H", ";71H", ";72H", ";73H", ";74H", ";75H", ";76H", ";77H", ";78H", ";79H",
    ";80H"
};


cursor(x, y)
int x,y;
{
    register char  *p;

    if (lpnt >= lpend)
	lflush();

    p = y_num[y];		/* get the string to print */
    while(*p)
	*lpnt++ = *p++;		/* print the string */

    p = x_num[x];		/* get the string to print */
    while(*p)
	*lpnt++ = *p++;		/* print the string */
}
#else VT100
/*
 * cursor(x,y)	  Put cursor at specified coordinates starting at [1,1](termcap)
 */
cursor(x, y)
int x,y;
{
    if (lpnt >= lpend)
	lflush();

    *lpnt++ = CURSOR;
    *lpnt++ = x;
    *lpnt++ = y;
}
#endif VT100


/*
 *	Routine to position cursor at beginning of 24th line
 */
cursors() {
    cursor(1, 24);
}

#ifndef VT100
/*
 * Warning: ringing the bell is control code 7. Don't use in defines.
 * Don't change the order of these defines.
 * Also used in helpfiles. Codes used in helpfiles should be \E[1 to \E[7 with
 * obvious meanings.
 */

static char cap[256];
char   *CM,
       *CE,
       *CD,
       *CL,
       *SO,
       *SE,
       *AL,
       *DL;			/* Termcap capabilities */
static char *outbuf = 0;	/* translated output buffer */

int writechar();

/*
 * init_term()		Terminal initialization -- setup termcap info
 */
init_term()
{
    char    termbuf[1024];
    char   *capptr = cap + 10;
    char   *term;

    switch(tgetent(termbuf, term = getenv("TERM"))) {
	case -1: 
	    write(2, "Cannot open termcap file.\n", 26);
	    exit();
	case 0: 
	    write(2, "Cannot find entry of ", 21);
	    write(2, term, strlen(term));
	    write(2, " in termcap\n", 12);
	    exit();
    };

    CM = tgetstr("cm", &capptr);/* Cursor motion */
    CE = tgetstr("ce", &capptr);/* Clear to eoln */
    CL = tgetstr("cl", &capptr);/* Clear screen */

 /* OPTIONAL */
    AL = tgetstr("al", &capptr);/* Insert line */
    DL = tgetstr("dl", &capptr);/* Delete line */
    SO = tgetstr("so", &capptr);/* Begin standout mode */
    SE = tgetstr("se", &capptr);/* End standout mode */
    CD = tgetstr("cd", &capptr);/* Clear to end of display */

    if (!CM) {			/* can't find cursor motion entry */
	write(2, "Sorry, for a ", 13);
	write(2, term, strlen(term));
	write(2, ", I can't find the cursor motion entry in termcap\n", 50);
	exit();
    }
    if (!CE) {			/* can't find clear to end of line entry */
	write(2, "Sorry, for a ", 13);
	write(2, term, strlen(term));
	write(2, ", I can't find the clear to end of line entry in termcap\n", 57);
	exit();
    }
    if (!CL) {			/* can't find clear entire screen entry */
	write(2, "Sorry, for a ", 13);
	write(2, term, strlen(term));
	write(2, ", I can't find the clear entire screen entry in termcap\n", 56);
	exit();
    }
    /* get memory for decoded output buffer */
    if ((outbuf = malloc(BUFBIG + 16)) == 0) {
	write(2, "Error malloc'ing memory for decoded output buffer\n", 50);
	died(-285);		/* malloc() failure */
    }
}
#endif VT100

/*
 * cl_line(x,y)  Clear the whole line indicated by 'y' and leave cursor at [x,y]
 */
cl_line(x, y)
int x,y;
{
#ifdef VT100
    cursor(x, y);
    lprcat("\33[2K");
#else VT100
    cursor(1, y);
    *lpnt++ = CL_LINE;
    cursor(x, y);
#endif VT100
}


/*
 * cl_up(x,y) Clear screen from [x,1] to current position. Leave cursor at [x,y]
 */
cl_up(x, y)
register int x,y;
{
#ifdef VT100
    cursor(x, y);
    lprcat("\33[1J\33[2K");
#else VT100
    register int i;

    cursor(1, 1);
    for(i = 1; i <= y; i++) {
	*lpnt++ = CL_LINE;
	*lpnt++ = '\n';
    }
    cursor(x, y);
#endif VT100
}

/*
 * cl_dn(x,y) 	Clear screen from [1,y] to end of display. Leave cursor at [x,y]
 */
cl_dn(x, y)
register int x,y;
{
#ifdef VT100
    cursor(x, y);
    lprcat("\33[J\33[2K");
#else VT100
    register int i;

    cursor(1, y);
    if (!CD) {
	*lpnt++ = CL_LINE;
	for(i = y; i <= 24; i++) {
	    *lpnt++ = CL_LINE;
	    if (i != 24)
		*lpnt++ = '\n';
	}
	cursor(x, y);
    } else
	*lpnt++ = CL_DOWN;
    cursor(x, y);
#endif VT100
}


/*
 * standout(str)    Print the argument string in inverse video(standout mode).
 */
standout(str)
register char *str;
{
#ifdef VT100
    setbold();
    while(*str)
	*lpnt++ = *str++;
    resetbold();
#else VT100
    *lpnt++ = ST_START;
    while(*str)
	*lpnt++ = *str++;
    *lpnt++ = ST_END;
#endif VT100
}


/*
 * set_score_output() 	Called when output should be literally printed.
 */
set_score_output()
{
    enable_scroll = -1;
}

/*
 *  lflush()			Flush the output buffer
 *
 *  Returns nothing of value.
 *  For termcap version: Flush output in output buffer according to output
 *			 status as indicated by `enable_scroll'
 */
#ifndef VT100
static int scrline = 18;  /* line # for wraparound instead of scrolling if no DL */
lflush()
{
    register int lpoint;
    register char *str;
    static int curx = 0;
    static int cury = 0;

    if ((lpoint = lpnt - lpbuf) > 0) {
#ifdef EXTRA
	c[BYTESOUT] += lpoint;
#endif
	if (enable_scroll <= -1) {
	    flush_buf();
	    if (write(lfd, lpbuf, lpoint) != lpoint)
		write(2, "error writing to output file\n", 29);
	    lpnt = lpbuf;	/* point back to beginning of buffer */
	    return;
	}
	for(str = lpbuf; str < lpnt; str++) {
	    if (*str >= 32) {
		writechar(*str);
		curx++;
	    } else
		switch(*str) {
		    case CLEAR: 
			tputs(CL, 0, writechar);
			curx = cury = 0;
			break;

		    case CL_LINE: 
			tputs(CE, 0, writechar);
			break;

		    case CL_DOWN: 
			tputs(CD, 0, writechar);
			break;

		    case ST_START: 
			tputs(SO, 0, writechar);
			break;

		    case ST_END: 
			tputs(SE, 0, writechar);
			break;

		    case CURSOR: 
			curx = *++str - 1;
			cury = *++str - 1;
			tputs(tgoto(CM, curx, cury), 0, writechar);
			break;

		    case '\n': 
			if ((cury == 23) && enable_scroll) {
			    if (!DL || !AL) {/* wraparound or scroll? */
				if (++scrline > 23)
				    scrline = 19;

				if (++scrline > 23)
				    scrline = 19;
				tputs(tgoto(CM, 0, scrline), 0, writechar);
				tputs(CE, 0, writechar);

				if (--scrline < 19)
				    scrline = 23;
				tputs(tgoto(CM, 0, scrline), 0, writechar);
				tputs(CE, 0, writechar);
			    } else {
				tputs(tgoto(CM, 0, 19), 0, writechar);
				tputs(DL, 0, writechar);
				tputs(tgoto(CM, 0, 23), 0, writechar);
			    /* 	tputs(AL, 0, writechar); */
			    }
			} else {
			    writechar('\n');
			    cury++;
			}
			curx = 0;
			break;

		    default: 
			writechar(*str);
			curx++;
		};
	}
    }
    lpnt = lpbuf;
    flush_buf();		/* flush real output buffer now */
}
#else VT100
/*
 *  lflush()				flush the output buffer
 *
 *  Returns nothing of value.
 */
lflush()
{
    register int lpoint;

    if ((lpoint = lpnt - lpbuf) > 0) {
#ifdef EXTRA
	c[BYTESOUT] += lpoint;
#endif
	if (write(lfd, lpbuf, lpoint) != lpoint)
	    write(2, "error writing to output file\n", 29);
    }
    lpnt = lpbuf;		/* point back to beginning of buffer */
}
#endif VT100

#ifndef VT100
static int index = 0;
/*
 * writechar(ch)		Print one character in decoded output buffer.
 */
int writechar(c)
int c;
{
    outbuf[index++] = c;
    if (index >= BUFBIG)
	flush_buf();
}

/*
 * flush_buf()			Flush buffer with decoded output.
 */
flush_buf()
{
    if (index)
	write(lfd, outbuf, index);
    index = 0;
}


/*
 * char *tmcapcnv(sd,ss)  Routine to convert VT100 escapes to termcap format
 *
 * Processes only the \33[#m sequence(converts . files for termcap use)
 */
char *tmcapcnv(sd, ss)
register char *sd,*ss;
{
    register int tmstate = 0;	/* 0=normal, 1=\33 2=[ 3=# */
    char *sdptr,tmdigit = 0;	/* the # in \33[#m */

    sdptr = sd;
    while(*ss) {
	switch(tmstate) {
	    case 0: 
		if (*ss == '\33') {
		    tmstate++;
		    break;
		}
	ign: 
		*sdptr++ = *ss;
	ign2: 
		tmstate = 0;
		break;
	    case 1: 
		if (*ss != '[')
		    goto ign;
		tmstate++;
		break;
	    case 2: 
		if (isdigit(*ss)) {
		    tmdigit = *ss - '0';
		    tmstate++;
		    break;
		}
		if (*ss == 'm') {
		    *sdptr++ = ST_END;
		    goto ign2;
		}
		goto ign;
	    case 3: 
		if (*ss == 'm') {
		    if (tmdigit)
			*sdptr++ = ST_START;
		    else
			*sdptr++ = ST_END;
		    goto ign2;
		}
	    default: 
		goto ign;
	};
	ss++;
    }
    *sdptr = 0;			/* NULL terminator */
    return(sd);
}
#endif VT100


/*
 *   beep()	Routine to emit a beep if enabled(see no-beep in larn.opt)
 */
beep()
{
    if (!nobeep)
	*lpnt++ = '\7';
}
SHAR_EOF
if test 22021 -ne "`wc -c < 'io.c'`"
then
	echo shar: error transmitting "'io.c'" '(should have been 22021 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'keysense.c'" '(7755 characters)'
if test -f 'keysense.c'
then
	echo shar: will not over-write existing file "'keysense.c'"
else
cat << \SHAR_EOF > 'keysense.c'

/*
 *  MODULE NAME   : KEYSENSE
 *  MODULE TYPE   : Implementation
 *
 *  DESCRIPTION:
 *    This module declares three functions that, together, make it possible to
 *    to sense single keypresses in VAX/VMS.  There is an enable routine, a
 *    disable routine, and the actual sensing routine.  The sensing routine is
 *    synchronous - that is, it waits until a key is pressed before continuing
 *    with the program.
 *
 *  IMPLEMENTED BY:
 *    Mark D. Nagel  (Original code by Dave Conroy)
 *    Department of Internal Medicine
 *    Section of Infectious and Immunologic Diseases
 *    University of California, Davis
 *    Davis, CA  95616
 *
 *  LAST MODIFIED : 27 May 1986
 *
 *  REVISION HISTORY - Version 1.00
 */

#include <stdio.h>
#include <ctype.h>
#include <stsdef.h>
#include <ssdef.h>
#include <descrip.h>
#include <iodef.h>
#include <ttdef.h>
#include <tt2def.h>

#define EOS	'\0'
#define ESC	'\33'
#define TRUE	1
#define FALSE	0

/*
 *  GLOBAL VARIABLES
 *
 *  DESCRIPTION:
 *    The variables declared here are used globally throughout this module.
 *    They relate to I/O buffering and channel information.
 */

#define	NIBUF	128			/* Size of input buffer */
#define	EFN	0			/* Event flag number */

char	ibuf[NIBUF];			/* Input buffer */
int	nibuf = 0;			/* # of bytes in above */
int	ibufi = 0;			/* Read index */
int	oldmode[3];			/* Old TTY mode bits */
int	newmode[3];			/* New TTY mode bits */
short	iochan;				/* TTY I/O channel */

static short keysense_on = FALSE;

/*
 *  FUNCTION NAME: KeySense_On()
 *
 *  DESCRIPTION:
 *    This function assigns a channel to SYS$COMMAND on VAX/VMS and sets it
 *    to raw mode so that single keypresses may be sensed.
 *
 *  RETURN VALUE: None.
 */

void KeySense_On()
{
    struct dsc$descriptor	idsc;
    struct dsc$descriptor	odsc;
    char			oname[40];
    int				iosb[2];
    int				status;

    if (!keysense_on) {
	odsc.dsc$a_pointer = "SYS$COMMAND";
	odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
	odsc.dsc$b_dtype   = DSC$K_DTYPE_T;
	odsc.dsc$b_class   = DSC$K_CLASS_S;
	idsc.dsc$b_dtype   = DSC$K_DTYPE_T;
	idsc.dsc$b_class   = DSC$K_CLASS_S;
	do {
	    idsc.dsc$a_pointer = odsc.dsc$a_pointer;
	    idsc.dsc$w_length  = odsc.dsc$w_length;
	    odsc.dsc$a_pointer = &oname[0];
	    odsc.dsc$w_length  = sizeof(oname);
	    status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
	    if (status != SS$_NORMAL && status != SS$_NOTRAN)
		exit(status);
	    if (oname[0] == 0x1B) {
		odsc.dsc$a_pointer += 4;
		odsc.dsc$w_length  -= 4;
	    }
	} while (status == SS$_NORMAL);
	status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
	if (status != SS$_NORMAL)
	exit(status);
	status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0);
	if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
	    exit(status);
	newmode[0] = oldmode[0];		/* Only in version 4.	*/
	newmode[1] = oldmode[1] | TT$M_NOECHO | TT$M_TTSYNC;
	newmode[2] = oldmode[2] | TT2$M_PASTHRU;
	status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, newmode, sizeof(newmode), 0, 0, 0, 0);
	if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
	    exit(status);
	keysense_on = TRUE;
    }
}


/*
 *  FUNCTION NAME: KeySense(wait)
 *
 *  DESCRIPTION:
 *    This function will return the next key typed at the terminal if the 
 *    function 'KeySense_On' has been executed.  The character is returned
 *    synchronously - that is, the program will hang until a key is pressed if
 *    the parameter 'wait' is TRUE.  Otherwise, the routine will return the
 *    last key presses or -1 if no key was pressed.
 *
 *  RETURN VALUE: Single character or -1.
 */

char KeySense(wait)
int wait;
{
    int status;
    int iosb[2];
    int term[2];

    if (keysense_on) {
	term[0] = 0;
	term[1] = 0;
	while (ibufi >= nibuf) {
	    ibufi = 0;
	    status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED, iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
	    if (status != SS$_NORMAL)
		continue;
	    status = iosb[0] & 0xFFFF;
	    if (status != SS$_NORMAL && status != SS$_TIMEOUT)
		continue;
	    nibuf = (iosb[0]>>16) + (iosb[1]>>16);
	    if (nibuf == 0) {
		if (wait) {
		    status = SYS$QIOW(EFN, iochan, IO$_READLBLK, iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
		    if (status != SS$_NORMAL)
			continue;
		    if ((iosb[0] & 0xFFFF) != SS$_NORMAL)
			continue;
		    nibuf = (iosb[0]>>16) + (iosb[1]>>16);
	        } else {
		    lib$wait(&0.10);
		    return (-1);
		}
	    }
	}
	if (ibuf[ibufi] == 0x0A || ibuf[ibufi] == 0x0D)
	    ibuf[ibufi] = '\n';
	return (ibuf[ibufi++] & 0xFF);
    }
}


/*
 *  FUNCTION NAME: Check_KeySense()	
 *
 *  DESCRIPTION:
 *    This function will return TRUE if keysense is currently on and FALSE
 *    if it is not.
 *
 *  RETURN VALUE: Boolean.
 */

int Check_KeySense()
{
    return(keysense_on);
}


/*
 *  FUNCTION NAME: KeySense_Off()
 *
 *  DESCRIPTION:
 *    This function disables the single keypress input mode.  
 *
 *  RETURN VALUE: None.
 */

void KeySense_Off()
{
    int status;
    int iosb[1];

    if (keysense_on) {
	status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0);
	if (status != SS$_NORMAL || (iosb[0]&0xFFFF) != SS$_NORMAL)
	    exit(status);
	status = SYS$DASSGN(iochan);
	if (status != SS$_NORMAL)
	    exit(status);
	keysense_on = FALSE;
    }
}


/*
 *  FUNCTION NAME: system(cmd)
 *
 *  DESCRIPTION:
 *    Run a command. The "cmd" is a pointer to a command string, or NULL if
 *    you want to run a copy of DCL in the subjob (this is how the standard
 *    routine LIB$SPAWN works. You have to do weird stuff with the terminal
 *    on the way in and the way out if KeySense is on, because DCL does not
 *    want the channel to be in raw mode.
 *
 *  RETURN VALUE: None.
 */

system(cmd)
register char *cmd;
{
    struct  dsc$descriptor  cdsc;
    struct  dsc$descriptor  *cdscp;
    long    status;
    long    substatus;
    long    iosb[2];

    if (keysense_on) {
	status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0);
	if (status != SS$_NORMAL || (iosb[0]&0xFFFF) != SS$_NORMAL)
	    return (FALSE);
    }
    cdscp = NULL;			/* Assume DCL.       */
    if (cmd != NULL) {			/* Build descriptor. */
	cdsc.dsc$a_pointer = cmd;
	cdsc.dsc$w_length  = strlen(cmd);
	cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
	cdsc.dsc$b_class   = DSC$K_CLASS_S;
	cdscp = &cdsc;
    }
    status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
    if (status != SS$_NORMAL)
	substatus = status;
    if (keysense_on) {
	status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, newmode, sizeof(newmode), 0, 0, 0, 0);
	if (status != SS$_NORMAL || (iosb[0]&0xFFFF) != SS$_NORMAL)
	    return (FALSE);
    }
    if ((substatus & STS$M_SUCCESS) == 0)     /* Command failed. */
	return (FALSE);
    return (TRUE);
}


/*
 *  FUNCTION NAME: getpass(prompt)
 *
 *  DESCRIPTION:
 *    Read a password from the keyboard with echoing turned off.  The password
 *    must be terminated by a CR.  This CR will become a NUL.  The password
 *    is stored statically, so if it is necessary to keep it you must copy
 *    it.
 *
 *  RETURN VALUE: pointer to string or NULL if this is an invalid device.
 */

#define MAXBUF	100

char *getpass(prompt)
char *prompt;
{
    static char inbuf[MAXBUF+1];
    char ch, KeySense();
    int i = 0, was_on;

    was_on = keysense_on;
    if (isatty(stdin)) {
	puts(prompt);
	KeySense_On();
	while (1) {
	    ch = KeySense(1);
	    if ((ch == 0x7F || ch == 0x08) && i > 0)
		--i;
	    else if (ch == 0x0A || ch == 0x0D)
		break;
	    else if (i >= MAXBUF - 1)
		continue;
	    else if (isprint(ch))
		inbuf[i++] = ch;
	}
	inbuf[i] = '\0';
	if (!was_on)
	    KeySense_Off();
	return(inbuf);
    }
    return(NULL);
}
SHAR_EOF
if test 7755 -ne "`wc -c < 'keysense.c'`"
then
	echo shar: error transmitting "'keysense.c'" '(should have been 7755 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'larn.c'" '(28359 characters)'
if test -f 'larn.c'
then
	echo shar: will not over-write existing file "'larn.c'"
else
cat << \SHAR_EOF > 'larn.c'

/*	main.c		*/

#include "header.h"
#include <times.h>

#ifndef LARNHOME
#define LARNHOME "SYS$GAMES:"	/* normally supplied by a Makefile */
#endif

#ifndef WIZID
#define WIZID	0
#endif

#define MAXFILENAMESIZE	128

/*
 * All these strings will be appended to in main() to be complete filenames
 */

/* the game save filename */
globaldef char savefilename[SAVEFILENAMESIZE];

/* the score file */
globaldef char scorefile[255];

/* the logging file */
globaldef char logfile[255];

/* the help text file */
globaldef char helpfile[255];

/* the maze data file */
globaldef char larnlevels[255];

/* the fortune data file */
globaldef char fortfile[255];

/* the larn.opt filename */
globaldef char optsfile[255];

/* the player id datafile name */
globaldef char playerids[255];

/* the holiday datafile */
globaldef char holifile[255];

globaldef char diagfile[] = "LARN12.DBG";	/* the diagnostic filename */
globaldef char ckpfile[]  = "LARN12.CKP";	/* the checkpoint filename */
globaldef char *password  = "pvnert(x)";	/* the wizards password <=32 */

#if WIZID == -1
globaldef int wisid = 0;	/* the user id of the only person who can be wizard */
#else
globaldef int wisid = WIZID;	/* the user id of the only person who can be wizard */
#endif

static char copyright[] = "\nLarn is copyrighted 1986 by Noah Morgan.\n";

globaldef int srcount = 0;	/* line counter for showstr() */
globaldef int dropflag = 0;	/* if 1 then don't lookforobject() next round */
int rmst = 80;			/* random monster creation counter */
globaldef int userid;		/* the players login user id number */
globaldef char nowelcome = 0;
globaldef char nomove = 0;	/* if (nomove) then don't count next iteration as a move */
globaldef long start_cpu;

static char viewflag = 0;
/* if viewflag then we have done a 99 stay here and don't showcell in the main loop */
globaldef char restorflag = 0;		/* 1 means restore has been done */

static char cmdhelp[] = "\
Cmd line format: larn [-slicnh] [-o<optsifle>] [-##] [++]\n\
  -s   show the scoreboard\n\
  -l   show the logfile\n\
  -i   show scoreboard with inventory of checkpoint file\n\
  -c   clear the scoreboard file (requires password)\n\
  -h   print this help message\n\
  -o<optsfile> specify option filename to be used instead of LARN12.OPT\n\
  -##  set the difficulty level to ##\n\
  ++   restore a checkpointed game\n\
";

#ifdef VT100
static char *termtypes[] = {
    "vt100-80", "vt100","vt101", "vt102", "vt103",
    "vt125", "vt131", "vt140"
};
#endif VT100

main(argc, argv)
int argc;
char **argv;
{
    register int i,j;
    int hard;
    char *ptr = 0, *ttype;
    struct tms cputime;

/*
 *	first task is to identify the player
 */
#ifndef VT100
    init_term();	/* setup the terminal(find out what type) for termcap */
#endif VT100
    if ((ptr = getenv("USER")) == 0)
	if ((ptr = getenv("LOGNAME")) == 0) {
	    write(2, "Can't find your logname.  Who Are You?\n", 39);
	    exit();
	}

    times(&cputime);		/* need to know what it was */
    start_cpu = cputime.tms_utime + cputime.tms_stime;

/*
 *	now malloc the memory for the buffers 
 */
    lpbuf = malloc((5 * BUFBIG) >> 2);/* output buffer */
    inbuffer = malloc((5 * MAXIBUF) >> 2);/* output buffer */
    if ((lpbuf == 0) ||(inbuffer == 0))
	died(-285);	/* malloc() failure */

    lcreat((char *) 0);
    newgame();		/* set the initial clock  */
    for (i = 0; i < MAXLEVEL+MAXVLEVEL; beenhere[i++] = 0);
    hard = -1;

/*
 *	second task is to prepare the pathnames the player will need
 */
    strcpy(loginname, ptr);/* save loginname of the user for logging purposes */
    strcpy(logname, ptr);	/* this will be overwritten with the players name */
    if ((ptr = getenv("HOME")) == 0)
	ptr = "[]";
#ifdef SAVEINHOME
    sprintf(savefilename,"%sLARN12.SAV",ptr);
#else
    sprintf(savefilename,%s%s.SAV",LARNHOME,logname);	/* prepare savefile name */
#endif
    sprintf(optsfile, "%sLARN12.OPT", ptr);		/* the larn.opt filename */
    sprintf(scorefile,"%s%s",LARNHOME,SCORENAME);	/* the larn scoreboard filename */
    sprintf(logfile,"%s%s",LARNHOME,LOGFNAME);		/* larn activity logging filename */
    sprintf(helpfile,"%s%s",LARNHOME,HELPNAME);		/* the larn on-line help file */
    sprintf(larnlevels,"%s%s",LARNHOME,LEVELSNAME);	/* the pre-made cave level data file */
    sprintf(fortfile,"%s%s",LARNHOME,FORTSNAME);	/* the fortune data file name */
    sprintf(playerids,"%s%s",LARNHOME,PLAYERIDS);	/* the playerid data file name */
    sprintf(holifile,"%s%s",LARNHOME,HOLIFILE);		/* the holiday data file name */

#ifdef VT100
/*
 *	check terminal type to avoid users who have not vt100 type terminals
 */
    ttype = getenv("TERM");
    for (j = 1, i = 0; i < sizeof(termtypes) / sizeof(char *); i++)
	if (strcmp(ttype, termtypes[i]) == 0) {
	    j = 0;
	    break;
	}
    if (j)  {
	lprcat("Sorry, Larn needs a VT100 family terminal for all it's features.\n");
	lflush();
	exit();
    }
#endif VT100

/*
 *	now make scoreboard if it is not there (don't clear) 
 */
    if (access(scorefile, 0) == -1)/* not there */
	makeboard();

/*
 *	now process the command line arguments 
 */
    for (i = 1; i < argc; i++) {
	if (argv[i][0] == '-')
	    switch(argv[i][1]) {
		case 's':	/* show scoreboard */
		    showscores();
		    exit();

		case 'l': 	/* show log file */
		    diedlog();
		    exit();

		case 'i':	/* show all scoreboard */
		    showallscores();
		    exit();

		case 'c': 	/* anyone with password can create scoreboard */
		    lprcat("Preparing to initialize the scoreboard.\n");
		    if (getpassword() != 0) {	/* make new scoreboard */
			makeboard();
			lprc('\n');
			showscores();
		    }
		    exit();

		case 'n': 	/* no welcome msg	 */
		    nowelcome = 1;
		    argv[i][0] = 0;
		    break;

		case '0': 
		case '1': 
		case '2': 
		case '3': 
		case '4': 
		case '5': 
		case '6': 
		case '7': 
		case '8': 
		case '9': 	/* for hardness */
		    sscanf(&argv[i][1], "%d", &hard);
		    break;

		case 'h': 	/* print out command line arguments */
		    write(1, cmdhelp, sizeof(cmdhelp));
		    exit();

		case 'o': 	/* specify a larn.opt filename */
		    strncpy(optsfile, argv[i] + 2, 127);
		    break;

		default: 
		    printf("Unknown option <%s>\n", argv[i]);
		    exit();
	    };

	if (argv[i][0] == '+') {
	    clear();
	    restorflag = 1;
	    if (argv[i][1] == '+') {
		hitflag = 1;
		restoregame(ckpfile);/* restore checkpointed game */
	    }
	    i = argc;
	}
    }

    readopts();	/* read the options file if there is one */

#ifdef UIDSCORE
    userid = (getegid()<<16) | geteuid();    /* obtain the user's id number */
#else UIDSCORE
    userid = getplid(logname);	/* obtain the players id number */
    if (userid < 0) {
	write(2, "Can't obtain playerid\n", 22);
	exit(1);
    }
#endif UIDSCORE

#ifdef TIMECHECK
/*
 *  this section of code checks to see if larn is allowed during working hours
 */
    if (dayplay == 0)	/* check for not-during-daytime-hours */
	if (playable()) {
	    write(2, "Sorry, Larn can not be played during working hours.\n", 52);
	    exit();
	}
#endif TIMECHECK

    if (access(savefilename, 0) == 0) {	/* restore game if need to */
	clear();
	restorflag = 1;
	hitflag = 1;
	restoregame(savefilename);/* restore last game	 */
    }
    sigsetup();		/* trap all needed signals */
    sethard(hard);		/* set up the desired difficulty */
    setupvt100();		/* setup the terminal special mode */
    if (c[HP] == 0) {		/* create new game */
	makeplayer();		/* make the character that will play */
	newcavelevel(0);	/* make the dungeon */
	predostuff = 1;		/* tell signals that we are in the welcome screen */
	if (nowelcome == 0)
	    welcome();		/* welcome the player to the game */
    }
    drawscreen();		/* show the initial dungeon */
    predostuff = 2;		/* tell the trap functions that they must do a showplayer() from here on */
    nice(1);			/* games should be run niced */
    yrepcount = hit2flag = 0;
    while (1) {
	if (dropflag == 0)
	    lookforobject();	/* see if there is an object here */
	else
	    dropflag = 0;	/* don't show it just dropped an item */
	if (hitflag == 0) {
	    if (c[HASTEMONST])
		movemonst();
	    movemonst();
	}			/* move the monsters */
	if (viewflag == 0)
	    showcell(playerx, playery);
	else
	    viewflag = 0;	/* show stuff around player */
	if (hit3flag)
	    flushall();
	hitflag = hit3flag = 0;
	nomove = 1;
	bot_linex();	/* update bottom line */
	while (nomove) {
	    if (hit3flag)
		flushall();
	    nomove = 0;
	    parse();
	}			/* get commands and make moves */
	regen();		/* regenerate hp and spells */
	if (c[TIMESTOP] == 0)
	    if (--rmst <= 0) {
		rmst = 120 - (level << 2);
		fillmonst(makemonst(level));
	    }
    }
}


/*
	showstr()

	show character's inventory
 */
showstr()
{
    register int i,number;

    for (number = 3, i = 0; i < 26; i++)
	if (iven[i])
	    number++;	/* count items in inventory */
    t_setup(number);
    qshowstr();
    t_endup(number);
}

qshowstr()
{
    register int i,j,k,sigsav;

    srcount = 0;
    sigsav = nosignal;
    nosignal = 1;		/* don't allow ^C etc */
    if (c[GOLD]) {
	lprintf(".)   %d gold pieces",(long) c[GOLD]);
	srcount++;
    }
    for (k = 26; k >= 0; k--)
	if (iven[k]) {
	    for (i = 22; i < 84; i++)
		for (j = 0; j <= k; j++)
		    if (i == iven[j])
			show3(j);
	    k = 0;
	}

    lprintf("\nElapsed time is %d.  You have %d mobuls left",(long)((gtime + 99) / 100 + 1),(long)((TIMELIMIT - gtime) / 100));
    more();
    nosignal = sigsav;
}


/*
 *	subroutine to clear screen depending on # lines to display
 */
t_setup(count)
register int count;
{
    if (count < 20) {	/* how do we clear the screen? */
	cl_up(79, count);
	cursor(1, 1);
    } else {
	resetscroll();
	clear();
    }
}

/*
 *	subroutine to restore normal display screen depending on t_setup()
 */
t_endup(count)
register int count;
{
    if (count < 18)		/* how did we clear the screen? */
	draws(0, MAXX, 0,(count > MAXY) ? MAXY : count);
    else {
	drawscreen();
	setscroll();
    }
}

/*
	function to show the things player is wearing only
 */
showwear()
{
    register int i,j,sigsav,count;

    sigsav = nosignal;
    nosignal = 1;		/* don't allow ^c etc */
    srcount = 0;

    for (count = 2, j = 0; j <= 26; j++)/* count number of items we will display */
	if (i = iven[j])
	    switch(i) {
		case OLEATHER: 
		case OPLATE: 
		case OCHAIN: 
		case ORING: 
		case OSTUDLEATHER: 
		case OSPLINT: 
		case OPLATEARMOR: 
		case OSSPLATE: 
		case OSHIELD: 
		    count++;
	    };

    t_setup(count);

    for (i = 22; i < 84; i++)
	for (j = 0; j <= 26; j++)
	    if (i == iven[j])
		switch(i) {
		    case OLEATHER: 
		    case OPLATE: 
		    case OCHAIN: 
		    case ORING: 
		    case OSTUDLEATHER: 
		    case OSPLINT: 
		    case OPLATEARMOR: 
		    case OSSPLATE: 
		    case OSHIELD: 
			show3(j);
		};
    more();
    nosignal = sigsav;
    t_endup(count);
}

/*
	function to show the things player can wield only 
 */
showwield()
{
    register int i,j,sigsav,count;

    sigsav = nosignal;
    nosignal = 1;		/* don't allow ^c etc */
    srcount = 0;

    for (count = 2, j = 0; j <= 26; j++)/* count how many items */
	if (i = iven[j])
	    switch(i) {
		case ODIAMOND: 
		case ORUBY: 
		case OEMERALD: 
		case OSAPPHIRE: 
		case OBOOK: 
		case OCHEST: 
		case OLARNEYE: 
		case ONOTHEFT: 
		case OSPIRITSCARAB: 
		case OCUBEofUNDEAD: 
		case OPOTION: 
		case OSCROLL: 
		    break;
		default: 
		    count++;
	    };

    t_setup(count);

    for (i = 22; i < 84; i++)
	for (j = 0; j <= 26; j++)
	    if (i == iven[j])
		switch(i) {
		    case ODIAMOND: 
		    case ORUBY: 
		    case OEMERALD: 
		    case OSAPPHIRE: 
		    case OBOOK: 
		    case OCHEST: 
		    case OLARNEYE: 
		    case ONOTHEFT: 
		    case OSPIRITSCARAB: 
		    case OCUBEofUNDEAD: 
		    case OPOTION: 
		    case OSCROLL: 
			break;
		    default: 
			show3(j);
		};
    more();
    nosignal = sigsav;
    t_endup(count);
}

/*
 *	function to show the things player can read only
 */
showread()
{
    register int i,j,sigsav,count;

    sigsav = nosignal;
    nosignal = 1;		/* don't allow ^c etc */
    srcount = 0;

    for (count = 2, j = 0; j <= 26; j++)
	switch(iven[j]) {
	    case OBOOK: 
	    case OSCROLL: 
		count++;
	};
    t_setup(count);

    for (i = 22; i < 84; i++)
	for (j = 0; j <= 26; j++)
	    if (i == iven[j])
		switch(i) {
		    case OBOOK: 
		    case OSCROLL: 
			show3(j);
		};
    more();
    nosignal = sigsav;
    t_endup(count);
}

/*
 *	function to show the things player can eat only
 */
showeat()
{
    register int i,j,sigsav,count;

    sigsav = nosignal;
    nosignal = 1;		/* don't allow ^c etc */
    srcount = 0;

    for (count = 2, j = 0; j <= 26; j++)
	switch(iven[j]) {
	    case OCOOKIE: 
		count++;
	};
    t_setup(count);

    for (i = 22; i < 84; i++)
	for (j = 0; j <= 26; j++)
	    if (i == iven[j])
		switch(i) {
		    case OCOOKIE: 
			show3(j);
		};
    more();
    nosignal = sigsav;
    t_endup(count);
}

/*
	function to show the things player can quaff only
 */
showquaff()
{
    register int i,j,sigsav,count;

    sigsav = nosignal;
    nosignal = 1;		/* don't allow ^c etc */
    srcount = 0;

    for (count = 2, j = 0; j <= 26; j++)
	switch(iven[j]) {
	    case OPOTION: 
		count++;
	};
    t_setup(count);

    for (i = 22; i < 84; i++)
	for (j = 0; j <= 26; j++)
	    if (i == iven[j])
		switch(i) {
		    case OPOTION: 
			show3(j);
		};
    more();
    nosignal = sigsav;
    t_endup(count);
}

show1(idx, str2)
register int idx;
register char *str2[];
{
    if (str2 == 0)
	lprintf("\n%c)   %s", idx + 'a', objectname[iven[idx]]);
    else
	if (*str2[ivenarg[idx]] == 0)
	    lprintf("\n%c)   %s", idx + 'a', objectname[iven[idx]]);
	else
	    lprintf("\n%c)   %s of%s", idx + 'a', objectname[iven[idx]], str2[ivenarg[idx]]);
}

show3(index)
register int index;
{
    switch(iven[index]) {
	case OPOTION: 
	    show1(index, potionname);
	    break;
	case OSCROLL: 
	    show1(index, scrollname);
	    break;

	case OLARNEYE: 
	case OBOOK: 
	case OSPIRITSCARAB: 
	case ODIAMOND: 
	case ORUBY: 
	case OCUBEofUNDEAD: 
	case OEMERALD: 
	case OCHEST: 
	case OCOOKIE: 
	case OSAPPHIRE: 
	case ONOTHEFT: 
	    show1(index,(char **) 0);
	    break;

	default: 
	    lprintf("\n%c)   %s", index + 'a', objectname[iven[index]]);
	    if (ivenarg[index] > 0)
		lprintf(" + %d",(long) ivenarg[index]);
	    else
		if (ivenarg[index] < 0)
		    lprintf(" %d",(long) ivenarg[index]);
	    break;
    }
    if (c[WIELD] == index)
	lprcat("(weapon in hand)");
    if ((c[WEAR] == index) ||(c[SHIELD] == index))
	lprcat("(being worn)");
    if (++srcount >= 22) {
	srcount = 0;
	more();
	clear();
    }
}

/*
	subroutine to randomly create monsters if needed
 */
randmonst()
{
    if (c[TIMESTOP])
	return;		/* 	don't make monsters if time is stopped	 */
    if (--rmst <= 0) {
	rmst = 120 - (level << 2);
	fillmonst(makemonst(level));
    }
}


/*
    parse()

    get and execute a command
 */
parse()
{
    register int i,j,k,flag;

    while (1) {
	k = yylex();
	switch(k) {	/*  get the token from the input and switch on it */
	    case 'h': 
		moveplayer(4);
		return;		/* west */
	    case 'H': 
		run(4);
		return;		/* west */
	    case 'l': 
		moveplayer(2);
		return;		/* east */
	    case 'L': 
		run(2);
		return;		/* east */
	    case 'j': 
		moveplayer(1);
		return;		/* south */
	    case 'J': 
		run(1);
		return;		/* south */
	    case 'k': 
		moveplayer(3);
		return;		/* north */
	    case 'K': 
		run(3);
		return;		/* north */
	    case 'u': 
		moveplayer(5);
		return;		/* northeast */
	    case 'U': 
		run(5);
		return;		/* northeast */
	    case 'y': 
		moveplayer(6);
		return;		/* northwest */
	    case 'Y': 
		run(6);
		return;		/* northwest */
	    case 'n': 
		moveplayer(7);
		return;		/* southeast */
	    case 'N': 
		run(7);
		return;		/* southeast */
	    case 'b': 
		moveplayer(8);
		return;		/* southwest */
	    case 'B': 
		run(8);
		return;		/* southwest */

	    case '.': 		/* stay here */
		if (yrepcount)
		    viewflag = 1;
		return;

	    case 'w': 		/* wield a weapon */
		yrepcount = 0;
		wield();
		return;

	    case 'W':	 	/* wear armor */
		yrepcount = 0;
		wear();
		return;

	    case 'r':	 	/* to read a scroll */
		yrepcount = 0;
		if (c[BLINDCOUNT]) {
		    cursors();
		    lprcat("\nYou can't read anything when you're blind!");
		} else if (c[TIMESTOP] == 0)
		    readscr();
		return;

	    case 'q':	 	/* quaff a potion */
		yrepcount = 0;
		if (c[TIMESTOP] == 0)
		    quaff();
		return;

	    case 'd':		/* to drop an object */
		yrepcount = 0;
		if (c[TIMESTOP] == 0)
		    dropobj();
		return;

	    case 'c':		/* cast a spell */
		yrepcount = 0;
		cast();
		return;

	    case 'i':		/* status */
		yrepcount = 0;
		nomove = 1;
		showstr();
		return;

	    case 'e':		/* to eat a fortune cookie */
		yrepcount = 0;
		if (c[TIMESTOP] == 0)
		    eatcookie();
		return;

	    case 'D':		/* list spells and scrolls */
		yrepcount = 0;
		seemagic(0);
		nomove = 1;
		return;

	    case '?': 		/* give the help screen */
		yrepcount = 0;
		help();
		nomove = 1;
		return;

	    case 'S':   	/* save the game - doesn't return */
		clear();
		lprcat("Saving . . .");
		lflush();
		savegame(savefilename);
		wizard = 1;
		died(-257);

	    case 'Z': 
		yrepcount = 0;
		if (c[LEVEL] > 9) {
		    oteleport(1);
		    return;
		}
		cursors();
		lprcat("\nAs yet, you don't have enough experience to use teleportation");
		return;	/* teleport yourself */

	    case '^': 	/* identify traps */
		flag = yrepcount = 0;
		cursors();
		lprc('\n');
		for (j = playery - 1; j < playery + 2; j++) {
		    if (j < 0)
			j = 0;
		    if (j >= MAXY)
			break;
		    for (i = playerx - 1; i < playerx + 2; i++) {
			if (i < 0)
			    i = 0;
			if (i >= MAXX)
			    break;
			switch(item[i][j]) {
			    case OTRAPDOOR: 
			    case ODARTRAP: 
			    case OTRAPARROW: 
			    case OTELEPORTER: 
				lprcat("\nIts ");
				lprcat(objectname[item[i][j]]);
				flag++;
			};
		    }
		}
		if (flag == 0)
		    lprcat("\nNo traps are visible");
		return;

#if WIZID
	    case '_': 	/* this is the fudge player password for wizard mode */
		yrepcount = 0;
		cursors();
		nomove = 1;
		if (userid != wisid) {
		    lprcat("Sorry, you are not empowered to be a wizard.\n");
		    scbr();	/* system("stty -echo cbreak"); */
		    lflush();
		    return;
		}
		if (getpassword() == 0) {
		    scbr();	/* system("stty -echo cbreak"); */
		    return;
		}
		wizard = 1;
		scbr();		/* system("stty -echo cbreak"); */
		for (i = 0; i < 6; i++)
		    c[i] = 70;
		iven[0] = iven[1] = 0;
		take(OPROTRING, 50);
		take(OLANCE, 25);
		c[WIELD] = 1;
		c[LANCEDEATH] = 1;
		c[WEAR] = c[SHIELD] = -1;
		raiseexperience(6000000L);
		c[AWARENESS] += 25000;
		{
		    register int i,j;

		    for (i = 0; i < MAXY; i++)
			for (j = 0; j < MAXX; j++)
			    know[j][i] = 1;
		    for (i = 0; i < SPNUM; i++)
			spelknow[i] = 1;
		    for (i = 0; i < MAXSCROLL; i++)
			scrollname[i][0] = ' ';
		    for (i = 0; i < MAXPOTION; i++)
			potionname[i][0] = ' ';
		}
		for (i = 0; i < MAXSCROLL; i++)
		    if (strlen(scrollname[i]) > 2) {	/* no null items */
			item[i][0] = OSCROLL;
			iarg[i][0] = i;
		    }
		for (i = MAXX - 1; i > MAXX - 1 - MAXPOTION; i--)
		    if (strlen(potionname[i - MAXX + MAXPOTION]) > 2) {/* no null items */
			item[i][0] = OPOTION;
			iarg[i][0] = i - MAXX + MAXPOTION;
		    }
		for (i = 1; i < MAXY; i++) {
		    item[0][i] = i;
		    iarg[0][i] = 0;
		}
		for (i = MAXY; i < MAXY + MAXX; i++) {
		    item[i - MAXY][MAXY - 1] = i;
		    iarg[i - MAXY][MAXY - 1] = 0;
		}
		for (i = MAXX + MAXY; i < MAXX + MAXY + MAXY; i++) {
		    item[MAXX - 1][i - MAXX - MAXY] = i;
		    iarg[MAXX - 1][i - MAXX - MAXY] = 0;
		}
		c[GOLD] += 250000;
		drawscreen();
		return;
#endif

	    case 'T': 
		yrepcount = 0;
		cursors();
		if (c[SHIELD] != -1) {
		    c[SHIELD] = -1;
		    lprcat("\nYour shield is off");
		    bottomline();
		} else if (c[WEAR] != -1) {
		    c[WEAR] = -1;
		    lprcat("\nYour armor is off");
		    bottomline();
		} else
		    lprcat("\nYou aren't wearing anything");
		return;

	    case 'g': 
		cursors();
		lprintf("\nThe stuff you are carrying presently weighs %d pounds",(long) packweight());
	    case ' ': 
		yrepcount = 0;
		nomove = 1;
		return;

	    case 'v': 
		yrepcount = 0;
		cursors();
		lprintf("\nCaverns of Larn, Version %d.%d, Diff=%d",(long) VERSION,(long) SUBVERSION,(long) c[HARDGAME]);
		if (wizard)
		    lprcat(" Wizard");
		nomove = 1;
		if (cheat)
		    lprcat(" Cheater");
		lprcat(copyright);
		return;

	    case 'Q': 		/* quit */
	    case 'Y'-64:
	    case 'C'-64:
		yrepcount = 0;
		quit();
		nomove = 1;
		return;

	    case 'L' - 64:	/* look */ 
		yrepcount = 0;
		drawscreen();
		nomove = 1;
		return;

#if WIZID
#ifdef EXTRA
	    case 'A': 		/* create diagnostic file */
		yrepcount = 0;
		nomove = 1;
		if (wizard) {
		    diag();
		    return;
		}
		return;
#endif
#endif
	    case 'P': 
		cursors();
		if (outstanding_taxes > 0)
		    lprintf("\nYou presently owe %d gp in taxes.",(long) outstanding_taxes);
		else
		    lprcat("\nYou do not owe any taxes.");
		return;
	};
    }
}


parse2()
{
    if (c[HASTEMONST])
	movemonst();
    movemonst();		/* move the monsters */
    randmonst();
    regen();
}

run(dir)
int dir;
{
    register int i = 1;

    while (i) {
	i = moveplayer(dir);
	if (i > 0) {
	    if (c[HASTEMONST])
		movemonst();
	    movemonst();
	    randmonst();
	    regen();
	}
	if (hitflag)
	    i = 0;
	if (i != 0)
	    showcell(playerx, playery);
    }
}


/*
	function to wield a weapon
 */
wield()
{
    register int i;

    while (1) {
	if ((i = whatitem("wield")) == '\33')
	    return;
	if (i != '.') {
	    if (i == '*')
		showwield();
	    else
		if (iven[i - 'a'] == 0) {
		    ydhi(i);
		    return;
		} else
		    if (iven[i - 'a'] == OPOTION) {
			ycwi(i);
			return;
		    } else
			if (iven[i - 'a'] == OSCROLL) {
			    ycwi(i);
			    return;
			} else
			    if ((c[SHIELD] != -1) &&(iven[i - 'a'] == O2SWORD)) {
				lprcat("\nBut one arm is busy with your shield!");
				return;
			    } else {
				c[WIELD] = i - 'a';
				if (iven[i - 'a'] == OLANCE)
				    c[LANCEDEATH] = 1;
				else
				    c[LANCEDEATH] = 0;
				bottomline();
				return;
			    }
	}
    }
}

/*
	common routine to say you don't have an item
 */
ydhi(x)
int x;
{
    cursors();
    lprintf("\nYou don't have item %c!", x);
}

ycwi(x)
int     x;
{
    cursors();
    lprintf("\nYou can't wield item %c!", x);
}

/*
	function to wear armor
 */
wear()
{
    register int    i;

    while (1) {
	if ((i = whatitem("wear")) == '\33')
	    return;
	if (i != '.') {
	    if (i == '*')
		showwear();
	    else
		switch(iven[i - 'a']) {
		    case 0: 
			ydhi(i);
			return;
		    case OLEATHER: 
		    case OCHAIN: 
		    case OPLATE: 
		    case OSTUDLEATHER: 
		    case ORING: 
		    case OSPLINT: 
		    case OPLATEARMOR: 
		    case OSSPLATE: 
			if (c[WEAR] != -1) {
			    lprcat("\nYou're already wearing some armor");
			    return;
			}
			c[WEAR] = i - 'a';
			bottomline();
			return;
		    case OSHIELD: 
			if (c[SHIELD] != -1) {
			    lprcat("\nYou are already wearing a shield");
			    return;
			}
			if (iven[c[WIELD]] == O2SWORD) {
			    lprcat("\nYour hands are busy with the two handed sword!");
			    return;
			}
			c[SHIELD] = i - 'a';
			bottomline();
			return;
		    default: 
			lprcat("\nYou can't wear that!");
		};
	}
    }
}

/*
	function to drop an object
 */
dropobj()
{
    register int i;
    register char *p;
    long amt;

    p = &item[playerx][playery];
    while (1) {
	if ((i = whatitem("drop")) == '\33')
	    return;
	if (i == '*')
	    showstr();
	else {
	    if (i == '.') {	/* drop some gold */
		if (*p) {
		    lprcat("\nThere's something here already!");
		    return;
		}
		lprcat("\n\n");
		cl_dn(1, 23);
		lprcat("How much gold do you drop? ");
		if ((amt = readnum((long) c[GOLD])) == 0)
		    return;
		if (amt > c[GOLD]) {
		    lprcat("\nYou don't have that much!");
		    return;
		}
		if (amt <= 32767) {
		    *p = OGOLDPILE;
		    i = amt;
		} else if (amt <= 327670L) {
		    *p = ODGOLD;
		    i = amt / 10;
		    amt = 10 * i;
		} else if (amt <= 3276700L) {
		    *p = OMAXGOLD;
		    i = amt / 100;
		    amt = 100 * i;
		} else if (amt <= 32767000L) {
		    *p = OKGOLD;
		    i = amt / 1000;
		    amt = 1000 * i;
		} else {
		    *p = OKGOLD;
		    i = 32767;
		    amt = 32767000L;
		}
		c[GOLD] -= amt;
		lprintf("You drop %d gold pieces",(long) amt);
		iarg[playerx][playery] = i;
		bottomgold();
		know[playerx][playery] = 0;
		dropflag = 1;
		return;
	    }
	    drop_object(i - 'a');
	    return;
	}
    }
}

/*
 *	readscr()		Subroutine to read a scroll one is carrying
 */
readscr()
{
    register int i;

    while (1) {
	if ((i = whatitem("read")) == '\33')
	    return;
	if (i != '.') {
	    if (i == '*')
		showread();
	    else {
		if (iven[i - 'a'] == OSCROLL) {
		    read_scroll(ivenarg[i - 'a']);
		    iven[i - 'a'] = 0;
		    return;
		}
		if (iven[i - 'a'] == OBOOK) {
		    readbook(ivenarg[i - 'a']);
		    iven[i - 'a'] = 0;
		    return;
		}
		if (iven[i - 'a'] == 0) {
		    ydhi(i);
		    return;
		}
		lprcat("\nThere's nothing on it to read");
		return;
	    }
	}
    }
}

/*
 *	subroutine to eat a cookie one is carrying
 */
eatcookie()
{
    register int i;
    char *p;

    while (1) {
	if ((i = whatitem("eat")) == '\33')
	    return;
	if (i != '.')
	    if (i == '*')
		showeat();
	    else {
		if (iven[i - 'a'] == OCOOKIE) {
		    lprcat("\nThe cookie was delicious.");
		    iven[i - 'a'] = 0;
		    if (!c[BLINDCOUNT]) {
			if (p = fortune(fortfile)) {
			    lprcat("  Inside you find a scrap of paper that says:\n");
			    lprcat(p);
			}
		    }
		    return;
		}
		if (iven[i - 'a'] == 0) {
		    ydhi(i);
		    return;
		}
		lprcat("\nYou can't eat that!");
		return;
	    }
    }
}

/*
 *	subroutine to quaff a potion one is carrying
 */
quaff()
{
    register int i;

    while (1) {
	if ((i = whatitem("quaff")) == '\33')
	    return;
	if (i != '.') {
	    if (i == '*')
		showquaff();
	    else {
		if (iven[i - 'a'] == OPOTION) {
		    quaffpotion(ivenarg[i - 'a']);
		    iven[i - 'a'] = 0;
		    return;
		}
		if (iven[i - 'a'] == 0) {
		    ydhi(i);
		    return;
		}
		lprcat("\nYou wouldn't want to quaff that, would you? ");
		return;
	    }
	}
    }
}

/*
	function to ask what player wants to do
 */
whatitem(str)
char *str;
{
    int i;

    cursors();
    lprintf("\nWhat do you want to %s [* for all] ? ", str);
    i = 0;
    while (i > 'z' ||(i < 'a' && i != '*' && i != '\33' && i != '.'))
	i = readchar();
    if (i == '\33')
	lprcat(" aborted");
    return(i);
}

/*
	subroutine to get a number from the player
	and allow * to mean return amt, else return the number entered
 */
unsigned long readnum(mx)
long mx;
{
    register int i;
    register unsigned long amt = 0;

    sncbr();
    if ((i = readchar()) == '*')
	amt = mx;		/* allow him to say * for all gold */
    else
	while (i != '\n') {
	    if (i == '\033') {
		scbr();
		lprcat(" aborted");
		return(0);
	    }
	    if ((i <= '9') && (i >= '0') && (amt < 999999999))
		amt = amt * 10 + i - '0';
	    i = readchar();
	}
    scbr();
    return(amt);
}


#ifdef TIMECHECK
/*
 *	routine to check the time of day and return 1 if its during work hours
 *	checks the file ".holidays" for forms like "mmm dd comment..."
 */
int playable()
{
    long g_time,time();
    int hour,day,year;
    char *date,*month,*p;

    time(&g_time);		/* get the time and date */
    date = ctime(&g_time);	/* format: Fri Jul  4 00:27:56 EDT 1986 */
    year = atoi(date + 20);
    hour = (date[11] - '0') * 10 + date[12] - '0';
    day = (date[8] != ' ') ?((date[8] - '0') * 10 + date[9] - '0') :(date[9] - '0');
    month = date + 4;
    date[7] = 0;		/* point to and NULL terminate month */

    if (((hour >= 8 && hour < 17))/* 8AM - 5PM */
	&& strncmp("Sat", date, 3) != 0		/* not a Saturday */
	&& strncmp("Sun", date, 3) != 0) {	/* not a Sunday */
	/* now check for a .holidays datafile */
	lflush();
	if (lopen(holifile) >= 0)
	    for (;;) {
		if ((p = lgetw()) == 0)
		    break;
		if (strlen(p) < 6)
		    continue;
		if ((strncmp(p, month, 3) == 0) &&(day == atoi(p + 4)) &&(year == atoi(p + 7)))
		    return(0);/* a holiday */
	    }
	lrclose();
	lcreat((char *) 0);
	return(1);
    }
    return(0);
}
#endif TIMECHECK
SHAR_EOF
if test 28359 -ne "`wc -c < 'larn.c'`"
then
	echo shar: error transmitting "'larn.c'" '(should have been 28359 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'larn12.ftn'" '(1324 characters)'
if test -f 'larn12.ftn'
then
	echo shar: will not over-write existing file "'larn12.ftn'"
else
cat << \SHAR_EOF > 'larn12.ftn'
gem value = gem * 2 ^ perfection
sitting down can have unexpected results
don't pry into the affairs of others
drinking can be hazardous to your health
beware of the gusher!
some monsters are greedy
nymphs have light fingers
try kissing a disenchantress!
hammers and brains don't mix
what does a potion of cure dianthroritis taste like?
hit point gain/loss when raising a level depends on constitution
healing a mighty wizard can be exhilarating
be sure to pay your taxes
are Vampires afraid of something?
some dragons can fly
dos thou strive for perfection?
patience is a virtue, unless your daughter dies
what does the Eye of Larn see in its guardian?
a level 25 player casts like crazy!
energy rings affect spell regeneration
difficulty affects regeneration
control of the pesty spirits is most helpful
don't fall into a bottomless pit
dexterity allows you to carry more
you can get 2 points of WC for the price of one
never enter the dungeon naked!  the monsters will laugh at you!
did someone put itching powder in your armor?
you klutz!
avoid opening doors.  you never know whats on the other side.
infinite regeneration ---> temptation
the greatest weapon in the game has not the highest Weapon Class
you can't buy the most powerful scroll
identify things before you use them
there's more than one way through a wall
SHAR_EOF
if test 1324 -ne "`wc -c < 'larn12.ftn'`"
then
	echo shar: error transmitting "'larn12.ftn'" '(should have been 1324 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'larn12.hdy'" '(2304 characters)'
if test -f 'larn12.hdy'
then
	echo shar: will not over-write existing file "'larn12.hdy'"
else
cat << \SHAR_EOF > 'larn12.hdy'
"Jan 01 1986 New Years Day.  Any comment goes here.  Dont forget 01 not 1"
"Feb 17 1986 Washingtons Birthday (Presidents Day)"
"May 26 1986 Memorial Day"
"Jul 04 1986 Independence Day"
"Sep 01 1986 Labor Day"
"Oct 13 1986 Columbus Day"
"Nov 27 1986 Thanksgiving"
"Dec 25 1986 Christmas"

"Jan 01 1987 New Years Day.  Any comment goes here.  Dont forget 01 not 1"
"Feb 16 1987 Washingtons Birthday (Presidents Day)"
"May 25 1987 Memorial Day"
"Jul 04 1987 Independence Day"
"Sep 07 1987 Labor Day"
"Oct 12 1987 Columbus Day"
"Nov 26 1987 Thanksgiving"
"Dec 25 1987 Christmas"

"Jan 01 1988 New Years Day.  Any comment goes here.  Dont forget 01 not 1"
"Feb 15 1988 Washingtons Birthday (Presidents Day)"
"May 30 1988 Memorial Day"
"Jul 04 1988 Independence Day"
"Sep 05 1988 Labor Day"
"Oct 10 1988 Columbus Day"
"Nov 24 1988 Thanksgiving"
"Dec 25 1988 Christmas"

"Jan 01 1989 New Years Day.  Any comment goes here.  Dont forget 01 not 1"
"Feb 13 1989 Washingtons Birthday (Presidents Day)"
"May 28 1989 Memorial Day"
"Jul 04 1989 Independence Day"
"Sep 03 1989 Labor Day"
"Oct 15 1989 Columbus Day"
"Nov 29 1989 Thanksgiving"
"Dec 25 1989 Christmas"

"Jan 01 1990 New Years Day.  Any comment goes here.  Dont forget 01 not 1"
"Feb 12 1990 Washingtons Birthday (Presidents Day)"
"May 27 1990 Memorial Day"
"Jul 04 1990 Independence Day"
"Sep 02 1990 Labor Day"
"Oct 14 1990 Columbus Day"
"Nov 28 1990 Thanksgiving"
"Dec 25 1990 Christmas"

"Jan 01 1991 New Years Day.  Any comment goes here.  Dont forget 01 not 1"
"Feb 11 1991 Washingtons Birthday (Presidents Day)"
"May 26 1991 Memorial Day"
"Jul 04 1991 Independence Day"
"Sep 01 1991 Labor Day"
"Oct 10 1991 Columbus Day"
"Nov 27 1991 Thanksgiving"
"Dec 25 1991 Christmas"

"Jan 01 1992 New Years Day.  Any comment goes here.  Dont forget 01 not 1"
"Feb 10 1992 Washingtons Birthday (Presidents Day)"
"May 25 1992 Memorial Day"
"Jul 04 1992 Independence Day"
"Sep 07 1992 Labor Day"
"Oct 12 1992 Columbus Day"
"Nov 26 1992 Thanksgiving"
"Dec 25 1992 Christmas"

"Jan 01 1993 New Years Day.  Any comment goes here.  Dont forget 01 not 1"
"Feb 15 1993 Washingtons Birthday (Presidents Day)"
"May 30 1993 Memorial Day"
"Jul 04 1993 Independence Day"
"Sep 05 1993 Labor Day"
"Oct 10 1993 Columbus Day"
"Nov 24 1993 Thanksgiving"
"Dec 25 1993 Christmas"

SHAR_EOF
if test 2304 -ne "`wc -c < 'larn12.hdy'`"
then
	echo shar: error transmitting "'larn12.hdy'" '(should have been 2304 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)

Hello all!  This is a port of Larn v12.0 to VAX/VMS.  Now everyone can save
his/her daughter!!  Just unpack using /bin/sh and read readme.txt.

                                                - Mark Nagel

P.S.  Thanks to Lord Kahless for letting me post this!



-------------------------------cut here-------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	larn12.hlp
#	larn12.maz
#	larn12.opt
#	make.com
#	moreobj.c
#	movem.c
#	nap.c
#	readme.txt
# This archive created: Sat Aug 30 14:51:08 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'larn12.hlp'" '(6275 characters)'
if test -f 'larn12.hlp'
then
	echo shar: will not over-write existing file "'larn12.hlp'"
else
cat << \SHAR_EOF > 'larn12.hlp'
5    Welcome to the game of Larn.  At this moment, you face a great problem.
Your daughter has contracted a strange disease, and none of your home remedies
seem to have any effect.  You sense that she is in mortal danger, and you must
try to save her.  Time ago you heard of a land of great danger and opportunity.
Perhaps here is the solution you need.

    It has been said that there once was a great magician who called himself
Polinneaus.  Many years ago, after having many miraculous successes, Polinneaus
retired to the caverns of Larn, where he devoted most of his time to the
creation of magic.   Rumors have it that one day Polinneaus set out to dispel
an attacking army in a forest some distance to the north.  It is believed that
here he met his demise.

    The caverns of Larn, it is thought, must be magnificent in design,
and contain much magic and treasure.  One option you have is to undertake a
journey into these caverns.


    Good Luck!  You're going to need it!




		    [4mHelp File for The Caverns of Larn[m

h  move to the left	   H  run left			.  stay here
j  move down		   J  run down			Z  teleport yourself
k  move up		   K  run up			c  cast a spell
l  move to the right	   L  run right			r  read a scroll
y  move northwest	   Y  run northwest		q  quaff a potion
u  move northeast	   U  run northeast		W  wear armor
b  move southwest	   B  run southwest		T  take off armor
n  move southeast	   N  run southeast		w  wield a weapon
^  identify a trap	   g  give present pack weight	P  give tax status
d  drop an item	           i  inventory your pockets	Q  quit the game
v  print program version   S  save the game		D  list all items found
?  this help screen	   A  create diagnostic file    e  eat something
				(wizards only)
larn ++   restore checkpointed game
larn -s   list the scoreboard
larn -i   list scores with inventories
larn -n   suppress welcome message when beginning a game
larn -h   print out all the command line options
larn -<number>      specify difficulty of the game (may be used with -n)
larn -o<optsfile>   specify the .larnopts file to be used
larn -c           create new scoreboards -- prompts for a password
			    [7mSpecial Notes[m

When [7mdropping gold[m, if you type '*' as your amount, all your gold gets dropped.
In general, typing in '*' means all of what your interested in.  This is true
when visiting the bank, or when contributing at altars.

Larn may need a [7mVT100[m to operate.  A check is made of the environment variable
[7m"TERM"[m and it must be equal to [7m"vt100"[m.  This only applies if 
the game has been compiled with "VT100" defined in the Makefile.  If compiled
to use [7mtermcap[m, there are no terminal restrictions, save needing cm, ce, & cl
termcap entries.

When in the store, trading post, school, or home, an [7m<escape>[m will get you out.

larn -l           print out the larn log file 

When casting a spell, if you need a list of spells you can cast, type '[7mD[m' as
the first letter of your spell.  The available list of spells will be shown,
after which you may enter the spell code.  This only works on the 1st letter
of the spell you are casting.

The Author of Larn is Noah Morgan (1982-3), Copying for Profit is Prohibited
Copyright 1986 by Noah Morgan, All Rights Reserved.
			[7mBackground Information for Larn[m

    Welcome to the game of Larn.  At this moment, you face a great problem.
Your daughter has contracted a strange disease, and none of your home remedies
seem to have any effect.  You sense that she is in mortal danger, and you must
try to save her.  Time ago you heard of a land of great danger and opportunity.
Perhaps here is the solution you need.

    It has been said that there once was a great magician who called himself
Polinneaus.  Many years ago, after having many miraculous successes, Polinneaus
retired to the caverns of Larn, where he devoted most of his time to the
creation of magic.   Rumors have it that one day Polinneaus set out to dispel
an attacking army in a forest some distance to the north.  It is believed that
here he met his demise.

    The caverns of Larn, it is thought, must be magnificent in design,
and contain much magic and treasure.  One option you have is to undertake a
journey into these caverns.

    Good Luck!  You're going to need it!



		    [7mHow to use the .larnopts option file[m

The file ".larnopts", if used, should be in your home directory (see -o).
A sequence of words terminated by whitespace is used to specify options.

	Word                     Meaning

    bold-objects		  select bold display of objects
    inverse-objects		  select inverse video display of objects
    no-introduction		  do not display intro message
    enable-checkpointing          turn on periodic checkpointing
    no-beep			  disable beeping of the terminal
    male			  choose your sex to be a man
    female			  choose your sex to be a woman
    name: "your name"		  choose your playing name
    monster: "monst name"	  choose a name for a monster
    savefile: "save-file-name"    define what the savegame filename will be

Your name and monster names must be enclosed in double quotation marks and may
be up to 34 characters long.  Longer names are truncated.  Anything enclosed in
quotation marks is considered one word, and must be separated from other words
by whitespace.

	       [7mExplanation of the Larn scoreboard facility[m

    Larn supports TWO scoreboards, one for winners, and one for deceased
characters.  Each player (by userid or playerid, see UIDSCORE in Makefile)
is allowed one slot on each scoreboard, if the score is in the top ten for
that scoreboard.  This design helps insure that frequent players of Larn
do not hog the scoreboard, and gives more players a chance for glory.  Level
of difficulty is also noted on the scoreboards, and this takes precedence
over score for determining what entry is on the scoreboard.  For example:
if "Yar, the Bug Slayer" has a score of 128003 on the scoreboard at diff 0,
then his game at diff 1 and a score of 4112 would replace his previous
entry on the scoreboard.  Note that when a player dies, his inventory is
stored in the scoreboard so that everyone can see what items the player had
at the time of his death.











SHAR_EOF
echo shar: 24 control characters may be missing from "'larn12.hlp'"
if test 6275 -ne "`wc -c < 'larn12.hlp'`"
then
	echo shar: error transmitting "'larn12.hlp'" '(should have been 6275 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'larn12.maz'" '(18513 characters)'
if test -f 'larn12.maz'
then
	echo shar: will not over-write existing file "'larn12.maz'"
else
cat << \SHAR_EOF > 'larn12.maz'
@###################################################################
#           #  .        #                 #     #     #     #   . #
#           D           D  .                       .        D .   #
###D##########################################  #     #     ###D###
#          -#                 #.    #      # ################ .  .#
#     ####### ######## ############ D #### #                #     #
# ... #.#   # #  # . # #            # #### # ############ # ###D###
#     #.# # # ## #   # # ############ #### # #-  #      # # #.    #
#  .  # # # # ## #-  # # #    -     D #### # # . D    # #.# # ... #
#     # #.# #    #   # # #   . .    # #    # #   #    # #-# # ~.! #
###D### ### #######D## # ############ ###### ########## ### #######
#                    #  @          .#        #     .....       ...#
###D###########################################################D###
#  .  #.....#     #     #     #    -#     #     #     #     #     #
#      .....    .       D           D                 D     D.    #
#     #.....#     #     #     #     #     #    .#     #     #     #
###################################################################

###################################################################
#.. .                   D  #                .  #              #-  #
############# ######### # ## ### ##### ## #### ###### ####### ### #
#.#!#~# #   #       .-# # #-   #    #   # # -# #      #           #
# # #.#  .  #   ####### # #    #    #   # #  # #      #       #####
# # ..# #####   #     # # #### #    ## ## ## # ###### ####### #   #
# - ..D #   D   #   . D # #  # #.##### ## ## # #. #.# #..#  # ### #
####### ####### ###   # # #    # #      # D  # D  D   #..D  #     #
#-                #   # # #### # ###### # ## # #. #   #..#    #####
### #######################- # # #    ######################  #   #
#   ...       #   .       #..# ###    #   - ..  .          #. ### #
#             #           #  # ###    #################### #  #   #
#                              ###                                #
################################################################# #
#-                        D    ###    #          #            #   #
#  .                      #            #                   #  D   #
###################################################################

###################################################################
#  ..                                                             #
# ############## ############################################## # #
#         #    # #                                #     ..    # # #
#         #D## # # ############D################# ########### # # #
######### #- # # # #-    D    # # ~  #          # #         # # # #
#       # #  # # # #   ### #  # #    D   -      # # ####### # # # #
#  .... # #### # # #   #!# #  # ######      ..  #.# #     # # # # #
#  .... #      # # # ### # #  # #    #########D#### # ### # # # # #
#  .... ######## # # D   # #- # #..  #       ...#.# # #.# # # # # #
#       #        # ###   # #### #.-  D   -      #.# #.#.# # # # # #
#####DD## ######## #     #    D D.   #          # # #...# # # # # #
# #   ..# #    # # ############################## # ##### # # # # #
# ......# #  #   #                                #       # # # # #
# ####### ###### ################################ ######### # ### #
#               .D.                                         #     #
###################################################################

###################################################################
#                  ##        ##            ###                ##  #
#  #####            ## ..-  ##            ##.##              ##   #
#  # ! ##            ## .  ##            ##  .##    ..      ##    #
#  #....######        ##  ##            ##  .  ##          ##     #
#  # -  #    ##        ##D#            ##  .    ##        ##      #
#  #####D  ~  ####### ###........     ## ...     ##      ##       #
#  #    #     ##        ##   ....    ##  .        ##    ##        #
#  #.   ########         ##         ##   .     -  ####D####   -   #
#  #.-  #...## ##   ...   ##        ###  ......  ##       ##      #
#  #.   #..##   ##         #########  ##    ... ##   ###   ## ..  #
#  #..  #.##     ## ## -  ##  .  ####  ##      ##   #####   ##    #
#  #####D##          ##  ##     ######  ##    ##   #######   ##   #
#  D  -.##            ####     ########  ##DD##    ########   #D  #
#  ######   ...        ##     ##########                       ## #
####                                                 .     .    ###
###################################################################

###################################################################
#                                                                 #
#     ####.########################################## ## ##########
#     #      #.#.#.#                   #.. #.   #           #     #
#######    # # # # #       #####       #!  #    ########### # ### #
#     #    # # # # #      ##...##      #   #    #         # # #-# #
# ..- D    # # # # #     ## .   ##     ####D#####  .. ### #   # # #
#     #    #       #    ##.   ~ .##    #   #    ###   # # ##### # #
############ # # # #   ##  . .   .##   #...# .. #.#   # #       # #
#  ..     .# # # # #   ##     -   ##   #   #    D.D   # ######### #
#      .   D # # # #    ##.......##    ####D#####.#   #           #
#   - .    # # # # #     ##     ##     # . #    ###   ########### #
############ #.#.# #      ###D###      # . #....#               # #
#            # #-# D               ..  #  .#    ###....##  ##-### #
####   ########################################## ######    ###   #
#         .                                                       #
###################################################################

###################################################################
#                                                                 #
#                        ###########################D#######  ##  #
#  #######################                    # ##...... ##   ##  #
#                        ########D######  #   # !##.... ##    ##  #
#   ############    ##  ##    ...      #  #   #...## ~ ## ######  #
#   #          #    #    # ......      #  #   # .. #####      ##  #
#   #    - ..  #    #    #   ###########  #   #  .  ######### ##  #
#   #####  #####    #    #   #            #   #...   ##       ##  #
#       #  #        ##########  ########  ########DD#### #######  #
#       #  #  ....  #        #  #             #     #  ##     ##  #
#   #####  #        #    ....#  #  #########  #     #   ##### ##  #
#   #-    ######D##########..#  #  #########  #  -  #..  ##   ##  #
#   #####  #                 #  #             #...  #.....##      #
#       #  ###################  ###############...  ####   # ######
#       #                                                         #
###################################################################

###################################################################
#                                                                 #
########### #####      #####     #####D####    #####       ###### #
#..       # #-..D ######   ##    # ##     #   ## ..##    ### #### #
#  #### ### ##### #         ##   #  ##### #  ## ### ##   #   #    #
#  #  # #       # # ##### #  ##  #      # ####  # #..##### - ###  #
#  #  # ####### ### #...# #   ########  #       # #~.   ....   #  #
#  #  #       #     #...# #          #  ######### ##############  #
#  #  ######  #######   # ###   ###  #       ..                #  #
#  #       #          - # #-#####!#  # #      ####  ## ####    #  #
#  ######  #   ########## #.. ....#  # ########  #  #  #  ##   ## #
#     -.#  #####          ####...##  #    .  .#  #..#  #   ##   # #
#    ####        ######      #.###   #####.####  ####  ###  ##  # #
#    #-    #######....####   ......      #.#       .     #   ## # #
#    #######             ##### ###########.###############    ### #
#                                         .                       #
###################################################################

###################################################################
#   #     #-   .      #   # # # # # #   #                         #
# # #     #####.##### # # # # # # # # # # ###########D########### #
# # #####     # # ### # # # # # # # # # ###     #....    #  #   # #
# #     #     #       # # # # # # # # # #       #.!. -.. #.##.# # #
# # . - #     # ####### # # # # # # # # #       ########## ## #   #
#.#######     #         #       D     #        .              # # #
#.     -#     ################################################### #
#   #####     D.                                             .    #
#  #         ###  ###D### ### ### ###D### ### ### ###D### ###.### #
#  # ######  ### .#    .# #.    # #     # #     # #     # # .   # #
#  ### # -#  ### .#. - .# #     # #...- # # ..  # #  -..# # .   # #
#      #  #  ###  #. ~ .# #     # #     # #     # # .. .# #     # #
#.######  #  ###  #     # #.....# #     # #     # #     # #     # #
# #      #######  ####### ####### ####### ####### ####### ####### #
# # ...                                       ..                  #
###################################################################

###################################################################
#           #  .        #     ###         #     #     #     #   . #
#           D           D  .        #              .        D .   #
############################################### #     #     ###D###
#          -#                 #.    #      # ################ .  .#
#     #######D######## ############ # #### #                #     #
# ... #.    # #!~  . # #            # #--# # ############ #####D###
#     #.# # # ## #   # # ############ #--# # #-  #      # # #.    #
#  .  # #-# # ## #-  # # #    -     D ## # # # . D #### #.# # ... #
#     # #-# #    #   # # #   . .    # #    # #   #    # #-# # -.- #
###D### ### ####### ## # ############ ###### ########## ### ###D###
#                    #  @          .               .....       ...#
#####################################           ###############D###
#  .  #.....#     #     #     #    -#           #     #     #     #
#      .....    .       D           D                 D     D.    #
#     #.....#     #     #     #     #          .#     #     #     #
###################################################################

###################################################################
#.. .       #           D                   .                 #-  #
### ######### ######### # ## ### ##### ## ########### ####### ### #
#.# #   #   #       .-# # #-   #    #   # # -# #      #           #
# # #.#  .  #   ####### # #    #    #   # #  # #      #       #####
# # ..#######   #     # # #### #    ## ## ##!# ###### ####### #   #
# - ..D #   D   #   . D # #  # #.##### ## ## # #. #.# #..#  # ### #
####### ####### ###   # # #    # #      # D  # D  D   #..D  #     #
#-                #   # # #### # ###### # ## # #. #   #..#    #####
### #######################- # # #    ######################  #   #
#   ...       #   .       #..# ###    #   - ..  .          #. ### #
#             #           #  # #-#    #################### #  #   #
#                         #     -#                                #
################################-################################ #
#-.....             # ####D    ###    #          #            #   #
#~.....              #    #            #                   #  D   #
###################################################################

###################################################################
#  ..                                                             #
# ############## ############################################## # #
#         #    # #                                #     ..    # # #
#         #D## # # ############D################# ########### # # #
######### #- # # # #-    D    # #.!..#          # #         # # # #
#   #   # #  # # # #   ### ## # #....D   -      # # ####### # # # #
#  .... # #### # # #   #~# #  # ######      ..  #.# #     # # # # #
###....##      # # # ###.# #  #      #########D## # # ### # # # # #
#  .... ######## # # D  .# #- #  ..  #       ...#.# # #.# # # # # #
#   #  ##        # ###  .# ####  .-  D   -      #.# #.#.# # # # # #
#####DD## ######## #... .#       .   #          # # #.#.  # # # # #
# #   ..# #      # ############################## # # ##### # # # #
# ......# #  # # #                                # #       # # # #
# ####### ###### ################################D# ######### ### #
#               .D.                                           #-.-#
###################################################################

###################################################################
#                  ##        ##         ##        ##          ##  #
#  ##############   ## ..-  ##          ##  .     ##         ##   #
#  #    #       ##   ## .  ##           ##   .    ##..      ##    #
#  #....######   ##   ##  ######## #######  .     ##       ##     #
#  # -  #    ##   ##   ##D#            ##  .      ##      ##      #
#  #          D###### ###........     ## ...      ##     ######   #
#  #    #     ##        ##   ....    ##  .        ##    ##  - #   #
#  #.   ########         ##         ##   .     -  ####D####.. D   #
#  #.-  #...## ##   ...   ##        ###  ......  ##       #####   #
#  #.   #..##   ##         #########  ##    ... ##   ###   ## ..  #
#  #..  #.##     ## ## -  ##  .  ####  ##      ##   #####   ##    #
#  #####D#######  #  ##  ##     ##..##  ##    ##   ##   ##   ##   #
#  D  -.##     #  #   ####     ##.-.-##  ##DD##    ### ####   ##  #
#  ######.  ...# ####  ##     #### #####                ##     ##D#
####~!....     D                                     .     .      #
###################################################################

###################################################################
#                                                                 #
#     ####.########################################## ## ##########
#     #      #.#.#.#                   #..  .   #           #     #
#######    # # # # #   #############   #        ########### # ### #
#     #    # # # # #    --##...##--    #        #         # # #-# #
# ..- D    # # # # #   #-## .   ##-#   ####D#####  .. ### #   # # #
#     #    #       #   ###.     .###   # ~ #    ###   ### ##### # #
############ # # # #   ##  . .   .##   #...# .. #.#             # #
#  ..     .# # # # #   ##     -   ##   #   #    D.    # ######### #
#      .   D # # # #   ###.......###   ####D#####.#   #           #
#   - .    # # # # #    -##     ##-    # .      ###   ########### #
############ #.#.# #   ######D######   # .  ....#               # #
#            #!#-# #               ..  #  .     ###....##  ##-### #
####   ##############################  ########## ######    ###   #
#  D      .                                                       #
###################################################################

###################################################################
#                                                                 #
#                        ###############D####################D#   #
#  #######################                    # ##......      #   #
#                        ########D######  #   #  ##....       #   #
#   ############### ##  ##    ...      #  #   #...##      #####   #
#   #    ~        # #    #!......      #  #   # .. #####      #   #
#   #    - ..     # #    #   ###########  #   #  .  ######### #   #
#   #####  ######## #    #   #         #  #   #...   ##       #   #
#       #  #      # ##########  ########  ########D #### ######   #
#       #  #  ....# #        #  #             #     #  ##     #   #
#   #####  # ###### #    ....#  #  #########  #     #   #####D#   #
#   #-    ## #      #######..#  #  #########  #  -  #..           #
#   #####  #                 #  #             #...  #.....        #
#       #  ###################  ###############...  ####     ######
#       #                                                         #
###################################################################

###################################################################
#                      #                                          #
########### #####      #         #####D####    #####       ###### #
#..       # #~..D ######   ##    # ##     #   ## ..##    ### #### #
#  #### ### ##### #         ##   #  ##### #  ## ### ##   #   #    #
#  #  # #       # # ##### #  ##  #      # ####  # #..##### - ###  #
#  #  # ####### ### #...# #   ########  #       # #!.   ....   #  #
#  #  #       #     #...# #          #  ######### ##############  #
#  #  ######  #######   # ###   ###  #       ..                #  #
#  #       #          - # #-    # #  #        ######## ####    #  #
#  #       #   ########## #.. ....#  # ########        #  ##   ## #
#  #  -.   #####          ####...##  #    .  .#   ..   #        # #
#  #             ######      #####   #####.####        #######  # #
#  #  -    #######....####   ......      #.#       .     #   ## # #
#  #########             ##### ###########.###############    ### #
#                                         .                       #
###################################################################

###################################################################
# D D     #-..........#     #   #   #   #                         #
#D#D#     #####.#####.# #   #   #   # # #############D########### #
# # #####     #.#~###.# #   #   #   # # ###      ....    #  #   # #
#D#     #     #.......# #   #   #   # # #        . . -.. #. #.# # #
# # . - #     #.####### #   #   #   # # ##################    #   #
#D#######     #.        #       D     #        .              # # #
#. D D -#     ################################################### #
#  ######      .                                             .    #
#  #    D    ###  ###D### ####### ###D### ####### ###D### ####### #
#  # ######  # # .#    .# #.    # #     # #     # #     # # .   # #
#  ###   -#  # # .#. - .# #     # #...- # # ..  # #  -..# # .   # #
#DD#      #  # #  #.   .# #     # #     # #     # # .. .# #     # #
#.######  #    #  #     # #.....# #     # #     # # !   # #     # #
# #      #######  ####### ### ### ####### ### ### ####### ### ### #
# # ...                                       ..                  #
###################################################################

SHAR_EOF
if test 18513 -ne "`wc -c < 'larn12.maz'`"
then
	echo shar: error transmitting "'larn12.maz'" '(should have been 18513 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'larn12.opt'" '(253 characters)'
if test -f 'larn12.opt'
then
	echo shar: will not over-write existing file "'larn12.opt'"
else
cat << \SHAR_EOF > 'larn12.opt'
process-name: "Winnie-the-Pooh"
enable-checkpointing
bold-objects
male
play-day-play
no-introduction
name: "King of the Realm"
monster: "abominable snowman"
monster: "tooth fairy"
monster: "Yaccerous Lexicous"
savefile: "/save/noah/games/Larn12.0.sav"

SHAR_EOF
if test 253 -ne "`wc -c < 'larn12.opt'`"
then
	echo shar: error transmitting "'larn12.opt'" '(should have been 253 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'make.com'" '(5478 characters)'
if test -f 'make.com'
then
	echo shar: will not over-write existing file "'make.com'"
else
cat << \SHAR_EOF > 'make.com'
$
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$! Available compile time options:
$!    WIZID=xxx  - this is the userid (or playerid) of the wizard.  Default is
$!		  zero (superuser), which disables all wizard functions.
$!		  Players must have this userid (or playerid) in order to
$!		  become the non-scoring wizard player.  Definition of WIZID
$!		  to non-zero will enable the special wizard debugging
$!		  commands.  For root to become wizard, use WIZID= -1.
$!    EXTRA      - incorporates code to gather additional performance statistics
$!    TIMECHECK  - incorporates code to disable play during working hours (8-5)
$!    SAVEINHOME - put save files in users HOME instead of LARNHOME the as default
$!    VER        - This is the version of the software, example:  12
$!    SUBVER     - This is the revision of the software, example:  1
$!    MACRORND
$!		- Define to use macro version of rnd() and rund() (fast & big)
$!    UIDSCORE
$!		- Define to use user id's to manage scoreboard.  Leaving this
$!		  out will cause player id's from the file "LARN12.IDS" to be
$!		  used instead.  (LARN12.IDS is created upon demand).  Only one
$!		  entry per id # is allowed in each scoreboard (winning &
$!		  non-winning).
$!    VT100	- Compile for using vt100 family of terminals.  Omission of this
$!		  define will cause larn to use termcap, but it will be MUCH
$!		  slower due to an extra layer of output interpretation. 
$!		  Also, only VT100 mode allows 2 different standout modes,
$!		  inverse video, and bold video.  And only in VT100 mode is
$!		  the scrolling region of the terminal used (much nicer than
$!		  insert/delete line sequences to simulate it, if VT100 is
$!		  omitted).
$!    NONAP	- This causes napms() to return immediately instead of delaying
$!		  n milliseconds.  This define may be needed on some systems
$!		  if the nap stuff does not work correctly (possible hang).
$!		  nap() is primarilly used to delay for effect when casting
$!		  missile type spells.
$!
$! End of configurable make options
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$!
$!
$!	 WIZID = (0101<<16) | 02     ([101,2])
$!
$
$! You must define LARNHOME in LARN.C before executing this command file.
$
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$	DEF = " /DEF=(SAVEINHOME,WIZZARD,WIZID=4259842,EXTRA,VT100,VER=12,SUBVER=0,MACRORND)"
$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$
$	SET DEFAULT [MARK.SRC.GAMES.LARN.TMP]	! change to suit your needs
$
$!--------------------------------------------
$! Make command file for VMS Larn version 12.0
$!--------------------------------------------
$
$	ON ERROR THEN GOTO ERROR_HANDLER
$!
$! If we are making a debug version, define options appropriately.
$!
$	C_OPTS = "/NOLIST /NOOPT"
$	L_OPTS = "/NOMAP"
$	IF P1 .NES. "DEBUG" THEN GOTO NO_DEBUG
$	C_OPTS = C_OPTS + " /DEBUG"
$	L_OPTS = L_OPTS + " /DEBUG"
$ NO_DEBUG:
$	C_OPTS = C_OPTS + "'DEF'"
$!
$! Define the module library
$!
$	LIB = "LARNLIB.OLB"
$
$	IF F$SEARCH("''LIB'") .EQS. "" THEN -
	    LIBRARY/CREATE 'LIB'/OBJ		! CREATE THE LIBRARY IF IT DOESN'T EXIST
$!
$! Main module doesn't go in the library
$!
$	CC 'C_OPTS' LARN
$	

$!
$! Everything else does
$!
$	CC 'C_OPTS' BILL
$	LIBRARY 'LIB'/OBJ BILL
$	DELETE BILL.OBJ;
$	CC 'C_OPTS' CREATE
$	LIBRARY 'LIB'/OBJ CREATE
$	DELETE CREATE.OBJ;
$       CC 'C_OPTS' DATA
$	LIBRARY 'LIB'/OBJ DATA
$	DELETE DATA.OBJ;
$	CC 'C_OPTS' DIAG
$	LIBRARY 'LIB'/OBJ DIAG
$	DELETE DIAG.OBJ;
$	CC 'C_OPTS' DISPLAY
$	LIBRARY 'LIB'/OBJ DISPLAY
$	DELETE DISPLAY.OBJ;
$	CC 'C_OPTS' FORTUNE
$	LIBRARY 'LIB'/OBJ FORTUNE
$	DELETE FORTUNE.OBJ;
$	CC 'C_OPTS' GLOBAL
$	LIBRARY 'LIB'/OBJ GLOBAL
$	DELETE GLOBAL.OBJ;
$	CC 'C_OPTS' HELP
$	LIBRARY 'LIB'/OBJ HELP
$	DELETE HELP.OBJ;
$	CC 'C_OPTS' IO
$	LIBRARY 'LIB'/OBJ IO
$	DELETE IO.OBJ;
$	CC 'C_OPTS' KEYSENSE
$	LIBRARY 'LIB'/OBJ KEYSENSE
$	DELETE KEYSENSE.OBJ;
$	CC 'C_OPTS' MONSTER
$	LIBRARY 'LIB'/OBJ MONSTER
$	DELETE MONSTER.OBJ;
$	CC 'C_OPTS' MOREOBJ
$	LIBRARY 'LIB'/OBJ MOREOBJ
$	DELETE MOREOBJ.OBJ;
$	CC 'C_OPTS' MOVEM
$	LIBRARY 'LIB'/OBJ MOVEM
$	DELETE MOVEM.OBJ;
$	CC 'C_OPTS' NAP
$	LIBRARY 'LIB'/OBJ NAP
$	DELETE NAP.OBJ;
$	CC 'C_OPTS' OBJECT
$	LIBRARY 'LIB'/OBJ OBJECT
$	DELETE OBJECT.OBJ;
$	CC 'C_OPTS' REGEN
$	LIBRARY 'LIB'/OBJ REGEN
$	DELETE REGEN.OBJ;
$	CC 'C_OPTS' SAVELEV
$	LIBRARY 'LIB'/OBJ SAVELEV
$	DELETE SAVELEV.OBJ;
$	CC 'C_OPTS' SCORES
$	LIBRARY 'LIB'/OBJ SCORES
$	DELETE SCORES.OBJ;
$	CC 'C_OPTS' SIGNAL
$	LIBRARY 'LIB'/OBJ SIGNAL
$	DELETE SIGNAL.OBJ;
$	CC 'C_OPTS' STORE
$	LIBRARY 'LIB'/OBJ STORE
$	DELETE STORE.OBJ;
$	CC 'C_OPTS' TOK
$	LIBRARY 'LIB'/OBJ TOK
$	DELETE TOK.OBJ;
$!
$! now link 'em up
$!
$	LINK 'L_OPTS' LARN,'LIB'/LIB,SYS$LIBRARY:VAXCRTL/LIB
$
$	EXIT
$
$ ERROR_HANDLER:
$	WRITE SYS$OUTPUT "Fatal error has occurred.  See ya!"

SHAR_EOF
echo shar: a missing newline was added to "'make.com'"
echo shar: 485 control characters may be missing from "'make.com'"
if test 5478 -ne "`wc -c < 'make.com'`"
then
	echo shar: error transmitting "'make.com'" '(should have been 5478 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'moreobj.c'" '(9411 characters)'
if test -f 'moreobj.c'
then
	echo shar: will not over-write existing file "'moreobj.c'"
else
cat << \SHAR_EOF > 'moreobj.c'

/* moreobj.c 		Larn is copyrighted 1986 by Noah Morgan.
 *
 *	Routines in this file:
 *
 *	oaltar()
 *	othrone()
 *	ochest()
 *	ofountain()
 */
#include "header.h"

/*
 *	******
 *	OALTAR
 *	******
 *
 *	subroutine to process an altar object
 */
oaltar()
{
    unsigned long k;

    lprcat("\nDo you (p) pray or (d) desecrate");
    iopts();
    while (1) {
	while (1)
	    switch(readchar()) {
		case 'p': 
		    lprcat(" pray\nDo you (m) give money or (j) just pray? ");
		    while (1)
			switch(readchar()) {
			    case 'j': 
				if (rnd(100) < 75)
				    lprcat("\nnothing happens");
				else if (rnd(13) < 4)
				    ohear();
				else if (rnd(43) == 10) {
				    if (c[WEAR])
					lprcat("\nYou feel your armor vibrate for a moment");
				    enchantarmor();
				    return;
				} else if (rnd(43) == 10) {
				    if (c[WIELD])
					lprcat("\nYou feel your weapon vibrate for a moment");
				    enchweapon();
				    return;
				} else
				    createmonster(makemonst(level + 1));
				return;

			    case 'm': 
				lprcat("\n\n");
				cursor(1, 24);
				cltoeoln();
				cursor(1, 23);
				cltoeoln();
				lprcat("How much do you donate? ");
				k = readnum((long) c[GOLD]);
				if (c[GOLD] < k) {
				    lprcat("\nYou don't have that much!");
				    return;
				}
				c[GOLD] -= k;
				if (k < c[GOLD] / 10 || k < rnd(50)) {
				    createmonster(makemonst(level + 1));
				    c[AGGRAVATE] += 200;
				} else if (rnd(101) > 50) {
				    ohear();
				    return;
				} else
				    if (rnd(43) == 5) {
					if (c[WEAR])
					    lprcat("\nYou feel your armor vibrate for a moment");
					enchantarmor();
					return;
				} else if (rnd(43) == 8) {
				    if (c[WIELD])
					lprcat("\nYou feel your weapon vibrate for a moment");
				    enchweapon();
				    return;
				} else
				    lprcat("\nThank You.");
				bottomline();
				return;

			    case '\33': 
				return;
			};

		case 'd': 
		    lprcat(" desecrate");
		    if (rnd(100) < 60) {
			createmonster(makemonst(level + 2) + 8);
			c[AGGRAVATE] += 2500;
		    } else if (rnd(101) < 30) {
			lprcat("\nThe altar crumbles into a pile of dust before your eyes");
			forget();  /* remember to destroy the altar */
		    } else
			lprcat("\nnothing happens");
		    return;

		case 'i': 
		case '\33': 
		    ignore();
		    if (rnd(100) < 30) {
			createmonster(makemonst(level + 1));
			c[AGGRAVATE] += rnd(450);
		    } else
			lprcat("\nnothing happens");
		    return;
	    };
    }
}

/*
	function to cast a +3 protection on the player
 */
static ohear()
{
    lprcat("\nYou have been heard!");
    if (c[ALTPRO] == 0)
	c[MOREDEFENSES] += 3;
    c[ALTPRO] += 500;		/* protection field */
    bottomline();
}

/*
	*******
	OTHRONE
	*******

	subroutine to process a throne object
 */
othrone(arg)
int arg;
{
    register int i,k;

    lprcat("\nDo you (p) pry off jewels or (s) sit down");
    iopts();
    while (1) {
	while (1)
	    switch(readchar()) {
		case 'p': 
		    lprcat(" pry off");
		    k = rnd(101);
		    if (k < 25) {
			for (i = 0; i < rnd(4); i++)
			    creategem();/* gems pop off the throne */
			item[playerx][playery] = ODEADTHRONE;
			know[playerx][playery] = 0;
		    } else if (k < 40 && arg == 0) {
			createmonster(GNOMEKING);
			item[playerx][playery] = OTHRONE2;
			know[playerx][playery] = 0;
		    } else
			lprcat("\nnothing happens");
		    return;

		case 's': 
		    lprcat(" sit down");
		    k = rnd(101);
		    if (k < 30 && arg == 0) {
			createmonster(GNOMEKING);
			item[playerx][playery] = OTHRONE2;
			know[playerx][playery] = 0;
		    } else if (k < 35) {
			lprcat("\nZaaaappp!  You've been teleported!\n");
			beep();
			oteleport(0);
		    } else
			lprcat("\nnothing happens");
		    return;

		case 'i': 
		case '\33': 
		    ignore();
		    return;
	    };
    }
}

odeadthrone()
{
    register int k;

    lprcat("\nDo you (s) sit down");
    iopts();
    while (1) {
	while (1)
	    switch(readchar()) {
		case 's': 
		    lprcat(" sit down");
		    k = rnd(101);
		    if (k < 35) {
			lprcat("\nZaaaappp!  You've been teleported!\n");
			beep();
			oteleport(0);
		    } else
			lprcat("\nnothing happens");
		    return;

		case 'i': 
		case '\33': 
		    ignore();
		    return;
	    };
    }
}

/*
	******
	OCHEST
	******

	subroutine to process a throne object
 */
ochest()
{
    register int i,k;

    lprcat("\nDo you (t) take it or (o) try to open it");
    iopts();
    while (1) {
	while (1)
	    switch(readchar()) {
		case 'o': 
		    lprcat(" open it");
		    k = rnd(101);
		    if (k < 40) {
			lprcat("\nThe chest explodes as you open it");
			beep();
			i = rnd(10);
			lastnum = 281;/* in case he dies */
			lprintf("\nYou suffer %d hit points damage!",(long) i);
			checkloss(i);
			switch(rnd(10)) {/* see if he gets a curse */
			    case 1: 
				c[ITCHING] += rnd(1000) + 100;
				lprcat("\nYou feel an irritation spread over your skin!");
				beep();
				break;

			    case 2: 
				c[CLUMSINESS] += rnd(1600) + 200;
				lprcat("\nYou begin to lose hand to eye coordination!");
				beep();
				break;

			    case 3: 
				c[HALFDAM] += rnd(1600) + 200;
				beep();
				lprcat("\nA sickness engulfs you!");
				break;
			};
			item[playerx][playery] = know[playerx][playery] = 0;
			if (rnd(100) < 69)
			    creategem();/* gems from the chest */
			dropgold(rnd(110 * iarg[playerx][playery] + 200));
			for (i = 0; i < rnd(4); i++)
			    something(iarg[playerx][playery] + 2);
		    } else
			lprcat("\nnothing happens");
		    return;

		case 't': 
		    lprcat(" take");
		    if (take(OCHEST, iarg[playerx][playery]) == 0)
			item[playerx][playery] = know[playerx][playery] = 0;
		    return;

		case 'i': 
		case '\33': 
		    ignore();
		    return;
	    };
    }
}

/*
	*********
	OFOUNTAIN
	*********
 */

ofountain()
{
    register int x;

    cursors();
    lprcat("\nDo you (d) drink or (w) wash yourself");
    iopts();
    while (1)
	switch(readchar()) {
	    case 'd': 
		lprcat("drink");
		if (rnd(1501) < 2) {
		    lprcat("\nOops!  You seem to have caught the dreadful sleep!");
		    beep();
		    lflush();
		    sleep(3);
		    died(280);
		    return;
		}
		x = rnd(100);
		if (x < 7) {
		    c[HALFDAM] += 200 + rnd(200);
		    lprcat("\nYou feel a sickness coming on");
		} else if (x < 13)
		    quaffpotion(23);/* see invisible */
		else if (x < 45)
		    lprcat("\nnothing seems to have happened");
		else if (rnd(3) != 2)
		    fntchange(1);   /* change char levels upward */
		else
		    fntchange(-1);  /* change char levels downward */
		if (rnd(12) < 3) {
		    lprcat("\nThe fountains bubbling slowly quiets");
		    item[playerx][playery] = ODEADFOUNTAIN;/* dead fountain */
		    know[playerx][playery] = 0;
		}
		return;

	    case '\33': 
	    case 'i': 
		ignore();
		return;

	    case 'w': 
		lprcat("wash yourself");
		if (rnd(100) < 11) {
		    x = rnd((level << 2) + 2);
		    lprintf("\nOh no!  The water was foul!  You suffer %d hit points!",(long) x);
		    lastnum = 273;
		    losehp(x);
		    bottomline();
		    cursors();
		} else if (rnd(100) < 29)
		    lprcat("\nYou got the dirt off!");
		else if (rnd(100) < 31)
		    lprcat("\nThis water seems to be hard water!  The dirt didn't come off!");
		else if (rnd(100) < 34)
		    createmonster(WATERLORD);  /* make water lord */
		else
		    lprcat("\nnothing seems to have happened");
		return;
	}
}

/*
	a subroutine to raise or lower character levels
	if x > 0 they are raised   if x < 0 they are lowered
 */
fntchange(how)
int how;
{
    register long   j;
    lprc('\n');
    switch(rnd(9)) {
	case 1: 
	    lprcat("Your strength");
	    fch(how, &c[0]);
	    break;
	case 2: 
	    lprcat("Your intelligence");
	    fch(how, &c[1]);
	    break;
	case 3: 
	    lprcat("Your wisdom");
	    fch(how, &c[2]);
	    break;
	case 4: 
	    lprcat("Your constitution");
	    fch(how, &c[3]);
	    break;
	case 5: 
	    lprcat("Your dexterity");
	    fch(how, &c[4]);
	    break;
	case 6: 
	    lprcat("Your charm");
	    fch(how, &c[5]);
	    break;
	case 7: 
	    j = rnd(level + 1);
	    if (how < 0) {
		lprintf("You lose %d hit point",(long) j);
		if (j > 1)
		    lprcat("s!");
		else
		    lprc('!');
		losemhp((int) j);
	    } else {
		lprintf("You gain %d hit point",(long) j);
		if (j > 1)
		    lprcat("s!");
		else
		    lprc('!');
		raisemhp((int) j);
	    }
	    bottomline();
	    break;

	case 8: 
	    j = rnd(level + 1);
	    if (how > 0) {
		lprintf("You just gained %d spell",(long) j);
		raisemspells((int) j);
		if (j > 1)
		    lprcat("s!");
		else
		    lprc('!');
	    } else {
		lprintf("You just lost %d spell",(long) j);
		losemspells((int) j);
		if (j > 1)
		    lprcat("s!");
		else
		    lprc('!');
	    }
	    bottomline();
	    break;

	case 9: 
	    j = 5 * rnd((level + 1) *(level + 1));
	    if (how < 0) {
		lprintf("You just lost %d experience point",(long) j);
		if (j > 1)
		    lprcat("s!");
		else
		    lprc('!');
		loseexperience((long) j);
	    } else {
		lprintf("You just gained %d experience point",(long) j);
		if (j > 1)
		    lprcat("s!");
		else
		    lprc('!');
		raiseexperience((long) j);
	    }
	    break;
    }
    cursors();
}

/*
	***
	FCH
	***

	subroutine to process an up/down of a character attribute for ofountain
 */
static fch(how, x)
int how;
long *x;
{
    if (how < 0) {
	lprcat(" went down by one!");
	--(*x);
    } else {
	lprcat(" went up by one!");
	(*x)++;
    }
    bottomline();
}
SHAR_EOF
if test 9411 -ne "`wc -c < 'moreobj.c'`"
then
	echo shar: error transmitting "'moreobj.c'" '(should have been 9411 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'movem.c'" '(11581 characters)'
if test -f 'movem.c'
then
	echo shar: will not over-write existing file "'movem.c'"
else
cat << \SHAR_EOF > 'movem.c'
/*
 *	movem.c (move monster)		Larn is copyrighted 1986 by Noah Morgan.
 *
 *	Here are the functions in this file:
 *
 *	movemonst()		Routine to move the monsters toward the player
 *	movemt(x,y)		Function to move a monster at (x,y) -- must determine where
 *	mmove(x,y,xd,yd)	Function to actually perform the monster movement
 *	movsphere() 		Function to look for and move spheres of annihilation
 */
#include "header.h"

/*
 *	movemonst()		Routine to move the monsters toward the player
 *
 *	This routine has the responsibility to determine which monsters are to
 *	move, and call movemt() to do the move.
 *	Returns no value.
 */
static short    w1[9],
                w1x[9],
                w1y[9];
static int  tmp1,
            tmp2,
            tmp3,
            tmp4,
            distance;
movemonst () {
    register int    i,
                    j;
    if (c[TIMESTOP])
	return;			/* no action if time is stopped */
    if (c[HASTESELF])
	if ((c[HASTESELF] & 1) == 0)
	    return;
    if (spheres)
	movsphere ();		/* move the spheres of annihilation if any */
    if (c[HOLDMONST])
	return;			/* no action if monsters are held */

    if (c[AGGRAVATE]) {		/* determine window of monsters to move */
	tmp1 = playery - 5;
	tmp2 = playery + 6;
	tmp3 = playerx - 10;
	tmp4 = playerx + 11;
	distance = 40;		/* depth of intelligent monster movement */
    }
    else {
	tmp1 = playery - 3;
	tmp2 = playery + 4;
	tmp3 = playerx - 5;
	tmp4 = playerx + 6;
	distance = 17;		/* depth of intelligent monster movement */
    }

    if (level == 0) {		/* if on outside level monsters can move in perimeter */
	if (tmp1 < 0)
	    tmp1 = 0;
	if (tmp2 > MAXY)
	    tmp2 = MAXY;
	if (tmp3 < 0)
	    tmp3 = 0;
	if (tmp4 > MAXX)
	    tmp4 = MAXX;
    }
    else {			/* if in a dungeon monsters can't be on the perimeter (wall there) */
	if (tmp1 < 1)
	    tmp1 = 1;
	if (tmp2 > MAXY - 1)
	    tmp2 = MAXY - 1;
	if (tmp3 < 1)
	    tmp3 = 1;
	if (tmp4 > MAXX - 1)
	    tmp4 = MAXX - 1;
    }

    for (j = tmp1; j < tmp2; j++)/* now reset monster moved flags */
	for (i = tmp3; i < tmp4; i++)
	    moved[i][j] = 0;
    moved[lasthx][lasthy] = 0;

    if (c[AGGRAVATE] || !c[STEALTH]) {/* who gets moved? split for efficiency */
	for (j = tmp1; j < tmp2; j++)/* look thru all locations in window */
	    for (i = tmp3; i < tmp4; i++)
		if (mitem[i][j])/* if there is a monster to move */
		    if (moved[i][j] == 0)/* if it has not already been moved */
			movemt (i, j);/* go and move the monster */
    }
    else {			/* not aggravated and not stealth */
	for (j = tmp1; j < tmp2; j++)/* look thru all locations in window */
	    for (i = tmp3; i < tmp4; i++)
		if (mitem[i][j])/* if there is a monster to move */
		    if (moved[i][j] == 0)/* if it has not already been moved */
			if (stealth[i][j])/* if it is asleep due to stealth */
			    movemt (i, j);/* go and move the monster */
    }

    if (mitem[lasthx][lasthy]) {/* now move monster last hit by player if not already moved */
	if (moved[lasthx][lasthy] == 0) {/* if it has not already been moved */
	    movemt (lasthx, lasthy);
	    lasthx = w1x[0];
	    lasthy = w1y[0];
	}
    }
}

/*
 *	movemt(x,y)		Function to move a monster at (x,y) -- must determine where
 *		int x,y;
 *
 *	This routine is responsible for determining where one monster at (x,y) will
 *	move to.  Enter with the monsters coordinates in (x,y).
 *	Returns no value.
 */
static int  tmpitem,
            xl,
            xh,
            yl,
            yh;
movemt (i, j)
int     i,
        j;
{
    register int    k,
                    m,
                    z,
                    tmp,
                    xtmp,
                    ytmp,
                    monst;
    switch (monst = mitem[i][j]) {/* for half speed monsters */
	case TROGLODYTE: 
	case HOBGOBLIN: 
	case METAMORPH: 
	case XVART: 
	case INVISIBLESTALKER: 
	case ICELIZARD: 
	    if ((gtime & 1) == 1)
		return;
    };

    if (c[SCAREMONST]) {	/* choose destination randomly if scared */
	if ((xl = i + rnd (3) - 2) < 0)
	    xl = 0;
	if (xl >= MAXX)
	    xl = MAXX - 1;
	if ((yl = j + rnd (3) - 2) < 0)
	    yl = 0;
	if (yl >= MAXY)
	    yl = MAXY - 1;
	if ((tmp = item[xl][yl]) != OWALL)
	    if (mitem[xl][yl] == 0)
		if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
		    if (tmp != OCLOSEDDOOR)
			mmove (i, j, xl, yl);
	return;
    }

    if (monster[monst].intelligence > 10 - c[HARDGAME]) {/* if smart monster */
    /* intelligent movement here -- first setup screen array */
	xl = tmp3 - 2;
	yl = tmp1 - 2;
	xh = tmp4 + 2;
	yh = tmp2 + 2;
	vxy (&xl, &yl);
	vxy (&xh, &yh);
	for (k = yl; k < yh; k++)
	    for (m = xl; m < xh; m++) {
		switch (item[m][k]) {
		    case OWALL: 
		    case OPIT: 
		    case OTRAPARROW: 
		    case ODARTRAP: 
		    case OCLOSEDDOOR: 
		    case OTRAPDOOR: 
		    case OTELEPORTER: 
		smm: 
			screen[m][k] = 127;
			break;
		    case OMIRROR: 
			if (mitem[m][k] == VAMPIRE)
			    goto smm;
		    default: 
			screen[m][k] = 0;
			break;
		};
	    }
	screen[playerx][playery] = 1;

    /* now perform proximity ripple from playerx,playery to monster */
	xl = tmp3 - 1;
	yl = tmp1 - 1;
	xh = tmp4 + 1;
	yh = tmp2 + 1;
	vxy (&xl, &yl);
	vxy (&xh, &yh);
	for (tmp = 1; tmp < distance; tmp++)/* only up to 20 squares away */
	    for (k = yl; k < yh; k++)
		for (m = xl; m < xh; m++)
		    if (screen[m][k] == tmp)/* if find proximity n advance it */
			for (z = 1; z < 9; z++) {/* go around in a circle */
			    if (screen[xtmp = m + diroffx[z]][ytmp = k + diroffy[z]] == 0)
				screen[xtmp][ytmp] = tmp + 1;
			    if (xtmp == i && ytmp == j)
				goto out;
			}

out: 
	if (tmp < distance)	/* did find connectivity */
	/* now select lowest value around playerx,playery */
	    for (z = 1; z < 9; z++)/* go around in a circle */
		if (screen[xl = i + diroffx[z]][yl = j + diroffy[z]] == tmp)
		    if (!mitem[xl][yl]) {
			mmove (i, j, w1x[0] = xl, w1y[0] = yl);
			return;
		    }
    }

 /* dumb monsters move here */
    xl = i - 1;
    yl = j - 1;
    xh = i + 2;
    yh = j + 2;
    if (i < playerx)
	xl++;
    else
	if (i > playerx)
	    --xh;
    if (j < playery)
	yl++;
    else
	if (j > playery)
	    --yh;
    for (k = 0; k < 9; k++)
	w1[k] = 10000;

    for (k = xl; k < xh; k++)
	for (m = yl; m < yh; m++) {/* for each square compute distance to player */
	    tmp = k - i + 4 + 3 * (m - j);
	    tmpitem = item[k][m];
	    if (tmpitem != OWALL || (k == playerx && m == playery))
		if (mitem[k][m] == 0)
		    if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
			if (tmpitem != OCLOSEDDOOR) {
			    w1[tmp] = (playerx - k) * (playerx - k) + (playery - m) * (playery - m);
			    w1x[tmp] = k;
			    w1y[tmp] = m;
			}
	}

    tmp = 0;
    for (k = 1; k < 9; k++)
	if (w1[tmp] > w1[k])
	    tmp = k;

    if (w1[tmp] < 10000)
	if ((i != w1x[tmp]) || (j != w1y[tmp]))
	    mmove (i, j, w1x[tmp], w1y[tmp]);
}

/*
 *	mmove(x,y,xd,yd)	Function to actually perform the monster movement
 *		int x,y,xd,yd;
 *
 *	Enter with the from coordinates in (x,y) and the destination coordinates
 *	in (xd,yd).
 */
mmove (aa, bb, cc, dd)
int     aa,
        bb,
        cc,
        dd;
{
    register int    tmp,
                    i,
                    flag;
    char   *who,
           *p;
    flag = 0;			/* set to 1 if monster hit by arrow trap */
    if ((cc == playerx) && (dd == playery)) {
	hitplayer (aa, bb);
	moved[aa][bb] = 1;
	return;
    }
    i = item[cc][dd];
    if ((i == OPIT) || (i == OTRAPDOOR))
	switch (mitem[aa][bb]) {
	    case SPIRITNAGA: 
	    case PLATINUMDRAGON: 
	    case WRAITH: 
	    case VAMPIRE: 
	    case SILVERDRAGON: 
	    case POLTERGEIST: 
	    case DEMONLORD: 
	    case DEMONLORD + 1: 
	    case DEMONLORD + 2: 
	    case DEMONLORD + 3: 
	    case DEMONLORD + 4: 
	    case DEMONLORD + 5: 
	    case DEMONLORD + 6: 
	    case DEMONPRINCE: 
		break;

	    default: 
		mitem[aa][bb] = 0;/* fell in a pit or trapdoor */
	};
    tmp = mitem[cc][dd] = mitem[aa][bb];
    if (i == OANNIHILATION) {
	if (tmp >= DEMONLORD + 3) {/* demons dispel spheres */
	    cursors ();
	    lprintf ("\nThe %s dispels the sphere!", monster[tmp].name);
	    rmsphere (cc, dd);	/* delete the sphere */
	}
	else
	    i = tmp = mitem[cc][dd] = 0;
    }
    stealth[cc][dd] = 1;
    if ((hitp[cc][dd] = hitp[aa][bb]) < 0)
	hitp[cc][dd] = 1;
    mitem[aa][bb] = 0;
    moved[cc][dd] = 1;
    if (tmp == LEPRECHAUN)
	switch (i) {
	    case OGOLDPILE: 
	    case OMAXGOLD: 
	    case OKGOLD: 
	    case ODGOLD: 
	    case ODIAMOND: 
	    case ORUBY: 
	    case OEMERALD: 
	    case OSAPPHIRE: 
		item[cc][dd] = 0;/* leprechaun takes gold */
	};

    if (tmp == TROLL)		/* if a troll regenerate him */
	if ((gtime & 1) == 0)
	    if (monster[tmp].hitpoints > hitp[cc][dd])
		hitp[cc][dd]++;

    if (i == OTRAPARROW) {	/* arrow hits monster */
	who = "An arrow";
	if ((hitp[cc][dd] -= rnd (10) + level) <= 0) {
	    mitem[cc][dd] = 0;
	    flag = 2;
	}
	else
	    flag = 1;
    }
    if (i == ODARTRAP) {	/* dart hits monster */
	who = "A dart";
	if ((hitp[cc][dd] -= rnd (6)) <= 0) {
	    mitem[cc][dd] = 0;
	    flag = 2;
	}
	else
	    flag = 1;
    }
    if (i == OTELEPORTER) {	/* monster hits teleport trap */
	flag = 3;
	fillmonst (mitem[cc][dd]);
	mitem[cc][dd] = 0;
    }
    if (c[BLINDCOUNT])
	return;			/* if blind don't show where monsters are	 */
    if (know[cc][dd] & 1) {
	p = 0;
	if (flag)
	    cursors ();
	switch (flag) {
	    case 1: 
		p = "\n%s hits the %s";
		break;
	    case 2: 
		p = "\n%s hits and kills the %s";
		break;
	    case 3: 
		p = "\nThe %s%s gets teleported";
		who = "";
		break;
	};
	if (p) {
	    lprintf (p, who, monster[tmp].name);
	    beep ();
	}
    }
 /* 	if (yrepcount>1) { know[aa][bb] &= 2;  know[cc][dd] &= 2; return; } */
    if (know[aa][bb] & 1)
	show1cell (aa, bb);
    if (know[cc][dd] & 1)
	show1cell (cc, dd);
}

/*
 *	movsphere() 	Function to look for and move spheres of annihilation
 *
 *	This function works on the sphere linked list, first duplicating the list
 *	(the act of moving changes the list), then processing each sphere in order
 *	to move it.  They eat anything in their way, including stairs, volcanic
 *	shafts, potions, etc, except for upper level demons, who can dispel
 *	spheres.
 *	No value is returned.
 */
#define SPHMAX 20		/* maximum number of spheres movsphere can handle */
movsphere () {
    register int    x,
                    y,
                    dir,
                    len;
    register struct sphere *sp,
                           *sp2;
    struct sphere   sph[SPHMAX];

 /* first duplicate sphere list */
    for (sp = 0, x = 0, sp2 = spheres; sp2; sp2 = sp2 -> p)/* look through sphere list */
	if (sp2 -> lev == level) {/* only if this level */
	    sph[x] = *sp2;
	    sph[x++].p = 0;	/* copy the struct */
	    if (x > 1)
		sph[x - 2].p = &sph[x - 1];/* link pointers */
	}
    if (x)
	sp = sph;		/* if any spheres, point to them */
    else
	return;			/* no spheres */

    for (sp = sph; sp; sp = sp -> p) {/* look through sphere list */
	x = sp -> x;
	y = sp -> y;
	if (item[x][y] != OANNIHILATION)
	    continue;		/* not really there */
	if (--(sp -> lifetime) < 0) {/* has sphere run out of gas? */
	    rmsphere (x, y);	/* delete sphere */
	    continue;
	}
	switch (rnd ((int) max (7, c[INTELLIGENCE] >> 1))) {/* time to move the sphere */
	    case 1: 
	    case 2: 		/* change direction to a random one */
		sp -> dir = rnd (8);
	    default: 		/* move in normal direction */
		dir = sp -> dir;
		len = sp -> lifetime;
		rmsphere (x, y);
		newsphere (x + diroffx[dir], y + diroffy[dir], dir, len);
	};
    }
}
SHAR_EOF
if test 11581 -ne "`wc -c < 'movem.c'`"
then
	echo shar: error transmitting "'movem.c'" '(should have been 11581 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'nap.c'" '(938 characters)'
if test -f 'nap.c'
then
	echo shar: will not over-write existing file "'nap.c'"
else
cat << \SHAR_EOF > 'nap.c'

/* nap.c	Larn is copyrighted 1986 by Noah Morgan. */

#include <times.h>

/*
 *	routine to take a nap for n milliseconds
 */
nap (x)
register int x;
{
    if (x <= 0)
	return;		/* eliminate chance for infinite loop */
    lflush ();
    if (x > 999)
	sleep (x / 1000);
    else
	napms (x);
}


#ifdef NONAP
napms (x)			/* do nothing */
int x;
{
}
#else NONAP
/*  napms - sleep for time milliseconds - uses times()
 *	    This assumes that times returns a relative time in 100ths of a
 *	    second.  This will do horrible things if your times() returns
 *	    seconds!
 */
napms (time)
int time;
{
    long matchclock,times ();
    struct tms stats;

    if (time <= 0)
	time = 1;		/* eliminate chance for infinite loop */
    times(&stats);
    /* 10ms/tic is 1000 ms/sec / 100 tics/sec */
    matchclock = stats.tms_utime + (time/10);
    while (1) {
	times(&stats);
	if (matchclock < stats.tms_utime)
	    break;
    }
}
#endif NONAP
SHAR_EOF
if test 938 -ne "`wc -c < 'nap.c'`"
then
	echo shar: error transmitting "'nap.c'" '(should have been 938 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'readme.txt'" '(8418 characters)'
if test -f 'readme.txt'
then
	echo shar: will not over-write existing file "'readme.txt'"
else
cat << \SHAR_EOF > 'readme.txt'


******************************************************************************
PREFACE FOR VMS PORT OF LARN 12.0

    After hacking away at this thing, I have finally gotten it to work on
VMS 4.2 using the VAX-11 C 2.1 compiler.  I have not tested it completely, but
it seems to function correctly.  I left the termcap stuff in because it works
fine on VMS if you have a termcap database, but the VT100 *is* incredibly
faster.  You can adjust the compile time options in the DEF line of MAKE.COM
(except for LARNHOME; you will have to change that inside of LARN.C).  I
removed a few obviously anti-VMS options, but everything else seems OK.
Anyway, to compile this baby just MAKE.COM after you have edited the options
and LARN.C.  NOTE:  Since does not have a *real* fork(), you should *not*
enable checkpoints in option file unless your system is pretty unreliable.
It slows the game a lot.  Have fun!


To compile:

    1) Edit MAKE.COM to reflect your needs.
        a)  If you choose to use the playerid option, make sure you have
            whoever is to be wizard play first.  Otherwise you must set
            WISID to be 65536*GID+UID.  Note that the GID and UID come from
            [GID,UID] account numbers (the displayed values are in OCTAL).
            So the WISID for [101,3] is 101(octal) * 65536 + 3(octal).
        b)  You will have to modify the symbol LARNHOME in the LARN.C file
            since I couldn't figure out how to /DEFINE=(LARNHOME="whatever")
            in the MAKE.COM file.  All LARN12.* files should also go in this
            directory (LARNHOME) before sexecuting.
        c)  Execute MAKE.COM (you will have to edit the default directory in
            this command file).
        d)  Move the executable (LARN.EXE) and all LARN12.* files to LARNHOME
            and set LARN as a foreign command (LARN :== $LARNHOME:LARN).


   - Mark Nagel

     ..!{ucbvax,dual,lll-crg}!ucdavis!{u557676751ea,u572112244ea,donovan}

*******************************************************************************
*******************************************************************************

Larn is a dungeon type game program.  Larn is a adventure/action game similar
in concept to rogue or hack, but with a much different feel. 
Try it, you'll like it!

You will have to edit the Makefile to reflect your configuration.  Define
LARNHOME as the place where the larn auxiliary files will reside, and
BINDIR as the place where the larn executable should be placed.  Type
"make" to compile, or "make all" to compile and install ("make install"
does just the install).

Here's a list of what is in each of the various source files:

CHANGES.TXT	this is a list of the things that were changed since ver 11.0
1MAKEFILE.	makefile script to compile the program
README.TXT	this is what you are now reading
BILL.C          code for the letters of praise if player wins

/* moved to LARN.C  MDN  */
CONFIG.C        data definitions for the installation dependent data --
		savefilenames, where the scorefiles are, etc.

CREATE.C        code to create the dungeon and all objects
DATA.C          data definitions for the game -- no code here
DIAG.C          code to produce diagnostic data for wizards, & savegame stuff
DISPLAY.C       code to update the display on the screen
FORTUNE.C	code for the fortune cookies
GLOBAL.C        code for globally used functions that are specific to larn
HEADER.H        constant and structure definitions
HELP.C          code for the help screens in the game of larn
LARN12.HDY	data file which lists upcoming holidays
IO.C		code to handle file and terminal i/o

/* added this module  --  MDN */
KEYSENSE.C	code to handle single key reading, dcl spawning

LARN.C		code for the main command control and parsing
LARN12.MAZ	data file for pre-made mazes
LARN12.OPT	a sample .larnopts option data file
LARN12.FTN	data file which contains the hints
MONSTER.C       code to handle attack and defense modes with monsters
MOREOBJ.C	code for the fountains, altars, thrones
MOVEM.C		code to move the monsters around the dungeon
NAP.C		code to sleep for less than a second
OBJECT.C	code to handle objects in the dungeon
REGEN.C		code to regenerate the player and advance game time
SAVELEV.C	code to get/put a level from level storage into working level
		memory
SCORES.C	code to process and manage the scoreboard
SIGNAL.C	code to handle signals that are trapped
STORE.C		code for the larn thrift shoppe, bank, trading post, lrs
TOK.C		code for the input front end and options file processing

To find out how to play the game, run it and type in a '?' to get the help
screens.  By the way, the wizards password is "pvnert(x)" and to become wizard
type in an underscore, you are then prompted for the password.  Wizards are
non-scoring characters that get enlightenment, everlasting expanded 
awareness, and one of every object in the game.  They help the author to debug
the game.

Note regarding the wizard id:  If you are using userid's, then WIZID must be
set to the userid of the person who can become wizard.  If you are using
player id's, WIZID must be set to the playerid (edit file .playerids if needed)
of the player who can become wizard.

You may want to clear out the scoreboard.  The command "larn -c" will make a
new scoreboard.  It will prompt you for the wizards password.

BUGS & FIXES:

James McNamara has volunteered to maintain the latest sources, and provide
latest bug fixes to anyone who asks.  Both James and I will field requests for
sources, for those who ask.

			  ___	Prince of Gems (alias Noah Morgan)
			 /.  \	USENET: panda!condor!noah
			 \   /	at GenRad Inc.  Bolton MA
			  \ /
			   v


Below is some additional info about the installation of larn:

Install: Notes on the game LARN installation.
Larn is copyrighted 1986 by Noah Morgan.
This file (below) originally by James D. McNamara, last update 7/27/86 by nm

THIS DISTRIBUTION:

	You should receive six (6) shar files, which are:

	larn.part-1
	larn.part-2
	larn.part-3
	larn.part-4
	larn.part-5
	larn.part-6

I.	Use /bin/sh (or your system equivalent) to "unravel" shar files
	larn.part-1, ..., larn.part-6.  I suggest you do this directly
	into $LARNHOME (See Section III.).  Notable files:

	README	-	The author's how-to.
	MANIFEST -	Files you should have.

III.	Edit a copy of "Makefile" and leave the edited version in $LARNHOME.

All the "configuration" options are tidily near the top of the "Makefile."
Here are the ones you probably will want to edit:

LARNHOME	I specified (literally) the directory, with path from root,
	where "larn" will reside.  This included where I put the *.c files,
	it is where the *.o files ended up, as well as all data and *.h files.
	i suspect the *.c and intallation-documentation files can be moved off,
	but the data and bits must all remain here for execution.

BINDIR		I specified (literally) the directory, with path from root,
	where the executable "larn" will reside.  The "Makefile" will dump
	the "a.out", named "larn", in this directory.  My BINDIR was not
	my LARNHOME, so $BINDIR/larn was the ONLY file dumed here.  You'll
	probably have to chmod it for public execute, etc.


OPTIONS		This is how *I* specified them... they are documented in-line:
	OPTIONS = -DWIZZARD -DWIZID=157 -DEXTRA -DBSD -DSAVEINHOME

IV.	Compile the bugger.  Read "README" before you do.  You have a couple
	of options here:

	make			- will not install, suspect good for updates.
	make all		- compile (and) intall
	make install		- just install

	I did "make" and then "make install" -- seems to work "ok", but
	"make all" probably safer, if I had known.  Note that "Makefile"
	is the default file for "make."

V.	Execute and have fun.  If wizard code "ok", larn -c will refresh the
	scoreboard.  Play and win (or get killed) to put somebody on the
	scoreboard.

VI.	BUGS and FIXES.

	Please forward any bug-fixes in these regards to me (or Noah), so I may
	compile a fix-list for other installers.  Thanks.

Regards,
===============================================================================
James D. McNamara                    CSNET:   jim@bu-cs
                                     ARPANET: jim%bu-cs@csnet-relay
                                     UUCP:    ...harvard!bu-cs!jim
                                     BITNET:  jim%bu-cs%csnet-relay.arpa@wiscvm
===============================================================================

SHAR_EOF
if test 8418 -ne "`wc -c < 'readme.txt'`"
then
	echo shar: error transmitting "'readme.txt'" '(should have been 8418 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)

Hello all!  This is a port of Larn v12.0 to VAX/VMS.  Now everyone can save
his/her daughter!!  Just unpack using /bin/sh and read readme.txt.

                                                - Mark Nagel

P.S.  Thanks to Lord Kahless for letting me post this!



-------------------------------cut here-------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	monster.c
#	regen.c
#	savelev.c
#	signal.c
#	tok.c
# This archive created: Sat Aug 30 14:52:16 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'monster.c'" '(45763 characters)'
if test -f 'monster.c'
then
	echo shar: will not over-write existing file "'monster.c'"
else
cat << \SHAR_EOF > 'monster.c'

/*
 *	monster.c		Larn is copyrighted 1986 by Noah Morgan. 
 *
 *This file contains the following functions:
 *----------------------------------------------------------------------------
 *
 *createmonster(monstno)	Function to create a monster next to the player
 *int monstno;
 *
 *int cgood(x,y,itm,monst)	Function to check location for emptiness
 *int x,y,itm,monst;
 *
 *createitem(it,arg)	Routine to place an item next to the player
 *int it,arg;
 *
 *cast() 		Subroutine called by parse to cast a spell for the user
 *
 *speldamage(x) 	Function to perform spell functions cast by the player
 *int x;
 *
 *loseint()		Routine to decrement your int(intelligence) if > 3
 *
 *isconfuse() 		Routine to check to see if player is confused
 *
 *nospell(x,monst)	Routine to return 1 if a spell doesn't affect a monster
 *int x,monst;
 *
 *fullhit(xx)		Function to return full damage against a monst(aka web)
 *int xx;
 *
 *direct(spnum,dam,str,arg)	Routine to direct spell damage 1 square in 1 dir
 *int spnum,dam,arg;
 *char *str;
 *
 *godirect(spnum,dam,str,delay,cshow)		Function to perform missile attacks
 *int spnum,dam,delay;
 *char *str,cshow;
 *
 *ifblind(x,y)	Routine to put "monster" or the monster name into lastmosnt
 *int x,y;
 *
 *tdirect(spnum)	Routine to teleport away a monster
 *int spnum;
 *
 *omnidirect(sp,dam,str)  Routine to damage all monsters 1 square from player
 *int sp,dam;
 *char *str;
 *
 *dirsub(x,y)		Routine to ask for direction, then modify x,y for it
 *int *x,*y;
 *
 *vxy(x,y)		Routine to verify/fix(*x,*y) for being within bounds
 *int *x,*y;
 *
 *dirpoly(spnum)	Routine to ask for a direction and polymorph a monst
 *int spnum;
 *
 *hitmonster(x,y) 	Function to hit a monster at the designated coordinates
 *int x,y;
 *
 *hitm(x,y,amt)		Function to just hit a monster at a given coordinates
 *int x,y,amt;
 *
 *hitplayer(x,y)	Function for the monster to hit the player from(x,y)
 *int x,y;
 *
 *dropsomething(monst) 	Function to create an object when a monster dies
 *int monst;
 *
 *dropgold(amount) 	Function to drop some gold around player
 *int amount;
 *
 *something(level) 	Function to create a random item around player
 *int level;
 *
 *newobject(lev,i) 	Routine to return a randomly selected new object
 *int lev,*i;
 *
 *spattack(atckno,xx,yy) 	Function to process special attacks from monsters
 *int atckno,xx,yy;
 *
 *checkloss(x) 	Routine to subtract hp from user and flag bottomline display
 *int x;
 *
 *annihilate()   Routine to annihilate monsters around player, playerx,playery
 *
 *newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
 *int x,y,dir,lifetime;
 *
 *rmsphere(x,y)		Function to delete a sphere of annihilation from list
 *int x,y;
 *
 *sphboom(x,y)		Function to perform the effects of a sphere detonation
 *int x,y;
 *
 *genmonst()		Function to ask for monster and genocide from game
 *
 */

#include "header.h"

struct isave {			/* used for alter reality */
    char    type;		/* 0=item,  1=monster */
    char    id;			/* item number or monster number */
    short   arg;		/* the type of item or hitpoints of monster */
};

/*
 *createmonster(monstno)	Function to create a monster next to the player
 *int monstno;
 *
 *	Enter with the monster number(1 to MAXMONST+8)
 *	Returns no value.
 */
createmonster(mon)
int mon;
{
    register int    x,
                    y,
                    k,
                    i;
    if (mon < 1 || mon > MAXMONST + 8) {/* check for monster number out of bounds */
	beep();
	lprintf("\ncan't createmonst(%d)\n",(long) mon);
	nap(3000);
	return;
    }
    while (monster[mon].genocided && mon < MAXMONST)
	mon++;			/* genocided? */
    for (k = rnd(8), i = -8; i < 0; i++, k++) {/* choose direction, then try all */
	if (k > 8)
	    k = 1;		/* wraparound the diroff arrays */
	x = playerx + diroffx[k];
	y = playery + diroffy[k];
	if (cgood(x, y, 0, 1)) {/* if we can create here */
	    mitem[x][y] = mon;
	    hitp[x][y] = monster[mon].hitpoints;
	    stealth[x][y] = know[x][y] = 0;
	    switch(mon) {
		case ROTHE: 
		case POLTERGEIST: 
		case VAMPIRE: 
		    stealth[x][y] = 1;
	    };
	    return;
	}
    }
}

/*
 *	int cgood(x,y,itm,monst)	  Function to check location for emptiness
 *		int x,y,itm,monst;
 *
 *	Routine to return TRUE if a location does not have itm or monst there
 *	returns FALSE(0) otherwise
 *	Enter with itm or monst TRUE or FALSE if checking it
 *	Example:  if itm==TRUE check for no item at this location
 *			  if monst==TRUE check for no monster at this location
 *	This routine will return FALSE if at a wall or the dungeon exit on level 1
 */
int     cgood(x, y, itm, monst)
register int    x,
                y;
int     itm,
        monst;
{
    if ((y >= 0) && (y <= MAXY - 1) && (x >= 0) && (x <= MAXX - 1))/* within bounds? */
	if (item[x][y] != OWALL)/* can't make anything on walls */
	    if (itm == 0 || (item[x][y] == 0))/* is it free of items? */
		if (monst == 0 || (mitem[x][y] == 0))/* is it free of monsters? */
		    if ((level != 1) || (x != 33) || (y != MAXY - 1))/* not exit to level 1 */
			return(1);
    return(0);
}

/*
 *	createitem(it,arg) 		Routine to place an item next to the player
 *		int it,arg;
 *
 *	Enter with the item number and its argument(iven[], ivenarg[])
 *	Returns no value, thus we don't know about createitem() failures.
 */
createitem(it, arg)
int     it,
        arg;
{
    register int    x,
                    y,
                    k,
                    i;
    if (it >= MAXOBJ)
	return;			/* no such object */
    for (k = rnd(8), i = -8; i < 0; i++, k++) {/* choose direction, then try all */
	if (k > 8)
	    k = 1;		/* wraparound the diroff arrays */
	x = playerx + diroffx[k];
	y = playery + diroffy[k];
	if (cgood(x, y, 1, 0)) {/* if we can create here */
	    item[x][y] = it;
	    know[x][y] = 0;
	    iarg[x][y] = arg;
	    return;
	}
    }
}

/*
 *	cast() 		Subroutine called by parse to cast a spell for the user
 *
 *	No arguments and no return value.
 */
static char eys[] = "\nEnter your spell: ";
cast()
{
    register int    i,j,a,b,d;

    cursors();
    if (c[SPELLS] <= 0) {
	lprcat("\nYou don't have any spells!");
	return;
    }
    lprcat(eys);
    --c[SPELLS];
    while ((a = readchar()) == 'D') {
	seemagic(-1);
	cursors();
	lprcat(eys);
    }
    if (a == '\33')
	goto over;		/* 	to escape casting a spell	 */
    if ((b = readchar()) == '\33')
	goto over;		/* 	to escape casting a spell	 */
    if ((d = readchar()) == '\33') {
over: 
	lprcat(aborted);
	c[SPELLS]++;
	return;
    }				/* 	to escape casting a spell	 */
#ifdef EXTRA
    c[SPELLSCAST]++;
#endif
    for (lprc('\n'), j = -1, i = 0; i < SPNUM; i++)/* seq search for his spell, hash? */
	if ((spelcode[i][0] == a) && (spelcode[i][1] == b) && (spelcode[i][2] == d))
	    if (spelknow[i]) {
		speldamage(i);
		j = 1;
		i = SPNUM;
	    }

    if (j == -1)
	lprcat("  Nothing Happened ");
    bottomline();
}

/*
 *	speldamage(x) 		Function to perform spell functions cast by the player
 *		int x;
 *
 *	Enter with the spell number, returns no value.
 *	Please insure that there are 2 spaces before all messages here
 */
speldamage(x)
int     x;
{
    register int    i,
                    j,
                    clev;
    int     xl,
            xh,
            yl,
            yh;
    register char  *p,
                   *kn,
                   *pm;
    if (x >= SPNUM)
	return;			/* no such spell */
    if (c[TIMESTOP]) {
	lprcat("  It didn't seem to work");
	return;
    }				/* not if time stopped */
    clev = c[LEVEL];
    if ((rnd(23) == 7) || (rnd(18) > c[INTELLIGENCE])) {
	lprcat("  It didn't work!");
	return;
    }
    if (clev * 3 + 2 < x) {
	lprcat("  Nothing happens.  You seem inexperienced at this");
	return;
    }

    switch(x) {
	/* ----- LEVEL 1 SPELLS ----- */

	case 0: 
	    if (c[PROTECTIONTIME] == 0)
		c[MOREDEFENSES] += 2;/* protection field +2 */
	    c[PROTECTIONTIME] += 250;
	    return;

	case 1: 
	    i = rnd(((clev + 1) << 1)) + clev + 3;
	    godirect(x, i,(clev >= 2) ? "  Your missiles hit the %s" : "  Your missile hit the %s", 100, '+');
				/* magic missile */

	    return;

	case 2: 
	    if (c[DEXCOUNT] == 0)
		c[DEXTERITY] += 3;/* 	dexterity	 */
	    c[DEXCOUNT] += 400;
	    return;

	case 3: 
	    i = rnd(3) + 1;
	    p = "  While the %s slept, you smashed it %d times";
    ws: 
	    direct(x, fullhit(i), p, i);/* 	sleep	 */
	    return;

	case 4: 		/* 	charm monster	 */
	    c[CHARMCOUNT] += c[CHARISMA] << 1;
	    return;

	case 5: 
	    godirect(x, rnd(10) + 15 + clev, "  The sound damages the %s", 70, '@');/* 	sonic spear */
	    return;

	/* ----- LEVEL 2 SPELLS ----- */

	case 6: 
	    i = rnd(3) + 2;
	    p = "  While the %s is entangled, you hit %d times";
	    goto ws;		/* web */

	case 7: 
	    if (c[STRCOUNT] == 0)
		c[STREXTRA] += 3;/* 	strength	 */
	    c[STRCOUNT] += 150 + rnd(100);
	    return;

	case 8: 
	    yl = playery - 5;	/* enlightenment */
	    yh = playery + 6;
	    xl = playerx - 15;
	    xh = playerx + 16;
	    vxy(&xl, &yl);
	    vxy(&xh, &yh);	/* check bounds */
	    for (i = yl; i <= yh; i++)/* enlightenment	 */
		for (j = xl; j <= xh; j++)
		    know[j][i] = 1;
	    draws(xl, xh + 1, yl, yh + 1);
	    return;

	case 9: 
	    raisehp(20 +(clev << 1));
	    return;		/* healing */

	case 10: 
	    c[BLINDCOUNT] = 0;
	    return;		/* cure blindness	 */

	case 11: 
	    createmonster(makemonst(level + 1) + 8);
	    return;

	case 12: 
	    if (rnd(11) + 7 <= c[WISDOM])
		direct(x, rnd(20) + 20 + clev, "  The %s believed!", 0);
	    else
		lprcat("  It didn't believe the illusions!");
	    return;

	case 13: 		/* if he has the amulet of invisibility then add more time */
	    for (j = i = 0; i < 26; i++)
		if (iven[i] == OAMULET)
		    j += 1 + ivenarg[i];
	    c[INVISIBILITY] +=(j << 7) + 12;
	    return;

	/* ----- LEVEL 3 SPELLS ----- */

	case 14: 
	    godirect(x, rnd(25 + clev) + 25 + clev, "  The fireball hits the %s", 40, '*');
	    return;		/* 	fireball */

	case 15: 
	    godirect(x, rnd(25) + 20 + clev, "  Your cone of cold strikes the %s", 60, 'O');/* 	cold */
	    return;

	case 16: 
	    dirpoly(x);
	    return;		/* 	polymorph */

	case 17: 
	    c[CANCELLATION] += 5 + clev;
	    return;		/* 	cancellation	 */

	case 18: 
	    c[HASTESELF] += 7 + clev;
	    return;		/* 	haste self	 */

	case 19: 
	    omnidirect(x, 30 + rnd(10), "  The %s gasps for air");/* cloud kill */
	    return;

	case 20: 
	    xh = min(playerx + 1, MAXX - 2);
	    yh = min(playery + 1, MAXY - 2);
	    for (i = max(playerx - 1, 1); i <= xh; i++)/* vaporize rock */
		for (j = max(playery - 1, 1); j <= yh; j++) {
		    kn = &know[i][j];
		    pm = &mitem[i][j];
		    switch(*(p = &item[i][j])) {
			case OWALL: 
			    if (level < MAXLEVEL + MAXVLEVEL - 1)
				*p = *kn = 0;
			    break;

			case OSTATUE: 
			    if (c[HARDGAME] < 3) {
				*p = OBOOK;
				iarg[i][j] = level;
				*kn = 0;
			    }
			    break;

			case OTHRONE: 
			    *pm = GNOMEKING;
			    *kn = 0;
			    *p = OTHRONE2;
			    hitp[i][j] = monster[GNOMEKING].hitpoints;
			    break;

			case OALTAR: 
			    *pm = DEMONPRINCE;
			    *kn = 0;
			    hitp[i][j] = monster[DEMONPRINCE].hitpoints;
			    break;
		    };
		    switch(*pm) {
			case XORN: 
			    ifblind(i, j);
			    hitm(i, j, 200);
			    break;/* Xorn takes damage from vpr */
		    }
		}
	    return;

	/* ----- LEVEL 4 SPELLS ----- */

	case 21: 
	    direct(x, 100 + clev, "  The %s shrivels up", 0);/* dehydration */
	    return;

	case 22: 
	    godirect(x, rnd(25) + 20 +(clev << 1), "  A lightning bolt hits the %s", 1, '~');/* 	lightning */
	    return;

	case 23: 
	    i = min(c[HP] - 1, c[HPMAX] / 2);/* drain life */
	    direct(x, i + i, "", 0);
	    c[HP] -= i;
	    return;

	case 24: 
	    if (c[GLOBE] == 0)
		c[MOREDEFENSES] += 10;
	    c[GLOBE] += 200;
	    loseint();		/* globe of invulnerability */
	    return;

	case 25: 
	    omnidirect(x, 32 + clev, "  The %s struggles for air in your flood!");/* flood */
	    return;

	case 26: 
	    if (rnd(151) == 63) {
		beep();
		lprcat("\nYour heart stopped!\n");
		nap(4000);
		died(270);
		return;
	    }
	    if (c[WISDOM] > rnd(10) + 10)
		direct(x, 2000, "  The %s's heart stopped", 0);/* finger of death */
	    else
		lprcat("  It didn't work");
	    return;

	/* ----- LEVEL 5 SPELLS ----- */

	case 27: 
	    c[SCAREMONST] += rnd(10) + clev;
	    return;		/* scare monster */

	case 28: 
	    c[HOLDMONST] += rnd(10) + clev;
	    return;		/* hold monster */

	case 29: 
	    c[TIMESTOP] += rnd(20) +(clev << 1);
	    return;		/* time stop */

	case 30: 
	    tdirect(x);
	    return;		/* teleport away */

	case 31: 
	    omnidirect(x, 35 + rnd(10) + clev, "  The %s cringes from the flame");/* magic fire */
	    return;

	/* ----- LEVEL 6 SPELLS ----- */

	case 32: 
	    if ((rnd(23) == 5) && (wizard == 0)) {/* sphere of annihilation */
		beep();
		lprcat("\nYou have been enveloped by the zone of nothingness!\n");
		nap(4000);
		died(258);
		return;
	    }
	    xl = playerx;
	    yl = playery;
	    loseint();
	    i = dirsub(&xl, &yl);/* get direction of sphere */
	    newsphere(xl, yl, i, rnd(20) + 11);/* make a sphere */
	    return;

	case 33: 
	    genmonst();
	    spelknow[33] = 0;	/* genocide */
	    loseint();
	    return;

	case 34: 		/* summon demon */
	    if (rnd(100) > 30) {
		direct(x, 150, "  The demon strikes at the %s", 0);
		return;
	    }
	    if (rnd(100) > 15) {
		lprcat("  Nothing seems to have happened");
		return;
	    }
	    lprcat("  The demon turned on you and vanished!");
	    beep();
	    i = rnd(40) + 30;
	    lastnum = 277;
	    losehp(i);		/* must say killed by a demon */
	    return;

	case 35: 		/* walk through walls */
	    c[WTW] += rnd(10) + 5;
	    return;

	case 36: 		/* alter reality */
	    {
		struct isave   *save;/* pointer to item save structure */
		int     sc;
		sc = 0;		/* # items saved */
		save =(struct isave   *) malloc(sizeof(struct isave) * MAXX * MAXY * 2);
		for (j = 0; j < MAXY; j++)
		    for (i = 0; i < MAXX; i++) {/* save all items and monsters */
			xl = item[i][j];
			if (xl && xl != OWALL && xl != OANNIHILATION) {
			    save[sc].type = 0;
			    save[sc].id = item[i][j];
			    save[sc++].arg = iarg[i][j];
			}
			if (mitem[i][j]) {
			    save[sc].type = 1;
			    save[sc].id = mitem[i][j];
			    save[sc++].arg = hitp[i][j];
			}
			item[i][j] = OWALL;
			mitem[i][j] = 0;
			if (wizard)
			    know[i][j] = 1;
			else
			    know[i][j] = 0;
		    }
		eat(1, 1);
		if (level == 1)
		    item[33][MAXY - 1] = 0;
		for (j = rnd(MAXY - 2), i = 1; i < MAXX - 1; i++)
		    item[i][j] = 0;
		while (sc > 0) {/* put objects back in level */
		    --sc;
		    if (save[sc].type == 0) {
			int     trys;
			for (trys = 100, i = j = 1; --trys > 0 && item[i][j]; i = rnd(MAXX - 1), j = rnd(MAXY - 1));
			if (trys) {
			    item[i][j] = save[sc].id;
			    iarg[i][j] = save[sc].arg;
			}
		    }
		    else {	/* put monsters back in */
			int     trys;
			for (trys = 100, i = j = 1; --trys > 0 && (item[i][j] == OWALL || mitem[i][j]); i = rnd(MAXX - 1), j = rnd(MAXY - 1));
			if (trys) {
			    mitem[i][j] = save[sc].id;
			    hitp[i][j] = save[sc].arg;
			}
		    }
		}
		loseint();
		draws(0, MAXX, 0, MAXY);
		if (wizard == 0)
		    spelknow[36] = 0;
		free((char *) save);
		positionplayer();
		return;
	    }

	case 37: 		/* permanence */
	    adjtime(-99999L);
	    spelknow[37] = 0;	/* forget */
	    loseint();
	    return;

	default: 
	    lprintf("  spell %d not available!",(long) x);
	    beep();
	    return;
    };
}

/*
 *	loseint()		Routine to subtract 1 from your int(intelligence) if > 3
 *
 *	No arguments and no return value
 */
loseint()
{
    if (--c[INTELLIGENCE] < 3)
	c[INTELLIGENCE] = 3;
}

/*
 *	isconfuse() 		Routine to check to see if player is confused
 *
 *	This routine prints out a message saying "You can't aim your magic!"
 *	returns 0 if not confused, non-zero(time remaining confused) if confused
 */
isconfuse()
{
    if (c[CONFUSE]) {
	lprcat(" You can't aim your magic!");
	beep();
    }
    return(c[CONFUSE]);
}

/*
 *	nospell(x,monst)	Routine to return 1 if a spell doesn't affect a monster
 *		int x,monst;
 *
 *	Subroutine to return 1 if the spell can't affect the monster
 *	  otherwise returns 0
 *	Enter with the spell number in x, and the monster number in monst.
 */
nospell(x, monst)
int     x,
        monst;
{
    register int    tmp;
    if (x >= SPNUM || monst >= MAXMONST + 8 || monst < 0 || x < 0)
	return(0);		/* bad spell or monst */
    if ((tmp = spelweird[monst - 1][x]) == 0)
	return(0);
    cursors();
    lprc('\n');
    lprintf(spelmes[tmp], monster[monst].name);
    return(1);
}

/*
 *	fullhit(xx)		Function to return full damage against a monster(aka web)
 *		int xx;
 *
 *	Function to return hp damage to monster due to a number of full hits
 *	Enter with the number of full hits being done
 */
fullhit(xx)
int     xx;
{
    register int    i;
    if (xx < 0 || xx > 20)
	return(0);		/* fullhits are out of range */
    if (c[LANCEDEATH])
	return(10000);		/* lance of death */
    i = xx *((c[WCLASS] >> 1) + c[STRENGTH] + c[STREXTRA] - c[HARDGAME] - 12 + c[MOREDAM]);
    return((i >= 1) ? i : xx);
}

/*
 *	direct(spnum,dam,str,arg)	Routine to direct spell damage 1 square in 1 dir
 *		int spnum,dam,arg;
 *		char *str;
 *
 *	Routine to ask for a direction to a spell and then hit the monster
 *	Enter with the spell number in spnum, the damage to be done in dam,
 *	  lprintf format string in str, and lprintf's argument in arg.
 *	Returns no value.
 */
direct(spnum, dam, str, arg)
int     spnum,
        dam,
        arg;
char   *str;
{
    int     x,
            y;
    register int    m;
    if (spnum < 0 || spnum >= SPNUM || str == 0)
	return;			/* bad arguments */
    if (isconfuse())
	return;
    dirsub(&x, &y);
    m = mitem[x][y];
    if (item[x][y] == OMIRROR) {
	if (spnum == 3) {	/* sleep */
	    lprcat("You fall asleep! ");
	    beep();
    fool: 
	    arg += 2;
	    while (arg-- > 0) {
		parse2();
		nap(1000);
	    }
	    return;
	}
	else
	    if (spnum == 6) {	/* web */
		lprcat("You get stuck in your own web! ");
		beep();
		goto fool;
	    }
	    else {
		lastnum = 278;
		lprintf(str, "spell caster(thats you)",(long) arg);
		beep();
		losehp(dam);
		return;
	    }
    }
    if (m == 0) {
	lprcat("  There wasn't anything there!");
	return;
    }
    ifblind(x, y);
    if (nospell(spnum, m)) {
	lasthx = x;
	lasthy = y;
	return;
    }
    lprintf(str, lastmonst,(long) arg);
    hitm(x, y, dam);
}

/*
 *	godirect(spnum,dam,str,delay,cshow)		Function to perform missile attacks
 *		int spnum,dam,delay;
 *		char *str,cshow;
 *
 *	Function to hit in a direction from a missile weapon and have it keep
 *	on going in that direction until its power is exhausted
 *	Enter with the spell number in spnum, the power of the weapon in hp,
 *	  lprintf format string in str, the # of milliseconds to delay between 
 *	  locations in delay, and the character to represent the weapon in cshow.
 *	Returns no value.
 */
godirect(spnum, dam, str, delay, cshow)
int     spnum,
        dam,
        delay;
char   *str,
        cshow;
{
    register char  *p;
    register int    x,
                    y,
                    m;
    int     dx,
            dy;
    if (spnum < 0 || spnum >= SPNUM || str == 0 || delay < 0)
	return;			/* bad args */
    if (isconfuse())
	return;
    dirsub(&dx, &dy);
    x = dx;
    y = dy;
    dx = x - playerx;
    dy = y - playery;
    x = playerx;
    y = playery;
    while (dam > 0) {
	x += dx;
	y += dy;
	if ((x > MAXX - 1) || (y > MAXY - 1) || (x < 0) || (y < 0)) {
	    dam = 0;
	    break;		/* out of bounds */
	}
	if ((x == playerx) && (y == playery)) {/* if energy hits player */
	    cursors();
	    lprcat("\nYou are hit my your own magic!");
	    beep();
	    lastnum = 278;
	    losehp(dam);
	    return;
	}
	if (c[BLINDCOUNT] == 0) {/* if not blind show effect */
	    cursor(x + 1, y + 1);
	    lprc(cshow);
	    nap(delay);
	    show1cell(x, y);
	}
	if ((m = mitem[x][y])) {/* is there a monster there? */
	    ifblind(x, y);
	    if (nospell(spnum, m)) {
		lasthx = x;
		lasthy = y;
		return;
	    }
	    cursors();
	    lprc('\n');
	    lprintf(str, lastmonst);
	    dam -= hitm(x, y, dam);
	    show1cell(x, y);
	    nap(1000);
	    x -= dx;
	    y -= dy;
	}
	else
	    switch(*(p = &item[x][y])) {
		case OWALL: 
		    cursors();
		    lprc('\n');
		    lprintf(str, "wall");
		    if (dam >= 50 + c[HARDGAME])/* enough damage? */
			if (level < MAXLEVEL + MAXVLEVEL - 1)/* not on V3 */
			    if ((x < MAXX - 1) && (y < MAXY - 1) && (x) && (y)) {
				lprcat("  The wall crumbles");
			god3: 
				*p = 0;
			god: 
				know[x][y] = 0;
				show1cell(x, y);
			    }
	    god2: 
		    dam = 0;
		    break;

		case OCLOSEDDOOR: 
		    cursors();
		    lprc('\n');
		    lprintf(str, "door");
		    if (dam >= 40) {
			lprcat("  The door is blasted apart");
			goto god3;
		    }
		    goto god2;

		case OSTATUE: 
		    cursors();
		    lprc('\n');
		    lprintf(str, "statue");
		    if (c[HARDGAME] < 3)
			if (dam > 44) {
			    lprcat("  The statue crumbles");
			    *p = OBOOK;
			    iarg[x][y] = level;
			    goto god;
			}
		    goto god2;

		case OTHRONE: 
		    cursors();
		    lprc('\n');
		    lprintf(str, "throne");
		    if (dam > 39) {
			mitem[x][y] = GNOMEKING;
			hitp[x][y] = monster[GNOMEKING].hitpoints;
			*p = OTHRONE2;
			goto god;
		    }
		    goto god2;

		case OMIRROR: 
		    dx *= -1;
		    dy *= -1;
		    break;
	    };
	dam -= 3 +(c[HARDGAME] >> 1);
    }
}

/*
 *	ifblind(x,y)	Routine to put "monster" or the monster name into lastmosnt
 *		int x,y;
 *
 *	Subroutine to copy the word "monster" into lastmonst if the player is blind
 *	Enter with the coordinates(x,y) of the monster
 *	Returns no value.
 */
ifblind(x, y)
int     x,
        y;
{
    char   *p;
    vxy(&x, &y);		/* verify correct x,y coordinates */
    if (c[BLINDCOUNT]) {
	lastnum = 279;
	p = "monster";
    }
    else {
	lastnum = mitem[x][y];
	p = monster[lastnum].name;
    }
    strcpy(lastmonst, p);
}

/*
 *	tdirect(spnum)		Routine to teleport away a monster
 *		int spnum;
 *
 *	Routine to ask for a direction to a spell and then teleport away monster
 *	Enter with the spell number that wants to teleport away
 *	Returns no value.
 */
tdirect(spnum)
int     spnum;
{
    int     x,
            y;
    register int    m;
    if (spnum < 0 || spnum >= SPNUM)
	return;			/* bad args */
    if (isconfuse())
	return;
    dirsub(&x, &y);
    if ((m = mitem[x][y]) == 0) {
	lprcat("  There wasn't anything there!");
	return;
    }
    ifblind(x, y);
    if (nospell(spnum, m)) {
	lasthx = x;
	lasthy = y;
	return;
    }
    fillmonst(m);
    mitem[x][y] = know[x][y] = 0;
}

/*
 *	omnidirect(sp,dam,str)   Routine to damage all monsters 1 square from player
 *		int sp,dam;
 *		char *str;
 *
 *	Routine to cast a spell and then hit the monster in all directions
 *	Enter with the spell number in sp, the damage done to wach square in dam,
 *	  and the lprintf string to identify the spell in str.
 *	Returns no value.
 */
omnidirect(spnum, dam, str)
int     spnum,
        dam;
char   *str;
{
    register int    x,
                    y,
                    m;
    if (spnum < 0 || spnum >= SPNUM || str == 0)
	return;			/* bad args */
    for (x = playerx - 1; x < playerx + 2; x++)
	for (y = playery - 1; y < playery + 2; y++) {
	    if (m = mitem[x][y])
		if (nospell(spnum, m) == 0) {
		    ifblind(x, y);
		    cursors();
		    lprc('\n');
		    lprintf(str, lastmonst);
		    hitm(x, y, dam);
		    nap(800);
		}
		else {
		    lasthx = x;
		    lasthy = y;
		}
	}
}

/*
 *	static dirsub(x,y)		Routine to ask for direction, then modify x,y for it
 *		int *x,*y;
 *
 *	Function to ask for a direction and modify an x,y for that direction
 *	Enter with the origination coordinates in(x,y).
 *	Returns index into diroffx[](0-8).
 */
static  dirsub(x, y)
int    *x,
       *y;
{
    register int    i;
    lprcat("\nIn What Direction? ");
    for (i = 0;;)
	switch(readchar()) {
	    case 'b': 
		i++;
	    case 'n': 
		i++;
	    case 'y': 
		i++;
	    case 'u': 
		i++;
	    case 'h': 
		i++;
	    case 'k': 
		i++;
	    case 'l': 
		i++;
	    case 'j': 
		i++;
		goto out;
	};
out: 
    *x = playerx + diroffx[i];
    *y = playery + diroffy[i];
    vxy(x, y);
    return(i);
}

/*
 *	vxy(x,y)	   Routine to verify/fix coordinates for being within bounds
 *		int *x,*y;
 *
 *	Function to verify x & y are within the bounds for a level
 *	If *x or *y is not within the absolute bounds for a level, fix them so that
 *	  they are on the level.
 *	Returns TRUE if it was out of bounds, and the *x & *y in the calling
 *	routine are affected.
 */
vxy(x, y)
int    *x,
       *y;
{
    int     flag = 0;
    if (*x < 0) {
	*x = 0;
	flag++;
    }
    if (*y < 0) {
	*y = 0;
	flag++;
    }
    if (*x >= MAXX) {
	*x = MAXX - 1;
	flag++;
    }
    if (*y >= MAXY) {
	*y = MAXY - 1;
	flag++;
    }
    return(flag);
}

/*
 *	dirpoly(spnum)		Routine to ask for a direction and polymorph a monst
 *		int spnum;
 *
 *	Subroutine to polymorph a monster and ask for the direction its in
 *	Enter with the spell number in spmun.
 *	Returns no value.
 */
dirpoly(spnum)
int     spnum;
{
    int     x,
            y,
            m;
    if (spnum < 0 || spnum >= SPNUM)
	return;			/* bad args */
    if (isconfuse())
	return;			/* if he is confused, he can't aim his magic */
    dirsub(&x, &y);
    if (mitem[x][y] == 0) {
	lprcat("  There wasn't anything there!");
	return;
    }
    ifblind(x, y);
    if (nospell(spnum, mitem[x][y])) {
	lasthx = x;
	lasthy = y;
	return;
    }
    while (monster[m = mitem[x][y] = rnd(MAXMONST + 7)].genocided);
    hitp[x][y] = monster[m].hitpoints;
    show1cell(x, y);		/* show the new monster */
}

/*
 *	hitmonster(x,y) 	Function to hit a monster at the designated coordinates
 *		int x,y;
 *
 *	This routine is used for a bash & slash type attack on a monster
 *	Enter with the coordinates of the monster in(x,y).
 *	Returns no value.
 */
hitmonster(x, y)
int     x,
        y;
{
    register int    tmp,
                    monst,
                    damag,
                    flag;
    if (c[TIMESTOP])
	return;			/* not if time stopped */
    vxy(&x, &y);		/* verify coordinates are within range */
    if ((monst = mitem[x][y]) == 0)
	return;
    hit3flag = 1;
    ifblind(x, y);
    tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS] / 4 - 12;
    cursors();
    if ((rnd(20) < tmp - c[HARDGAME]) || (rnd(71) < 5)) {/* need at least random chance to hit */
	lprcat("\nYou hit");
	flag = 1;
	damag = fullhit(1);
	if (damag < 9999)
	    damag = rnd(damag) + 1;
    }
    else {
	lprcat("\nYou missed");
	flag = 0;
    }
    lprcat(" the ");
    lprcat(lastmonst);
    if (flag)			/* if the monster was hit */
	if ((monst == RUSTMONSTER) || (monst == DISENCHANTRESS) || (monst == CUBE))
	    if (c[WIELD] > 0)
		if (ivenarg[c[WIELD]] > -10) {
		    lprintf("\nYour weapon is dulled by the %s", lastmonst);
		    beep();
		    --ivenarg[c[WIELD]];
		}
    if (flag)
	hitm(x, y, damag);
    if (monst == VAMPIRE)
	if (hitp[x][y] < 25) {
	    mitem[x][y] = BAT;
	    know[x][y] = 0;
	}
}

/*
 *	hitm(x,y,amt)		Function to just hit a monster at a given coordinates
 *		int x,y,amt;
 *
 *	Returns the number of hitpoints the monster absorbed
 *	This routine is used to specifically damage a monster at a location(x,y)
 *	Called by hitmonster(x,y)
 */
hitm(x, y, amt)
int     x,
        y;
register    amt;
{
    register int    monst;
    int     hpoints,
            amt2;
    vxy(&x, &y);		/* verify coordinates are within range */
    amt2 = amt;			/* save initial damage so we can return it */
    monst = mitem[x][y];
    if (c[HALFDAM])
	amt >>= 1;		/* if half damage curse adjust damage points */
    if (amt <= 0)
	amt2 = amt = 1;
    lasthx = x;
    lasthy = y;
    stealth[x][y] = 1;		/* make sure hitting monst breaks stealth condition */
    c[HOLDMONST] = 0;		/* hit a monster breaks hold monster spell	 */
    switch(monst) {		/* if a dragon and orb(s) of dragon slaying	 */
	case WHITEDRAGON: 
	case REDDRAGON: 
	case GREENDRAGON: 
	case BRONZEDRAGON: 
	case PLATINUMDRAGON: 
	case SILVERDRAGON: 
	    amt *= 1 +(c[SLAYING] << 1);
	    break;
    }
 /* invincible monster fix is here */
    if (hitp[x][y] > monster[monst].hitpoints)
	hitp[x][y] = monster[monst].hitpoints;
    if ((hpoints = hitp[x][y]) <= amt) {
#ifdef EXTRA
	c[MONSTKILLED]++;
#endif
	lprintf("\nThe %s died!", lastmonst);
	raiseexperience((long) monster[monst].experience);
	amt = monster[monst].gold;
	if (amt > 0)
	    dropgold(rnd(amt) + amt);
	dropsomething(monst);
	disappear(x, y);
	bottomline();
	return(hpoints);
    }
    hitp[x][y] = hpoints - amt;
    return(amt2);
}

/*
 *	hitplayer(x,y) 		Function for the monster to hit the player from(x,y)
 *		int x,y;
 *
 *	Function for the monster to hit the player with monster at location x,y
 *	Returns nothing of value.
 */
hitplayer(x, y)
int     x,
        y;
{
    register int    dam,
                    tmp,
                    mster,
                    bias;
    vxy(&x, &y);		/* verify coordinates are within range */
    lastnum = mster = mitem[x][y];
 /* 	spirit naga's and poltergeist's do nothing if scarab of negate spirit	 */
    if (c[NEGATESPIRIT] || c[SPIRITPRO])
	if ((mster == POLTERGEIST) || (mster == SPIRITNAGA))
	    return;
 /* 	if undead and cube of undead control	 */
    if (c[CUBEofUNDEAD] || c[UNDEADPRO])
	if ((mster == VAMPIRE) || (mster == WRAITH) || (mster == ZOMBIE))
	    return;
    if ((know[x][y] & 1) == 0) {
	know[x][y] = 1;
	show1cell(x, y);
    }
    bias =(c[HARDGAME]) + 1;
    hitflag = hit2flag = hit3flag = 1;
    yrepcount = 0;
    cursors();
    ifblind(x, y);
    if (c[INVISIBILITY])
	if (rnd(33) < 20) {
	    lprintf("\nThe %s misses wildly", lastmonst);
	    return;
	}
    if (c[CHARMCOUNT])
	if (rnd(30) + 5 * monster[mster].level - c[CHARISMA] < 30) {
	    lprintf("\nThe %s is awestruck at your magnificence!", lastmonst);
	    return;
	}
    if (mster == BAT)
	dam = 1;
    else {
	dam = monster[mster].damage;
	dam += rnd((int)((dam < 1) ? 1 : dam)) + monster[mster].level;
    }
    tmp = 0;
    if (monster[mster].attack > 0)
	if (((dam + bias + 8) > c[AC]) || (rnd((int)((c[AC] > 0) ? c[AC] : 1)) == 1)) {
	    if (spattack(monster[mster].attack, x, y)) {
		flushall();
		return;
	    }
	    tmp = 1;
	    bias -= 2;
	    cursors();
	}
    if (((dam + bias) > c[AC]) || (rnd((int)((c[AC] > 0) ? c[AC] : 1)) == 1)) {
	lprintf("\n  The %s hit you ", lastmonst);
	tmp = 1;
	if ((dam -= c[AC]) < 0)
	    dam = 0;
	if (dam > 0) {
	    losehp(dam);
	    bottomhp();
	    flushall();
	}
    }
    if (tmp == 0)
	lprintf("\n  The %s missed ", lastmonst);
}

/*
 *	dropsomething(monst) 	Function to create an object when a monster dies
 *		int monst;
 *
 *	Function to create an object near the player when certain monsters are killed
 *	Enter with the monster number
 *	Returns nothing of value.
 */
dropsomething(monst)
int     monst;
{
    switch(monst) {
	case ORC: 
	case NYMPH: 
	case ELF: 
	case TROGLODYTE: 
	case TROLL: 
	case ROTHE: 
	case VIOLETFUNGI: 
	case PLATINUMDRAGON: 
	case GNOMEKING: 
	case REDDRAGON: 
	    something(level);
	    return;

	case LEPRECHAUN: 
	    if (rnd(101) >= 75)
		creategem();
	    if (rnd(5) == 1)
		dropsomething(LEPRECHAUN);
	    return;
    }
}

/*
 *	dropgold(amount) 	Function to drop some gold around player
 *		int amount;
 *
 *	Enter with the number of gold pieces to drop
 *	Returns nothing of value.
 */
dropgold(amount)
register int    amount;
{
    if (amount > 250)
	createitem(OMAXGOLD, amount / 100);
    else
	createitem(OGOLDPILE, amount);
}

/*
 *	something(level) 	Function to create a random item around player
 *		int level;
 *
 *	Function to create an item from a designed probability around player
 *	Enter with the cave level on which something is to be dropped
 *	Returns nothing of value.
 */
something(level)
int     level;
{
    register int    j;
    int     i;
    if (level < 0 || level > MAXLEVEL + MAXVLEVEL)
	return;			/* correct level? */
    if (rnd(101) < 8)
	something(level);	/* possibly more than one item */
    j = newobject(level, &i);
    createitem(j, i);
}

/*
 *	newobject(lev,i) 	Routine to return a randomly selected new object
 *		int lev,*i;
 *
 *	Routine to return a randomly selected object to be created
 *	Returns the object number created, and sets *i for its argument
 *	Enter with the cave level and a pointer to the items arg
 */
static char nobjtab[] = {
    0, OSCROLL, OSCROLL, OSCROLL, OSCROLL, OPOTION,
    OPOTION, OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE,
    OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER, OLEATHER, OLEATHER,
    OLEATHER, OREGENRING, OPROTRING, OENERGYRING, ODEXRING, OSTRRING, OSPEAR,
    OBELT, ORING, OSTUDLEATHER, OSHIELD, OFLAIL, OCHAIN, O2SWORD, OPLATE,
    OLONGSWORD
};

newobject(lev, i)
register int    lev,
               *i;
{
    register int    tmp = 32,
                    j;
    if (level < 0 || level > MAXLEVEL + MAXVLEVEL)
	return(0);		/* correct level? */
    if (lev > 6)
	tmp = 37;
    else
	if (lev > 4)
	    tmp = 35;
    j = nobjtab[tmp = rnd(tmp)];/* the object type */
    switch(tmp) {
	case 1: 
	case 2: 
	case 3: 
	case 4: 
	    *i = newscroll();
	    break;
	case 5: 
	case 6: 
	case 7: 
	case 8: 
	    *i = newpotion();
	    break;
	case 9: 
	case 10: 
	case 11: 
	case 12: 
	    *i = rnd((lev + 1) * 10) + lev * 10 + 10;
	    break;
	case 13: 
	case 14: 
	case 15: 
	case 16: 
	    *i = lev;
	    break;
	case 17: 
	case 18: 
	case 19: 
	    if (!(*i = newdagger()))
		return(0);
	    break;
	case 20: 
	case 21: 
	case 22: 
	    if (!(*i = newleather()))
		return(0);
	    break;
	case 23: 
	case 32: 
	case 35: 
	    *i = rund(lev / 3 + 1);
	    break;
	case 24: 
	case 26: 
	    *i = rnd(lev / 4 + 1);
	    break;
	case 25: 
	    *i = rund(lev / 4 + 1);
	    break;
	case 27: 
	    *i = rnd(lev / 2 + 1);
	    break;
	case 30: 
	case 33: 
	    *i = rund(lev / 2 + 1);
	    break;
	case 28: 
	    *i = rund(lev / 3 + 1);
	    if (*i == 0)
		return(0);
	    break;
	case 29: 
	case 31: 
	    *i = rund(lev / 2 + 1);
	    if (*i == 0)
		return(0);
	    break;
	case 34: 
	    *i = newchain();
	    break;
	case 36: 
	    *i = newplate();
	    break;
	case 37: 
	    *i = newsword();
	    break;
    }
    return(j);
}

/*
 *  spattack(atckno,xx,yy) 	Function to process special attacks from monsters
 *  	int atckno,xx,yy;
 *
 *	Enter with the special attack number, and the coordinates(xx,yy)
 *		of the monster that is special attacking
 *	Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise
 *
 * atckno   monster     effect
 * ---------------------------------------------------
 *	0	none
 *	1	rust monster	eat armor
 *	2	hell hound		breathe light fire
 *	3	dragon			breathe fire
 *	4	giant centipede	weakening sing
 *	5	white dragon	cold breath
 *	6	wraith			drain level
 *	7	waterlord		water gusher
 *	8	leprechaun		steal gold
 *	9	disenchantress	disenchant weapon or armor
 *	10	ice lizard		hits with barbed tail
 *	11	umber hulk		confusion
 *	12	spirit naga		cast spells	taken from special attacks
 *	13	platinum dragon	psionics
 *	14	nymph			steal objects
 *	15	bugbear			bite
 *	16	osequip			bite
 *
 *	char rustarm[ARMORTYPES][2];
 *	special array for maximum rust damage to armor from rustmonster
 *	format is: { armor type , minimum attribute 
 */
#define ARMORTYPES 6
static char rustarm[ARMORTYPES][2] = {
    OSTUDLEATHER, -2, ORING, -4, OCHAIN, -5,
    OSPLINT, -6, OPLATE, -8, OPLATEARMOR, -9
};
static char spsel[] = {
    1, 2, 3, 5, 6, 8, 9, 11, 13, 14
};
spattack(x, xx, yy)
int     x,
        xx,
        yy;
{
    register int    i,
                    j = 0,
                    k,
                    m;
    register char  *p = 0;
    if (c[CANCELLATION])
	return(0);
    vxy(&xx, &yy);		/* verify x & y coordinates */
    switch(x) {
	case 1: 		/* rust your armor, j=1 when rusting has occurred */
	    m = k = c[WEAR];
	    if ((i = c[SHIELD]) != -1)
		if (--ivenarg[i] < -1)
		    ivenarg[i] = -1;
		else
		    j = 1;
	    if ((j == 0) && (k != -1)) {
		m = iven[k];
		for (i = 0; i < ARMORTYPES; i++)
		    if (m == rustarm[i][0]) {/* find his armor in table */
			if (--ivenarg[k] < rustarm[i][1])
			    ivenarg[k] = rustarm[i][1];
			else
			    j = 1;
			break;
		    }
	    }
	    if (j == 0)		/* if rusting did not occur */
		switch(m) {
		    case OLEATHER: 
			p = "\nThe %s hit you -- Your lucky you have leather on";
			break;
		    case OSSPLATE: 
			p = "\nThe %s hit you -- Your fortunate to have stainless steel armor!";
			break;
		}
	    else {
		beep();
		p = "\nThe %s hit you -- your armor feels weaker";
	    }
	    break;

	case 2: 
	    i = rnd(15) + 8 - c[AC];
    spout: 
	    p = "\nThe %s breathes fire at you!";
	    if (c[FIRERESISTANCE])
		p = "\nThe %s's flame doesn't phase you!";
	    else
	spout2: 
		if (p) {
		    lprintf(p, lastmonst);
		    beep();
		}
	    checkloss(i);
	    return(0);

	case 3: 
	    i = rnd(20) + 25 - c[AC];
	    goto spout;

	case 4: 
	    if (c[STRENGTH] > 3) {
		p = "\nThe %s stung you!  You feel weaker";
		beep();
		--c[STRENGTH];
	    }
	    else
		p = "\nThe %s stung you!";
	    break;

	case 5: 
	    p = "\nThe %s blasts you with his cold breath";
	    i = rnd(15) + 18 - c[AC];
	    goto spout2;

	case 6: 
	    lprintf("\nThe %s drains you of your life energy!", lastmonst);
	    loselevel();
	    beep();
	    return(0);

	case 7: 
	    p = "\nThe %s got you with a gusher!";
	    i = rnd(15) + 25 - c[AC];
	    goto spout2;

	case 8: 
	    if (c[NOTHEFT])
		return(0);	/* he has a device of no theft */
	    if (c[GOLD]) {
		p = "\nThe %s hit you -- Your purse feels lighter";
		if (c[GOLD] > 32767)
		    c[GOLD] >>= 1;
		else
		    c[GOLD] -= rnd((int)(1 +(c[GOLD] >> 1)));
		if (c[GOLD] < 0)
		    c[GOLD] = 0;
	    }
	    else
		p = "\nThe %s couldn't find any gold to steal";
	    lprintf(p, lastmonst);
	    disappear(xx, yy);
	    beep();
	    bottomgold();
	    return(1);

	case 9: 
	    for (j = 50;;) {	/* disenchant */
		i = rund(26);
		m = iven[i];	/* randomly select item */
		if (m > 0 && ivenarg[i] > 0 && m != OSCROLL && m != OPOTION) {
		    if ((ivenarg[i] -= 3) < 0)
			ivenarg[i] = 0;
		    lprintf("\nThe %s hits you -- you feel a sense of loss", lastmonst);
		    srcount = 0;
		    beep();
		    show3(i);
		    bottomline();
		    return(0);
		}
		if (--j <= 0) {
		    p = "\nThe %s nearly misses";
		    break;
		}
		break;
	    }
	    break;

	case 10: 
	    p = "\nThe %s hit you with his barbed tail";
	    i = rnd(25) - c[AC];
	    goto spout2;

	case 11: 
	    p = "\nThe %s has confused you";
	    beep();
	    c[CONFUSE] += 10 + rnd(10);
	    break;

	case 12: 		/* 	performs any number of other special attacks	 */
	    return(spattack(spsel[rund(10)], xx, yy));

	case 13: 
	    p = "\nThe %s flattens you with his psionics!";
	    i = rnd(15) + 30 - c[AC];
	    goto spout2;

	case 14: 
	    if (c[NOTHEFT])
		return(0);	/* he has device of no theft */
	    if (emptyhanded() == 1) {
		p = "\nThe %s couldn't find anything to steal";
		break;
	    }
	    lprintf("\nThe %s picks your pocket and takes:", lastmonst);
	    beep();
	    if (stealsomething() == 0)
		lprcat("  nothing");
	    disappear(xx, yy);
	    bottomline();
	    return(1);

	case 15: 
	    i = rnd(10) + 5 - c[AC];
    spout3: 
	    p = "\nThe %s bit you!";
	    goto spout2;

	case 16: 
	    i = rnd(15) + 10 - c[AC];
	    goto spout3;
    };
    if (p) {
	lprintf(p, lastmonst);
	bottomline();
    }
    return(0);
}

/*
 *	checkloss(x) 	Routine to subtract hp from user and flag bottomline display
 *		int x;
 *
 *	Routine to subtract hitpoints from the user and flag the bottomline display
 *	Enter with the number of hit points to lose
 *	Note: if x > c[HP] this routine could kill the player!
 */
checkloss(x)
int     x;
{
    if (x > 0) {
	losehp(x);
	bottomhp();
    }
}

/*
 *	annihilate() 	Routine to annihilate all monsters around player(playerx,playery)
 *
 *	Gives player experience, but no dropped objects
 *	Returns the experience gained from all monsters killed
 */
annihilate()
{
    int     i,j;
    register long   k;
    register char  *p;

    for (k = 0, i = playerx - 1; i <= playerx + 1; i++)
	for (j = playery - 1; j <= playery + 1; j++)
	    if (!vxy(&i, &j))	/* if not out of bounds */
		if (*(p = &mitem[i][j]))/* if a monster there */
		    if (*p < DEMONLORD + 2) {
			k += monster[*p].experience;
			*p = know[i][j] = 0;
		    }
		    else {
			lprintf("\nThe %s barely escapes being annihilated!", monster[*p].name);
			hitp[i][j] =(hitp[i][j] >> 1) + 1;/* lose half hit points */
		    }
    if (k > 0) {
	lprcat("\nYou hear loud screams of agony!");
	raiseexperience((long) k);
    }
    return(k);
}

/*
 *	newsphere(x,y,dir,lifetime)  Function to create a new sphere of annihilation
 *		int x,y,dir,lifetime;
 *
 *	Enter with the coordinates of the sphere in x,y
 *	  the direction(0-8 diroffx format) in dir, and the lifespan of the
 *	  sphere in lifetime(in turns)
 *	Returns the number of spheres currently in existence
 */
newsphere(x, y, dir, life)
int     x,
        y,
        dir,
        life;
{
    int     m;
    struct sphere  *sp;
    if (((sp =(struct sphere  *) malloc(sizeof(struct sphere)))) == 0)
	                                                            return(c[SPHCAST]);/* can't malloc, therefore failure */
    if (dir >= 9)
	dir = 0;		/* no movement if direction not found */
    if (level == 0)
	vxy(&x, &y);		/* don't go out of bounds */
    else {
	if (x < 1)
	    x = 1;
	if (x >= MAXX - 1)
	    x = MAXX - 2;
	if (y < 1)
	    y = 1;
	if (y >= MAXY - 1)
	    y = MAXY - 2;
    }
    if ((m = mitem[x][y]) >= DEMONLORD + 4) {/* demons dispel spheres */
	know[x][y] = 1;
	show1cell(x, y);	/* show the demon(ha ha) */
	cursors();
	lprintf("\nThe %s dispels the sphere!", monster[m].name);
	beep();
	rmsphere(x, y);	/* remove any spheres that are here */
	return(c[SPHCAST]);
    }
    if (m == DISENCHANTRESS) {	/* disenchantress cancels spheres */
	cursors();
	lprintf("\nThe %s causes cancellation of the sphere!", monster[m].name);
	beep();
boom: 
	sphboom(x, y);		/* blow up stuff around sphere */
	rmsphere(x, y);	/* remove any spheres that are here */
	return(c[SPHCAST]);
    }
    if (c[CANCELLATION]) {	/* cancellation cancels spheres */
	cursors();
	lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!");
	beep();
	goto boom;
    }
    if (item[x][y] == OANNIHILATION) {/* collision of spheres detonates spheres */
	cursors();
	lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!");
	beep();
	rmsphere(x, y);
	goto boom;
    }
    if (playerx == x && playery == y) {/* collision of sphere and player! */
	cursors();
	lprcat("\nYou have been enveloped by the zone of nothingness!\n");
	beep();
	rmsphere(x, y);	/* remove any spheres that are here */
	nap(4000);
	died(258);
    }
    item[x][y] = OANNIHILATION;
    mitem[x][y] = 0;
    know[x][y] = 1;
    show1cell(x, y);		/* show the new sphere */
    sp -> x = x;
    sp -> y = y;
    sp -> lev = level;
    sp -> dir = dir;
    sp -> lifetime = life;
    sp -> p = 0;
    if (spheres == 0)
	spheres = sp;		/* if first node in the sphere list */
    else {			/* add sphere to beginning of linked list */
	sp -> p = spheres;
	spheres = sp;
    }
    return(++c[SPHCAST]);	/* one more sphere in the world */
}

/*
 *	rmsphere(x,y)		Function to delete a sphere of annihilation from list
 *		int x,y;
 *
 *	Enter with the coordinates of the sphere(on current level)
 *	Returns the number of spheres currently in existence
 */
rmsphere(x, y)
int     x,y;
{
    register struct sphere *sp,*sp2 = 0;

    for (sp = spheres; sp; sp2 = sp, sp = sp -> p)
	if (level == sp -> lev)	/* is sphere on this level? */
	    if ((x == sp -> x) && (y == sp -> y)) {/* locate sphere at this location */
		item[x][y] = mitem[x][y] = 0;
		know[x][y] = 1;
		show1cell(x, y);/* show the now missing sphere */
		--c[SPHCAST];
		if (sp == spheres) {
		    sp2 = sp;
		    spheres = sp -> p;
		    free((char *) sp2);
		}
		else {
		    sp2 -> p = sp -> p;
		    free((char *) sp);
		}
		break;
	    }
    return(c[SPHCAST]);	/* return number of spheres in the world */
}

/*
 *	sphboom(x,y)	Function to perform the effects of a sphere detonation
 *		int x,y;
 *
 *	Enter with the coordinates of the blast, Returns no value
 */
sphboom(x, y)
int     x,
        y;
{
    register int    i,
                    j;
    if (c[HOLDMONST])
	c[HOLDMONST] = 1;
    if (c[CANCELLATION])
	c[CANCELLATION] = 1;
    for (j = max(1, x - 2); j < min(x + 3, MAXX - 1); j++)
	for (i = max(1, y - 2); i < min(y + 3, MAXY - 1); i++) {
	    item[j][i] = mitem[j][i] = 0;
	    show1cell(j, i);
	    if (playerx == j && playery == i) {
		cursors();
		beep();
		lprcat("\nYou were too close to the sphere!");
		nap(3000);
		died(283);	/* player killed in explosion */
	    }
	}
}

/*
 *	genmonst()		Function to ask for monster and genocide from game
 *
 *	This is done by setting a flag in the monster[] structure
 */
genmonst()
{
    register int    i,j;

    cursors();
    lprcat("\nGenocide what monster? ");
    for (i = 0;(!isalpha(i)) && (i != ' '); i = readchar());
    lprc(i);
    for (j = 0; j < MAXMONST; j++)/* search for the monster type */
	if (monstnamelist[j] == i) {/* have we found it? */
	    monster[j].genocided = 1;/* genocided from game */
	    lprintf("  There will be no more %s's", monster[j].name);
	/* now wipe out monsters on this level */
	    newcavelevel(level);
	    draws(0, MAXX, 0, MAXY);
	    bot_linex();
	    return;
	}
    lprcat("  You sense failure!");
}
SHAR_EOF
if test 45763 -ne "`wc -c < 'monster.c'`"
then
	echo shar: error transmitting "'monster.c'" '(should have been 45763 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'regen.c'" '(3839 characters)'
if test -f 'regen.c'
then
	echo shar: will not over-write existing file "'regen.c'"
else
cat << \SHAR_EOF > 'regen.c'
/* regen.c 			Larn is copyrighted 1986 by Noah Morgan. */
#include "header.h"
/*
	*******
	REGEN()
	*******
	regen()

	subroutine to regenerate player hp and spells
 */
regen () {
    register int    i,
                    flag;
    register long  *d;
    d = c;
#ifdef EXTRA
    d[MOVESMADE]++;
#endif
    if (d[TIMESTOP]) {
	if (--d[TIMESTOP] <= 0)
	    bottomline ();
	return;
    }				/* for stop time spell */
    flag = 0;

    if (d[STRENGTH] < 3) {
	d[STRENGTH] = 3;
	flag = 1;
    }
    if ((d[HASTESELF] == 0) || ((d[HASTESELF] & 1) == 0))
	gtime++;

    if (d[HP] != d[HPMAX])
	if (d[REGENCOUNTER]-- <= 0) {/* 	regenerate hit points	 */
	    d[REGENCOUNTER] = 22 + (d[HARDGAME] << 1) - d[LEVEL];
	    if ((d[HP] += d[REGEN]) > d[HPMAX])
		d[HP] = d[HPMAX];
	    bottomhp ();
	}

    if (d[SPELLS] < d[SPELLMAX])/* 	regenerate spells	 */
	if (d[ECOUNTER]-- <= 0) {
	    d[ECOUNTER] = 100 + 4 * (d[HARDGAME] - d[LEVEL] - d[ENERGY]);
	    d[SPELLS]++;
	    bottomspell ();
	}

    if (d[HERO])
	if (--d[HERO] <= 0) {
	    for (i = 0; i < 6; i++)
		d[i] -= 10;
	    flag = 1;
	}
    if (d[ALTPRO])
	if (--d[ALTPRO] <= 0) {
	    d[MOREDEFENSES] -= 3;
	    flag = 1;
	}
    if (d[PROTECTIONTIME])
	if (--d[PROTECTIONTIME] <= 0) {
	    d[MOREDEFENSES] -= 2;
	    flag = 1;
	}
    if (d[DEXCOUNT])
	if (--d[DEXCOUNT] <= 0) {
	    d[DEXTERITY] -= 3;
	    flag = 1;
	}
    if (d[STRCOUNT])
	if (--d[STRCOUNT] <= 0) {
	    d[STREXTRA] -= 3;
	    flag = 1;
	}
    if (d[BLINDCOUNT])
	if (--d[BLINDCOUNT] <= 0) {
	    cursors ();
	    lprcat ("\nThe blindness lifts  ");
	    beep ();
	}
    if (d[CONFUSE])
	if (--d[CONFUSE] <= 0) {
	    cursors ();
	    lprcat ("\nYou regain your senses");
	    beep ();
	}
    if (d[GIANTSTR])
	if (--d[GIANTSTR] <= 0) {
	    d[STREXTRA] -= 20;
	    flag = 1;
	}
    if (d[CHARMCOUNT])
	if ((--d[CHARMCOUNT]) <= 0)
	    flag = 1;
    if (d[INVISIBILITY])
	if ((--d[INVISIBILITY]) <= 0)
	    flag = 1;
    if (d[CANCELLATION])
	if ((--d[CANCELLATION]) <= 0)
	    flag = 1;
    if (d[WTW])
	if ((--d[WTW]) <= 0)
	    flag = 1;
    if (d[HASTESELF])
	if ((--d[HASTESELF]) <= 0)
	    flag = 1;
    if (d[AGGRAVATE])
	--d[AGGRAVATE];
    if (d[SCAREMONST])
	if ((--d[SCAREMONST]) <= 0)
	    flag = 1;
    if (d[STEALTH])
	if ((--d[STEALTH]) <= 0)
	    flag = 1;
    if (d[AWARENESS])
	--d[AWARENESS];
    if (d[HOLDMONST])
	if ((--d[HOLDMONST]) <= 0)
	    flag = 1;
    if (d[HASTEMONST])
	--d[HASTEMONST];
    if (d[FIRERESISTANCE])
	if ((--d[FIRERESISTANCE]) <= 0)
	    flag = 1;
    if (d[GLOBE])
	if (--d[GLOBE] <= 0) {
	    d[MOREDEFENSES] -= 10;
	    flag = 1;
	}
    if (d[SPIRITPRO])
	if (--d[SPIRITPRO] <= 0)
	    flag = 1;
    if (d[UNDEADPRO])
	if (--d[UNDEADPRO] <= 0)
	    flag = 1;
    if (d[HALFDAM])
	if (--d[HALFDAM] <= 0) {
	    cursors ();
	    lprcat ("\nYou now feel better ");
	    beep ();
	}
    if (d[SEEINVISIBLE])
	if (--d[SEEINVISIBLE] <= 0) {
	    monstnamelist[INVISIBLESTALKER] = ' ';
	    cursors ();
	    lprcat ("\nYou feel your vision return to normal");
	    beep ();
	}
    if (d[ITCHING]) {
	if (d[ITCHING] > 1)
	    if ((d[WEAR] != -1) || (d[SHIELD] != -1))
		if (rnd (100) < 50) {
		    d[WEAR] = d[SHIELD] = -1;
		    cursors ();
		    lprcat ("\nThe hysteria of itching forces you to remove your armor!");
		    beep ();
		    recalc ();
		    bottomline ();
		}
	if (--d[ITCHING] <= 0) {
	    cursors ();
	    lprcat ("\nYou now feel the irritation subside!");
	    beep ();
	}
    }
    if (d[CLUMSINESS]) {
	if (d[WIELD] != -1)
	    if (d[CLUMSINESS] > 1)
		if (item[playerx][playery] == 0)/* only if nothing there */
		    if (rnd (100) < 33)/* drop your weapon due to clumsiness */
			drop_object ((int) d[WIELD]);
	if (--d[CLUMSINESS] <= 0) {
	    cursors ();
	    lprcat ("\nYou now feel less awkward!");
	    beep ();
	}
    }
    if (flag)
	bottomline ();
}
SHAR_EOF
if test 3839 -ne "`wc -c < 'regen.c'`"
then
	echo shar: error transmitting "'regen.c'" '(should have been 3839 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'savelev.c'" '(852 characters)'
if test -f 'savelev.c'
then
	echo shar: will not over-write existing file "'savelev.c'"
else
cat << \SHAR_EOF > 'savelev.c'

/* savelev.c		 Larn is copyrighted 1986 by Noah Morgan. */

#include "header.h"

/*
 *	routine to save the present level into storage
 */
savelevel ()
{
    register int x,y,t;

    t = level * (MAXX*MAXY);
    for (x = 0; x < MAXX; x++) {
	t += MAXY;
	for (y = 0; y < MAXY; y++) {
	    cell[t+y].item  = item[x][y];
	    cell[t+y].iarg  = iarg[x][y];
	    cell[t+y].know  = know[x][y];
	    cell[t+y].mitem = mitem[x][y];
	    cell[t+y].hitp  = hitp[x][y];
	}
    }
}


/*
 *	routine to restore a level from storage
 */
getlevel ()
{
    register int x,y,t;

    t = level * (MAXX*MAXY);
    for (x = 0; x < MAXX; x++) {
	t += MAXY;
	for (y = 0; y < MAXY; y++) {
	    item[x][y]  = cell[t+y].item;
	    iarg[x][y]  = cell[t+y].iarg;
	    know[x][y]  = cell[t+y].know;
	    mitem[x][y] = cell[t+y].mitem;
	    hitp[x][y]  = cell[t+y].hitp;
	}
    }
}
SHAR_EOF
if test 852 -ne "`wc -c < 'savelev.c'`"
then
	echo shar: error transmitting "'savelev.c'" '(should have been 852 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'signal.c'" '(2848 characters)'
if test -f 'signal.c'
then
	echo shar: will not over-write existing file "'signal.c'"
else
cat << \SHAR_EOF > 'signal.c'

#include <signal.h>
#include "header.h"	/* "Larn is copyrighted 1986 by Noah Morgan.\n" */

#define BIT(a)(1<<((a)-1))

/* text to be displayed if ^C during intro screen */
static  s2choose()
{
    cursor(1, 24);
    lprcat("Press ");
    setbold();
    lprcat("return");
    resetbold();
    lprcat(" to continue: ");
    lflush();
}

/* what to do for a ^C */
static cntlc()
{
    if (nosignal)
        return;		/* don't do anything if inhibited */
    signal(SIGQUIT, SIG_IGN);
    signal(SIGINT, SIG_IGN);
    quit();
    if (predostuff == 1)
	s2choose();
    else
	showplayer();
    lflush();
    signal(SIGQUIT, cntlc);
    signal(SIGINT, cntlc);
}


/*
 *	subroutine to save the game if a hangup signal
 */
static sgam()
{
    savegame(savefilename);
    wizard = 1;
    died(-257);    /* hangup signal */
}


/*
 *    subroutine to issue the needed signal traps -  called from main()
 */
static sigill()
{
    sigpanic(SIGILL);
}

static sigtrap()
{
    sigpanic(SIGTRAP);
}

static sigiot()
{
    sigpanic(SIGIOT);
}

static  sigemt()
{
    sigpanic(SIGEMT);
}

static  sigfpe()
{
    sigpanic(SIGFPE);
}

static  sigbus()
{
    sigpanic(SIGBUS);
}

static  sigsegv()
{
    sigpanic(SIGSEGV);
}

static  sigsys()
{
    sigpanic(SIGSYS);
}

static  sigpipe()
{
    sigpanic(SIGPIPE);
}

static  sigterm()
{
    sigpanic(SIGTERM);
}

sigsetup() {
    signal(SIGQUIT, cntlc);
    signal(SIGINT, cntlc);
    signal(SIGKILL, SIG_IGN);
    signal(SIGHUP, sgam);
    signal(SIGILL, sigill);
    signal(SIGTRAP, sigtrap);
    signal(SIGIOT, sigiot);
    signal(SIGEMT, sigemt);
    signal(SIGFPE, sigfpe);
    signal(SIGBUS, sigbus);
    signal(SIGSEGV, sigsegv);
    signal(SIGSYS, sigsys);
    signal(SIGPIPE, sigpipe);
    signal(SIGTERM, sigterm);
}

static char *signame[NSIG] = {
    "",
    "SIGHUP",	/* 1	 hangup */
    "SIGINT",	/* 2	 interrupt */
    "SIGQUIT",	/* 3	 quit */
    "SIGILL",	/* 4	 illegal instruction(not reset when caught) */
    "SIGTRAP",	/* 5	 trace trap(not reset when caught) */
    "SIGIOT",	/* 6	 IOT instruction */
    "SIGEMT",	/* 7	 EMT instruction */
    "SIGFPE",	/* 8	 floating point exception */
    "SIGKILL",	/* 9	 kill(cannot be caught or ignored) */
    "SIGBUS",	/* 10	 bus error */
    "SIGSEGV",	/* 11	 segmentation violation */
    "SIGSYS",	/* 12	 bad argument to system call */
    "SIGPIPE",	/* 13	 write on a pipe with no one to read it */
    "SIGALRM",	/* 14	 alarm clock */
    "SIGTERM"	/* 15	 software termination signal from kill */
};

/*
 *	routine to process a fatal error signal
 */
static sigpanic(sig)
int sig;
{
    char buf[128];

    signal(sig, SIG_DFL);
    sprintf(buf, "\nLarn - Panic! Signal %d received [%s]", sig, signame[sig]);
    write(2, buf, strlen(buf));
    sleep(2);
    sncbr();
    savegame(savefilename);
    kill(getpid(), sig);	/* this will terminate us */
}
SHAR_EOF
if test 2848 -ne "`wc -c < 'signal.c'`"
then
	echo shar: error transmitting "'signal.c'" '(should have been 2848 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'tok.c'" '(5032 characters)'
if test -f 'tok.c'
then
	echo shar: will not over-write existing file "'tok.c'"
else
cat << \SHAR_EOF > 'tok.c'


/* tok.c		Larn is copyrighted 1986 by Noah Morgan. */

#include "header.h"

static char lastok = 0;
globaldef int yrepcount = 0,dayplay = 0;

#define MAXUM 52	/* maximum number of user re-named monsters */
#define MAXMNAME 40	/* max length of a monster re-name */
static char usermonster[MAXUM][MAXMNAME];/* the user named monster name goes here */
static char usermpoint = 0;	/* the user monster pointer */

/*
	lexical analyzer for larn
 */
yylex ()
{
    char cc;
    int  ic;

    if (hit2flag) {
	hit2flag = 0;
	yrepcount = 0;
	return (' ');
    }
    if (yrepcount > 0) {
	--yrepcount;
	return (lastok);
    } else
	yrepcount = 0;
    if (yrepcount == 0) {
	bottomdo ();
	showplayer ();
    }				/* 	show where the player is	 */
    lflush ();
    while (1) {
	c[BYTESIN]++;
	if (ckpflag)	/* check for periodic checkpointing */
	    if ((c[BYTESIN] % 400) == 0) {
		savegame (ckpfile);

#ifdef TIMECHECK
		if (dayplay == 0)
		    if (playable ()) {
			cursor (1, 19);
			lprcat ("\nSorry, but it is now time for work.  Your game has been saved.\n");
			beep ();
			lflush ();
			savegame (savefilename);
			wizard = nomove = 1;
			sleep (4);
			died (-257);
		    }
#endif TIMECHECK

	    }

	if ((cc = KeySense(0)) == -1)
	    return (lastok = -1);

	if (cc == 'Y' - 64) {	/* control Y -- shell escape */
	    resetscroll ();
	    clear();	/* scrolling region, home, clear, no attributes */
	    system(0);

	    setscroll ();
	    return (lastok = 'L' - 64);		/* redisplay screen */
	}

	if ((cc <= '9') && (cc >= '0')) {
	    yrepcount = yrepcount * 10 + cc - '0';
	} else {
	    if (yrepcount > 0)
		--yrepcount;
	    return (lastok = cc);
	}
    }
}


/*
 *	flushall()	Function to flush all type-ahead in the input buffer
 */
flushall ()
{
    /* if keyboard input buffer is too big, flush some of it */
    while (KeySense(0) >= 0);
}


/*
	function to set the desired hardness 
	enter with hard= -1 for default hardness, else any desired hardness
 */
sethard (hard)
int hard;
{
    register int    j,k,i;

    j = c[HARDGAME];
    hashewon ();
    if (restorflag == 0) {	/* don't set c[HARDGAME] if restoring game */
	if (hard >= 0)
	    c[HARDGAME] = hard;
    } else
	c[HARDGAME] = j;	/* set c[HARDGAME] to proper value if restoring game */

    if (k = c[HARDGAME])
	for (j = 0; j <= MAXMONST + 8; j++) {
	    i = ((6 + k) * monster[j].hitpoints + 1) / 6;
	    monster[j].hitpoints = (i < 0) ? 32767 : i;
	    i = ((6 + k) * monster[j].damage + 1) / 5;
	    monster[j].damage = (i > 127) ? 127 : i;
	    i = (10 * monster[j].gold) / (10 + k);
	    monster[j].gold = (i > 32767) ? 32767 : i;
	    i = monster[j].armorclass - k;
	    monster[j].armorclass = (i < -127) ? -127 : i;
	    i = (7 * monster[j].experience) / (7 + k) + 1;
	    monster[j].experience = (i <= 0) ? 1 : i;
	}
}


/*
	function to read and process the larn options file
 */
readopts ()
{
    register char  *i;
    register int    j,k;
    int flag = 1;	/* set to 0 if he specifies a name for his character */

    if (lopen (optsfile) < 0) {
	strcpy (logname, loginname);
	return;			/* user name if no character name */
    }
    i = " ";
    while (*i) {
	if ((i = (char *) lgetw ()) == 0)
	    break;		/* check for EOF */
	while ((*i == ' ') || (*i == '\t'))
	    i++;		/* eat leading whitespace */
	switch (*i) {
	    case 'b': 
		if (strcmp (i, "bold-objects") == 0)
		    boldon = 1;
		break;

	    case 'e': 
		if (strcmp (i, "enable-checkpointing") == 0)
		    ckpflag = 1;
		break;

	    case 'i': 
		if (strcmp (i, "inverse-objects") == 0)
		    boldon = 0;
		break;

	    case 'f': 
		if (strcmp (i, "female") == 0)
		    sex = 0;	/* male or female */
		break;

	    case 'm': 
		if (strcmp (i, "monster:") == 0) {/* name favorite monster */
		    if ((i = lgetw ()) == 0)
			break;
		    if (strlen (i) >= MAXMNAME)
			i[MAXMNAME - 1] = 0;
		    strcpy (usermonster[usermpoint], i);
		    if (usermpoint >= MAXUM)
			break;	/* defined all of em */
		    if (isalpha (j = usermonster[usermpoint][0])) {
			for (k = 1; k < MAXMONST + 8; k++)/* find monster */
			    if (monstnamelist[k] == j) {
				monster[k].name = &usermonster[usermpoint++][0];
				break;
			    }
		    }
		} else
		    if (strcmp (i, "male") == 0)
			sex = 1;
		break;

	    case 'n': 
		if (strcmp (i, "name:") == 0) {/* defining players name */
		    if ((i = lgetw ()) == 0)
			break;
		    if (strlen (i) >= LOGNAMESIZE)
			i[LOGNAMESIZE - 1] = 0;
		    strcpy (logname, i);
		    flag = 0;
		} else
		    if (strcmp (i, "no-introduction") == 0)
			nowelcome = 1;
		    else
			if (strcmp (i, "no-beep") == 0)
			    nobeep = 1;
		break;

	    case 'p': 
		if (strcmp (i, "play-day-play") == 0)
		    dayplay = 1;
		break;

	    case 's': 
		if (strcmp (i, "savefile:") == 0) {/* defining savefilename */
		    if ((i = lgetw ()) == 0)
			break;
		    if (strlen (i) >= SAVEFILENAMESIZE)/* avoid overflow */
			i[SAVEFILENAMESIZE - 1] = 0;
		    strcpy (savefilename, i);
		    flag = 0;
		}
		break;
	};
    }
    if (flag)
	strcpy (logname, loginname);
}
SHAR_EOF
if test 5032 -ne "`wc -c < 'tok.c'`"
then
	echo shar: error transmitting "'tok.c'" '(should have been 5032 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

u566393908ea@ucdavis.UUCP (u566393908ea) (08/31/86)

Hello all!  This is a port of Larn v12.0 to VAX/VMS.  Now everyone can save
his/her daughter!!  Just unpack using /bin/sh and read readme.txt.

                                                - Mark Nagel

P.S.  Thanks to Lord Kahless for letting me post this!



-------------------------------cut here-------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	object.c
#	scores.c
#	store.c
# This archive created: Sat Aug 30 14:53:02 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'object.c'" '(28817 characters)'
if test -f 'object.c'
then
	echo shar: will not over-write existing file "'object.c'"
else
cat << \SHAR_EOF > 'object.c'

/*	object.c		Larn is copyrighted 1986 by Noah Morgan. */

#include "header.h"

/*
	***************
	LOOK_FOR_OBJECT
	***************

	subroutine to look for an object and give the player his options
	if an object was found.
 */

lookforobject ()
{
    register int i,j;

    if (c[TIMESTOP])
	return;			/* can't find objects is time is stopped */
    i = item[playerx][playery];
    if (i == 0)
	return;
    showcell (playerx, playery);
    cursors ();
    yrepcount = 0;
    switch (i) {
	case OGOLDPILE: 
	case OMAXGOLD: 
	case OKGOLD: 
	case ODGOLD: 
	    lprcat ("\n\nYou have found some gold!");
	    ogold (i);
	    break;

	case OPOTION: 
	    lprcat ("\n\nYou have found a magic potion");
	    i = iarg[playerx][playery];
	    if (potionname[i][0])
		lprintf (" of %s", &potionname[i][1]);
	    opotion (i);
	    break;

	case OSCROLL: 
	    lprcat ("\n\nYou have found a magic scroll");
	    i = iarg[playerx][playery];
	    if (scrollname[i][0])
		lprintf (" of %s", &scrollname[i][1]);
	    oscroll (i);
	    break;

	case OALTAR: 
	    if (nearbymonst ())
		return;
	    lprcat ("\n\nThere is a Holy Altar here!");
	    oaltar ();
	    break;

	case OBOOK: 
	    lprcat ("\n\nYou have found a book.");
	    obook ();
	    break;

	case OCOOKIE: 
	    lprcat ("\n\nYou have found a fortune cookie.");
	    ocookie ();
	    break;

	case OTHRONE: 
	    if (nearbymonst ())
		return;
	    lprintf ("\n\nThere is %s here!", objectname[i]);
	    othrone (0);
	    break;

	case OTHRONE2: 
	    if (nearbymonst ())
		return;
	    lprintf ("\n\nThere is %s here!", objectname[i]);
	    othrone (1);
	    break;

	case ODEADTHRONE: 
	    lprintf ("\n\nThere is %s here!", objectname[i]);
	    odeadthrone ();
	    break;

	case OORB: 
	    lprcat ("\n\nYou have found the Orb!!!!!");
	    oorb ();
	    break;

	case OPIT: 
	    lprcat ("\n\nYou're standing at the top of a pit.");
	    opit ();
	    break;

	case OSTAIRSUP: 
	    lprcat ("\n\nThere is a circular staircase here");
	    ostairs (1);	/* up */
	    break;

	case OELEVATORUP: 
	    lprcat ("\n\nYou feel heavy for a moment, but the feeling disappears");
	    oelevator (1);	/*  up  */
	    break;

	case OFOUNTAIN: 
	    if (nearbymonst ())
		return;
	    lprcat ("\n\nThere is a fountain here");
	    ofountain ();
	    break;

	case OSTATUE: 
	    if (nearbymonst ())
		return;
	    lprcat ("\n\nYou are standing in front of a statue");
	    ostatue ();
	    break;

	case OCHEST: 
	    lprcat ("\n\nThere is a chest here");
	    ochest ();
	    break;

	case OIVTELETRAP: 
	    if (rnd (11) < 6)
		return;
	    item[playerx][playery] = OTELEPORTER;
	    know[playerx][playery] = 1;

	case OTELEPORTER: 
	    lprcat ("\nZaaaappp!  You've been teleported!\n");
	    beep ();
	    nap (3000);
	    oteleport (0);
	    break;

	case OSCHOOL: 
	    if (nearbymonst ())
		return;
	    lprcat ("\n\nYou have found the College of Larn.");
	    lprcat ("\nDo you (g) go inside, or (i) stay here? ");
	    i = 0;
	    while ((i != 'g') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if (i == 'g') {
		oschool ();	/* 	the college of larn	 */
	    }
	    else
		lprcat (" stay here");
	    break;

	case OMIRROR: 
	    if (nearbymonst ())
		return;
	    lprcat ("\n\nThere is a mirror here");
	    omirror ();
	    break;

	case OBANK2: 
	case OBANK: 
	    if (nearbymonst ())
		return;
	    if (i == OBANK)
		lprcat ("\n\nYou have found the bank of Larn.");
	    else
		lprcat ("\n\nYou have found a branch office of the bank of Larn.");
	    lprcat ("\nDo you (g) go inside, or (i) stay here? ");
	    j = 0;
	    while ((j != 'g') && (j != 'i') && (j != '\33'))
		j = readchar ();
	    if (j == 'g') {
		if (i == OBANK)
		    obank ();
		else
		    obank2 ();	/*  the bank of larn  */
	    }
	    else
		lprcat (" stay here");
	    break;

	case ODEADFOUNTAIN: 
	    if (nearbymonst ())
		return;
	    lprcat ("\n\nThere is a dead fountain here");
	    break;

	case ODNDSTORE: 
	    if (nearbymonst ())
		return;
	    lprcat ("\n\nThere is a DND store here.");
	    lprcat ("\nDo you (g) go inside, or (i) stay here? ");
	    i = 0;
	    while ((i != 'g') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if (i == 'g')
		dndstore ();	/*  the dnd adventurers store  */
	    else
		lprcat (" stay here");
	    break;

	case OSTAIRSDOWN: 
	    lprcat ("\n\nThere is a circular staircase here");
	    ostairs (-1);	/* down */
	    break;

	case OELEVATORDOWN: 
	    lprcat ("\n\nYou feel light for a moment, but the feeling disappears");
	    oelevator (-1);	/* 	down	 */
	    break;

	case OOPENDOOR: 
	    lprintf ("\n\nYou have found %s", objectname[i]);
	    lprcat ("\nDo you (c) close it");
	    iopts ();
	    i = 0;
	    while ((i != 'c') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if ((i == '\33') || (i == 'i')) {
		ignore ();
		break;
	    }
	    lprcat ("close");
	    forget ();
	    item[playerx][playery] = OCLOSEDDOOR;
	    iarg[playerx][playery] = 0;
	    playerx = lastpx;
	    playery = lastpy;
	    break;

	case OCLOSEDDOOR: 
	    lprintf ("\n\nYou have found %s", objectname[i]);
	    lprcat ("\nDo you (o) try to open it");
	    iopts ();
	    i = 0;
	    while ((i != 'o') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if ((i == '\33') || (i == 'i')) {
		ignore ();
		playerx = lastpx;
		playery = lastpy;
		break;
	    }
	    else {
		lprcat ("open");
		if (rnd (11) < 7) {
		    switch (iarg[playerx][playery]) {
			case 6: 
			    c[AGGRAVATE] += rnd (400);
			    break;

			case 7: 
			    lprcat ("\nYou are jolted by an electric shock ");
			    lastnum = 274;
			    losehp (rnd (20));
			    bottomline ();
			    break;

			case 8: 
			    loselevel ();
			    break;

			case 9: 
			    lprcat ("\nYou suddenly feel weaker ");
			    if (c[STRENGTH] > 3)
				c[STRENGTH]--;
			    bottomline ();
			    break;

			default: 
			    break;
		    }
		    playerx = lastpx;
		    playery = lastpy;
		}
		else {
		    forget ();
		    item[playerx][playery] = OOPENDOOR;
		}
	    }
	    break;

	case OENTRANCE: 
	    lprcat ("\nYou have found ");
	    lprcat (objectname[OENTRANCE]);
	    lprcat ("\nDo you (g) go inside");
	    iopts ();
	    i = 0;
	    while ((i != 'g') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if (i == 'g') {
		newcavelevel (1);
		playerx = 33;
		playery = MAXY - 2;
		item[33][MAXY - 1] = know[33][MAXY - 1] = mitem[33][MAXY - 1] = 0;
		draws (0, MAXX, 0, MAXY);
		bot_linex ();
		return;
	    }
	    else
		ignore ();
	    break;

	case OVOLDOWN: 
	    lprcat ("\nYou have found ");
	    lprcat (objectname[OVOLDOWN]);
	    lprcat ("\nDo you (c) climb down");
	    iopts ();
	    i = 0;
	    while ((i != 'c') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if ((i == '\33') || (i == 'i')) {
		ignore ();
		break;
	    }
	    if (level != 0) {
		lprcat ("\nThe shaft only extends 5 feet downward!");
		return;
	    }
	    if (packweight () > 45 + 3 * (c[STRENGTH] + c[STREXTRA])) {
		lprcat ("\nYou slip and fall down the shaft");
		beep ();
		lastnum = 275;
		losehp (30 + rnd (20));
		bottomhp ();
	    }

	    else
		lprcat ("climb down");
	    nap (3000);
	    newcavelevel (MAXLEVEL);
	    for (i = 0; i < MAXY; i++)
		for (j = 0; j < MAXX; j++)/* put player near volcano shaft */
		    if (item[j][i] == OVOLUP) {
			playerx = j;
			playery = i;
			j = MAXX;
			i = MAXY;
			positionplayer ();
		    }
	    draws (0, MAXX, 0, MAXY);
	    bot_linex ();
	    return;

	case OVOLUP: 
	    lprcat ("\nYou have found ");
	    lprcat (objectname[OVOLUP]);
	    lprcat ("\nDo you (c) climb up");
	    iopts ();
	    i = 0;
	    while ((i != 'c') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if ((i == '\33') || (i == 'i')) {
		ignore ();
		break;
	    }
	    if (level != 11) {
		lprcat ("\nThe shaft only extends 8 feet upwards before you find a blockage!");
		return;
	    }
	    if (packweight () > 45 + 5 * (c[STRENGTH] + c[STREXTRA])) {
		lprcat ("\nYou slip and fall down the shaft");
		beep ();
		lastnum = 275;
		losehp (15 + rnd (20));
		bottomhp ();
		return;
	    }
	    lprcat ("climb up");
	    lflush ();
	    nap (3000);
	    newcavelevel (0);
	    for (i = 0; i < MAXY; i++)
		for (j = 0; j < MAXX; j++)/* put player near volcano shaft */
		    if (item[j][i] == OVOLDOWN) {
			playerx = j;
			playery = i;
			j = MAXX;
			i = MAXY;
			positionplayer ();
		    }
	    draws (0, MAXX, 0, MAXY);
	    bot_linex ();
	    return;

	case OTRAPARROWIV: 
	    if (rnd (17) < 13)
		return;		/* for an arrow trap */
	    item[playerx][playery] = OTRAPARROW;
	    know[playerx][playery] = 0;

	case OTRAPARROW: 
	    lprcat ("\nYou are hit by an arrow");
	    beep ();		/* for an arrow trap */
	    lastnum = 259;
	    losehp (rnd (10) + level);
	    bottomhp ();
	    return;

	case OIVDARTRAP: 
	    if (rnd (17) < 13)
		return;		/* for a dart trap */
	    item[playerx][playery] = ODARTRAP;
	    know[playerx][playery] = 0;

	case ODARTRAP: 
	    lprcat ("\nYou are hit by a dart");
	    beep ();		/* for a dart trap */
	    lastnum = 260;
	    losehp (rnd (5));
	    if ((--c[STRENGTH]) < 3)
		c[STRENGTH] = 3;
	    bottomline ();
	    return;

	case OIVTRAPDOOR: 
	    if (rnd (17) < 13)
		return;		/* for a trap door */
	    item[playerx][playery] = OTRAPDOOR;
	    know[playerx][playery] = 1;

	case OTRAPDOOR: 
	    lastnum = 272;	/* a trap door */
	    if ((level == MAXLEVEL - 1) || (level == MAXLEVEL + MAXVLEVEL - 1)) {
		lprcat ("\nYou fell through a bottomless trap door!");
		beep ();
		nap (3000);
		died (271);
	    }
	    lprcat ("\nYou fall through a trap door!");
	    beep ();		/* for a trap door */
	    losehp (rnd (5 + level));
	    nap (2000);
	    newcavelevel (level + 1);
	    draws (0, MAXX, 0, MAXY);
	    bot_linex ();
	    return;


	case OTRADEPOST: 
	    if (nearbymonst ())
		return;
	    lprcat ("\nYou have found the Larn trading Post.");
	    lprcat ("\nDo you (g) go inside, or (i) stay here? ");
	    i = 0;
	    while ((i != 'g') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if (i == 'g')
		otradepost ();
	    else
		lprcat ("stay here");
	    return;

	case OHOME: 
	    if (nearbymonst ())
		return;
	    lprcat ("\nYou have found your way home.");
	    lprcat ("\nDo you (g) go inside, or (i) stay here? ");
	    i = 0;
	    while ((i != 'g') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if (i == 'g')
		ohome ();
	    else
		lprcat ("stay here");
	    return;

	case OWALL: 
	    break;

	case OANNIHILATION: 
	    died (283);
	    return;		/* annihilated by sphere of annihilation */

	case OLRS: 
	    if (nearbymonst ())
		return;
	    lprcat ("\n\nThere is an LRS office here.");
	    lprcat ("\nDo you (g) go inside, or (i) stay here? ");
	    i = 0;
	    while ((i != 'g') && (i != 'i') && (i != '\33'))
		i = readchar ();
	    if (i == 'g')
		olrs ();	/*  the larn revenue service */
	    else
		lprcat (" stay here");
	    break;

	default: 
	    finditem (i);
	    break;
    };
}

/*
	function to say what object we found and ask if player wants to take it
 */
finditem (itm)
int     itm;
{
    int     tmp,
            i;
    lprintf ("\n\nYou have found %s ", objectname[itm]);
    tmp = iarg[playerx][playery];
    switch (itm) {
	case ODIAMOND: 
	case ORUBY: 
	case OEMERALD: 
	case OSAPPHIRE: 
	case OSPIRITSCARAB: 
	case OORBOFDRAGON: 
	case OCUBEofUNDEAD: 
	case ONOTHEFT: 
	    break;

	default: 
	    if (tmp > 0)
		lprintf ("+ %d", (long) tmp);
	    else
		if (tmp < 0)
		    lprintf (" %d", (long) tmp);
    }
    lprcat ("\nDo you want to (t) take it");
    iopts ();
    i = 0;
    while (i != 't' && i != 'i' && i != '\33')
	i = readchar ();
    if (i == 't') {
	lprcat ("take");
	if (take (itm, tmp) == 0)
	    forget ();
	return;
    }
    ignore ();
}


/*
	*******
	OSTAIRS
	*******

	subroutine to process the stair cases
	if dir > 0 the up else down
 */
ostairs (dir)
int     dir;
{
    register int    k;
    lprcat ("\nDo you (s) stay here  ");
    if (dir > 0)
	lprcat ("(u) go up  ");
    else
	lprcat ("(d) go down  ");
    lprcat ("or (f) kick stairs? ");

    while (1)
	switch (readchar ()) {
	    case '\33': 
	    case 's': 
	    case 'i': 
		lprcat ("stay here");
		return;

	    case 'f': 
		lprcat ("kick stairs");
		if (rnd (2) == 1)
		    lprcat ("\nI hope you feel better.  Showing anger rids you of frustration.");
		else {
		    k = rnd ((level + 1) << 1);
		    lprintf ("\nYou hurt your foot dumb dumb!  You suffer %d hit points", (long) k);
		    lastnum = 276;
		    losehp (k);
		    bottomline ();
		}
		return;

	    case 'u': 
		lprcat ("go up");
		if (dir < 0)
		    lprcat ("\nThe stairs don't go up!");
		else
		    if (level >= 2 && level != 11) {
			k = level;
			newcavelevel (level - 1);
			draws (0, MAXX, 0, MAXY);
			bot_linex ();
		    }
		    else
			lprcat ("\nThe stairs lead to a dead end!");
		return;

	    case 'd': 
		lprcat ("go down");
		if (dir > 0)
		    lprcat ("\nThe stairs don't go down!");
		else
		    if (level != 0 && level != 10 && level != 13) {
			k = level;
			newcavelevel (level + 1);
			draws (0, MAXX, 0, MAXY);
			bot_linex ();
		    }
		    else
			lprcat ("\nThe stairs lead to a dead end!");
		return;
	};
}


/*
	*********
	OTELEPORTER
	*********

	subroutine to handle a teleport trap +/- 1 level maximum
 */
oteleport (err)
int     err;
{
    register int    tmp;
    if (err)
	if (rnd (151) < 3)
	    died (264);		/* 	stuck in a rock */
    c[TELEFLAG] = 1;		/* 	show ?? on bottomline if been teleported	 */
    if (level == 0)
	tmp = 0;
    else
	if (level < MAXLEVEL) {
	    tmp = rnd (5) + level - 3;
	    if (tmp >= MAXLEVEL)
		tmp = MAXLEVEL - 1;
	    if (tmp < 1)
		tmp = 1;
	}
	else {
	    tmp = rnd (3) + level - 2;
	    if (tmp >= MAXLEVEL + MAXVLEVEL)
		tmp = MAXLEVEL + MAXVLEVEL - 1;
	    if (tmp < MAXLEVEL)
		tmp = MAXLEVEL;
	}
    playerx = rnd (MAXX - 2);
    playery = rnd (MAXY - 2);
    if (level != tmp)
	newcavelevel (tmp);
    positionplayer ();
    draws (0, MAXX, 0, MAXY);
    bot_linex ();
}

/*
	*******
	OPOTION
	*******

	function to process a potion
 */
opotion (pot)
int     pot;
{
    lprcat ("\nDo you (d) drink it, (t) take it");
    iopts ();
    while (1)
	switch (readchar ()) {
	    case '\33': 
	    case 'i': 
		ignore ();
		return;

	    case 'd': 
		lprcat ("drink\n");
		forget ();	/* 	destroy potion	 */
		quaffpotion (pot);
		return;

	    case 't': 
		lprcat ("take\n");
		if (take (OPOTION, pot) == 0)
		    forget ();
		return;
	};
}

/*
	function to drink a potion
 */
quaffpotion (pot)
int     pot;
{
    register int    i,
                    j,
                    k;
    if (pot < 0 || pot >= MAXPOTION)
	return;			/* check for within bounds */
    potionname[pot][0] = ' ';
    switch (pot) {
	case 9: 
	    lprcat ("\nYou feel greedy . . .");
	    nap (2000);
	    for (i = 0; i < MAXY; i++)
		for (j = 0; j < MAXX; j++)
		    if ((item[j][i] == OGOLDPILE) || (item[j][i] == OMAXGOLD)) {
			know[j][i] = 1;
			show1cell (j, i);
		    }
	    showplayer ();
	    return;

	case 19: 
	    lprcat ("\nYou feel greedy . . .");
	    nap (2000);
	    for (i = 0; i < MAXY; i++)
		for (j = 0; j < MAXX; j++) {
		    k = item[j][i];
		    if ((k == ODIAMOND) || (k == ORUBY) || (k == OEMERALD) || (k == OMAXGOLD)
			    || (k == OSAPPHIRE) || (k == OLARNEYE) || (k == OGOLDPILE)) {
			know[j][i] = 1;
			show1cell (j, i);
		    }
		}
	    showplayer ();
	    return;

	case 20: 
	    c[HP] = c[HPMAX];
	    break;		/* instant healing */

	case 1: 
	    lprcat ("\nYou feel better");
	    if (c[HP] == c[HPMAX])
		raisemhp (1);
	    else
		if ((c[HP] += rnd (20) + 20 + c[LEVEL]) > c[HPMAX])
		    c[HP] = c[HPMAX];
	    break;

	case 2: 
	    lprcat ("\nSuddenly, you feel much more skillful!");
	    raiselevel ();
	    raisemhp (1);
	    return;

	case 3: 
	    lprcat ("\nYou feel strange for a moment");
	    c[rund (6)]++;
	    break;

	case 4: 
	    lprcat ("\nYou feel more self confident!");
	    c[WISDOM] += rnd (2);
	    break;

	case 5: 
	    lprcat ("\nWow!  You feel great!");
	    if (c[STRENGTH] < 12)
		c[STRENGTH] = 12;
	    else
		c[STRENGTH]++;
	    break;

	case 6: 
	    lprcat ("\nYour charm went up by one!");
	    c[CHARISMA]++;
	    break;

	case 8: 
	    lprcat ("\nYour intelligence went up by one!");
	    c[INTELLIGENCE]++;
	    break;

	case 10: 
	    for (i = 0; i < MAXY; i++)
		for (j = 0; j < MAXX; j++)
		    if (mitem[j][i]) {
			know[j][i] = 1;
			show1cell (j, i);
		    }
	     /* 	monster detection	 */ return;

	case 12: 
	    lprcat ("\nThis potion has no taste to it");
	    return;

	case 15: 
	    lprcat ("\nWOW!!!  You feel Super-fantastic!!!");
	    if (c[HERO] == 0)
		for (i = 0; i < 6; i++)
		    c[i] += 11;
	    c[HERO] += 250;
	    break;

	case 16: 
	    lprcat ("\nYou have a greater intestinal constitude!");
	    c[CONSTITUTION]++;
	    break;

	case 17: 
	    lprcat ("\nYou now have incredibly bulging muscles!!!");
	    if (c[GIANTSTR] == 0)
		c[STREXTRA] += 21;
	    c[GIANTSTR] += 700;
	    break;

	case 18: 
	    lprcat ("\nYou feel a chill run up your spine!");
	    c[FIRERESISTANCE] += 1000;
	    break;

	case 0: 
	    lprcat ("\nYou fall asleep. . .");
	    i = rnd (11) - (c[CONSTITUTION] >> 2) + 2;
	    while (--i > 0) {
		parse2 ();
		nap (1000);
	    }
	    cursors ();
	    lprcat ("\nYou woke up!");
	    return;

	case 7: 
	    lprcat ("\nYou become dizzy!");
	    if (--c[STRENGTH] < 3)
		c[STRENGTH] = 3;
	    break;

	case 11: 
	    lprcat ("\nYou stagger for a moment . .");
	    for (i = 0; i < MAXY; i++)
		for (j = 0; j < MAXX; j++)
		    know[j][i] = 0;
	    nap (2000);
	    draws (0, MAXX, 0, MAXY);/* potion of forgetfulness */
	    return;

	case 13: 
	    lprcat ("\nYou can't see anything!");/* blindness */
	    c[BLINDCOUNT] += 500;
	    return;

	case 14: 
	    lprcat ("\nYou feel confused");
	    c[CONFUSE] += 20 + rnd (9);
	    return;

	case 21: 
	    lprcat ("\nYou don't seem to be affected");
	    return;		/* cure dianthroritis */

	case 22: 
	    lprcat ("\nYou feel a sickness engulf you");/* poison */
	    c[HALFDAM] += 200 + rnd (200);
	    return;

	case 23: 
	    lprcat ("\nYou feel your vision sharpen");/* see invisible */
	    c[SEEINVISIBLE] += rnd (1000) + 400;
	    monstnamelist[INVISIBLESTALKER] = 'I';
	    return;
    };
    bottomline ();		/* 	show new stats		 */
    return;
}

/*
	*******
	OSCROLL
	*******

	function to process a magic scroll
 */
oscroll (typ)
int     typ;
{
    lprcat ("\nDo you ");
    if (c[BLINDCOUNT] == 0)
	lprcat ("(r) read it, ");
    lprcat ("(t) take it");
    iopts ();
    while (1)
	switch (readchar ()) {
	    case '\33': 
	    case 'i': 
		ignore ();
		return;

	    case 'r': 
		if (c[BLINDCOUNT])
		    break;
		lprcat ("read");
		forget ();
		if (typ == 2 || typ == 15) {
		    show1cell (playerx, playery);
		    cursors ();
		}
		 /* 	destroy it	 */ read_scroll (typ);
		return;

	    case 't': 
		lprcat ("take");
		if (take (OSCROLL, typ) == 0)
		    forget ();	/* 	destroy it	 */
		return;
	};
}

/*
	data for the function to read a scroll
 */
static int  xh,
            yh,
            yl,
            xl;
static char curse[] = {
    BLINDCOUNT, CONFUSE, AGGRAVATE, HASTEMONST, ITCHING,
    LAUGHING, DRAINSTRENGTH, CLUMSINESS, INFEEBLEMENT, HALFDAM
};
static char exten[] = {
    PROTECTIONTIME, DEXCOUNT, STRCOUNT, CHARMCOUNT,
    INVISIBILITY, CANCELLATION, HASTESELF, GLOBE, SCAREMONST, HOLDMONST, TIMESTOP
};
char    time_change[] = {
    HASTESELF, HERO, ALTPRO, PROTECTIONTIME, DEXCOUNT,
    STRCOUNT, GIANTSTR, CHARMCOUNT, INVISIBILITY, CANCELLATION,
    HASTESELF, AGGRAVATE, SCAREMONST, STEALTH, AWARENESS, HOLDMONST, HASTEMONST,
    FIRERESISTANCE, GLOBE, SPIRITPRO, UNDEADPRO, HALFDAM, SEEINVISIBLE,
    ITCHING, CLUMSINESS, WTW
};
/*
 *	function to adjust time when time warping and taking courses in school
 */
adjtime (tim)
register long   tim;
{
    register int    j;
    for (j = 0; j < 26; j++)	/* adjust time related parameters */
	if (c[time_change[j]])
	    if ((c[time_change[j]] -= tim) < 1)
		c[time_change[j]] = 1;
    regen ();
}

/*
	function to read a scroll
 */
read_scroll (typ)
int     typ;
{
    register int    i,
                    j;
    if (typ < 0 || typ >= MAXSCROLL)
	return;			/* be sure we are within bounds */
    scrollname[typ][0] = ' ';
    switch (typ) {
	case 0: 
	    lprcat ("\nYour armor glows for a moment");
	    enchantarmor ();
	    return;

	case 1: 
	    lprcat ("\nYour weapon glows for a moment");
	    enchweapon ();
	    return;		/* enchant weapon */

	case 2: 
	    lprcat ("\nYou have been granted enlightenment!");
	    yh = min (playery + 7, MAXY);
	    xh = min (playerx + 25, MAXX);
	    yl = max (playery - 7, 0);
	    xl = max (playerx - 25, 0);
	    for (i = yl; i < yh; i++)
		for (j = xl; j < xh; j++)
		    know[j][i] = 1;
	    nap (2000);
	    draws (xl, xh, yl, yh);
	    return;

	case 3: 
	    lprcat ("\nThis scroll seems to be blank");
	    return;

	case 4: 
	    createmonster (makemonst (level + 1));
	    return;		/*  this one creates a monster  */

	case 5: 
	    something (level);	/* 	create artifact		 */
	    return;

	case 6: 
	    c[AGGRAVATE] += 800;
	    return;		/* aggravate monsters */

	case 7: 
	    gtime += (i = rnd (1000) - 850);/* time warp */

	    if (i >= 0)
		lprintf ("\nYou went forward in time by %d mobuls", (long) ((i + 99) / 100));
	    else
		lprintf ("\nYou went backward in time by %d mobuls", (long) (-(i + 99) / 100));
	    adjtime ((long) i);	/* adjust time for time warping */
	    return;

	case 8: 
	    oteleport (0);
	    return;		/* 	teleportation */

	case 9: 
	    c[AWARENESS] += 1800;
	    return;		/* expanded awareness	 */

	case 10: 
	    c[HASTEMONST] += rnd (55) + 12;
	    return;		/* haste monster */

	case 11: 
	    for (i = 0; i < MAXY; i++)
		for (j = 0; j < MAXX; j++)
		    if (mitem[j][i])
			hitp[j][i] = monster[mitem[j][i]].hitpoints;
	    return;		/* monster healing */
	case 12: 
	    c[SPIRITPRO] += 300 + rnd (200);
	    bottomline ();
	    return;		/* spirit protection */

	case 13: 
	    c[UNDEADPRO] += 300 + rnd (200);
	    bottomline ();
	    return;		/* undead protection */

	case 14: 
	    c[STEALTH] += 250 + rnd (250);
	    bottomline ();
	    return;		/* stealth */

	case 15: 
	    lprcat ("\nYou have been granted enlightenment!");/* magic mapping */
	    for (i = 0; i < MAXY; i++)
		for (j = 0; j < MAXX; j++)
		    know[j][i] = 1;
	    nap (2000);
	    draws (0, MAXX, 0, MAXY);
	    return;

	case 16: 
	    c[HOLDMONST] += 30;
	    bottomline ();
	    return;		/* hold monster */

	case 17: 
	    for (i = 0; i < 26; i++)/* gem perfection */
		switch (iven[i]) {
		    case ODIAMOND: 
		    case ORUBY: 
		    case OEMERALD: 
		    case OSAPPHIRE: 
			j = ivenarg[i];
			j &= 255;
			j <<= 1;
			if (j > 255)
			    j = 255;/* double value */
			ivenarg[i] = j;
			break;
		}
	    break;

	case 18: 
	    for (i = 0; i < 11; i++)
		c[exten[i]] <<= 1;/* spell extension */
	    break;

	case 19: 
	    for (i = 0; i < 26; i++) {/* identify */
		if (iven[i] == OPOTION)
		    potionname[ivenarg[i]][0] = ' ';
		if (iven[i] == OSCROLL)
		    scrollname[ivenarg[i]][0] = ' ';
	    }
	    break;

	case 20: 
	    for (i = 0; i < 10; i++)/* remove curse */
		if (c[curse[i]])
		    c[curse[i]] = 1;
	    break;

	case 21: 
	    annihilate ();
	    break;		/* scroll of annihilation */

	case 22: 
	    godirect (22, 150, "The ray hits the %s", 0, ' ');/* pulverization */
	    break;
	case 23: 
	    c[LIFEPROT]++;
	    break;		/* life protection */
    };
}


oorb () {
}

opit () {
    register int    i;
    if (rnd (101) < 81)
	if (rnd (70) > 9 * c[DEXTERITY] - packweight () || rnd (101) < 5)
	    if (level == MAXLEVEL - 1)
		obottomless ();
	    else
		if (level == MAXLEVEL + MAXVLEVEL - 1)
		    obottomless ();
		else {
		    if (rnd (101) < 20) {
			i = 0;
			lprcat ("\nYou fell into a pit!  Your fall is cushioned by an unknown force\n");
		    }
		    else {
			i = rnd (level * 3 + 3);
			lprintf ("\nYou fell into a pit!  You suffer %d hit points damage", (long) i);
			lastnum = 261;/* 	if he dies scoreboard will say so */
		    }
		    losehp (i);
		    nap (2000);
		    newcavelevel (level + 1);
		    draws (0, MAXX, 0, MAXY);
		}
}

obottomless () {
    lprcat ("\nYou fell into a bottomless pit!");
    beep ();
    nap (3000);
    died (262);
}
oelevator (dir)
int     dir;
{
#ifdef lint
    int     x;
    x = dir;
    dir = x;
#endif lint
}

ostatue () {
}

omirror () {
}

obook () {
    lprcat ("\nDo you ");
    if (c[BLINDCOUNT] == 0)
	lprcat ("(r) read it, ");
    lprcat ("(t) take it");
    iopts ();
    while (1)
	switch (readchar ()) {
	    case '\33': 
	    case 'i': 
		ignore ();
		return;

	    case 'r': 
		if (c[BLINDCOUNT])
		    break;
		lprcat ("read");
		 /* no more book	 */ readbook (iarg[playerx][playery]);
		forget ();
		return;

	    case 't': 
		lprcat ("take");
		if (take (OBOOK, iarg[playerx][playery]) == 0)
		    forget ();	/* no more book	 */
		return;
	};
}

/*
	function to read a book
 */
readbook (lev)
register int    lev;
{
    register int    i,
                    tmp;
    if (lev <= 3)
	i = rund ((tmp = splev[lev]) ? tmp : 1);
    else
	i = rnd ((tmp = splev[lev] - 9) ? tmp : 1) + 9;
    spelknow[i] = 1;
    lprintf ("\nSpell \"%s\":  %s\n%s", spelcode[i], spelname[i], speldescript[i]);
    if (rnd (10) == 4) {
	lprcat ("\nYour int went up by one!");
	c[INTELLIGENCE]++;
	bottomline ();
    }
}

ocookie () {
    char   *p;
    lprcat ("\nDo you (e) eat it, (t) take it");
    iopts ();
    while (1)
	switch (readchar ()) {
	    case '\33': 
	    case 'i': 
		ignore ();
		return;

	    case 'e': 
		lprcat ("eat\nThe cookie tasted good.");
		forget ();	/* no more cookie	 */
		if (c[BLINDCOUNT])
		    return;
		if (!(p = fortune (fortfile)))
		    return;
		lprcat ("  A message inside the cookie reads:\n");
		lprcat (p);
		return;

	    case 't': 
		lprcat ("take");
		if (take (OCOOKIE, 0) == 0)
		    forget ();	/* no more book	 */
		return;
	};
}


/* routine to pick up some gold -- if arg==OMAXGOLD then the pile is worth 100* the argument */
ogold (arg)
int     arg;
{
    register long   i;
    i = iarg[playerx][playery];
    if (arg == OMAXGOLD)
	i *= 100;
    else
	if (arg == OKGOLD)
	    i *= 1000;
	else
	    if (arg == ODGOLD)
		i *= 10;
    lprintf ("\nIt is worth %d!", (long) i);
    c[GOLD] += i;
    bottomgold ();
    item[playerx][playery] = know[playerx][playery] = 0;/* 	destroy gold	 */
}

ohome () {
    register int    i;
    nosignal = 1;		/* disable signals */
    for (i = 0; i < 26; i++)
	if (iven[i] == OPOTION)
	    if (ivenarg[i] == 21) {
		iven[i] = 0;	/* remove the potion of cure dianthroritis from inventory */
		clear ();
		lprcat ("Congratulations.  You found a potion of cure dianthroritis.\n");
		lprcat ("\nFrankly, No one thought you could do it.  Boy!  Did you surprise them!\n");
		if (gtime > TIMELIMIT) {
		    lprcat ("\nThe doctor has the sad duty to inform you that your daughter died!\n");
		    lprcat ("You didn't make it in time.  In your agony, you kill the doctor,\nyour wife, and yourself!  Too bad!\n");
		    nap (5000);
		    died (269);
		}
		else {
		    lprcat ("\nThe doctor is now administering the potion, and in a few moments\n");
		    lprcat ("Your daughter should be well on her way to recovery.\n");
		    nap (6000);
		    lprcat ("\nThe potion is");
		    nap (3000);
		    lprcat (" working!  The doctor thinks that\n");
		    lprcat ("your daughter will recover in a few days.  Congratulations!\n");
		    beep ();
		    nap (5000);
		    died (263);
		}
	    }

    while (1) {
	clear ();
	lprintf ("Welcome home %s.  Latest word from the doctor is not good.\n", logname);

	if (gtime > TIMELIMIT) {
	    lprcat ("\nThe doctor has the sad duty to inform you that your daughter died!\n");
	    lprcat ("You didn't make it in time.  In your agony, you kill the doctor,\nyour wife, and yourself!  Too bad!\n");
	    nap (5000);
	    died (269);
	}

	lprcat ("\nThe diagnosis is confirmed as dianthroritis.  He guesses that\n");
	lprintf ("your daughter has only %d mobuls left in this world.  It's up to you,\n", (long) ((TIMELIMIT - gtime + 99) / 100));
	lprintf ("%s, to find the only hope for your daughter, the very rare\n", logname);
	lprcat ("potion of cure dianthroritis.  It is rumored that only deep in the\n");
	lprcat ("depths of the caves can this potion be found.\n\n\n");
	lprcat ("\n     ----- press ");
	standout ("return");
	lprcat (" to continue, ");
	standout ("escape");
	lprcat (" to leave ----- ");
	i = readchar ();
	while (i != '\33' && i != '\n')
	    i = readchar ();
	if (i == '\33') {
	    drawscreen ();
	    nosignal = 0;	/* enable signals */
	    return;
	}
    }
}

/*	routine to save program space	*/
iopts () {
    lprcat (", or (i) ignore it? ");
}
ignore () {
    lprcat ("ignore\n");
}
SHAR_EOF
if test 28817 -ne "`wc -c < 'object.c'`"
then
	echo shar: error transmitting "'object.c'" '(should have been 28817 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'scores.c'" '(22296 characters)'
if test -f 'scores.c'
then
	echo shar: will not over-write existing file "'scores.c'"
else
cat << \SHAR_EOF > 'scores.c'

/* scores.c			 Larn is copyrighted 1986 by Noah Morgan.
 *
 *	Functions in this file are:
 *
 * readboard() 	Function to read in the scoreboard into a static buffer
 * writeboard()	Function to write the scoreboard from readboard()'s buffer
 * makeboard() 	Function to create a new scoreboard(wipe out old one)
 * hashewon()	Function to return 1 if player has won a game before, else 0
 * long paytaxes(x)	Function to pay taxes if any are due
 * winshou()		Subroutine to print out the winning scoreboard
 * shou(x)		Subroutine to print out the non-winners scoreboard
 * showscores()		Function to show the scoreboard on the terminal
 * showallscores()	Function to show scores and the iven lists that go with them
 * sortboard()		Function to sort the scoreboard
 * newscore(score, whoo, whyded, winner) Function to add entry to scoreboard
 * new1sub(score,i,whoo,taxes) 	 Subroutine to put player into a 
 * new2sub(score,i,whoo,whyded)	 Subroutine to put player into a 
 * died(x) 	Subroutine to record who played larn, and what the score was
 * diedsub(x)	Subroutine to print out a line showing player when he is killed
 * diedlog() 	Subroutine to read a log file and print it out in ascii format
 * getplid(name)	Function to get players id # from id file
 *
 */
#include <times.h>
#include <stat.h>
#include "header.h"

struct scofmt {		/* This is the structure for the scoreboard */
    long    score;	/* the score of the player */
    long    suid;	/* the user id number of the player */
    short   what;	/* the number of the monster that killed player */
    short   level;	/* the level player was on when he died */
    short   hardlev;	/* the level of difficulty player played at */
    short   order;	/* the relative ordering place of this entry */
    char    who[40];	/* the name of the character */
    char    sciv[26][2];/* this is the inventory list of the character */
};

struct wscofmt {	/* This is the structure for the winning scoreboard */
    long    score;	/* the score of the player */
    long    timeused;	/* the time used in mobuls to win the game */
    long    taxes;	/* taxes he owes to LRS */
    long    suid;	/* the user id number of the player */
    short   hardlev;	/* the level of difficulty player played at */
    short   order;	/* the relative ordering place of this entry */
    char    who[40];	/* the name of the character */
};

struct log_fmt {	/* 102 bytes struct for the log file */
    long    score;	/* the players score */
    long    diedtime;	/* time when game was over */
    short   cavelev;	/* level in caves */
    short   diff;	/* difficulty player played at */
#ifdef EXTRA
    long    elapsedtime;/* real time of game in seconds */
    long    bytout;	/* bytes input and output */
    long    bytin;
    long    moves;	/* number of moves made by player */
    short   ac;		/* armor class of player */
    short   hp,hpmax;	/* players hitpoints */
    short   cputime;	/* cpu time needed in seconds */
    short   killed,
            spused;	/* monsters killed and spells cast */
    short   usage;	/* usage of the cpu in % */
    short   lev;	/* player level */
#endif
    char    who[12];	/* player name */
    char    what[46];	/* what happened to player */
};

static struct scofmt    sco[SCORESIZE];/* the structure for the scoreboard  */
static struct wscofmt   winr[SCORESIZE];/* struct for the winning scoreboard */
static struct log_fmt   logg;	/* structure for the log file */
static char *whydead[] = {
    "quit", "suspended", "self - annihilated", "shot by an arrow",
    "hit by a dart", "fell into a pit", "fell into a bottomless pit",
    "a winner", "trapped in solid rock", "killed by a missing save file",
    "killed by an old save file", "caught by the greedy cheater checker trap",
    "killed by a protected save file", "killed his family and committed suicide",
    "erased by a wayward finger", "fell through a bottomless trap door",
    "fell through a trap door", "drank some poisonous water",
    "fried by an electric shock", "slipped on a volcano shaft",
    "killed by a stupid act of frustration", "attacked by a revolting demon",
    "hit by his own magic", "demolished by an unseen attacker",
    "fell into the dreadful sleep", "killed by an exploding chest",
     /* 26 */ "killed by a missing maze data file", "annihilated in a sphere",
    "died a post mortem death", "wasted by a malloc() failure"
};

/*
 * readboard() 	Function to read in the scoreboard into a static buffer
 *
 * returns -1 if unable to read in the scoreboard, returns 0 if all is OK
 */
readboard()
{
    if (lopen(scorefile) < 0) {
	lprcat("Can't read scoreboard\n");
	lflush();
	return(-1);
    }
    lrfill((char *) sco, sizeof(sco));
    lrfill((char *) winr, sizeof(winr));
    lrclose();
    lcreat((char *) 0);
    return(0);
}

/*
 * writeboard()	Function to write the scoreboard from readboard()'s buffer
 *
 * returns -1 if unable to write the scoreboard, returns 0 if all is OK
 */
writeboard()
{
    set_score_output();
    delete(scorefile);		/* otherwise we get many many copies */
    if (lcreat(scorefile) < 0) {
	lprcat("Can't write scoreboard\n");
	lflush();
	return(-1);
    }
    lwrite((char *) sco, sizeof(sco));
    lwrite((char *) winr, sizeof(winr));
    lwclose();
    lcreat((char *) 0);
    return(0);
}

/*
 * makeboard() 		Function to create a new scoreboard(wipe out old one)
 *
 * returns -1 if unable to write the scoreboard, returns 0 if all is OK
 */
makeboard()
{
    register int    i;

    for (i = 0; i < SCORESIZE; i++) {
	winr[i].taxes = winr[i].score = sco[i].score = 0;
	winr[i].order = sco[i].order = i;
    }
    if (writeboard())
	return(-1);
    chmod(scorefile, 0664);
    return(0);
}

/*
 * hashewon()	 Function to return 1 if player has won a game before, else 0
 *
 * This function also sets c[HARDGAME] to appropriate value -- 0 if not a
 * winner, otherwise the next level of difficulty listed in the winners
 * scoreboard.  This function also sets outstanding_taxes to the value in
 * the winners scoreboard.
 */
hashewon()
{
    register int i;

    c[HARDGAME] = 0;
    if (readboard() < 0)
	return(0);		/* can't find scoreboard */
    for (i = 0; i < SCORESIZE; i++)/* search through winners scoreboard */
	if (winr[i].suid == userid)
	    if (winr[i].score > 0) {
		c[HARDGAME] = winr[i].hardlev + 1;
		outstanding_taxes = winr[i].taxes;
		return(1);
	    }
    return(0);
}

/*
 * long paytaxes(x)		 Function to pay taxes if any are due
 *
 * Enter with the amount(in gp) to pay on the taxes.
 * Returns amount actually paid.
 */
long paytaxes(x)
long x;
{
    register int i;
    register long amt;

    if (x < 0)
	return(0L);
    if (readboard() < 0)
	return(0L);
    for (i = 0; i < SCORESIZE; i++)
	if (winr[i].suid == userid)/* look for players winning entry */
	    if (winr[i].score > 0) {/* search for a winning entry for the player */
		amt = winr[i].taxes;
		if (x < amt)
		    amt = x;	/* don't overpay taxes(Ughhhhh) */
		winr[i].taxes -= amt;
		outstanding_taxes -= amt;
		if (writeboard() < 0)
		    return(0);
		return(amt);
	    }
    return(0L);		/* couldn't find user on winning scoreboard */
}

/*
 * winshou()		Subroutine to print out the winning scoreboard
 *
 * Returns the number of players on scoreboard that were shown 
 */
winshou()
{
    register struct wscofmt *p;
    register int i,j,count;

    for (count = j = i = 0; i < SCORESIZE; i++)/* is there anyone on the scoreboard? */
	if (winr[i].score != 0) {
	    j++;
	    break;
	}
    if (j) {
	lprcat("\n  Score    Difficulty   Time Needed   Larn Winners List\n");

	for (i = 0; i < SCORESIZE; i++)/* this loop is needed to print out the */
	    for (j = 0; j < SCORESIZE; j++) {/* winners in order */
		p = &winr[j];	/* pointer to the scoreboard entry */
		if (p -> order == i) {
		    if (p -> score) {
			count++;
			lprintf("%10d     %2d      %5d Mobuls   %s \n",
				(long) p -> score,(long) p -> hardlev,(long) p -> timeused, p -> who);
		    }
		    break;
		}
	    }
    }
    return(count);		/* return number of people on scoreboard */
}

/*
 * shou(x)		Subroutine to print out the non-winners scoreboard
 * int x;
 *
 * Enter with 0 to list the scores, enter with 1 to list inventories too
 * Returns the number of players on scoreboard that were shown 
 */
shou(x)
int x;
{
    register int i,j,n,k;
    int count;

    for (count = j = i = 0; i < SCORESIZE; i++)/* is the scoreboard empty? */
	if (sco[i].score != 0) {
	    j++;
	    break;
	}
    if (j) {
	lprcat("\n   Score   Difficulty   Larn Visitor Log\n");
	for (i = 0; i < SCORESIZE; i++)/* be sure to print them out in order */
	    for (j = 0; j < SCORESIZE; j++)
		if (sco[j].order == i) {
		    if (sco[j].score) {
			count++;
			lprintf("%10d     %2d       %s ",
				(long) sco[j].score,(long) sco[j].hardlev, sco[j].who);
			if (sco[j].what < 256)
			    lprintf("killed by a %s", monster[sco[j].what].name);
			else
			    lprintf("%s", whydead[sco[j].what - 256]);
			if (x != 263)
			    lprintf(" on %s", levelname[sco[j].level]);
			if (x) {
			    for (n = 0; n < 26; n++) {
				iven[n] = sco[j].sciv[n][0];
				ivenarg[n] = sco[j].sciv[n][1];
			    }
			    for (k = 1; k < 99; k++)
				for (n = 0; n < 26; n++)
				    if (k == iven[n]) {
					srcount = 0;
					show3(n);
				    }
			    lprcat("\n\n");
			}
			else
			    lprc('\n');
		    }
		    j = SCORESIZE;
		}
    }
    return(count);		/* return the number of players just shown */
}

/*
 * showscores()		Function to show the scoreboard on the terminal
 *
 * Returns nothing of value
 */
static char esb[] = "The scoreboard is empty.\n";
showscores()
{
    register int i,j;

    lflush();
    lcreat((char *) 0);
    if (readboard() < 0)
	return;
    i = winshou();
    j = shou(0);
    if (i + j == 0)
	lprcat(esb);
    else
	lprc('\n');
    lflush();
}

/*
 *	showallscores()	Function to show scores and the iven lists that go with them
 *
 *	Returns nothing of value
 */
showallscores()
{
    register int i,j;

    lflush();
    lcreat((char *) 0);
    if (readboard() < 0)
	return;
    c[WEAR] = c[WIELD] = c[SHIELD] = -1;/* not wielding or wearing anything */
    for (i = 0; i < MAXPOTION; i++)
	potionname[i][0] = ' ';
    for (i = 0; i < MAXSCROLL; i++)
	scrollname[i][0] = ' ';
    i = winshou();
    j = shou(1);
    if (i + j == 0)
	lprcat(esb);
    else
	lprc('\n');
    lflush();
}

/*
 *	sortboard()		Function to sort the scoreboard
 *
 *	Returns 0 if no sorting done, else returns 1
 */
sortboard()
{
    register int i,j,pos;
    long jdat;

    for (i = 0; i < SCORESIZE; i++)
	sco[i].order = winr[i].order = -1;
    pos = 0;
    while (pos < SCORESIZE) {
	jdat = 0;
	for (i = 0; i < SCORESIZE; i++)
	    if ((sco[i].order < 0) &&(sco[i].score >= jdat)) {
		j = i;
		jdat = sco[i].score;
	    }
	sco[j].order = pos++;
    }
    pos = 0;
    while (pos < SCORESIZE) {
	jdat = 0;
	for (i = 0; i < SCORESIZE; i++)
	    if ((winr[i].order < 0) &&(winr[i].score >= jdat)) {
		j = i;
		jdat = winr[i].score;
	    }
	winr[j].order = pos++;
    }
    return(1);
}

/*
 * newscore(score, whoo, whyded, winner) 	Function to add entry to scoreboard
 * int score, winner, whyded;
 * char *whoo;
 *
 * Enter with the total score in gp in score,  players name in whoo,
 * died() reason # in whyded, and TRUE/FALSE in winner if a winner
 * ex.		newscore(1000, "player 1", 32, 0);
 */
newscore(score, whoo, whyded, winner)
long score;
int winner,whyded;
char *whoo;
{
    register int i;
    long taxes;

    if (readboard() < 0)
	return;			/* 	do the scoreboard	 */
 /* if a winner then delete all non-winning scores */
    if (cheat)
	winner = 0;		/* if he cheated, don't let him win */
    if (winner) {
	for (i = 0; i < SCORESIZE; i++)
	    if (sco[i].suid == userid)
		sco[i].score = 0;
	taxes = score * TAXRATE;
	score += 100000 * c[HARDGAME];/* bonus for winning */
    /* if he has a slot on the winning scoreboard update it if greater score */
	for (i = 0; i < SCORESIZE; i++)
	    if (winr[i].suid == userid) {
		new1sub(score, i, whoo, taxes);
		return;
	    }
    /* he had no entry. look for last entry and see if he has a greater score */
	for (i = 0; i < SCORESIZE; i++)
	    if (winr[i].order == SCORESIZE - 1) {
		new1sub(score, i, whoo, taxes);
		return;
	    }
    } else
	if (!cheat) {		/* for not winning scoreboard */
	/* if he has a slot on the scoreboard update it if greater score */
	    for (i = 0; i < SCORESIZE; i++)
		if (sco[i].suid == userid) {
		    new2sub(score, i, whoo, whyded);
		    return;
		}
	/* he had no entry. look for last entry and see if he has a greater score */
	    for (i = 0; i < SCORESIZE; i++)
		if (sco[i].order == SCORESIZE - 1) {
		    new2sub(score, i, whoo, whyded);
		    return;
		}
	}
}

/*
 * new1sub(score,i,whoo,taxes) 	  Subroutine to put player into a 
 * int score,i,whyded,taxes;	  winning scoreboard entry if his score
 * char *whoo; 			  is high enough
 *
 * Enter with the total score in gp in score,  players name in whoo,
 * died() reason # in whyded, and TRUE/FALSE in winner if a winner
 * slot in scoreboard in i, and the tax bill in taxes.
 * Returns nothing of value
 */
new1sub(score, i, whoo, taxes)
long score,taxes;
int i;
char *whoo;
{
    register struct wscofmt *p;

    p = &winr[i];
    p -> taxes += taxes;
    if ((score >= p -> score) ||(c[HARDGAME] > p -> hardlev)) {
	strcpy(p -> who, whoo);
	p -> score = score;
	p -> hardlev = c[HARDGAME];
	p -> suid = userid;
	p -> timeused = gtime / 100;
    }
}

/*
 * new2sub(score,i,whoo,whyded)	 	  Subroutine to put player into a 
 * int score,i,whyded,taxes;		  non-winning scoreboard entry if his
 * char *whoo; 				  score is high enough
 *
 * Enter with the total score in gp in score,  players name in whoo,
 * died() reason # in whyded, and slot in scoreboard in i.
 * Returns nothing of value
 */
new2sub(score, i, whoo, whyded)
long score;
int i,whyded;
char *whoo;
{
    register int j;
    register struct scofmt *p;

    p = &sco[i];
    if ((score >= p -> score) ||(c[HARDGAME] > p -> hardlev)) {
	strcpy(p -> who, whoo);
	p -> score = score;
	p -> what = whyded;
	p -> hardlev = c[HARDGAME];
	p -> suid = userid;
	p -> level = level;
	for (j = 0; j < 26; j++) {
	    p -> sciv[j][0] = iven[j];
	    p -> sciv[j][1] = ivenarg[j];
	}
    }
}

/*
 * died(x) 	Subroutine to record who played larn, and what the score was
 * int x;
 *
 * if x < 0 then don't show scores
 * died() never returns!(unless c[LIFEPROT] and a reincarnatable death!)
 *
 * < 256	killed by the monster number
 *   256	quit
 *   257	suspended
 *   258	self - annihilated
 *   259	shot by an arrow
 *   260	hit by a dart
 *   261	fell into a pit
 *   262	fell into a bottomless pit
 *   263	a winner
 *   264	trapped in solid rock
 *   265	killed by a missing save file
 *   266	killed by an old save file
 *   267	caught by the greedy cheater checker trap
 *   268	killed by a protected save file
 *   269	killed his family and killed himself
 *   270	erased by a wayward finger
 *   271	fell through a bottomless trap door
 *   272	fell through a trap door
 *   273	drank some poisonous water
 *   274	fried by an electric shock
 *   275	slipped on a volcano shaft
 *   276	killed by a stupid act of frustration
 *   277	attacked by a revolting demon
 *   278	hit by his own magic
 *   279	demolished by an unseen attacker
 *   280	fell into the dreadful sleep
 *   281	killed by an exploding chest
 *   282	killed by a missing maze data file
 *   283	killed by a sphere of annihilation
 *   284	died a post mortem death
 *   285	malloc() failure
 *   300	quick quit -- don't put on scoreboard
 */

static int scorerror;

died(x)
int x;
{
    register int f,win;
    char ch,*mod;
    long zzz,i;
    struct tms cputime;

    if (c[LIFEPROT] > 0) {	/* if life protection */
	switch((x > 0) ? x : -x) {
	    case 256: 
	    case 257: 
	    case 262: 
	    case 263: 
	    case 265: 
	    case 266: 
	    case 267: 
	    case 268: 
	    case 269: 
	    case 271: 
	    case 282: 
	    case 284: 
	    case 285: 
	    case 300: 
		goto invalid;	/* can't be saved */
	};
	--c[LIFEPROT];
	c[HP] = 1;
	--c[CONSTITUTION];
	cursors();
	lprcat("\nYou feel wiiieeeeerrrrrd all over! ");
	beep();
	lflush();
	sleep(4);
	return;			/* only case where died() returns */
    }
invalid: 
    clearvt100();
    lflush();
    f = 0;
    if (ckpflag)
	delete(ckpfile);	/* remove checkpoint file if used */
    if (x < 0) {
	f++;
	x = -x;
    }				/* if we are not to display the scores */
    if ((x == 300) ||(x == 257))
	exit();		/* for quick exit or saved game */
    if (x == 263)
	win = 1;
    else
	win = 0;
    c[GOLD] += c[BANKACCOUNT];
    c[BANKACCOUNT] = 0;
 /* 	now enter the player at the end of the scoreboard */
    newscore(c[GOLD], logname, x, win);
    diedsub(x);		/* print out the score line */
    lflush();

    set_score_output();
    if ((wizard == 0) &&(c[GOLD] > 0)) {/* 	wizards can't score		 */
	if (lappend(logfile) < 0) {/* append to file */
	    if (lcreat(logfile) < 0) {/* and can't create new log file */
		lcreat((char *) 0);
		lprcat("\nCan't open record file:  I can't post your score.\n");
		sncbr();
		resetscroll();
		lflush();
		exit();
	    }
	    chmod(logfile, 0666);
	}
	strcpy(logg.who, loginname);
	logg.score = c[GOLD];
	logg.diff = c[HARDGAME];
	if (x < 256) {
	    ch = *monster[x].name;
	    if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
		mod = "an";
	    else
		mod = "a";
	    sprintf(logg.what, "killed by %s %s", mod, monster[x].name);
	} else
	    sprintf(logg.what, "%s", whydead[x - 256]);
	logg.cavelev = level;
	time(&zzz);		/* get current time -- write out score info */
	logg.diedtime = zzz;
#ifdef EXTRA
	times(&cputime);	/* get cpu time -- write out score info */
	logg.cputime = i = (cputime.tms_utime + cputime.tms_stime - start_cpu) / 100 + c[CPUTIME];
	logg.lev = c[LEVEL];
	logg.ac = c[AC];
	logg.hpmax = c[HPMAX];
	logg.hp = c[HP];
	logg.elapsedtime = (zzz - initialtime + 59) / 60;
	logg.usage = (10000 * i) / (zzz - initialtime);
	logg.bytin = c[BYTESIN];
	logg.bytout = c[BYTESOUT];
	logg.moves = c[MOVESMADE];
	logg.spused = c[SPELLSCAST];
	logg.killed = c[MONSTKILLED];
#endif
	lwrite((char *) & logg, sizeof(struct log_fmt));
	lwclose();

    /* 	now for the scoreboard maintenance -- not for a suspended game 	 */
	if (x != 257) {
	    if (sortboard())
		scorerror = writeboard();
	}
    }
    if ((x == 256) ||(x == 257) ||(f != 0))
	exit();
    if (scorerror == 0)
	showscores();		/* if we updated the scoreboard */
    if (x == 263)
	mailbill();
    exit();
}

/*
 *	diedsub(x) Subroutine to print out the line showing the player when he is killed
 *		int x;
 */
diedsub(x)
int x;
{
    register char   ch,*mod;

    lprintf("Score: %d, Diff: %d,  %s ",(long) c[GOLD],(long) c[HARDGAME], logname);
    if (x < 256) {
	ch = *monster[x].name;
	if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
	    mod = "an";
	else
	    mod = "a";
	lprintf("killed by %s %s", mod, monster[x].name);
    }
    else
	lprintf("%s", whydead[x - 256]);
    if (x != 263)
	lprintf(" on %s\n", levelname[level]);
    else
	lprc('\n');
}

/*
 * diedlog() 	Subroutine to read a log file and print it out in ascii format
 */
diedlog()
{
    register int    n;
    register char  *p;
    struct stat stbuf;

    lcreat((char *) 0);
    if (lopen(logfile) < 0) {
	lprintf("Can't locate log file \"%s\"\n", logfile);
	return;
    }
    if (fstat(fd, &stbuf) < 0) {
	lprintf("Can't  stat log file \"%s\"\n", logfile);
	return;
    }
    for (n = stbuf.st_size / sizeof(struct log_fmt); n > 0; --n) {
	lrfill((char *) & logg, sizeof(struct log_fmt));
	p = ctime(&logg.diedtime);
	p[16] = '\n';
	p[17] = 0;
	lprintf("Score: %d, Diff: %d,  %s %s on %d at %s",(long)(logg.score),(long)(logg.diff), logg.who, logg.what,(long)(logg.cavelev), p + 4);
#ifdef EXTRA
	if (logg.moves <= 0)
	    logg.moves = 1;
	lprintf("  Experience Level: %d,  AC: %d,  HP: %d/%d,  Elapsed Time: %d minutes\n",
		(long)(logg.lev),(long)(logg.ac),(long)(logg.hp),(long)(logg.hpmax),(long)(logg.elapsedtime));
	lprintf("  CPU time used: %d seconds,  Machine usage: %d.%02d%%\n",
		(long)(logg.cputime),(long)(logg.usage / 100),(long)(logg.usage % 100));
	lprintf("  BYTES in: %d, out: %d, moves: %d, deaths: %d, spells cast: %d\n",
		(long)(logg.bytin),(long)(logg.bytout),(long)(logg.moves),(long)(logg.killed),(long)(logg.spused));
	lprintf("  out bytes per move: %d,  time per move: %d ms\n",
		(long)(logg.bytout / logg.moves),(long)((logg.cputime * 1000) / logg.moves));
#endif
    }
    lflush();
    lrclose();
    return;
}

#ifndef UIDSCORE
/*
 *	getplid(name)		Function to get players id # from id file
 *
 *	Enter with the name of the players character in name.
 *	Returns the id # of the players character, or -1 if failure.
 *	This routine will try to find the name in the id file, if its not there,
 *	it will try to make a new entry in the file.  Only returns -1 if can't
 *	find him in the file, and can't make a new entry in the file.
 *	Format of playerids file:
 *			Id # in ascii     \n     character name     \n   
 */
static int  havepid = -1;	/* playerid # if previously done */

getplid(nam)
char *nam;
{
    int fd7,high = 999,no;
    register char *p,*p2;
    char name[80];

    if (havepid != -1)
	return(havepid);	/* already did it */
    lflush();			/* flush any pending I/O */
    sprintf(name, "%s\n", nam);	/* append a \n to name */
    if (lopen(playerids) < 0) {	/* no file, make it */
	if (lcreat(playerids) < 0)
	    return(-1);	/* can't make it */
	lwclose();
	goto addone;		/* now append new playerid record to file */
    }
    for (;;) {			/* now search for the name in the player id file */
	p = lgetl();
	if (p == NULL)
	    break;		/* EOF? */
	no = atoi(p);		/* the id # */
	p2 = lgetl();
	if (p2 == NULL)
	    break;		/* EOF? */
	if (no > high)
	    high = no;		/* accumulate highest id # */
	if (strcmp(p2, name) == 0) {/* we found him */
	    return(no);	/* his id number */
	}
    }
    lrclose();
 /* if we get here, we didn't find him in the file -- put him there */
addone: 
    if (lappend(playerids) < 0)
	return(-1);		/* can't open file for append */
    lprintf("%d\n%s",(long) ++high, name);/* new id # and name */
    lwclose();
    lcreat((char *) 0);	/* re-open terminal channel */
    return(high);
}
#endif UIDSCORE
SHAR_EOF
if test 22296 -ne "`wc -c < 'scores.c'`"
then
	echo shar: error transmitting "'scores.c'" '(should have been 22296 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'store.c'" '(22511 characters)'
if test -f 'store.c'
then
	echo shar: will not over-write existing file "'store.c'"
else
cat << \SHAR_EOF > 'store.c'

/*	store.c		Larn is copyrighted 1986 by Noah Morgan. */

#include "header.h"

static int  dndcount = 0,dnditm = 0;

/* this is the data for the stuff in the dnd store	*/
int maxitm = 83;	/* number of items in the dnd inventory table  */

globaldef struct _itm itm[90] = {
 /* cost	memory 		iven name	iven arg	how
     gp		pointer		iven[]		ivenarg[]	many */

 {  2,		0,		OLEATHER,	0,	   	3    },
 {  10,		0,		OSTUDLEATHER,	0,		2    },
 {  40,		0,		ORING,		0,		2    },
 {  85, 	0,		OCHAIN,		0,		2    },
 {  220,	0,		OSPLINT,	0,		1    },
 {  400,	0,		OPLATE,		0,		1    },
 {  900,	0,		OPLATEARMOR,	0,		1    },
 {  2600,	0,		OSSPLATE,	0,		1    },
 {  150,	0,		OSHIELD,	0,		1    },

 /* cost	memory 		iven name	iven arg	how
     gp		pointer		iven[]		ivenarg[]	many */

 {  2,		0,		ODAGGER,	0,		3    },
 {  20,		0,		OSPEAR,		0,		3    },
 {  80, 0, OFLAIL, 0, 2},
 {  150, 0, OBATTLEAXE, 0, 2},
 {  450, 0, OLONGSWORD, 0, 2},
 {  1000, 0, O2SWORD, 0, 2},
 {  5000, 0, OSWORD, 0, 1},
 {  16500, 0, OLANCE, 0, 1},
 {  6000, 0, OSWORDofSLASHING, 0, 0},
 {  10000, 0, OHAMMER, 0, 0 },

 /* cost	memory 		iven name	iven arg	how
     gp		pointer		iven[]		ivenarg[]	many */

    {
	150, 0, OPROTRING, 1, 1
    }
    ,
    {
	85, 0, OSTRRING, 1, 1
    }
    ,
    {
	120, 0, ODEXRING, 1, 1
    }
    ,
    {
	120, 0, OCLEVERRING, 1, 1
    }
    ,
    {
	180, 0, OENERGYRING, 0, 1
    }
    ,
    {
	125, 0, ODAMRING, 0, 1
    }
    ,
    {
	220, 0, OREGENRING, 0, 1
    }
    ,
    {
	1000, 0, ORINGOFEXTRA, 0, 1
    }
    ,

    {
	280, 0, OBELT, 0, 1
    }
    ,

    {
	400, 0, OAMULET, 0, 1
    }
    ,

    {
	6500, 0, OORBOFDRAGON, 0, 0
    }
    ,
    {
	5500, 0, OSPIRITSCARAB, 0, 0
    }
    ,
    {
	5000, 0, OCUBEofUNDEAD, 0, 0
    }
    ,
    {
	6000, 0, ONOTHEFT, 0, 0
    }
    ,

    {
	590, 0, OCHEST, 6, 1
    }
    ,
    {
	200, 0, OBOOK, 8, 1
    }
    ,
    {
	10, 0, OCOOKIE, 0, 3
    }
    ,

 /* cost	memory 		iven name	iven arg	how
     gp		pointer		iven[]		ivenarg[]	many */

    {
	20, potionname, OPOTION, 0, 6
    }
    ,
    {
	90, potionname, OPOTION, 1, 5
    }
    ,
    {
	520, potionname, OPOTION, 2, 1
    }
    ,
    {
	100, potionname, OPOTION, 3, 2
    }
    ,
    {
	50, potionname, OPOTION, 4, 2
    }
    ,
    {
	150, potionname, OPOTION, 5, 2
    }
    ,
    {
	70, potionname, OPOTION, 6, 1
    }
    ,
    {
	30, potionname, OPOTION, 7, 7
    }
    ,
    {
	200, potionname, OPOTION, 8, 1
    }
    ,
    {
	50, potionname, OPOTION, 9, 1
    }
    ,
    {
	80, potionname, OPOTION, 10, 1
    }
    ,

 /* cost	memory 		iven name	iven arg	how
     gp		pointer		iven[]		ivenarg[]	many */

    {
	30, potionname, OPOTION, 11, 3
    }
    ,
    {
	20, potionname, OPOTION, 12, 5
    }
    ,
    {
	40, potionname, OPOTION, 13, 3
    }
    ,
    {
	35, potionname, OPOTION, 14, 2
    }
    ,
    {
	520, potionname, OPOTION, 15, 1
    }
    ,
    {
	90, potionname, OPOTION, 16, 2
    }
    ,
    {
	200, potionname, OPOTION, 17, 2
    }
    ,
    {
	220, potionname, OPOTION, 18, 4
    }
    ,
    {
	80, potionname, OPOTION, 19, 6
    }
    ,
    {
	370, potionname, OPOTION, 20, 3
    }
    ,
    {
	50, potionname, OPOTION, 22, 1
    }
    ,
    {
	150, potionname, OPOTION, 23, 3
    }
    ,

 /* cost	memory 		iven name	iven arg	how
     gp		pointer		iven[]		ivenarg[]	many */

    {
	100, scrollname, OSCROLL, 0, 2
    }
    ,
    {
	125, scrollname, OSCROLL, 1, 2
    }
    ,
    {
	60, scrollname, OSCROLL, 2, 4
    }
    ,
    {
	10, scrollname, OSCROLL, 3, 4
    }
    ,
    {
	100, scrollname, OSCROLL, 4, 3
    }
    ,
    {
	200, scrollname, OSCROLL, 5, 2
    }
    ,
    {
	110, scrollname, OSCROLL, 6, 1
    }
    ,
    {
	500, scrollname, OSCROLL, 7, 2
    }
    ,
    {
	200, scrollname, OSCROLL, 8, 2
    }
    ,
    {
	250, scrollname, OSCROLL, 9, 4
    }
    ,
    {
	20, scrollname, OSCROLL, 10, 5
    }
    ,
    {
	30, scrollname, OSCROLL, 11, 3
    }
    ,

 /* cost	memory 		iven name	iven arg	how
     gp		pointer		iven[]		ivenarg[]	many */

    {
	340, scrollname, OSCROLL, 12, 1
    }
    ,
    {
	340, scrollname, OSCROLL, 13, 1
    }
    ,
    {
	300, scrollname, OSCROLL, 14, 2
    }
    ,
    {
	400, scrollname, OSCROLL, 15, 2
    }
    ,
    {
	500, scrollname, OSCROLL, 16, 2
    }
    ,
    {
	1000, scrollname, OSCROLL, 17, 1
    }
    ,
    {
	500, scrollname, OSCROLL, 18, 1
    }
    ,
    {
	340, scrollname, OSCROLL, 19, 2
    }
    ,
    {
	220, scrollname, OSCROLL, 20, 3
    }
    ,
    {
	3900, scrollname, OSCROLL, 21, 0
    }
    ,
    {
	610, scrollname, OSCROLL, 22, 1
    }
    ,
    {
	3000, scrollname, OSCROLL, 23, 0
    }
};


/*
	function for the dnd store
 */
dnd_2hed()
{
    lprcat("Welcome to the Larn Thrift Shoppe.  We stock many items explorers find useful\n");
    lprcat(" in their adventures.  Feel free to browse to your hearts content.\n");
    lprcat("Also be advised, if you break 'em, you pay for 'em.");
}

dnd_hed()
{
    register int i;

    for (i = dnditm; i < 26 + dnditm; i++)
	dnditem(i);
    cursor(50, 18);
    lprcat("You have ");
}

dndstore()
{
    register int i;

    dnditm = 0;
    nosignal = 1;		/* disable signals */
    clear();
    dnd_2hed();
    if (outstanding_taxes > 0) {
	lprcat("\n\nThe Larn Revenue Service has ordered us to not do business with tax evaders.\n");
	beep();
	lprintf("They have also told us that you owe %d gp in back taxes, and as we must\n",(long) outstanding_taxes);
	lprcat("comply with the law, we cannot serve you at this time.  Soo Sorry.\n");
	cursors();
	lprcat("\nPress ");
	standout("escape");
	lprcat(" to leave: ");
	lflush();
	i = 0;
	while (i != '\33')
	    i = readchar();
	drawscreen();
	nosignal = 0;		/* enable signals */
	return;
    }

    dnd_hed();
    while (1) {
	cursor(59, 18);
	lprintf("%d gold pieces",(long) c[GOLD]);
	cltoeoln();
	cl_dn(1, 20);		/* erase to eod */
	lprcat("\nEnter your transaction [");
	standout("space");
	lprcat(" for more, ");
	standout("escape");
	lprcat(" to leave]? ");
	i = 0;
	while ((i < 'a' || i > 'z') &&(i != ' ') &&(i != '\33') &&(i != 12))
	    i = readchar();
	if (i == 12) {
	    clear();
	    dnd_2hed();
	    dnd_hed();
	} else
	    if (i == '\33') {
		drawscreen();
		nosignal = 0;	/* enable signals */
		return;
	    } else
		if (i == ' ') {
		    cl_dn(1, 4);
		    if ((dnditm += 26) >= maxitm)
			dnditm = 0;
		    dnd_hed();
		} else {		/* buy something */
		    lprc(i);	/* echo the byte */
		    i += dnditm - 'a';
		    if (i >= maxitm)
			outofstock();
		    else
			if (itm[i].qty <= 0)
			    outofstock();
			else
			    if (pocketfull())
				handsfull();
			    else
				if (c[GOLD] < itm[i].price * 10)
				    nogold();
				else {
				    if (itm[i].mem != 0)
					*itm[i].mem[itm[i].arg] = ' ';
				    c[GOLD] -= itm[i].price * 10;
				    itm[i].qty--;
				    take(itm[i].obj, itm[i].arg);
				    if (itm[i].qty == 0)
					dnditem(i);
				    nap(1001);
				}
		}

    }
}


/*
	function for the players hands are full
 */
static  handsfull()
{
    lprcat("\nYou can't carry anything more!");
    lflush();
    nap(2200);
}

static  outofstock()
{
    lprcat("\nSorry, but we are out of that item.");
    lflush();
    nap(2200);
}

static  nogold()
{
    lprcat("\nYou don't have enough gold to pay for that!");
    lflush();
    nap(2200);
}

/*
	dnditem(index)

	to print the item list;  used in dndstore() enter with the index into itm
 */
static  dnditem(i)
register int i;
{
    register int    j,k;

    if (i >= maxitm)
	return;
    cursor((j = (i & 1) * 40 + 1),(k = ((i % 26) >> 1) + 5));
    if (itm[i].qty == 0) {
	lprintf("%39s", "");
	return;
    }
    lprintf("%c) ",(i % 26) + 'a');
    if (itm[i].obj == OPOTION) {
	lprcat("potion of ");
	lprintf("%s", &potionname[itm[i].arg][1]);
    } else
	if (itm[i].obj == OSCROLL) {
	    lprcat("scroll of ");
	    lprintf("%s", &scrollname[itm[i].arg][1]);
	} else
	    lprintf("%s", objectname[itm[i].obj]);
    cursor(j + 31, k);
    lprintf("%6d",(long)(itm[i].price * 10));
}


/*
	for the college of larn
 */
globaldef char course[26] = 0;		/* the list of courses taken */
char coursetime[] = {
    10, 15, 10, 20, 10, 10, 10, 5
};
/*
	function to display the header info for the school
 */
sch_hed()
{
    clear();
    lprcat("The College of Larn offers the exciting opportunity of higher education to\n");
    lprcat("all inhabitants of the caves.  Here is a list of the class schedule:\n\n\n");
    lprcat("\t\t    Course Name \t       Time Needed\n\n");

    if (course[0] == 0)
	lprcat("\t\ta)  Fighters Training I         10 mobuls");/* line 7 of crt */
    lprc('\n');
    if (course[1] == 0)
	lprcat("\t\tb)  Fighters Training II        15 mobuls");
    lprc('\n');
    if (course[2] == 0)
	lprcat("\t\tc)  Introduction to Wizardry    10 mobuls");
    lprc('\n');
    if (course[3] == 0)
	lprcat("\t\td)  Applied Wizardry            20 mobuls");
    lprc('\n');
    if (course[4] == 0)
	lprcat("\t\te)  Behavioral Psychology       10 mobuls");
    lprc('\n');
    if (course[5] == 0)
	lprcat("\t\tf)  Faith for Today             10 mobuls");
    lprc('\n');
    if (course[6] == 0)
	lprcat("\t\tg)  Contemporary Dance          10 mobuls");
    lprc('\n');
    if (course[7] == 0)
	lprcat("\t\th)  History of Larn              5 mobuls");

    lprcat("\n\n\t\tAll courses cost 250 gold pieces.");
    cursor(30, 18);
    lprcat("You are presently carrying ");
}

oschool() {
    register int    i;
    long    time_used;
    nosignal = 1;		/* disable signals */
    sch_hed();
    while (1) {
	cursor(57, 18);
	lprintf("%d gold pieces.   ",(long) c[GOLD]);
	cursors();
	lprcat("\nWhat is your choice [");
	standout("escape");
	lprcat(" to leave] ? ");
	yrepcount = 0;
	i = 0;
	while ((i < 'a' || i > 'h') &&(i != '\33') &&(i != 12))
	    i = readchar();
	if (i == 12) {
	    sch_hed();
	    continue;
	}
	else
	    if (i == '\33') {
		nosignal = 0;
		drawscreen();	/* enable signals */
		return;
	    }
	lprc(i);
	if (c[GOLD] < 250)
	    nogold();
	else
	    if (course[i - 'a']) {
		lprcat("\nSorry, but that class is filled.");
		nap(1000);
	    }
	    else
		if (i <= 'h') {
		    c[GOLD] -= 250;
		    time_used = 0;
		    switch(i) {
			case 'a': 
			    c[STRENGTH] += 2;
			    c[CONSTITUTION]++;
			    lprcat("\nYou feel stronger!");
			    cl_line(16, 7);
			    break;

			case 'b': 
			    if (course[0] == 0) {
				lprcat("\nSorry, but this class has a prerequisite of Fighters Training I");
				c[GOLD] += 250;
				time_used = -10000;
				break;
			    }
			    lprcat("\nYou feel much stronger!");
			    cl_line(16, 8);
			    c[STRENGTH] += 2;
			    c[CONSTITUTION] += 2;
			    break;

			case 'c': 
			    c[INTELLIGENCE] += 2;
			    lprcat("\nThe task before you now seems more attainable!");
			    cl_line(16, 9);
			    break;

			case 'd': 
			    if (course[2] == 0) {
				lprcat("\nSorry, but this class has a prerequisite of Introduction to Wizardry");
				c[GOLD] += 250;
				time_used = -10000;
				break;
			    }
			    lprcat("\nThe task before you now seems very attainable!");
			    cl_line(16, 10);
			    c[INTELLIGENCE] += 2;
			    break;

			case 'e': 
			    c[CHARISMA] += 3;
			    lprcat("\nYou now feel like a born leader!");
			    cl_line(16, 11);
			    break;

			case 'f': 
			    c[WISDOM] += 2;
			    lprcat("\nYou now feel more confident that you can find the potion in time!");
			    cl_line(16, 12);
			    break;

			case 'g': 
			    c[DEXTERITY] += 3;
			    lprcat("\nYou feel like dancing!");
			    cl_line(16, 13);
			    break;

			case 'h': 
			    c[INTELLIGENCE]++;
			    lprcat("\nYour instructor told you that the Eye of Larn is rumored to be guarded\n");
			    lprcat("by a platinum dragon who possesses psionic abilities. ");
			    cl_line(16, 14);
			    break;
		    }
		    time_used += coursetime[i - 'a'] * 100;
		    if (time_used > 0) {
			gtime += time_used;
			course[i - 'a']++;/* 	remember that he has taken that course	 */
			c[HP] = c[HPMAX];
			c[SPELLS] = c[SPELLMAX];/* he regenerated */


			if (c[BLINDCOUNT])
			    c[BLINDCOUNT] = 1;/* cure blindness too!  */
			if (c[CONFUSE])
			    c[CONFUSE] = 1;/* 	end confusion	 */
			adjtime((long) time_used);/* adjust parameters for time change */
		    }
		    nap(1000);
		}
    }
}

/*
 *	for the first national bank of Larn
 */
int     lasttime = 0;		/* last time he was in bank */
obank() {
    banktitle("    Welcome to the First National Bank of Larn.");
}
obank2() {
    banktitle("Welcome to the 5th level branch office of the First National Bank of Larn.");
}
static  banktitle(str)
char   *str;
{
    nosignal = 1;		/* disable signals */
    clear();
    lprcat(str);
    if (outstanding_taxes > 0) {
	register int    i;
	lprcat("\n\nThe Larn Revenue Service has ordered that your account be frozen until all\n");
	beep();
	lprintf("levied taxes have been paid.  They have also told us that you owe %d gp in\n",(long) outstanding_taxes);
	lprcat("taxes, and we must comply with them. We cannot serve you at this time.  Sorry.\n");
	lprcat("We suggest you go to the LRS office and pay your taxes.\n");
	cursors();
	lprcat("\nPress ");
	standout("escape");
	lprcat(" to leave: ");
	lflush();
	i = 0;
	while (i != '\33')
	    i = readchar();
	drawscreen();
	nosignal = 0;		/* enable signals */
	return;
    }
    lprcat("\n\n\tGemstone\t      Appraisal\t\tGemstone\t      Appraisal");
    obanksub();
    nosignal = 0;		/* enable signals */
    drawscreen();
}

/*
 *	function to put interest on your bank account
 */
ointerest() {
    register int    i;
    if (c[BANKACCOUNT] < 0)
	c[BANKACCOUNT] = 0;
    else
	if ((c[BANKACCOUNT] > 0) &&(c[BANKACCOUNT] < 500000)) {
	    i = (gtime - lasttime) / 100;/* # mobuls elapsed */
	    while ((i-- > 0) &&(c[BANKACCOUNT] < 500000))
		c[BANKACCOUNT] += c[BANKACCOUNT] / 250;
	    if (c[BANKACCOUNT] > 500000)
		c[BANKACCOUNT] = 500000;/* interest limit */
	}
    lasttime = (gtime / 100) * 100;
}

static short    gemorder[26] = 0;/* the reference to screen location for each */
static long gemvalue[26] = 0;	/* the appraisal of the gems */
obanksub() {
    unsigned long   amt;
    register int    i,
                    k;
    ointerest();		/* credit any needed interest */

    for (k = i = 0; i < 26; i++)
	switch(iven[i]) {
	    case OLARNEYE: 
	    case ODIAMOND: 
	    case OEMERALD: 
	    case ORUBY: 
	    case OSAPPHIRE: 

		if (iven[i] == OLARNEYE) {
		    gemvalue[i] = 250000 - ((gtime * 7) / 100) * 100;
		    if (gemvalue[i] < 50000)
			gemvalue[i] = 50000;
		}
		else
		    gemvalue[i] = (255 & ivenarg[i]) * 100;
		gemorder[i] = k;
		cursor((k % 2) * 40 + 1,(k >> 1) + 4);
		lprintf("%c) %s", i + 'a', objectname[iven[i]]);
		cursor((k % 2) * 40 + 33,(k >> 1) + 4);
		lprintf("%5d",(long) gemvalue[i]);
		k++;
	};
    cursor(31, 17);
    lprintf("You have %8d gold pieces in the bank.",(long) c[BANKACCOUNT]);
    cursor(40, 18);
    lprintf("You have %8d gold pieces",(long) c[GOLD]);
    if (c[BANKACCOUNT] + c[GOLD] >= 500000)
	lprcat("\nNote:  Larndom law states that only deposits under 500,000gp  can earn interest.");
    while (1) {
	cl_dn(1, 20);
	lprcat("\nYour wish? [(");
	standout("d");
	lprcat(") deposit,(");
	standout("w");
	lprcat(") withdraw,(");
	standout("s");
	lprcat(") sell a stone, or ");
	standout("escape");
	lprcat("]  ");
	yrepcount = 0;
	i = 0;
	while (i != 'd' && i != 'w' && i != 's' && i != '\33')
	    i = readchar();
	switch(i) {
	    case 'd': 
		lprcat("deposit\nHow much? ");
		amt = readnum((long) c[GOLD]);
		if (amt < 0) {
		    lprcat("\nSorry, but we can't take negative gold!");
		    nap(2000);
		    amt = 0;
		}
		else
		    if (amt > c[GOLD]) {
			lprcat("  You don't have that much.");
			nap(2000);
		    }
		    else {
			c[GOLD] -= amt;
			c[BANKACCOUNT] += amt;
		    }
		break;

	    case 'w': 
		lprcat("withdraw\nHow much? ");
		amt = readnum((long) c[BANKACCOUNT]);
		if (amt < 0) {
		    lprcat("\nSorry, but we don't have any negative gold!");
		    nap(2000);
		    amt = 0;
		}
		else
		    if (amt > c[BANKACCOUNT]) {
			lprcat("\nYou don't have that much in the bank!");
			nap(2000);
		    }
		    else {
			c[GOLD] += amt;
			c[BANKACCOUNT] -= amt;
		    }
		break;

	    case 's': 
		lprcat("\nWhich stone would you like to sell? ");
		i = 0;
		while ((i < 'a' || i > 'z') && i != '*')
		    i = readchar();
		if (i == '*')
		    for (i = 0; i < 26; i++) {
			if (gemvalue[i]) {
			    c[GOLD] += gemvalue[i];
			    iven[i] = 0;
			    gemvalue[i] = 0;
			    k = gemorder[i];
			    cursor((k % 2) * 40 + 1,(k >> 1) + 4);
			    lprintf("%39s", "");
			}
		    }
		else {
		    if (gemvalue[i = i - 'a'] == 0) {
			lprintf("\nItem %c is not a gemstone!", i + 'a');
			nap(2000);
			break;
		    }
		    c[GOLD] += gemvalue[i];
		    iven[i] = 0;
		    gemvalue[i] = 0;
		    k = gemorder[i];
		    cursor((k % 2) * 40 + 1,(k >> 1) + 4);
		    lprintf("%39s", "");
		}
		break;

	    case '\33': 
		return;
	};
	cursor(40, 17);
	lprintf("%8d",(long) c[BANKACCOUNT]);
	cursor(49, 18);
	lprintf("%8d",(long) c[GOLD]);
    }
}

/*
	subroutine to appraise any stone for the bank
 */
appraise(gemstone)
register int    gemstone;
{
    register int    j,
                    amt;
    for (j = 0; j < 26; j++)
	if (iven[j] == gemstone) {
	    lprintf("\nI see you have %s", objectname[gemstone]);
	    if (gemstone == OLARNEYE)
		lprcat("  I must commend you.  I didn't think\nyou could get it.");
	    lprcat("  Shall I appraise it for you? ");
	    yrepcount = 0;
	    if (getyn() == 'y') {
		lprcat("yes.\n  Just one moment please \n");
		nap(1000);
		if (gemstone == OLARNEYE) {
		    amt = 250000 - ((gtime * 7) / 100) * 100;
		    if (amt < 50000)
			amt = 50000;
		}
		else
		    amt = (255 & ivenarg[j]) * 100;
		lprintf("\nI can see this is an excellent stone, It is worth %d",(long) amt);
		lprcat("\nWould you like to sell it to us? ");
		yrepcount = 0;
		if (getyn() == 'y') {
		    lprcat("yes\n");
		    c[GOLD] += amt;
		    iven[j] = 0;
		}
		else
		    lprcat("no thank you.\n");
		if (gemstone == OLARNEYE)
		    lprcat("It is, of course, your privilege to keep the stone\n");
	    }
	    else
		lprcat("no\nO. K.\n");
	}
}
/*
	function for the trading post
 */
static  otradhead() {
            clear();
    lprcat("Welcome to the Larn Trading Post.  We buy items that explorers no longer find\n");
    lprcat("useful.  Since the condition of the items you bring in is not certain,\n");
    lprcat("and we incur great expense in reconditioning the items, we usually pay\n");
    lprcat("only 20% of their value were they to be new.  If the items are badly\n");
    lprcat("damaged, we will pay only 10% of their new value.\n\n");
}

otradepost() {
    register int    i,
                    j,
                    value,
                    isub,
                    izarg;
    dnditm = dndcount = 0;
    nosignal = 1;		/* disable signals */
    resetscroll();
    otradhead();
    while (1) {
	lprcat("\nWhat item do you want to sell to us [");
	standout("*");
	lprcat(" for list, or ");
	standout("escape");
	lprcat("] ? ");
	i = 0;
	while (i > 'z' ||(i < 'a' && i != '*' && i != '\33' && i != '.'))
	    i = readchar();
	if (i == '\33') {
	    setscroll();
	    recalc();
	    drawscreen();
	    nosignal = 0;	/* enable signals */
	    return;
	}
	isub = i - 'a';
	j = 0;
	if (iven[isub] == OSCROLL)
	    if (scrollname[ivenarg[isub]][0] == 0) {
		j = 1;
		cnsitm();
	    }			/* can't sell unidentified item */
	if (iven[isub] == OPOTION)
	    if (potionname[ivenarg[isub]][0] == 0) {
		j = 1;
		cnsitm();
	    }			/* can't sell unidentified item */
	if (!j)
	    if (i == '*') {
		clear();
		qshowstr();
		otradhead();
	    }
	    else
		if (iven[isub] == 0)
		    lprintf("\nYou don't have item %c!", isub + 'a');
		else {
		    for (j = 0; j < maxitm; j++)
			if ((itm[j].obj == iven[isub]) ||(iven[isub] == ODIAMOND) ||(iven[isub] == ORUBY) ||(iven[isub] == OEMERALD) ||(iven[isub] == OSAPPHIRE)) {
			    srcount = 0;
			    show3(isub);/* show what the item was */
			    if ((iven[isub] == ODIAMOND) ||(iven[isub] == ORUBY)
				    ||(iven[isub] == OEMERALD) ||(iven[isub] == OSAPPHIRE))
				value = 20 * ivenarg[isub];
			    else
				if ((itm[j].obj == OSCROLL) ||(itm[j].obj == OPOTION))
				    value = 2 * itm[j + ivenarg[isub]].price;
				else {
				    izarg = ivenarg[isub];
				    value = itm[j].price;/* appreciate if a +n object */
				    if (izarg >= 0)
					value *= 2;
				    while ((izarg-- > 0) &&((value = 14 *(67 + value) / 10) < 500000));
				}
			    lprintf("\nItem(%c) is worth %d gold pieces to us.  Do you want to sell it? ", i,(long) value);
			    yrepcount = 0;
			    if (getyn() == 'y') {
				lprcat("yes\n");
				c[GOLD] += value;
				if (c[WEAR] == isub)
				    c[WEAR] = -1;
				if (c[WIELD] == isub)
				    c[WIELD] = -1;
				if (c[SHIELD] == isub)
				    c[SHIELD] = -1;
				adjustcvalues(iven[isub], ivenarg[isub]);
				iven[isub] = 0;
			    }
			    else
				lprcat("no thanks.\n");
			    j = maxitm + 100;/* get out of the inner loop */
			}
		    if (j <= maxitm + 2)
			lprcat("\nSo sorry, but we are not authorized to accept that item.");
		}
    }
}

cnsitm() {
    lprcat("\nSorry, we can't accept unidentified objects.");
}

/*
 *	for the Larn Revenue Service
 */
olrs() {
    register int    i,
                    first;
    unsigned long   amt;
    first = nosignal = 1;	/* disable signals */
    clear();
    resetscroll();
    cursor(1, 4);
    lprcat("Welcome to the Larn Revenue Service district office.  How can we help you?");
    while (1) {
	if (first) {
	    first = 0;
	    goto nxt;
	}
	cursors();
	lprcat("\n\nYour wish? [(");
	standout("p");
	lprcat(") pay taxes, or ");
	standout("escape");
	lprcat("]  ");
	yrepcount = 0;
	i = 0;
	while (i != 'p' && i != '\33')
	    i = readchar();
	switch(i) {
	    case 'p': 
		lprcat("pay taxes\nHow much? ");
		amt = readnum((long) c[GOLD]);
		if (amt < 0) {
		    lprcat("\nSorry, but we can't take negative gold\n");
		    amt = 0;
		}
		else
		    if (amt > c[GOLD])
			lprcat("  You don't have that much.\n");
		    else
			c[GOLD] -= paytaxes((long) amt);
		break;

	    case '\33': 
		nosignal = 0;	/* enable signals */
		setscroll();
		drawscreen();
		return;
	};

nxt: 
	cursor(1, 6);
	if (outstanding_taxes > 0)
	    lprintf("You presently owe %d gp in taxes.  ",(long) outstanding_taxes);
	else
	    lprcat("You do not owe us any taxes.           ");
	cursor(1, 8);
	if (c[GOLD] > 0)
	    lprintf("You have %6d gp.    ",(long) c[GOLD]);
	else
	    lprcat("You have no gold pieces.  ");
    }
}
SHAR_EOF
if test 22511 -ne "`wc -c < 'store.c'`"
then
	echo shar: error transmitting "'store.c'" '(should have been 22511 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0