Amiga Hack Source (Part 7 of 13)
John A. Toebes, VIII
jcz at ncsu.UUCP
Sat Feb 22 01:11:55 AEST 1986
#file 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 int ct = ESHK->billct;
register struct bill_x *bp = bill;
total = 0;
while(ct--){
total += bp->price * bp->bquan;
bp++;
}
}
inshop(){
register int 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) myputs("\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
myputs(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 int 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){
long 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));
}
#file hack.stat.c
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
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);
}
#file 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 int 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 int tmp;
register int 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 int 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,'$');
}
}
#file 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.");
}
}
}
#file 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) myputchar(c);
}
putstr(s) register char *s; {
while(*s) putsym(*s++);
}
#file hack.track.c
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
#include "hack.h"
#ifdef TRACK
#define UTSZ 50
coord utrack[UTSZ];
int utcnt = 0;
int utpnt = 0;
initrack(){
utcnt = utpnt = 0;
}
/* add to track */
settrack(){
if(utcnt < UTSZ) utcnt++;
if(utpnt == UTSZ) utpnt = 0;
utrack[utpnt].x = u.ux;
utrack[utpnt].y = u.uy;
utpnt++;
}
coord *
gettrack(x,y) register int x,y; {
register int i,cnt;
coord tc;
cnt = utcnt;
for(i = utpnt-1; cnt--; i--){
if(i == -1) i = UTSZ-1;
tc = utrack[i];
if((x-tc.x)*(x-tc.x) + (y-tc.y)*(y-tc.y) < 3)
return(&(utrack[i]));
}
return(0);
}
#endif TRACK
#file hack.trap.c
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* hack.trap.c version 1.0.1 - added dotele(); */
#include "hack.h"
#include "def.trap.h"
extern struct monst *makemon();
char vowels[] = "aeiou";
char *traps[] = {
" bear trap",
"n arrow trap",
" dart trap",
" trapdoor",
" teleportation trap",
" pit",
" sleeping gas trap",
" piercer",
" mimic"
};
dotrap(trap) register struct gen *trap; {
nomul(0);
if(trap->gflag&SEEN && !rn2(5))
pline("You escape a%s.",traps[trap->gflag & TRAPTYPE]);
else {
trap->gflag |= SEEN;
switch(trap->gflag & TRAPTYPE) {
case SLP_GAS_TRAP:
pline("A cloud of gas puts you to sleep!");
nomul(-rnd(25));
break;
case BEAR_TRAP:
if(Levitation) {
pline("You float over a bear trap.");
break;
}
u.utrap = 4 + rn2(4);
u.utraptype = TT_BEARTRAP;
pline("A bear trap closes on your foot!");
break;
case PIERC:
deltrap(trap);
if(makemon(PM_PIERC,u.ux,u.uy)) {
pline("A piercer suddenly drops from the ceiling!");
if(uarmh)
pline("Its blow glances off your helmet.");
else
(void) thitu(3,d(4,6),"falling piercer");
}
break;
case ARROW_TRAP:
pline("An arrow shoots out at you!");
if(!thitu(8,rnd(6),"arrow")){
mksobj_at(WEAPON_SYM, ARROW, u.ux, u.uy);
fobj->quan = 1;
}
break;
case TRAPDOOR:
if(!xdnstair) {
pline("A trap door in the ceiling opens and a rock falls on your head!");
if(uarmh) pline("Fortunately, you are wearing a helmet!");
losehp(uarmh ? 2 : d(2,10),"falling rock");
} else {
register int newlevel = dlevel + 1;
while(!rn2(4) && newlevel < 29)
newlevel++;
pline("A trap door opens up under you!");
if(Levitation || u.ustuck) {
pline("For some reason you don't fall in.");
break;
}
goto_level(newlevel, FALSE);
}
break;
case DART_TRAP:
pline("A little dart shoots out at you!");
if(thitu(7,rnd(3),"little dart")) {
if(!rn2(6))
poisoned("dart","poison dart");
} else {
mksobj_at(WEAPON_SYM, DART, u.ux, u.uy);
fobj->quan = 1;
}
break;
case TELEP_TRAP:
if(trap->gflag & ONCE) {
deltrap(trap);
newsym(u.ux,u.uy);
vtele();
} else {
newsym(u.ux,u.uy);
tele();
}
break;
case PIT:
if(Levitation) {
pline("A pit opens up under you!");
pline("You don't fall in!");
break;
}
pline("You fall into a pit!");
u.utrap = rn1(6,2);
u.utraptype = TT_PIT;
losehp(rnd(6),"fall into a pit");
selftouch("Falling, you");
break;
default:
pline("You hit a trap of type %d",trap->gflag);
impossible();
}
}
}
mintrap(mtmp) register struct monst *mtmp; {
register struct gen *gen = g_at(mtmp->mx, mtmp->my, ftrap);
register int wasintrap = mtmp->mtrapped;
if(!gen) {
mtmp->mtrapped = 0; /* perhaps teleported? */
} else if(wasintrap) {
if(!rn2(40)) mtmp->mtrapped = 0;
} else {
register int tt = (gen->gflag & TRAPTYPE);
int in_sight = cansee(mtmp->mx,mtmp->my);
extern char mlarge[];
if(mtmp->mtrapseen & (1 << tt)) {
/* he has been in such a trap - perhaps he escapes */
if(rn2(4)) return(0);
}
mtmp->mtrapseen |= (1 << tt);
switch (tt) {
case BEAR_TRAP:
if(strchr(mlarge, mtmp->data->mlet)) {
if(in_sight)
pline("%s is caught in a bear trap!",
Monnam(mtmp));
else
if(mtmp->data->mlet == 'o')
pline("You hear the roaring of an angry bear!");
mtmp->mtrapped = 1;
}
break;
case PIT:
if(!strchr("Eyw", mtmp->data->mlet)) {
mtmp->mtrapped = 1;
if(in_sight)
pline("%s falls in a pit!", Monnam(mtmp));
}
break;
case SLP_GAS_TRAP:
if(!mtmp->msleep && !mtmp->mfroz) {
mtmp->msleep = 1;
if(in_sight)
pline("%s suddenly falls asleep!",
Monnam(mtmp));
}
break;
case TELEP_TRAP:
rloc(mtmp);
if(in_sight && !cansee(mtmp->mx,mtmp->my))
pline("%s suddenly disappears!",
Monnam(mtmp));
break;
case ARROW_TRAP:
if(in_sight) {
pline("%s is hit by an arrow!",
Monnam(mtmp));
}
mtmp->mhp -= 3;
break;
case DART_TRAP:
if(in_sight) {
pline("%s is hit by a dart!",
Monnam(mtmp));
}
mtmp->mhp -= 2;
/* not mondied here !! */
break;
case TRAPDOOR:
if(!xdnstair) {
mtmp->mhp -= 10;
if(in_sight)
pline("A trap door in the ceiling opens and a rock hits %s!", monnam(mtmp));
break;
}
if(mtmp->data->mlet != 'w'){
fall_down(mtmp);
if(in_sight)
pline("Suddenly, %s disappears out of sight.", monnam(mtmp));
return(2); /* no longer on this level */
}
break;
case PIERC:
break;
default:
pline("Some monster encountered an impossible trap.");
impossible();
}
}
return(mtmp->mtrapped);
}
selftouch(arg) char *arg; {
if(uwep && uwep->otyp == DEAD_COCKATRICE){
pline("%s touch the dead cockatrice.", arg);
pline("You turn to stone.");
killer = objects[uwep->otyp].oc_name;
done("died");
}
}
float_up(){
if(u.utrap) {
if(u.utraptype == TT_PIT) {
u.utrap = 0;
pline("You float up, out of the pit!");
} else {
pline("You float up, only your leg is still stuck.");
}
} else
pline("You start to float in the air!");
}
float_down(){
register struct gen *trap;
pline("You float gently to the ground.");
if(trap = g_at(u.ux,u.uy,ftrap))
switch(trap->gflag & TRAPTYPE) {
case PIERC:
break;
case TRAPDOOR:
if(!xdnstair || u.ustuck) break;
/* fall into next case */
default:
dotrap(trap);
}
pickup();
}
vtele() {
#define VAULT 6
register struct mkroom *croom;
for(croom = &rooms[0]; croom->hx >= 0; croom++)
if(croom->rtype == VAULT) {
register int x,y;
x = rn2(2) ? croom->lx : croom->hx;
y = rn2(2) ? croom->ly : croom->hy;
if(teleok(x,y)) {
teleds(x,y);
return;
}
}
tele();
}
tele() {
extern coord getpos();
coord cc;
register int nux,nuy;
if(Teleport_control) {
pline("To what position do you want to be teleported?");
cc = getpos(1, "the desired position"); /* 1: force valid */
/* possible extensions: introduce a small error if
magic power is low; allow transfer to solid rock */
if(teleok(cc.x, cc.y)){
teleds(cc.x, cc.y);
return;
}
pline("Sorry ...");
}
do {
nux = rnd(COLNO-1);
nuy = rn2(ROWNO);
} while(!teleok(nux, nuy));
teleds(nux, nuy);
}
teleds(nux, nuy)
register int nux,nuy;
{
if(Punished) unplacebc();
unsee();
u.utrap = 0;
u.ustuck = 0;
u.ux = nux;
u.uy = nuy;
setsee();
if(Punished) placebc(1);
if(u.uswallow){
u.uswldtim = u.uswallow = 0;
docrt();
}
nomul(0);
(void) inshop();
pickup();
if(!Blind) read_engr_at(u.ux,u.uy);
}
teleok(x,y) register int x,y; {
return( isok(x,y) && levl[x][y].typ > DOOR && !m_at(x,y) &&
!sobj_at(ENORMOUS_ROCK,x,y) && !g_at(x,y,ftrap)
);
/* Note: gold is permitted (because of vaults) */
}
dotele() {
extern char pl_character[];
if(
#ifdef WIZARD
!wizard &&
#endif WIZARD
(!Teleportation || u.ulevel < 6 ||
(pl_character[0] != 'W' && u.ulevel < 10))) {
pline("You are not able to teleport at will.");
return(0);
}
if(u.uhunger <= 100 || u.ustr < 6) {
pline("You miss the strength for a teleport spell.");
return(1);
}
tele();
morehungry(100);
return(1);
}
placebc(attach) int attach; {
if(!uchain || !uball){
pline("Where are your chain and ball??");
impossible();
return;
}
uball->ox = uchain->ox = u.ux;
uball->oy = uchain->oy = u.uy;
if(attach){
uchain->nobj = fobj;
fobj = uchain;
if(!carried(uball)){
uball->nobj = fobj;
fobj = uball;
}
}
}
unplacebc(){
if(!carried(uball)){
freeobj(uball);
unpobj(uball);
}
freeobj(uchain);
unpobj(uchain);
}
level_tele() {
register int newlevel = 5 + rn2(20); /* 5 - 24 */
if(dlevel == newlevel)
if(!xdnstair) newlevel--; else newlevel++;
goto_level(newlevel, FALSE);
}
#file hack.tty.c
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
#include "hack.h"
#include <stdio.h>
char inchar();
gettty(){
}
/* reset terminal to original state */
settty(s) char *s; {
clear_screen();
if(s) myprintf(s);
(void) myfflush(stdout);
flags.echo = OFF;
flags.cbreak = OFF;
}
setctty(){
}
setftty(){
}
echo(n)
register int n;
{
}
/* always want to expand tabs, or to send a clear line char before
printing something on topline */
xtabs()
{
}
#ifdef LONG_CMD
cbreak(n)
register int n;
{
}
#endif LONG_CMD
getlin(bufp)
register char *bufp;
{
register char *obufp = bufp;
register int c;
flags.topl = 2; /* nonempty, no --More-- required */
for(;;) {
(void) myfflush(stdout);
c = inchar();
if(c == '\b') {
if(bufp != obufp) {
bufp--;
putstr("\b \b"); /* putsym converts \b */
} else bell();
} else if(c == '\n') {
*bufp = 0;
return;
} else {
*bufp = c;
bufp[1] = 0;
putstr(bufp);
if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
bufp++;
}
}
}
getret() {
xgetret(TRUE);
}
cgetret() {
xgetret(FALSE);
}
xgetret(spaceflag)
boolean spaceflag; /* TRUE if space (return) required */
{
myprintf("\nHit %s to continue: ",
flags.cbreak ? "space" : "return");
xwaitforspace(spaceflag);
}
char morc; /* tell the outside world what char he used */
xwaitforspace(spaceflag)
boolean spaceflag;
{
register int c;
(void) myfflush(stdout);
morc = 0;
while((c = inchar()) != '\n')
{
if (flags.cbreak)
{
if (c == ' ')
break;
if (!spaceflag && letter(c))
{
morc = c;
break;
}
}
}
}
char *
parse()
{
static char inline[COLNO];
register int foo;
flags.move = 1;
if(!Invis) curs(u.ux,u.uy+2); else home();
(void) myfflush(stdout);
while((foo = inchar()) >= '0' && foo <= '9')
multi += 10*multi+foo-'0';
if(multi) {
multi--;
save_cm = inline;
}
inline[0] = foo;
inline[1] = 0;
if(foo == 'f' || foo == 'F'){
inline[1] = inchar();
#ifdef QUEST
if(inline[1] == foo) inline[2] = inchar(); else
#endif QUEST
inline[2] = 0;
}
if(foo == 'm' || foo == 'M'){
inline[1] = inchar();
inline[2] = 0;
}
clrlin();
return(inline);
}
char
readchar() {
register int sym;
(void) myfflush(stdout);
sym = inchar();
if(flags.topl == 1) flags.topl = 2;
return((char) sym);
}
More information about the Comp.sources.unix
mailing list