[comp.sources.games] v03i004: NetHack2.2 - display oriented dungeons and dragons, Part04/20

games-request@tekred.TEK.COM (12/02/87)

Submitted by: mike@genat.UUCP (Mike Stephenson)
Comp.sources.games: Volume 3, Issue 4
Archive-name: nethack2.2/Part04



#! /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 4 (of 20)."
# Contents:  invent.c shk.c trap.h
# Wrapped by billr@tekred on Tue Dec  1 16:24:50 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f invent.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"invent.c\"
else
echo shar: Extracting \"invent.c\" \(22894 characters\)
sed "s/^X//" >invent.c <<'END_OF_invent.c'
X/*	SCCS Id: @(#)invent.c	2.1	87/10/19
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X
X#include	<stdio.h>
X#include	"hack.h"
Xextern struct obj *splitobj();
Xextern struct obj zeroobj;
Xextern char morc;
Xextern char quitchars[];
Xstatic char *xprname();
X
X#ifndef NOWORM
X#include	"wseg.h"
Xextern struct wseg *wsegs[32];
X#endif
X
X#define	NOINVSYM	'#'
X
Xint lastinvnr = 51;	/* 0 ... 51 */
X
Xstatic
Xassigninvlet(otmp)
Xregister struct obj *otmp;
X{
X	boolean inuse[52];
X	register int i;
X	register struct obj *obj;
X
X	for(i = 0; i < 52; i++) inuse[i] = FALSE;
X	for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
X		i = obj->invlet;
X		if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
X		if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
X		if(i == otmp->invlet) otmp->invlet = 0;
X	}
X	if((i = otmp->invlet) &&
X	    (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
X		return;
X	for(i = lastinvnr+1; i != lastinvnr; i++) {
X		if(i == 52) { i = -1; continue; }
X		if(!inuse[i]) break;
X	}
X	otmp->invlet = (inuse[i] ? NOINVSYM :
X			(i < 26) ? ('a'+i) : ('A'+i-26));
X	lastinvnr = i;
X}
X
Xstruct obj *
Xaddinv(obj)
Xregister struct obj *obj;
X{
X	register struct obj *otmp;
X
X	/* merge or attach to end of chain */
X	if(!invent) {
X		invent = obj;
X		otmp = 0;
X	} else
X	for(otmp = invent; /* otmp */; otmp = otmp->nobj) {
X		if(merged(otmp, obj, 0))
X			return(otmp);
X		if(!otmp->nobj) {
X			otmp->nobj = obj;
X			break;
X		}
X	}
X	obj->nobj = 0;
X
X	if(flags.invlet_constant) {
X		assigninvlet(obj);
X		/*
X		 * The ordering of the chain is nowhere significant
X		 * so in case you prefer some other order than the
X		 * historical one, change the code below.
X		 */
X		if(otmp) {	/* find proper place in chain */
X			otmp->nobj = 0;
X			if((invent->invlet ^ 040) > (obj->invlet ^ 040)) {
X				obj->nobj = invent;
X				invent = obj;
X			} else
X			for(otmp = invent; ; otmp = otmp->nobj) {
X			    if(!otmp->nobj ||
X				(otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){
X				obj->nobj = otmp->nobj;
X				otmp->nobj = obj;
X				break;
X			    }
X			}
X		}
X	}
X
X	return(obj);
X}
X
Xuseup(obj)
Xregister struct obj *obj;
X{
X	if(obj->quan > 1){
X		obj->quan--;
X		obj->owt = weight(obj);
X	} else {
X		setnotworn(obj);
X		freeinv(obj);
X		obfree(obj, (struct obj *) 0);
X	}
X}
X
Xfreeinv(obj)
Xregister struct obj *obj;
X{
X	register struct obj *otmp;
X
X	if(obj == invent)
X		invent = invent->nobj;
X	else {
X		for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)
X			if(!otmp->nobj) panic("freeinv");
X		otmp->nobj = obj->nobj;
X	}
X}
X
X/* destroy object in fobj chain (if unpaid, it remains on the bill) */
Xdelobj(obj) register struct obj *obj; {
X	freeobj(obj);
X	unpobj(obj);
X	obfree(obj, (struct obj *) 0);
X}
X
X/* unlink obj from chain starting with fobj */
Xfreeobj(obj) register struct obj *obj; {
X	register struct obj *otmp;
X
X	if(obj == fobj) fobj = fobj->nobj;
X	else {
X		for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj)
X			if(!otmp) panic("error in freeobj");
X		otmp->nobj = obj->nobj;
X	}
X}
X
X/* Note: freegold throws away its argument! */
Xfreegold(gold) register struct gold *gold; {
X	register struct gold *gtmp;
X
X	if(gold == fgold) fgold = gold->ngold;
X	else {
X		for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)
X			if(!gtmp) panic("error in freegold");
X		gtmp->ngold = gold->ngold;
X	}
X	free((char *) gold);
X}
X
Xdeltrap(trap)
Xregister struct trap *trap;
X{
X	register struct trap *ttmp;
X
X	if(trap == ftrap)
X		ftrap = ftrap->ntrap;
X	else {
X		for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
X		ttmp->ntrap = trap->ntrap;
X	}
X	free((char *) trap);
X}
X
Xstruct wseg *m_atseg;
X
Xstruct monst *
Xm_at(x,y)
Xregister x,y;
X{
X	register struct monst *mtmp;
X#ifndef NOWORM
X	register struct wseg *wtmp;
X#endif
X
X	m_atseg = 0;
X	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
X		if(mtmp->mx == x && mtmp->my == y)
X			return(mtmp);
X#ifndef NOWORM
X		if(mtmp->wormno){
X		    for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg)
X		    if(wtmp->wx == x && wtmp->wy == y){
X			m_atseg = wtmp;
X			return(mtmp);
X		    }
X		}
X#endif
X	}
X	return(0);
X}
X
Xstruct obj *
Xo_at(x,y)
Xregister x,y;
X{
X	register struct obj *otmp;
X
X	for(otmp = fobj; otmp; otmp = otmp->nobj)
X		if(otmp->ox == x && otmp->oy == y) return(otmp);
X	return(0);
X}
X
Xstruct obj *
Xsobj_at(n,x,y)
Xregister n,x,y;
X{
X	register struct obj *otmp;
X
X	for(otmp = fobj; otmp; otmp = otmp->nobj)
X		if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)
X			return(otmp);
X	return(0);
X}
X
Xcarried(obj) register struct obj *obj; {
Xregister struct obj *otmp;
X	for(otmp = invent; otmp; otmp = otmp->nobj)
X		if(otmp == obj) return(1);
X	return(0);
X}
X
Xstruct obj *
Xcarrying(type)
Xregister int type;
X{
X	register struct obj *otmp;
X
X	for(otmp = invent; otmp; otmp = otmp->nobj)
X		if(otmp->otyp == type)
X			return(otmp);
X	return((struct obj *) 0);
X}
X
Xstruct obj *
Xo_on(id, objchn) unsigned int id; register struct obj *objchn; {
X	while(objchn) {
X		if(objchn->o_id == id) return(objchn);
X		objchn = objchn->nobj;
X	}
X	return((struct obj *) 0);
X}
X
Xstruct trap *
Xt_at(x,y)
Xregister x,y;
X{
X	register struct trap *trap = ftrap;
X	while(trap) {
X		if(trap->tx == x && trap->ty == y) return(trap);
X		trap = trap->ntrap;
X	}
X	return(0);
X}
X
Xstruct gold *
Xg_at(x,y)
Xregister x,y;
X{
X	register struct gold *gold = fgold;
X	while(gold) {
X		if(gold->gx == x && gold->gy == y) return(gold);
X		gold = gold->ngold;
X	}
X	return(0);
X}
X
X/* make dummy object structure containing gold - for temporary use only */
Xstruct obj *
Xmkgoldobj(q)
Xregister long q;
X{
X	register struct obj *otmp;
X
X	otmp = newobj(0);
X	/* should set o_id etc. but otmp will be freed soon */
X	otmp->olet = GOLD_SYM;
X	u.ugold -= q;
X	OGOLD(otmp) = q;
X	flags.botl = 1;
X	return(otmp);
X}
X
X/*
X * getobj returns:
X *	struct obj *xxx:	object to do something with.
X *	(struct obj *) 0	error return: no object.
X *	&zeroobj		explicitly no object (as in w-).
X */
Xstruct obj *
Xgetobj(let,word)
Xregister char *let,*word;
X{
X	register struct obj *otmp;
X	register char ilet,ilet1,ilet2;
X	char buf[BUFSZ];
X	char lets[BUFSZ];
X	register int foo = 0, foo2;
X	register char *bp = buf;
X	xchar allowcnt = 0;	/* 0, 1 or 2 */
X	boolean allowgold = FALSE;
X	boolean allowall = FALSE;
X	boolean allownone = FALSE;
X	xchar foox = 0;
X	long cnt;
X
X	if(*let == '0') let++, allowcnt = 1;
X	if(*let == GOLD_SYM) let++, allowgold = TRUE;
X	if(*let == '#') let++, allowall = TRUE;
X	if(*let == '-') let++, allownone = TRUE;
X	if(allownone) *bp++ = '-';
X	if(allowgold) *bp++ = GOLD_SYM;
X	if(bp > buf && bp[-1] == '-') *bp++ = ' ';
X
X	ilet = 'a';
X	for(otmp = invent; otmp; otmp = otmp->nobj){
X	    if(!*let || index(let, otmp->olet)) {
X		bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet;
X
X		/* ugly check: remove inappropriate things */
X		if((!strcmp(word, "take off") &&
X		    !(otmp->owornmask & (W_ARMOR - W_ARM2)))
X		|| (!strcmp(word, "wear") &&
X		    (otmp->owornmask & (W_ARMOR | W_RING)))
X		|| (!strcmp(word, "wield") &&
X		    (otmp->owornmask & W_WEP))
X#ifdef MARKER
X		|| (!strcmp(word, "write with") &&
X		    (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER))
X#endif
X		    ) {
X			foo--;
X			foox++;
X		}
X	    }
X	    if(ilet == 'z') ilet = 'A'; else ilet++;
X	}
X	bp[foo] = 0;
X	if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
X	(void) strcpy(lets, bp);	/* necessary since we destroy buf */
X	if(foo > 5) {			/* compactify string */
X		foo = foo2 = 1;
X		ilet2 = bp[0];
X		ilet1 = bp[1];
X		while(ilet = bp[++foo2] = bp[++foo]){
X			if(ilet == ilet1+1){
X				if(ilet1 == ilet2+1)
X					bp[foo2 - 1] = ilet1 = '-';
X				else if(ilet2 == '-') {
X					bp[--foo2] = ++ilet1;
X					continue;
X				}
X			}
X			ilet2 = ilet1;
X			ilet1 = ilet;
X		}
X	}
X	if(!foo && !allowall && !allowgold && !allownone) {
X		pline("You don't have anything %sto %s.",
X			foox ? "else " : "", word);
X		return(0);
X	}
X	for(;;) {
X		if(!buf[0]) {
X#ifdef REDO
X		    if(!in_doagain)
X#endif
X			pline("What do you want to %s [*]? ", word);
X		} else {
X#ifdef REDO
X		    if(!in_doagain)
X#endif
X			pline("What do you want to %s [%s or ?*]? ",
X				word, buf);
X		}
X		cnt = 0;
X		ilet = readchar();
X		while(digit(ilet) && allowcnt) {
X#ifdef REDO
X			if (ilet != '?' && ilet != '*')	savech(ilet);
X#endif
X			cnt = 10*cnt + (ilet - '0');
X			allowcnt = 2;	/* signal presence of cnt */
X			ilet = readchar();
X		}
X		if(digit(ilet)) {
X			pline("No count allowed with this command.");
X			continue;
X		}
X		if(index(quitchars,ilet)) {
X			pline("Never mind.");
X			return((struct obj *)0);
X		}
X		if(ilet == '-') {
X			return(allownone ? &zeroobj : (struct obj *) 0);
X		}
X		if(ilet == GOLD_SYM) {
X			if(!allowgold){
X				pline("You cannot %s gold.", word);
X				continue;
X			}
X			if(!(allowcnt == 2 && cnt < u.ugold))
X				cnt = u.ugold;
X			return(mkgoldobj(cnt));
X		}
X		if(ilet == '?') {
X			doinv(lets);
X			if(!(ilet = morc)) continue;
X			/* he typed a letter (not a space) to more() */
X		} else if(ilet == '*') {
X			doinv((char *) 0);
X			if(!(ilet = morc)) continue;
X			/* ... */
X		}
X#ifdef REDO
X		if (ilet != '?' && ilet != '*')	savech(ilet);
X#endif
X		if(flags.invlet_constant) {
X			for(otmp = invent; otmp; otmp = otmp->nobj)
X				if(otmp->invlet == ilet) break;
X		} else {
X			if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1;
X			ilet -= 'a';
X			for(otmp = invent; otmp && ilet;
X					ilet--, otmp = otmp->nobj) ;
X		}
X		if(!otmp) {
X			pline("You don't have that object.");
X			continue;
X		}
X		if(cnt < 0 || otmp->quan < cnt) {
X			pline("You don't have that many! [You have %u]"
X			, otmp->quan);
X			continue;
X		}
X		break;
X	}
X	if(!allowall && let && !index(let,otmp->olet)) {
X		pline("That is a silly thing to %s.",word);
X		return(0);
X	}
X	if(allowcnt == 2) {	/* cnt given */
X		if(cnt == 0) return(0);
X		if(cnt != otmp->quan) {
X			register struct obj *obj;
X			obj = splitobj(otmp, (int) cnt);
X			if(otmp == uwep) setuwep(obj);
X		}
X	}
X	return(otmp);
X}
X
Xckunpaid(otmp) register struct obj *otmp; {
X	return( otmp->unpaid );
X}
X
X/* interactive version of getobj - used for Drop and Identify */
X/* return the number of times fn was called successfully */
Xggetobj(word, fn, max)
Xchar *word;
Xint (*fn)(),  max;
X{
Xchar buf[BUFSZ];
Xregister char *ip;
Xregister char sym;
Xregister int oletct = 0, iletct = 0;
Xregister boolean allflag = FALSE;
Xchar olets[20], ilets[20];
Xint (*ckfn)() = (int (*)()) 0;
Xxchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0;	/* BAH */
X	if(!invent && !allowgold){
X		pline("You have nothing to %s.", word);
X		return(0);
X	} else {
X		register struct obj *otmp = invent;
X		register int uflg = 0;
X
X		if(allowgold) ilets[iletct++] = GOLD_SYM;
X		ilets[iletct] = 0;
X		while(otmp) {
X			if(!index(ilets, otmp->olet)){
X				ilets[iletct++] = otmp->olet;
X				ilets[iletct] = 0;
X			}
X			if(otmp->unpaid) uflg = 1;
X			otmp = otmp->nobj;
X		}
X		ilets[iletct++] = ' ';
X		if(uflg) ilets[iletct++] = 'u';
X		if(invent) ilets[iletct++] = 'a';
X		ilets[iletct] = 0;
X	}
X	pline("What kinds of thing do you want to %s? [%s] ",
X		word, ilets);
X	getlin(buf);
X	if(buf[0] == '\033') {
X		clrlin();
X		return(0);
X	}
X	ip = buf;
X	olets[0] = 0;
X	while(sym = *ip++){
X		if(sym == ' ') continue;
X		if(sym == GOLD_SYM) {
X			if(allowgold == 1)
X				(*fn)(mkgoldobj(u.ugold));
X			else if(!u.ugold)
X				pline("You have no gold.");
X			allowgold = 2;
X		} else
X		if(sym == 'a' || sym == 'A') allflag = TRUE; else
X		if(sym == 'u' || sym == 'U') ckfn = ckunpaid; else
X#ifdef SPELLS
X		if(index("!%?[()=*/+\"0", sym)){
X#else
X		if(index("!%?[()=*/\"0", sym)){
X#endif
X			if(!index(olets, sym)){
X				olets[oletct++] = sym;
X				olets[oletct] = 0;
X			}
X		}
X		else pline("You don't have any %c's.", sym);
X	}
X	if(allowgold == 2 && !oletct)
X		return(1);	/* he dropped gold (or at least tried to) */
X	else
X		return(askchain(invent, olets, allflag, fn, ckfn, max));
X}
X
X/*
X * Walk through the chain starting at objchn and ask for all objects
X * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL)
X * whether the action in question (i.e., fn) has to be performed.
X * If allflag then no questions are asked. Max gives the max nr of
X * objects to be treated. Return the number of objects treated.
X */
Xaskchain(objchn, olets, allflag, fn, ckfn, max)
Xstruct obj *objchn;
Xregister char *olets;
Xint allflag;
Xint (*fn)(), (*ckfn)();
Xint max;
X{
Xregister struct obj *otmp, *otmp2;
Xregister char sym, ilet;
Xregister int cnt = 0;
X#ifdef SORTING
X	/* changes so the askchain is interrogated in the order specified.
X	 * For example, if a person specifies =/ then first all rings will be
X	 * asked about followed by all wands -dgk
X	 */
Xnextclass:
X#endif
X	ilet = 'a'-1;
X	for(otmp = objchn; otmp; otmp = otmp2){
X		if(ilet == 'z') ilet = 'A'; else ilet++;
X		otmp2 = otmp->nobj;
X#ifdef SORTING
X		if (olets && *olets && otmp->olet != *olets) continue;
X#else
X		if(olets && *olets && !index(olets, otmp->olet)) continue;
X#endif
X		if(ckfn && !(*ckfn)(otmp)) continue;
X		if(!allflag) {
X			pline(xprname(otmp, ilet));
X			addtopl(" [nyaq]? ");
X			sym = readchar();
X		}
X		else	sym = 'y';
X
X		switch(sym){
X		case 'a':
X			allflag = 1;
X		case 'y':
X			cnt += (*fn)(otmp);
X			if(--max == 0) goto ret;
X		case 'n':
X		default:
X			break;
X		case 'q':
X			goto ret;
X		}
X	}
X#ifdef SORTING
X	if (olets && *olets && *++olets)
X		goto nextclass;
X#endif
X	pline(cnt ? "That was all." : "No applicable objects.");
Xret:
X	return(cnt);
X}
X
Xobj_to_let(obj)	/* should of course only be called for things in invent */
Xregister struct obj *obj;
X{
X	register struct obj *otmp;
X	register char ilet;
X
X	if(flags.invlet_constant)
X		return(obj->invlet);
X	ilet = 'a';
X	for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj)
X		if(++ilet > 'z') ilet = 'A';
X	return(otmp ? ilet : NOINVSYM);
X}
X
Xprinv(obj)
Xregister struct obj *obj;
X{
X	pline(xprname(obj, obj_to_let(obj)));
X}
X
Xstatic char *
Xxprname(obj,let)
Xregister struct obj *obj;
Xregister char let;
X{
X	static char li[BUFSZ];
X
X	(void) sprintf(li, "%c - %s.",
X		flags.invlet_constant ? obj->invlet : let,
X		doname(obj));
X	return(li);
X}
X
Xddoinv()
X{
X	doinv((char *) 0);
X	return(0);
X}
X
X#ifdef SORTING
X# ifdef SPELLS
Xchar inv_order[] = "\")[%?+/=!(*0_`";	/* to be safe, include _ and ` */
X# else
Xchar inv_order[] = "\")[%?/=!(*0_`";
X# endif
Xextern char *let_to_name();
X#endif
X
X/* called with 0 or "": all objects in inventory */
X/* otherwise: all objects with (serial) letter in lets */
Xdoinv(lets)
Xregister char *lets;
X{
X	register struct obj *otmp;
X	register char ilet;
X	int ct = 0;
X	char any[BUFSZ];
X#ifdef SORTING
X	char *invlet = inv_order;
X	int classcount = 0;
X#endif /* SORTING /**/
X
X	morc = 0;		/* just to be sure */
X
X	if(!invent){
X		pline("Not carrying anything.");
X		return;
X	}
X
X	cornline(0, (char *) 0);
X#ifdef SORTING
Xnextclass:
X	classcount = 0;
X	ilet = 'a';
X	for(otmp = invent; otmp; otmp = otmp->nobj) {
X		if(flags.invlet_constant) ilet = otmp->invlet;
X		if(!lets || !*lets || index(lets, ilet)) {
X			if (!flags.sortpack || otmp->olet == *invlet) {
X				if (flags.sortpack && !classcount) {
X					cornline(1, let_to_name(*invlet));
X					classcount++;
X				}
X				cornline(1, xprname(otmp, ilet));
X				any[ct++] = ilet;
X			}
X		}
X		if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
X	}
X	if (flags.sortpack && *++invlet) goto nextclass;
X#else
X	ilet = 'a';
X	for(otmp = invent; otmp; otmp = otmp->nobj) {
X	    if(flags.invlet_constant) ilet = otmp->invlet;
X	    if(!lets || !*lets || index(lets, ilet)) {
X		    cornline(1, xprname(otmp, ilet));
X		    any[ct++] = ilet;
X	    }
X	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
X	}
X#endif /* SORTING /**/
X	any[ct] = 0;
X	cornline(2, any);
X}
X
Xdotypeinv ()				/* free after Robert Viduya */
X/* Changed to one type only, so he doesnt have to type cr */
X{
X    char c, ilet;
X    char stuff[BUFSZ];
X    register int stct;
X    register struct obj *otmp;
X    boolean billx = inshop() && doinvbill(0);
X    boolean unpd = FALSE;
X
X	if (!invent && !u.ugold && !billx) {
X	    pline ("You aren't carrying anything.");
X	    return(0);
X	}
X
X	stct = 0;
X	if(u.ugold) stuff[stct++] = GOLD_SYM;
X	stuff[stct] = 0;
X	for(otmp = invent; otmp; otmp = otmp->nobj) {
X	    if (!index (stuff, otmp->olet)) {
X		stuff[stct++] = otmp->olet;
X		stuff[stct] = 0;
X	    }
X	    if(otmp->unpaid)
X		unpd = TRUE;
X	}
X	if(unpd) stuff[stct++] = 'u';
X	if(billx) stuff[stct++] = 'x';
X	stuff[stct] = 0;
X
X	if(stct > 1) {
X#ifdef REDO
X	  if (!in_doagain)
X#endif
X	    pline ("What type of object [%s] do you want an inventory of? ",
X		stuff);
X	    c = readchar();
X#ifdef REDO
X	    savech(c);
X#endif
X	    if(index(quitchars,c)) {
X	    	    clrlin();
X	    	    return(0);
X	    }
X	} else
X	    c = stuff[0];
X
X	if(c == GOLD_SYM)
X	    return(doprgold());
X
X	if(c == 'x' || c == 'X') {
X	    if(billx)
X		(void) doinvbill(1);
X	    else
X		pline("No used-up objects on the shopping bill.");
X	    return(0);
X	}
X
X	if((c == 'u' || c == 'U') && !unpd) {
X		pline("You are not carrying any unpaid objects.");
X		return(0);
X	}
X
X	stct = 0;
X	ilet = 'a';
X	for (otmp = invent; otmp; otmp = otmp -> nobj) {
X	    if(flags.invlet_constant) ilet = otmp->invlet;
X	    if (c == otmp -> olet || (c == 'u' && otmp -> unpaid))
X		stuff[stct++] = ilet;
X	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
X	}
X	stuff[stct] = '\0';
X	if(stct == 0)
X		pline("You have no such objects.");
X	else
X		doinv (stuff);
X
X	return(0);
X}
X
X/* look at what is here */
Xdolook() {
X    register struct obj *otmp, *otmp0;
X    register struct gold *gold;
X    char *verb = Blind ? "feel" : "see";
X    int	ct = 0;
X    int fd = 0;
X
X#ifdef KAA
X    read_engr_at(u.ux, u.uy); /* Eric Backus */
X#endif
X    if(!u.uswallow) {
X	otmp0 = o_at(u.ux, u.uy);
X	gold = g_at(u.ux, u.uy);
X    }  else  {
X	pline("You %s no objects here.", verb);
X	return(!!Blind);
X    }
X
X    /* added by GAN 10/30/86 */
X#ifdef FOUNTAINS
X    if(IS_FOUNTAIN(levl[u.ux][u.uy].typ))  {
X	fd++;
X	pline("There is a fountain here.");
X    }
X#endif
X#ifdef NEWCLASS
X    if(IS_THRONE(levl[u.ux][u.uy].typ))  {
X	fd++;
X	pline("There is an opulent throne here.");
X    }    
X#endif
X    if(u.ux == xupstair && u.uy == yupstair)  {
X	fd++;
X	pline("There is a stairway up here.");
X    }
X    if(u.ux == xdnstair && u.uy == ydnstair)  {
X	fd++;
X	pline("There is a stairway down here.");
X    }
X    if(Blind)  {
X	 pline("You try to feel what is lying here on the floor.");
X	 if(Levitation)  {
X		pline("But you can't reach it!");
X		return(0);
X	 }
X    }
X 
X    if(!otmp0 && !gold) {
X	if(Blind || !fd)
X		pline("You %s no objects here.", verb);
X	return(!!Blind);
X    }
X
X    cornline(0, "Things that are here:");
X    for(otmp = otmp0; otmp; otmp = otmp->nobj) {
X	if(otmp->ox == u.ux && otmp->oy == u.uy) {
X	    ct++;
X	    cornline(1, doname(otmp));
X			
X	    if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) {
X		pline("Touching the dead cockatrice is a fatal mistake ...");
X		pline("You die ...");
X		killer = "dead cockatrice";
X		done("died");
X	    }
X	}
X    }
X
X    if(gold) {
X	char gbuf[30];
X
X	(void) sprintf(gbuf, "%ld gold piece%s",
X		gold->amount, plur(gold->amount));
X	if(!ct++)
X	    pline("You %s here %s.", verb, gbuf);
X	else
X	    cornline(1, gbuf);
X    }
X
X    if(ct == 1 && !gold) {
X	pline("You %s here %s.", verb, doname(otmp0));
X	cornline(3, (char *) 0);
X    }
X    if(ct > 1)
X	cornline(2, (char *) 0);
X    return(!!Blind);
X}
X
Xstackobj(obj) register struct obj *obj; {
Xregister struct obj *otmp = fobj;
X	for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj)
X	if(otmp->ox == obj->ox && otmp->oy == obj->oy &&
X		merged(obj,otmp,1))
X			return;
X}
X
X/* merge obj with otmp and delete obj if types agree */
Xmerged(otmp,obj,lose) register struct obj *otmp, *obj; {
X	if(obj->otyp == otmp->otyp &&
X	  obj->unpaid == otmp->unpaid &&
X	  obj->spe == otmp->spe &&
X	  obj->dknown == otmp->dknown &&
X	  obj->cursed == otmp->cursed &&
X#ifdef SPELLS
X	  (index("%*?!+", obj->olet) ||
X#else
X	  (index("%*?!", obj->olet) ||
X#endif
X	    (obj->known == otmp->known &&
X		(obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)))) {
X		otmp->quan += obj->quan;
X		otmp->owt += obj->owt;
X		if(lose) freeobj(obj);
X		obfree(obj,otmp);	/* free(obj), bill->otmp */
X		return(1);
X	} else	return(0);
X}
X
X/*
X * Gold is no longer displayed; in fact, when you have a lot of money,
X * it may take a while before you have counted it all.
X * [Bug: d$ and pickup still tell you how much it was.]
X */
Xextern int (*occupation)();
Xextern char *occtxt;
Xstatic long goldcounted;
X
Xcountgold(){
X	if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) {
X		long eps = 0;
X		if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1));
X		pline("You probably have about %ld gold pieces.",
X			u.ugold + eps);
X		return(0);	/* done */
X	}
X	return(1);		/* continue */
X}
X
Xdoprgold(){
X	if(!u.ugold)
X		pline("You do not carry any gold.");
X	else if(u.ugold <= 500)
X		pline("You are carrying %ld gold piece%s.", u.ugold, plur(u.ugold));
X	else {
X		pline("You sit down in order to count your gold pieces.");
X		goldcounted = 500;
X		occupation = countgold;
X		occtxt = "counting your gold";
X	}
X	return(1);
X}
X
X/* --- end of gold counting section --- */
X
Xdoprwep(){
X	if(!uwep) pline("You are empty handed.");
X	else prinv(uwep);
X	return(0);
X}
X
Xdoprarm(){
X	if(!uarm && !uarmg && !uarms && !uarmh)
X		pline("You are not wearing any armor.");
X	else {
X		char lets[6];
X		register int ct = 0;
X
X		if(uarm) lets[ct++] = obj_to_let(uarm);
X		if(uarm2) lets[ct++] = obj_to_let(uarm2);
X		if(uarmh) lets[ct++] = obj_to_let(uarmh);
X		if(uarms) lets[ct++] = obj_to_let(uarms);
X		if(uarmg) lets[ct++] = obj_to_let(uarmg);
X		lets[ct] = 0;
X		doinv(lets);
X	}
X	return(0);
X}
X
Xdoprring(){
X	if(!uleft && !uright)
X		pline("You are not wearing any rings.");
X	else {
X		char lets[3];
X		register int ct = 0;
X
X		if(uleft) lets[ct++] = obj_to_let(uleft);
X		if(uright) lets[ct++] = obj_to_let(uright);
X		lets[ct] = 0;
X		doinv(lets);
X	}
X	return(0);
X}
X
Xdigit(c) char c; {
X	return(c >= '0' && c <= '9');
X}
X
X/*
X * useupf(obj)
X * uses up an object that's on the floor
X */
Xuseupf(obj)
Xregister struct obj *obj;
X{
X	if(obj->quan > 1)  {
X		obj->quan--;
X		obj->owt = weight(obj);
X	}  else delobj(obj);
X}
X
X#ifdef SORTING
X/*
X * Convert from a symbol to a string for printing object classes
X *
X * Names from objects.h
X * char obj_symbols[] = {
X *	ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM,
X *	BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM,
X *	WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 };
X */
X#define Sprintf (void) sprintf
X
Xextern char obj_symbols[];
Xstatic char *names[] = {"Illegal objects", "Amulets", "Comestibles", "Weapons",
X			"Tools", "Iron balls", "Chains", "Rocks", "Armor",
X			"Potions", "Scrolls", "Wands",
X#ifdef SPELLS
X			"Spellbooks",
X#endif
X			"Rings", "Gems"};
Xchar *
Xlet_to_name(let)
Xchar let;
X{
X	char *pos = index(obj_symbols, let);
X	extern char *HI, *HE;
X	/* arbitrary buffer size by Tom May (tom@uw-warp) */
X	static char *buf = NULL;
X
X	if (buf == NULL)
X	    buf = (char *) alloc (strlen(HI) + strlen(HE) + 15 + 1);
X
X	if (pos == NULL) pos = obj_symbols;
X	if (HI && HE)
X	    Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE);
X	else
X	    Sprintf(buf, "%s", names[pos - obj_symbols]);
X	return (buf);
X}
X#endif /* SORTING /**/
X
Xreassign ()
X{
X	register int i;
X	register struct obj *obj;
X
X	for(obj = invent, i = 0; obj; obj = obj->nobj, i++)
X		obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26);
X	lastinvnr = i;
X}
END_OF_invent.c
if test 22894 -ne `wc -c <invent.c`; then
    echo shar: \"invent.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f shk.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"shk.c\"
else
echo shar: Extracting \"shk.c\" \(27302 characters\)
sed "s/^X//" >shk.c <<'END_OF_shk.c'
X/*	SCCS Id: @(#)shk.c	2.1	87/08/23
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X
X#include "hack.h"
X#ifdef QUEST
Xint shlevel = 0;
Xstruct monst *shopkeeper = 0;
Xstruct	obj	*billobjs = 0;
Xobfree(obj,merge) register struct obj *obj, *merge; {
X	free((char *) obj);
X}
Xinshop(){ return(0); }
Xaddtobill(){}
Xsubfrombill(){}
Xsplitbill(){}
Xdopay(){ return(0); }
Xpaybill(){}
Xdoinvbill(){ return(0); }
Xshkdead(){}
Xshkcatch(){ return(0); }
Xshk_move(){ return(0); }
Xreplshk(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {}
Xchar *shkname(){ return(""); }
X
X#else
X#include	"mfndpos.h"
X#include	"mkroom.h"
X#include	"eshk.h"
X
X#define	ESHK(mon)	((struct eshk *)(&(mon->mextra[0])))
X#define	NOTANGRY(mon)	mon->mpeaceful
X#define	ANGRY(mon)	!NOTANGRY(mon)
X
Xextern char plname[], *xname();
Xextern struct monst *makemon();
Xextern struct obj *o_on(), *bp_to_obj(),
X		  *carrying();
X
X/* Descriptor of current shopkeeper. Note that the bill need not be
X   per-shopkeeper, since it is valid only when in a shop. */
Xstatic struct monst *shopkeeper = 0;
Xstatic struct bill_x *bill;
Xstatic int shlevel = 0;	/* level of this shopkeeper */
X       struct obj *billobjs;	/* objects on bill with bp->useup */
X				/* only accessed here and by save & restore */
Xstatic long int total;		/* filled by addupbill() */
Xstatic long int followmsg;	/* last time of follow message */
Xstatic setpaid(), findshk(), dopayobj(), getprice(), realhunger();
X
X/*
X	invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
X		obj->quan <= bp->bquan
X */
X
Xchar *
Xshkname(mtmp)				/* called in do_name.c */
Xregister struct monst *mtmp;
X{
X	return(ESHK(mtmp)->shknam);
X}
X
Xshkdead(mtmp)				/* called in mon.c */
Xregister struct monst *mtmp;
X{
X	register struct eshk *eshk = ESHK(mtmp);
X
X	if(eshk->shoplevel == dlevel)
X		rooms[eshk->shoproom].rtype = OROOM;
X	if(mtmp == shopkeeper) {
X		setpaid();
X		shopkeeper = 0;
X		bill = (struct bill_x *) -1000;	/* dump core when referenced */
X	}
X}
X
Xreplshk(mtmp,mtmp2)
Xregister struct monst *mtmp, *mtmp2;
X{
X	if(mtmp == shopkeeper) {
X		shopkeeper = mtmp2;
X		bill = &(ESHK(shopkeeper)->bill[0]);
X	}
X}
X
Xstatic
Xsetpaid(){	/* caller has checked that shopkeeper exists */
X		/* either we paid or left the shop or he just died */
Xregister struct obj *obj;
Xregister struct monst *mtmp;
X	for(obj = invent; obj; obj = obj->nobj)
X		obj->unpaid = 0;
X	for(obj = fobj; obj; obj = obj->nobj)
X		obj->unpaid = 0;
X	for(obj = fcobj; obj; obj = obj->nobj)
X		obj->unpaid = 0;
X	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X		for(obj = mtmp->minvent; obj; obj = obj->nobj)
X			obj->unpaid = 0;
X	for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
X		for(obj = mtmp->minvent; obj; obj = obj->nobj)
X			obj->unpaid = 0;
X	while(obj = billobjs){
X		billobjs = obj->nobj;
X		free((char *) obj);
X	}
X	ESHK(shopkeeper)->billct = 0;
X}
X
Xstatic
Xaddupbill(){	/* delivers result in total */
X		/* caller has checked that shopkeeper exists */
Xregister ct = ESHK(shopkeeper)->billct;
Xregister struct bill_x *bp = bill;
X	total = 0;
X	while(ct--){
X		total += bp->price * bp->bquan;
X		bp++;
X	}
X}
X
Xinshop(){
Xregister roomno = inroom(u.ux,u.uy);
X
X	/* Did we just leave a shop? */
X	if(u.uinshop &&
X	    (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
X
X	/* This is part of the bugfix for shopkeepers not having their
X	 * bill paid.  As reported by ab@unido -dgk
X	 * I made this standard due to the KOPS code below. -mrs 
X	 */
X		if(shopkeeper) {
X		    if(ESHK(shopkeeper)->billct) {
X			if(inroom(shopkeeper->mx, shopkeeper->my) 
X			    == u.uinshop - 1)	/* ab@unido */
X			    pline("Somehow you escaped the shop without paying!");
X			addupbill();
X			pline("You stole for a total worth of %ld zorkmids.",
X				total);
X			ESHK(shopkeeper)->robbed += total;
X			setpaid();
X			if((rooms[ESHK(shopkeeper)->shoproom].rtype == SHOPBASE)
X			    == (rn2(3) == 0))
X			    ESHK(shopkeeper)->following = 1;
X#ifdef KOPS
X			{   /* Keystone Kops srt@ucla */
X			    coord mm;
X			    register int cnt = dlevel + rnd(3);
X			    /* Create a swarm near the staircase */
X			    pline("An alarm sounds throughout the dungeon!");
X			    pline("The Keystone Kops are after you!");
X			    mm.x = xdnstair;
X			    mm.y = ydnstair;
X			    while(cnt--) {
X				    (void) enexto(&mm, mm.x, mm.y);
X				    (void) mkmon_at('K', mm.x, mm.y);
X			    }
X			    /* Create a swarm near the shopkeeper */
X			    cnt = dlevel + rnd(3);
X			    mm.x = shopkeeper->mx;
X			    mm.y = shopkeeper->my;
X			    while(cnt--) {
X				    (void) enexto(&mm, mm.x, mm.y);
X				    (void) mkmon_at('K', mm.x, mm.y);
X			    }
X			}
X#endif
X		    }
X		    shopkeeper = 0;
X		    shlevel = 0;
X		}
X		u.uinshop = 0;
X	}
X
X	/* Did we just enter a zoo of some kind? */
X	if(roomno >= 0) {
X		register int rt = rooms[roomno].rtype;
X		register struct monst *mtmp;
X		if(rt == ZOO) {
X			pline("Welcome to David's treasure zoo!");
X		} else
X		if(rt == SWAMP) {
X			pline("It looks rather muddy down here.");
X		} else
X		if(rt == COURT) {
X			pline("You are in an opulent throne room!");
X		} else
X		if(rt == MORGUE) {
X			if(midnight())
X				pline("Go away! Go away!");
X			else
X				pline("You get an uncanny feeling ...");
X		} else
X			rt = 0;
X		if(rt != 0) {
X			rooms[roomno].rtype = OROOM;
X			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X				if(rt != ZOO || !rn2(3))
X					mtmp->msleep = 0;
X		}
X	}
X
X	/* Did we just enter a shop? */
X	if(roomno >= 0 && rooms[roomno].rtype >= SHOPBASE) {
X	    register int rt = rooms[roomno].rtype;
X
X	    if(shlevel != dlevel || !shopkeeper
X				 || ESHK(shopkeeper)->shoproom != roomno)
X		findshk(roomno);
X	    if(!shopkeeper) {
X		rooms[roomno].rtype = OROOM;
X		u.uinshop = 0;
X	    } else if(!u.uinshop){
X		if(!ESHK(shopkeeper)->visitct ||
X		    strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)){
X
X		    /* He seems to be new here */
X		    ESHK(shopkeeper)->visitct = 0;
X		    ESHK(shopkeeper)->following = 0;
X		    (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
X		    NOTANGRY(shopkeeper) = 1;
X		}
X		if(!ESHK(shopkeeper)->following) {
X		    boolean box, pick;
X
X		    pline("Hello %s! Welcome%s to %s's %s!",
X			plname,
X			ESHK(shopkeeper)->visitct++ ? " again" : "",
X			shkname(shopkeeper),
X			shtypes[rt - SHOPBASE].name);
X/*			shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype - SHOPBASE].name);
X*/
X		    box = carrying(ICE_BOX) != (struct obj *)0;
X		    pick = carrying(PICK_AXE) != (struct obj *)0;
X		    if(box || pick) {
X			if(dochug(shopkeeper)) {
X				u.uinshop = 0;	/* he died moving */
X				return(0);
X			}
X			pline("Will you please leave your %s outside?",
X			    (box && pick) ? "box and pick-axe" :
X			    box ? "box" : "pick-axe");
X		    }
X		}
X		u.uinshop = roomno + 1;
X	    }
X	}
X	return(u.uinshop);
X}
X
Xstatic
Xfindshk(roomno)
Xregister roomno;
X{
Xregister struct monst *mtmp;
X	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X	    if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
X			   && ESHK(mtmp)->shoplevel == dlevel) {
X		shopkeeper = mtmp;
X		bill = &(ESHK(shopkeeper)->bill[0]);
X		shlevel = dlevel;
X		if(ANGRY(shopkeeper) &&
X		   strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))
X			NOTANGRY(shopkeeper) = 1;
X		/* billobjs = 0; -- this is wrong if we save in a shop */
X		/* (and it is harmless to have too many things in billobjs) */
X		return;
X	}
X	shopkeeper = 0;
X	shlevel = 0;
X	bill = (struct bill_x *) -1000;	/* dump core when referenced */
X}
X
Xstatic struct bill_x *
Xonbill(obj) register struct obj *obj; {
Xregister struct bill_x *bp;
X	if(!shopkeeper) return(0);
X	for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
X		if(bp->bo_id == obj->o_id) {
X			if(!obj->unpaid) pline("onbill: paid obj on bill?");
X			return(bp);
X		}
X	if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
X	return(0);
X}
X
X/* called with two args on merge */
Xobfree(obj,merge) register struct obj *obj, *merge; {
Xregister struct bill_x *bp = onbill(obj);
Xregister struct bill_x *bpm;
X	if(bp) {
X		if(!merge){
X			bp->useup = 1;
X			obj->unpaid = 0;	/* only for doinvbill */
X			obj->nobj = billobjs;
X			billobjs = obj;
X			return;
X		}
X		bpm = onbill(merge);
X		if(!bpm){
X			/* this used to be a rename */
X			impossible("obfree: not on bill??");
X			return;
X		} else {
X			/* this was a merger */
X			bpm->bquan += bp->bquan;
X			ESHK(shopkeeper)->billct--;
X			*bp = bill[ESHK(shopkeeper)->billct];
X		}
X	}
X	free((char *) obj);
X}
X
Xstatic
Xpay(tmp,shkp)
Xlong tmp;
Xregister struct monst *shkp;
X{
X	long robbed = ESHK(shkp)->robbed;
X
X	u.ugold -= tmp;
X	shkp->mgold += tmp;
X	flags.botl = 1;
X	if(robbed) {
X		robbed -= tmp;
X		if(robbed < 0) robbed = 0;
X		ESHK(shkp)->robbed = robbed;
X	}
X}
X
Xdopay(){
Xlong ltmp;
Xregister struct bill_x *bp;
Xregister struct monst *shkp;
Xint pass, tmp;
X
X	multi = 0;
X	(void) inshop();
X	for(shkp = fmon; shkp; shkp = shkp->nmon)
X		if(shkp->isshk && dist(shkp->mx,shkp->my) < 3)
X			break;
X	if(!shkp && u.uinshop &&
X	   inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)->shoproom)
X		shkp = shopkeeper;
X
X	if(!shkp) {
X		pline("There is nobody here to receive your payment.");
X		return(0);
X	}
X	ltmp = ESHK(shkp)->robbed;
X	if(shkp != shopkeeper && NOTANGRY(shkp)) {
X		if(!ltmp) {
X			pline("You do not owe %s anything.", monnam(shkp));
X		} else
X		if(!u.ugold) {
X			pline("You have no money.");
X		} else {
X		    long ugold = u.ugold;
X
X		    if(u.ugold > ltmp) {
X			pline("You give %s the %ld gold pieces %s asked for.",
X			monnam(shkp), ltmp, index("@CGHKLOQTVWZ&ehimt", shkp->data->mlet)
X			? "he" : (index("nN", shkp->data->mlet) ? "she" : "it"));
X			pay(ltmp, shkp);
X		    } else {
X			pline("You give %s all your gold.", monnam(shkp));
X			pay(u.ugold, shkp);
X		    }
X		    if(ugold < ltmp/2) {
X			pline("Unfortunately, %s doesn't look satisfied.",
X			index("@CGHKLOQTVWZ&ehimt", shkp->data->mlet)
X			? "he" : (index("nN", shkp->data->mlet) ? "she" : "it"));
X		    } else {
X			ESHK(shkp)->robbed = 0;
X			ESHK(shkp)->following = 0;
X			if(ESHK(shkp)->shoplevel != dlevel) {
X			/* For convenience's sake, let him disappear */
X			    shkp->minvent = 0;		/* %% */
X			    shkp->mgold = 0;
X			    mondead(shkp);
X			}
X		    }
X		}
X		return(1);
X	}
X		
X	if(!ESHK(shkp)->billct){
X		pline("You do not owe %s anything.", monnam(shkp));
X		if(!u.ugold){
X			pline("Moreover, you have no money.");
X			return(1);
X		}
X		if(ESHK(shkp)->robbed){
X			pline("But since %s shop has been robbed recently,",
X			index("@CGHKLOQTVWZ&ehimt", shkp->data->mlet)
X			? "his" : (index("nN", shkp->data->mlet) ? "her" : "its"));
X		    pline("you %srepay %s's expenses.",
X		      (u.ugold < ESHK(shkp)->robbed) ? "partially " : "",
X		      monnam(shkp));
X		    pay(min(u.ugold, ESHK(shkp)->robbed), shkp);
X		    ESHK(shkp)->robbed = 0;
X		    return(1);
X		}
X		if(ANGRY(shkp)){
X			pline("But in order to appease %s,",
X				amonnam(shkp, "angry"));
X			if(u.ugold >= 1000){
X				ltmp = 1000;
X				pline(" you give %s 1000 gold pieces.",
X				index("@CGHKLOQTVWZ&ehimt", shkp->data->mlet)
X				? "him" : (index("nN", shkp->data->mlet) ? "her" : "it"));
X			} else {
X				ltmp = u.ugold;
X				pline(" you give %s all your money.",
X				index("@CGHKLOQTVWZ&ehimt", shkp->data->mlet)
X				? "him" : (index("nN", shkp->data->mlet) ? "her" : "it"));
X			}
X			pay(ltmp, shkp);
X			if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)
X			   || rn2(3)){
X				pline("%s calms down.", Monnam(shkp));
X				NOTANGRY(shkp) = 1;
X			} else	pline("%s is as angry as ever.",
X					Monnam(shkp));
X		}
X		return(1);
X	}
X	if(shkp != shopkeeper) {
X		impossible("dopay: not to shopkeeper?");
X		if(shopkeeper) setpaid();
X		return(0);
X	}
X	for(pass = 0; pass <= 1; pass++) {
X		tmp = 0;
X		while(tmp < ESHK(shopkeeper)->billct) {
X			bp = &bill[tmp];
X			if(!pass && !bp->useup) {
X				tmp++;
X				continue;
X			}
X			if(!dopayobj(bp)) return(1);
X#ifdef MSDOS
X			*bp = bill[--ESHK(shopkeeper)->billct];
X#else
X			bill[tmp] = bill[--ESHK(shopkeeper)->billct];
X#endif /* MSDOS /**/
X		}
X	}
X	pline("Thank you for shopping in %s's %s!",
X		shkname(shopkeeper),
X		shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype - SHOPBASE].name);
X	NOTANGRY(shopkeeper) = 1;
X	return(1);
X}
X
X/* return 1 if paid successfully */
X/*        0 if not enough money */
X/*       -1 if object could not be found (but was paid) */
Xstatic
Xdopayobj(bp) register struct bill_x *bp; {
Xregister struct obj *obj;
Xlong ltmp;
X
X	/* find the object on one of the lists */
X	obj = bp_to_obj(bp);
X
X	if(!obj) {
X		impossible("Shopkeeper administration out of order.");
X		setpaid();	/* be nice to the player */
X		return(0);
X	}
X
X	if(!obj->unpaid && !bp->useup){
X		impossible("Paid object on bill??");
X		return(1);
X	}
X	obj->unpaid = 0;
X	ltmp = bp->price * bp->bquan;
X	if(ANGRY(shopkeeper)) ltmp += ltmp/3;
X	if(u.ugold < ltmp){
X		pline("You don't have gold enough to pay %s.",
X			doname(obj));
X		obj->unpaid = 1;
X		return(0);
X	}
X	pay(ltmp, shopkeeper);
X	pline("You bought %s for %ld gold piece%s.",
X		doname(obj), ltmp, plur(ltmp));
X	if(bp->useup) {
X		register struct obj *otmp = billobjs;
X		if(obj == billobjs)
X			billobjs = obj->nobj;
X		else {
X			while(otmp && otmp->nobj != obj) otmp = otmp->nobj;
X			if(otmp) otmp->nobj = obj->nobj;
X			else pline("Error in shopkeeper administration.");
X		}
X		free((char *) obj);
X	}
X	return(1);
X}
X
X/* routine called after dying (or quitting) with nonempty bill */
Xpaybill(){
X	if(shlevel == dlevel && shopkeeper && ESHK(shopkeeper)->billct){
X		addupbill();
X		if(total > u.ugold){
X			shopkeeper->mgold += u.ugold;
X			u.ugold = 0;
X		pline("%s comes and takes all your possessions.",
X			Monnam(shopkeeper));
X		} else {
X			u.ugold -= total;
X			shopkeeper->mgold += total;
X	pline("%s comes and takes the %ld zorkmids you owed him.",
X		Monnam(shopkeeper), total);
X		}
X		setpaid();	/* in case we create bones */
X	}
X}
X
X/* find obj on one of the lists */
Xstruct obj *
Xbp_to_obj(bp)
Xregister struct bill_x *bp;
X{
X	register struct obj *obj;
X	register struct monst *mtmp;
X	register unsigned id = bp->bo_id;
X
X	if(bp->useup)
X		obj = o_on(id, billobjs);
X	else if(!(obj = o_on(id, invent)) &&
X		!(obj = o_on(id, fobj)) &&
X		!(obj = o_on(id, fcobj))) {
X		    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X			if(obj = o_on(id, mtmp->minvent))
X			    break;
X		    for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
X			if(obj = o_on(id, mtmp->minvent))
X			    break;
X		}
X	return(obj);
X}
X
X/* called in hack.c when we pickup an object */
Xaddtobill(obj) register struct obj *obj; {
Xregister struct bill_x *bp;
Xchar	buf[40];
X	if(!inshop() ||
X	(u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
X	(u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y) ||
X		onbill(obj) /* perhaps we threw it away earlier */
X	  ) return;
X	if(ESHK(shopkeeper)->billct == BILLSZ){
X		pline("You got that for free!");
X		return;
X	}
X#ifdef DGKMOD
X	/* To recognize objects the showkeeper is not interested in. -dgk
X	 */
X	if (obj->no_charge) {
X		obj->no_charge = 0;
X		return;
X	}
X#endif
X	bp = &bill[ESHK(shopkeeper)->billct];
X	bp->bo_id = obj->o_id;
X	bp->bquan = obj->quan;
X	bp->useup = 0;
X	bp->price = getprice(obj);
X	strcpy(buf, "For you, ");
X	if (ANGRY(shopkeeper)) strcat(buf, "scum ");
X	else {
X	    switch(rnd(4) + u.udemigod) {
X		case 1:	strcat(buf, "good");
X			break;
X		case 2:	strcat(buf, "honored");
X			break;
X		case 3:	strcat(buf, "most gracious");
X			break;
X		case 4:	strcat(buf, "esteemed");
X			break;
X		case 5:	strcat(buf, "holy");
X			break;
X	    }
X	    if(u.usym != '@') strcat(buf, " creature");
X	    else	      strcat(buf, (flags.female) ? " lady" : " sir");
X	}
X	pline("%s; only %d %s %s.", buf, bp->price,
X			(bp->bquan > 1) ? "per" : "for this",
X			typename(obj->otyp));
X
X	ESHK(shopkeeper)->billct++;
X	obj->unpaid = 1;
X}
X
Xsplitbill(obj,otmp) register struct obj *obj, *otmp; {
X	/* otmp has been split off from obj */
Xregister struct bill_x *bp;
Xregister int tmp;
X	bp = onbill(obj);
X	if(!bp) {
X		impossible("splitbill: not on bill?");
X		return;
X	}
X	if(bp->bquan < otmp->quan) {
X		impossible("Negative quantity on bill??");
X	}
X	if(bp->bquan == otmp->quan) {
X		impossible("Zero quantity on bill??");
X	}
X	bp->bquan -= otmp->quan;
X
X	/* addtobill(otmp); */
X	if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0;
X	else {
X		tmp = bp->price;
X		bp = &bill[ESHK(shopkeeper)->billct];
X		bp->bo_id = otmp->o_id;
X		bp->bquan = otmp->quan;
X		bp->useup = 0;
X		bp->price = tmp;
X		ESHK(shopkeeper)->billct++;
X	}
X}
X
Xsubfrombill(obj) register struct obj *obj; {
Xlong ltmp;
Xregister int tmp;
Xregister struct obj *otmp;
Xregister struct bill_x *bp;
X	if(!inshop() || (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
X		(u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y))
X		return;
X	if((bp = onbill(obj)) != 0){
X		obj->unpaid = 0;
X		if(bp->bquan > obj->quan){
X			otmp = newobj(0);
X			*otmp = *obj;
X			bp->bo_id = otmp->o_id = flags.ident++;
X			otmp->quan = (bp->bquan -= obj->quan);
X			otmp->owt = 0;	/* superfluous */
X			otmp->onamelth = 0;
X			bp->useup = 1;
X			otmp->nobj = billobjs;
X			billobjs = otmp;
X			return;
X		}
X		ESHK(shopkeeper)->billct--;
X		*bp = bill[ESHK(shopkeeper)->billct];
X		return;
X	}
X	if(obj->unpaid){
X		pline("%s didn't notice.", Monnam(shopkeeper));
X		obj->unpaid = 0;
X		return;		/* %% */
X	}
X	/* he dropped something of his own - probably wants to sell it */
X	if(shopkeeper->msleep || shopkeeper->mfroz ||
X		inroom(shopkeeper->mx,shopkeeper->my) != ESHK(shopkeeper)->shoproom)
X		return;
X	if(ESHK(shopkeeper)->billct == BILLSZ
X	   || !saleable(rooms[ESHK(shopkeeper)->shoproom].rtype-SHOPBASE, obj)
X/*
X	  ((tmp = shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype-SHOPBASE].symb) && tmp != obj->olet)
X*/
X	   || index("_0", obj->olet)) {
X		pline("%s seems not interested.", Monnam(shopkeeper));
X#ifdef DGKMOD
X		obj->no_charge = 1;
X#endif
X		return;
X	}
X	ltmp = getprice(obj) * obj->quan;
X	if(ANGRY(shopkeeper)) {
X		ltmp /= 3;
X		NOTANGRY(shopkeeper) = 1;
X	} else	ltmp /= 2;
X	if(ESHK(shopkeeper)->robbed){
X		if((ESHK(shopkeeper)->robbed -= ltmp) < 0)
X			ESHK(shopkeeper)->robbed = 0;
Xpline("Thank you for your contribution to restock this recently plundered shop.");
X		return;
X	}
X	if(ltmp > shopkeeper->mgold)
X		ltmp = shopkeeper->mgold;
X	pay(-ltmp, shopkeeper);
X	if(!ltmp) {
X		pline("%s gladly accepts %s but cannot pay you at present.",
X			Monnam(shopkeeper), doname(obj));
X#ifdef DGKMOD
X			obj->no_charge = 1;
X#endif
X	} else
X	pline("You sold %s and got %ld gold piece%s.", doname(obj), ltmp,
X		plur(ltmp));
X}
X
Xdoinvbill(mode)
Xint mode;		/* 0: deliver count 1: paged */
X{
X	register struct bill_x *bp;
X	register struct obj *obj;
X	long totused, thisused;
X	char buf[BUFSZ];
X
X	if(mode == 0) {
X	    register int cnt = 0;
X
X	    if(shopkeeper)
X		for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++)
X		    if(bp->useup ||
X		      ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
X			cnt++;
X	    return(cnt);
X	}
X
X	if(!shopkeeper) {
X		impossible("doinvbill: no shopkeeper?");
X		return(0);
X	}
X
X	set_pager(0);
X	if(page_line("Unpaid articles already used up:") || page_line(""))
X	    goto quit;
X
X	totused = 0;
X	for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) {
X	    obj = bp_to_obj(bp);
X	    if(!obj) {
X		impossible("Bad shopkeeper administration.");
X		goto quit;
X	    }
X	    if(bp->useup || bp->bquan > obj->quan) {
X		register int cnt, oquan, uquan;
X
X		oquan = obj->quan;
X		uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
X		thisused = bp->price * uquan;
X		totused += thisused;
X		obj->quan = uquan;		/* cheat doname */
X		(void) sprintf(buf, "x -  %s", doname(obj));
X		obj->quan = oquan;		/* restore value */
X		for(cnt = 0; buf[cnt]; cnt++);
X		while(cnt < 50)
X			buf[cnt++] = ' ';
X		(void) sprintf(&buf[cnt], " %5ld zorkmids", thisused);
X		if(page_line(buf))
X			goto quit;
X	    }
X	}
X	(void) sprintf(buf, "Total:%50ld zorkmids", totused);
X	if(page_line("") || page_line(buf))
X		goto quit;
X	set_pager(1);
X	return(0);
Xquit:
X	set_pager(2);
X	return(0);
X}
X
Xstatic
Xgetprice(obj) register struct obj *obj; {
Xregister int tmp, ac;
X	switch(obj->olet){
X	case AMULET_SYM:
X		tmp = rn1(1500, 3500);
X		break;
X	case TOOL_SYM:
X	    switch(obj->otyp) {
X		case EXPENSIVE_CAMERA:	tmp = rn1(400, 200);
X					break;
X#ifdef MARKER
X		case MAGIC_MARKER:	tmp = rn1(100,50);
X					break;
X#endif
X#ifdef WALKIES
X		case LEASH:		tmp = rn1(40,20);
X					break;
X#endif
X#ifdef RPH
X		case BLINDFOLD:		tmp = rn1(40,20);
X					break;
X		case MIRROR:		tmp = rn1(80,40);
X					break;
X#endif
X		case STETHOSCOPE:	tmp = rn1(100,80);
X					break;
X		case CAN_OPENER:	tmp = rn1(50,30);
X					break;
X		default:		tmp = rn1(20,10);
X					break;
X	    }
X	    break;
X	case RING_SYM:
X		tmp = rn1(200,100);
X		break;
X	case WAND_SYM:
X		tmp = rn1(300,150);
X		break;
X	case SCROLL_SYM:
X#ifdef MAIL
X		if(obj->otyp == SCR_MAIL)
X			tmp = rn1(5,5);
X		else
X#endif
X			tmp = rn1(200,100);
X		break;
X	case POTION_SYM:
X		tmp = rn1(200,100);
X		break;
X#ifdef SPELLS
X	case SPBOOK_SYM:
X		tmp = rn1(500,500);
X		break;
X#endif
X	case FOOD_SYM:
X
X		tmp = (2000+objects[obj->otyp].nutrition)/realhunger();
X		tmp = rn1((tmp < 10) ? 10 : tmp,
X		          objects[obj->otyp].nutrition/20 + 5);
X		break;
X	case GEM_SYM:
X		tmp = rn1(120,60);
X		break;
X	case ARMOR_SYM:
X		ac = ARM_BONUS(obj);
X		if(ac <= -10)		/* probably impossible */
X			ac = -9;
X		tmp = ac*ac+10*rn1(10+ac,10);
X		break;
X	case WEAPON_SYM:
X		if(obj->otyp < BOOMERANG)
X			tmp = rn1(4,2);
X		else if(obj->otyp == BOOMERANG ||
X			obj->otyp == DAGGER ||
X			obj->otyp == CLUB ||
X			obj->otyp == SLING)
X			tmp = rn1(50,50);
X		else if(obj->otyp == KATANA)
X			tmp = rn1(700,800);
X		else if(obj->otyp == LONG_SWORD ||
X			obj->otyp == TWO_HANDED_SWORD ||
X			obj->otyp == BROAD_SWORD)
X			tmp = rn1(500,500);
X		else	tmp = rn1(150,100);
X		break;
X	case CHAIN_SYM:
X		pline("Strange ..., carrying a chain?");
X	case BALL_SYM:
X		tmp = 10;
X		break;
X	default:
X		tmp = 10000;
X	}
X	return(tmp);
X}
X
Xstatic
Xrealhunger(){	/* not completely foolproof */
Xregister tmp = u.uhunger;
Xregister struct obj *otmp = invent;
X	while(otmp){
X		if(otmp->olet == FOOD_SYM && !otmp->unpaid)
X			tmp += objects[otmp->otyp].nutrition;
X		otmp = otmp->nobj;
X	}
X	return((tmp <= 0) ? 1 : tmp);
X}
X
Xshkcatch(obj)
Xregister struct obj *obj;
X{
X	register struct monst *shkp = shopkeeper;
X
X	if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep &&
X	    u.dx && u.dy &&
X	    inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop &&
X	    shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y &&
X	    u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) {
X		pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj));
X		obj->nobj = shkp->minvent;
X		shkp->minvent = obj;
X		return(1);
X	}
X	return(0);
X}
X
X/*
X * shk_move: return 1: he moved  0: he didnt  -1: let m_move do it
X */
Xshk_move(shkp)
Xregister struct monst *shkp;
X{
X	register struct monst *mtmp;
X	register struct permonst *mdat = shkp->data;
X	register xchar gx,gy,omx,omy,nx,ny,nix,niy;
X	register schar appr,i;
X	register int udist;
X	int z;
X	schar shkroom,chi,chcnt,cnt;
X	boolean uondoor, satdoor, avoid, badinv;
X	coord poss[9];
X	long info[9];
X	struct obj *ib = 0;
X
X	omx = shkp->mx;
X	omy = shkp->my;
X
X	if((udist = dist(omx,omy)) < 3) {
X		if(ANGRY(shkp)) {
X			(void) hitu(shkp, d(mdat->damn, mdat->damd)+1);
X			return(0);
X		}
X		if(ESHK(shkp)->following) {
X			if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)){
X				pline("Hello %s! I was looking for %s.",
X					plname, ESHK(shkp)->customer);
X				ESHK(shkp)->following = 0;
X				return(0);
X			}
X			if(!ESHK(shkp)->robbed) {	/* impossible? */
X				ESHK(shkp)->following = 0;
X				return(0);
X			}
X			if(moves > followmsg+4) {
X				pline("Hello %s! Didn't you forget to pay?",
X					plname);
X				followmsg = moves;
X#ifdef HARD
X				if (!rn2(5)) {
X	    pline ("%s doesn't like customers who don't pay.", Monnam(shkp));
X				    NOTANGRY(shkp) = 0;
X				}
X#endif				    
X			}
X			if(udist < 2)
X				return(0);
X		}
X	}
X
X	shkroom = inroom(omx,omy);
X	appr = 1;
X	gx = ESHK(shkp)->shk.x;
X	gy = ESHK(shkp)->shk.y;
X	satdoor = (gx == omx && gy == omy);
X	if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){
X		gx = u.ux;
X		gy = u.uy;
X		if(shkroom < 0 || shkroom != inroom(u.ux,u.uy))
X		    if(udist > 4)
X			return(-1);	/* leave it to m_move */
X	} else if(ANGRY(shkp)) {
X		long saveBlind = Blinded;
X		long saveBlindf = Blindfolded;
X		Blinded = Blindfolded = 0;
X		if(shkp->mcansee && !Invis && cansee(omx,omy)) {
X			gx = u.ux;
X			gy = u.uy;
X		}
X		Blinded = saveBlind;
X		Blindfolded = saveBlindf;
X		avoid = FALSE;
X	} else {
X#define	GDIST(x,y)	((x-gx)*(x-gx)+(y-gy)*(y-gy))
X		if(Invis)
X		  avoid = FALSE;
X		else {
X		  uondoor = (u.ux == ESHK(shkp)->shd.x &&
X				u.uy == ESHK(shkp)->shd.y);
X		  if(uondoor) {
X		    if(ESHK(shkp)->billct)
X			pline("Hello %s! Will you please pay before leaving?",
X				plname);
X		    badinv = (carrying(PICK_AXE) || carrying(ICE_BOX));
X		    if(satdoor && badinv)
X			return(0);
X		    avoid = !badinv;
X		  } else {
X		    avoid = (u.uinshop && dist(gx,gy) > 8);
X		    badinv = FALSE;
X		  }
X
X		  if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
X			&& GDIST(omx,omy) < 3){
X			if(!badinv && !online(omx,omy))
X				return(0);
X			if(satdoor)
X				appr = gx = gy = 0;
X		  }
X		}
X	}
X	if(omx == gx && omy == gy)
X		return(0);
X	if(shkp->mconf) {
X		avoid = FALSE;
X		appr = 0;
X	}
X	nix = omx;
X	niy = omy;
X	cnt = mfndpos(shkp,poss,info,ALLOW_SSM);
X	if(avoid && uondoor) {		/* perhaps we cannot avoid him */
X		for(i=0; i<cnt; i++)
X			if(!(info[i] & NOTONL)) goto notonl_ok;
X		avoid = FALSE;
X	notonl_ok:
X		;
X	}
X	chi = -1;
X	chcnt = 0;
X	for(i=0; i<cnt; i++){
X		nx = poss[i].x;
X		ny = poss[i].y;
X		if(levl[nx][ny].typ == ROOM
X		|| shkroom != ESHK(shkp)->shoproom
X		|| ESHK(shkp)->following) {
X#ifdef STUPID
X		    /* cater for stupid compilers */
X		    register int zz;
X#endif
X		    if(uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) {
X			nix = nx; niy = ny; chi = i; break;
X		    }
X		    if(avoid && (info[i] & NOTONL))
X			continue;
X		    if((!appr && !rn2(++chcnt)) ||
X#ifdef STUPID
X			(appr && (zz = GDIST(nix,niy)) && zz > GDIST(nx,ny))
X#else
X			(appr && GDIST(nx,ny) < GDIST(nix,niy))
X#endif
X			) {
X			    nix = nx;
X			    niy = ny;
X			    chi = i;
X		    }
X		}
X	}
X	if(nix != omx || niy != omy){
X		if(info[chi] & ALLOW_M){
X			mtmp = m_at(nix,niy);
X			if(hitmm(shkp,mtmp) == 1 && rn2(3) &&
X			   hitmm(mtmp,shkp) == 2) return(2);
X			return(0);
X		} else if(info[chi] & ALLOW_U){
X			(void) hitu(shkp, d(mdat->damn, mdat->damd)+1);
X			return(0);
X		}
X		shkp->mx = nix;
X		shkp->my = niy;
X		pmon(shkp);
X		if(ib) {
X			freeobj(ib);
X			mpickobj(shkp, ib);
X		}
X		return(1);
X	}
X	return(0);
X}
X#endif /* QUEST /**/
X
Xonline(x,y)		/*	New version to speed things up.
X			 *	Compiler dependant, may not always work.
X			 */
X	register xchar x, y;
X{
X	return((x-=u.ux) == 0 || (y-=u.uy) == 0 || x == y || (x+=y) == 0);
X}
X
X/*			Original version, just in case...
X *online(x,y) {
X *	return(x==u.ux || y==u.uy || (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy));
X *}
X */
X
X/* Does this monster follow me downstairs? */
Xfollower(mtmp)
Xregister struct monst *mtmp;
X{
X	return( mtmp->mtame || index("1TVWZi&, ", mtmp->data->mlet) ||
X		(mtmp->isshk && ESHK(mtmp)->following) );
X}
X
X/* He is digging in the shop. */
Xshopdig(fall)
Xregister int fall;
X{
X    if(!fall) {
X	if(u.utraptype == TT_PIT)
X	    pline("\"Be careful, sir, or you might fall through the floor.\"");
X	else
X	    pline("\"Please, do not damage the floor here.\"");
X    } else if(dist(shopkeeper->mx, shopkeeper->my) < 3) {
X	register struct obj *obj, *obj2;
X
X	pline("%s grabs your backpack!", shkname(shopkeeper));
X	for(obj = invent; obj; obj = obj2) {
X		obj2 = obj->nobj;
X		if(obj->owornmask) continue;
X		freeinv(obj);
X		obj->nobj = shopkeeper->minvent;
X		shopkeeper->minvent = obj;
X		if(obj->unpaid)
X			subfrombill(obj);
X	}
X    }
X}
END_OF_shk.c
if test 27302 -ne `wc -c <shk.c`; then
    echo shar: \"shk.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f trap.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"trap.h\"
else
echo shar: Extracting \"trap.h\" \(1012 characters\)
sed "s/^X//" >trap.h <<'END_OF_trap.h'
X/*	SCCS Id: @(#)trap.h	1.4	87/08/08
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* trap.h - version 1.0.2 */
X
Xstruct trap {
X	struct trap *ntrap;
X	xchar tx,ty;
X	Bitfield(ttyp,5);
X	Bitfield(tseen,1);
X	Bitfield(once,1);
X};
X
Xextern struct trap *ftrap;
Xstruct trap *t_at();
X#define newtrap()	(struct trap *) alloc(sizeof(struct trap))
X
X/* Standard Hack traps. */
X#define NO_TRAP         0
X#define BEAR_TRAP       1
X#define ARROW_TRAP      2
X#define DART_TRAP       3
X#define TRAPDOOR        4
X#define TELEP_TRAP      5
X#define PIT             6
X#define SLP_GAS_TRAP    7
X#define PIERC           8
X#define MIMIC           9
X
X/* Defines below this line are automatically added by makedefs (-t option) */
X/* if you add any additional code below the next line, it will disappear.  */
X/* DO NOT REMOVE THIS LINE */
X
X#define	MGTRP		10
X#define	SQBRD		11
X#define	WEB		12
X#define	SPIKED_PIT	13
X#define	LEVEL_TELEP	14
X#define	ANTI_MAGIC	15
X#define	RUST_TRAP	16
X#define	POLY_TRAP	17
X
X#define	TRAPNUM	18
END_OF_trap.h
if test 1012 -ne `wc -c <trap.h`; then
    echo shar: \"trap.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 4 \(of 20\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 20 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