Hack Sources (Part 11 of 15)

ron at vaxnix.UUCP ron at vaxnix.UUCP
Mon Dec 31 03:27:00 AEST 1984


# This is part 11 (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.shk.c hack.stat.c hack.steal.c hack.termcap.c hack.timeout.c hack.topl.c

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

#include "hack.h"
#ifdef QUEST
int shlevel = 0;
struct monst *shopkeeper = 0;
struct obj *billobjs = 0;
obfree(obj,merge) register struct obj *obj, *merge; {
	free((char *) obj);
}
inshop(){ return(0); }
addtobill(){}
subfrombill(){}
splitbill(){}
dopay(){}
paybill(){}
doinvbill(){}
shkdead(){}
shk_move(){ return(0); }
setshk(){}
char *shkname(){ return(""); }

#else
#include	"hack.mfndpos.h"
#include	"def.eshk.h"

#define	ESHK	((struct eshk *)(&(shopkeeper->mextra[0])))
#define	NOTANGRY	shopkeeper->mpeaceful
#define	ANGRY	!NOTANGRY

extern char plname[];
extern struct obj *o_on();
struct monst *shopkeeper = 0;
struct bill_x *bill;
int shlevel = 0;	/* level of this shopkeeper */
struct obj *billobjs;	/* objects on bill with bp->useup */
/* #define	billobjs	shopkeeper->minvent
   doesnt work so well, since we do not want these objects to be dropped
   when the shopkeeper is killed.
   (See also the save and restore routines.)
 */

/* invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
		obj->quan <= bp->bquan
 */

long int total;

char shtypes[] = "=/)%?!["; /* 8 shoptypes: 7 specialized, 1 mixed */
char *shopnam[] = {
	"engagement ring", "walking cane", "antique weapon",
	"delicatessen", "second hand book", "liquor",
	"used armor", "assorted antiques"
};

char *
shkname() {
	return(ESHK->shknam);
}

shkdead(){
	rooms[ESHK->shoproom].rtype = 0;
	setpaid();
	shopkeeper = 0;
	bill = (struct bill_x *) -1000;	/* dump core when referenced */
}

setpaid(){	/* caller has checked that shopkeeper exists */
register struct obj *obj;
	for(obj = invent; obj; obj = obj->nobj)
		obj->unpaid = 0;
	for(obj = fobj; obj; obj = obj->nobj)
		obj->unpaid = 0;
	while(obj = billobjs){
		billobjs = obj->nobj;
		free((char *) obj);
	}
	ESHK->billct = 0;
}

addupbill(){	/* delivers result in total */
		/* caller has checked that shopkeeper exists */
register ct = ESHK->billct;
register struct bill_x *bp = bill;
	total = 0;
	while(ct--){
		total += bp->price * bp->bquan;
		bp++;
	}
}

inshop(){
register tmp = inroom(u.ux,u.uy);
	if(tmp < 0 || rooms[tmp].rtype < 8) {
		u.uinshop = 0;
		if(shopkeeper && ESHK->billct){
			pline("Somehow you escaped the shop without paying!");
			addupbill();
			pline("You stole for a total worth of %lu zorkmids.",
				total);
			ESHK->robbed += total;
			setpaid();
		}
		if(tmp >= 0 && rooms[tmp].rtype == 7){
			register struct monst *mtmp;
			pline("Welcome to David's treasure zoo!");
			rooms[tmp].rtype = 0;
			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
				if(!rn2(4)) mtmp->msleep = 0;
		}
	} else {
		if(shlevel != dlevel) setshk();
		if(!shopkeeper) u.uinshop = 0;
		else if(!u.uinshop){
			if(!ESHK->visitct ||
				strncmp(ESHK->customer, plname, PL_NSIZ)){
				/* He seems to be new here */
				ESHK->visitct = 0;
				(void) strncpy(ESHK->customer,plname,PL_NSIZ);
				NOTANGRY = 1;
			}
			pline("Hello %s! Welcome%s to %s's %s shop!",
				plname,
				ESHK->visitct++ ? " again" : "",
				shkname(),
				shopnam[rooms[ESHK->shoproom].rtype - 8] );
			u.uinshop = 1;
		}
	}
	return(u.uinshop);
}

setshk(){
register struct monst *mtmp;
	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->isshk){
		shopkeeper = mtmp;
		bill = &(ESHK->bill[0]);
		shlevel = dlevel;
		if(ANGRY && strncpy(ESHK->customer,plname,PL_NSIZ))
			NOTANGRY = 1;
		billobjs = 0;
		return;
	}
	shopkeeper = 0;
	bill = (struct bill_x *) -1000;	/* dump core when referenced */
}

struct bill_x *
onbill(obj) register struct obj *obj; {
register struct bill_x *bp;
	if(!shopkeeper) return(0);
	for(bp = bill; bp < &bill[ESHK->billct]; bp++)
		if(bp->bo_id == obj->o_id) {
			if(!obj->unpaid) pline("onbill: paid obj on bill?");
			return(bp);
		}
	if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
	return(0);
}

/* called with two args on merge */
obfree(obj,merge) register struct obj *obj, *merge; {
register struct bill_x *bp = onbill(obj);
register struct bill_x *bpm;
	if(bp) {
		if(!merge){
			bp->useup = 1;
			obj->unpaid = 0;	/* only for doinvbill */
			obj->nobj = billobjs;
			billobjs = obj;
			return;
		}
		bpm = onbill(merge);
		if(!bpm){
			/* this used to be a rename */
			impossible();
			return;
		} else {
			/* this was a merger */
			bpm->bquan += bp->bquan;
			ESHK->billct--;
			*bp = bill[ESHK->billct];
		}
	}
	free((char *) obj);
}

pay(tmp) long tmp; {
	u.ugold -= tmp;
	shopkeeper->mgold += tmp;
	flags.botl = 1;
}

dopay(){
long ltmp;
register struct bill_x *bp;
int shknear = (shlevel == dlevel && shopkeeper &&
	dist(shopkeeper->mx,shopkeeper->my) < 3);
int pass, tmp;

	multi = 0;
	if(!inshop() && !shknear) {
		pline("You are not in a shop.");
		return(0);
	}
	if(!shknear &&
	    inroom(shopkeeper->mx,shopkeeper->my) != ESHK->shoproom){
		pline("There is nobody here to receive your payment.");
		return(0);
	}
	if(!ESHK->billct){
		pline("You do not owe %s anything.", monnam(shopkeeper));
		if(!u.ugold){
			pline("Moreover, you have no money.");
			return(1);
		}
		if(ESHK->robbed){
			pline("But since the shop has been robbed recently,");
			pline("you %srepay %s's expenses.",
				(u.ugold < ESHK->robbed) ? "partially " : "",
				monnam(shopkeeper));
			pay((u.ugold<ESHK->robbed) ? u.ugold : ESHK->robbed);
			ESHK->robbed = 0;
			return(1);
		}
		if(ANGRY){
			pline("But in order to appease %s,",
				amonnam(shopkeeper, "angry"));
			if(u.ugold >= 1000){
				ltmp = 1000;
				pline(" you give him 1000 gold pieces.");
			} else {
				ltmp = u.ugold;
				pline(" you give him all your money.");
			}
			pay(ltmp);
			if(rn2(3)){
				pline("%s calms down.", Monnam(shopkeeper));
				NOTANGRY = 1;
			} else	pline("%s is as angry as ever.",
					Monnam(shopkeeper));
		}
		return(1);
	}
	for(pass = 0; pass <= 1; pass++) {
		tmp = 0;
		while(tmp < ESHK->billct) {
			bp = &bill[tmp];
			if(!pass && !bp->useup) {
				tmp++;
				continue;
			}
			if(!dopayobj(bp)) return(1);
			bill[tmp] = bill[--ESHK->billct];
		}
	}
	pline("Thank you for shopping in %s's %s store!",
		shkname(),
		shopnam[rooms[ESHK->shoproom].rtype - 8]);
	NOTANGRY = 1;
	return(1);
}

/* return 1 if paid successfully */
/*        0 if not enough money */
/*       -1 if object could not be found (but was paid) */
dopayobj(bp) register struct bill_x *bp; {
register struct obj *obj;
long ltmp;

	/* find the object on one of the lists */
	if(bp->useup)
		obj = o_on(bp->bo_id, billobjs);
	else if(!(obj = o_on(bp->bo_id, invent)) &&
		!(obj = o_on(bp->bo_id, fobj)) &&
		!(obj = o_on(bp->bo_id, fcobj))) {
		    register struct monst *mtmp;
		    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
			if(obj = o_on(bp->bo_id, mtmp->minvent))
			    break;
		    for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
			if(obj = o_on(bp->bo_id, mtmp->minvent))
			    break;
		}
	if(!obj) {
		pline("Shopkeeper administration out of order.");
		impossible();
		setpaid();	/* be nice to the player */
		return(0);
	}

	if(!obj->unpaid && !bp->useup){
		pline("Paid object on bill??");
		impossible();
		return(1);
	}
	obj->unpaid = 0;
	ltmp = bp->price * bp->bquan;
	if(ANGRY) ltmp += ltmp/3;
	if(u.ugold < ltmp){
		pline("You don't have gold enough to pay %s.",
			doname(obj));
		obj->unpaid = 1;
		return(0);
	}
	pay(ltmp);
	pline("You bought %s for %ld gold piece%s.",
		doname(obj), ltmp, (ltmp == 1) ? "" : "s");
	if(bp->useup) {
		register struct obj *otmp = billobjs;
		if(obj == billobjs)
			billobjs = obj->nobj;
		else {
			while(otmp && otmp->nobj != obj) otmp = otmp->nobj;
			if(otmp) otmp->nobj = obj->nobj;
			else pline("Error in shopkeeper administration");
		}
		free((char *) obj);
	}
	return(1);
}

/* routine called after dying (or quitting) with nonempty bill */
paybill(){
	if(shopkeeper && ESHK->billct){
		addupbill();
		if(total > u.ugold){
			shopkeeper->mgold += u.ugold;
			u.ugold = 0;
		pline("%s comes and takes all your possessions.",
			Monnam(shopkeeper));
		} else {
			u.ugold -= total;
			shopkeeper->mgold += total;
	pline("%s comes and takes the %ld zorkmids you owed him.",
		Monnam(shopkeeper), total);
		}
		setpaid();	/* in case we create bones */
	}
}

/* called in hack.c when we pickup an object */
addtobill(obj) register struct obj *obj; {
register struct bill_x *bp;
	if(!inshop() || (u.ux == ESHK->shk.x && u.uy == ESHK->shk.y) ||
		(u.ux == ESHK->shd.x && u.uy == ESHK->shd.y) ||
		onbill(obj) /* perhaps we threw it away earlier */
	) return;
	if(ESHK->billct == BILLSZ){
		pline("You got that for free!");
		return;
	}
	bp = &bill[ESHK->billct];
	bp->bo_id = obj->o_id;
	bp->bquan = obj->quan;
	bp->useup = 0;
	bp->price = getprice(obj);
	ESHK->billct++;
	obj->unpaid = 1;
}

splitbill(obj,otmp) register struct obj *obj, *otmp; {
	/* otmp has been split off from obj */
register struct bill_x *bp;
register int tmp;
	bp = onbill(obj);
	if(!bp) { impossible(); return; }
	if(bp->bquan < otmp->quan) {
		pline("Negative quantity on bill??");
		impossible();
	}
	if(bp->bquan == otmp->quan) {
		pline("Zero quantity on bill??");
		impossible();
	}
	bp->bquan -= otmp->quan;

	/* addtobill(otmp); */
	if(ESHK->billct == BILLSZ) otmp->unpaid = 0;
	else {
		tmp = bp->price;
		bp = &bill[ESHK->billct];
		bp->bo_id = otmp->o_id;
		bp->bquan = otmp->quan;
		bp->useup = 0;
		bp->price = tmp;
		ESHK->billct++;
	}
}

subfrombill(obj) register struct obj *obj; {
long ltmp;
register int tmp;
register struct obj *otmp;
register struct bill_x *bp;
	if(!inshop() || (u.ux == ESHK->shk.x && u.uy == ESHK->shk.y) ||
		(u.ux == ESHK->shd.x && u.uy == ESHK->shd.y))
		return;
	if((bp = onbill(obj)) != 0){
		obj->unpaid = 0;
		if(bp->bquan > obj->quan){
			otmp = newobj(0);
			*otmp = *obj;
			bp->bo_id = otmp->o_id = flags.ident++;
			otmp->quan = (bp->bquan -= obj->quan);
			otmp->owt = 0;	/* superfluous */
			otmp->onamelth = 0;
			bp->useup = 1;
			otmp->nobj = billobjs;
			billobjs = otmp;
			return;
		}
		ESHK->billct--;
		*bp = bill[ESHK->billct];
		return;
	}
	if(obj->unpaid){
		pline("%s didn't notice.", Monnam(shopkeeper));
		obj->unpaid = 0;
		return;		/* %% */
	}
	/* he dropped something of his own - probably wants to sell it */
	if(shopkeeper->msleep || shopkeeper->mfroz ||
		inroom(shopkeeper->mx,shopkeeper->my) != ESHK->shoproom)
		return;
	if(ESHK->billct == BILLSZ ||
	  ((tmp = shtypes[rooms[ESHK->shoproom].rtype-8]) && tmp != obj->olet)
	  || index("_0", obj->olet)) {
		pline("%s seems not interested.", Monnam(shopkeeper));
		return;
	}
	ltmp = getprice(obj) * obj->quan;
	if(ANGRY) {
		ltmp /= 3;
		NOTANGRY = 1;
	} else	ltmp /= 2;
	if(ESHK->robbed){
		if((ESHK->robbed -= ltmp) < 0) ESHK->robbed = 0;
pline("Thank you for your contribution to restock this recently plundered shop.");
		return;
	}
	if(ltmp > shopkeeper->mgold) ltmp = shopkeeper->mgold;
	pay(-ltmp);
	if(!ltmp)
	pline("%s gladly accepts %s but cannot pay you at present.",
		Monnam(shopkeeper), doname(obj));
	else
	pline("You sold %s and got %ld gold piece%s.", doname(obj), ltmp,
		(ltmp == 1) ? "" : "s");
}

doinvbill(cl) int cl; {
register unsigned tmp,cnt = 0;
register struct obj *obj;
char buf[BUFSZ];
	if(!shopkeeper) return;
	for(tmp = 0; tmp < ESHK->billct; tmp++) if(bill[tmp].useup) cnt++;
	if(!cnt) return;
	if(!cl && !flags.oneline) cls();
	if(!flags.oneline) puts("\n\nUnpaid articles already used up:\n");
	for(tmp = 0; tmp < ESHK->billct; tmp++) if(bill[tmp].useup){
		for(obj = billobjs; obj; obj = obj->nobj)
			if(obj->o_id == bill[tmp].bo_id) break;
		if(!obj) {
			pline("Bad shopkeeper administration.");
			impossible();
			return;
		}
		(void) sprintf(buf, "* -  %s", doname(obj));
		for(cnt=0; buf[cnt]; cnt++);
		while(cnt < 50) buf[cnt++] = ' ';
		(void) sprintf(&buf[cnt], " %5d zorkmids",
				bill[tmp].price * bill[tmp].bquan);
		if(flags.oneline)
			pline(buf);
		else
			puts(buf);
	}
	if(!cl && !flags.oneline) {
		getret();
		docrt();
	}
}

getprice(obj) register struct obj *obj; {
register int tmp,ac;
	switch(obj->olet){
		case AMULET_SYM:
			tmp = 10*rnd(500);
			break;
		case TOOL_SYM:
			tmp = 10*rnd(150);
			break;
		case RING_SYM:
			tmp = 10*rnd(100);
			break;
		case WAND_SYM:
			tmp = 10*rnd(100);
			break;
		case SCROLL_SYM:
			tmp = 10*rnd(50);
			break;
		case POTION_SYM:
			tmp = 10*rnd(50);
			break;
		case FOOD_SYM:
			tmp = 10*rnd(5 + (2000/realhunger()));
			break;
		case GEM_SYM:
			tmp = 10*rnd(20);
			break;
		case ARMOR_SYM:
			ac = 10 - obj->spe;
			tmp = 100 + (10-ac)*(10-ac)*rnd(20-ac);
			break;
		case WEAPON_SYM:
			if(obj->otyp < BOOMERANG)
				tmp = 5*rnd(10);
			else if(obj->otyp == LONG_SWORD ||
				obj->otyp == TWO_HANDED_SWORD)
				tmp = 10*rnd(150);
			else	tmp = 10*rnd(75);
			break;
		case CHAIN_SYM:
			pline("Strange ..., carrying a chain?");
		case BALL_SYM:
			tmp = 10;
			break;
		default:
			tmp = 10000;
	}
	return(tmp);
}

realhunger(){	/* not completely foolproof */
register tmp = u.uhunger;
register struct obj *otmp = invent;
	while(otmp){
		if(otmp->olet == FOOD_SYM && !otmp->unpaid)
			tmp += objects[otmp->otyp].nutrition;
		otmp = otmp->nobj;
	}
	return((tmp <= 0) ? 1 : tmp);
}

shk_move(){
register struct monst *mtmp;
register struct permonst *mdat = shopkeeper->data;
register xchar gx,gy,omx,omy,nx,ny,nix,niy;
register schar appr,i;
schar shkr,tmp,chi,chcnt,cnt;
boolean uondoor, avoid;
coord poss[9];
int info[9];
	omx = shopkeeper->mx;
	omy = shopkeeper->my;
	shkr = inroom(omx,omy);
	if(ANGRY && dist(omx,omy) < 3){
		(void) hitu(shopkeeper, d(mdat->damn, mdat->damd)+1);
		return(0);
	}
	appr = 1;
	gx = ESHK->shk.x;
	gy = ESHK->shk.y;
	if(ANGRY){
		int saveBlind = Blind;
		Blind = 0;
		if(shopkeeper->mcansee && !Invis && cansee(omx,omy)) {
			gx = u.ux;
			gy = u.uy;
		}
		Blind = saveBlind;
		avoid = FALSE;
	} else {
#define	GDIST(x,y)	((x-gx)*(x-gx)+(y-gy)*(y-gy))
		if(Invis)
		  avoid = FALSE;
		else {
		  uondoor = (u.ux == ESHK->shd.x && u.uy == ESHK->shd.y);
		  avoid = ((u.uinshop && dist(gx,gy) > 8) || uondoor);
		  if(((!ESHK->robbed && !ESHK->billct) || avoid)
		  	&& GDIST(omx,omy) < 3){
		  	if(!online(omx,omy)) return(0);
		  	if(omx == gx && omy == gy)
		  		appr = gx = gy = 0;
		  }
		}
	}
	if(omx == gx && omy == gy) return(0);
	if(shopkeeper->mconf) appr = 0;
	nix = omx;
	niy = omy;
	cnt = mfndpos(shopkeeper,poss,info,
		(avoid ? NOTONL : 0) | ALLOW_SSM);
	if(cnt == 0 && avoid && uondoor)
		cnt = mfndpos(shopkeeper,poss,info,ALLOW_SSM);
	chi = -1;
	chcnt = 0;
	for(i=0; i<cnt; i++){
		nx = poss[i].x;
		ny = poss[i].y;
	   	if((tmp = levl[nx][ny].typ) == ROOM ||
		(shkr != ESHK->shoproom && (tmp==CORR || tmp==DOOR)))
#ifdef STUPID
		/* cater for stupid compilers */
		{ int zz;
		if((!appr && !rn2(++chcnt)) ||
		   (appr && (zz = GDIST(nix,niy)) && zz > GDIST(nx,ny))){
#else
		if((!appr && !rn2(++chcnt)) ||
		   (appr && GDIST(nx,ny) < GDIST(nix,niy))){
#endif STUPID
			nix = nx;
			niy = ny;
			chi = i;
#ifdef STUPID
		   }
#endif STUPID
		}
	}
	if(nix != omx || niy != omy){
		if(info[chi] & ALLOW_M){
			mtmp = m_at(nix,niy);
			if(hitmm(shopkeeper,mtmp) == 1 && rn2(3) &&
			   hitmm(mtmp,shopkeeper) == 2) return(2);
			return(0);
		} else if(info[chi] & ALLOW_U){
			(void) hitu(shopkeeper, d(mdat->damn, mdat->damd)+1);
			return(0);
		}
		shopkeeper->mx = nix;
		shopkeeper->my = niy;
		pmon(shopkeeper);
		return(1);
	}
	return(0);
}
#endif QUEST

char *
plur(n) unsigned n; {
	return((n==1) ? "" : "s");
}

online(x,y) {
	return(x==u.ux || y==u.uy ||
		(x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy));
}
//E*O*F hack.shk.c//

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

#include <sys/types.h>
#include <sys/stat.h>
extern char *index();
struct stat buf,hbuf;

gethdate(name) char *name; {
register char *np;
	if(stat(name, &hbuf))
		error("Cannot get status of %s.",
			(np = index(name, '/')) ? np+1 : name);
}

uptodate(fd) {
	if(fstat(fd, &buf)) {
		pline("Cannot get status?");
		return(0);
	}
	if(buf.st_ctime < hbuf.st_ctime) {
		pline("Saved level is out of date.");
		return(0);
	}
	return(1);
}
//E*O*F hack.stat.c//

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

#include "hack.h"

stealgold(mtmp)  register struct monst *mtmp; {
register struct gen *gold = g_at(u.ux, u.uy, fgold);
register tmp;
	if(gold && ( !u.ugold || gold->gflag > u.ugold || !rn2(5))) {
		mtmp->mgold += gold->gflag;
		freegold(gold);
		if(Invis) newsym(u.ux, u.uy);
		pline("%s quickly snatches some gold from between your feet!",
			Monnam(mtmp));
		if(!u.ugold || !rn2(5)) {
			rloc(mtmp);
			mtmp->mflee = 1;
		}
	} else if(u.ugold) {
		u.ugold -= (tmp = somegold());
		pline("Your purse feels lighter.");
		mtmp->mgold += tmp;
		rloc(mtmp);
		mtmp->mflee = 1;
		flags.botl = 1;
	}
}

somegold(){
	return( (u.ugold < 100) ? u.ugold :
		(u.ugold > 10000) ? rnd(10000) : rnd((int) u.ugold) );
}

/* steal armor after he finishes taking it off */
unsigned stealoid;		/* object to be stolen */
unsigned stealmid;		/* monster doing the stealing */
stealarm(){
	register struct monst *mtmp;
	register struct obj *otmp;

	for(otmp = invent; otmp; otmp = otmp->nobj)
	  if(otmp->o_id == stealoid) {
	    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
	      if(mtmp->m_id == stealmid) {
		if(dist(mtmp->mx,mtmp->my) < 3) {
		  freeinv(otmp);
		  pline("%s steals %s!", Monnam(mtmp), doname(otmp));
		  mpickobj(mtmp,otmp);
		  mtmp->mflee = 1;
		  rloc(mtmp);
		}
		break;
	      }
	    break;
	  }
	stealoid = 0;
}

/* returns 1 when something was stolen */
/* (or at least, when N should flee now) */
/* avoid stealing the object stealoid */
steal(mtmp)
struct monst *mtmp;
{
	register struct obj *otmp;
	register tmp;
	register named = 0;

	if(!invent){
	    if(Blind)
	      pline("Somebody tries to rob you, but finds nothing to steal.");
	    else
	      pline("%s tries to rob you, but she finds nothing to steal!",
		Monnam(mtmp));
	    return(1);	/* let her flee */
	}
	tmp = 0;
	for(otmp = invent; otmp; otmp = otmp->nobj)
		tmp += ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1);
	tmp = rn2(tmp);
	for(otmp = invent; otmp; otmp = otmp->nobj)
		if((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1))
			< 0) break;
	if(!otmp) panic("Steal fails!");
	if(otmp->o_id == stealoid) return(0);
	if((otmp->owornmask & (W_ARMOR | W_RING))){
		switch(otmp->olet) {
		case RING_SYM:
			ringoff(otmp);
			break;
		case ARMOR_SYM:
			if(multi < 0 || otmp == uarms){
			  setworn((struct obj *) 0, otmp->owornmask & W_ARMOR);
			  break;
			}
		{ int curssv = otmp->cursed;
			otmp->cursed = 0;
			pline("%s seduces you and %s off your %s.",
				Amonnam(mtmp, Blind ? "gentle" : "beautiful"),
				otmp->cursed ? "helps you to take"
					    : "you start taking",
				(otmp == uarmg) ? "gloves" :
				(otmp == uarmh) ? "helmet" : "armor");
			named++;
			(void) armoroff(otmp);
			otmp->cursed = curssv;
			if(multi < 0){
				extern char *nomovemsg;
				extern int (*afternmv)();
				/*
				multi = 0;
				nomovemsg = 0;
				afternmv = 0;
				*/
				stealoid = otmp->o_id;
				stealmid = mtmp->m_id;
				afternmv = stealarm;
				return(0);
			}
			break;
		}
		default:
			impossible();
		}
	}
	else if(otmp == uwep)
		setuwep((struct obj *) 0);
	if(otmp->olet == CHAIN_SYM) {
		pline("How come you are carrying that chain?");
		impossible();
	}
	if(Punished && otmp == uball){
		Punished = 0;
		freeobj(uchain);
		free((char *) uchain);
		uchain = (struct obj *) 0;
		uball->spe = 0;
		uball = (struct obj *) 0;	/* superfluous */
	}
	freeinv(otmp);
	pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp));
	mpickobj(mtmp,otmp);
	return((multi < 0) ? 0 : 1);
}

mpickobj(mtmp,otmp)
register struct monst *mtmp;
register struct obj *otmp;
{
	otmp->nobj = mtmp->minvent;
	mtmp->minvent = otmp;
}

/* release the objects the killed animal has stolen */
relobj(mtmp,show)
register struct monst *mtmp;
register show;
{
	register struct obj *otmp, *otmp2;

	for(otmp = mtmp->minvent; otmp; otmp = otmp2){
		otmp->ox = mtmp->mx;
		otmp->oy = mtmp->my;
		otmp2 = otmp->nobj;
		otmp->nobj = fobj;
		fobj = otmp;
		stackobj(fobj);
		if(show & cansee(mtmp->mx,mtmp->my))
			atl(otmp->ox,otmp->oy,otmp->olet);
	}
	mtmp->minvent = (struct obj *) 0;
	if(mtmp->mgold || mtmp->data->mlet == 'L') {
		register int tmp;

		tmp = (mtmp->mgold > 10000) ? 10000 : mtmp->mgold;
		mkgold( tmp + d(dlevel,30), mtmp->mx, mtmp->my);
		if(show & cansee(mtmp->mx,mtmp->my))
			atl(mtmp->mx,mtmp->my,'$');
	}
}
//E*O*F hack.steal.c//

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

#include <stdio.h>
#include "config.h"	/* for ROWNO and COLNO */
extern char *tgetstr(), *tgoto(), *getenv();
extern long *alloc();

short ospeed;		/* terminal baudrate; used by tputs */
char tbuf[512];
char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE;
char PC = '\0';

startup()
{
	register char *tmp;
	register char *tptr;
	char *tbufptr, *pc;

	gettty();	/* sets ospeed */

	tptr = (char *) alloc(1024);

	tbufptr = tbuf;
	if(!(tmp = getenv("TERM")))
		error("Can't get TERM.");
	if(tgetent(tptr,tmp) < 1)
		error("Unknown terminal type: %s.", tmp);
	if(pc = tgetstr("pc",&tbufptr))
		PC = *pc;
	if(!(BC = tgetstr("bc",&tbufptr))) {	
		if(!tgetflag("bs"))
			error("Terminal must backspace.");
		BC = tbufptr;
		tbufptr += 2;
		*BC = '\b';
	}
	HO = tgetstr("ho", &tbufptr);
	if(tgetnum("co") < COLNO || tgetnum("li") < ROWNO+2)
		error("Screen must be at least %d by %d!",
			ROWNO+2, COLNO);
	if(!(CL = tgetstr("cl",&tbufptr)) || !(CE = tgetstr("ce",&tbufptr)) ||
		!(ND = tgetstr("nd", &tbufptr)) ||
		!(UP = tgetstr("up",&tbufptr)) || tgetflag("os"))
		error("Hack needs CL, CE, UP, ND, and no OS.");
	if(!(CM = tgetstr("cm",&tbufptr)))
		printf("Use of hack on terminals without CM is suspect...\n");
	XD = tgetstr("xd",&tbufptr);
	SO = tgetstr("so",&tbufptr);
	SE = tgetstr("se",&tbufptr);
	if(!SO || !SE) SO = SE = 0;
	if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
	free(tptr);
}

/* Cursor movements */
extern xchar curx, cury;

curs(x,y)
register int x,y;	/* not xchar: perhaps xchar is unsigned and
			   curx-x would be unsigned as well */
{

	if (y == cury && x == curx) return;
	if(abs(cury-y)<= 3 && abs(curx-x)<= 3) nocmov(x,y);
	else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
		(void) putchar('\r');
		curx = 1;
		nocmov(x,y);
	} else if(!CM) nocmov(x,y);
	else cmov(x,y);
}

nocmov(x,y)
{
	if (curx < x) {		/* Go to the right. */
		while (curx < x) {
			xputs(ND);
			curx++;
		}
	} else if (curx > x) {
		while (curx > x) {	/* Go to the left. */
			xputs(BC);
			curx--;
		}
	}
	if (cury > y) {
		if(UP) {
			while (cury > y) {	/* Go up. */
				xputs(UP);
				cury--;
			}
		} else cmov(x,y);
	} else if (cury < y) {
		if(XD) {
			while(cury<y) {
				xputs(XD);
				cury++;
			}
		} else cmov(x,y);
	}
}

cmov(x,y)
register x,y;
{
	if(!CM) error("Tries to cmov from %d %d to %d %d\n",curx,cury,x,y);
	xputs(tgoto(CM,x-1,y-1));
	cury = y;
	curx = x;
}

xputc(c) char c; {
	(void) fputc(c,stdout);
}

xputs(s) char *s; {
	tputs(s, 1, xputc);
}

cl_end() {
	xputs(CE);
}

clear_screen() {
	xputs(CL);
	curx = cury = 1;
}

home()
{
	if(HO) xputs(HO);
	else xputs(tgoto(CM,0,0));
	curx = cury = 1;
}

standoutbeg()
{
	if(SO) xputs(SO);
}

standoutend()
{
	if(SE) xputs(SE);
}

backsp()
{
	xputs(BC);
	curx--;
}

bell()
{
	putsym('\007');
}

delay_output() {
	/* delay 40 ms - could also use a 'nap'-system call */
	tputs("40", 1, xputc);
}
//E*O*F hack.termcap.c//

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

#include	"hack.h"
#define	SIZE(x)	(sizeof(x) / sizeof(x[0]))

timeout(){
register struct prop *upp;
	for(upp = u.uprops; upp < u.uprops+SIZE(u.uprops); upp++)
	    if((upp->p_flgs & TIMEOUT) && !--upp->p_flgs) {
		if(upp->p_tofn) (*upp->p_tofn)();
		else switch(upp - u.uprops){
		case SICK:
			pline("You die because of food poisoning");
			killer = u.usick_cause;
			done("died");
			/* NOTREACHED */
		case FAST:
			pline("You feel yourself slowing down");
			break;
		case CONFUSION:
			pline("You feel less confused now");
			break;
		case BLIND:
			pline("You can see again");
			setsee();
			break;
		case INVIS:
			on_scr(u.ux,u.uy);
			pline("You are no longer invisible.");
		}
	}
}
//E*O*F hack.timeout.c//

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

#include "hack.h"
#include <stdio.h>
extern char *eos();
#define	TOPLSZ	(COLNO-8)	/* leave room for --More-- */
char toplines[BUFSZ];
xchar tlx, tly;			/* set by pline; used by addtopl */

struct topl {
	struct topl *next_topl;
	char *topl_text;
} *old_toplines, *last_redone_topl;
#define	OTLMAX	20		/* max nr of old toplines remembered */

doredotopl(){
	if(last_redone_topl)
		last_redone_topl = last_redone_topl->next_topl;
	if(!last_redone_topl)
		last_redone_topl = old_toplines;
	if(last_redone_topl){
		(void) strcpy(toplines, last_redone_topl->topl_text);
	}
	redotoplin();
	return(0);
}

redotoplin() {
	home();
	if(index(toplines, '\n')) cl_end();
	putstr(toplines);
	cl_end();
	tlx = curx;
	tly = cury;
	flags.topl = 1;
	if(tly > 1)
		more();
}

remember_topl() {
register struct topl *tl;
register int cnt = OTLMAX;
	if(last_redone_topl &&
	   !strcmp(toplines, last_redone_topl->topl_text)) return;
	if(old_toplines &&
	   !strcmp(toplines, old_toplines->topl_text)) return;
	last_redone_topl = 0;
	tl = (struct topl *)
		alloc((unsigned)(strlen(toplines) + sizeof(struct topl) + 1));
	tl->next_topl = old_toplines;
	tl->topl_text = (char *)(tl + 1);
	(void) strcpy(tl->topl_text, toplines);
	old_toplines = tl;
	while(cnt && tl){
		cnt--;
		tl = tl->next_topl;
	}
	if(tl && tl->next_topl){
		free((char *) tl->next_topl);
		tl->next_topl = 0;
	}
}

addtopl(s) char *s; {
	curs(tlx,tly);
	if(tlx + strlen(s) > COLNO) putsym('\n');
	putstr(s);
	tlx = curx;
	tly = cury;
	flags.topl = 1;
}

xmore(spaceflag)
boolean spaceflag;	/* TRUE if space required */
{
	if(flags.topl) {
		curs(tlx, tly);
		if(tlx + 8 > COLNO) putsym('\n'), tly++;
	}
	putstr("--More--");
	xwaitforspace(spaceflag);
	if(flags.topl && tly > 1) {
		home();
		cl_end();
		docorner(1, tly-1);
	}
	flags.topl = 0;
}

more(){
	xmore(TRUE);
}

cmore(){
	xmore(FALSE);
}

clrlin(){
	if(flags.topl) {
		home();
		cl_end();
		if(tly > 1) docorner(1, tly-1);
		remember_topl();
	}
	flags.topl = 0;
}

/*VARARGS1*/
pline(line,arg1,arg2,arg3,arg4,arg5,arg6)
register char *line,*arg1,*arg2,*arg3,*arg4,*arg5,*arg6;
{
	char pbuf[BUFSZ];
	register char *bp = pbuf, *tl;
	register int n,n0;

	if(!line || !*line) return;
	if(!index(line, '%')) (void) strcpy(pbuf,line); else
	(void) sprintf(pbuf,line,arg1,arg2,arg3,arg4,arg5,arg6);
	if(flags.topl == 1 && !strcmp(pbuf, toplines)) return;
	nscr();		/* %% */

	/* If there is room on the line, print message on same line */
	/* But messages like "You die..." deserve their own line */
	n0 = strlen(bp);
	if(flags.topl == 1 && tly == 1 &&
	    n0 + strlen(toplines) + 3 < TOPLSZ &&
	    strncmp(bp, "You ", 4)) {
		(void) strcat(toplines, "  ");
		(void) strcat(toplines, bp);
		tlx += 2;
		addtopl(bp);
		return;
	}
	if(flags.topl == 1) more();
	remember_topl();
	toplines[0] = 0;
	while(n0){
		if(n0 >= COLNO){
			/* look for appropriate cut point */
			n0 = 0;
			for(n = 0; n < COLNO; n++) if(bp[n] == ' ')
				n0 = n;
			if(!n0) for(n = 0; n < COLNO-1; n++)
				if(!letter(bp[n])) n0 = n;
			if(!n0) n0 = COLNO-2;
		}
		(void) strncpy((tl = eos(toplines)), bp, n0);
		tl[n0] = 0;
		bp += n0;

		/* remove trailing spaces, but leave one */
		while(n0 > 1 && tl[n0-1] == ' ' && tl[n0-2] == ' ')
			tl[--n0] = 0;

		n0 = strlen(bp);
		if(n0 && tl[0]) (void) strcat(tl, "\n");
	}
	redotoplin();
}

putsym(c) char c; {
	switch(c) {
	case '\b':
		backsp();
		return;
	case '\n':
		curx = 1;
		cury++;
		if(cury > tly) tly = cury;
		break;
	default:
		curx++;
		if(curx == COLNO) putsym('\n');
	}
	(void) putchar(c);
}

putstr(s) register char *s; {
	while(*s) putsym(*s++);
}
//E*O*F hack.topl.c//

exit 0



More information about the Comp.sources.unix mailing list