Hack sources (part 4 of 15)

funhouse play at mcvax.UUCP
Tue Dec 18 10:30:32 AEST 1984


# This is part 4 (of 15) of the Hack sources. Send complaints to
# mcvax!play .
# 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.cmdlist.c hack.do.c

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

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

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

struct rm levl[COLNO][ROWNO];	/* level map */
#ifndef QUEST
struct mkroom rooms[MAXNROFROOMS+1];
coord doors[DOORMAX];
#endif QUEST
struct monst *fmon = 0;
struct gen *fgold = 0, *ftrap = 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;

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;
//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, 1984. */

#include	"hack.h"
extern struct monst *bchit();
extern struct obj *addinv();
extern char pl_character[];

doapply() {
register struct obj *obj;
	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 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.");
		return(0);
	}
	return(1);
}

/* ARGSUSED */
use_camera(obj) /* register */ struct obj *obj; {
register struct monst *mtmp;
	if(!getdir()){
		flags.move = multi = 0;
		return;
	}
	if(mtmp = bchit(u.dx, u.dy, COLNO, '!')) {
		if(mtmp->msleep){
			mtmp->msleep = 0;
			pline("The flash awakens the %s.", monnam(mtmp));
		} 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(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;
			}
		}
	}
}

struct obj *current_ice_box;	/* a local variable of use_ice_box, to be
				used by its local procedures in/ck_ice_box */
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);
}

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

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);
}

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;
}

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(levl[bchx][bchy].typ < CORR) {
			bchx -= ddx;
			bchy -= ddy;
			break;
		}
		if(sym) Tmp_at(bchx, bchy);
	}
	if(sym) Tmp_at(-1, -1);
	return(mtmp);
}

#include	"def.edog.h"
/* ARGSUSED */
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*10) {
			if(mtmp->msleep)
				mtmp->msleep = 0;
			if(mtmp->mtame)
				EDOG(mtmp)->whistletime = moves;
		}
		mtmp = mtmp->nmon;
	}
}

/* ARGSUSED */
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;
	}
}
//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, 1984. */

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

struct permonst pm_ghost = { "ghost", ' ', 10, 3, -5, 1, 1, sizeof(plname) };


char bones[] = "bones_xx";

/* save bones and possessions of a deceased adventurer */
savebones(){
register fd;
register struct obj *otmp;
register struct gen *gtmp;
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->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);
	u.ux = FAR;		/* avoid animals standing next to us */
	keepdogs();		/* all tame animals become wild again */
	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
		mtmp->mlstmv = 0;
		if(mtmp->mdispl) unpmon(mtmp);
	}
	for(gtmp = ftrap; gtmp; gtmp = gtmp->ngen)
		gtmp->gflag &= ~SEEN;
	for(otmp = fobj; otmp; otmp = otmp->nobj)
		otmp->onamelth = 0;
	if((fd = creat(bones, FMASK)) < 0) return;
	savelev(fd);
	(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){
		(void) getlev(fd);
		(void) close(fd);
		for(x = 0; x < COLNO; x++) for(y = 0; y < ROWNO; y++)
			levl[x][y].seen = levl[x][y].new = 0;
	}
	if(unlink(bones) < 0){
		pline("Cannot unlink %s", bones);
		return(0);
	}
	return(ok);
}
//E*O*F hack.bones.c//

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

#include	"config.h"
#include	"def.objclass.h"
#include	"def.func_tab.h"

int doredraw(),doredotopl(),dodrop(),dodrink(),doread(),dosearch(),
doversion(),doweararm(),dowearring(),doremarm(),doremring(),dopay(),doapply(),
dosave(),dowield(),ddoinv(),dozap(),ddocall(),dowhatis(),doengrave(),
dohelp(),doeat(),doddrop(),do_mname(),doidtrap(),doprwep(),doprarm(),doprring();
#ifdef SHELL
int dosh();
#endif SHELL
#ifdef OPTIONS
int doset();
#endif OPTIONS
int doup(), dodown(), done1(), donull();
int dothrow();
struct func_tab list[]={
	'\022', doredraw,
	'\020', doredotopl,
	'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', ddoinv,
/*	'I' : UNUSED */
/*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
#ifdef OPTIONS
	'o', doset,
#endif OPTIONS
/*	'O' : UNUSED */
	'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,
	'^', doidtrap,
	 WEAPON_SYM,  doprwep,
	 ARMOR_SYM,  doprarm,
	 RING_SYM,  doprring,
	0,0,0
};
//E*O*F hack.cmdlist.c//

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

#include <stdio.h>
#include <signal.h>
#include "hack.h"
#include "def.func_tab.h"

extern char *getenv(),*parse(),*getlogin(),*lowc(),*unctrl();
extern int float_down();
extern char *nomovemsg, *catmore;
extern struct obj *splitobj(), *addinv();
extern boolean hmon();

/*	Routines to do various user commands */

int done1();

dodrink() {
	register struct obj *otmp,*objs;
	register struct monst *mtmp;
	register int unkn = 0, nothing = 0;

	otmp = getobj("!", "drink");
	if(!otmp) return(0);
	switch(otmp->otyp){
	case POT_RESTORE_STRENGTH:
		unkn++;
		pline("Wow!  This makes you feel great!");
		if(u.ustr < u.ustrmax) {
			u.ustr = u.ustrmax;
			flags.botl = 1;
		}
		break;
	case POT_BOOZE:
		unkn++;
		pline("Ooph!  This tastes like liquid fire!");
		Confusion += d(3,8);
		/* the whiskey makes us feel better */
		if(u.uhp < u.uhpmax) losehp(-1, "bottle of whiskey");
		if(!rn2(4)) {
			pline("You pass out.");
			multi = -rnd(15);
			nomovemsg = "You awake with a headache.";
		}
		break;
	case POT_INVISIBILITY:
		if(Invis)
		  nothing++;
		else {
		  if(!Blind)
		    pline("Gee!  All of a sudden, you can't see yourself.");
		  else
		    pline("You feel rather airy."), unkn++;
		  newsym(u.ux,u.uy);
		}
		Invis += rn1(15,31);
		break;
	case POT_FRUIT_JUICE:
		pline("This tastes like fruit juice.");
		lesshungry(20);
		break;
	case POT_HEALING:
		pline("You begin to feel better.");
		flags.botl = 1;
		u.uhp += rnd(10);
		if(u.uhp > u.uhpmax)
			u.uhp = ++u.uhpmax;
		if(Blind) Blind = 1;	/* see on next move */
		if(Sick) Sick = 0;
		break;
	case POT_PARALYSIS:
		pline("Your feet are frozen to the floor!");
		nomul(-(rn1(10,25)));
		break;
	case POT_MONSTER_DETECTION:
		if(!fmon) {
			strange_feeling(otmp);
			return(1);
		} else {
			cls();
			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
				if(mtmp->mx > 0)
				at(mtmp->mx,mtmp->my,mtmp->data->mlet);
			prme();
			pline("You sense the presence of monsters.");
			more();
			docrt();
		}
		break;
	case POT_OBJECT_DETECTION:
		if(!fobj) {
			strange_feeling(otmp);
			return(1);
		} else {
		    for(objs = fobj; objs; objs = objs->nobj)
			if(objs->ox != u.ux || objs->oy != u.uy)
				goto outobjmap;
		    pline("You sense the presence of objects close nearby.");
		    break;
		outobjmap:
			cls();
			for(objs = fobj; objs; objs = objs->nobj)
				at(objs->ox,objs->oy,objs->olet);
			prme();
			pline("You sense the presence of objects.");
			more();
			docrt();
		}
		break;
	case POT_SICKNESS:
		pline("Yech! This stuff tastes like poison.");
		if(Poison_resistance)
    pline("(But in fact it was biologically contaminated orange juice.)");
		losestr(rn1(4,3));
		losehp(rnd(10), "poison potion");
		break;
	case POT_CONFUSION:
		if(!Confusion)
			pline("Huh, What?  Where am I?");
		else
			nothing++;
		Confusion += rn1(7,16);
		break;
	case POT_GAIN_STRENGTH:
		pline("Wow do you feel strong!");
		if(u.ustr == 118) break;
		if(u.ustr > 17) u.ustr += rnd(118-u.ustr);
		else u.ustr++;
		if(u.ustr > u.ustrmax) u.ustrmax = u.ustr;
		flags.botl = 1;
		break;
	case POT_SPEED:
		if(Wounded_legs) {
			if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
				pline("Your legs feel somewhat better.");
			else
				pline("Your leg feels somewhat better.");
			Wounded_legs = 0;
			unkn++;
			break;
		}
		if(!(Fast & ~INTRINSIC))
			pline("You are suddenly moving much faster.");
		else
			pline("Your legs get new energy."), unkn++;
		Fast += rn1(10,100);
		break;
	case POT_BLINDNESS:
		if(!Blind)
			pline("A cloud of darkness falls upon you.");
		else
			nothing++;
		Blind += rn1(100,250);
		seeoff(0);
		break;
	case POT_GAIN_LEVEL: 
		pluslvl();
		break;
	case POT_EXTRA_HEALING:
		pline("You feel much better.");
		flags.botl = 1;
		u.uhp += d(2,20)+1;
		if(u.uhp > u.uhpmax)
			u.uhp = (u.uhpmax += 2);
		if(Blind) Blind = 1;
		if(Sick) Sick = 0;
		break;
	case POT_LEVITATION:
		if(!Levitation)
			float_up();
		else
			nothing++;
		Levitation += rnd(100);
		u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down;
		break;
	default:
		pline("What a funny potion! (%d)", otmp->otyp);
		impossible();
		return(0);
	}
	if(nothing) {
	    unkn++;
	    pline("You have a peculiar feeling for a moment, then it passes.");
	}
	if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
		if(!unkn) {
			objects[otmp->otyp].oc_name_known = 1;
			u.urexp += 10;
		} else if(!objects[otmp->otyp].oc_uname)
			docall(otmp);
	}
	useup(otmp);
	return(1);
}

pluslvl()
{
	register num;

	pline("You feel more experienced.");
	num = rnd(10);
	u.uhpmax += num;
	u.uhp += num;
	u.uexp = (10*pow(u.ulevel-1))+1;
	pline("Welcome to level %d.", ++u.ulevel);
	flags.botl = 1;
}

strange_feeling(obj)
register struct obj *obj;
{
	pline("You have a strange feeling for a moment, then it passes.");
	if(!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname)
		docall(obj);
	useup(obj);
}

dodrop() {
	register struct obj *obj;

	obj = getobj("0$#", "drop");
	if(!obj) return(0);
	if(obj->olet == '$') {
		if(obj->quan == 0)
			pline("You didn't drop any gold pieces.");
		else {
			mkgold((int) obj->quan, u.ux, u.uy);
			pline("You dropped %u gold piece%s.",
				obj->quan, plur(obj->quan));
			if(Invis) newsym(u.ux, u.uy);
		}
		free((char *) obj);
		return(1);
	}
	return(drop(obj));
}

drop(obj) register struct obj *obj; {
	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);
}

dropx(obj) register struct obj *obj; {
	if(obj->otyp == CRYSKNIFE)
		obj->otyp = WORM_TOOTH;
	freeinv(obj);
	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));
}

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

	if(!cmd) {
		firsttime = TRUE;
		flags.nopick = 0;
		cmd = parse();
	}
	if(!*cmd || *cmd == 0377)
		return;		/* probably we just had an interrupt */
	if(movecm(cmd)) {
	walk:
		if(multi) flags.mv = 1;
		domove();
		return;
	}
	if(movecm(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' && movecm(cmd+1)) ||
		movecm(unctrl(cmd))) {
		flags.run = 2;
		goto rush;
	}
	if(*cmd == 'F' && movecm(lowc(cmd+1))) {
		flags.run = 3;
		goto rush;
	}
	if(*cmd == 'm' && movecm(cmd+1)) {
		flags.run = 0;
		flags.nopick = 1;
		goto walk;
	}
	if(*cmd == 'M' && movecm(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++;
	}
	pline("Unknown command '%s'",cmd);
	multi = flags.move = 0;
}

doredraw()
{
	docrt();
	return(0);
}

dohelp()
{
	if(child(1)){
		execl(catmore,"more","help",(char *)0);
		exit(1);
	}
	return(0);
}

#ifdef SHELL
dosh(){
register char *str;
	if(child(0)) {
		(void) chdir(getenv("HOME"));
		if(str = getenv("SHELL")) execl(str,str,(char *) 0);
		if(strcmp("player", getlogin()))
			execl("/bin/sh","sh",(char *) 0);
		pline("sh: cannot execute.");
		exit(1);
	}
	return(0);
}
#endif SHELL

#ifdef BSD
#include	<sys/wait.h>
#else
#include	<wait.h>
#endif BSD

child(wt) {
register int f = fork();
	if(f == 0){		/* child */
		settty((char *) 0);
		(void) setuid(getuid());
		return(1);
	}
	if(f == -1) {	/* cannot fork */
		pline("Fork failed. Try again.");
		return(0);
	}
	/* fork succeeded; wait for child to exit */
	(void) signal(SIGINT,SIG_IGN);
	(void) signal(SIGQUIT,SIG_IGN);
	(void) wait((union wait *) 0);
	setctty();
	(void) signal(SIGINT,done1);
#ifdef WIZARD
	if(wizard) (void) signal(SIGQUIT,SIG_DFL);
#endif WIZARD
	if(wt) getret();
	docrt();
	return(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.
		 */
		pline("A mysterious force prevents you from going %d.",
			up ? "up" : "down");
		return;
	}

	if(Punished) unplacebc();
	keepdogs();
	seeoff(1);
	flags.nscrinh = 1;
	u.ux = FAR;				/* hack */
	(void) inshop();			/* probably was a trapdoor */

	savelev(fd);
	(void) close(fd);

	dlevel = newlevel;
	if(maxdlevel < dlevel)
		maxdlevel = dlevel;
	glo(dlevel);
	if((fd = open(lock,0)) < 0)
		mklev();
	else {
		(void) getlev(fd);
		(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");
		}
	    }
	} 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();
#ifdef TRACK
	initrack();
#endif TRACK

	losedogs();
	flags.nscrinh = 0;
	setsee();
	docrt();
	pickup();
	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())
		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(obj->otyp == BOOMERANG) {
		mon = boomhit(u.dx,u.dy);
		/* boomhit delivers -1 if the thing was caught */
		if((int) mon == -1) {
			(void) addinv(obj);
			return(1);
		}
	} else
		mon = bhit(u.dx,u.dy,
			(!Punished || obj != uball) ? 8 :
				!u.ustuck ? 5 : 1,
			obj->olet);
	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(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'){
			 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);
			 }
			}
		}
	}
	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 int 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);
}

getdir()
{
char buf[2];
	pline("What direction?");
	buf[0] = readchar();
	buf[1] = 0;
	return(movecm(buf));
}

/* 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);
}

char *
lowc(str)
register char *str;
{
	static char buf[2];

	if(*str >= 'A' && *str <= 'Z') *buf = *str+'a'-'A';
	else *buf = *str;
	buf[1] = 0;
	return(buf);
}

char *
unctrl(str)
register char *str;
{
	static char buf[2];
	if(*str >= ('A' & 037) && *str <= ('Z' & 037))
		*buf = *str + 0140;
	else *buf = *str;
	buf[1] = 0;
	return(buf);
}
//E*O*F hack.do.c//

exit 0



More information about the Comp.sources.unix mailing list