[net.sources.games] Hack 1.0.2 - part 3 of 10

aeb@mcvax.UUCP (Andries Brouwer) (04/04/85)

# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# hack.Decl.c hack.apply.c hack.bones.c hack.cmd.c hack.do.c
# hack.do_name.c hack.do_wear.c hack.dog.c

echo x - hack.Decl.c
cat > "hack.Decl.c" << '//E*O*F hack.Decl.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.Decl.c - version 1.0.2 */

#include	"hack.h"
char nul[40];			/* contains zeros */
char plname[PL_NSIZ];		/* player name */
char lock[32] = "1lock";	/* long enough for login name */

boolean in_mklev;
#ifdef WIZARD
boolean wizard;			/* TRUE when called as  hack -w */
#endif WIZARD

struct rm levl[COLNO][ROWNO];	/* level map */
#ifndef QUEST
#include "def.mkroom.h"
struct mkroom rooms[MAXNROFROOMS+1];
coord doors[DOORMAX];
#endif QUEST
struct monst *fmon = 0;
struct trap *ftrap = 0;
struct gold *fgold = 0;
struct obj *fobj = 0, *fcobj = 0, *invent = 0, *uwep = 0, *uarm = 0,
	*uarm2 = 0, *uarmh = 0, *uarms = 0, *uarmg = 0, *uright = 0,
	*uleft = 0, *uchain = 0, *uball = 0;
struct flag flags;
struct you u;
struct monst youmonst;	/* dummy; used as return value for boomhit */

xchar dlevel = 1;
xchar xupstair, yupstair, xdnstair, ydnstair;
char *save_cm = 0, *killer, *nomovemsg;

long moves = 1;
long wailmsg = 0;

int multi = 0;
char genocided[60];
char fut_geno[60];

xchar curx,cury;
xchar seelx, seehx, seely, seehy;	/* corners of lit room */

coord bhitpos;

char quitchars[] = " \r\n\033";
//E*O*F hack.Decl.c//

echo x - hack.apply.c
cat > "hack.apply.c" << '//E*O*F hack.apply.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.apply.c - version 1.0.2 */

#include	"hack.h"
#include	"def.edog.h"
#include	"def.mkroom.h"
extern struct monst *bchit();
extern struct obj *addinv();
extern struct trap *maketrap();
extern int (*occupation)();
extern char *occtxt;
extern char quitchars[];
extern char pl_character[];

doapply() {
	register struct obj *obj;
	register int res = 1;

	obj = getobj("(", "use or apply");
	if(!obj) return(0);

	switch(obj->otyp){
	case EXPENSIVE_CAMERA:
		use_camera(obj); break;
	case ICE_BOX:
		use_ice_box(obj); break;
	case PICK_AXE:
		res = use_pick_axe(obj); break;
	case MAGIC_WHISTLE:
		if(pl_character[0] == 'W' || u.ulevel > 9) {
			use_magic_whistle(obj);
			break;
		}
		/* fall into next case */
	case WHISTLE:
		use_whistle(obj); break;
	default:
		pline("Sorry, I don't know how to use that.");
		nomul(0);
		return(0);
	}
	nomul(0);
	return(res);
}

/* ARGSUSED */
static
use_camera(obj) /* register */ struct obj *obj; {
register struct monst *mtmp;
	if(!getdir(1)){		/* ask: in what direction? */
		flags.move = multi = 0;
		return;
	}
	if(u.uswallow) {
		pline("You take a picture of %s's stomach.", monnam(u.ustuck));
		return;
	}
	if(u.dz) {
		pline("You take a picture of the %s.",
			(u.dz > 0) ? "floor" : "ceiling");
		return;
	}
	if(mtmp = bchit(u.dx, u.dy, COLNO, '!')) {
		if(mtmp->msleep){
			mtmp->msleep = 0;
			pline("The flash awakens %s.", monnam(mtmp)); /* a3 */
		} else
		if(mtmp->data->mlet != 'y')
		if(mtmp->mcansee || mtmp->mblinded){
			register int tmp = dist(mtmp->mx,mtmp->my);
			register int tmp2;
			/* if(cansee(mtmp->mx,mtmp->my)) */
			  pline("%s is blinded by the flash!",Monnam(mtmp));
			setmangry(mtmp);
			if(tmp < 9 && !mtmp->isshk && rn2(4)) {
				mtmp->mflee = 1;
				if(rn2(4)) mtmp->mfleetim = rnd(100);
			}
			if(tmp < 3) mtmp->mcansee  = mtmp->mblinded = 0;
			else {
				tmp2 = mtmp->mblinded;
				tmp2 += rnd(1 + 50/tmp);
				if(tmp2 > 127) tmp2 = 127;
				mtmp->mblinded = tmp2;
				mtmp->mcansee = 0;
			}
		}
	}
}

static
struct obj *current_ice_box;	/* a local variable of use_ice_box, to be
				used by its local procedures in/ck_ice_box */
static
in_ice_box(obj) register struct obj *obj; {
	if(obj == current_ice_box ||
		(Punished && (obj == uball || obj == uchain))){
		pline("You must be kidding.");
		return(0);
	}
	if(obj->owornmask & (W_ARMOR | W_RING)) {
		pline("You cannot refrigerate something you are wearing.");
		return(0);
	}
	if(obj->owt + current_ice_box->owt > 70) {
		pline("It won't fit.");
		return(1);	/* be careful! */
	}
	if(obj == uwep) {
		if(uwep->cursed) {
			pline("Your weapon is welded to your hand!");
			return(0);
		}
		setuwep((struct obj *) 0);
	}
	current_ice_box->owt += obj->owt;
	freeinv(obj);
	obj->o_cnt_id = current_ice_box->o_id;
	obj->nobj = fcobj;
	fcobj = obj;
	obj->age = moves - obj->age;	/* actual age */
	return(1);
}

static
ck_ice_box(obj) register struct obj *obj; {
	return(obj->o_cnt_id == current_ice_box->o_id);
}

static
out_ice_box(obj) register struct obj *obj; {
register struct obj *otmp;
	if(obj == fcobj) fcobj = fcobj->nobj;
	else {
		for(otmp = fcobj; otmp->nobj != obj; otmp = otmp->nobj)
			if(!otmp->nobj) panic("out_ice_box");
		otmp->nobj = obj->nobj;
	}
	current_ice_box->owt -= obj->owt;
	obj->age = moves - obj->age;	/* simulated point of time */
	(void) addinv(obj);
}

static
use_ice_box(obj) register struct obj *obj; {
register int cnt = 0;
register struct obj *otmp;
	current_ice_box = obj;	/* for use by in/out_ice_box */
	for(otmp = fcobj; otmp; otmp = otmp->nobj)
		if(otmp->o_cnt_id == obj->o_id)
			cnt++;
	if(!cnt) pline("Your ice-box is empty.");
	else {
	    pline("Do you want to take something out of the ice-box? [yn] ");
	    if(readchar() == 'y')
		if(askchain(fcobj, (char *) 0, 0, out_ice_box, ck_ice_box, 0))
		    return;
		pline("That was all. Do you wish to put something in? [yn] ");
		if(readchar() != 'y') return;
	}
	/* call getobj: 0: allow cnt; #: allow all types; %: expect food */
	otmp = getobj("0#%", "put in");
	if(!otmp || !in_ice_box(otmp))
		flags.move = multi = 0;
}

static
struct monst *
bchit(ddx,ddy,range,sym) register int ddx,ddy,range; char sym; {
	register struct monst *mtmp = (struct monst *) 0;
	register int bchx = u.ux, bchy = u.uy;

	if(sym) Tmp_at(-1, sym);	/* open call */
	while(range--) {
		bchx += ddx;
		bchy += ddy;
		if(mtmp = m_at(bchx,bchy))
			break;
		if(!ZAP_POS(levl[bchx][bchy].typ)) {
			bchx -= ddx;
			bchy -= ddy;
			break;
		}
		if(sym) Tmp_at(bchx, bchy);
	}
	if(sym) Tmp_at(-1, -1);
	return(mtmp);
}

/* ARGSUSED */
static
use_whistle(obj) struct obj *obj; {
register struct monst *mtmp = fmon;
	pline("You produce a high whistling sound.");
	while(mtmp) {
		if(dist(mtmp->mx,mtmp->my) < u.ulevel*20) {
			if(mtmp->msleep)
				mtmp->msleep = 0;
			if(mtmp->mtame)
				EDOG(mtmp)->whistletime = moves;
		}
		mtmp = mtmp->nmon;
	}
}

/* ARGSUSED */
static
use_magic_whistle(obj) struct obj *obj; {
register struct monst *mtmp = fmon;
	pline("You produce a strange whistling sound.");
	while(mtmp) {
		if(mtmp->mtame) mnexto(mtmp);
		mtmp = mtmp->nmon;
	}
}

static int dig_effort;	/* effort expended on current pos */
static uchar dig_level;
static coord dig_pos;
static boolean dig_down;

static
dig() {
	register struct rm *lev;
	register dpx = dig_pos.x, dpy = dig_pos.y;

	/* perhaps a nymph stole his pick-axe while he was busy digging */
	/* or perhaps he teleported away */
	if(u.uswallow || !uwep || uwep->otyp != PICK_AXE ||
	    dig_level != dlevel ||
	    ((dig_down && (dpx != u.ux || dpy != u.uy)) ||
	     (!dig_down && dist(dpx,dpy) > 2)))
		return(0);

	dig_effort += 10 + abon() + uwep->spe + rn2(5);
	if(dig_down) {
		if(!xdnstair) {
			pline("The floor here seems too hard to dig in.");
			return(0);
		}
		if(dig_effort > 250) {
			dighole();
			return(0);	/* done with digging */
		}
		if(dig_effort > 50) {
			register struct trap *ttmp = t_at(dpx,dpy);

			if(!ttmp) {
				ttmp = maketrap(dpx,dpy,PIT);
				ttmp->tseen = 1;
				pline("You have dug a pit.");
				u.utrap = rn1(4,2);
				u.utraptype = TT_PIT;
				return(0);
			}
		}
	} else
	if(dig_effort > 100) {
		register char *digtxt;
		register struct obj *obj;

		lev = &levl[dpx][dpy];
		if(obj = sobj_at(ENORMOUS_ROCK, dpx, dpy)) {
			fracture_rock(obj);
			digtxt = "The rock falls apart.";
		} else if(!lev->typ || lev->typ == SCORR) {
			lev->typ = CORR;
			digtxt = "You succeeded in cutting away some rock.";
		} else if(lev->typ == HWALL || lev->typ == VWALL
					    || lev->typ == SDOOR) {
			lev->typ = xdnstair ? DOOR : ROOM;
			digtxt = "You just made an opening in the wall.";
		} else
		  digtxt = "Now what exactly was it that you were digging in?";
		mnewsym(dpx, dpy);
		prl(dpx, dpy);
		pline(digtxt);		/* after mnewsym & prl */
		return(0);
	} else {
		if(IS_WALL(levl[dpx][dpy].typ)) {
			register int rno = inroom(dpx,dpy);

			if(rno >= 0 && rooms[rno].rtype >= 8) {
			  pline("This wall seems too hard to dig into.");
			  return(0);
			}
		}
		pline("You hit the rock with all your might.");
	}
	return(1);
}

dighole()
{
	register struct trap *ttmp = t_at(u.ux, u.uy);

	if(!xdnstair) {
		pline("The floor here seems too hard to dig in.");
	} else {
		if(ttmp)
			ttmp->ttyp = TRAPDOOR;
		else
			ttmp = maketrap(u.ux, u.uy, TRAPDOOR);
		ttmp->tseen = 1;
		pline("You've made a hole in the floor.");
		if(!u.ustuck) {
			pline("You fall through ...");
			if(u.utraptype == TT_PIT) {
				u.utrap = 0;
				u.utraptype = 0;
			}
			goto_level(dlevel+1, FALSE);
		}
	}
}

static
use_pick_axe(obj)
struct obj *obj;
{
	char dirsyms[12];
	extern char sdir[];
	register char *dsp = dirsyms, *sdp = sdir;
	register struct monst *mtmp;
	register struct rm *lev;
	register int rx, ry, res = 0;

	if(obj != uwep) {
		pline("You now wield %s.", doname(obj));
		setuwep(obj);
		res = 1;
	}
	while(*sdp) {
		(void) movecmd(*sdp);	/* sets u.dx and u.dy and u.dz */
		rx = u.ux + u.dx;
		ry = u.uy + u.dy;
		if(u.dz > 0 || (u.dz == 0 && isok(rx, ry) &&
		    (IS_ROCK(levl[rx][ry].typ)
		    || sobj_at(ENORMOUS_ROCK, rx, ry))))
			*dsp++ = *sdp;
		sdp++;
	}
	*dsp = 0;
	pline("In what direction do you want to dig? [%s] ", dirsyms);
	if(!getdir(0))		/* no txt */
		return(res);
	if(u.uswallow && attack(u.ustuck)) /* return(1) */;
	else
	if(u.dz < 0)
		pline("You cannot reach the ceiling.");
	else
	if(u.dz == 0) {
		if(Confusion)
			confdir();
		rx = u.ux + u.dx;
		ry = u.uy + u.dy;
		if((mtmp = m_at(rx, ry)) && attack(mtmp))
			return(1);
		if(!isok(rx, ry)) {
			pline("Clash!");
			return(1);
		}
		lev = &levl[rx][ry];
		if(lev->typ == DOOR)
			pline("Your %s against the door.",
				aobjnam(obj, "clang"));
		else if(!IS_ROCK(lev->typ)
		     && !sobj_at(ENORMOUS_ROCK, rx, ry)) {
			/* ACCESSIBLE or POOL */
			pline("You swing your %s through thin air.",
				aobjnam(obj, (char *) 0));
		} else {
			if(dig_pos.x != rx || dig_pos.y != ry
			    || dig_level != dlevel || dig_down) {
				dig_down = FALSE;
				dig_pos.x = rx;
				dig_pos.y = ry;
				dig_level = dlevel;
				dig_effort = 0;
				pline("You start digging.");
			} else
				pline("You continue digging.");
			occupation = dig;
			occtxt = "digging";
		}
	} else if(Levitation) {
		pline("You cannot reach the floor.");
	} else {
		if(dig_pos.x != u.ux || dig_pos.y != u.uy
		    || dig_level != dlevel || !dig_down) {
			dig_down = TRUE;
			dig_pos.x = u.ux;
			dig_pos.y = u.uy;
			dig_level = dlevel;
			dig_effort = 0;
			pline("You start digging in the floor.");
		} else
			pline("You continue digging in the floor.");
		occupation = dig;
		occtxt = "digging";
	}
	return(1);
}
//E*O*F hack.apply.c//

echo x - hack.bones.c
cat > "hack.bones.c" << '//E*O*F hack.bones.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.bones.c - version 1.0.2 */

#include "hack.h"
extern char plname[PL_NSIZ];
extern long somegold();
extern struct monst *makemon();
extern struct permonst pm_ghost;

char bones[] = "bones_xx";

/* save bones and possessions of a deceased adventurer */
savebones(){
register fd;
register struct obj *otmp;
register struct trap *ttmp;
register struct monst *mtmp;
	if(!rn2(1 + dlevel/2)) return;	/* not so many ghosts on low levels */
	bones[6] = '0' + (dlevel/10);
	bones[7] = '0' + (dlevel%10);
	if((fd = open(bones,0)) >= 0){
		(void) close(fd);
		return;
	}
	/* drop everything; the corpse's possessions are usually cursed */
	otmp = invent;
	while(otmp){
		otmp->ox = u.ux;
		otmp->oy = u.uy;
		otmp->known = 0;
		otmp->age = 0;		/* very long ago */
		otmp->owornmask = 0;
		if(rn2(5)) otmp->cursed = 1;
		if(otmp->olet == AMULET_SYM)
			otmp->spe = -1; /* no longer the actual amulet */
		if(!otmp->nobj){
			otmp->nobj = fobj;
			fobj = invent;
			invent = 0;	/* superfluous */
			break;
		}
		otmp = otmp->nobj;
	}
	if(!(mtmp = makemon(PM_GHOST, u.ux, u.uy))) return;
	mtmp->mx = u.ux;
	mtmp->my = u.uy;
	mtmp->msleep = 1;
	(void) strcpy((char *) mtmp->mextra, plname);
	mkgold(somegold() + d(dlevel,30), u.ux, u.uy);
	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
		if(mtmp->mtame) {
			mtmp->mtame = 0;
			mtmp->mpeaceful = 0;
		}
		mtmp->mlstmv = 0;
		if(mtmp->mdispl) unpmon(mtmp);
	}
	for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
		ttmp->tseen = 0;
	for(otmp = fobj; otmp; otmp = otmp->nobj)
		otmp->onamelth = 0;
	if((fd = creat(bones, FMASK)) < 0) return;
	savelev(fd,dlevel);
	(void) close(fd);
}

getbones(){
register fd,x,y,ok;
	if(rn2(3)) return(0);	/* only once in three times do we find bones */
	bones[6] = '0' + dlevel/10;
	bones[7] = '0' + dlevel%10;
	if((fd = open(bones, 0)) < 0) return(0);
	if((ok = uptodate(fd)) != 0){
		getlev(fd, 0, dlevel);
		for(x = 0; x < COLNO; x++) for(y = 0; y < ROWNO; y++)
			levl[x][y].seen = levl[x][y].new = 0;
	}
	(void) close(fd);
	if(unlink(bones) < 0){
		pline("Cannot unlink %s", bones);
		return(0);
	}
	return(ok);
}
//E*O*F hack.bones.c//

echo x - hack.cmd.c
cat > "hack.cmd.c" << '//E*O*F hack.cmd.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.cmd.c - version 1.0.2 */

#include	"hack.h"
#include	"def.func_tab.h"

int doredraw(),doredotopl(),dodrop(),dodrink(),doread(),dosearch(),dopickup(),
doversion(),doweararm(),dowearring(),doremarm(),doremring(),dopay(),doapply(),
dosave(),dowield(),ddoinv(),dozap(),ddocall(),dowhatis(),doengrave(),dotele(),
dohelp(),doeat(),doddrop(),do_mname(),doidtrap(),doprwep(),doprarm(),
doprring(),doprgold(),dodiscovered(),dotypeinv(),dolook(),doset(),
doup(), dodown(), done1(), donull(), dothrow(), doextcmd(), dodip();
#ifdef SHELL
int dosh();
#endif SHELL
#ifdef SUSPEND
int dosuspend();
#endif SUSPEND

struct func_tab cmdlist[]={
	'\020', doredotopl,
	'\022', doredraw,
	'\024', dotele,
#ifdef SUSPEND
	'\032', dosuspend,
#endif SUSPEND
	'a', doapply,
/*	'A' : UNUSED */
/*	'b', 'B' : go sw */
	'c', ddocall,
	'C', do_mname,
	'd', dodrop,
	'D', doddrop,
	'e', doeat,
	'E', doengrave,
/*	'f', 'F' : multiple go (might become 'fight') */
/*	'g', 'G' : UNUSED */
/*	'h', 'H' : go west */
	'i', dotypeinv,		/* Robert Viduya */
	'I', ddoinv,
/*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
/*	'o', doopen,	*/
	'O', doset,
	'p', dopay,
	'P', dowearring,
	'q', dodrink,
	'Q', done1,
	'r', doread,
	'R', doremring,
	's', dosearch,
	'S', dosave,
	't', dothrow,
	'T', doremarm,
/*	'u', 'U' : go ne */
	'v', doversion,
/*	'V' : UNUSED */
	'w', dowield,
	'W', doweararm,
/*	'x', 'X' : UNUSED */
/*	'y', 'Y' : go nw */
	'z', dozap,
/*	'Z' : UNUSED */
	'<', doup,
	'>', dodown,
	'/', dowhatis,
	'?', dohelp,
#ifdef SHELL
	'!', dosh,
#endif SHELL
	'.', donull,
	' ', donull,
	',', dopickup,
	':', dolook,
	'^', doidtrap,
	'\\', dodiscovered,		/* Robert Viduya */
	 WEAPON_SYM,  doprwep,
	 ARMOR_SYM,  doprarm,
	 RING_SYM,  doprring,
	'$', doprgold,
	'#', doextcmd,
	0,0,0
};

struct ext_func_tab extcmdlist[] = {
	"dip", dodip,
	(char *) 0, donull
};

extern char *parse(), lowc(), unctrl(), quitchars[];

rhack(cmd)
register char *cmd;
{
	register struct func_tab *tlist = cmdlist;
	boolean firsttime = FALSE;
	register res;

	if(!cmd) {
		firsttime = TRUE;
		flags.nopick = 0;
		cmd = parse();
	}
	if(!*cmd || *cmd == 0377 || (flags.no_rest_on_space && *cmd == ' ')){
		bell();
		flags.move = 0;
		return;		/* probably we just had an interrupt */
	}
	if(movecmd(*cmd)) {
	walk:
		if(multi) flags.mv = 1;
		domove();
		return;
	}
	if(movecmd(lowc(*cmd))) {
		flags.run = 1;
	rush:
		if(firsttime){
			if(!multi) multi = COLNO;
			u.last_str_turn = 0;
		}
		flags.mv = 1;
#ifdef QUEST
		if(flags.run >= 4) finddir();
		if(firsttime){
			u.ux0 = u.ux + u.dx;
			u.uy0 = u.uy + u.dy;
		}
#endif QUEST
		domove();
		return;
	}
	if((*cmd == 'f' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
		flags.run = 2;
		goto rush;
	}
	if(*cmd == 'F' && movecmd(lowc(cmd[1]))) {
		flags.run = 3;
		goto rush;
	}
	if(*cmd == 'm' && movecmd(cmd[1])) {
		flags.run = 0;
		flags.nopick = 1;
		goto walk;
	}
	if(*cmd == 'M' && movecmd(lowc(cmd[1]))) {
		flags.run = 1;
		flags.nopick = 1;
		goto rush;
	}
#ifdef QUEST
	if(*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) {
		flags.run = 4;
		if(*cmd == 'F') flags.run += 2;
		if(cmd[2] == '-') flags.run += 1;
		goto rush;
	}
#endif QUEST
	while(tlist->f_char) {
		if(*cmd == tlist->f_char){
			res = (*(tlist->f_funct))(0);
			if(!res) {
				flags.move = 0;
				multi = 0;
			}
			return;
		}
		tlist++;
	}
	{ char expcmd[10];
	  register char *cp = expcmd;
	  while(*cmd && cp-expcmd < sizeof(expcmd)-2) {
		if(*cmd >= 040 && *cmd < 0177)
			*cp++ = *cmd++;
		else {
			*cp++ = '^';
			*cp++ = *cmd++ ^ 0100;
		}
	  }
	  *cp++ = 0;
	  pline("Unknown command '%s'", expcmd);
	}
	multi = flags.move = 0;
}

doextcmd()	/* here after # - now read a full-word command */
{
	char buf[BUFSZ];
	register struct ext_func_tab *efp = extcmdlist;

	pline("# ");
	getlin(buf);
	clrlin();
	while(efp->ef_txt) {
		if(!strcmp(efp->ef_txt, buf))
			return((*(efp->ef_funct))());
		efp++;
	}
	pline("%s: unknown command.", buf);
	return(0);
}

char
lowc(sym)
char sym;
{
    return( (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym );
}

char
unctrl(sym)
char sym;
{
    return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym );
}

/* 'rogue'-like direction commands */
char sdir[] = "hykulnjb><";
schar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 };
schar ydir[10] = {  0,-1,-1,-1, 0, 1, 1, 1, 0, 0 };
schar zdir[10] = {  0, 0, 0, 0, 0, 0, 0, 0, 1,-1 };

movecmd(sym)	/* also sets u.dz, but returns false for <> */
char sym;
{
	register char *dp;

	u.dz = 0;
	if(!(dp = index(sdir, sym))) return(0);
	u.dx = xdir[dp-sdir];
	u.dy = ydir[dp-sdir];
	u.dz = zdir[dp-sdir];
	return(!u.dz);
}

getdir(s)
boolean s;
{
	char dirsym;

	if(s) pline("In what direction?");
	dirsym = readchar();
	if(!movecmd(dirsym) && !u.dz) {
		if(!index(quitchars, dirsym))
			pline("What a strange direction!");
		return(0);
	}
	if(Confusion && !u.dz)
		confdir();
	return(1);
}

confdir()
{
	register x = rn2(8);
	u.dx = xdir[x];
	u.dy = ydir[x];
}

#ifdef QUEST
finddir(){
register int i, ui = u.di;
	for(i = 0; i <= 8; i++){
		if(flags.run & 1) ui++; else ui += 7;
		ui %= 8;
		if(i == 8){
			pline("Not near a wall.");
			flags.move = multi = 0;
			return(0);
		}
		if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
			break;
	}
	for(i = 0; i <= 8; i++){
		if(flags.run & 1) ui += 7; else ui++;
		ui %= 8;
		if(i == 8){
			pline("Not near a room.");
			flags.move = multi = 0;
			return(0);
		}
		if(isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
			break;
	}
	u.di = ui;
	u.dx = xdir[ui];
	u.dy = ydir[ui];
}

isroom(x,y)  register x,y; {		/* what about POOL? */
	return(isok(x,y) && (levl[x][y].typ == ROOM ||
				(levl[x][y].typ >= LDOOR && flags.run >= 6)));
}
#endif QUEST

isok(x,y) register x,y; {
	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
	return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1);
}
//E*O*F hack.cmd.c//

echo x - hack.do.c
cat > "hack.do.c" << '//E*O*F hack.do.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.do.c - version 1.0.2 */

/* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */

#include "hack.h"

extern struct obj *splitobj(), *addinv();
extern boolean hmon();
extern boolean level_exists[];
extern struct monst youmonst;
extern char *Doname();

dodrop() {
	return(drop(getobj("0$#", "drop")));
}

static
drop(obj) register struct obj *obj; {
	if(!obj) return(0);
	if(obj->olet == '$') {		/* pseudo object */
		register long amount = OGOLD(obj);

		if(amount == 0)
			pline("You didn't drop any gold pieces.");
		else {
			mkgold(amount, u.ux, u.uy);
			pline("You dropped %ld gold piece%s.",
				amount, plur(amount));
			if(Invis) newsym(u.ux, u.uy);
		}
		free((char *) obj);
		return(1);
	}
	if(obj->owornmask & (W_ARMOR | W_RING)){
		pline("You cannot drop something you are wearing.");
		return(0);
	}
	if(obj == uwep) {
		if(uwep->cursed) {
			pline("Your weapon is welded to your hand!");
			return(0);
		}
		setuwep((struct obj *) 0);
	}
	pline("You dropped %s.", doname(obj));
	dropx(obj);
	return(1);
}

/* Called in several places - should not produce texts */
dropx(obj)
register struct obj *obj;
{
	freeinv(obj);
	dropy(obj);
}

dropy(obj)
register struct obj *obj;
{
	if(obj->otyp == CRYSKNIFE)
		obj->otyp = WORM_TOOTH;
	obj->ox = u.ux;
	obj->oy = u.uy;
	obj->nobj = fobj;
	fobj = obj;
	if(Invis) newsym(u.ux,u.uy);
	subfrombill(obj);
	stackobj(obj);
}

/* drop several things */
doddrop() {
	return(ggetobj("drop", drop, 0));
}

dodown()
{
	if(u.ux != xdnstair || u.uy != ydnstair) {
		pline("You can't go down here.");
		return(0);
	}
	if(u.ustuck) {
		pline("You are being held, and cannot go down.");
		return(1);
	}
	if(Levitation) {
		pline("You're floating high above the stairs.");
		return(0);
	}

	goto_level(dlevel+1, TRUE);
	return(1);
}

doup()
{
	if(u.ux != xupstair || u.uy != yupstair) {
		pline("You can't go up here.");
		return(0);
	}
	if(u.ustuck) {
		pline("You are being held, and cannot go up.");
		return(1);
	}
	if(inv_weight() + 5 > 0) {
		pline("Your load is too heavy to climb the stairs.");
		return(1);
	}

	goto_level(dlevel-1, TRUE);
	return(1);
}

goto_level(newlevel, at_stairs)
register int newlevel;
register boolean at_stairs;
{
	register fd;
	register boolean up = (newlevel < dlevel);

	if(newlevel <= 0) done("escaped");    /* in fact < 0 is impossible */
	if(newlevel == dlevel) return;	      /* this cannot happen either */

	glo(dlevel);
	fd = creat(lock, FMASK);
	if(fd < 0) {
		/*
		 * This is not quite impossible: e.g., we may have
		 * exceeded our quota. If that is the case then we
		 * cannot leave this level, and cannot save either.
		 * Another possibility is that the directory was not
		 * writable.
		 */
		pline("A mysterious force prevents you from going %s.",
			up ? "up" : "down");
		return;
	}

	if(Punished) unplacebc();
	u.utrap = 0;				/* needed in level_tele */
	u.ustuck = 0;				/* idem */
	keepdogs();
	seeoff(1);
	if(u.uswallow)				/* idem */
		u.uswldtim = u.uswallow = 0;
	flags.nscrinh = 1;
	u.ux = FAR;				/* hack */
	(void) inshop();			/* probably was a trapdoor */

	savelev(fd,dlevel);
	(void) close(fd);

	dlevel = newlevel;
	if(maxdlevel < dlevel)
		maxdlevel = dlevel;
	glo(dlevel);

	if(!level_exists[dlevel])
		mklev();
	else {
		extern int hackpid;

		if((fd = open(lock,0)) < 0) {
			pline("Cannot open %s", lock);
			pline("Probably someone removed it.");
			more();
			done("tricked");
		}
		getlev(fd, hackpid, dlevel);
		(void) close(fd);
	}

	if(at_stairs) {
	    if(up) {
		u.ux = xdnstair;
		u.uy = ydnstair;
		if(!u.ux) {		/* entering a maze from below? */
		    u.ux = xupstair;	/* this will confuse the player! */
		    u.uy = yupstair;
		}
		if(Punished){
			pline("With great effort you climb the stairs");
			placebc(1);
		}
	    } else {
		u.ux = xupstair;
		u.uy = yupstair;
		if(inv_weight() + 5 > 0 || Punished){
			pline("You fall down the stairs.");
			losehp(rnd(3), "fall");
			if(Punished) {
			    if(uwep != uball && rn2(3)){
				pline("... and are hit by the iron ball");
				losehp(rnd(20), "iron ball");
			    }
			    placebc(1);
			}
			selftouch("Falling, you");
		}
	    }
	    { register struct monst *mtmp = m_at(u.ux, u.uy);
	      if(mtmp)
		mnexto(mtmp);
	    }
	} else {	/* trapdoor or level_tele */
	    do {
		u.ux = rnd(COLNO-1);
		u.uy = rn2(ROWNO);
	    } while(levl[u.ux][u.uy].typ != ROOM ||
			m_at(u.ux,u.uy));
	    if(Punished){
		if(uwep != uball && !up /* %% */ && rn2(5)){
			pline("The iron ball falls on your head.");
			losehp(rnd(25), "iron ball");
		}
		placebc(1);
	    }
	    selftouch("Falling, you");
	}
	(void) inshop();
	initrack();

	losedogs();
	flags.nscrinh = 0;
	setsee();
	seeobjs();	/* make old cadavers disappear - riv05!a3 */
	docrt();
	{ register struct monst *mtmp;
	  if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp);	/* riv05!a3 */
	}
	pickup(1);
	read_engr_at(u.ux,u.uy);
}

donull() {
	return(1);	/* Do nothing, but let other things happen */
}

struct monst *bhit(), *boomhit();
dothrow()
{
	register struct obj *obj;
	register struct monst *mon;
	register tmp;

	obj = getobj("#)", "throw");   /* it is also possible to throw food */
				       /* (or jewels, or iron balls ... ) */
	if(!obj || !getdir(1))	       /* ask "in what direction?" */
		return(0);
	if(obj->owornmask & (W_ARMOR | W_RING)){
		pline("You can't throw something you are wearing");
		return(0);
	}
	if(obj == uwep){
		if(obj->cursed){
			pline("Your weapon is welded to your hand");
			return(1);
		}
		if(obj->quan > 1)
			setuwep(splitobj(obj, 1));
		else
			setuwep((struct obj *) 0);
	}
	else if(obj->quan > 1)
		(void) splitobj(obj, 1);
	freeinv(obj);
	if(u.uswallow) {
		mon = u.ustuck;
		bhitpos.x = mon->mx;
		bhitpos.y = mon->my;
	} else if(u.dz) {
	  if(u.dz < 0) {
	    pline("%s hits the ceiling, then falls back on top of your head.",
		Doname(obj));		/* note: obj->quan == 1 */
	    if(obj->olet == POTION_SYM)
		potionhit(&youmonst, obj);
	    else {
		if(uarmh) pline("Fortunately, you are wearing a helmet!");
		losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object");
		dropy(obj);
	    }
	  } else {
	    pline("%s hits the floor.", Doname(obj));
	    if(obj->otyp == EXPENSIVE_CAMERA) {
		pline("It is shattered in a thousand pieces!");
		obfree(obj, Null(obj));
	    } else if(obj->otyp == EGG) {
		pline("\"Splash!\"");
		obfree(obj, Null(obj));
	    } else if(obj->olet == POTION_SYM) {
		pline("The flask breaks, and you smell a peculiar odor ...");
		potionbreathe(obj);
		obfree(obj, Null(obj));
	    } else {
		dropy(obj);
	    }
	  }
	  return(1);
	} else if(obj->otyp == BOOMERANG) {
		mon = boomhit(u.dx, u.dy);
		if(mon == &youmonst) {		/* the thing was caught */
			(void) addinv(obj);
			return(1);
		}
	} else {
		if(obj->otyp == PICK_AXE && shkcatch(obj))
		    return(1);

		mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 :
			(!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1,
			obj->olet,
			(int (*)()) 0, (int (*)()) 0, obj);
	}
	if(mon) {
		/* awake monster if sleeping */
		wakeup(mon);

		if(obj->olet == WEAPON_SYM) {
			tmp = -1+u.ulevel+mon->data->ac+abon();
			if(obj->otyp < ROCK) {
				if(!uwep ||
				    uwep->otyp != obj->otyp+(BOW-ARROW))
					tmp -= 4;
				else {
					tmp += uwep->spe;
				}
			} else
			if(obj->otyp == BOOMERANG) tmp += 4;
			tmp += obj->spe;
			if(u.uswallow || tmp >= rnd(20)) {
				if(hmon(mon,obj,1) == TRUE){
				  /* mon still alive */
#ifndef NOWORM
				  cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp);
#endif NOWORM
				} else mon = 0;
				/* weapons thrown disappear sometimes */
				if(obj->otyp < BOOMERANG && rn2(3)) {
					/* check bill; free */
					obfree(obj, (struct obj *) 0);
					return(1);
				}
			} else miss(objects[obj->otyp].oc_name, mon);
		} else if(obj->otyp == HEAVY_IRON_BALL) {
			tmp = -1+u.ulevel+mon->data->ac+abon();
			if(!Punished || obj != uball) tmp += 2;
			if(u.utrap) tmp -= 2;
			if(u.uswallow || tmp >= rnd(20)) {
				if(hmon(mon,obj,1) == FALSE)
					mon = 0;	/* he died */
			} else miss("iron ball", mon);
		} else if(obj->olet == POTION_SYM && u.ulevel > rn2(15)) {
			potionhit(mon, obj);
			return(1);
		} else {
			if(cansee(bhitpos.x,bhitpos.y))
				pline("You miss %s.",monnam(mon));
			else pline("You miss it.");
			if(obj->olet == FOOD_SYM && mon->data->mlet == 'd')
				if(tamedog(mon,obj)) return(1);
			if(obj->olet == GEM_SYM && mon->data->mlet == 'u' &&
				!mon->mtame){
			 if(obj->dknown && objects[obj->otyp].oc_name_known){
			  if(objects[obj->otyp].g_val > 0){
			    u.uluck += 5;
			    goto valuable;
			  } else {
			    pline("%s is not interested in your junk.",
				Monnam(mon));
			  }
			 } else { /* value unknown to @ */
			    u.uluck++;
			valuable:
			    pline("%s graciously accepts your gift.",
				Monnam(mon));
			    mpickobj(mon, obj);
			    rloc(mon);
			    return(1);
			 }
			}
		}
	}
		/* the code following might become part of dropy() */
	if(obj->otyp == CRYSKNIFE)
		obj->otyp = WORM_TOOTH;
	obj->ox = bhitpos.x;
	obj->oy = bhitpos.y;
	obj->nobj = fobj;
	fobj = obj;
	/* prevent him from throwing articles to the exit and escaping */
	/* subfrombill(obj); */
	stackobj(obj);
	if(Punished && obj == uball &&
		(bhitpos.x != u.ux || bhitpos.y != u.uy)){
		freeobj(uchain);
		unpobj(uchain);
		if(u.utrap){
			if(u.utraptype == TT_PIT)
				pline("The ball pulls you out of the pit!");
			else {
			    register long side =
				rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
			    pline("The ball pulls you out of the bear trap.");
			    pline("Your %s leg is severely damaged.",
				(side == LEFT_SIDE) ? "left" : "right");
			    Wounded_legs |= side + rnd(1000);
			    losehp(2, "thrown ball");
			}
			u.utrap = 0;
		}
		unsee();
		uchain->nobj = fobj;
		fobj = uchain;
		u.ux = uchain->ox = bhitpos.x - u.dx;
		u.uy = uchain->oy = bhitpos.y - u.dy;
		setsee();
		(void) inshop();
	}
	if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
	return(1);
}

/* split obj so that it gets size num */
/* remainder is put in the object structure delivered by this call */
struct obj *
splitobj(obj, num) register struct obj *obj; register int num; {
register struct obj *otmp;
	otmp = newobj(0);
	*otmp = *obj;		/* copies whole structure */
	otmp->o_id = flags.ident++;
	otmp->onamelth = 0;
	obj->quan = num;
	obj->owt = weight(obj);
	otmp->quan -= num;
	otmp->owt = weight(otmp);	/* -= obj->owt ? */
	obj->nobj = otmp;
	if(obj->unpaid) splitbill(obj,otmp);
	return(otmp);
}

more_experienced(exp,rexp)
register int exp, rexp;
{
	extern char pl_character[];

	u.uexp += exp;
	u.urexp += 4*exp + rexp;
	if(exp) flags.botl = 1;
	if(u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000))
		flags.beginner = 0;
}
//E*O*F hack.do.c//

echo x - hack.do_name.c
cat > "hack.do_name.c" << '//E*O*F hack.do_name.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.do_name.c - version 1.0.2 */

#include "hack.h"
#include <stdio.h>
extern char plname[];

coord
getpos(force,goal) int force; char *goal; {
register cx,cy,i,c;
extern char sdir[];		/* defined in hack.c */
extern schar xdir[], ydir[];	/* idem */
extern char *visctrl();		/* see below */
coord cc;
	pline("(For instructions type a ?)");
	cx = u.ux;
	cy = u.uy;
	curs(cx,cy+2);
	while((c = readchar()) != '.'){
		for(i=0; i<8; i++) if(sdir[i] == c){
			if(1 <= cx + xdir[i] && cx + xdir[i] <= COLNO)
				cx += xdir[i];
			if(0 <= cy + ydir[i] && cy + ydir[i] <= ROWNO-1)
				cy += ydir[i];
			goto nxtc;
		}
		if(c == '?'){
			pline("Use [hjkl] to move the cursor to %s.", goal);
			pline("Type a . when you are at the right place.");
		} else {
			pline("unknown direction: '%s' (%s)",
				visctrl(c),
				force ? "use hjkl or ." : "aborted");
			if(force) goto nxtc;
			cc.x = -1;
			cc.y = 0;
			return(cc);
		}
	nxtc:	;
		curs(cx,cy+2);
	}
	cc.x = cx;
	cc.y = cy;
	return(cc);
}

do_mname(){
char buf[BUFSZ];
coord cc;
register int cx,cy,lth,i;
register struct monst *mtmp, *mtmp2;
extern char *lmonnam();
	cc = getpos(0, "the monster you want to name");
	cx = cc.x;
	cy = cc.y;
	if(cx < 0) return(0);
	mtmp = m_at(cx,cy);
	if(!mtmp){
	    if(cx == u.ux && cy == u.uy)
		pline("This ugly monster is called %s and cannot be renamed.",
		    plname);
	    else
		pline("There is no monster there.");
	    return(1);
	}
	if(mtmp->mimic){
	    pline("I see no monster there.");
	    return(1);
	}
	if(!cansee(cx,cy)) {
	    pline("I cannot see a monster there.");
	    return(1);
	}
	pline("What do you want to call %s? ", lmonnam(mtmp));
	getlin(buf);
	clrlin();
	if(!*buf) return(1);
	lth = strlen(buf)+1;
	if(lth > 63){
		buf[62] = 0;
		lth = 63;
	}
	mtmp2 = newmonst(mtmp->mxlth + lth);
	*mtmp2 = *mtmp;
	for(i=0; i<mtmp->mxlth; i++)
		((char *) mtmp2->mextra)[i] = ((char *) mtmp->mextra)[i];
	mtmp2->mnamelth = lth;
	(void) strcpy(NAME(mtmp2), buf);
	replmon(mtmp,mtmp2);
	return(1);
}

/*
 * This routine changes the address of  obj . Be careful not to call it
 * when there might be pointers around in unknown places. For now: only
 * when  obj  is in the inventory.
 */
do_oname(obj) register struct obj *obj; {
register struct obj *otmp, *otmp2;
register lth;
char buf[BUFSZ];
	pline("What do you want to name %s? ", doname(obj));
	getlin(buf);
	clrlin();
	if(!*buf) return;
	lth = strlen(buf)+1;
	if(lth > 63){
		buf[62] = 0;
		lth = 63;
	}
	otmp2 = newobj(lth);
	*otmp2 = *obj;
	otmp2->onamelth = lth;
	(void) strcpy(ONAME(otmp2), buf);

	setworn((struct obj *) 0, obj->owornmask);
	setworn(otmp2, otmp2->owornmask);

	/* do freeinv(obj); etc. by hand in order to preserve
	   the position of this object in the inventory */
	if(obj == invent) invent = otmp2;
	else for(otmp = invent; ; otmp = otmp->nobj){
		if(!otmp)
			panic("Do_oname: cannot find obj.");
		if(otmp->nobj == obj){
			otmp->nobj = otmp2;
			break;
		}
	}
	/* obfree(obj, otmp2);	/* now unnecessary: no pointers on bill */
	free((char *) obj);	/* let us hope nobody else saved a pointer */
}

ddocall()
{
	register struct obj *obj;

	pline("Do you want to name an individual object? [yn] ");
	if(readchar() == 'y'){
		obj = getobj("#", "name");
		if(obj) do_oname(obj);
	} else {
		obj = getobj("?!=/", "call");
		if(obj) docall(obj);
	}
	return(0);
}

docall(obj)
register struct obj *obj;
{
	char buf[BUFSZ];
	struct obj otemp;
	register char **str1;
	extern char *xname();
	register char *str;

	otemp = *obj;
	otemp.quan = 1;
	str = xname(&otemp);
	pline("Call %s %s: ", index(vowels,*str) ? "an" : "a", str);
	getlin(buf);
	clrlin();
	if(!*buf) return;
	str = newstring(strlen(buf)+1);
	(void) strcpy(str,buf);
	str1 = &(objects[obj->otyp].oc_uname);
	if(*str1) free(*str1);
	*str1 = str;
}

char *ghostnames[] = {		/* these names should have length < PL_NSIZ */
	"adri", "andries", "david", "dirk", "emile", "fred", "hether", "jay",
	"jon", "kenny", "maud", "michiel", "mike", "robert", "ron",
	"tom", "wilmar"
};

char *
xmonnam(mtmp, vb) register struct monst *mtmp; int vb; {
static char buf[BUFSZ];		/* %% */
extern char *shkname();
	if(mtmp->mnamelth && !vb) {
		(void) strcpy(buf, NAME(mtmp));
		return(buf);
	}
	switch(mtmp->data->mlet) {
	case ' ':
		{ register char *gn = (char *) mtmp->mextra;
		  if(!*gn) {		/* might also look in scorefile */
		    gn = ghostnames[rn2(SIZE(ghostnames))];
		    if(!rn2(2)) (void)
		      strcpy((char *) mtmp->mextra, !rn2(5) ? plname : gn);
		  }
		  (void) sprintf(buf, "%s's ghost", gn);
		}
		break;
	case '@':
		if(mtmp->isshk) {
			(void) strcpy(buf, shkname(mtmp));
			break;
		}
		/* fall into next case */
	default:
		(void) sprintf(buf, "the %s%s",
			mtmp->minvis ? "invisible " : "",
			mtmp->data->mname);
	}
	if(vb && mtmp->mnamelth) {
		(void) strcat(buf, " called ");
		(void) strcat(buf, NAME(mtmp));
	}
	return(buf);
}

char *
lmonnam(mtmp) register struct monst *mtmp; {
	return(xmonnam(mtmp, 1));
}

char *
monnam(mtmp) register struct monst *mtmp; {
	return(xmonnam(mtmp, 0));
}

char *
Monnam(mtmp) register struct monst *mtmp; {
register char *bp = monnam(mtmp);
	if('a' <= *bp && *bp <= 'z') *bp += ('A' - 'a');
	return(bp);
}

char *
amonnam(mtmp,adj)
register struct monst *mtmp;
register char *adj;
{
	register char *bp = monnam(mtmp);
	static char buf[BUFSZ];		/* %% */

	if(!strncmp(bp, "the ", 4)) bp += 4;
	(void) sprintf(buf, "the %s %s", adj, bp);
	return(buf);
}

char *
Amonnam(mtmp, adj)
register struct monst *mtmp;
register char *adj;
{
	register char *bp = amonnam(mtmp,adj);

	*bp = 'T';
	return(bp);
}

char *
Xmonnam(mtmp) register struct monst *mtmp; {
register char *bp = Monnam(mtmp);
	if(!strncmp(bp, "The ", 4)) {
		bp += 2;
		*bp = 'A';
	}
	return(bp);
}

char *
visctrl(c)
char c;
{
static char ccc[3];
	if(c < 040) {
		ccc[0] = '^';
		ccc[1] = c + 0100;
		ccc[2] = 0;
	} else {
		ccc[0] = c;
		ccc[1] = 0;
	}
	return(ccc);
}
//E*O*F hack.do_name.c//

echo x - hack.do_wear.c
cat > "hack.do_wear.c" << '//E*O*F hack.do_wear.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.do_wear.c - version 1.0.2 */

#include "hack.h"
#include <stdio.h>
extern char *nomovemsg;
extern char quitchars[];

off_msg(otmp) register struct obj *otmp; {
	pline("You were wearing %s.", doname(otmp));
}

doremarm() {
	register struct obj *otmp;
	if(!uarm && !uarmh && !uarms && !uarmg) {
		pline("Not wearing any armor.");
		return(0);
	}
	otmp = (!uarmh && !uarms && !uarmg) ? uarm :
		(!uarms && !uarm && !uarmg) ? uarmh :
		(!uarmh && !uarm && !uarmg) ? uarms :
		(!uarmh && !uarm && !uarms) ? uarmg :
		getobj("[", "take off");
	if(!otmp) return(0);
	if(!(otmp->owornmask & (W_ARMOR - W_ARM2))) {
		pline("You can't take that off.");
		return(0);
	}
	(void) armoroff(otmp);
	return(1);
}

doremring() {
	if(!uleft && !uright){
		pline("Not wearing any ring.");
		return(0);
	}
	if(!uleft)
		return(dorr(uright));
	if(!uright)
		return(dorr(uleft));
	if(uleft && uright) while(1) {
		char answer;

		pline("What ring, Right or Left? ");
		if(index(quitchars, (answer = readchar())))
			return(0);
		switch(answer) {
		case 'l':
		case 'L':
			return(dorr(uleft));
		case 'r':
		case 'R':
			return(dorr(uright));
		}
	}
	/* NOTREACHED */
#ifdef lint
	return(0);
#endif lint
}

dorr(otmp) register struct obj *otmp; {
	if(cursed(otmp)) return(0);
	ringoff(otmp);
	off_msg(otmp);
	return(1);
}

cursed(otmp) register struct obj *otmp; {
	if(otmp->cursed){
		pline("You can't. It appears to be cursed.");
		return(1);
	}
	return(0);
}

armoroff(otmp) register struct obj *otmp; {
register int delay = -objects[otmp->otyp].oc_delay;
	if(cursed(otmp)) return(0);
	setworn((struct obj *) 0, otmp->owornmask & W_ARMOR);
	if(delay) {
		nomul(delay);
		switch(otmp->otyp) {
		case HELMET:
			nomovemsg = "You finished taking off your helmet.";
			break;
		case PAIR_OF_GLOVES:
			nomovemsg = "You finished taking off your gloves";
			break;
		default:
			nomovemsg = "You finished taking off your suit.";
		}
	} else {
		off_msg(otmp);
	}
	return(1);
}

doweararm() {
	register struct obj *otmp;
	register int delay;
	register int err = 0;
	long mask = 0;

	otmp = getobj("[", "wear");
	if(!otmp) return(0);
	if(otmp->owornmask & W_ARMOR) {
		pline("You are already wearing that!");
		return(0);
	}
	if(otmp->otyp == HELMET){
		if(uarmh) {
			pline("You are already wearing a helmet.");
			err++;
		} else
			mask = W_ARMH;
	} else if(otmp->otyp == SHIELD){
		if(uarms) pline("You are already wearing a shield."), err++;
		if(uwep && uwep->otyp == TWO_HANDED_SWORD)
	pline("You cannot wear a shield and wield a two-handed sword."), err++;
		if(!err) mask = W_ARMS;
	} else if(otmp->otyp == PAIR_OF_GLOVES) {
		if(uarmg) {
			pline("You are already wearing gloves.");
			err++;
		} else
		if(uwep && uwep->cursed) {
			pline("You cannot wear gloves over your weapon.");
			err++;
		} else
			mask = W_ARMG;
	} else {
		if(uarm) {
			if(otmp->otyp != ELVEN_CLOAK || uarm2) {
				pline("You are already wearing some armor.");
				err++;
			}
		}
		if(!err) mask = W_ARM;
	}
	if(err) return(0);
	setworn(otmp, mask);
	if(otmp == uwep)
		setuwep((struct obj *) 0);
	delay = -objects[otmp->otyp].oc_delay;
	if(delay){
		nomul(delay);
		nomovemsg = "You finished your dressing manoeuvre.";
	}
	otmp->known = 1;
	return(1);
}

dowearring() {
	register struct obj *otmp;
	long mask = 0;
	long oldprop;

	if(uleft && uright){
		pline("There are no more ring-fingers to fill.");
		return(0);
	}
	otmp = getobj("=", "wear");
	if(!otmp) return(0);
	if(otmp->owornmask & W_RING) {
		pline("You are already wearing that!");
		return(0);
	}
	if(otmp == uleft || otmp == uright) {
		pline("You are already wearing that.");
		return(0);
	}
	if(uleft) mask = RIGHT_RING;
	else if(uright) mask = LEFT_RING;
	else do {
		char answer;

 		pline("What ring-finger, Right or Left? ");
		if(index(quitchars, (answer = readchar())))
			return(0);
		switch(answer){
		case 'l':
		case 'L':
			mask = LEFT_RING;
			break;
		case 'r':
		case 'R':
			mask = RIGHT_RING;
			break;
		}
	} while(!mask);
	setworn(otmp, mask);
	if(otmp == uwep)
		setuwep((struct obj *) 0);
	oldprop = u.uprops[PROP(otmp->otyp)].p_flgs;
	u.uprops[PROP(otmp->otyp)].p_flgs |= mask;
	switch(otmp->otyp){
	case RIN_LEVITATION:
		if(!oldprop) float_up();
		break;
	case RIN_PROTECTION_FROM_SHAPE_CHANGERS:
		rescham();
		break;
	case RIN_GAIN_STRENGTH:
		u.ustr += otmp->spe;
		u.ustrmax += otmp->spe;
		if(u.ustr > 118) u.ustr = 118;
		if(u.ustrmax > 118) u.ustrmax = 118;
		flags.botl = 1;
		break;
	case RIN_INCREASE_DAMAGE:
		u.udaminc += otmp->spe;
		break;
	}
	prinv(otmp);
	return(1);
}

ringoff(obj)
register struct obj *obj;
{
register long mask;
	mask = obj->owornmask & W_RING;
	setworn((struct obj *) 0, obj->owornmask);
	if(!(u.uprops[PROP(obj->otyp)].p_flgs & mask))
		impossible("Strange... I didnt know you had that ring.");
	u.uprops[PROP(obj->otyp)].p_flgs &= ~mask;
	switch(obj->otyp) {
	case RIN_LEVITATION:
		if(!Levitation) {	/* no longer floating */
			float_down();
		}
		break;
	case RIN_GAIN_STRENGTH:
		u.ustr -= obj->spe;
		u.ustrmax -= obj->spe;
		if(u.ustr > 118) u.ustr = 118;
		if(u.ustrmax > 118) u.ustrmax = 118;
		flags.botl = 1;
		break;
	case RIN_INCREASE_DAMAGE:
		u.udaminc -= obj->spe;
		break;
	}
}

find_ac(){
register int uac = 10;
#define ARM_BONUS(obj)	((10 - objects[obj->otyp].a_ac) + obj->spe)
	if(uarm) uac -= ARM_BONUS(uarm);
	if(uarm2) uac -= ARM_BONUS(uarm2);
	if(uarmh) uac -= ARM_BONUS(uarmh);
	if(uarms) uac -= ARM_BONUS(uarms);
	if(uarmg) uac -= ARM_BONUS(uarmg);
	if(uleft && uleft->otyp == RIN_PROTECTION) uac -= uleft->spe;
	if(uright && uright->otyp == RIN_PROTECTION) uac -= uright->spe;
	if(uac != u.uac){
		u.uac = uac;
		flags.botl = 1;
	}
}

glibr(){
register struct obj *otmp;
int xfl = 0;
	if(!uarmg) if(uleft || uright) {
		/* Note: at present also cursed rings fall off */
		pline("Your %s off your fingers.",
			(uleft && uright) ? "rings slip" : "ring slips");
		xfl++;
		if((otmp = uleft) != Null(obj)){
			ringoff(uleft);
			dropx(otmp);
		}
		if((otmp = uright) != Null(obj)){
			ringoff(uright);
			dropx(otmp);
		}
	}
	if((otmp = uwep) != Null(obj)){
		/* Note: at present also cursed weapons fall */
		setuwep((struct obj *) 0);
		dropx(otmp);
		pline("Your weapon %sslips from your hands.",
			xfl ? "also " : "");
	}
}

struct obj *
some_armor(){
register struct obj *otmph = uarm;
	if(uarmh && (!otmph || !rn2(4))) otmph = uarmh;
	if(uarmg && (!otmph || !rn2(4))) otmph = uarmg;
	if(uarms && (!otmph || !rn2(4))) otmph = uarms;
	return(otmph);
}

corrode_armor(){
register struct obj *otmph = some_armor();
	if(otmph){
		if(otmph->rustfree ||
		   otmph->otyp == ELVEN_CLOAK ||
		   otmph->otyp == LEATHER_ARMOR ||
		   otmph->otyp == STUDDED_LEATHER_ARMOR) {
			pline("Your %s not affected!",
				aobjnam(otmph, "are"));
			return;
		}
		pline("Your %s!", aobjnam(otmph, "corrode"));
		otmph->spe--;
	}
}
//E*O*F hack.do_wear.c//

echo x - hack.dog.c
cat > "hack.dog.c" << '//E*O*F hack.dog.c//'
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.dog.c - version 1.0.2 */

#include	"hack.h"
#include	"hack.mfndpos.h"
extern struct monst *makemon();
#include "def.edog.h"
#include "def.mkroom.h"

struct permonst li_dog =
	{ "little dog", 'd',2,18,6,1,6,sizeof(struct edog) };
struct permonst dog =
	{ "dog", 'd',4,16,5,1,6,sizeof(struct edog) };
struct permonst la_dog =
	{ "large dog", 'd',6,15,4,2,4,sizeof(struct edog) };


makedog(){
register struct monst *mtmp = makemon(&li_dog,u.ux,u.uy);
	if(!mtmp) return; /* dogs were genocided */
	initedog(mtmp);
}

initedog(mtmp) register struct monst *mtmp; {
	mtmp->mtame = mtmp->mpeaceful = 1;
	EDOG(mtmp)->hungrytime = 1000 + moves;
	EDOG(mtmp)->eattime = 0;
	EDOG(mtmp)->droptime = 0;
	EDOG(mtmp)->dropdist = 10000;
	EDOG(mtmp)->apport = 10;
	EDOG(mtmp)->whistletime = 0;
}

/* attach the monsters that went down (or up) together with @ */
struct monst *mydogs = 0;
struct monst *fallen_down = 0;	/* monsters that fell through a trapdoor */

losedogs(){
register struct monst *mtmp;
	while(mtmp = mydogs){
		mydogs = mtmp->nmon;
		mtmp->nmon = fmon;
		fmon = mtmp;
		mnexto(mtmp);
	}
	while(mtmp = fallen_down){
		fallen_down = mtmp->nmon;
		mtmp->nmon = fmon;
		fmon = mtmp;
		rloc(mtmp);
	}
}

keepdogs(){
register struct monst *mtmp;
	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
	    if(dist(mtmp->mx,mtmp->my) < 3 && follower(mtmp)) {
		relmon(mtmp);
		mtmp->nmon = mydogs;
		mydogs = mtmp;
		unpmon(mtmp);
		keepdogs();	/* we destroyed the link, so use recursion */
		return;		/* (admittedly somewhat primitive) */
	}
}

fall_down(mtmp) register struct monst *mtmp; {
	relmon(mtmp);
	mtmp->nmon = fallen_down;
	fallen_down = mtmp;
	unpmon(mtmp);
	mtmp->mtame = 0;
}

/* return quality of food; the lower the better */
#define	DOGFOOD	0
#define	CADAVER	1
#define	ACCFOOD	2
#define	MANFOOD	3
#define	APPORT	4
#define	POISON	5
#define	UNDEF	6
dogfood(obj) register struct obj *obj; {
	switch(obj->olet) {
	case FOOD_SYM:
	    return(
		(obj->otyp == TRIPE_RATION) ? DOGFOOD :
		(obj->otyp < CARROT) ? ACCFOOD :
		(obj->otyp < CORPSE) ? MANFOOD :
		(poisonous(obj) || obj->age + 50 <= moves ||
		    obj->otyp == DEAD_COCKATRICE)
			? POISON : CADAVER
	    );
	default:
	    if(!obj->cursed) return(APPORT);
	    /* fall into next case */
	case BALL_SYM:
	case CHAIN_SYM:
	case ROCK_SYM:
	    return(UNDEF);
	}
}

/* return 0 (no move), 1 (move) or 2 (dead) */
dog_move(mtmp, after) register struct monst *mtmp; {
register int nx,ny,omx,omy,appr,nearer,j;
int udist,chi,i,whappr;
register struct monst *mtmp2;
register struct permonst *mdat = mtmp->data;
register struct edog *edog = EDOG(mtmp);
struct obj *obj;
struct trap *trap;
xchar cnt,chcnt,nix,niy;
schar dogroom,uroom;
xchar gx,gy,gtyp,otyp;	/* current goal */
coord poss[9];
int info[9];
#define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy))
#define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy))

	if(moves <= edog->eattime) return(0);	/* dog is still eating */
	omx = mtmp->mx;
	omy = mtmp->my;
	whappr = (moves - EDOG(mtmp)->whistletime < 5);
	if(moves > edog->hungrytime + 500 && !mtmp->mconf){
		mtmp->mconf = 1;
		mtmp->mhpmax /= 3;
		if(mtmp->mhp > mtmp->mhpmax)
			mtmp->mhp = mtmp->mhpmax;
		if(cansee(omx,omy))
			pline("%s is confused from hunger", Monnam(mtmp));
		else	pline("You feel worried about %s.", monnam(mtmp));
	} else
	if(moves > edog->hungrytime + 750 || mtmp->mhp < 1){
		if(cansee(omx,omy))
			pline("%s dies from hunger", Monnam(mtmp));
		else
		pline("You have a sad feeling for a moment, then it passes");
		mondied(mtmp);
		return(2);
	}
	dogroom = inroom(omx,omy);
	uroom = inroom(u.ux,u.uy);
	udist = dist(omx,omy);

	/* if we are carrying sth then we drop it (perhaps near @) */
	/* Note: if apport == 1 then our behaviour is independent of udist */
	if(mtmp->minvent){
		if(!rn2(udist) || !rn2((int) edog->apport))
		if(rn2(10) < edog->apport){
			relobj(mtmp, (int) mtmp->minvis);
			if(edog->apport > 1) edog->apport--;
		}
	} else {
		if(obj = o_at(omx,omy)) if(!index("0_", obj->olet)){
		    if((otyp = dogfood(obj)) <= CADAVER){
			nix = omx;
			niy = omy;
			goto eatobj;
		    }
		    if(obj->owt < 10*mtmp->data->mlevel)
		    if(rn2(20) < edog->apport+3)
		    if(rn2(udist) || !rn2((int) edog->apport)){
			freeobj(obj);
			unpobj(obj);
			/* if(levl[omx][omy].scrsym == obj->olet)
				newsym(omx,omy); */
			mpickobj(mtmp,obj);
		    }
		}
	}

	/* first we look for food */
	gtyp = UNDEF;	/* no goal as yet */
#ifdef LINT
	gx = gy = 0;	/* suppress 'used before set' message */
#endif LINT
	for(obj = fobj; obj; obj = obj->nobj) {
		otyp = dogfood(obj);
		if(otyp > gtyp || otyp == UNDEF) continue;
		if(inroom(obj->ox,obj->oy) != dogroom) continue;
		if(otyp < MANFOOD &&
		 (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) {
			if(otyp < gtyp || (otyp == gtyp &&
				DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){
				gx = obj->ox;
				gy = obj->oy;
				gtyp = otyp;
			}
		} else
		if(gtyp == UNDEF && dogroom >= 0 &&
		   uroom == dogroom &&
		   !mtmp->minvent && edog->apport > rn2(8)){
			gx = obj->ox;
			gy = obj->oy;
			gtyp = APPORT;
		}
	}
	if(gtyp == UNDEF ||
	  (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)){
		if(dogroom < 0 || dogroom == uroom){
			gx = u.ux;
			gy = u.uy;
#ifndef QUEST
		} else {
			int tmp = rooms[dogroom].fdoor;
			    cnt = rooms[dogroom].doorct;

			gx = gy = FAR;	/* random, far away */
			while(cnt--){
			    if(dist(gx,gy) >
				dist(doors[tmp].x, doors[tmp].y)){
					gx = doors[tmp].x;
					gy = doors[tmp].y;
				}
				tmp++;
			}
			/* here gx == FAR e.g. when dog is in a vault */
			if(gx == FAR || (gx == omx && gy == omy)){
				gx = u.ux;
				gy = u.uy;
			}
#endif QUEST
		}
		appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0;
		if(after && udist <= 4 && gx == u.ux && gy == u.uy)
			return(0);
		if(udist > 1){
			if(!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) ||
			   whappr ||
			   (mtmp->minvent && rn2((int) edog->apport)))
				appr = 1;
		}
		/* if you have dog food he'll follow you more closely */
		if(appr == 0){
			obj = invent;
			while(obj){
				if(obj->otyp == TRIPE_RATION){
					appr = 1;
					break;
				}
				obj = obj->nobj;
			}
		}
	} else	appr = 1;	/* gtyp != UNDEF */
	if(mtmp->mconf) appr = 0;

	if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)){
	extern coord *gettrack();
	register coord *cp;
		cp = gettrack(omx,omy);
		if(cp){
			gx = cp->x;
			gy = cp->y;
		}
	}

	nix = omx;
	niy = omy;
	cnt = mfndpos(mtmp,poss,info,ALLOW_M | ALLOW_TRAPS);
	chcnt = 0;
	chi = -1;
	for(i=0; i<cnt; i++){
		nx = poss[i].x;
		ny = poss[i].y;
		if(info[i] & ALLOW_M){
			mtmp2 = m_at(nx,ny);
			if(mtmp2->data->mlevel >= mdat->mlevel+2 ||
			  mtmp2->data->mlet == 'c')
				continue;
			if(after) return(0); /* hit only once each move */

			if(hitmm(mtmp, mtmp2) == 1 && rn2(4) &&
			  mtmp2->mlstmv != moves &&
			  hitmm(mtmp2,mtmp) == 2) return(2);
			return(0);
		}

		/* dog avoids traps */
		/* but perhaps we have to pass a trap in order to follow @ */
		if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){
			if(!trap->tseen && rn2(40)) continue;
			if(rn2(10)) continue;
		}

		/* dog eschewes cursed objects */
		/* but likes dog food */
		obj = fobj;
		while(obj){
		    if(obj->ox != nx || obj->oy != ny)
			goto nextobj;
		    if(obj->cursed) goto nxti;
		    if(obj->olet == FOOD_SYM &&
			(otyp = dogfood(obj)) < MANFOOD &&
			(otyp < ACCFOOD || edog->hungrytime <= moves)){
			/* Note: our dog likes the food so much that he
			might eat it even when it conceals a cursed object */
			nix = nx;
			niy = ny;
			chi = i;
		     eatobj:
			edog->eattime =
			    moves + obj->quan * objects[obj->otyp].oc_delay;
			edog->hungrytime =
			    moves + 5*obj->quan * objects[obj->otyp].nutrition;
			mtmp->mconf = 0;
			if(cansee(nix,niy))
			    pline("%s ate %s.", Monnam(mtmp), doname(obj));
			/* perhaps this was a reward */
			if(otyp != CADAVER)
			edog->apport += 200/(edog->dropdist+moves-edog->droptime);
			delobj(obj);
			goto newdogpos;
		    }
		nextobj:
		    obj = obj->nobj;
		}

		for(j=0; j<MTSZ && j<cnt-1; j++)
			if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y)
				if(rn2(4*(cnt-j))) goto nxti;

/* Some stupid C compilers cannot compute the whole expression at once. */
		nearer = GDIST(nx,ny);
		nearer -= GDIST(nix,niy);
		nearer *= appr;
		if((nearer == 0 && !rn2(++chcnt)) || nearer<0 ||
			(nearer > 0 && !whappr &&
				((omx == nix && omy == niy && !rn2(3))
				|| !rn2(12))
			)){
			nix = nx;
			niy = ny;
			if(nearer < 0) chcnt = 0;
			chi = i;
		}
	nxti:	;
	}
newdogpos:
	if(nix != omx || niy != omy){
		if(info[chi] & ALLOW_U){
			(void) hitu(mtmp, d(mdat->damn, mdat->damd)+1);
			return(0);
		}
		mtmp->mx = nix;
		mtmp->my = niy;
		for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1];
		mtmp->mtrack[0].x = omx;
		mtmp->mtrack[0].y = omy;
	}
	if(mintrap(mtmp) == 2)	/* he died */
		return(2);
	pmon(mtmp);
	return(1);
}

/* return roomnumber or -1 */
inroom(x,y) xchar x,y; {
#ifndef QUEST
	register struct mkroom *croom = &rooms[0];
	while(croom->hx >= 0){
		if(croom->hx >= x-1 && croom->lx <= x+1 &&
		   croom->hy >= y-1 && croom->ly <= y+1)
			return(croom - rooms);
		croom++;
	}
#endif QUEST
	return(-1);	/* not in room or on door */
}

tamedog(mtmp, obj)
register struct monst *mtmp;
register struct obj *obj;
{
	register struct monst *mtmp2;

	if(flags.moonphase == FULL_MOON && night() && rn2(6))
		return(0);

	/* If we cannot tame him, at least he's no longer afraid. */
	mtmp->mflee = 0;
	mtmp->mfleetim = 0;
	if(mtmp->mtame || mtmp->mfroz ||
#ifndef NOWORM
		mtmp->wormno ||
#endif NOWORM
		mtmp->isshk || mtmp->isgd)
		return(0); /* no tame long worms? */
	if(obj) {
		if(dogfood(obj) >= MANFOOD) return(0);
		if(cansee(mtmp->mx,mtmp->my)){
			pline("%s devours the %s.", Monnam(mtmp),
				objects[obj->otyp].oc_name);
		}
		obfree(obj, (struct obj *) 0);
	}
	mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
	*mtmp2 = *mtmp;
	mtmp2->mxlth = sizeof(struct edog);
	if(mtmp->mnamelth) (void) strcpy(NAME(mtmp2), NAME(mtmp));
	initedog(mtmp2);
	replmon(mtmp,mtmp2);
	return(1);
}
//E*O*F hack.dog.c//

exit 0