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

Hack 1.0.2 - part 9 of 10

0 views
Skip to first unread message

Andries Brouwer

unread,
Apr 12, 1985, 10:11:53 AM4/12/85
to

# 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.u_init.c hack.unix.c hack.vault.c hack.version.c hack.wield.c hack.worm.c hack.worn.c hack.zap.c

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

#include "hack.h"
#include <stdio.h>
#include <signal.h>
#define Strcpy (void) strcpy
#define Strcat (void) strcat
#define UNDEF_TYP 0
#define UNDEF_SPE '\177'
extern struct obj *addinv();
extern char *eos();
extern char plname[];
extern boolean female;

struct you zerou;
char pl_character[PL_CSIZ];
char *(roles[]) = { /* must all have distinct first letter */
/* roles[4] may be changed to -man */
"Tourist", "Speleologist", "Fighter", "Knight",
"Cave-man", "Wizard"
};
#define NR_OF_ROLES SIZE(roles)
char rolesyms[NR_OF_ROLES + 1]; /* filled by u_init() */

struct trobj {
uchar trotyp;
schar trspe;
char trolet;
Bitfield(trquan,6);
Bitfield(trknown,1);
};

#ifdef WIZARD
struct trobj Extra_objs[] = {
{ 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 }
};
#endif WIZARD

struct trobj Cave_man[] = {
{ MACE, 1, WEAPON_SYM, 1, 1 },
{ BOW, 1, WEAPON_SYM, 1, 1 },
{ ARROW, 0, WEAPON_SYM, 25, 1 }, /* quan is variable */
{ LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1 },
{ 0, 0, 0, 0, 0}
};

struct trobj Fighter[] = {
{ TWO_HANDED_SWORD, 0, WEAPON_SYM, 1, 1 },
{ RING_MAIL, 0, ARMOR_SYM, 1, 1 },
{ 0, 0, 0, 0, 0 }
};

struct trobj Knight[] = {
{ LONG_SWORD, 0, WEAPON_SYM, 1, 1 },
{ SPEAR, 2, WEAPON_SYM, 1, 1 },
{ RING_MAIL, 1, ARMOR_SYM, 1, 1 },
{ HELMET, 0, ARMOR_SYM, 1, 1 },
{ SHIELD, 0, ARMOR_SYM, 1, 1 },
{ PAIR_OF_GLOVES, 0, ARMOR_SYM, 1, 1 },
{ 0, 0, 0, 0, 0 }
};

struct trobj Speleologist[] = {
{ STUDDED_LEATHER_ARMOR, 0, ARMOR_SYM, 1, 1 },
{ UNDEF_TYP, 0, POTION_SYM, 2, 0 },
{ FOOD_RATION, 0, FOOD_SYM, 3, 1 },
{ PICK_AXE, UNDEF_SPE, TOOL_SYM, 1, 0 },
{ ICE_BOX, 0, TOOL_SYM, 1, 0 },
{ 0, 0, 0, 0, 0}
};

struct trobj Tinopener[] = {
{ CAN_OPENER, 0, TOOL_SYM, 1, 1 },
{ 0, 0, 0, 0, 0 }
};

struct trobj Tourist[] = {
{ UNDEF_TYP, 0, FOOD_SYM, 10, 1 },
{ POT_EXTRA_HEALING, 0, POTION_SYM, 2, 0 },
{ EXPENSIVE_CAMERA, 0, TOOL_SYM, 1, 1 },
{ DART, 2, WEAPON_SYM, 25, 1 }, /* quan is variable */
{ 0, 0, 0, 0, 0 }
};

struct trobj Wizard[] = {
{ ELVEN_CLOAK, 0, ARMOR_SYM, 1, 1 },
{ UNDEF_TYP, UNDEF_SPE, WAND_SYM, 2, 0 },
{ UNDEF_TYP, UNDEF_SPE, RING_SYM, 2, 0 },
{ UNDEF_TYP, UNDEF_SPE, POTION_SYM, 2, 0 },
{ UNDEF_TYP, UNDEF_SPE, SCROLL_SYM, 3, 0 },
{ 0, 0, 0, 0, 0 }
};

u_init(){
register int i;
char exper = 'y', pc;
extern char readchar();
if(female) /* should have been set in HACKOPTIONS */
roles[4] = "Cave-woman";
for(i = 0; i < NR_OF_ROLES; i++)
rolesyms[i] = roles[i][0];
rolesyms[i] = 0;

if(pc = pl_character[0]) {
if('a' <= pc && pc <= 'z') pc += 'A'-'a';
if((i = role_index(pc)) >= 0)
goto got_suffix; /* implies experienced */
printf("\nUnknown role: %c\n", pc);
pl_character[0] = pc = 0;
}

printf("\nAre you an experienced player? [ny] ");

while(!index("ynYN \n\004", (exper = readchar())))
bell();
if(exper == '\004') /* Give him an opportunity to get out */
end_of_input();
printf("%c\n", exper); /* echo */
if(index("Nn \n", exper)) {
exper = 0;
goto beginner;
}

printf("\nTell me what kind of character you are:\n");
printf("Are you");
for(i = 0; i < NR_OF_ROLES; i++) {
printf(" a %s", roles[i]);
if(i == 2) /* %% */
printf(",\n\t");
else if(i < NR_OF_ROLES - 2)
printf(",");
else if(i == NR_OF_ROLES - 2)
printf(" or");
}
printf("? [%s] ", rolesyms);

while(pc = readchar()) {
if('a' <= pc && pc <= 'z') pc += 'A'-'a';
if((i = role_index(pc)) >= 0) {
printf("%c\n", pc); /* echo */
(void) fflush(stdout); /* should be seen */
break;
}
if(pc == '\n')
break;
if(pc == '\004') /* Give him the opportunity to get out */
end_of_input();
bell();
}
if(pc == '\n')
pc = 0;

beginner:
if(!pc) {
printf("\nI'll choose a character for you.\n");
i = rn2(NR_OF_ROLES);
pc = rolesyms[i];
printf("This game you will be a%s %s.\n",
exper ? "n experienced" : "",
roles[i]);
getret();
/* give him some feedback in case mklev takes much time */
(void) putchar('\n');
(void) fflush(stdout);
}
if(exper) {
roles[i][0] = pc;
}

got_suffix:

(void) strncpy(pl_character, roles[i], PL_CSIZ-1);
pl_character[PL_CSIZ-1] = 0;
flags.beginner = 1;
u = zerou;
u.usym = '@';
u.ulevel = 1;
init_uhunger();
#ifdef QUEST
u.uhorizon = 6;
#endif QUEST
uarm = uarm2 = uarmh = uarms = uarmg = uwep = uball = uchain =
uleft = uright = 0;

switch(pc) {
case 'c':
case 'C':
Cave_man[2].trquan = 12 + rnd(9)*rnd(9);
u.uhp = u.uhpmax = 16;
u.ustr = u.ustrmax = 18;
ini_inv(Cave_man);
break;
case 't':
case 'T':
Tourist[3].trquan = 20 + rnd(20);
u.ugold = u.ugold0 = rnd(1000);
u.uhp = u.uhpmax = 10;
u.ustr = u.ustrmax = 8;
ini_inv(Tourist);
if(!rn2(25)) ini_inv(Tinopener);
break;
case 'w':
case 'W':
for(i=1; i<=4; i++) if(!rn2(5))
Wizard[i].trquan += rn2(3) - 1;
u.uhp = u.uhpmax = 15;
u.ustr = u.ustrmax = 16;
ini_inv(Wizard);
break;
case 's':
case 'S':
Fast = INTRINSIC;
Stealth = INTRINSIC;
u.uhp = u.uhpmax = 12;
u.ustr = u.ustrmax = 10;
ini_inv(Speleologist);
if(!rn2(10)) ini_inv(Tinopener);
break;
case 'k':
case 'K':
u.uhp = u.uhpmax = 12;
u.ustr = u.ustrmax = 10;
ini_inv(Knight);
break;
case 'f':
case 'F':
u.uhp = u.uhpmax = 14;
u.ustr = u.ustrmax = 17;
ini_inv(Fighter);
break;
default: /* impossible */
u.uhp = u.uhpmax = 12;
u.ustr = u.ustrmax = 16;
}
find_ac();
if(!rn2(20)) {
register int d = rn2(7) - 2; /* biased variation */
u.ustr += d;
u.ustrmax += d;
}

#ifdef WIZARD
if(wizard) wiz_inv();
#endif WIZARD

/* make sure he can carry all he has - especially for T's */
while(inv_weight() > 0 && u.ustr < 118)
u.ustr++, u.ustrmax++;
}

ini_inv(trop) register struct trobj *trop; {
register struct obj *obj;
extern struct obj *mkobj();
while(trop->trolet) {
obj = mkobj(trop->trolet);
obj->known = trop->trknown;
/* not obj->dknown = 1; - let him look at it at least once */
obj->cursed = 0;
if(obj->olet == WEAPON_SYM){
obj->quan = trop->trquan;
trop->trquan = 1;
}
if(trop->trspe != UNDEF_SPE)
obj->spe = trop->trspe;
if(trop->trotyp != UNDEF_TYP)
obj->otyp = trop->trotyp;
else
if(obj->otyp == WAN_WISHING) /* gitpyr!robert */
obj->otyp = WAN_DEATH;
obj->owt = weight(obj); /* defined after setting otyp+quan */
obj = addinv(obj);
if(obj->olet == ARMOR_SYM){
switch(obj->otyp){
case SHIELD:
if(!uarms) setworn(obj, W_ARMS);
break;
case HELMET:
if(!uarmh) setworn(obj, W_ARMH);
break;
case PAIR_OF_GLOVES:
if(!uarmg) setworn(obj, W_ARMG);
break;
case ELVEN_CLOAK:
if(!uarm2)
setworn(obj, W_ARM);
break;
default:
if(!uarm) setworn(obj, W_ARM);
}
}
if(obj->olet == WEAPON_SYM)
if(!uwep) setuwep(obj);
if(--trop->trquan) continue; /* make a similar object */
trop++;
}
}

#ifdef WIZARD
wiz_inv(){
register struct trobj *trop = &Extra_objs[0];
extern char *getenv();
register char *ep = getenv("INVENT");
register int type;
while(ep && *ep) {
type = atoi(ep);
ep = index(ep, ',');
if(ep) while(*ep == ',' || *ep == ' ') ep++;
if(type <= 0 || type > NROFOBJECTS) continue;
trop->trotyp = type;
trop->trolet = objects[type].oc_olet;
trop->trspe = 4;
trop->trknown = 1;
trop->trquan = 1;
ini_inv(trop);
}
/* give him a wand of wishing by default */
trop->trotyp = WAN_WISHING;
trop->trolet = WAND_SYM;
trop->trspe = 20;
trop->trknown = 1;
trop->trquan = 1;
ini_inv(trop);
}
#endif WIZARD

plnamesuffix() {
register char *p;
if(p = rindex(plname, '-')) {
*p = 0;
pl_character[0] = p[1];
pl_character[1] = 0;
if(!plname[0]) {
askname();
plnamesuffix();
}
}
}

role_index(pc)
char pc;
{ /* must be called only from u_init() */
/* so that rolesyms[] is defined */
register char *cp;

if(cp = index(rolesyms, pc))
return(cp - rolesyms);
return(-1);
}
//E*O*F hack.u_init.c//

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

/* This file collects some Unix dependencies; hack.pager.c contains some more */

/*
* The time is used for:
* - seed for rand()
* - year on tombstone and yymmdd in record file
* - phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
* - night and midnight (the undead are dangerous at midnight)
* - determination of what files are "very old"
*/

#include "hack.h" /* mainly for index() which depends on BSD */

#include <sys/types.h> /* for time_t and stat */
#include <sys/stat.h>
#ifdef BSD
#include <sys/time.h>
#else
#include <time.h>
#endif BSD

extern char *getenv();
extern time_t time();

setrandom()
{
(void) srand((int) time ((time_t *) 0));
}

struct tm *
getlt()
{
time_t date;
struct tm *localtime();

(void) time(&date);
return(localtime(&date));
}

getyear()
{
return(1900 + getlt()->tm_year);
}

char *
getdate()
{
static char datestr[7];
register struct tm *lt = getlt();

(void) sprintf(datestr, "%2d%2d%2d",
lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
if(datestr[2] == ' ') datestr[2] = '0';
if(datestr[4] == ' ') datestr[4] = '0';
return(datestr);
}

static int day_in_year[] = { /* days in year for each month */
-1, 30, 58, 89, 119, 150, 180, 211, 241, 272, 303, 333
}; /* note: Jan. 1 will equal zero */

phase_of_the_moon() /* 0-7, with 0: new, 4: full */
{ /* moon period: 29.5306 days */
/* year: 365.2422 days */
register struct tm *lt = getlt();
register int epact, diy, golden;

diy = lt->tm_mday + day_in_year[lt->tm_mon];
if ((lt->tm_mon > 1) && (lt->tm_year % 4 == 0))
diy++;
golden = (lt->tm_year % 19) + 1;
epact = (11 * golden + 18) % 30;
if ((epact == 25 && golden > 11) || epact == 24)
epact++;

return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 );
}

night()
{
register int hour = getlt()->tm_hour;

return(hour < 6 || hour > 21);
}

midnight()
{
return(getlt()->tm_hour == 0);
}

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 of saved level? ");
return(0);
}
if(buf.st_ctime < hbuf.st_ctime) {
pline("Saved level is out of date. ");
return(0);
}
return(1);
}

/* see whether we should throw away all xlock files */
veryold(fd) {
register int i;
time_t date;

if(fstat(fd, &buf)) return(0); /* cannot get status */
if(buf.st_size != sizeof(int)) return(0); /* not an xlock file */
(void) time(&date);
if(date - buf.st_ctime < 3L*24L*60L*60L) return(0); /* recent */
(void) close(fd);
for(i=1; i<30; i++) { /* try to remove all */
glo(i);
(void) unlink(lock);
}
glo(0);
if(unlink(lock)) return(0); /* cannot remove it */
return(1); /* success! */
}

#ifdef MAIL

/*
* Notify user when new mail has arrived. [Idea from Merlyn Leroy, but
* I don't know the details of his implementation.]
* { Later note: he disliked my calling a general mailreader and felt that
* hack should do the paging itself. But when I get mail, I want to put it
* in some folder, reply, etc. - it would be unreasonable to put all these
* functions in hack. }
* The mail daemon '2' is at present not a real monster, but only a visual
* effect. Thus, makemon() is superfluous. This might become otherwise,
* however. The motion of '2' is less restrained than usual: diagonal moves
* from a DOOR are possible. He might also use SDOOR's. Also, '2' is visible
* in a ROOM, even when you are Blind.
* Its path should be longer when you are Telepat-hic and Blind.
*
* Interesting side effects:
* - You can get rich by sending yourself a lot of mail and selling
* it to the shopkeeper. Unfortunately mail isn't very valuable.
* - You might die in case '2' comes along at a critical moment during
* a fight and delivers a scroll the weight of which causes you to
* collapse.
*
* Possible extensions:
* - Open the file MAIL and do fstat instead of stat for efficiency.
* (But sh uses stat, so this cannot be too bad.)
* - Examine the mail and produce a scroll of mail called "From somebody".
* - Invoke MAILREADER in such a way that only this single letter is read.
*
* - Make him lose his mail when a Nymph steals the letter.
* - Do something to the text when the scroll is enchanted or cancelled.
*/
#include "def.mkroom.h"
static struct stat omstat,nmstat;
static char *mailbox;
static long laststattime;

getmailstatus() {
if(!(mailbox = getenv("MAIL")))
return;
if(stat(mailbox, &omstat)){
#ifdef PERMANENT_MAILBOX
pline("Cannot get status of MAIL=%s .", mailbox);
mailbox = 0;
#else
omstat.st_ctime = 0;
#endif PERMANENT_MAILBOX
}
}

ckmailstatus() {
if(!mailbox
#ifdef MAILCKFREQ
|| moves < laststattime + MAILCKFREQ
#endif MAILCKFREQ
)
return;
laststattime = moves;
if(stat(mailbox, &nmstat)){
#ifdef PERMANENT_MAILBOX
pline("Cannot get status of MAIL=%s anymore.", mailbox);
mailbox = 0;
#else
nmstat.st_ctime = 0;
#endif PERMANENT_MAILBOX
} else if(nmstat.st_ctime > omstat.st_ctime) {
if(nmstat.st_size)
newmail();
getmailstatus(); /* might be too late ... */
}
}

newmail() {
/* produce a scroll of mail */
register struct obj *obj;
register struct monst *md;
extern char plname[];
extern struct obj *mksobj(), *addinv();
extern struct monst *makemon();
extern struct permonst pm_mail_daemon;

obj = mksobj(SCR_MAIL);
if(md = makemon(&pm_mail_daemon, u.ux, u.uy)) /* always succeeds */
mdrush(md,0);

pline("\"Hello, %s! I have some mail for you.\"", plname);
if(md) {
if(dist(md->mx,md->my) > 2)
pline("\"Catch!\"");
more();

/* let him disappear again */
mdrush(md,1);
mondead(md);
}

obj = addinv(obj);
(void) identify(obj); /* set known and do prinv() */
}

/* make md run through the cave */
mdrush(md,away)
register struct monst *md;
boolean away;
{
register int uroom = inroom(u.ux, u.uy);
if(uroom >= 0) {
register int tmp = rooms[uroom].fdoor;
register int cnt = rooms[uroom].doorct;
register int fx = u.ux, fy = u.uy;
while(cnt--) {
if(dist(fx,fy) < dist(doors[tmp].x, doors[tmp].y)){
fx = doors[tmp].x;
fy = doors[tmp].y;
}
tmp++;
}
tmp_at(-1, md->data->mlet); /* open call */
if(away) { /* interchange origin and destination */
unpmon(md);
tmp = fx; fx = md->mx; md->mx = tmp;
tmp = fy; fy = md->my; md->my = tmp;
}
while(fx != md->mx || fy != md->my) {
register int dx,dy,nfx = fx,nfy = fy,d1,d2;

tmp_at(fx,fy);
d1 = DIST(fx,fy,md->mx,md->my);
for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++)
if(dx || dy) {
d2 = DIST(fx+dx,fy+dy,md->mx,md->my);
if(d2 < d1) {
d1 = d2;
nfx = fx+dx;
nfy = fy+dy;
}
}
if(nfx != fx || nfy != fy) {
fx = nfx;
fy = nfy;
} else {
if(!away) {
md->mx = fx;
md->my = fy;
}
break;
}
}
tmp_at(-1,-1); /* close call */
}
if(!away)
pmon(md);
}

readmail() {
#ifdef DEF_MAILREADER /* This implies that UNIX is defined */
register char *mr = 0;
more();
if(!(mr = getenv("MAILREADER")))
mr = DEF_MAILREADER;
if(child(1)){
execl(mr, mr, (char *) 0);
exit(1);
}
#else DEF_MAILREADER
(void) page_file(mailbox, FALSE);
#endif DEF_MAILREADER
/* get new stat; not entirely correct: there is a small time
window where we do not see new mail */
getmailstatus();
}
#endif MAIL
//E*O*F hack.unix.c//

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

#include "hack.h"
#ifdef QUEST
setgd(/* mtmp */) /* struct monst *mtmp; */ {}
gd_move() { return(2); }
gddead(mtmp) struct monst *mtmp; {}
replgd(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {}
invault(){}

#else


#include "def.mkroom.h"
extern struct monst *makemon();
#define FCSIZ (ROWNO+COLNO)
struct fakecorridor {
xchar fx,fy,ftyp;
};

struct egd {
int fcbeg, fcend; /* fcend: first unused pos */
xchar gdx, gdy; /* goal of guard's walk */
unsigned gddone:1;
struct fakecorridor fakecorr[FCSIZ];
};

static struct permonst pm_guard =
{ "guard", '@', 12, 12, -1, 4, 10, sizeof(struct egd) };

static struct monst *guard;
static int gdlevel;
#define EGD ((struct egd *)(&(guard->mextra[0])))

static
restfakecorr()
{
register fcx,fcy,fcbeg;
register struct rm *crm;

while((fcbeg = EGD->fcbeg) < EGD->fcend) {
fcx = EGD->fakecorr[fcbeg].fx;
fcy = EGD->fakecorr[fcbeg].fy;
if((u.ux == fcx && u.uy == fcy) || cansee(fcx,fcy) ||
m_at(fcx,fcy))
return;
crm = &levl[fcx][fcy];
crm->typ = EGD->fakecorr[fcbeg].ftyp;
if(!crm->typ) crm->seen = 0;
newsym(fcx,fcy);
EGD->fcbeg++;
}
/* it seems he left the corridor - let the guard disappear */
mondead(guard);
guard = 0;
}

static
goldincorridor()
{
register int fci;

for(fci = EGD->fcbeg; fci < EGD->fcend; fci++)
if(g_at(EGD->fakecorr[fci].fx, EGD->fakecorr[fci].fy))
return(1);
return(0);
}

setgd(){
register struct monst *mtmp;
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->isgd){
guard = mtmp;
gdlevel = dlevel;
return;
}
guard = 0;
}

invault(){
register tmp = inroom(u.ux, u.uy);
if(tmp < 0 || rooms[tmp].rtype != VAULT) {
u.uinvault = 0;
return;
}
if(++u.uinvault % 50 == 0 && (!guard || gdlevel != dlevel)) {
char buf[BUFSZ];
register x,y,dd,gx,gy;

/* first find the goal for the guard */
for(dd = 1; (dd < ROWNO || dd < COLNO); dd++) {
for(y = u.uy-dd; y <= u.uy+dd; y++) {
if(y < 0 || y > ROWNO-1) continue;
for(x = u.ux-dd; x <= u.ux+dd; x++) {
if(y != u.uy-dd && y != u.uy+dd && x != u.ux-dd)
x = u.ux+dd;
if(x < 0 || x > COLNO-1) continue;
if(levl[x][y].typ == CORR) goto fnd;
}
}
}
impossible("Not a single corridor on this level??");
tele();
return;
fnd:
gx = x; gy = y;

/* next find a good place for a door in the wall */
x = u.ux; y = u.uy;
while(levl[x][y].typ == ROOM) {
register int dx,dy;

dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
if(abs(gx-x) >= abs(gy-y))
x += dx;
else
y += dy;
}

/* make something interesting happen */
if(!(guard = makemon(&pm_guard,x,y))) return;
guard->isgd = guard->mpeaceful = 1;
EGD->gddone = 0;
gdlevel = dlevel;
if(!cansee(guard->mx, guard->my)) {
mondead(guard);
guard = 0;
return;
}

pline("Suddenly one of the Vault's guards enters!");
pmon(guard);
pline("\"Hello stranger, who are you?\" - ");
getlin(buf);

if(!strcmp(buf, "Croesus") || !strcmp(buf, "Kroisos")) {
pline("\"Oh, yes - of course. Sorry to have disturbed you.\"");
mondead(guard);
guard = 0;
return;
}
clrlin();
pline("\"I don't know you.\"");
if(!u.ugold)
pline("\"Please follow me.\"");
else {
pline("\"Most likely all that gold was stolen from this vault.\"");
pline("\"Please drop your gold (say d$ ) and follow me.\"");
}
EGD->gdx = gx;
EGD->gdy = gy;
EGD->fcbeg = 0;
EGD->fakecorr[0].fx = x;
EGD->fakecorr[0].fy = y;
EGD->fakecorr[0].ftyp = levl[x][y].typ;
levl[x][y].typ = DOOR;
EGD->fcend = 1;
}
}

gd_move(){
register int x,y,dx,dy,gx,gy,nx,ny,typ;
register struct fakecorridor *fcp;
register struct rm *crm;
if(!guard || gdlevel != dlevel){
impossible("Where is the guard?");
return(2); /* died */
}
if(u.ugold || goldincorridor())
return(0); /* didnt move */
if(dist(guard->mx,guard->my) > 1 || EGD->gddone) {
restfakecorr();
return(0); /* didnt move */
}
x = guard->mx;
y = guard->my;
/* look around (hor & vert only) for accessible places */
for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) {
if(nx == x || ny == y) if(nx != x || ny != y)
if(isok(nx,ny))
if(!IS_WALL(typ = (crm = &levl[nx][ny])->typ) && typ != POOL) {
register int i;
for(i = EGD->fcbeg; i < EGD->fcend; i++)
if(EGD->fakecorr[i].fx == nx &&
EGD->fakecorr[i].fy == ny)
goto nextnxy;
if((i = inroom(nx,ny)) >= 0 && rooms[i].rtype == VAULT)
goto nextnxy;
/* seems we found a good place to leave him alone */
EGD->gddone = 1;
if(ACCESSIBLE(typ)) goto newpos;
crm->typ = (typ == SCORR) ? CORR : DOOR;
goto proceed;
}
nextnxy: ;
}
nx = x;
ny = y;
gx = EGD->gdx;
gy = EGD->gdy;
dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
if(abs(gx-x) >= abs(gy-y)) nx += dx; else ny += dy;

while((typ = (crm = &levl[nx][ny])->typ) != 0) {
/* in view of the above we must have IS_WALL(typ) or typ == POOL */
/* must be a wall here */
if(isok(nx+nx-x,ny+ny-y) && typ != POOL &&
ZAP_POS(levl[nx+nx-x][ny+ny-y].typ)){
crm->typ = DOOR;
goto proceed;
}
if(dy && nx != x) {
nx = x; ny = y+dy;
continue;
}
if(dx && ny != y) {
ny = y; nx = x+dx; dy = 0;
continue;
}
/* I don't like this, but ... */
crm->typ = DOOR;
goto proceed;
}
crm->typ = CORR;
proceed:
if(cansee(nx,ny)) {
mnewsym(nx,ny);
prl(nx,ny);
}
fcp = &(EGD->fakecorr[EGD->fcend]);
if(EGD->fcend++ == FCSIZ) panic("fakecorr overflow");
fcp->fx = nx;
fcp->fy = ny;
fcp->ftyp = typ;
newpos:
if(EGD->gddone) nx = ny = 0;
guard->mx = nx;
guard->my = ny;
pmon(guard);
restfakecorr();
return(1);
}

gddead(){
guard = 0;
}

replgd(mtmp,mtmp2)
register struct monst *mtmp, *mtmp2;
{
if(mtmp == guard)
guard = mtmp2;
}

#endif QUEST
//E*O*F hack.vault.c//

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

#include "date.h"

doversion(){
pline("%s 1.0.2 - last edit %s.", (
#ifdef QUEST
"Quest"
#else
"Hack"
#endif QUEST
), datestring);
return(0);
}
//E*O*F hack.version.c//

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

#include "hack.h"
extern struct obj zeroobj;

setuwep(obj) register struct obj *obj; {
setworn(obj, W_WEP);
}

dowield()
{
register struct obj *wep;
register int res = 0;

multi = 0;
if(!(wep = getobj("#-)", "wield"))) /* nothing */;
else if(uwep == wep)
pline("You are already wielding that!");
else if(uwep && uwep->cursed)
pline("The %s welded to your hand!",
aobjnam(uwep, "are"));
else if(wep == &zeroobj) {
if(uwep == 0){
pline("You are already empty handed.");
} else {
setuwep((struct obj *) 0);
res++;
pline("You are empty handed.");
}
} else if(uarms && wep->otyp == TWO_HANDED_SWORD)
pline("You cannot wield a two-handed sword and wear a shield.");
else if(wep->owornmask & (W_ARMOR | W_RING))
pline("You cannot wield that!");
else {
setuwep(wep);
res++;
if(uwep->cursed) pline("The %s itself to your hand!",
aobjnam(uwep, "weld"));
else prinv(uwep);
}
return(res);
}

corrode_weapon(){
if(!uwep || uwep->olet != WEAPON_SYM) return; /* %% */
if(uwep->rustfree)
pline("Your %s not affected.", aobjnam(uwep, "are"));
else {
pline("Your %s!", aobjnam(uwep, "corrode"));
uwep->spe--;
}
}

chwepon(otmp,amount)
register struct obj *otmp;
register amount;
{
register char *color = (amount < 0) ? "black" : "green";
register char *time;
if(!uwep || uwep->olet != WEAPON_SYM) {
strange_feeling(otmp,
(amount > 0) ? "Your hands twitch."
: "Your hands itch.");
return(0);
}

if(uwep->otyp == WORM_TOOTH && amount > 0) {
uwep->otyp = CRYSKNIFE;
pline("Your weapon seems sharper now.");
uwep->cursed = 0;
return(1);
}

if(uwep->otyp == CRYSKNIFE && amount < 0) {
uwep->otyp = WORM_TOOTH;
pline("Your weapon looks duller now.");
return(1);
}

/* there is a (soft) upper limit to uwep->spe */
if(amount > 0 && uwep->spe > 5 && rn2(3)) {
pline("Your %s violently green for a while and then evaporate%s.",
aobjnam(uwep, "glow"), plur(uwep->quan));
useup(uwep);
return(1);
}
if(!rn2(6)) amount *= 2;
time = (amount*amount == 1) ? "moment" : "while";
pline("Your %s %s for a %s.",
aobjnam(uwep, "glow"), color, time);
uwep->spe += amount;
if(amount > 0) uwep->cursed = 0;
return(1);
}
//E*O*F hack.wield.c//

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

#include "hack.h"
#ifndef NOWORM
#include "def.wseg.h"

struct wseg *wsegs[32]; /* linked list, tail first */
struct wseg *wheads[32];
long wgrowtime[32];

getwn(mtmp) struct monst *mtmp; {
register tmp;
for(tmp=1; tmp<32; tmp++) if(!wsegs[tmp]) {
mtmp->wormno = tmp;
return(1);
}
return(0); /* level infested with worms */
}

/* called to initialize a worm unless cut in half */
initworm(mtmp) struct monst *mtmp; {
register struct wseg *wtmp;
register tmp = mtmp->wormno;
if(!tmp) return;
wheads[tmp] = wsegs[tmp] = wtmp = newseg();
wgrowtime[tmp] = 0;
wtmp->wx = mtmp->mx;
wtmp->wy = mtmp->my;
/* wtmp->wdispl = 0; */
wtmp->nseg = 0;
}

worm_move(mtmp) struct monst *mtmp; {
register struct wseg *wtmp, *whd;
register tmp = mtmp->wormno;
wtmp = newseg();
wtmp->wx = mtmp->mx;
wtmp->wy = mtmp->my;
wtmp->nseg = 0;
/* wtmp->wdispl = 0; */
(whd = wheads[tmp])->nseg = wtmp;
wheads[tmp] = wtmp;
if(cansee(whd->wx,whd->wy)){
unpmon(mtmp);
atl(whd->wx, whd->wy, '~');
whd->wdispl = 1;
} else whd->wdispl = 0;
if(wgrowtime[tmp] <= moves) {
if(!wgrowtime[tmp]) wgrowtime[tmp] = moves + rnd(5);
else wgrowtime[tmp] += 2+rnd(15);
mtmp->mhpmax += 3;
mtmp->mhp += 3;
return;
}
whd = wsegs[tmp];
wsegs[tmp] = whd->nseg;
remseg(whd);
}

worm_nomove(mtmp) register struct monst *mtmp; {
register tmp;
register struct wseg *wtmp;
tmp = mtmp->wormno;
wtmp = wsegs[tmp];
if(wtmp == wheads[tmp]) return;
if(wtmp == 0 || wtmp->nseg == 0) panic("worm_nomove?");
wsegs[tmp] = wtmp->nseg;
remseg(wtmp);
mtmp->mhp -= 3; /* mhpmax not changed ! */
}

wormdead(mtmp) register struct monst *mtmp; {
register tmp = mtmp->wormno;
register struct wseg *wtmp, *wtmp2;
if(!tmp) return;
mtmp->wormno = 0;
for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){
wtmp2 = wtmp->nseg;
remseg(wtmp);
}
wsegs[tmp] = 0;
}

wormhit(mtmp) register struct monst *mtmp; {
register tmp = mtmp->wormno;
register struct wseg *wtmp;
if(!tmp) return; /* worm without tail */
for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg)
(void) hitu(mtmp,1);
}

wormsee(tmp) register unsigned tmp; {
register struct wseg *wtmp = wsegs[tmp];
if(!wtmp) panic("wormsee: wtmp==0");
for(; wtmp->nseg; wtmp = wtmp->nseg)
if(!cansee(wtmp->wx,wtmp->wy) && wtmp->wdispl){
newsym(wtmp->wx, wtmp->wy);
wtmp->wdispl = 0;
}
}

pwseg(wtmp) register struct wseg *wtmp; {
if(!wtmp->wdispl){
atl(wtmp->wx, wtmp->wy, '~');
wtmp->wdispl = 1;
}
}

cutworm(mtmp,x,y,weptyp)
register struct monst *mtmp;
register xchar x,y;
register uchar weptyp; /* uwep->otyp or 0 */
{
register struct wseg *wtmp, *wtmp2;
register struct monst *mtmp2;
register tmp,tmp2;
if(mtmp->mx == x && mtmp->my == y) return; /* hit headon */

/* cutting goes best with axe or sword */
tmp = rnd(20);
if(weptyp == LONG_SWORD || weptyp == TWO_HANDED_SWORD ||
weptyp == AXE) tmp += 5;
if(tmp < 12) return;

/* if tail then worm just loses a tail segment */
tmp = mtmp->wormno;
wtmp = wsegs[tmp];
if(wtmp->wx == x && wtmp->wy == y){
wsegs[tmp] = wtmp->nseg;
remseg(wtmp);
return;
}

/* cut the worm in two halves */
mtmp2 = newmonst(0);
*mtmp2 = *mtmp;
mtmp2->mxlth = mtmp2->mnamelth = 0;

/* sometimes the tail end dies */
if(rn2(3) || !getwn(mtmp2)){
monfree(mtmp2);
tmp2 = 0;
} else {
tmp2 = mtmp2->wormno;
wsegs[tmp2] = wsegs[tmp];
wgrowtime[tmp2] = 0;
}
do {
if(wtmp->nseg->wx == x && wtmp->nseg->wy == y){
if(tmp2) wheads[tmp2] = wtmp;
wsegs[tmp] = wtmp->nseg->nseg;
remseg(wtmp->nseg);
wtmp->nseg = 0;
if(tmp2){
pline("You cut the worm in half.");
mtmp2->mhpmax = mtmp2->mhp =
d(mtmp2->data->mlevel, 8);
mtmp2->mx = wtmp->wx;
mtmp2->my = wtmp->wy;
mtmp2->nmon = fmon;
fmon = mtmp2;
pmon(mtmp2);
} else {
pline("You cut off part of the worm's tail.");
remseg(wtmp);
}
mtmp->mhp /= 2;
return;
}
wtmp2 = wtmp->nseg;
if(!tmp2) remseg(wtmp);
wtmp = wtmp2;
} while(wtmp->nseg);
panic("Cannot find worm segment");
}

remseg(wtmp) register struct wseg *wtmp; {
if(wtmp->wdispl)
newsym(wtmp->wx, wtmp->wy);
free((char *) wtmp);
}
#endif NOWORM
//E*O*F hack.worm.c//

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

#include "hack.h"

struct worn {
long w_mask;
struct obj **w_obj;
} worn[] = {
{ W_ARM, &uarm },
{ W_ARM2, &uarm2 },
{ W_ARMH, &uarmh },
{ W_ARMS, &uarms },
{ W_ARMG, &uarmg },
{ W_RINGL, &uleft },
{ W_RINGR, &uright },
{ W_WEP, &uwep },
{ W_BALL, &uball },
{ W_CHAIN, &uchain },
{ 0, 0 }
};

setworn(obj, mask)
register struct obj *obj;
long mask;
{
register struct worn *wp;
register struct obj *oobj;

for(wp = worn; wp->w_mask; wp++) if(wp->w_mask & mask) {
oobj = *(wp->w_obj);
if(oobj && !(oobj->owornmask & wp->w_mask))
impossible("Setworn: mask = %ld.", wp->w_mask);
if(oobj) oobj->owornmask &= ~wp->w_mask;
if(obj && oobj && wp->w_mask == W_ARM){
if(uarm2) {
impossible("Setworn: uarm2 set?");
} else
setworn(uarm, W_ARM2);
}
*(wp->w_obj) = obj;
if(obj) obj->owornmask |= wp->w_mask;
}
if(uarm2 && !uarm) {
uarm = uarm2;
uarm2 = 0;
uarm->owornmask ^= (W_ARM | W_ARM2);
}
}

/* called e.g. when obj is destroyed */
setnotworn(obj) register struct obj *obj; {
register struct worn *wp;

for(wp = worn; wp->w_mask; wp++)
if(obj == *(wp->w_obj)) {
*(wp->w_obj) = 0;
obj->owornmask &= ~wp->w_mask;
}
if(uarm2 && !uarm) {
uarm = uarm2;
uarm2 = 0;
uarm->owornmask ^= (W_ARM | W_ARM2);
}
}
//E*O*F hack.worn.c//

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

#include "hack.h"

extern struct obj *mkobj_at();
extern struct monst *makemon(), *mkmon_at(), youmonst;
struct monst *bhit();
char *exclam();

char *fl[]= {
"magic missile",
"bolt of fire",
"sleep ray",
"bolt of cold",
"death ray"
};

/* Routines for IMMEDIATE wands. */
/* bhitm: monster mtmp was hit by the effect of wand otmp */
bhitm(mtmp, otmp)
register struct monst *mtmp;
register struct obj *otmp;
{
wakeup(mtmp);
switch(otmp->otyp) {
case WAN_STRIKING:
if(u.uswallow || rnd(20) < 10+mtmp->data->ac) {
register int tmp = d(2,12);
hit("wand", mtmp, exclam(tmp));
mtmp->mhp -= tmp;
if(mtmp->mhp < 1) killed(mtmp);
} else miss("wand", mtmp);
break;
case WAN_SLOW_MONSTER:
mtmp->mspeed = MSLOW;
break;
case WAN_SPEED_MONSTER:
mtmp->mspeed = MFAST;
break;
case WAN_UNDEAD_TURNING:
if(index(UNDEAD,mtmp->data->mlet)) {
mtmp->mhp -= rnd(8);
if(mtmp->mhp < 1) killed(mtmp);
else mtmp->mflee = 1;
}
break;
case WAN_POLYMORPH:
if( newcham(mtmp,&mons[rn2(CMNUM)]) )
objects[otmp->otyp].oc_name_known = 1;
break;
case WAN_CANCELLATION:
mtmp->mcan = 1;
break;
case WAN_TELEPORTATION:
rloc(mtmp);
break;
case WAN_MAKE_INVISIBLE:
mtmp->minvis = 1;
break;
#ifdef WAN_PROBING
case WAN_PROBING:
mstatusline(mtmp);
break;
#endif WAN_PROBING
default:
impossible("What an interesting wand (%u)", otmp->otyp);
}
}

bhito(obj, otmp) /* object obj was hit by the effect of wand otmp */
register struct obj *obj, *otmp; /* returns TRUE if sth was done */
{
register int res = TRUE;

if(obj == uball || obj == uchain)
res = FALSE;
else
switch(otmp->otyp) {
case WAN_POLYMORPH:
/* preserve symbol and quantity, but turn rocks into gems */
mkobj_at((obj->otyp == ROCK || obj->otyp == ENORMOUS_ROCK)
? GEM_SYM : obj->olet,
obj->ox, obj->oy) -> quan = obj->quan;
delobj(obj);
break;
case WAN_STRIKING:
if(obj->otyp == ENORMOUS_ROCK)
fracture_rock(obj);
else
res = FALSE;
break;
case WAN_CANCELLATION:
if(obj->spe && obj->olet != AMULET_SYM) {
obj->known = 0;
obj->spe = 0;
}
break;
case WAN_TELEPORTATION:
rloco(obj);
break;
case WAN_MAKE_INVISIBLE:
obj->oinvis = 1;
break;
case WAN_UNDEAD_TURNING:
res = revive(obj);
break;
case WAN_SLOW_MONSTER: /* no effect on objects */
case WAN_SPEED_MONSTER:
#ifdef WAN_PROBING
case WAN_PROBING:
#endif WAN_PROBING
res = FALSE;
break;
default:
impossible("What an interesting wand (%u)", otmp->otyp);
}
return(res);
}

dozap()
{
register struct obj *obj;
xchar zx,zy;

obj = getobj("/", "zap");
if(!obj) return(0);
if(obj->spe < 0 || (obj->spe == 0 && rn2(121))) {
pline("Nothing Happens");
return(1);
}
if(obj->spe == 0)
pline("You wrest one more spell from the worn-out wand.");
if(!(objects[obj->otyp].bits & NODIR) && !getdir(1))
return(1); /* make him pay for knowing !NODIR */
obj->spe--;
if(objects[obj->otyp].bits & IMMEDIATE) {
if(u.uswallow)
bhitm(u.ustuck, obj);
else if(u.dz) {
if(u.dz > 0) {
register struct obj *otmp = o_at(u.ux, u.uy);
if(otmp)
(void) bhito(otmp, obj);
}
} else
(void) bhit(u.dx,u.dy,rn1(8,6),0,bhitm,bhito,obj);
} else {
switch(obj->otyp){
case WAN_LIGHT:
litroom(TRUE);
break;
case WAN_SECRET_DOOR_DETECTION:
if(!findit()) return(1);
break;
case WAN_CREATE_MONSTER:
{ register int cnt = 1;
if(!rn2(23)) cnt += rn2(7) + 1;
while(cnt--)
(void) makemon((struct permonst *) 0, u.ux, u.uy);
}
break;
case WAN_WISHING:
{ char buf[BUFSZ];
register struct obj *otmp;
extern struct obj *readobjnam(), *addinv();
if(u.uluck + rn2(5) < 0) {
pline("Unfortunately, nothing happens.");
break;
}
pline("You may wish for an object. What do you want? ");
getlin(buf);
otmp = readobjnam(buf);
otmp = addinv(otmp);
prinv(otmp);
break;
}
case WAN_DIGGING:
/* Original effect (approximately):
* from CORR: dig until we pierce a wall
* from ROOM: piece wall and dig until we reach
* an ACCESSIBLE place.
* Currently: dig for digdepth positions;
* also down on request of Lennart Augustsson.
*/
{ register struct rm *room;
register int digdepth;
if(u.uswallow) {
register struct monst *mtmp = u.ustuck;

pline("You pierce %s's stomach wall!",
monnam(mtmp));
mtmp->mhp = 1; /* almost dead */
unstuck(mtmp);
mnexto(mtmp);
break;
}
if(u.dz) {
if(u.dz < 0) {
pline("You loosen a rock from the ceiling.");
pline("It falls on your head!");
losehp(1, "falling rock");
} else {
dighole();
}
break;
}
zx = u.ux+u.dx;
zy = u.uy+u.dy;
digdepth = 8 + rn2(18);
Tmp_at(-1, '*'); /* open call */
while(--digdepth >= 0) {
if(!isok(zx,zy)) break;
room = &levl[zx][zy];
Tmp_at(zx,zy);
if(!xdnstair){
if(zx < 3 || zx > COLNO-3 ||
zy < 3 || zy > ROWNO-3)
break;
if(room->typ == HWALL ||
room->typ == VWALL){
room->typ = ROOM;
break;
}
} else
if(room->typ == HWALL || room->typ == VWALL ||
room->typ == SDOOR || room->typ == LDOOR){
room->typ = DOOR;
digdepth -= 2;
} else
if(room->typ == SCORR || !room->typ) {
room->typ = CORR;
digdepth--;
}
mnewsym(zx,zy);
zx += u.dx;
zy += u.dy;
}
mnewsym(zx,zy); /* not always necessary */
Tmp_at(-1,-1); /* closing call */
break;
}
default:
buzz((int) obj->otyp - WAN_MAGIC_MISSILE,
u.ux, u.uy, u.dx, u.dy);
break;
}
if(!objects[obj->otyp].oc_name_known) {
objects[obj->otyp].oc_name_known = 1;
more_experienced(0,10);
}
}
return(1);
}

char *
exclam(force)
register int force;
{
/* force == 0 occurs e.g. with sleep ray */
/* note that large force is usual with wands so that !! would
require information about hand/weapon/wand */
return( (force < 0) ? "?" : (force <= 4) ? "." : "!" );
}

hit(str,mtmp,force)
register char *str;
register struct monst *mtmp;
register char *force; /* usually either "." or "!" */
{
if(!cansee(mtmp->mx,mtmp->my)) pline("The %s hits it.", str);
else pline("The %s hits %s%s", str, monnam(mtmp), force);
}

miss(str,mtmp)
register char *str;
register struct monst *mtmp;
{
if(!cansee(mtmp->mx,mtmp->my)) pline("The %s misses it.",str);
else pline("The %s misses %s.",str,monnam(mtmp));
}

/* bhit: called when a weapon is thrown (sym = obj->olet) or when an
IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of
range or when a monster is hit; the monster is returned, and bhitpos
is set to the final position of the weapon thrown; the ray of a wand
may affect several objects and monsters on its path - for each of
these an argument function is called. */
/* check !u.uswallow before calling bhit() */

struct monst *
bhit(ddx,ddy,range,sym,fhitm,fhito,obj)
register int ddx,ddy,range; /* direction and range */
char sym; /* symbol displayed on path */
int (*fhitm)(), (*fhito)(); /* fns called when mon/obj hit */
struct obj *obj; /* 2nd arg to fhitm/fhito */
{
register struct monst *mtmp;
register struct obj *otmp;
register int typ;

bhitpos.x = u.ux;
bhitpos.y = u.uy;

if(sym) tmp_at(-1, sym); /* open call */
while(range-- > 0) {
bhitpos.x += ddx;
bhitpos.y += ddy;
typ = levl[bhitpos.x][bhitpos.y].typ;
if(mtmp = m_at(bhitpos.x,bhitpos.y)){
if(sym) {
tmp_at(-1, -1); /* close call */
return(mtmp);
}
(*fhitm)(mtmp, obj);
range -= 3;
}
if(fhito && (otmp = o_at(bhitpos.x,bhitpos.y))){
if((*fhito)(otmp, obj))
range--;
}
if(!ZAP_POS(typ)) {
bhitpos.x -= ddx;
bhitpos.y -= ddy;
break;
}
if(sym) tmp_at(bhitpos.x, bhitpos.y);
}

/* leave last symbol unless in a pool */
if(sym)
tmp_at(-1, (levl[bhitpos.x][bhitpos.y].typ == POOL) ? -1 : 0);
return(0);
}

struct monst *
boomhit(dx,dy) {
register int i, ct;
register struct monst *mtmp;
char sym = ')';
extern schar xdir[], ydir[];

bhitpos.x = u.ux;
bhitpos.y = u.uy;

for(i=0; i<8; i++) if(xdir[i] == dx && ydir[i] == dy) break;
tmp_at(-1, sym); /* open call */
for(ct=0; ct<10; ct++) {
if(i == 8) i = 0;
sym = ')' + '(' - sym;
tmp_at(-2, sym); /* change let call */
dx = xdir[i];
dy = ydir[i];
bhitpos.x += dx;
bhitpos.y += dy;
if(mtmp = m_at(bhitpos.x, bhitpos.y)){
tmp_at(-1,-1);
return(mtmp);
}
if(!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)) {
bhitpos.x -= dx;
bhitpos.y -= dy;
break;
}
if(bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
if(rn2(20) >= 10+u.ulevel){ /* we hit ourselves */
(void) thitu(10, rnd(10), "boomerang");
break;
} else { /* we catch it */
tmp_at(-1,-1);
pline("Skillfully, you catch the boomerang.");
return(&youmonst);
}
}
tmp_at(bhitpos.x, bhitpos.y);
if(ct % 5 != 0) i++;
}
tmp_at(-1, -1); /* do not leave last symbol */
return(0);
}

char
dirlet(dx,dy) register dx,dy; {
return
(dx == dy) ? '\\' : (dx && dy) ? '/' : dx ? '-' : '|';
}

/* type == -1: monster spitting fire at you */
/* type == -1,-2,-3: bolts sent out by wizard */
/* called with dx = dy = 0 with vertical bolts */
buzz(type,sx,sy,dx,dy)
register int type;
register xchar sx,sy;
register int dx,dy;
{
int abstype = abs(type);
register char *fltxt = (type == -1) ? "blaze of fire" : fl[abstype];
struct rm *lev;
xchar range;
struct monst *mon;

if(u.uswallow) {
register int tmp;

if(type < 0) return;
tmp = zhit(u.ustuck, type);
pline("The %s rips into %s%s",
fltxt, monnam(u.ustuck), exclam(tmp));
return;
}
if(type < 0) pru();
range = rn1(7,7);
Tmp_at(-1, dirlet(dx,dy)); /* open call */
while(range-- > 0) {
sx += dx;
sy += dy;
if((lev = &levl[sx][sy])->typ) Tmp_at(sx,sy);
else {
int bounce = 0;
if(cansee(sx-dx,sy-dy))
pline("The %s bounces!", fltxt);
if(ZAP_POS(levl[sx][sy-dy].typ))
bounce = 1;
if(ZAP_POS(levl[sx-dx][sy].typ)) {
if(!bounce || rn2(2)) bounce = 2;
}
switch(bounce){
case 0:
dx = -dx;
dy = -dy;
continue;
case 1:
dy = -dy;
sx -= dx;
break;
case 2:
dx = -dx;
sy -= dy;
break;
}
Tmp_at(-2,dirlet(dx,dy));
continue;
}
if(lev->typ == POOL && abstype == 1 /* fire */) {
range -= 3;
lev->typ = ROOM;
if(cansee(sx,sy)) {
mnewsym(sx,sy);
pline("The water evaporates.");
} else
pline("You hear a hissing sound.");
}
if((mon = m_at(sx,sy)) &&
(type != -1 || mon->data->mlet != 'D')) {
wakeup(mon);
if(rnd(20) < 18 + mon->data->ac) {
register int tmp = zhit(mon,abstype);
if(mon->mhp < 1) {
if(type < 0) {
if(cansee(mon->mx,mon->my))
pline("%s is killed by the %s!",
Monnam(mon), fltxt);
mondied(mon);
} else
killed(mon);
} else
hit(fltxt, mon, exclam(tmp));
range -= 2;
} else
miss(fltxt,mon);
} else if(sx == u.ux && sy == u.uy) {
nomul(0);
if(rnd(20) < 18+u.uac) {
register int dam = 0;
range -= 2;
pline("The %s hits you!",fltxt);
switch(abstype) {
case 0:
dam = d(2,6);
break;
case 1:
if(Fire_resistance)
pline("You don't feel hot!");
else dam = d(6,6);
break;
case 2:
nomul(-rnd(25)); /* sleep ray */
break;
case 3:
if(Cold_resistance)
pline("You don't feel cold!");
else dam = d(6,6);
break;
case 4:
u.uhp = -1;
}
losehp(dam,fltxt);
} else pline("The %s whizzes by you!",fltxt);
stop_occupation();
}
if(!ZAP_POS(lev->typ)) {
int bounce = 0, rmn;
if(cansee(sx,sy)) pline("The %s bounces!",fltxt);
range--;
if(!dx || !dy || !rn2(20)){
dx = -dx;
dy = -dy;
} else {
if(ZAP_POS(rmn = levl[sx][sy-dy].typ) &&
(IS_ROOM(rmn) || ZAP_POS(levl[sx+dx][sy-dy].typ)))
bounce = 1;
if(ZAP_POS(rmn = levl[sx-dx][sy].typ) &&
(IS_ROOM(rmn) || ZAP_POS(levl[sx-dx][sy+dy].typ)))
if(!bounce || rn2(2))
bounce = 2;

switch(bounce){
case 0:
dy = -dy;
dx = -dx;
break;
case 1:
dy = -dy;
break;
case 2:
dx = -dx;
break;
}
Tmp_at(-2, dirlet(dx,dy));
}
}
}
Tmp_at(-1,-1);
}

zhit(mon,type) /* returns damage to mon */
register struct monst *mon;
register type;
{
register int tmp = 0;

switch(type) {
case 0: /* magic missile */
tmp = d(2,6);
break;
case -1: /* Dragon blazing fire */
case 1: /* fire */
if(index("Dg", mon->data->mlet)) break;
tmp = d(6,6);
if(index("YF", mon->data->mlet)) tmp += 7;
break;
case 2: /* sleep*/
mon->mfroz = 1;
break;
case 3: /* cold */
if(index("YFgf", mon->data->mlet)) break;
tmp = d(6,6);
if(mon->data->mlet == 'D') tmp += 7;
break;
case 4: /* death*/
if(index(UNDEAD, mon->data->mlet)) break;
tmp = mon->mhp+1;
break;
}
mon->mhp -= tmp;
return(tmp);
}

#define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\
? 'a' + (otyp - DEAD_ACID_BLOB)\
: '@' + (otyp - DEAD_HUMAN))
revive(obj)
register struct obj *obj;
{
register struct monst *mtmp;

if(obj->olet == FOOD_SYM && obj->otyp > CORPSE) {
/* do not (yet) revive shopkeepers */
/* Note: this might conceivably produce two monsters
at the same position - strange, but harmless */
mtmp = mkmon_at(CORPSE_I_TO_C(obj->otyp),obj->ox,obj->oy);
delobj(obj);
}
return(!!mtmp); /* TRUE if some monster created */
}

rloco(obj)
register struct obj *obj;
{
register tx,ty,otx,oty;

otx = obj->ox;
oty = obj->oy;
do {
tx = rn1(COLNO-3,2);
ty = rn2(ROWNO);
} while(!goodpos(tx,ty));
obj->ox = tx;
obj->oy = ty;
if(cansee(otx,oty))
newsym(otx,oty);
}

fracture_rock(obj) /* fractured by pick-axe or wand of striking */
register struct obj *obj; /* no texts here! */
{
/* unpobj(obj); */
obj->otyp = ROCK;
obj->quan = 7 + rn2(60);
obj->owt = weight(obj);
obj->olet = WEAPON_SYM;
if(cansee(obj->ox,obj->oy))
prl(obj->ox,obj->oy);
}
//E*O*F hack.zap.c//

exit 0

0 new messages