Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Hack sources (part 11 of 15)

8 views
Skip to first unread message

funhouse

unread,
Dec 17, 1984, 7:38:45 PM12/17/84
to
# 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

0 new messages