[comp.sources.games] v02i011: nethack - display oriented dungeons & dragons, Part11/16

games-request@tekred.TEK.COM (07/28/87)

Submitted by: mike@genat.UUCP (Mike Stephenson)
Comp.sources.games: Volume 2, Issue 11
Archive-name: nethack/Part11



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 11 (of 16)."
# Contents:  README.OLD cmd.c data.base save.c spell.c worn.c
# Wrapped by billr@tekred on Tue Jul 28 09:49:40 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README.OLD -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README.OLD\"
else
echo shar: Extracting \"README.OLD\" \(10200 characters\)
sed "s/^X//" >README.OLD <<'END_OF_README.OLD'
X
X	This file consists of all previous README files for the game, as
Xreleased with the original version (Jay F.), first usenet version (Andries B.),
Xand PC-Hack (Don K.).  This way "README" is current for this version.
X
X						Mike Stephenson
X
X-- Original README file --------------------------------------------------------
X
XThis is export hack, my first semester programming project.
X
XTo set it up for your system, you will have to do the following:
X	1: create a hack uid, to own the top ten list, etc.
X	2: create a hack directory "/usr/lib/game/hack" is the default.
X	2.5: make the directory 700 mode.	/* sav files go in there...*/
X	3: modify hack.main.c to use the new directory.
X	4: modify hack.main.c so it uses the new hack gid.  Gid accounts can
Xgo into magic mode without the password, can get cores with ^G, etc.
X(make sure gid isn't checked anywhere else...)
X	5: recompile hack.
X	6: put it in games after making it set-uid hack.
X	8: fix the bugs I undobtedly left in it.
X	9: tell me what you think of it.
X
X	Hack uses the UCB file /etc/termcap to get your terminal escape codes.
XIf you don't use it, you will have to make extensive changes to hack.pri.c
X
XIf you find any bugs (That you think I don't know about), or have any
Xawesome new changes (Like a better save (One that works!)), or have ANY
Xquestions, write me
X		Jay Fenlason
X		29 East St.
X		Sudbury Mass.
X			01776
X
Xor call me at (617) 443-5036.  Since I have both a modem and a teen-age
Xsister, Good Luck.
X
X
XHack is split (roughly) into several source files that do different things.
XI have tried to fit all the procedures having to do with a certain segment
Xof the game into a single file, but the job is not the best in the world.
XThe rough splits are:
X
Xhack.c		General random stuff and things I never got around to moving.
Xhack.main.c	main() and other random procedures, also the lock file stuff.
Xhack.mon.c	Monsters, moving, attacking, etc.
Xhack.do.c	drink, eat, read, wield, save, etc.
Xhack.do1.c	zap, wear, remove, etc...
Xhack.pri.c	stuff having to do with the screen, most of the terminal
X		independant stuff is in here.
Xhack.lev.c	temp files and calling of mklev.
X
XBecause of the peculiar restraints on our system, I make mklev (create
Xa level) a separate procedure execd by hack when needed.  The source for
Xmklev is (Naturaly) mklev.c.  You may want to put mklev back into hack.
XGood luck.
X
XMost of hack was written by me, with help from
X		Kenny Woodland (KW)	(general random things including
X			the original BUZZ())
X		Mike Thome	(MT)	(The original chamelian)
X	and	Jon Payne	(JP)	(The original lock file kludge and
X			the massive CURS())
X
XThis entire program would not have been possible without the SFSU Logo
XWorkshop.  I am eternally grateful to all of our students (Especially K.L.),
Xwithout whom I would never have seen Rogue.  I am especially grateful to
XMike Clancy, without whose generous help I would never have gotten to play
XROGUE.
X
X-- Hack 1.0.x README file ------------------------------------------------------
X
XHack is a display oriented dungeons & dragons - like game.
XBoth display and command structure resemble rogue.
X(For a game with the same structure but entirely different display -
Xa real cave instead of dull rectangles - try Quest)
X
XHack was originally written by Jay Fenlason (at lincolnsudbury:
X 29 East St., Sudbury Mass., 01776) with help from
X Kenny Woodland, Mike Thome and Jon Payne.
XBasically it was an implementation of Rogue, however, with 52+ instead of 26
X monster types.
XThe current version is more than thrice as large (with such new features as
X the dog, the long worms, the shops, etc.) and almost entirely rewritten
X (only the display routines are the original ones - I must rewrite these
X too one day; especially when you are blind strange things still happen).
X
XFiles for hack:
X	hack		The actual game
X	record		Top 100 list (just start with an empty file)
X	news		Tells about recent changes in hack, or bugs found ...
X			(Just start with no news file.)
X	data		Auxiliary file used by hack to give you the names
X			and sometimes some more information on the
X			objects and monsters.
X	help		Introductory information (no doubt outdated).
X	hh		Compactified version of help.
X	perm		An empty file used for locking purposes.
X	rumors		Texts for fortune cookies.
X			(Some of these contain information on the game,
X			others are just plain stupid. Additional rumors
X			are appreciated.)
X	hack.sh		A shell script.
X			(We have hack.sh in /usr/games/hack and
X			hack in /usr/games/lib/hackdir/hack and all the other
X			hack stuff in /usr/games/lib/hackdir - perhaps this
X			will make the script clear.
X			There is no need for you to use it.)
X	READ_ME		This file.
X	Original_READ_ME Jay Fenlason's READ_ME
X
XSystem files used:
X	/etc/termcap	Used in conjunction with the environment variable
X			$TERM.
X	/bin/cat
X	/usr/ucb/more
X	/bin/sh		Used when $SHELL is undefined.
X
XHow to install hack:
X0. Compile the sources. Perhaps you should first look at the file config.h
X   and define BSD if you are on a BSDtype system,
X   define STUPID if your C-compiler chokes on complicated expressions.
X   Make sure schar and uchar represent signed and unsigned types.
X   If your C compiler doesnt allow initialization of bit fields
X   change Bitfield. When config.h looks reasonable, say 'make'.
X   (Perhaps you have to change TERMLIB in the makefile.)
X1. If it didnt exist already, introduce a loginname `play' .
X2. The program  hack  resides in a directory so that it is executable
X   for everybody and is suid play:
X	---s--s--x  1 play	206848 Apr  3 00:17 hack
X   Perhaps you wish to restrict playing to certain hours, or have games
X   running under nice; in that case you might write a program play.c
X   such that the program play is suid play and executable for everybody
X   while all the games in /usr/games are readable or executable for
X   play only; all the program play does is asking for the name of a game,
X   checking that time-of-day and system load do not forbid playing,
X   and then executing the game. Thus:
X	-r-sr-sr-x  1 play	 13312 May 24 12:52 play
X	---x------  1 play	206848 Apr  3 00:17 hack
X   If you are worried about security you might let play do
X   chroot("/usr/games") so that no player can get access to the rest
X   of the system via shell escapes and the likes.
X   If you #define SECURE in config.h then hack will not setuid(getuid())
X   before executing a chdir(). Hack will always do setuid(getuid()) with
X   a fork. If you do not define UNIX then hack will not fork.
X3. The rest of the stuff belonging to hack sits in a subdirectory hackdir
X   (on our system /usr/games/lib/hackdir) with modes
X	drwx------  3 play	1024 Aug  9 09:03 hackdir
X   Here all the temporary files will be created (with names like xlock.17
X   or user.5).
X4. If you are not really short on file space, creating a subdirectory
X   hackdir/save (modes again drwx------) will enable users to save their
X   unfinished games.
X
XThe program hack is called
X$ hack [-d hackdir] [maxnrofplayers]
X(for playing) or
X$ hack [-d hackdir] -s [listofusers | limit | all]
X(for seeing part of the scorelist).
XThe shell file hack (in this kit called hack.sh) takes care of
Xcalling hack with the right arguments.
X
XSend complaints, bug reports, suggestions for improvements to
Xmcvax!aeb - in real life Andries Brouwer.
X
X-- PC Hack 3.51 README file ----------------------------------------------------
X
X	Welcome to the sources for PC HACK (version 3.51).
X
XIntroduction
X------------
XThis is a version of the public domain program HACK 1.03 (copyright
XStichting Mathematisch Centrum, Amsterdam, 1984, 1985.) implemented
Xunder MSDOS with the Microsoft(tm) C v3.0 compiler.
X
XYou may copy this version of PC HACK and make any changes you want to
Xit.  You may give it away, but you may not sell it.
X
X
XThe sources are in ARC format in HACK351S.ARC.  The commands:
X
X	C> arc51 e hack351s makefile make.*
X	C> arc51 e hack351s *.h
X	C> arc51 e hack351s *.c
X
Xwill unpack the files.
X
XWith a hard disk system, you should be able to type `make' and the sources
Xwill start to be compiled.  This takes a long time.  A floppy disk system
Xdoes not really have enough storage.
X
X
XCompiling
X---------
XThe LARGE compiler model is used.  To add WIZARD mode, add a -DWIZARD
Xto the MAKEFILE, or a #define WIZARD to the CONFIG.H file.
X
XThe MAKEFILE included with PC HACK 3.51 sources is for my version of MAKE.
XIt is very similar to UNIX(tm) `make'.  See MAKE.DOC for details.
X
XTo compile the sources by hand the command for each `filename.c' file is:
X	msc -AL -DREGBUG -DLINT_ARGS -Ot -Gs filename.c;
X
X
XLinking
X-------
XI used the Microsoft 8086 Linker version 3.01
X
XTo link the *.obj files by hand, the command is:
X	link @linkfile
X
XWhere the contents of the linkfile (not supplied) should be:
X
Xdecl.obj apply.obj bones.obj cmd.obj do.obj +
Xdo_name.obj do_wear.obj dog.obj eat.obj +
Xend.obj engrave.obj fight.obj hack.obj +
Xinvent.obj ioctl.obj lev.obj main.obj +
Xmakemon.obj mhitu.obj mklev.obj mkmaze.obj +
Xmkobj.obj mkshop.obj mon.obj monst.obj +
Xo_init.obj objnam.obj options.obj pager.obj +
Xpotion.obj pri.obj read.obj rip.obj +
Xrumors.obj save.obj search.obj shk.obj +
Xshknam.obj steal.obj termcap.obj +
Xtimeout.obj topl.obj track.obj trap.obj +
Xtty.obj unix.obj u_init.obj vault.obj +
Xwield.obj wizard.obj worm.obj worn.obj +
Xzap.obj version.obj rnd.obj alloc.obj +
Xmsdos.obj 
Xhack /NOIG /STACK:4000; 
X
X
XDifferences from UNIX HACK
X--------------------------
XChanges that were introduced to port UNIX HACK to the MSDOS environment
Xare surrounded with `#ifdef MSDOS', `#endif' directives.
X
XOther changes I have made are surrounded by `#ifdef DGK', `#endif'
Xdirectives.  It should be possible to compile these sources without
Xany of my changes by removing the `#define DGK' line from CONFIG.H.
X
XAlso, functions I have added are mainly restricted to the file msdos.c,
Xalthough some of them are in other places (ie. wizard.c)
X
X
XFinally
X-------
XIf you have any questions, contact me at one of:
X
X	Don Kneller
X	UUCP:	...ucbvax!ucsfcgl!kneller
X	ARPA:	kneller@ucsf-cgl.ARPA
X	BITNET:	kneller@ucsfcgl.BITNET
X	USMAIL:	D. G. Kneller
X		2 Panoramic Way #204
X		Berkeley, CA 94704
X
X--------------------------------------------------------------------------------
XEND OF FILE
END_OF_README.OLD
if test 10200 -ne `wc -c <README.OLD`; then
    echo shar: \"README.OLD\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cmd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cmd.c\"
else
echo shar: Extracting \"cmd.c\" \(10152 characters\)
sed "s/^X//" >cmd.c <<'END_OF_cmd.c'
X/*	SCCS Id: @(#)cmd.c	1.3	87/07/14
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* cmd.c - version 1.0.3 */
X
X#include	"hack.h"
X#include	"func_tab.h"
X
Xint doredraw(),doredotopl(),dodrop(),dodrink(),doread(),dosearch(),dopickup(),
Xdoversion(),doweararm(),dowearring(),doremarm(),doddoremarm(),doremring(),
Xdopay(),doapply(),dosave(),dowield(),ddoinv(),dozap(),ddocall(),dowhatis(),
Xdoengrave(),dotele(),dohelp(),doeat(),doddrop(),do_mname(),doidtrap(),
Xdoprwep(),doprarm(),doprring(),doprgold(),dodiscovered(),dotypeinv(),dolook(),
Xdoset(),doup(), dodown(), done1(), donull(), dothrow(), doextcmd(), dodip(),
Xdopray(), doextlist();
X#ifdef NEWCLASS
Xint dosit();
X#endif
X#ifdef SPELLS
Xint docast(), dovspell(), doxcribe();
X#endif
X#ifdef SHELL
Xint dosh();
X#endif
X#ifdef SUSPEND
Xint dosuspend();
X#endif
X#ifdef KAA
Xint doremove(), dobreathe();
X# ifdef KOPS
Xint dowipe();
X# endif
X#endif
X
Xint rndobjsym(), rndmonsym();
Xchar *hcolor(), *rndmonnam(), *defmonnam();
X
Xextern char *occtxt;
Xextern int (*occupation)();
X
X# ifdef DGKMOD
Xint dotogglepickup(), doMSCversion();
X# ifdef DEBUG
Xint dodebug();
X# endif
X
Xstatic int (*timed_occ_fn)();
X
X/* Count down by decrementing multi */
Xtimed_occupation() {
X	(*timed_occ_fn)();
X	if (multi > 0)
X		multi--;
X	return (multi > 0);
X}
X
X/* If a time is given, use it to timeout this function, otherwise the
X * function times out by its own means.
X */
Xvoid
Xset_occupation(fn, txt, time)
Xint (*fn)();
Xchar *txt;
X{
X	if (time) {
X		occupation = timed_occupation;
X		timed_occ_fn = fn;
X	} else
X		occupation = fn;
X	occtxt = txt;
X	occtime = 0;
X}
X#endif /* DGKMOD */
X
X#ifdef REDO
X/* Provide a means to redo the last command.  The flag `in_doagain' is set
X * to true while redoing the command.  This flag is tested in commands that
X * require additional input (like `throw' which requires a thing and a
X * direction), and the input prompt is not shown.  Also, while in_doagain is
X * TRUE, no keystrokes can be saved into the saveq.
X */
X#define BSIZE 20
Xstatic char pushq[BSIZE], saveq[BSIZE];
Xstatic int phead, ptail, shead, stail;
Xint in_doagain;
X
Xchar
Xpopch() {
X	/* If occupied, return 0, letting tgetch know a character should
X	 * be read from the keyboard.  If the character read is not the
X	 * ABORT character (as checked in main.c), that character will be
X	 * pushed back on the pushq.
X	 */
X	if (occupation) return(0);
X	if (in_doagain) return ((shead != stail) ? saveq[stail++] : 0);
X	else		return ((phead != ptail) ? pushq[ptail++] : 0);
X}
X
X/* A ch == 0 resets the pushq */
Xvoid
Xpushch(ch)
Xchar ch;
X{
X	if (!ch)
X		phead = ptail = 0;
X	if (phead < BSIZE)
X		pushq[phead++] = ch;
X}
X
X/* A ch == 0 resets the saveq.  Only save keystrokes when not
X * replaying a previous command.
X */
Xvoid
Xsavech(ch)
Xchar ch;
X{
X	if (!in_doagain) {
X		if (!ch)
X			phead = ptail = shead = stail = 0;
X		else if (shead < BSIZE)
X			saveq[shead++] = ch;
X	}
X}
X# endif /* REDO */
X
Xstruct func_tab cmdlist[]={
X	{'\020', doredotopl},
X	{'\022', doredraw},
X	{'\024', dotele},
X#ifdef SUSPEND
X	{'\032', dosuspend},
X#endif
X	{'a', doapply},
X	{'A', doddoremarm},
X/*	'b', 'B' : go sw */
X	{'c', ddocall},
X	{'C', do_mname},
X	{'d', dodrop},
X	{'D', doddrop},
X	{'e', doeat},
X	{'E', doengrave},
X/* Soon to be
X	{'f', dofight, "fighting"},
X	{'F', doFight, "fighting"},
X */
X/*	'g', 'G' : multiple go */
X/*	'h', 'H' : go west */
X	{'I', dotypeinv},		/* Robert Viduya */
X	{'i', ddoinv},
X/*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
X/*	'o', doopen,	*/
X	{'O', doset},
X	{'p', dopay},
X	{'P', dowearring},
X	{'q', dodrink},
X	{'Q', done1},
X	{'r', doread},
X	{'R', doremring},
X	{'s', dosearch, "searching"},
X	{'S', dosave},
X	{'t', dothrow},
X	{'T', doremarm},
X/*	'u', 'U' : go ne */
X	{'v', doversion},
X	{'w', dowield},
X	{'W', doweararm},
X#ifdef SPELLS
X	{'x', dovspell},			/* Mike Stephenson */
X	{'X', doxcribe},			/* Mike Stephenson */ 
X#endif
X/*	'y', 'Y' : go nw */
X	{'z', dozap},
X/*	'Z' : UNUSED */
X	{'<', doup},
X	{'>', dodown},
X	{'/', dowhatis},
X	{'?', dohelp},
X#ifdef SHELL
X	{'!', dosh},
X#endif
X	{'.', donull, "waiting"},
X	{' ', donull, "waiting"},
X	{',', dopickup},
X	{':', dolook},
X	{'^', doidtrap},
X	{'\\', dodiscovered},		/* Robert Viduya */
X#ifdef DGKMOD
X	{'@', dotogglepickup},
X	{'V', doMSCversion},
X# ifdef DEBUG_DOESNT_WORK
X	{'\004', dodebug},	/* generic debug function */
X# endif
X#endif
X	{WEAPON_SYM,  doprwep},
X	{ARMOR_SYM,  doprarm},
X	{RING_SYM,  doprring},
X	{'$', doprgold},
X	{'#', doextcmd},
X	{0,0,0}
X};
X
Xstruct ext_func_tab extcmdlist[] = {
X#ifdef KAA
X	"breathe", "breathe like a dragon", dobreathe,
X#endif
X#ifdef SPELLS
X	"cast", "cast a spell", docast,
X#endif
X	"dip", "dip an object into something", dodip,
X	"pray", "pray to the gods for help", dopray,
X#ifdef KAA
X	"remove", "remove a cursed item", doremove,
X#endif
X#ifdef NEWCLASS
X	"sit", "sit down", dosit,
X#endif
X#if defined(KOPS) && defined(KAA)
X	"wipe", "wipe your face off", dowipe,
X#endif
X	"?", "get this list of extended commands", doextlist,
X	(char *) 0, (char *) 0, donull
X};
X
Xextern char *parse(), lowc(), unctrl(), quitchars[];
X
Xrhack(cmd)
Xregister char *cmd;
X{
X	register struct func_tab *tlist = cmdlist;
X	boolean firsttime = FALSE;
X	register res;
X
X	if(!cmd) {
X		firsttime = TRUE;
X		flags.nopick = 0;
X		cmd = parse();
X	}
X#ifdef REDO
X	if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
X		in_doagain = TRUE;
X		stail = 0;
X		rhack((char *) 0);	/* read and execute command */
X		in_doagain = FALSE;
X		return;
X	}
X
X	/* Special case of *cmd == ' ' handled better below */
X	if(!*cmd || *cmd == 0377) {
X#else
X	if(!*cmd || *cmd == 0377 || (flags.no_rest_on_space && *cmd == ' ')){
X#endif
X		bell();
X		flags.move = 0;
X		return(0);	/* probably we just had an interrupt */
X	}
X	if(movecmd(*cmd)) {
X	walk:
X		if(multi) flags.mv = 1;
X		domove();
X		return;
X	}
X	if(movecmd(lowc(*cmd))) {
X		flags.run = 1;
X	rush:
X		if(firsttime){
X			if(!multi) multi = COLNO;
X			u.last_str_turn = 0;
X		}
X		flags.mv = 1;
X#ifdef QUEST
X		if(flags.run >= 4) finddir();
X		if(firsttime){
X			u.ux0 = u.ux + u.dx;
X			u.uy0 = u.uy + u.dy;
X		}
X#endif
X		domove();
X		return;
X	}
X	if((*cmd == 'g' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
X		flags.run = 2;
X		goto rush;
X	}
X	if(*cmd == 'G' && movecmd(lowc(cmd[1]))) {
X		flags.run = 3;
X		goto rush;
X	}
X	if(*cmd == 'm' && movecmd(cmd[1])) {
X		flags.run = 0;
X		flags.nopick = 1;
X		goto walk;
X	}
X	if(*cmd == 'M' && movecmd(lowc(cmd[1]))) {
X		flags.run = 1;
X		flags.nopick = 1;
X		goto rush;
X	}
X#ifdef QUEST
X	if(*cmd == cmd[1] && (*cmd == 'g' || *cmd == 'G')) {
X		flags.run = 4;
X		if(*cmd == 'G') flags.run += 2;
X		if(cmd[2] == '-') flags.run += 1;
X		goto rush;
X	}
X#endif
X	while(tlist->f_char) {
X		if(*cmd == tlist->f_char){
X#ifdef DGKMOD
X			/* Special case of *cmd == ' ' handled here */
X			if (*cmd == ' ' && flags.no_rest_on_space)
X				break;
X
X			/* Now control-A can stop lengthy commands */
X			if (tlist->f_text && !occupation && multi)
X				set_occupation(tlist->f_funct, tlist->f_text,
X					multi);
X#endif
X			res = (*(tlist->f_funct))();
X			if(!res) {
X				flags.move = 0;
X				multi = 0;
X			}
X			return;
X		}
X		tlist++;
X	}
X	{ char expcmd[10];
X	  register char *cp = expcmd;
X	  while(*cmd && cp-expcmd < sizeof(expcmd)-2) {
X		if(*cmd >= 040 && *cmd < 0177)
X			*cp++ = *cmd++;
X		else {
X			*cp++ = '^';
X			*cp++ = *cmd++ ^ 0100;
X		}
X	  }
X	  *cp++ = 0;
X	  pline("Unknown command '%s'.", expcmd);
X	}
X	multi = flags.move = 0;
X}
X
Xdoextcmd()	/* here after # - now read a full-word command */
X{
X	char buf[BUFSZ];
X	register struct ext_func_tab *efp = extcmdlist;
X
X	pline("# ");
X	getlin(buf);
X	clrlin();
X	if(buf[0] == '\033')
X		return(0);
X	while(efp->ef_txt) {
X		if(!strcmp(efp->ef_txt, buf))
X			return((*(efp->ef_funct))());
X		efp++;
X	}
X	pline("%s: unknown command.", buf);
X	return(0);
X}
X
Xdoextlist()	/* here after #? - now list all full-word commands */
X{
X	register struct ext_func_tab *efp = extcmdlist;
X	char     buf[BUFSZ];
X
X	set_pager(0);
X	if(page_line("") ||
X	   page_line("        Extended Command Set:") ||
X	   page_line(""))					 goto quit;
X
X	while(efp->ef_txt) {
X
X		(void)sprintf(buf, "    %-8s  - %s.", efp->ef_txt, efp->ef_desc);
X		if(page_line(buf)) goto quit;
X		efp++;
X	}
X	set_pager(1);
X	return(0);
Xquit:
X	set_pager(2);
X	return(0);
X}
X
Xchar
Xlowc(sym)
Xchar sym;
X{
X    return( (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym );
X}
X
Xchar
Xunctrl(sym)
Xchar sym;
X{
X    return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym );
X}
X
X/* 'rogue'-like direction commands */
Xchar sdir[] = "hykulnjb><";
Xschar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 };
Xschar ydir[10] = {  0,-1,-1,-1, 0, 1, 1, 1, 0, 0 };
Xschar zdir[10] = {  0, 0, 0, 0, 0, 0, 0, 0, 1,-1 };
X
Xmovecmd(sym)	/* also sets u.dz, but returns false for <> */
Xchar sym;
X{
X	register char *dp;
X
X	u.dz = 0;
X	if(!(dp = index(sdir, sym))) return(0);
X	u.dx = xdir[dp-sdir];
X	u.dy = ydir[dp-sdir];
X	u.dz = zdir[dp-sdir];
X	return(!u.dz);
X}
X
Xgetdir(s)
Xboolean s;
X{
X	char dirsym;
X
X#ifdef REDO
X	if (!in_doagain)
X#endif
X	    if(s) pline("In what direction?");
X	dirsym = readchar();
X#ifdef REDO
X	savech(dirsym);
X#endif
X#ifdef KAA
X	if(dirsym == '.' || dirsym == 's')
X		u.dx = u.dy = u.dz = 0;
X	else
X#endif
X	if(!movecmd(dirsym) && !u.dz) {
X		if(!index(quitchars, dirsym))
X			pline("What a strange direction!");
X		return(0);
X	}
X	if(Confusion && !u.dz) confdir();
X	return(1);
X}
X
Xconfdir()
X{
X	register x = rn2(8);
X	u.dx = xdir[x];
X	u.dy = ydir[x];
X}
X
X#ifdef QUEST
Xfinddir(){
Xregister int i, ui = u.di;
X	for(i = 0; i <= 8; i++){
X		if(flags.run & 1) ui++; else ui += 7;
X		ui %= 8;
X		if(i == 8){
X			pline("Not near a wall.");
X			flags.move = multi = 0;
X			return(0);
X		}
X		if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
X			break;
X	}
X	for(i = 0; i <= 8; i++){
X		if(flags.run & 1) ui += 7; else ui++;
X		ui %= 8;
X		if(i == 8){
X			pline("Not near a room.");
X			flags.move = multi = 0;
X			return(0);
X		}
X		if(isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
X			break;
X	}
X	u.di = ui;
X	u.dx = xdir[ui];
X	u.dy = ydir[ui];
X}
X
Xisroom(x,y)  register x,y; {		/* what about POOL? */
X	return(isok(x,y) && (levl[x][y].typ == ROOM ||
X				(levl[x][y].typ >= LDOOR && flags.run >= 6)));
X}
X#endif /* QUEST /**/
X
Xisok(x,y) register x,y; {
X	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
X	return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1);
X}
END_OF_cmd.c
if test 10152 -ne `wc -c <cmd.c`; then
    echo shar: \"cmd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f data.base -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"data.base\"
else
echo shar: Extracting \"data.base\" \(9619 characters\)
sed "s/^X//" >data.base <<'END_OF_data.base'
X	NetHack & Quest data file - version 1.0
X@	human (or you)
X-	a wall
X|	a wall
X+	a door
X.	the floor of a room
X	a dark part of a room
X#	a corridor
X}	water filled area
X<	the staircase to the previous level
X>	the staircase to the next level
X^	a trap
X$	a pile, pot or chest of gold
X%%	a piece of food
X!	a potion
X*	a gem
X?	a scroll
X=	a ring
X/	a wand
X[	a suit of armor
X)	a weapon
X(	a useful item (camera, key, rope etc.)
X0	an iron ball
X_	an iron chain
X`	an enormous rock (or opulant throne)
X"	an amulet
X,	a trapper
X:	a chameleon
X;	a giant eel
X'	a lurker above
X&	a demon
XA	a giant ant
XB	a giant bat
XC	a centaur;
X	Of all the monsters put together by  the  Greek	 imagination
X	the  Centaurs (Kentauroi) constituted a class in themselves.
X	Despite a strong streak	 of  sensuality	 in  their  make-up,
X	their  normal  behaviour  was  moral, and they took a kindly
X	thought of man's welfare. The attempted outrage of Nessos on
X	Deianeira,  and	 that  of the whole tribe of Centaurs on the
X	Lapith women, are more than offset  by	the  hospitality  of
X	Pholos	and  by	 the  wisdom of Cheiron, physician, prophet,
X	lyrist, and the instructor of Achilles.	 Further,  the	Cen-
X	taurs  were  peculiar in that their nature, which united the
X	body of a horse with the trunk and head of a  man,  involved
X	an  unthinkable	 duplication  of  vital organs and important
X	members. So grotesque a combination seems  almost  un-Greek.
X	These  strange	creatures were said to live in the caves and
X	clefts of the mountains, myths associating  them  especially
X	with the hills of Thessaly and the range of Erymanthos.
X		       [Mythology of all races, Vol. 1, pp. 270-271]
XD	a dragon;
X	In the West the dragon was the natural	enemy  of  man.	 Although
X	preferring to live in bleak and desolate regions, whenever it was
X	seen among men it left in its wake a  trail  of	 destruction  and
X	disease. Yet any attempt to slay this beast was a perilous under-
X	taking. For the dragon's assailant had to contend not  only  with
X	clouds	of  sulphurous fumes pouring from its fire-breathing nos-
X	trils, but also with the thrashings of its tail, the most  deadly
X	part of its serpent-like body.
X	[From: Mythical Beasts by Deirdre Headon (The Leprechaun Library)]
XE	a floating eye
XF	a freezing sphere
XG	a gnome;
X	... And then a gnome came by, carrying a bundle, an old fellow
X	three times as large as an imp and wearing clothes of a sort,
X	especially a hat. And he was clearly just as frightened as the
X	imps though he could not go so fast. Ramon Alonzo saw that there
X	must be some great trouble that was vexing magical things; and,
X	since gnomes speak the language of men, and will answer if spoken
X	to gently, he raised his hat, and asked of the gnome his name.
X	The gnome did not stop his hasty shuffle a moment as he answered
X	'Alaraba' and grabbed the rim of his hat but forgot to doff it.
X	'What is the trouble, Alaraba?' said Ramon Alonzo.
X	'White magic. Run!' said the gnome ...
X			[From: The Charwoman's Shadow, by Lord Dunsany.]
XH	a hobgoblin;
X	Hobgoblin. Used by the	Puritans  and  in  later  times	 for
X	wicked	goblin	spirits,  as in Bunyan's 'Hobgoblin nor foul
X	friend', but its more correct use is for the friendly  spir-
X	its  of	 the brownie type.  In 'A midsummer night's dream' a
X	fairy says to Shakespeare's Puck:
X		Those that Hobgoblin call you, and sweet Puck,
X		You do their work, and they shall have good luck:
X		Are you not he?
X	and obviously Puck would not wish to be called	a  hobgoblin
X	if that was an ill-omened word.
X	Hobgoblins are on the whole, good-humoured and ready  to  be
X	helpful,  but fond of practical joking, and like most of the
X	fairies rather nasty people to annoy. Boggarts hover on	 the
X	verge of hobgoblindom.	Bogles are just over the edge.
X	One Hob mentioned by Henderson, was Hob Headless who haunted
X	the  road  between Hurworth and Neasham, but could not cross
X	the little river Kent, which flowed into the  Tess.  He	 was
X	exorcised  and	laid under a large stone by the roadside for
X	ninety-nine years and a day. If anyone was so unwary  as  to
X	sit  on	 that stone, he would be unable to quit it for ever.
X	The ninety-nine years is nearly up, so trouble may  soon  be
X	heard of on the road between Hurworth and Neasham.
X		       [Katharine Briggs, A  dictionary	 of Fairies]
XI	an invisible stalker
XJ	a jackal
XK	a kobold
XL	a leprechaun;
X	The Irish Leprechaun is the Faeries' shoemaker and is  known
X	under  various	names  in different parts of Ireland: Cluri-
X	caune in Cork, Lurican in Kerry, Lurikeen in Kildare and Lu-
X	rigadaun  in  Tipperary.  Although he works for the Faeries,
X	the Leprechaun is not of the same species. He is small,	 has
X	dark  skin  and wears strange clothes.	His nature has some-
X	thing of the manic-depressive about it: first  he  is  quite
X	happy,	whistling merrily as he nails a sole on to a shoe; a
X	few minutes later, he is sullen and  morose,  drunk  on	 his
X	home-made  heather ale. The Leprechaun's two great loves are
X	tobacco and whiskey, and he is a first-rate con-man,  impos-
X	sible  to  out-fox.  No	 one, no matter how clever, has ever
X	managed to cheat him out of his hidden pot of  gold  or	 his
X	magic  shilling. At the last minute he always thinks of some
X	way to divert his captor's attention  and  vanishes  in	 the
X	twinkling  of  an eye.
X			  [From: A Field Guide to the Little People
X			     by	 Nancy Arrowsmith & George Moorse. ]
XM	a mimic
XN	a nymph
XO	an orc
XP	a purple worm
XQ	a quasit
XR	a rust monster
XS	a snake
XT	a troll
XU	an umber hulk
XV	a vampire
XW	a wraith
XX	a xorn
XY	a yeti
XZ	a zombie
Xa	an acid blob
Xb	a giant beetle
Xc	a cockatrice;
X	Once in a great while, when the positions of the  stars	 are
X	just  right, a seven-year-old rooster will lay an egg. Then,
X	along will come a snake, to coil around the egg, or a  toad,
X	to  squat  upon	 the  egg, keeping it warm and helping it to
X	hatch. When it hatches, out comes a creature  called  basil-
X	isk, or cockatrice, the most deadly of all creatures. A sin-
X	gle glance from its yellow, piercing toad's eyes  will	kill
X	both  man  and beast. Its power of destruction is said to be
X	so great that sometimes simply to hear its  hiss  can  prove
X	fatal.	Its breath is so venomenous that it causes all vege-
X	tation to wither.
X	There is, however, one	creature  which	 can  withstand	 the
X	basilisk's deadly gaze, and this is the weasel. No one knows
X	why this is so, but although the fierce weasel can slay	 the
X	basilisk,  it will itself be killed in the struggle. Perhaps
X	the weasel knows the basilisk's fatal weakness: if  it	ever
X	sees  its own reflection in a mirror it will perish instant-
X	ly. But even a dead basilisk is dangerous, for	it  is	said
X	that merely touching its lifeless body can cause a person to
X	sicken and die.
X	    [From: Mythical Beasts by Deirdre Headon (The Leprechaun
X		   Library) and other sources. ]
Xd	a dog
Xe	an ettin
Xf	a fog cloud
Xg	a gelatinous cube
Xh	a homunculus
Xi	an imp;
X	 ... imps ... little creatures of two feet high	 that  could
X	gambol and jump prodigiously; ...
X			[From: The Charwoman's Shadow, by Lord Dunsany.]
X
X	An 'imp' is an off-shoot or cutting. Thus an 'ymp tree'	 was
X	a grafted tree, or one grown from a cutting, not from seed.
X	'Imp' properly means a small devil, an off-shoot  of  Satan,
X	but  the distinction between goblins or bogles and imps from
X	hell is hard to make, and many in the  Celtic  countries  as
X	well as the English Puritans regarded all fairies as devils.
X	The fairies of tradition often hover  uneasily	between	 the
X	ghostly and the diabolic state.
X			 [Katharine Briggs, A dictionary of Fairies]
Xj	a jaguar
Xk	a killer bee
Xl	a leocrotta
Xm	a minotaur
Xn	a nurse
Xo	an owlbear
Xp	a piercer
Xq	a quivering blob
Xr	a giant rat
Xs	a scorpion
Xt	a tengu;
X	The tengu was the  most	 troublesome  creature	of  Japanese
X	legend.	  Part	bird  and part man, with red beak for a nose
X	and flashing eyes, the tengu was notorious for	stirring  up
X	feuds  and  prolonging	enmity between families. Indeed, the
X	belligerent tengus were supposed to have  been	man's  first
X	instructors in the use of arms.
X			    [From: Mythical Beasts by Deirdre Headon
X					 (The Leprechaun Library). ]
Xu	a unicorn;
X	Men have always sought the elusive unicorn, for	 the  single
X	twisted	 horn  which projected from its forehead was thought
X	to be a powerful talisman. It was said that the unicorn	 had
X	simply	to  dip	 the tip of its horn in a muddy pool for the
X	water to become pure. Men also believed that to	 drink	from
X	this horn was a protection against all sickness, and that if
X	the horn was ground to a powder it would act as an  antidote
X	to  all poisons. Less than 200 years ago in France, the horn
X	of a unicorn was used in a ceremony to test the	 royal	food
X	for poison.
X	Although only the size of a small horse, the  unicorn  is  a
X	very  fierce  beast,  capable  of killing an elephant with a
X	single thrust from its horn.  Its  fleetness  of  foot	also
X	makes  this solitary creature difficult to capture. However,
X	it can be tamed and captured by a maiden. Made gentle by the
X	sight  of a virgin, the unicorn can be lured to lay its head
X	in her lap, and in this docile mood, the maiden	 may  secure
X	it with a golden rope.
X			    [From: Mythical Beasts by Deirdre Headon
X					 (The Leprechaun Library). ]
Xv	a violet fungi
Xw	a long worm;
X	From its teeth the crysknife can be manufactured.
X~	the tail of a long worm
Xx	a xan;
X	The xan were animals sent to prick the legs of the Lords of Xibalba.
Xy	a yellow light
Xz	a zruty;
X	The zruty are wild and gigantic beings, living in the wildernesses
X	of the Tatra mountains.
X1	The wizard of Yendor
X2	The mail daemon
END_OF_data.base
if test 9619 -ne `wc -c <data.base`; then
    echo shar: \"data.base\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f save.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"save.c\"
else
echo shar: Extracting \"save.c\" \(10331 characters\)
sed "s/^X//" >save.c <<'END_OF_save.c'
X/*	SCCS Id: @(#)save.c	1.3	87/07/14
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* save.c - version 1.0.3 */
X
X#include <signal.h>
X#include <stdio.h>
X#include "hack.h"
Xextern char genocided[60];		/* defined in Decl.c */
Xextern char fut_geno[60];		/* idem */
Xextern struct permonst	pm_wizard;	/* since the wizard evolves */
X
Xextern char SAVEF[], nul[];
Xextern char pl_character[PL_CSIZ];
Xextern long lseek();
Xextern struct obj *restobjchn();
Xextern struct monst *restmonchn();
X
Xdosave(){
X	clear_screen();
X	fflush(stdout);
X	if(dosave0(0)) {
X		settty("Be seeing you ...\n");
X		exit(0);
X	}
X#ifdef lint
X	return(0);
X#endif
X}
X
X#ifndef NOSAVEONHANGUP
Xhangup(){
X	(void) dosave0(1);
X	exit(1);
X}
X#endif
X
X/* returns 1 if save successful */
Xdosave0(hu) int hu; {
X	register fd, ofd;
X	int tmp;		/* not register ! */
X#ifdef DGK
X	long fds, needed;
X	extern long bytes_counted;
X	int mode;
X#endif
X#ifdef UNIX
X	(void) signal(SIGHUP, SIG_IGN);
X#endif
X	(void) signal(SIGINT, SIG_IGN);
X#ifdef DGK
X	if (!saveDiskPrompt(0))
X		return 0;
X	fd = open(SAVEF, O_WRONLY | O_BINARY | O_CREAT, FMASK);
X#else
X	fd = creat(SAVEF, FMASK);
X#endif
X	if(fd < 0) {
X		if(!hu) pline("Cannot open save file. (Continue or Quit)");
X		(void) unlink(SAVEF);		/* ab@unido */
X		return(0);
X	}
X	if(flags.moonphase == FULL_MOON)	/* ut-sally!fletcher */
X		u.uluck--;			/* and unido!ab */
X#ifdef DGKMOD
X	home();
X	cl_end();
X#endif
X#ifdef DGK
X	msmsg("Saving: ");
X	mode = COUNT;
Xagain:
X	savelev(fd, dlevel, mode);
X	/* count_only will be set properly by savelev */
X#else
X	savelev(fd,dlevel);
X#endif
X	saveobjchn(fd, invent);
X	saveobjchn(fd, fcobj);
X	savemonchn(fd, fallen_down);
X	tmp = getuid();
X	bwrite(fd, (char *) &tmp, sizeof tmp);
X	bwrite(fd, (char *) &flags, sizeof(struct flag));
X	bwrite(fd, (char *) &dlevel, sizeof dlevel);
X	bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel);
X	bwrite(fd, (char *) &moves, sizeof moves);
X	bwrite(fd, (char *) &u, sizeof(struct you));
X#ifdef SPELLS
X	bwrite(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1));
X#endif
X	if(u.ustuck)
X		bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
X	bwrite(fd, (char *) pl_character, sizeof pl_character);
X	bwrite(fd, (char *) genocided, sizeof genocided);
X	bwrite(fd, (char *) fut_geno, sizeof fut_geno);
X#ifdef HARD
X	bwrite(fd, (char *) &pm_wizard, sizeof(struct permonst));
X#endif
X	savenames(fd);
X#ifdef DGK
X	if (mode == COUNT) {
X		/* make sure there is enough disk space */
X		needed = bytes_counted;
X		for (tmp = 1; tmp <= maxdlevel; tmp++)
X			if (tmp != dlevel && fileinfo[tmp].where)
X				needed += fileinfo[tmp].size + (sizeof tmp);
X		fds = freediskspace(SAVEF);
X		if (needed > fds) {
X			pline("There is insufficient space on SAVE disk.");
X			pline("Require %ld bytes but only have %ld.", needed,
X				fds);
X			flushout();
X			(void) close(fd);
X			(void) unlink(SAVEF);
X			return 0;
X		}
X		mode = WRITE;
X		goto again;
X	}
X#endif
X	for(tmp = 1; tmp <= maxdlevel; tmp++) {
X		extern int hackpid;
X#ifdef DGK
X		if (tmp == dlevel || !fileinfo[tmp].where) continue;
X		if (fileinfo[tmp].where != ACTIVE)
X			swapin_file(tmp);
X#else
X		extern boolean level_exists[];
X
X		if(tmp == dlevel || !level_exists[tmp]) continue;
X#endif
X		glo(tmp);
X#ifdef DGK
X		msmsg(".");
X#endif
X		if((ofd = open(lock, 0)) < 0) {
X		    if(!hu) pline("Error while saving: cannot read %s.", lock);
X		    (void) close(fd);
X		    (void) unlink(SAVEF);
X		    if(!hu) done("tricked");
X		    return(0);
X		}
X		getlev(ofd, hackpid, tmp);
X		(void) close(ofd);
X		bwrite(fd, (char *) &tmp, sizeof tmp);	/* level number */
X#ifdef DGK
X		savelev(fd,tmp,WRITE);			/* actual level */
X#else
X		savelev(fd,tmp);			/* actual level */
X#endif
X		(void) unlink(lock);
X	}
X	(void) close(fd);
X	glo(dlevel);
X	(void) unlink(lock);	/* get rid of current level --jgm */
X	glo(0);
X	(void) unlink(lock);
X	return(1);
X}
X
Xdorecover(fd)
Xregister fd;
X{
X	register nfd;
X	int tmp;		/* not a register ! */
X	unsigned mid;		/* idem */
X	struct obj *otmp;
X	extern boolean restoring;
X#ifdef DGK
X	struct flag oldflags;
X
X	oldflags = flags;	/* Save flags set in the config file */
X#endif
X	restoring = TRUE;
X	getlev(fd, 0, 0);
X	invent = restobjchn(fd);
X	for(otmp = invent; otmp; otmp = otmp->nobj)
X		if(otmp->owornmask)
X			setworn(otmp, otmp->owornmask);
X	fcobj = restobjchn(fd);
X	fallen_down = restmonchn(fd);
X	mread(fd, (char *) &tmp, sizeof tmp);
X	if(tmp != getuid()) {		/* strange ... */
X		(void) close(fd);
X		(void) unlink(SAVEF);
X		puts("Saved game was not yours.");
X		restoring = FALSE;
X		return(0);
X	}
X	mread(fd, (char *) &flags, sizeof(struct flag));
X#ifdef DGK
X	/* Some config file OPTIONS take precedence over those in save file.
X	 */
X	flags.rawio = oldflags.rawio;
X	flags.DECRainbow = oldflags.DECRainbow;
X	flags.IBMBIOS = oldflags.IBMBIOS;
X#endif
X	mread(fd, (char *) &dlevel, sizeof dlevel);
X	mread(fd, (char *) &maxdlevel, sizeof maxdlevel);
X	mread(fd, (char *) &moves, sizeof moves);
X	mread(fd, (char *) &u, sizeof(struct you));
X#ifdef SPELLS
X	mread(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1));
X#endif
X	if(u.ustuck)
X		mread(fd, (char *) &mid, sizeof mid);
X	mread(fd, (char *) pl_character, sizeof pl_character);
X	mread(fd, (char *) genocided, sizeof genocided);
X	mread(fd, (char *) fut_geno, sizeof fut_geno);
X#ifdef HARD
X	mread(fd, (char *) &pm_wizard, sizeof(struct permonst));
X#endif
X	restnames(fd);
X#ifdef DGK
X	msmsg("\n");
X	cl_end();
X	msmsg("You got as far as level %d%s.\n", maxdlevel,
X		flags.debug ? " in WIZARD mode" : "");
X	cl_end();
X	msmsg("Restoring: ");
X#endif
X	while(1) {
X		if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp)
X			break;
X		getlev(fd, 0, tmp);
X		glo(tmp);
X#ifdef DGK
X		msmsg(".");
X		nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK);
X#else
X		nfd = creat(lock, FMASK);
X#endif
X		if (nfd < 0)	panic("Cannot open temp file %s!\n", lock);
X#ifdef DGK
X		if (!savelev(nfd, tmp, COUNT | WRITE)) {
X
X			/* The savelev can't proceed because the size required
X			 * is greater than the available disk space.
X			 */
X			msmsg("\nNot enough space on `%s' to restore your game.\n",
X				levels);
X
X			/* Remove levels and bones that may have been created.
X			 */
X			(void) close(nfd);
X			eraseall(levels, alllevels);
X			eraseall(levels, allbones);
X
X			/* Perhaps the person would like to play without a
X			 * RAMdisk.
X			 */
X			if (ramdisk) {
X				/* PlaywoRAMdisk may not return, but if it does
X				 * it is certain that ramdisk will be 0.
X				 */
X				playwoRAMdisk();
X				(void) lseek(fd, 0L, 0); /* Rewind save file */
X				return dorecover(fd);	 /* and try again */
X			} else {
X				msmsg("Be seeing you ...\n");
X				exit(0);
X			}
X		}
X#else
X		savelev(nfd,tmp);
X#endif
X		(void) close(nfd);
X	}
X	(void) lseek(fd, 0L, 0);
X	getlev(fd, 0, 0);
X	(void) close(fd);
X	(void) unlink(SAVEF);
X	if(Punished) {
X		for(otmp = fobj; otmp; otmp = otmp->nobj)
X			if(otmp->olet == CHAIN_SYM) goto chainfnd;
X		panic("Cannot find the iron chain?");
X	chainfnd:
X		uchain = otmp;
X		if(!uball){
X			for(otmp = fobj; otmp; otmp = otmp->nobj)
X				if(otmp->olet == BALL_SYM && otmp->spe)
X					goto ballfnd;
X			panic("Cannot find the iron ball?");
X		ballfnd:
X			uball = otmp;
X		}
X	}
X	if(u.ustuck) {
X		register struct monst *mtmp;
X
X		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X			if(mtmp->m_id == mid) goto monfnd;
X		panic("Cannot find the monster ustuck.");
X	monfnd:
X		u.ustuck = mtmp;
X	}
X#ifndef QUEST
X	setsee();  /* only to recompute seelx etc. - these weren't saved */
X#endif
X#ifdef DGK
X	gameDiskPrompt();
X#endif
X	docrt();
X	restoring = FALSE;
X	return(1);
X}
X
Xstruct obj *
Xrestobjchn(fd)
Xregister fd;
X{
X	register struct obj *otmp, *otmp2;
X	register struct obj *first = 0;
X	int xl;
X#ifdef lint
X	/* suppress "used before set" warning from lint */
X	otmp2 = 0;
X#endif
X	while(1) {
X		mread(fd, (char *) &xl, sizeof(xl));
X		if(xl == -1) break;
X		otmp = newobj(xl);
X		if(!first) first = otmp;
X		else otmp2->nobj = otmp;
X		mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj));
X		if(!otmp->o_id) otmp->o_id = flags.ident++;
X		otmp2 = otmp;
X	}
X	if(first && otmp2->nobj){
X		impossible("Restobjchn: error reading objchn.");
X		otmp2->nobj = 0;
X	}
X	return(first);
X}
X#ifdef MSDOS
Xstruct monst *
Xrestmonchn(fd)
Xregister fd;
X{
X	register struct monst *mtmp, *mtmp2;
X	register struct monst *first = 0;
X	int xl;
X	int monsindex;
X	extern struct permonst li_dog, dog, la_dog;
X#ifdef KAA
X	extern struct permonst hell_hound;
X# ifdef HARD
X	extern struct permonst d_lord, d_prince;
X# endif
X#endif
X
X#ifdef lint
X	/* suppress "used before set" warning from lint */
X	mtmp2 = 0;
X#endif /* lint /**/
X	while(1) {
X		mread(fd, (char *) &xl, sizeof(xl));
X		if(xl == -1) break;
X		mtmp = newmonst(xl);
X		if(!first) first = mtmp;
X		else mtmp2->nmon = mtmp;
X		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
X		if(!mtmp->m_id)
X			mtmp->m_id = flags.ident++;
X		monsindex = *((int *)&mtmp->data);
X		if (monsindex == -1)		/* Special fake index */
X			mtmp->data = &li_dog;
X		else if (monsindex == -2)	/* Special fake index */
X			mtmp->data = &dog;
X		else if (monsindex == -3)	/* Special fake index */
X			mtmp->data = &la_dog;
X#ifdef KAA
X		else if (monsindex == -4)
X			mtmp->data = &hell_hound;
X# ifdef HARD
X		else if (monsindex == -5)
X			permonstp = &d_lord;
X
X		else if (monsindex == -6)
X			permonstp = &d_prince;
X# endif
X#endif
X		else
X			mtmp->data = &mons[monsindex];
X		if(mtmp->minvent)
X			mtmp->minvent = restobjchn(fd);
X		mtmp2 = mtmp;
X	}
X	if(first && mtmp2->nmon){
X		impossible("Restmonchn: error reading monchn.");
X		mtmp2->nmon = 0;
X	}
X	return(first);
X}
X#else
Xstruct monst *
Xrestmonchn(fd)
Xregister fd;
X{
X	register struct monst *mtmp, *mtmp2;
X	register struct monst *first = 0;
X	int xl;
X
X	struct permonst *monbegin;
X	long differ;
X
X	mread(fd, (char *)&monbegin, sizeof(monbegin));
X	differ = (char *)(&mons[0]) - (char *)(monbegin);
X
X#ifdef lint
X	/* suppress "used before set" warning from lint */
X	mtmp2 = 0;
X#endif
X	while(1) {
X		mread(fd, (char *) &xl, sizeof(xl));
X		if(xl == -1) break;
X		mtmp = newmonst(xl);
X		if(!first) first = mtmp;
X		else mtmp2->nmon = mtmp;
X		mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
X		if(!mtmp->m_id)
X			mtmp->m_id = flags.ident++;
X		mtmp->data = (struct permonst *)
X			((char *) mtmp->data + differ);
X		if(mtmp->minvent)
X			mtmp->minvent = restobjchn(fd);
X		mtmp2 = mtmp;
X	}
X	if(first && mtmp2->nmon){
X		impossible("Restmonchn: error reading monchn.");
X		mtmp2->nmon = 0;
X	}
X	return(first);
X}
X#endif
END_OF_save.c
if test 10331 -ne `wc -c <save.c`; then
    echo shar: \"save.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f spell.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"spell.c\"
else
echo shar: Extracting \"spell.c\" \(9414 characters\)
sed "s/^X//" >spell.c <<'END_OF_spell.c'
X/*	SCCS Id: @(#)spell.c	1.3	87/07/14
X/* hack.spell.c - version 1.0.1		M. Stephenson 07-04-86 */
X
X#include "hack.h"
X#ifdef SPELLS
Xextern char *nomovemsg;
X
Xdoxcribe() {
X	register struct obj *book;
X	struct	 obj	*getobj();
X	register boolean confused = (Confusion != 0);
X	register boolean oops;
X	register schar	 delay;
X	register int   booktype;
X	register int	 i;
X
X	book = getobj("+", "transcribe");
X	if(!book) return(0);
X
X	if(Blind) {
X	    pline("Being blind, you cannot read the mystic runes.");
X	    useup(book);		/* well, if you are stupid... */
X	    return(0);
X	}
X
X	if(confused) {
X	    pline("Being confused, you cannot grasp the meaning of this tome.");
X	    useup(book);		/* and more stupidity... */
X	    return(0);
X	}
X	booktype = book->otyp;
X	oops = !rn2(u.ulevel - objects[booktype].spl_lev + 7);
X	switch(booktype)  {
X
X/* level 1 spells */
X	case SPE_HEALING:
X	case SPE_DETECT_MONSTERS:
X	case SPE_FORCE_BOLT:
X	case SPE_LIGHT:
X	case SPE_SLEEP:
X/* level 2 spells */
X	case SPE_MAGIC_MISSILE:
X	case SPE_CONFUSE_MONSTER:
X	case SPE_SLOW_MONSTER:
X	case SPE_CURE_BLINDNESS:
X	case SPE_CREATE_MONSTER:
X	case SPE_DETECT_FOOD:
X		delay = -objects[booktype].oc_delay;
X		break;
X/* level 3 spells */
X	case SPE_HASTE_SELF:
X	case SPE_CAUSE_FEAR:
X	case SPE_CURE_SICKNESS:
X	case SPE_DETECT_UNSEEN:
X	case SPE_EXTRA_HEALING:
X	case SPE_CHARM_MONSTER:
X/* level 4 spells */
X	case SPE_LEVITATION:
X	case SPE_RESTORE_STRENGTH:
X	case SPE_INVISIBILITY:
X	case SPE_FIREBALL:
X	case SPE_DETECT_TREASURE:
X		delay = -(objects[booktype].spl_lev - 1) * objects[booktype].oc_delay;
X		break;
X/* level 5 spells */
X	case SPE_REMOVE_CURSE:
X	case SPE_MAGIC_MAPPING:
X	case SPE_CONE_OF_COLD:
X	case SPE_IDENTIFY:
X	case SPE_DIG:
X/* level 6 spells */
X	case SPE_TURN_UNDEAD:
X	case SPE_POLYMORPH:
X	case SPE_CREATE_FAMILIAR:
X	case SPE_TELEPORT_AWAY:
X		delay = -objects[booktype].spl_lev * objects[booktype].oc_delay;
X		break;
X/* level 7 spells */
X	case SPE_CANCELLATION:
X	case SPE_FINGER_OF_DEATH:
X	case SPE_GENOCIDE:
X		delay = -8 * objects[booktype].oc_delay;
X		break;
X/* impossible */
X	default:
X		impossible("Unknown spell-book, %d;", booktype);
X		return(0);
X	}
X
X	pline("You begin to transcribe the spell.");
X	if(oops || book->cursed)  {
X		cursed_book(objects[booktype].spl_lev);
X		nomul(delay);			/* study time */
X	} else  {
X		nomul(delay);			/* study time */
X		for(i = 0; i < MAXSPELL; i++)  {
X			if(spl_book[i].sp_id == booktype)  {
X				nomovemsg = "Oh, you already know that one!";
X				useup(book);
X				return(1);
X			} else if (spl_book[i].sp_id == NO_SPELL)  {
X				spl_book[i].sp_id = booktype;
X				spl_book[i].sp_lev = objects[booktype].spl_lev;
X				spl_book[i].sp_flags = objects[booktype].bits;
X				nomovemsg = "You add the spell to your books.";
X				objects[booktype].oc_name_known = 1;
X				useup(book);
X				return(1);
X			}
X		}
X		impossible("Too many spells in spellbook!");
X	}
X	useup(book);
X	return(1);
X}
X
Xcursed_book(level)
X	register int	level;
X{
X	register int	nobj, cnt, onum;
X	register struct obj	*otmp;
X
X	switch(rnd(level)) {
X	case 0:
X		pline("you feel a wrenching sensation.");
X		tele();		/* teleport him */
X		break;
X	case 1:
X		pline("you feel threatened.");
X		aggravate();
X		break;
X	case 2:
X		if(!Blind)	pline("a cloud of darkness falls upon you.");
X		Blind += rn1(100,250);
X		seeoff(0);
X		break;
X	case 3:
X		if (u.ugold <= 0)  {
X			pline("you feel a strange sensation.");
X		} else {
X			pline("you notice you have no gold!");
X			u.ugold = 0;
X			flags.botl = 1;
X		}
X		break;
X	case 4:
X		pline("These runes were just too much to comprehend.");
X		HConfusion += rn1(7,16);
X		break;
X	case 5:
X		pline("The book was coated with contact poison!");
X		if(Poison_resistance) {
X		    losestr(rn1(1,2));
X		    losehp(rnd(6), "contact poison");
X		} else {
X		    losestr(rn1(4,3));
X		    losehp(rnd(10), "contact poison");
X		}
X		break;
X	case 6:
X		pline("As you read the book, it explodes in your face!");
X		losehp (2*rnd(10)+5, "exploding rune");
X		break;
X	case 7:
X		/* curse a few inventory items at random! */
X		nobj = 0;
X		for (otmp = invent; otmp; otmp = otmp->nobj)  nobj++;
X
X		for (cnt = rnd(6); cnt > 0; cnt--)  {
X
X			onum = rn2(nobj);
X			for(otmp = invent; onum != 0; onum--) otmp = otmp->nobj;
X			otmp->cursed++;
X		}
X		break;
X	}
X	return(0);
X}
X
Xdocast()
X{
X	register int	 spell, energy;
X	register boolean confused = (Confusion != 0);
X	register struct  obj	*pseudo;
X	struct	 obj	 *mksobj();
X
X	spell = getspell();
X	if (!spell) return(0);
X	else  {
X
X		energy = spellev(spell);
X		if(energy > u.uen)  {
X			pline("You are too weak to cast that spell.");
X			return(0);
X		} else  if ((u.uhunger <= 100) || (u.ustr < 6))  {
X			pline("You miss the strength for that spell.");
X			return(0);
X		} else	{
X			morehungry(energy * 10);
X			u.uen -= energy;
X		}
X	}
X#ifdef HARD
X	if ((rn2(10) + u.ulevel + u.uluck - spellev(spell)) < 0) {
X
X		pline("Fizzle.....");
X		return(0);
X	}
X#endif
X
X/*	pseudo is a temporary "false" object containing the spell stats. */
X	pseudo = mksobj(spellid(spell));
X	pseudo->quan = 20;			/* do not let useup get it */
X	switch(pseudo->otyp)  {
X
X/* These spells are all duplicates of wand effects */
X	case SPE_FORCE_BOLT:
X	case SPE_SLEEP:
X	case SPE_MAGIC_MISSILE:
X	case SPE_SLOW_MONSTER:
X	case SPE_FIREBALL:
X	case SPE_CONE_OF_COLD:
X	case SPE_DIG:
X	case SPE_TURN_UNDEAD:
X	case SPE_POLYMORPH:
X	case SPE_TELEPORT_AWAY:
X	case SPE_CANCELLATION:
X	case SPE_FINGER_OF_DEATH:
X	case SPE_LIGHT:
X	case SPE_DETECT_UNSEEN:
X		if (!(objects[pseudo->otyp].bits & NODIR))	getdir(1);
X		weffects(pseudo);
X		break;
X/* These are all duplicates of scroll effects */
X	case SPE_CONFUSE_MONSTER:
X	case SPE_DETECT_FOOD:
X	case SPE_CAUSE_FEAR:
X	case SPE_CHARM_MONSTER:
X	case SPE_REMOVE_CURSE:
X	case SPE_MAGIC_MAPPING:
X	case SPE_CREATE_MONSTER:
X	case SPE_IDENTIFY:
X	case SPE_GENOCIDE:
X		seffects(pseudo);
X		break;
X	case SPE_HASTE_SELF:
X	case SPE_DETECT_TREASURE:
X	case SPE_DETECT_MONSTERS:
X	case SPE_LEVITATION:
X	case SPE_RESTORE_STRENGTH:
X	case SPE_INVISIBILITY:
X		peffects(pseudo);
X		break;
X	case SPE_HEALING:
X		pline("You feel a bit better.");
X		healup(rnd(8), 1, 0, 0);
X		break;
X	case SPE_CURE_BLINDNESS:
X		healup(0, 0, 0, 1);
X		break;
X	case SPE_CURE_SICKNESS:
X		pline("You are no longer ill.");
X		healup(0, 0, 1, 0);
X		break;
X	case SPE_EXTRA_HEALING:
X		pline("You feel a fair bit better.");
X		healup(d(2,8), 1, 0, 0);
X		break;
X	case SPE_CREATE_FAMILIAR:
X		{	register struct monst *mtmp;
X			struct   monst  *makedog();
X
X			mtmp = makedog();
X			if(mtmp) {
X				/* make it into something else */
X				(void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]);
X				if(confused)
X					mtmp->mtame = mtmp->mpeaceful = 0;
X			}
X		}
X		break;
X	default:
X		impossible("Unknown spell %d attempted.", spell);
X		obfree(pseudo, (struct obj *)0);
X		return(0);
X	}
X	flags.botl = 1;
X	obfree(pseudo, (struct obj *)0);	/* now, get rid of it */
X	return(1);
X}
X
Xgetspell()  {
X
X	register int	max, ilet, i;
X	char	 lets[BUFSZ], buf[BUFSZ];
X
X	if (spl_book[0].sp_id == NO_SPELL)  {
X
X		pline("You don't know any spells right now.");
X		return(0);
X	} else  {
X
X	    for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++);
X	    if (max >= MAXSPELL)  {
X
X		impossible("Too many spells memorized.");
X		return(0);
X	    }
X
X	    for(i = 0; (i < max) && (i < 26); buf[++i] = 0)  buf[i] = 'a' + i;
X	    for(i = 26; (i < max) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26;
X
X	    if (max == 1)  strcpy(lets, "a");
X	    else if (max < 27)  sprintf(lets, "a-%c", 'a' + max - 1);
X	    else if (max == 27)  sprintf(lets, "a-z A");
X	    else sprintf(lets, "a-z A-%c", 'A' + max - 27);
X	    for(;;)  {
X
X		pline("Cast which spell [%s ?]: ", lets);
X		if ((ilet = readchar()) == '?')  {
X			dovspell();
X			continue;
X		} else if ((ilet == '\033')||(ilet == '\n')||(ilet == ' '))
X			return(0);
X		else for(i = 0; buf[i] != 0; i++)  if(ilet == buf[i])  return(++i);
X		pline("You don't know that spell.");
X	    }
X	}
X}
X
Xlosespells() {
X	register boolean confused = (Confusion != 0);
X	register int	 n, nzap, i;
X
X	for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++);
X	if (!n) return;
X	if (n < MAXSPELL) {
X		nzap = rnd(n);
X		if (nzap < n) nzap += confused;
X		for (i = 0; i < nzap; i++) spl_book[n-i-1].sp_id = NO_SPELL;
X	} else impossible("Too many spells in spellbook!");
X	return;
X}
X
Xdovspell() {
X
X	register int max, i, side;
X	char     buf[BUFSZ],
X		 *spellname();
X
X	if (spl_book[0].sp_id == NO_SPELL)  {
X
X		pline("You don't know any spells right now.");
X		return(0);
X	} else  {
X
X	    for(max = 1; (max < MAXSPELL) && (spl_book[max].sp_id != NO_SPELL); max++);
X	    if (max >= MAXSPELL)  {
X
X		impossible("Too many spells memorized.");
X		return(0);
X	    }
X	}
X	set_pager(0);
X	side = (max + 1) / 2;
X	if(page_line("Currently known spells:") || page_line(""))  goto quit;
X
X	for(i = 1; i <= side; i++) {
X
X		if((i < side) || !(max % 2))  {
X
X		    (void) sprintf(buf, "%c - (%d) %22s          %c - (%d) %22s",
X				   spellet(i), spellev(i), spellname(i),
X				   spellet(i + side), spellev(i + side), spellname(i + side));
X		} else {
X
X		    (void) sprintf(buf, "%c - (%d) %22s", spellet(i), spellev(i), spellname(i));
X		}
X		if(page_line(buf)) goto quit;
X	}
X
X	set_pager(1);
X	return(0);
Xquit:
X	set_pager(2);
X	return(0);
X}
X
Xspellet(spl)  {
X
X	if (spl < 27)	return('a' + spl - 1);
X	else		return('A' + spl - 27);
X}
X
Xspellev(spl)  {
X
X	return(spl_book[spl-1].sp_lev);
X}
X
Xchar *
Xspellname(spl)  {
X
X	return(objects[spl_book[spl-1].sp_id].oc_name);
X}
X
Xspellid(spl)  {
X
X	return(spl_book[spl-1].sp_id);
X}
X
X#endif /* SPELLS /**/
END_OF_spell.c
if test 9414 -ne `wc -c <spell.c`; then
    echo shar: \"spell.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f worn.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"worn.c\"
else
echo shar: Extracting \"worn.c\" \(1402 characters\)
sed "s/^X//" >worn.c <<'END_OF_worn.c'
X/*	SCCS Id: @(#)worn.c	1.3	87/07/14
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* worn.c - version 1.0.2 */
X
X#include "hack.h"
X
Xstruct worn {
X	long w_mask;
X	struct obj **w_obj;
X} worn[] = {
X	{ W_ARM, &uarm },
X	{ W_ARM2, &uarm2 },
X	{ W_ARMH, &uarmh },
X	{ W_ARMS, &uarms },
X	{ W_ARMG, &uarmg },
X	{ W_RINGL, &uleft },
X	{ W_RINGR, &uright },
X	{ W_WEP, &uwep },
X	{ W_BALL, &uball },
X	{ W_CHAIN, &uchain },
X	{ 0, 0 }
X};
X
Xsetworn(obj, mask)
Xregister struct obj *obj;
Xlong mask;
X{
X	register struct worn *wp;
X	register struct obj *oobj;
X
X	for(wp = worn; wp->w_mask; wp++) if(wp->w_mask & mask) {
X		oobj = *(wp->w_obj);
X		if(oobj && !(oobj->owornmask & wp->w_mask))
X			impossible("Setworn: mask = %ld.", wp->w_mask);
X		if(oobj) oobj->owornmask &= ~wp->w_mask;
X		if(obj && oobj && wp->w_mask == W_ARM){
X			if(uarm2) {
X				impossible("Setworn: uarm2 set?");
X			} else
X				setworn(uarm, W_ARM2);
X		}
X		*(wp->w_obj) = obj;
X		if(obj) obj->owornmask |= wp->w_mask;
X	}
X	if(uarm2 && !uarm) {
X		uarm = uarm2;
X		uarm2 = 0;
X		uarm->owornmask ^= (W_ARM | W_ARM2);
X	}
X}
X
X/* called e.g. when obj is destroyed */
Xsetnotworn(obj) register struct obj *obj; {
X	register struct worn *wp;
X
X	for(wp = worn; wp->w_mask; wp++)
X		if(obj == *(wp->w_obj)) {
X			*(wp->w_obj) = 0;
X			obj->owornmask &= ~wp->w_mask;
X		}
X	if(uarm2 && !uarm) {
X		uarm = uarm2;
X		uarm2 = 0;
X		uarm->owornmask ^= (W_ARM | W_ARM2);
X	}
X}
END_OF_worn.c
if test 1402 -ne `wc -c <worn.c`; then
    echo shar: \"worn.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 11 \(of 16\).
cp /dev/null ark11isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 16 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0