Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83 (MC840302); site mcvax.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!godot!harvard!seismo!mcvax!play From: play@mcvax.UUCP (funhouse) Newsgroups: net.sources Subject: Hack sources (part 3 of 15) Message-ID: <6245@mcvax.UUCP> Date: Mon, 17-Dec-84 19:29:30 EST Article-I.D.: mcvax.6245 Posted: Mon Dec 17 19:29:30 1984 Date-Received: Wed, 19-Dec-84 02:13:24 EST Organization: CWI, Amsterdam Lines: 1161 # This is part 3 (of 15) of the Hack sources. Send complaints to # mcvax!play . # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # hack.h hack.c help hh echo x - hack.h cat > "hack.h" << '//E*O*F hack.h//' /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ #include "mklev.h" #include "hack.onames.h" #define ON 1 #define OFF 0 extern struct obj *invent, *uwep, *uarm, *uarm2, *uarmh, *uarms, *uarmg, *uleft, *uright, *fcobj; extern struct obj *uchain; /* defined iff PUNISHED */ extern struct obj *uball; /* defined if PUNISHED */ struct obj *o_at(), *getobj(), *sobj_at(); struct flag { unsigned ident; /* social security number for each monster */ unsigned topl:2; /* a top line (message) has been printed */ /* 0: top line empty; 2: no --More-- reqd. */ unsigned cbreak:1; /* in cbreak mode, rogue format */ unsigned oneline:1; /* give inventories 1 line at a time */ unsigned move:1; unsigned mv:1; unsigned run:3; /* 0: h (etc), 1: H (etc), 2: fh (etc) */ /* 3: FH, 4: ff+, 5: ff-, 6: FF+, 7: FF- */ unsigned nopick:1; /* do not pickup objects */ unsigned echo:1; /* 1 to echo characters */ unsigned botl:1; /* partially redo status line */ unsigned botlx:1; /* print an entirely new bottom line */ unsigned nscrinh:1; /* inhibit nscr() in pline(); */ }; extern struct flag flags; struct prop { #define TIMEOUT 007777 /* mask */ #define LEFT_RING W_RINGL /* 010000L */ #define RIGHT_RING W_RINGR /* 020000L */ #define INTRINSIC 040000L #define LEFT_SIDE LEFT_RING #define RIGHT_SIDE RIGHT_RING #define BOTH_SIDES (LEFT_SIDE | RIGHT_SIDE) long p_flgs; int (*p_tofn)(); /* called after timeout */ }; struct you { xchar ux, uy; schar dx, dy; /* direction of fast move */ #ifdef QUEST schar di; /* direction of FF */ xchar ux0, uy0; /* initial position FF */ #endif QUEST xchar udisx, udisy; /* last display pos */ char usym; /* usually '@' */ schar uluck; int last_str_turn:3; /* 0: none, 1: half turn, 2: full turn */ /* +: turn right, -: turn left */ unsigned udispl:1; /* @ on display */ unsigned ulevel:5; #ifdef QUEST unsigned uhorizon:7; #endif QUEST unsigned utrap:3; /* trap timeout */ unsigned utraptype:1; /* defined if utrap nonzero */ #define TT_BEARTRAP 0 #define TT_PIT 1 unsigned uinshop:1; /* perhaps these #define's should also be generated by makedefs */ #define TELEPAT LAST_RING /* not a ring */ #define Telepat u.uprops[TELEPAT].p_flgs #define FAST (LAST_RING+1) /* not a ring */ #define Fast u.uprops[FAST].p_flgs #define CONFUSION (LAST_RING+2) /* not a ring */ #define Confusion u.uprops[CONFUSION].p_flgs #define INVIS (LAST_RING+3) /* not a ring */ #define Invis u.uprops[INVIS].p_flgs #define GLIB (LAST_RING+4) /* not a ring */ #define Glib u.uprops[GLIB].p_flgs #define PUNISHED (LAST_RING+5) /* not a ring */ #define Punished u.uprops[PUNISHED].p_flgs #define SICK (LAST_RING+6) /* not a ring */ #define Sick u.uprops[SICK].p_flgs #define BLIND (LAST_RING+7) /* not a ring */ #define Blind u.uprops[BLIND].p_flgs #define WOUNDED_LEGS (LAST_RING+8) /* not a ring */ #define Wounded_legs u.uprops[WOUNDED_LEGS].p_flgs #define PROP(x) (x-RIN_ADORNMENT) /* convert ring to index in uprops */ unsigned umconf:1; char *usick_cause; struct prop uprops[LAST_RING+9]; unsigned uswallow:1; /* set if swallowed by a monster */ unsigned uswldtim:4; /* time you have been swallowed */ unsigned uhs:3; /* hunger state - see hack.eat.c */ schar ustr,ustrmax; schar udaminc; schar uac; int uhp,uhpmax; long int ugold,ugold0,uexp,urexp; int uhunger; /* refd only in eat.c and shk.c */ int uinvault; struct monst *ustuck; int nr_killed[CMNUM+2]; /* used for experience bookkeeping */ }; extern struct you u; extern char *traps[]; extern char *plur(), *monnam(), *Monnam(), *amonnam(), *Amonnam(), *doname(), *aobjnam(); extern char readchar(); extern char vowels[]; extern xchar curx,cury; /* cursor location on screen */ extern coord bhitpos; /* place where thrown weapon falls to the ground */ extern xchar seehx,seelx,seehy,seely; /* where to see*/ extern char *save_cm,*killer; extern xchar dlevel, maxdlevel; /* dungeon level */ extern long moves; extern int multi; extern char lock[]; #define DIST(x1,y1,x2,y2) (((x1)-(x2))*((x1)-(x2)) + ((y1)-(y2))*((y1)-(y2))) #define PL_CSIZ 20 /* sizeof pl_character */ #define MAX_CARR_CAP 120 /* so that boulders can be heavier */ #define FAR (COLNO+2) /* position outside screen */ //E*O*F hack.h// echo x - hack.c cat > "hack.c" << '//E*O*F hack.c//' /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ #include "hack.h" #include extern char news0(); extern char *nomovemsg; extern char *exclam(); extern struct obj *addinv(); extern boolean hmon(); /* called on movement: 1. when throwing ball+chain far away 2. when teleporting 3. when walking out of a lit room */ unsee() { register x,y; register struct rm *lev; /* if(u.udispl){ u.udispl = 0; newsym(u.udisx, u.udisy); } */ #ifndef QUEST if(seehx){ seehx = 0; } else #endif QUEST for(x = u.ux-1; x < u.ux+2; x++) for(y = u.uy-1; y < u.uy+2; y++) { lev = &levl[x][y]; if(!lev->lit && lev->scrsym == '.') { lev->scrsym =' '; lev->new = 1; on_scr(x,y); } } } /* called: in hack.eat.c: seeoff(0) - blind after eating rotten food in hack.mon.c: seeoff(0) - blinded by a yellow light in hack.mon.c: seeoff(1) - swallowed in hack.do.c: seeoff(0) - blind after drinking potion in hack.do.c: seeoff(1) - go up or down the stairs in hack.trap.c:seeoff(1) - fall through trapdoor */ seeoff(mode) /* 1 to redo @, 0 to leave them */ { /* 1 means misc movement, 0 means blindness */ register x,y; register struct rm *lev; if(u.udispl && mode){ u.udispl = 0; levl[u.udisx][u.udisy].scrsym = news0(u.udisx,u.udisy); } #ifndef QUEST if(seehx) { seehx = 0; } else #endif QUEST if(!mode) { for(x = u.ux-1; x < u.ux+2; x++) for(y = u.uy-1; y < u.uy+2; y++) { lev = &levl[x][y]; if(!lev->lit && lev->scrsym == '.') lev->seen = 0; } } } /* 'rogue'-like direction commands */ char sdir[] = "hykulnjb"; schar xdir[8] = { -1,-1,0,1,1,1,0,-1 }; schar ydir[8] = { 0,-1,-1,-1,0,1,1,1 }; movecm(cmd) register char *cmd; { register char *dp; if(!(dp = index(sdir, *cmd))) return(0); u.dx = xdir[dp-sdir]; u.dy = ydir[dp-sdir]; return(1); } #ifdef QUEST finddir(){ register int i, ui = u.di; for(i = 0; i <= 8; i++){ if(flags.run & 1) ui++; else ui += 7; ui %= 8; if(i == 8){ pline("Not near a wall."); flags.move = multi = 0; return(0); } if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui])) break; } for(i = 0; i <= 8; i++){ if(flags.run & 1) ui += 7; else ui++; ui %= 8; if(i == 8){ pline("Not near a room."); flags.move = multi = 0; return(0); } if(isroom(u.ux+xdir[ui], u.uy+ydir[ui])) break; } u.di = ui; u.dx = xdir[ui]; u.dy = ydir[ui]; } isroom(x,y) register x,y; { return(isok(x,y) && (levl[x][y].typ == ROOM || (levl[x][y].typ >= LDOOR && flags.run >= 6))); } #endif QUEST isok(x,y) register x,y; { return(x >= 0 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1); } domove() { xchar oldx,oldy; register struct monst *mtmp; register struct rm *tmpr,*ust; struct gen *trap; register struct obj *otmp; wipe_engr_at(u.ux, u.uy, rnd(5)); if(inv_weight() > 0){ pline("You collapse under your load."); nomul(0); return; } if(Confusion) { do { u.dx = rn1(3,-1); u.dy = rn1(3,-1); tmpr = &levl[u.ux+u.dx][u.uy+u.dy]; } while((!u.dx && !u.dy) || !isok(u.ux+u.dx, u.uy+u.dy) || tmpr->typ < DOOR); } else tmpr = &levl[u.ux+u.dx][u.uy+u.dy]; if(!isok(u.ux+u.dx, u.uy+u.dy)){ nomul(0); return; } ust = &levl[u.ux][u.uy]; oldx = u.ux; oldy = u.uy; if(!u.uswallow) if(trap = g_at(u.ux+u.dx,u.uy+u.dy,ftrap)) { if(trap->gflag & SEEN) nomul(0); } if(u.ustuck && !u.uswallow && (u.ux+u.dx != u.ustuck->mx || u.uy+u.dy != u.ustuck->my)) { if(dist(u.ustuck->mx, u.ustuck->my) > 2){ /* perhaps it fled (or was teleported or ... ) */ u.ustuck = 0; } else { if(Blind) pline("You cannot escape from it!"); else pline("You cannot escape from %s!.", monnam(u.ustuck)); nomul(0); return; } } if((mtmp = m_at(u.ux+u.dx,u.uy+u.dy)) || u.uswallow) { /* attack monster */ schar tmp; boolean malive = TRUE; register struct permonst *mdat; nomul(0); gethungry(); if(multi < 0) return; /* we just fainted */ if(u.uswallow) mtmp = u.ustuck; mdat = mtmp->data; if(mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep && !mtmp->mconf && mtmp->mcansee && !rn2(7) && (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */ mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) goto nomon; if(mtmp->mimic){ if(!u.ustuck && !mtmp->mflee) u.ustuck = mtmp; switch(levl[u.ux+u.dx][u.uy+u.dy].scrsym){ case '+': pline("The door actually was a Mimic."); break; case '$': pline("The chest was a Mimic!"); break; default: pline("Wait! That's a Mimic!"); } wakeup(mtmp); /* clears mtmp->mimic */ return; } wakeup(mtmp); /* clears mtmp->mimic */ if(mtmp->mhide && mtmp->mundetected){ register struct obj *obj; mtmp->mundetected = 0; if((obj = o_at(mtmp->mx,mtmp->my)) && !Blind) pline("Wait! There's a %s hiding under %s!", mdat->mname, doname(obj)); return; } tmp = u.uluck + u.ulevel + mdat->ac + abon(); if(uwep) { if(uwep->olet == WEAPON_SYM) tmp += uwep->spe; if(uwep->otyp == TWO_HANDED_SWORD) tmp -= 1; else if(uwep->otyp == DAGGER) tmp += 2; else if(uwep->otyp == CRYSKNIFE) tmp += 3; else if(uwep->otyp == SPEAR && index("XDne", mdat->mlet)) tmp += 2; } if(mtmp->msleep) { mtmp->msleep = 0; tmp += 2; } if(mtmp->mfroz) { tmp += 4; if(!rn2(10)) mtmp->mfroz = 0; } if(mtmp->mflee) tmp += 2; if(u.utrap) tmp -= 3; if(tmp <= rnd(20) && !u.uswallow){ if(Blind) pline("You miss it."); else pline("You miss %s.",monnam(mtmp)); } else { /* we hit the monster; be careful: it might die! */ if((malive = hmon(mtmp,uwep,0)) == TRUE) { /* monster still alive */ if(!rn2(25) && mtmp->mhp < mtmp->orig_hp/2) { mtmp->mflee = 1; if(u.ustuck == mtmp && !u.uswallow) u.ustuck = 0; } #ifndef NOWORM if(mtmp->wormno) cutworm(mtmp, u.ux+u.dx, u.uy+u.dy, uwep ? uwep->otyp : 0); #endif NOWORM } if(mdat->mlet == 'a') { if(rn2(2)) { pline("You are splashed by the blob's acid!"); losehp_m(rnd(6), mtmp); } if(!rn2(6)) corrode_weapon(); else if(!rn2(60)) corrode_armor(); } } if(malive && !Blind && mdat->mlet == 'E' && rn2(3)) { if(mtmp->mcansee) { pline("You are frozen by the floating eye's gaze!"); nomul((u.ulevel > 6 || rn2(4)) ? rn1(20,-21) : -200); } else { pline("The blinded floating eye cannot defend itself."); if(!rn2(500)) u.uluck--; } } return; } nomon: /* not attacking an animal, so we try to move */ if(u.utrap) { if(u.utraptype == TT_PIT) { pline("You are still in a pit."); u.utrap--; } else { pline("You are caught in a beartrap."); if((u.dx && u.dy) || !rn2(5)) u.utrap--; } return; } if((tmpr->typ < DOOR) || (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))){ flags.move = 0; nomul(0); return; } while(otmp = sobj_at(ENORMOUS_ROCK, u.ux+u.dx, u.uy+u.dy)) { register xchar rx = u.ux+2*u.dx, ry = u.uy+2*u.dy; register struct gen *gtmp; nomul(0); if(isok(rx,ry) && (levl[rx][ry].typ > DOOR || (levl[rx][ry].typ == DOOR && (!u.dx || !u.dy)))) { if(m_at(rx,ry)) { pline("You hear a monster behind the rock."); pline("Perhaps that's why you cannot move it."); return; } if(gtmp = g_at(rx,ry,ftrap)) #include "def.trap.h" switch(gtmp->gflag & ~SEEN) { case PIT: pline("You push the rock into a pit!"); deltrap(gtmp); delobj(otmp); pline("It completely fills the pit!"); continue; case TELEP_TRAP: pline("You push the rock and suddenly it disappears!"); delobj(otmp); continue; } otmp->ox = rx; otmp->oy = ry; /* pobj(otmp); */ if(cansee(rx,ry)) atl(rx,ry,otmp->olet); if(Invis) newsym(u.ux+u.dx, u.uy+u.dy); { static int lastmovetime; /* note: this var contains garbage initially and after a restore */ if(moves > lastmovetime+2 || moves < lastmovetime) pline("With great effort you move the enormous rock."); lastmovetime = moves; } } else { pline("You try to move the enormous rock, but in vain."); return; } } if(u.dx && u.dy && levl[u.ux][u.uy+u.dy].typ < DOOR && levl[u.ux+u.dx][u.uy].typ < DOOR && invent && inv_weight()+40 > 0) { pline("You are carrying too much to get through."); nomul(0); return; } if(Punished && DIST(u.ux+u.dx, u.uy+u.dy, uchain->ox, uchain->oy) > 2){ if(carried(uball)) { movobj(uchain, u.ux, u.uy); goto nodrag; } if(DIST(u.ux+u.dx, u.uy+u.dy, uball->ox, uball->oy) < 3){ /* leave ball, move chain under/over ball */ movobj(uchain, uball->ox, uball->oy); goto nodrag; } if(inv_weight() + (int) uball->owt/2 > 0) { pline("You cannot %sdrag the heavy iron ball.", invent ? "carry all that and also " : ""); nomul(0); return; } movobj(uball, uchain->ox, uchain->oy); unpobj(uball); /* BAH %% */ uchain->ox = u.ux; uchain->oy = u.uy; nomul(-2); nomovemsg = ""; nodrag: ; } u.ux += u.dx; u.uy += u.dy; if(flags.run) { if(tmpr->typ == DOOR || (xupstair == u.ux && yupstair == u.uy) || (xdnstair == u.ux && ydnstair == u.uy)) nomul(0); } /* if(u.udispl) { u.udispl = 0; newsym(oldx,oldy); } */ if(!Blind) { #ifdef QUEST setsee(); #else if(ust->lit) { if(tmpr->lit) { if(tmpr->typ == DOOR) prl1(u.ux+u.dx,u.uy+u.dy); else if(ust->typ == DOOR) nose1(oldx-u.dx,oldy-u.dy); } else { unsee(); prl1(u.ux+u.dx,u.uy+u.dy); } } else { if(tmpr->lit) setsee(); else { prl1(u.ux+u.dx,u.uy+u.dy); if(tmpr->typ == DOOR) { if(u.dy) { prl(u.ux-1,u.uy); prl(u.ux+1,u.uy); } else { prl(u.ux,u.uy-1); prl(u.ux,u.uy+1); } } } nose1(oldx-u.dx,oldy-u.dy); } #endif QUEST } else { pru(); } if(!flags.nopick) pickup(); if(trap) dotrap(trap); /* fall into pit, arrow trap, etc. */ (void) inshop(); if(!Blind) read_engr_at(u.ux,u.uy); } movobj(obj, ox, oy) register struct obj *obj; register int ox, oy; { /* Some dirty programming to get display right */ freeobj(obj); unpobj(obj); obj->nobj = fobj; fobj = obj; obj->ox = ox; obj->oy = oy; } pickup(){ register struct gen *gold; register struct obj *obj, *obj2; register int wt; if(Levitation) return; while(gold = g_at(u.ux,u.uy,fgold)) { pline("%u gold piece%s.", gold->gflag, plur(gold->gflag)); u.ugold += gold->gflag; flags.botl = 1; freegold(gold); if(flags.run) nomul(0); if(Invis) newsym(u.ux,u.uy); } for(obj = fobj; obj; obj = obj2) { obj2 = obj->nobj; /* perhaps obj will be picked up */ if(obj->ox == u.ux && obj->oy == u.uy) { if(flags.run) nomul(0); #define DEAD_c CORPSE+('c'-'a'+'Z'-'@'+1) if(obj->otyp == DEAD_COCKATRICE && !uarmg){ pline("Touching the dead cockatrice is a fatal mistake."); pline("You turn to stone."); killer = "cockatrice cadaver"; done("died"); } if(obj->otyp == SCR_SCARE_MONSTER){ if(!obj->spe) obj->spe = 1; else { /* Note: perhaps the 1st pickup failed: you cannot carry anymore, and so we never dropped it - let's assume that treading on it twice also destroys the scroll */ pline("The scroll turns to dust as you pick it up."); delobj(obj); continue; } } /* do not pick up uchain */ if(Punished && obj == uchain) continue; wt = inv_weight() + obj->owt; if(wt > 0) { if(obj->quan > 1) { /* see how many we can lift */ extern struct obj *splitobj(); int savequan = obj->quan; int iw = inv_weight(); int qq; for(qq = 1; qq < savequan; qq++){ obj->quan = qq; if(iw + weight(obj) > 0) break; } obj->quan = savequan; qq--; /* we can carry qq of them */ if(!qq) goto too_heavy; pline("You can only carry %s of the %s lying here.", (qq == 1) ? "one" : "some", doname(obj)); (void) splitobj(obj, qq); /* note: obj2 is set already, so we'll never * encounter the other half; if it should be * otherwise then write * obj2 = splitobj(obj,qq); */ goto lift_some; } too_heavy: pline("There %s %s here, but %s.", (obj->quan == 1) ? "is" : "are", doname(obj), !invent ? "it is too heavy for you to lift" : "you cannot carry anymore"); break; } lift_some: if(inv_cnt() >= 52) { pline("Your knapsack cannot accomodate anymore items."); break; } if(wt > -5) pline("You have a little trouble lifting"); freeobj(obj); if(Invis) newsym(u.ux,u.uy); addtobill(obj); /* sets obj->unpaid if necessary */ { int pickquan = obj->quan; int mergquan; if(!Blind) obj->dknown = 1; /* this is done by prinv(), but addinv() needs it already for merging */ obj = addinv(obj); /* might merge it with other objects */ mergquan = obj->quan; obj->quan = pickquan; /* to fool prinv() */ prinv(obj); obj->quan = mergquan; } } } } /* stop running if we see something interesting */ /* turn around a corner if that is the only way we can proceed */ /* do not turn left or right twice */ lookaround(){ register x,y,i,x0,y0,m0,i0 = 9; register int corrct = 0, noturn = 0; register struct monst *mtmp; #ifdef lint /* suppress "used before set" message */ x0 = y0 = 0; #endif lint if(Blind || flags.run == 0) return; if(flags.run == 1 && levl[u.ux][u.uy].typ >= ROOM) return; #ifdef QUEST if(u.ux0 == u.ux+u.dx && u.uy0 == u.uy+u.dy) goto stop; #endif QUEST for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++){ if(x == u.ux && y == u.uy) continue; if(!levl[x][y].typ) continue; if((mtmp = m_at(x,y)) && !mtmp->mimic && (!mtmp->minvis || See_invisible)){ if(!mtmp->mtame || (x == u.ux+u.dx && y == u.uy+u.dy)) goto stop; } else mtmp = 0; /* invisible M cannot influence us */ if(x == u.ux-u.dx && y == u.uy-u.dy) continue; switch(levl[x][y].scrsym){ case '|': case '-': case '.': case ' ': break; case '+': if(x != u.ux && y != u.uy) break; if(flags.run != 1) goto stop; /* fall into next case */ case CORR_SYM: corr: if(flags.run == 1 || flags.run == 3) { i = DIST(x,y,u.ux+u.dx,u.uy+u.dy); if(i > 2) break; if(corrct == 1 && DIST(x,y,x0,y0) != 1) noturn = 1; if(i < i0) { i0 = i; x0 = x; y0 = y; m0 = mtmp ? 1 : 0; } } corrct++; break; case '^': if(flags.run == 1) goto corr; /* if you must */ if(x == u.ux+u.dx && y == u.uy+u.dx) goto stop; break; default: /* e.g. objects or trap or stairs */ if(flags.run == 1) goto corr; if(mtmp) break; /* d */ stop: nomul(0); return; } } #ifdef QUEST if(corrct > 0 && (flags.run == 4 || flags.run == 5)) goto stop; #endif QUEST if(corrct > 1 && flags.run == 2) goto stop; if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) { /* make sure that we do not turn too far */ if(i0 == 2) { if(u.dx == y0-u.uy && u.dy == u.ux-x0) i = 2; /* straight turn right */ else i = -2; /* straight turn left */ } else if(u.dx && u.dy) { if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy)) i = -1; /* half turn left */ else i = 1; /* half turn right */ } else { if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy)) i = 1; /* half turn right */ else i = -1; /* half turn left */ } i += u.last_str_turn; if(i <= 2 && i >= -2) { u.last_str_turn = i; u.dx = x0-u.ux, u.dy = y0-u.uy; } } } #ifdef QUEST cansee(x,y) xchar x,y; { register int dx,dy,adx,ady,sdx,sdy,dmax,d; if(Blind) return(0); if(!isok(x,y)) return(0); d = dist(x,y); if(d < 3) return(1); if(d > u.uhorizon*u.uhorizon) return(0); if(!levl[x][y].lit) return(0); dx = x - u.ux; adx = abs(dx); sdx = sgn(dx); dy = y - u.uy; ady = abs(dy); sdy = sgn(dy); if(dx == 0 || dy == 0 || adx == ady){ dmax = (dx == 0) ? ady : adx; for(d = 1; d <= dmax; d++) if(!rroom(sdx*d,sdy*d)) return(0); return(1); } else if(ady > adx){ for(d = 1; d <= ady; d++){ if(!rroom(sdx*( (d*adx)/ady ), sdy*d) || !rroom(sdx*( (d*adx-1)/ady+1 ), sdy*d)) return(0); } return(1); } else { for(d = 1; d <= adx; d++){ if(!rroom(sdx*d, sdy*( (d*ady)/adx )) || !rroom(sdx*d, sdy*( (d*ady-1)/adx+1 ))) return(0); } return(1); } } rroom(x,y) register int x,y; { return(levl[u.ux+x][u.uy+y].typ >= ROOM); } #else cansee(x,y) xchar x,y; { if(Blind || u.uswallow) return(0); if(dist(x,y) < 3) return(1); if(levl[x][y].lit && seelx <= x && x <= seehx && seely <= y && y <= seehy) return(1); return(0); } #endif QUEST sgn(a) register int a; { return((a> 0) ? 1 : (a == 0) ? 0 : -1); } pow(num) /* returns 2 to the num */ register unsigned num; { return(1 << num); } #ifdef QUEST setsee() { register x,y; if(Blind) { pru(); return; } for(y = u.uy-u.uhorizon; y <= u.uy+u.uhorizon; y++) for(x = u.ux-u.uhorizon; x <= u.ux+u.uhorizon; x++) { if(cansee(x,y)) prl(x,y); } } #else setsee() { register x,y; if(Blind) { pru(); return; } if(!levl[u.ux][u.uy].lit) { seelx = u.ux-1; seehx = u.ux+1; seely = u.uy-1; seehy = u.uy+1; } else { for(seelx = u.ux; levl[seelx-1][u.uy].lit; seelx--); for(seehx = u.ux; levl[seehx+1][u.uy].lit; seehx++); for(seely = u.uy; levl[u.ux][seely-1].lit; seely--); for(seehy = u.uy; levl[u.ux][seehy+1].lit; seehy++); } for(y = seely; y <= seehy; y++) for(x = seelx; x <= seehx; x++) { prl(x,y); } if(!levl[u.ux][u.uy].lit) seehx = 0; /* seems necessary elsewhere */ else { if(seely == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seely-1); if(seehy == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seehy+1); if(seelx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seelx-1,y); if(seehx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seehx+1,y); } } #endif QUEST nomul(nval) register nval; { if(multi < 0) return; multi = nval; flags.mv = flags.run = 0; } abon() { if(u.ustr == 3) return(-3); else if(u.ustr < 6) return(-2); else if(u.ustr < 8) return(-1); else if(u.ustr < 17) return(0); else if(u.ustr < 69) return(1); /* up to 18/50 */ else if(u.ustr < 118) return(2); else return(3); } dbon() { if(u.ustr < 6) return(-1); else if(u.ustr < 16) return(0); else if(u.ustr < 18) return(1); else if(u.ustr == 18) return(2); /* up to 18 */ else if(u.ustr < 94) return(3); /* up to 18/75 */ else if(u.ustr < 109) return(4); /* up to 18/90 */ else if(u.ustr < 118) return(5); /* up to 18/99 */ else return(6); } losestr(num) register num; { u.ustr -= num; while(u.ustr < 3) { u.ustr++; u.uhp -= 6; u.uhpmax -= 6; } flags.botl = 1; } losehp(n,knam) register n; register char *knam; { u.uhp -= n; if(u.uhp > u.uhpmax) u.uhpmax = u.uhp; /* perhaps n was negative */ flags.botl = 1; if(u.uhp < 1) killer = knam; /* the thing that killed you */ } losehp_m(n,mtmp) register n; register struct monst *mtmp; { u.uhp -= n; flags.botl = 1; if(u.uhp < 1) done_in_by(mtmp); } losexp() /* hit by V or W */ { register num; if(u.ulevel > 1) pline("Goodbye level %d.",u.ulevel--); else u.uhp = -1; num = rnd(10); u.uhp -= num; u.uhpmax -= num; u.uexp = 10*pow(u.ulevel-1); flags.botl = 1; } inv_weight(){ register struct obj *otmp = invent; register int wt = 0; register int carrcap = 5*(((u.ustr > 18) ? 20 : u.ustr) + u.ulevel); if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP; if(Wounded_legs & LEFT_SIDE) carrcap -= 10; if(Wounded_legs & RIGHT_SIDE) carrcap -= 10; while(otmp){ wt += otmp->owt; otmp = otmp->nobj; } return(wt - carrcap); } inv_cnt(){ register struct obj *otmp = invent; register int ct = 0; while(otmp){ ct++; otmp = otmp->nobj; } return(ct); } //E*O*F hack.c// echo x - help cat > "help" << '//E*O*F help//' Welcome to HACK! Hack is a Dungeons and Dragons like game where you (the adventurer) descend into the depths of the dungeon in search of the Amulet of Yendor (reputed to be hidden on the twentieth level). You are accompanied by a little dog that can help you in many ways and can be trained to do all sorts of things. On the way you will find useful (or useless) items, (quite possibly with magic properties) and assorted monsters. You attack a monster by trying to move into the space a monster is in (but often it is much wiser to leave it alone). Unlike most adventure games, which give you a verbal description of your location, hack gives you a visual image of the dungeon level you are on. Hack uses the following symbols: A to Z and a to z: monsters. You can find out what a letter represents by saying "/ (letter)", as in "/A", which will tell you that 'A' is a giant ant. - and | These form the walls of a room (or maze). . this is the floor of a room. # this is a corridor. > this is the staircase to the next level. < the staircase to the previous level. ` A large boulder. @ You (usually). ^ A trap. ) A weapon of some sort. ( Some other useful object (key, rope, dynamite, camera, ...) [ A suit of armor. % A piece of food (not necessarily healthy ...). / A wand. = A ring. ? A scroll. ! A magic potion. $ A pile or pot of gold. Commands: Hack knows the following commands: ? help: print this list. Q Quit the game. < up: go up the staircase (if you are standing on it). > down: go down (just like up). kjhlyubn - go one step in the direction indicated. k: north (i.e., to the top of the screen), j: south, h: west, l: east, y: ne, u: nw, b: se, n: sw. KJHLYUBN - Go in that direction until you hit a wall or run into something. m (followed by one of kjhlyubn): move without picking up any objects. M (followed by one of KJHLYUBN): Move far, no pickup. f (followed by one of kjhlyubn): move until something interesting is found. F (followed by one of KJHLYUBN): as previous, but forking of corridors is not considered interesting. i print your inventory. s search for secret doors and traps around you. ^ ask for the type of a trap you found earlier. ) ask for current wielded weapon. [ ask for current armor. = ask for current rings. . rest, do nothing. ^R redraw the screen. ^P repeat last message (subsequent ^P's repeat earlier messages). / (followed by any symbol): tell what this symbol represents. e eat food. w wield weapon. w- means: wield nothing, use bare hands. q drink (quaff) a potion. r read a scroll. T Takeoff armor. R Remove Ring. W Wear armor. P Put on a ring. t throw or shoot a weapon. p pay your shopping bill. d drop something. d7a: drop seven items of object a. D Drop several things. In answer to the question "What kinds of things do you want to drop? [!%= au]" you should give zero or more object symbols possibly followed by 'a' and/or 'u'. 'a' means: drop all such objects, without asking for confirmation. 'u' means: drop only unpaid objects (when in a shop). a use, apply - Generic command for using a key to lock or unlock a door, using a camera, using a rope, etc. c call: name a certain object or class of objects. C Call: Name an individual monster. E Engrave: Write a message in the dust on the floor. E- means: use fingers for writing. o set options. (see below) v print version number. You can put a number before a command to repeat it that many times, as in "20s" or "40.". Options: To turn an option on, say 'ox', where x is the optionletter. To turn it off, say 'o!x'. The following options currently exist. e echo Echo typed characters. o oneline Give inventories one line at a time (at the top of your screen). Have Fun, and Good Hacking! //E*O*F help// echo x - hh cat > "hh" << '//E*O*F hh//' y k u Move commands: \|/ hykulnjb: single move in specified direction h-.-l HYKULNJB: repeated move in specified direction /|\ (until stopped by e.g. a wall) b j n f: fast movement in direction (until something interesting is seen) m: move without picking up objects Meta commands: Q quit leave the game S save save the game (to be continued later) o set set options ? help print information / whatis give name (and sometimes more info) of specified monster ! sh escape to some SHELL v version print version number ^R redraw redraw the screen (^R denotes the symbol CTRL/R) ^P print repeat last message (subsequent ^P's repeat earlier messages) Game commands: a apply, use use something (a key, camera, etc.) c call give a name to a class of objects d drop drop an object. d7a: drop seven items of object a. e eat eat something i invent list the inventory (and shopping bill) p pay pay your bill q drink quaff a potion r read read a scroll s search search for secret doors, hidden traps and monsters t throw throw or shoot a weapon w wield wield a weapon (w- wield nothing) z zap zap a wand C name name an individual monster (e.g., baptize your dog) D Drop drop several things E Engrave write a message in the dust on the floor (E- use fingers) P wear put on a ring R remove remove a ring T remove take off some armor W wear put on some armor < up go up the stairs > down go down the stairs ^ trap_id identify a previously found trap ),[,= ask for current weapon, armor, rings, respectively . or wait a moment //E*O*F hh// exit 0