From fortune!hpda!hplabs!hao!seismo!mcvax!aeb Fri Apr 12 07:11:53 1985 Relay-Version: version B 2.10.2 9/18/84; site wdl1.UUCP Posting-Version: version B 2.10.1 6/24/83 (MC840302); site mcvax.UUCP Path: wdl1!fortune!hpda!hplabs!hao!seismo!mcvax!aeb From: aeb@mcvax.UUCP (Andries Brouwer) Newsgroups: net.sources.games Subject: Hack 1.0.2 - part 9 of 10 Message-ID: <599@mcvax.UUCP> Date: 12 Apr 85 15:11:53 GMT Article-I.D.: mcvax.599 Posted: Fri Apr 12 07:11:53 1985 Date-Received: 16 Apr 85 12:39:35 GMT Reply-To: aeb@mcvax.UUCP (Andries Brouwer) Followup-To: net.games.hack Organization: CWI, Amsterdam Lines: 1926 # 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 #include #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 /* for time_t and stat */ #include #ifdef BSD #include #else #include #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