From fortune!hpda!hplabs!hao!seismo!mcvax!aeb Mon Apr 8 11:41:39 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 5 of 10 Message-ID: <581@mcvax.UUCP> Date: 8 Apr 85 19:41:39 GMT Article-I.D.: mcvax.581 Posted: Mon Apr 8 11:41:39 1985 Date-Received: 12 Apr 85 06:29:21 GMT Reply-To: aeb@mcvax.UUCP (Andries Brouwer) Followup-To: net.games.hack Organization: CWI, Amsterdam Lines: 2642 # 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.lev.c hack.makemon.c hack.mkobj.c hack.mon.c hack.mhitu.c # hack.monst.c hack.mklev.c echo x - hack.lev.c cat > "hack.lev.c" << '//E*O*F hack.lev.c//' /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.lev.c - version 1.0.2 */ #include "hack.h" #include "def.mkroom.h" #include extern struct monst *restmonchn(); extern struct obj *restobjchn(); extern struct obj *billobjs; extern char *itoa(); extern int hackpid; extern xchar dlevel; extern char nul[]; #ifndef NOWORM #include "def.wseg.h" extern struct wseg *wsegs[32], *wheads[32]; extern long wgrowtime[32]; #endif NOWORM #define MAXLEVEL 40 boolean level_exists[MAXLEVEL]; savelev(fd,lev) int fd; xchar lev; { #ifndef NOWORM register struct wseg *wtmp, *wtmp2; register tmp; #endif NOWORM if(fd < 0) panic("Save on bad file!"); /* impossible */ if(lev >= 0 && lev < MAXLEVEL) level_exists[lev] = TRUE; bwrite(fd,(char *) &hackpid,sizeof(hackpid)); bwrite(fd,(char *) &lev,sizeof(lev)); bwrite(fd,(char *) levl,sizeof(levl)); bwrite(fd,(char *) &moves,sizeof(long)); bwrite(fd,(char *) &xupstair,sizeof(xupstair)); bwrite(fd,(char *) &yupstair,sizeof(yupstair)); bwrite(fd,(char *) &xdnstair,sizeof(xdnstair)); bwrite(fd,(char *) &ydnstair,sizeof(ydnstair)); savemonchn(fd, fmon); savegoldchn(fd, fgold); savetrapchn(fd, ftrap); saveobjchn(fd, fobj); saveobjchn(fd, billobjs); billobjs = 0; save_engravings(fd); #ifndef QUEST bwrite(fd,(char *) rooms,sizeof(rooms)); bwrite(fd,(char *) doors,sizeof(doors)); #endif QUEST fgold = 0; ftrap = 0; fmon = 0; fobj = 0; #ifndef NOWORM bwrite(fd,(char *) wsegs,sizeof(wsegs)); for(tmp=1; tmp<32; tmp++){ for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){ wtmp2 = wtmp->nseg; bwrite(fd,(char *) wtmp,sizeof(struct wseg)); } wsegs[tmp] = 0; } bwrite(fd,(char *) wgrowtime,sizeof(wgrowtime)); #endif NOWORM } bwrite(fd,loc,num) register fd; register char *loc; register unsigned num; { /* lint wants the 3rd arg of write to be an int; lint -p an unsigned */ if(write(fd, loc, (int) num) != num) panic("cannot write %u bytes to file #%d", num, fd); } saveobjchn(fd,otmp) register fd; register struct obj *otmp; { register struct obj *otmp2; unsigned xl; int minusone = -1; while(otmp) { otmp2 = otmp->nobj; xl = otmp->onamelth; bwrite(fd, (char *) &xl, sizeof(int)); bwrite(fd, (char *) otmp, xl + sizeof(struct obj)); free((char *) otmp); otmp = otmp2; } bwrite(fd, (char *) &minusone, sizeof(int)); } savemonchn(fd,mtmp) register fd; register struct monst *mtmp; { register struct monst *mtmp2; unsigned xl; int minusone = -1; struct permonst *monbegin = &mons[0]; bwrite(fd, (char *) &monbegin, sizeof(monbegin)); while(mtmp) { mtmp2 = mtmp->nmon; xl = mtmp->mxlth + mtmp->mnamelth; bwrite(fd, (char *) &xl, sizeof(int)); bwrite(fd, (char *) mtmp, xl + sizeof(struct monst)); if(mtmp->minvent) saveobjchn(fd,mtmp->minvent); free((char *) mtmp); mtmp = mtmp2; } bwrite(fd, (char *) &minusone, sizeof(int)); } savegoldchn(fd,gold) register fd; register struct gold *gold; { register struct gold *gold2; while(gold) { gold2 = gold->ngold; bwrite(fd, (char *) gold, sizeof(struct gold)); free((char *) gold); gold = gold2; } bwrite(fd, nul, sizeof(struct gold)); } savetrapchn(fd,trap) register fd; register struct trap *trap; { register struct trap *trap2; while(trap) { trap2 = trap->ntrap; bwrite(fd, (char *) trap, sizeof(struct trap)); free((char *) trap); trap = trap2; } bwrite(fd, nul, sizeof(struct trap)); } getlev(fd,pid,lev) int fd,pid; xchar lev; { register struct gold *gold; register struct trap *trap; #ifndef NOWORM register struct wseg *wtmp; #endif NOWORM register tmp; long omoves; int hpid; xchar dlvl; /* First some sanity checks */ mread(fd, (char *) &hpid, sizeof(hpid)); mread(fd, (char *) &dlvl, sizeof(dlvl)); if((pid && pid != hpid) || (lev && dlvl != lev)) { pline("Strange, this map is not as I remember it."); pline("Somebody is trying some trickery here ..."); pline("This game is void ..."); done("tricked"); } fgold = 0; ftrap = 0; mread(fd, (char *) levl, sizeof(levl)); mread(fd, (char *)&omoves, sizeof(omoves)); mread(fd, (char *)&xupstair, sizeof(xupstair)); mread(fd, (char *)&yupstair, sizeof(yupstair)); mread(fd, (char *)&xdnstair, sizeof(xdnstair)); mread(fd, (char *)&ydnstair, sizeof(ydnstair)); fmon = restmonchn(fd); /* regenerate animals while on another level */ { long tmoves = (moves > omoves) ? moves-omoves : 0; register struct monst *mtmp, *mtmp2; extern char genocided[]; for(mtmp = fmon; mtmp; mtmp = mtmp2) { long newhp; /* tmoves may be very large */ mtmp2 = mtmp->nmon; if(index(genocided, mtmp->data->mlet)) { mondead(mtmp); continue; } if(mtmp->mtame && tmoves > 250) { mtmp->mtame = 0; mtmp->mpeaceful = 0; } newhp = mtmp->mhp + (index(MREGEN, mtmp->data->mlet) ? tmoves : tmoves/20); if(newhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax; else mtmp->mhp = newhp; } } setgd(); gold = newgold(); mread(fd, (char *)gold, sizeof(struct gold)); while(gold->gx) { gold->ngold = fgold; fgold = gold; gold = newgold(); mread(fd, (char *)gold, sizeof(struct gold)); } free((char *) gold); trap = newtrap(); mread(fd, (char *)trap, sizeof(struct trap)); while(trap->tx) { trap->ntrap = ftrap; ftrap = trap; trap = newtrap(); mread(fd, (char *)trap, sizeof(struct trap)); } free((char *) trap); fobj = restobjchn(fd); billobjs = restobjchn(fd); rest_engravings(fd); #ifndef QUEST mread(fd, (char *)rooms, sizeof(rooms)); mread(fd, (char *)doors, sizeof(doors)); #endif QUEST #ifndef NOWORM mread(fd, (char *)wsegs, sizeof(wsegs)); for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){ wheads[tmp] = wsegs[tmp] = wtmp = newseg(); while(1) { mread(fd, (char *)wtmp, sizeof(struct wseg)); if(!wtmp->nseg) break; wheads[tmp]->nseg = wtmp = newseg(); wheads[tmp] = wtmp; } } mread(fd, (char *)wgrowtime, sizeof(wgrowtime)); #endif NOWORM } mread(fd, buf, len) register fd; register char *buf; register unsigned len; { register int rlen; rlen = read(fd, buf, (int) len); if(rlen != len){ pline("Read %d instead of %u bytes\n", rlen, len); panic("Cannot read %u bytes from file #%d\n", len, fd); } } mklev() { extern boolean in_mklev; if(getbones()) return; in_mklev = TRUE; makelevel(); in_mklev = FALSE; } //E*O*F hack.lev.c// echo x - hack.makemon.c cat > "hack.makemon.c" << '//E*O*F hack.makemon.c//' /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.makemon.c - version 1.0.2 */ #include "hack.h" extern char fut_geno[]; extern char *index(); extern struct obj *mkobj_at(); struct monst zeromonst; /* * called with [x,y] = coordinates; * [0,0] means anyplace * [u.ux,u.uy] means: call mnexto (if !in_mklev) * * In case we make an Orc or killer bee, we make an entire horde (swarm); * note that in this case we return only one of them (the one at [x,y]). */ struct monst * makemon(ptr,x,y) register struct permonst *ptr; { register struct monst *mtmp; register tmp, ct; boolean anything = (!ptr); if(x != 0 || y != 0) if(m_at(x,y)) return((struct monst *) 0); if(ptr){ if(index(fut_geno, ptr->mlet)) return((struct monst *) 0); } else { ct = CMNUM - strlen(fut_geno); if(index(fut_geno, 'm')) ct++; /* make only 1 minotaur */ if(index(fut_geno, '@')) ct++; if(ct <= 0) return(0); /* no more monsters! */ tmp = rn2(ct*dlevel/24 + 7); if(tmp < dlevel - 4) tmp = rn2(ct*dlevel/24 + 12); if(tmp >= ct) tmp = rn1(ct - ct/2, ct/2); for(ct = 0; ct < CMNUM; ct++){ ptr = &mons[ct]; if(index(fut_geno, ptr->mlet)) continue; if(!tmp--) goto gotmon; } panic("makemon?"); } gotmon: mtmp = newmonst(ptr->pxlth); *mtmp = zeromonst; /* clear all entries in structure */ for(ct = 0; ct < ptr->pxlth; ct++) ((char *) &(mtmp->mextra[0]))[ct] = 0; mtmp->nmon = fmon; fmon = mtmp; mtmp->m_id = flags.ident++; mtmp->data = ptr; mtmp->mxlth = ptr->pxlth; if(ptr->mlet == 'D') mtmp->mhpmax = mtmp->mhp = 80; else if(!ptr->mlevel) mtmp->mhpmax = mtmp->mhp = rnd(4); else mtmp->mhpmax = mtmp->mhp = d(ptr->mlevel, 8); mtmp->mx = x; mtmp->my = y; mtmp->mcansee = 1; if(ptr->mlet == 'M'){ mtmp->mimic = 1; mtmp->mappearance = ']'; } { extern boolean in_mklev; if(!in_mklev) { if(x == u.ux && y == u.uy && ptr->mlet != ' ') mnexto(mtmp); if(x == 0 && y == 0) rloc(mtmp); }} if(ptr->mlet == 's' || ptr->mlet == 'S') { mtmp->mhide = mtmp->mundetected = 1; if(in_mklev) if(mtmp->mx && mtmp->my) (void) mkobj_at(0, mtmp->mx, mtmp->my); } if(ptr->mlet == ':') { mtmp->cham = 1; (void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); } if(ptr->mlet == 'I' || ptr->mlet == ';') mtmp->minvis = 1; if(ptr->mlet == 'L' || ptr->mlet == 'N' || (in_mklev && index("&w;", ptr->mlet) && rn2(5)) ) mtmp->msleep = 1; #ifndef NOWORM if(ptr->mlet == 'w' && getwn(mtmp)) initworm(mtmp); #endif NOWORM if(anything) if(ptr->mlet == 'O' || ptr->mlet == 'k') { coord enexto(); coord mm; register int cnt = rnd(10); mm.x = x; mm.y = y; while(cnt--) { mm = enexto(mm.x, mm.y); (void) makemon(ptr, mm.x, mm.y); } } return(mtmp); } coord enexto(xx,yy) register xchar xx,yy; { register xchar x,y; coord foo[15], *tfoo; int range; tfoo = foo; range = 1; do { /* full kludge action. */ for(x = xx-range; x <= xx+range; x++) if(goodpos(x, yy-range)) { tfoo->x = x; tfoo++->y = yy-range; if(tfoo == &foo[15]) goto foofull; } for(x = xx-range; x <= xx+range; x++) if(goodpos(x,yy+range)) { tfoo->x = x; tfoo++->y = yy+range; if(tfoo == &foo[15]) goto foofull; } for(y = yy+1-range; y < yy+range; y++) if(goodpos(xx-range,y)) { tfoo->x = xx-range; tfoo++->y = y; if(tfoo == &foo[15]) goto foofull; } for(y = yy+1-range; y < yy+range; y++) if(goodpos(xx+range,y)) { tfoo->x = xx+range; tfoo++->y = y; if(tfoo == &foo[15]) goto foofull; } range++; } while(tfoo == foo); foofull: return( foo[rn2(tfoo-foo)] ); } goodpos(x,y) /* used only in mnexto and rloc */ { return( ! (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 || m_at(x,y) || !ACCESSIBLE(levl[x][y].typ) || (x == u.ux && y == u.uy) || sobj_at(ENORMOUS_ROCK, x, y) )); } rloc(mtmp) struct monst *mtmp; { register tx,ty; register char ch = mtmp->data->mlet; #ifndef NOWORM if(ch == 'w' && mtmp->mx) return; /* do not relocate worms */ #endif NOWORM do { tx = rn1(COLNO-3,2); ty = rn2(ROWNO); } while(!goodpos(tx,ty)); mtmp->mx = tx; mtmp->my = ty; if(u.ustuck == mtmp){ if(u.uswallow) { u.ux = tx; u.uy = ty; docrt(); } else u.ustuck = 0; } pmon(mtmp); } struct monst * mkmon_at(let,x,y) char let; register int x,y; { register int ct; register struct permonst *ptr; for(ct = 0; ct < CMNUM; ct++) { ptr = &mons[ct]; if(ptr->mlet == let) return(makemon(ptr,x,y)); } return(0); } //E*O*F hack.makemon.c// echo x - hack.mkobj.c cat > "hack.mkobj.c" << '//E*O*F hack.mkobj.c//' /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.mkobj.c - version 1.0.2 */ #include "hack.h" char mkobjstr[] = "))[[!!!!????%%%%/=**))[[!!!!????%%%%/=**(%"; struct obj *mkobj(), *mksobj(); struct obj * mkobj_at(let,x,y) register let,x,y; { register struct obj *otmp = mkobj(let); otmp->ox = x; otmp->oy = y; otmp->nobj = fobj; fobj = otmp; return(otmp); } mksobj_at(otyp,x,y) register otyp,x,y; { register struct obj *otmp = mksobj(otyp); otmp->ox = x; otmp->oy = y; otmp->nobj = fobj; fobj = otmp; } struct obj * mkobj(let) { if(!let) let = mkobjstr[rn2(sizeof(mkobjstr) - 1)]; return( mksobj( letter(let) ? CORPSE + ((let > 'Z') ? (let-'a'+'Z'-'@'+1) : (let-'@')) : probtype(let) ) ); } struct obj zeroobj; struct obj * mksobj(otyp) register otyp; { register struct obj *otmp; char let = objects[otyp].oc_olet; otmp = newobj(0); *otmp = zeroobj; otmp->age = moves; otmp->o_id = flags.ident++; otmp->quan = 1; otmp->olet = let; otmp->otyp = otyp; otmp->dknown = index("/=!?*", let) ? 0 : 1; switch(let) { case WEAPON_SYM: otmp->quan = (otmp->otyp <= ROCK) ? rn1(6,6) : 1; if(!rn2(11)) otmp->spe = rnd(3); else if(!rn2(10)) { otmp->cursed = 1; otmp->spe = -rnd(3); } break; case FOOD_SYM: if(otmp->otyp >= CORPSE) break; #ifdef NOT_YET_IMPLEMENTED /* if tins are to be identified, need to adapt doname() etc */ if(otmp->otyp == TIN) otmp->spe = rnd(...); #endif NOT_YET_IMPLEMENTED /* fall into next case */ case GEM_SYM: otmp->quan = rn2(6) ? 1 : 2; case TOOL_SYM: case CHAIN_SYM: case BALL_SYM: case ROCK_SYM: case POTION_SYM: case SCROLL_SYM: case AMULET_SYM: break; case ARMOR_SYM: if(!rn2(8)) otmp->cursed = 1; if(!rn2(10)) otmp->spe = rnd(3); else if(!rn2(9)) { otmp->spe = -rnd(3); otmp->cursed = 1; } break; case WAND_SYM: if(otmp->otyp == WAN_WISHING) otmp->spe = 3; else otmp->spe = rn1(5, (objects[otmp->otyp].bits & NODIR) ? 11 : 4); break; case RING_SYM: if(objects[otmp->otyp].bits & SPEC) { if(!rn2(3)) { otmp->cursed = 1; otmp->spe = -rnd(2); } else otmp->spe = rnd(2); } else if(otmp->otyp == RIN_TELEPORTATION || otmp->otyp == RIN_AGGRAVATE_MONSTER || otmp->otyp == RIN_HUNGER || !rn2(9)) otmp->cursed = 1; break; default: panic("impossible mkobj"); } otmp->owt = weight(otmp); return(otmp); } letter(c) { return(('@' <= c && c <= 'Z') || ('a' <= c && c <= 'z')); } weight(obj) register struct obj *obj; { register int wt = objects[obj->otyp].oc_weight; return(wt ? wt*obj->quan : (obj->quan + 1)/2); } mkgold(num,x,y) register long num; { register struct gold *gold; register long amount = (num ? num : 1 + (rnd(dlevel+2) * rnd(30))); if(gold = g_at(x,y)) gold->amount += amount; else { gold = newgold(); gold->ngold = fgold; gold->gx = x; gold->gy = y; gold->amount = amount; fgold = gold; /* do sth with display? */ } } //E*O*F hack.mkobj.c// echo x - hack.mon.c cat > "hack.mon.c" << '//E*O*F hack.mon.c//' /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.mon.c - version 1.0.2 */ #include "hack.h" #include "hack.mfndpos.h" #define NULL (char *) 0 extern struct monst *makemon(); extern struct obj *mkobj_at(); int warnlevel; /* used by movemon and dochugw */ long lastwarntime; int lastwarnlev; char *warnings[] = { "white", "pink", "red", "ruby", "purple", "black" }; movemon() { register struct monst *mtmp; register int fr; warnlevel = 0; while(1) { /* find a monster that we haven't treated yet */ /* note that mtmp or mtmp->nmon might get killed while mtmp moves, so we cannot just walk down the chain (even new monsters might get created!) */ for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->mlstmv < moves) goto next_mon; /* treated all monsters */ break; next_mon: mtmp->mlstmv = moves; /* most monsters drown in pools */ { boolean inpool, iseel; inpool = (levl[mtmp->mx][mtmp->my].typ == POOL); iseel = (mtmp->data->mlet == ';'); if(inpool && !iseel) { if(cansee(mtmp->mx,mtmp->my)) pline("%s drowns.", Monnam(mtmp)); mondead(mtmp); continue; } /* but eels have a difficult time outside */ if(iseel && !inpool) { if(mtmp->mhp > 1) mtmp->mhp--; mtmp->mflee = 1; mtmp->mfleetim += 2; } } if(mtmp->mblinded && !--mtmp->mblinded) mtmp->mcansee = 1; if(mtmp->mfleetim && !--mtmp->mfleetim) mtmp->mflee = 0; if(mtmp->mimic) continue; if(mtmp->mspeed != MSLOW || !(moves%2)){ /* continue if the monster died fighting */ fr = -1; if(Conflict && cansee(mtmp->mx,mtmp->my) && (fr = fightm(mtmp)) == 2) continue; if(fr<0 && dochugw(mtmp)) continue; } if(mtmp->mspeed == MFAST && dochugw(mtmp)) continue; } warnlevel -= u.ulevel; if(warnlevel >= SIZE(warnings)) warnlevel = SIZE(warnings)-1; if(warnlevel >= 0) if(warnlevel > lastwarnlev || moves > lastwarntime + 5){ register char *rr; switch(Warning & (LEFT_RING | RIGHT_RING)){ case LEFT_RING: rr = "Your left ring glows"; break; case RIGHT_RING: rr = "Your right ring glows"; break; case LEFT_RING | RIGHT_RING: rr = "Both your rings glow"; break; default: rr = "Your fingertips glow"; break; } pline("%s %s!", rr, warnings[warnlevel]); lastwarntime = moves; lastwarnlev = warnlevel; } dmonsfree(); /* remove all dead monsters */ } justswld(mtmp,name) register struct monst *mtmp; char *name; { mtmp->mx = u.ux; mtmp->my = u.uy; u.ustuck = mtmp; pmon(mtmp); kludge("%s swallows you!",name); more(); seeoff(1); u.uswallow = 1; u.uswldtim = 0; swallowed(); } youswld(mtmp,dam,die,name) register struct monst *mtmp; register dam,die; char *name; { if(mtmp != u.ustuck) return; kludge("%s digests you!",name); u.uhp -= dam; if(u.uswldtim++ >= die){ /* a3 */ pline("It totally digests you!"); u.uhp = -1; } if(u.uhp < 1) done_in_by(mtmp); } dochugw(mtmp) register struct monst *mtmp; { register x = mtmp->mx; register y = mtmp->my; register d = dochug(mtmp); register dd; if(!d) /* monster still alive */ if(Warning) if(!mtmp->mpeaceful) if(mtmp->data->mlevel > warnlevel) if((dd = dist(mtmp->mx,mtmp->my)) < dist(x,y)) if(dd < 100) if(!canseemon(mtmp)) warnlevel = mtmp->data->mlevel; return(d); } /* returns 1 if monster died moving, 0 otherwise */ dochug(mtmp) register struct monst *mtmp; { register struct permonst *mdat; register tmp; if(mtmp->cham && !rn2(6)) (void) newcham(mtmp, &mons[dlevel+14+rn2(CMNUM-14-dlevel)]); mdat = mtmp->data; if(mdat->mlevel < 0) panic("bad monster %c (%d)",mdat->mlet,mdat->mlevel); /* regenerate monsters */ if((!(moves%20) || index(MREGEN, mdat->mlet)) && mtmp->mhp < mtmp->mhpmax) mtmp->mhp++; if(mtmp->mfroz) return(0); /* frozen monsters don't do anything */ if(mtmp->msleep) { /* wake up, or get out of here. */ /* ettins are hard to surprise */ /* Nymphs and Leprechauns do not easily wake up */ if(cansee(mtmp->mx,mtmp->my) && (!Stealth || (mdat->mlet == 'e' && rn2(10))) && (!index("NL",mdat->mlet) || !rn2(50)) && (Aggravate_monster || index("d1", mdat->mlet) || (!rn2(7) && !mtmp->mimic))) mtmp->msleep = 0; else return(0); } /* not frozen or sleeping: wipe out texts written in the dust */ wipe_engr_at(mtmp->mx, mtmp->my, 1); /* confused monsters get unconfused with small probability */ if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0; /* some monsters teleport */ if(mtmp->mflee && index("tNL", mdat->mlet) && !rn2(40)){ rloc(mtmp); return(0); } if(mdat->mmove < rnd(6)) return(0); if(mtmp->mflee || mtmp->mconf || (index("BIuy", mdat->mlet) && !rn2(4)) || (mdat->mlet == 'L' && !u.ugold && (mtmp->mgold || rn2(2))) || dist(mtmp->mx,mtmp->my) > 2 || (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful ) { tmp = m_move(mtmp,0); /* 2: monster died moving */ if(tmp == 2 || (tmp && mdat->mmove <= 12)) return(tmp == 2); } if(!index("Ea", mdat->mlet) && dist(mtmp->mx, mtmp->my) < 3 && !mtmp->mpeaceful && u.uhp > 0 && !sengr_at("Elbereth", u.ux, u.uy) && !sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy)) { if(mhitu(mtmp)) return(1); /* monster died (e.g. 'y' or 'F') */ } /* extra movement for fast monsters */ if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp,1); return(tmp == 2); } m_move(mtmp,after) register struct monst *mtmp; { register struct monst *mtmp2; register nx,ny,omx,omy,appr,nearer,cnt,i,j; xchar gx,gy,nix,niy,chcnt; schar chi; boolean likegold, likegems, likeobjs; char msym = mtmp->data->mlet; schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */ coord poss[9]; int info[9]; if(mtmp->mtrapped) { i = mintrap(mtmp); if(i == 2) return(2); /* he died */ if(i == 1) return(0); /* still in trap, so didnt move */ } if(mtmp->mhide && o_at(mtmp->mx,mtmp->my) && rn2(10)) return(0); /* do not leave hiding place */ /* my dog gets a special treatment */ if(mtmp->mtame) { return( dog_move(mtmp, after) ); } /* likewise for shopkeeper */ if(mtmp->isshk) { mmoved = shk_move(mtmp); if(mmoved >= 0) goto postmov; mmoved = 0; /* follow player outside shop */ } /* and for the guard */ if(mtmp->isgd) { mmoved = gd_move(); goto postmov; } /* teleport if that lies in our nature ('t') or when badly wounded ('1') */ if((msym == 't' && !rn2(5)) || (msym == '1' && (mtmp->mhp < 7 || (!xdnstair && !rn2(5)) || levl[u.ux][u.uy].typ == STAIRS))) { if(mtmp->mhp < 7 || (msym == 't' && rn2(2))) rloc(mtmp); else mnexto(mtmp); mmoved = 1; goto postmov; } /* spit fire ('D') or use a wand ('1') when appropriate */ if(index("D1", msym)) inrange(mtmp); if(msym == 'U' && !mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && rn2(5)) { if(!Confusion) pline("%s's gaze has confused you!", Monnam(mtmp)); else pline("You are getting more and more confused."); if(rn2(3)) mtmp->mcan = 1; Confusion += d(3,4); /* timeout */ } if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1); appr = 1; if(mtmp->mflee) appr = -1; if(mtmp->mconf || Invis || !mtmp->mcansee || (index("BIy", msym) && !rn2(3))) appr = 0; omx = mtmp->mx; omy = mtmp->my; gx = u.ux; gy = u.uy; if(msym == 'L' && appr == 1 && mtmp->mgold > u.ugold) appr = -1; /* random criterion for 'smell' or track finding ability should use mtmp->msmell or sth */ if(msym == '@' || ('a' <= msym && msym <= 'z')) { extern coord *gettrack(); register coord *cp; schar mroom; mroom = inroom(omx,omy); if(mroom < 0 || mroom != inroom(u.ux,u.uy)){ cp = gettrack(omx,omy); if(cp){ gx = cp->x; gy = cp->y; } } } /* look for gold or jewels nearby */ likegold = (index("LOD", msym) != NULL); likegems = (index("ODu", msym) != NULL); likeobjs = mtmp->mhide; #define SRCHRADIUS 25 { xchar mind = SRCHRADIUS; /* not too far away */ register int dd; if(likegold){ register struct gold *gold; for(gold = fgold; gold; gold = gold->ngold) if((dd = DIST(omx,omy,gold->gx,gold->gy)) < mind){ mind = dd; gx = gold->gx; gy = gold->gy; } } if(likegems || likeobjs){ register struct obj *otmp; for(otmp = fobj; otmp; otmp = otmp->nobj) if(likeobjs || otmp->olet == GEM_SYM) if(msym != 'u' || objects[otmp->otyp].g_val != 0) if((dd = DIST(omx,omy,otmp->ox,otmp->oy)) < mind){ mind = dd; gx = otmp->ox; gy = otmp->oy; } } if(mind < SRCHRADIUS && appr == -1) { if(dist(omx,omy) < 10) { gx = u.ux; gy = u.uy; } else appr = 1; } } nix = omx; niy = omy; cnt = mfndpos(mtmp,poss,info, msym == 'u' ? NOTONL : (msym == '@' || msym == '1') ? (ALLOW_SSM | ALLOW_TRAPS) : index(UNDEAD, msym) ? NOGARLIC : ALLOW_TRAPS); /* ALLOW_ROCK for some monsters ? */ chcnt = 0; chi = -1; for(i=0; imtrack[j].x && ny == mtmp->mtrack[j].y) if(rn2(4*(cnt-j))) goto nxti; #ifdef STUPID /* some stupid compilers think that this is too complicated */ { int d1 = DIST(nx,ny,gx,gy); int d2 = DIST(nix,niy,gx,gy); nearer = (d1 < d2); } #else nearer = (DIST(nx,ny,gx,gy) < DIST(nix,niy,gx,gy)); #endif STUPID if((appr == 1 && nearer) || (appr == -1 && !nearer) || !mmoved || (!appr && !rn2(++chcnt))){ nix = nx; niy = ny; chi = i; mmoved = 1; } nxti: ; } if(mmoved){ if(info[chi] & ALLOW_M){ mtmp2 = m_at(nix,niy); if(hitmm(mtmp,mtmp2) == 1 && rn2(4) && hitmm(mtmp2,mtmp) == 2) return(2); return(0); } if(info[chi] & ALLOW_U){ (void) hitu(mtmp, d(mtmp->data->damn, mtmp->data->damd)+1); return(0); } mtmp->mx = nix; mtmp->my = niy; for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1]; mtmp->mtrack[0].x = omx; mtmp->mtrack[0].y = omy; #ifndef NOWORM if(mtmp->wormno) worm_move(mtmp); #endif NOWORM } else { if(msym == 'u' && rn2(2)){ rloc(mtmp); return(0); } #ifndef NOWORM if(mtmp->wormno) worm_nomove(mtmp); #endif NOWORM } postmov: if(mmoved == 1) { if(mintrap(mtmp) == 2) /* he died */ return(2); if(likegold) mpickgold(mtmp); if(likegems) mpickgems(mtmp); if(mtmp->mhide) mtmp->mundetected = 1; } pmon(mtmp); return(mmoved); } mpickgold(mtmp) register struct monst *mtmp; { register struct gold *gold; while(gold = g_at(mtmp->mx, mtmp->my)){ mtmp->mgold += gold->amount; freegold(gold); if(levl[mtmp->mx][mtmp->my].scrsym == '$') newsym(mtmp->mx, mtmp->my); } } mpickgems(mtmp) register struct monst *mtmp; { register struct obj *otmp; for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp->olet == GEM_SYM) if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my) if(mtmp->data->mlet != 'u' || objects[otmp->otyp].g_val != 0){ freeobj(otmp); mpickobj(mtmp, otmp); if(levl[mtmp->mx][mtmp->my].scrsym == GEM_SYM) newsym(mtmp->mx, mtmp->my); /* %% */ return; /* pick only one object */ } } /* return number of acceptable neighbour positions */ mfndpos(mon,poss,info,flag) register struct monst *mon; coord poss[9]; int info[9], flag; { register int x,y,nx,ny,cnt = 0,ntyp; register struct monst *mtmp; int nowtyp; boolean pool; x = mon->mx; y = mon->my; nowtyp = levl[x][y].typ; pool = (mon->data->mlet == ';'); nexttry: /* eels prefer the water, but if there is no water nearby, they will crawl over land */ if(mon->mconf) { flag |= ALLOW_ALL; flag &= ~NOTONL; } for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) if(nx != x || ny != y) if(isok(nx,ny)) if(!IS_ROCK(ntyp = levl[nx][ny].typ)) if(!(nx != x && ny != y && (nowtyp == DOOR || ntyp == DOOR))) if((ntyp == POOL) == pool) { info[cnt] = 0; if(nx == u.ux && ny == u.uy){ if(!(flag & ALLOW_U)) continue; info[cnt] = ALLOW_U; } else if(mtmp = m_at(nx,ny)){ if(!(flag & ALLOW_M)) continue; info[cnt] = ALLOW_M; if(mtmp->mtame){ if(!(flag & ALLOW_TM)) continue; info[cnt] |= ALLOW_TM; } } if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) { if(flag & NOGARLIC) continue; info[cnt] |= NOGARLIC; } if(sobj_at(SCR_SCARE_MONSTER, nx, ny) || (!mon->mpeaceful && sengr_at("Elbereth", nx, ny))) { if(!(flag & ALLOW_SSM)) continue; info[cnt] |= ALLOW_SSM; } if(sobj_at(ENORMOUS_ROCK, nx, ny)) { if(!(flag & ALLOW_ROCK)) continue; info[cnt] |= ALLOW_ROCK; } if(!Invis && online(nx,ny)){ if(flag & NOTONL) continue; info[cnt] |= NOTONL; } /* we cannot avoid traps of an unknown kind */ { register struct trap *ttmp = t_at(nx, ny); register int tt; if(ttmp) { tt = 1 << ttmp->ttyp; if(mon->mtrapseen & tt){ if(!(flag & tt)) continue; info[cnt] |= tt; } } } poss[cnt].x = nx; poss[cnt].y = ny; cnt++; } if(!cnt && pool && nowtyp != POOL) { pool = FALSE; goto nexttry; } return(cnt); } dist(x,y) int x,y; { return((x-u.ux)*(x-u.ux) + (y-u.uy)*(y-u.uy)); } poisoned(string, pname) register char *string, *pname; { register int i; if(Blind) pline("It was poisoned."); else pline("The %s was poisoned!",string); if(Poison_resistance) { pline("The poison doesn't seem to affect you."); return; } i = rn2(10); if(i == 0) { u.uhp = -1; pline("I am afraid the poison was deadly ..."); } else if(i <= 5) { losestr(rn1(3,3)); } else { losehp(rn1(10,6), pname); } if(u.uhp < 1) { killer = pname; done("died"); } } mondead(mtmp) register struct monst *mtmp; { relobj(mtmp,1); unpmon(mtmp); relmon(mtmp); unstuck(mtmp); if(mtmp->isshk) shkdead(mtmp); if(mtmp->isgd) gddead(); #ifndef NOWORM if(mtmp->wormno) wormdead(mtmp); #endif NOWORM monfree(mtmp); } /* called when monster is moved to larger structure */ replmon(mtmp,mtmp2) register struct monst *mtmp, *mtmp2; { relmon(mtmp); monfree(mtmp); mtmp2->nmon = fmon; fmon = mtmp2; if(mtmp2->isshk) replshk(mtmp,mtmp2); if(mtmp2->isgd) replgd(mtmp,mtmp2); } relmon(mon) register struct monst *mon; { register struct monst *mtmp; if(mon == fmon) fmon = fmon->nmon; else { for(mtmp = fmon; mtmp->nmon != mon; mtmp = mtmp->nmon) ; mtmp->nmon = mon->nmon; } } /* we do not free monsters immediately, in order to have their name available shortly after their demise */ struct monst *fdmon; /* chain of dead monsters, need not to be saved */ monfree(mtmp) register struct monst *mtmp; { mtmp->nmon = fdmon; fdmon = mtmp; } dmonsfree(){ register struct monst *mtmp; while(mtmp = fdmon){ fdmon = mtmp->nmon; free((char *) mtmp); } } unstuck(mtmp) register struct monst *mtmp; { if(u.ustuck == mtmp) { if(u.uswallow){ u.ux = mtmp->mx; u.uy = mtmp->my; u.uswallow = 0; setsee(); docrt(); } u.ustuck = 0; } } killed(mtmp) register struct monst *mtmp; { #ifdef lint #define NEW_SCORING #endif lint register int tmp,tmp2,nk,x,y; register struct permonst *mdat = mtmp->data; if(mtmp->cham) mdat = PM_CHAMELEON; if(Blind) pline("You destroy it!"); else { pline("You destroy %s!", mtmp->mtame ? amonnam(mtmp, "poor") : monnam(mtmp)); } if(u.umconf) { if(!Blind) pline("Your hands stop glowing blue."); u.umconf = 0; } /* count killed monsters */ #define MAXMONNO 100 nk = 1; /* in case we cannot find it in mons */ tmp = mdat - mons; /* index in mons array (if not 'd', '@', ...) */ if(tmp >= 0 && tmp < CMNUM+2) { extern char fut_geno[]; u.nr_killed[tmp]++; if((nk = u.nr_killed[tmp]) > MAXMONNO && !index(fut_geno, mdat->mlet)) charcat(fut_geno, mdat->mlet); } /* punish bad behaviour */ if(mdat->mlet == '@') Telepat = 0, u.uluck -= 2; if(mtmp->mpeaceful || mtmp->mtame) u.uluck--; if(mdat->mlet == 'u') u.uluck -= 5; /* give experience points */ tmp = 1 + mdat->mlevel * mdat->mlevel; if(mdat->ac < 3) tmp += 2*(7 - mdat->ac); if(index("AcsSDXaeRTVWU&In:P", mdat->mlet)) tmp += 2*mdat->mlevel; if(index("DeV&P",mdat->mlet)) tmp += (7*mdat->mlevel); if(mdat->mlevel > 6) tmp += 50; if(mdat->mlet == ';') tmp += 1000; #ifdef NEW_SCORING /* ------- recent addition: make nr of points decrease when this is not the first of this kind */ { int ul = u.ulevel; int ml = mdat->mlevel; if(ul < 14) /* points are given based on present and future level */ for(tmp2 = 0; !tmp2 || ul + tmp2 <= ml; tmp2++) if(u.uexp + 1 + (tmp + ((tmp2 <= 0) ? 0 : 4<<(tmp2-1)))/nk >= 10*pow((unsigned)(ul-1))) if(++ul == 14) break; tmp2 = ml - ul -1; tmp = (tmp + ((tmp2 < 0) ? 0 : 4<= 10*pow(u.ulevel-1)){ pline("Welcome to experience level %u.", ++u.ulevel); tmp = rnd(10); if(tmp < 3) tmp = rnd(10); u.uhpmax += tmp; u.uhp += tmp; flags.botl = 1; } /* dispose of monster and make cadaver */ x = mtmp->mx; y = mtmp->my; mondead(mtmp); tmp = mdat->mlet; if(tmp == 'm') { /* he killed a minotaur, give him a wand of digging */ /* note: the dead minotaur will be on top of it! */ mksobj_at(WAN_DIGGING, x, y); /* if(cansee(x,y)) atl(x,y,fobj->olet); */ stackobj(fobj); } else #ifndef NOWORM if(tmp == 'w') { mksobj_at(WORM_TOOTH, x, y); stackobj(fobj); } else #endif NOWORM if(!letter(tmp) || !rn2(3)) tmp = 0; if(ACCESSIBLE(levl[x][y].typ)) /* might be mimic in wall or dead eel*/ if(x != u.ux || y != u.uy) /* might be here after swallowed */ if(index("NTVm&",mdat->mlet) || rn2(5)) { register struct obj *obj2 = mkobj_at(tmp,x,y); if(cansee(x,y)) atl(x,y,obj2->olet); stackobj(obj2); } } kludge(str,arg) register char *str,*arg; { if(Blind) { if(*str == '%') pline(str,"It"); else pline(str,"it"); } else pline(str,arg); } rescham() /* force all chameleons to become normal */ { register struct monst *mtmp; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->cham) { mtmp->cham = 0; (void) newcham(mtmp, PM_CHAMELEON); } } newcham(mtmp,mdat) /* make a chameleon look like a new monster */ /* returns 1 if the monster actually changed */ register struct monst *mtmp; register struct permonst *mdat; { register mhp, hpn, hpd; if(mdat == mtmp->data) return(0); /* still the same monster */ #ifndef NOWORM if(mtmp->wormno) wormdead(mtmp); /* throw tail away */ #endif NOWORM hpn = mtmp->mhp; hpd = (mtmp->data->mlevel)*8; if(!hpd) hpd = 4; mtmp->data = mdat; mhp = (mdat->mlevel)*8; /* new hp: same fraction of max as before */ mtmp->mhp = 2 + (hpn*mhp)/hpd; hpn = mtmp->mhpmax; mtmp->mhpmax = 2 + (hpn*mhp)/hpd; mtmp->minvis = (mdat->mlet == 'I') ? 1 : 0; #ifndef NOWORM if(mdat->mlet == 'w' && getwn(mtmp)) initworm(mtmp); /* perhaps we should clear mtmp->mtame here? */ #endif NOWORM unpmon(mtmp); /* necessary for 'I' and to force pmon */ pmon(mtmp); return(1); } mnexto(mtmp) /* Make monster mtmp next to you (if possible) */ struct monst *mtmp; { extern coord enexto(); coord mm; mm = enexto(u.ux, u.uy); mtmp->mx = mm.x; mtmp->my = mm.y; pmon(mtmp); } ishuman(mtmp) register struct monst *mtmp; { return(mtmp->data->mlet == '@'); } setmangry(mtmp) register struct monst *mtmp; { if(!mtmp->mpeaceful) return; if(mtmp->mtame) return; mtmp->mpeaceful = 0; if(ishuman(mtmp)) pline("%s gets angry!", Monnam(mtmp)); } /* not one hundred procent correct: now a snake may hide under an invisible object */ canseemon(mtmp) register struct monst *mtmp; { return((!mtmp->minvis || See_invisible) && (!mtmp->mhide || !o_at(mtmp->mx,mtmp->my)) && cansee(mtmp->mx, mtmp->my)); } //E*O*F hack.mon.c// echo x - hack.mhitu.c cat > "hack.mhitu.c" << '//E*O*F hack.mhitu.c//' /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.mhitu.c - version 1.0.2 */ #include "hack.h" extern struct monst *makemon(); /* * mhitu: monster hits you * returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise */ mhitu(mtmp) register struct monst *mtmp; { register struct permonst *mdat = mtmp->data; register int tmp, ctmp; nomul(0); /* If swallowed, can only be affected by hissers and by u.ustuck */ if(u.uswallow) { if(mtmp != u.ustuck) { if(mdat->mlet == 'c' && !rn2(13)) { pline("Outside, you hear %s's hissing!", monnam(mtmp)); pline("%s gets turned to stone!", Monnam(u.ustuck)); pline("And the same fate befalls you."); done_in_by(mtmp); /* notreached: return(1); */ } return(0); } switch(mdat->mlet) { /* now mtmp == u.ustuck */ case ',': youswld(mtmp, (u.uac > 0) ? u.uac+4 : 4, 5, "The trapper"); break; case '\'': youswld(mtmp,rnd(6),7,"The lurker above"); break; case 'P': youswld(mtmp,d(2,4),12,"The purple worm"); break; default: /* This is not impossible! */ pline("The mysterious monster totally digests you."); u.uhp = 0; } if(u.uhp < 1) done_in_by(mtmp); return(0); } /* make eels visible the moment they hit/miss us */ if(mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx,mtmp->my)){ mtmp->minvis = 0; pmon(mtmp); } if(!index("1&DuxynNF",mdat->mlet)) tmp = hitu(mtmp,d(mdat->damn,mdat->damd)); else tmp = 0; if(index(UNDEAD, mdat->mlet) && midnight()) tmp += hitu(mtmp,d(mdat->damn,mdat->damd)); ctmp = tmp && !mtmp->mcan && (!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50)); switch(mdat->mlet) { case '1': if(wiz_hit(mtmp)) return(1); /* he disappeared */ break; case '&': if(!mtmp->cham && !mtmp->mcan && !rn2(13)) { (void) makemon(PM_DEMON,u.ux,u.uy); } else { (void) hitu(mtmp,d(2,6)); (void) hitu(mtmp,d(2,6)); (void) hitu(mtmp,rnd(3)); (void) hitu(mtmp,rnd(3)); (void) hitu(mtmp,rn1(4,2)); } break; case ',': if(tmp) justswld(mtmp,"The trapper"); break; case '\'': if(tmp) justswld(mtmp, "The lurker above"); break; case ';': if(ctmp) { if(!u.ustuck && !rn2(10)) { pline("%s swings itself around you!", Monnam(mtmp)); u.ustuck = mtmp; } else if(u.ustuck == mtmp && levl[mtmp->mx][mtmp->my].typ == POOL) { pline("%s drowns you ...", Monnam(mtmp)); done("drowned"); } } break; case 'A': if(ctmp && rn2(2)) { pline("You feel weaker!"); losestr(1); } break; case 'C': (void) hitu(mtmp,rnd(6)); break; case 'c': if(!rn2(5)) { pline("You hear %s's hissing!", monnam(mtmp)); if(ctmp || !rn2(20) || (flags.moonphase == NEW_MOON && !carrying(DEAD_LIZARD))) { pline("You get turned to stone!"); done_in_by(mtmp); } } break; case 'D': if(rn2(6) || mtmp->mcan) { (void) hitu(mtmp,d(3,10)); (void) hitu(mtmp,rnd(8)); (void) hitu(mtmp,rnd(8)); break; } kludge("%s breathes fire!","The dragon"); buzz(-1,mtmp->mx,mtmp->my,u.ux-mtmp->mx,u.uy-mtmp->my); break; case 'd': (void) hitu(mtmp,d(2, (flags.moonphase == FULL_MOON) ? 3 : 4)); break; case 'e': (void) hitu(mtmp,d(3,6)); break; case 'F': if(mtmp->mcan) break; kludge("%s explodes!","The freezing sphere"); if(Cold_resistance) pline("You don't seem affected by it."); else { xchar dn; if(17-(u.ulevel/2) > rnd(20)) { pline("You get blasted!"); dn = 6; } else { pline("You duck the blast..."); dn = 3; } losehp_m(d(dn,6), mtmp); } mondead(mtmp); return(1); case 'g': if(ctmp && multi >= 0 && !rn2(6)) { kludge("You are frozen by %ss juices","the cube'"); nomul(-rnd(10)); } break; case 'h': if(ctmp && multi >= 0 && !rn2(5)) { nomul(-rnd(10)); kludge("You are put to sleep by %ss bite!", "the homunculus'"); } break; case 'j': tmp = hitu(mtmp,rnd(3)); tmp &= hitu(mtmp,rnd(3)); if(tmp){ (void) hitu(mtmp,rnd(4)); (void) hitu(mtmp,rnd(4)); } break; case 'k': if((hitu(mtmp,rnd(4)) || !rn2(3)) && ctmp){ poisoned("bee's sting",mdat->mname); } break; case 'L': if(tmp) stealgold(mtmp); break; case 'N': if(mtmp->mcan && !Blind) { pline("%s tries to seduce you, but you seem not interested.", Amonnam(mtmp, "plain")); if(rn2(3)) rloc(mtmp); } else if(steal(mtmp)) { rloc(mtmp); mtmp->mflee = 1; } break; case 'n': if(!uwep && !uarm && !uarmh && !uarms && !uarmg) { pline("%s hits! (I hope you don't mind)", Monnam(mtmp)); u.uhp += rnd(7); if(!rn2(7)) u.uhpmax++; if(u.uhp > u.uhpmax) u.uhp = u.uhpmax; flags.botl = 1; if(!rn2(50)) rloc(mtmp); } else { (void) hitu(mtmp,d(2,6)); (void) hitu(mtmp,d(2,6)); } break; case 'o': tmp = hitu(mtmp,rnd(6)); if(hitu(mtmp,rnd(6)) && ctmp && !u.ustuck && rn2(2)) { u.ustuck = mtmp; kludge("%s has grabbed you!","The owlbear"); u.uhp -= d(2,8); } else if(u.ustuck == mtmp) { u.uhp -= d(2,8); pline("You are being crushed."); } break; case 'P': if(ctmp && !rn2(4)) justswld(mtmp,"The purple worm"); else (void) hitu(mtmp,d(2,4)); break; case 'Q': (void) hitu(mtmp,rnd(2)); (void) hitu(mtmp,rnd(2)); break; case 'R': if(tmp && uarmh && !uarmh->rustfree && (int) uarmh->spe >= -1) { pline("Your helmet rusts!"); uarmh->spe--; } else if(ctmp && uarm && !uarm->rustfree && /* Mike Newton */ uarm->otyp < STUDDED_LEATHER_ARMOR && (int) uarm->spe >= -1) { pline("Your armor rusts!"); uarm->spe--; } break; case 'S': if(ctmp && !rn2(8)) { poisoned("snake's bite",mdat->mname); } break; case 's': if(tmp && !rn2(8)) { poisoned("scorpion's sting",mdat->mname); } (void) hitu(mtmp,rnd(8)); (void) hitu(mtmp,rnd(8)); break; case 'T': (void) hitu(mtmp,rnd(6)); (void) hitu(mtmp,rnd(6)); break; case 't': if(!rn2(5)) rloc(mtmp); break; case 'u': mtmp->mflee = 1; break; case 'U': (void) hitu(mtmp,d(3,4)); (void) hitu(mtmp,d(3,4)); break; case 'v': if(ctmp && !u.ustuck) u.ustuck = mtmp; break; case 'V': if(tmp) u.uhp -= 4; if(ctmp) losexp(); break; case 'W': if(ctmp) losexp(); break; #ifndef NOWORM case 'w': if(tmp) wormhit(mtmp); #endif NOWORM break; case 'X': (void) hitu(mtmp,rnd(5)); (void) hitu(mtmp,rnd(5)); (void) hitu(mtmp,rnd(5)); break; case 'x': { register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE; pline("%s pricks in your %s leg!", Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left"); Wounded_legs |= side + rnd(5); losehp_m(2, mtmp); break; } case 'y': if(mtmp->mcan) break; mondead(mtmp); if(!Blind) { pline("You are blinded by a blast of light!"); Blind = d(4,12); seeoff(0); } return(1); case 'Y': (void) hitu(mtmp,rnd(6)); break; } if(u.uhp < 1) done_in_by(mtmp); return(0); } hitu(mtmp,dam) register struct monst *mtmp; register dam; { register tmp, res; if(u.uswallow) return(0); if(mtmp->mhide && mtmp->mundetected) { mtmp->mundetected = 0; if(!Blind) { register struct obj *obj; extern char * Xmonnam(); if(obj = o_at(mtmp->mx,mtmp->my)) pline("%s was hidden under %s!", Xmonnam(mtmp), doname(obj)); } } tmp = u.uac; /* give people with Ac = -10 at least some vulnerability */ if(tmp < 0) { dam += tmp; /* decrease damage */ if(dam <= 0) dam = 1; tmp = -rn2(-tmp); } tmp += mtmp->data->mlevel; if(multi < 0) tmp += 4; if(Invis || !mtmp->mcansee) tmp -= 2; if(mtmp->mtrapped) tmp -= 2; if(tmp <= rnd(20)) { if(Blind) pline("It misses."); else pline("%s misses.",Monnam(mtmp)); res = 0; } else { if(Blind) pline("It hits!"); else pline("%s hits!",Monnam(mtmp)); losehp_m(dam, mtmp); res = 1; } stop_occupation(); return(res); } //E*O*F hack.mhitu.c// echo x - hack.monst.c cat > "hack.monst.c" << '//E*O*F hack.monst.c//' /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.monst.c - version 1.0.2 */ #include "hack.h" #include "def.eshk.h" extern char plname[PL_NSIZ]; struct permonst mons[CMNUM+2] = { { "bat", 'B',1,22,8,1,4,0 }, { "gnome", 'G',1,6,5,1,6,0 }, { "hobgoblin", 'H',1,9,5,1,8,0 }, { "jackal", 'J',0,12,7,1,2,0 }, { "kobold", 'K',1,6,7,1,4,0 }, { "leprechaun", 'L',5,15,8,1,2,0 }, { "giant rat", 'r',0,12,7,1,3,0 }, { "acid blob", 'a',2,3,8,0,0,0 }, { "floating eye", 'E',2,1,9,0,0,0 }, { "homunculus", 'h',2,6,6,1,3,0 }, { "imp", 'i',2,6,2,1,4,0 }, { "orc", 'O',2,9,6,1,8,0 }, { "yellow light", 'y',3,15,0,0,0,0 }, { "zombie", 'Z',2,6,8,1,8,0 }, { "giant ant", 'A',3,18,3,1,6,0 }, { "fog cloud", 'f',3,1,0,1,6,0 }, { "nymph", 'N',6,12,9,1,2,0 }, { "piercer", 'p',3,1,3,2,6,0 }, { "quasit", 'Q',3,15,3,1,4,0 }, { "quivering blob", 'q',3,1,8,1,8,0 }, { "violet fungi", 'v',3,1,7,1,4,0 }, { "giant beetle", 'b',4,6,4,3,4,0 }, { "centaur", 'C',4,18,4,1,6,0 }, { "cockatrice", 'c',4,6,6,1,3,0 }, { "gelatinous cube", 'g',4,6,8,2,4,0 }, { "jaguar", 'j',4,15,6,1,8,0 }, { "killer bee", 'k',4,14,4,2,4,0 }, { "snake", 'S',4,15,3,1,6,0 }, { "freezing sphere", 'F',2,13,4,0,0,0 }, { "owlbear", 'o',5,12,5,2,6,0 }, { "rust monster", 'R',10,18,3,0,0,0 }, { "scorpion", 's',5,15,3,1,4,0 }, { "tengu", 't',5,13,5,1,7,0 }, { "wraith", 'W',5,12,5,1,6,0 }, #ifdef NOWORM { "wumpus", 'w',8,3,2,3,6,0 }, #else { "long worm", 'w',8,3,5,1,4,0 }, #endif NOWORM { "large dog", 'd',6,15,4,2,4,0 }, { "leocrotta", 'l',6,18,4,3,6,0 }, { "mimic", 'M',7,3,7,3,4,0 }, { "troll", 'T',7,12,4,2,7,0 }, { "unicorn", 'u',8,24,5,1,10,0 }, { "yeti", 'Y',5,15,6,1,6,0 }, { "stalker", 'I',8,12,3,4,4,0 }, { "umber hulk", 'U',9,6,2,2,10,0 }, { "vampire", 'V',8,12,1,1,6,0 }, { "xorn", 'X',8,9,-2,4,6,0 }, { "xan", 'x',7,18,-2,2,4,0 }, { "zruty", 'z',9,8,3,3,6,0 }, { "chameleon", ':',6,5,6,4,2,0 }, { "dragon", 'D',10,9,-1,3,8,0 }, { "ettin", 'e',10,12,3,2,8,0 }, { "lurker above", '\'',10,3,3,0,0,0 }, { "nurse", 'n',11,6,0,1,3,0 }, { "trapper", ',',12,3,3,0,0,0 }, { "purple worm", 'P',15,9,6,2,8,0 }, { "demon", '&',10,12,-4,1,4,0 }, { "minotaur", 'm',15,15,6,4,10,0 }, { "shopkeeper", '@', 12, 18, 0, 4, 8, sizeof(struct eshk) } }; struct permonst pm_ghost = { "ghost", ' ', 10, 3, -5, 1, 1, sizeof(plname) }; struct permonst pm_wizard = { "wizard of Yendor", '1', 15, 12, -2, 1, 12, 0 }; #ifdef MAIL struct permonst pm_mail_daemon = { "mail daemon", '2', 100, 1, 10, 0, 0, 0 }; #endif MAIL struct permonst pm_eel = { "giant eel", ';', 15, 6, -3, 3, 6, 0 }; //E*O*F hack.monst.c// echo x - hack.mklev.c cat > "hack.mklev.c" << '//E*O*F hack.mklev.c//' /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.mklev.c - version 1.0.2 */ #include "hack.h" extern char *getlogin(), *getenv(); extern struct monst *makemon(); extern struct obj *mkobj_at(); extern struct trap *maketrap(); #define somex() ((rand()%(croom->hx-croom->lx+1))+croom->lx) #define somey() ((rand()%(croom->hy-croom->ly+1))+croom->ly) #include "def.mkroom.h" #define XLIM 4 /* define minimum required space around a room */ #define YLIM 3 boolean secret; /* TRUE while making a vault: increase [XY]LIM */ struct mkroom rooms[MAXNROFROOMS+1]; int smeq[MAXNROFROOMS+1]; coord doors[DOORMAX]; int doorindex; struct rm zerorm; int comp(); schar nxcor; boolean goldseen; int nroom; xchar xdnstair,xupstair,ydnstair,yupstair; /* Definitions used by makerooms() and addrs() */ #define MAXRS 50 /* max lth of temp rectangle table - arbitrary */ struct rectangle { xchar lx,ly,hx,hy; } rs[MAXRS+1]; int rscnt,rsmax; /* 0..rscnt-1: currently under consideration */ /* rscnt..rsmax: discarded */ makelevel() { register struct mkroom *croom, *troom; register unsigned tryct; register x,y; nroom = 0; doorindex = 0; rooms[0].hx = -1; /* in case we are in a maze */ for(x=0; x= rn1(3, 26)) { /* there might be several mazes */ makemaz(); return; } /* construct the rooms */ nroom = 0; secret = FALSE; (void) makerooms(); /* construct stairs (up and down in different rooms if possible) */ croom = &rooms[rn2(nroom)]; xdnstair = somex(); ydnstair = somey(); levl[xdnstair][ydnstair].scrsym ='>'; levl[xdnstair][ydnstair].typ = STAIRS; if(nroom > 1) { troom = croom; croom = &rooms[rn2(nroom-1)]; if(croom >= troom) croom++; } xupstair = somex(); /* %% < and > might be in the same place */ yupstair = somey(); levl[xupstair][yupstair].scrsym ='<'; levl[xupstair][yupstair].typ = STAIRS; /* for each room: put things inside */ for(croom = rooms; croom->hx > 0; croom++) { /* put a sleeping monster inside */ /* Note: monster may be on the stairs. This cannot be avoided: maybe the player fell through a trapdoor while a monster was on the stairs. Conclusion: we have to check for monsters on the stairs anyway. */ if(!rn2(3)) (void) makemon((struct permonst *) 0, somex(), somey()); /* put traps and mimics inside */ goldseen = FALSE; while(!rn2(8-(dlevel/6))) mktrap(0,0,croom); if(!goldseen && !rn2(3)) mkgold(0L,somex(),somey()); if(!rn2(3)) { (void) mkobj_at(0, somex(), somey()); tryct = 0; while(!rn2(5)) { if(++tryct > 100){ printf("tryct overflow4\n"); break; } (void) mkobj_at(0, somex(), somey()); } } } qsort((char *) rooms, nroom, sizeof(struct mkroom), comp); makecorridors(); make_niches(); /* make a secret treasure vault, not connected to the rest */ if(nroom <= (2*MAXNROFROOMS/3)) if(rn2(3)) { troom = &rooms[nroom]; secret = TRUE; if(makerooms()) { troom->rtype = VAULT; /* treasure vault */ for(x = troom->lx; x <= troom->hx; x++) for(y = troom->ly; y <= troom->hy; y++) mkgold((long)(rnd(dlevel*100) + 50), x, y); if(!rn2(3)) makevtele(); } } #ifdef WIZARD if(wizard && getenv("SHOPTYPE")) mkshop(); else #endif WIZARD if(dlevel > 1 && dlevel < 20 && rn2(dlevel) < 3) mkshop(); else if(dlevel > 6 && !rn2(7)) mkzoo(ZOO); else if(dlevel > 9 && !rn2(5)) mkzoo(BEEHIVE); else if(dlevel > 11 && !rn2(6)) mkzoo(MORGUE); else if(dlevel > 18 && !rn2(6)) mkswamp(); } makerooms() { register struct rectangle *rsp; register int lx, ly, hx, hy, lowx, lowy, hix, hiy, dx, dy; int tryct = 0, xlim, ylim; /* init */ xlim = XLIM + secret; ylim = YLIM + secret; if(nroom == 0) { rsp = rs; rsp->lx = rsp->ly = 0; rsp->hx = COLNO-1; rsp->hy = ROWNO-1; rsmax = 1; } rscnt = rsmax; /* make rooms until satisfied */ while(rscnt > 0 && nroom < MAXNROFROOMS-1) { if(!secret && nroom > (MAXNROFROOMS/3) && !rn2((MAXNROFROOMS-nroom)*(MAXNROFROOMS-nroom))) return(0); /* pick a rectangle */ rsp = &rs[rn2(rscnt)]; hx = rsp->hx; hy = rsp->hy; lx = rsp->lx; ly = rsp->ly; /* find size of room */ if(secret) dx = dy = 1; else { dx = 2 + rn2((hx-lx-8 > 20) ? 12 : 8); dy = 2 + rn2(4); if(dx*dy > 50) dy = 50/dx; } /* look whether our room will fit */ if(hx-lx < dx + dx/2 + 2*xlim || hy-ly < dy + dy/3 + 2*ylim) { /* no, too small */ /* maybe we throw this area out */ if(secret || !rn2(MAXNROFROOMS+1-nroom-tryct)) { rscnt--; rs[rsmax] = *rsp; *rsp = rs[rscnt]; rs[rscnt] = rs[rsmax]; tryct = 0; } else tryct++; continue; } lowx = lx + xlim + rn2(hx - lx - dx - 2*xlim + 1); lowy = ly + ylim + rn2(hy - ly - dy - 2*ylim + 1); hix = lowx + dx; hiy = lowy + dy; if(maker(lowx, dx, lowy, dy)) { if(secret) return(1); addrs(lowx-1, lowy-1, hix+1, hiy+1); tryct = 0; } else if(tryct++ > 100) break; } return(0); /* failed to make vault - very strange */ } addrs(lowx,lowy,hix,hiy) register int lowx,lowy,hix,hiy; { register struct rectangle *rsp; register int lx,ly,hx,hy,xlim,ylim; boolean discarded; xlim = XLIM + secret; ylim = YLIM + secret; /* walk down since rscnt and rsmax change */ for(rsp = &rs[rsmax-1]; rsp >= rs; rsp--) { if((lx = rsp->lx) > hix || (ly = rsp->ly) > hiy || (hx = rsp->hx) < lowx || (hy = rsp->hy) < lowy) continue; if((discarded = (rsp >= &rs[rscnt]))) { *rsp = rs[--rsmax]; } else { rsmax--; rscnt--; *rsp = rs[rscnt]; if(rscnt != rsmax) rs[rscnt] = rs[rsmax]; } if(lowy - ly > 2*ylim + 4) addrsx(lx,ly,hx,lowy-2,discarded); if(lowx - lx > 2*xlim + 4) addrsx(lx,ly,lowx-2,hy,discarded); if(hy - hiy > 2*ylim + 4) addrsx(lx,hiy+2,hx,hy,discarded); if(hx - hix > 2*xlim + 4) addrsx(hix+2,ly,hx,hy,discarded); } } addrsx(lx,ly,hx,hy,discarded) register int lx,ly,hx,hy; boolean discarded; /* piece of a discarded area */ { register struct rectangle *rsp; /* check inclusions */ for(rsp = rs; rsp < &rs[rsmax]; rsp++) { if(lx >= rsp->lx && hx <= rsp->hx && ly >= rsp->ly && hy <= rsp->hy) return; } /* make a new entry */ if(rsmax >= MAXRS) { #ifdef WIZARD if(wizard) pline("MAXRS may be too small."); #endif WIZARD return; } rsmax++; if(!discarded) { *rsp = rs[rscnt]; rsp = &rs[rscnt]; rscnt++; } rsp->lx = lx; rsp->ly = ly; rsp->hx = hx; rsp->hy = hy; } comp(x,y) register struct mkroom *x,*y; { if(x->lx < y->lx) return(-1); return(x->lx > y->lx); } coord finddpos(xl,yl,xh,yh) { coord ff; register x,y; x = (xl == xh) ? xl : (xl + rn2(xh-xl+1)); y = (yl == yh) ? yl : (yl + rn2(yh-yl+1)); if(okdoor(x, y)) goto gotit; for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++) if(okdoor(x, y)) goto gotit; for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++) if(levl[x][y].typ == DOOR || levl[x][y].typ == SDOOR) goto gotit; /* cannot find something reasonable -- strange */ x = xl; y = yh; gotit: ff.x = x; ff.y = y; return(ff); } /* if allowable, create a door at [x,y] */ okdoor(x,y) register x,y; { if(levl[x-1][y].typ == DOOR || levl[x+1][y].typ == DOOR || levl[x][y+1].typ == DOOR || levl[x][y-1].typ == DOOR || levl[x-1][y].typ == SDOOR || levl[x+1][y].typ == SDOOR || levl[x][y-1].typ == SDOOR || levl[x][y+1].typ == SDOOR || (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) || doorindex >= DOORMAX) return(0); return(1); } dodoor(x,y,aroom) register x,y; register struct mkroom *aroom; { if(doorindex >= DOORMAX) { impossible("DOORMAX exceeded?"); return; } if(!okdoor(x,y) && nxcor) return; dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR); } dosdoor(x,y,aroom,type) register x,y; register struct mkroom *aroom; register type; { register struct mkroom *broom; register tmp; levl[x][y].typ = type; if(type == DOOR) levl[x][y].scrsym ='+'; aroom->doorct++; broom = aroom+1; if(broom->hx < 0) tmp = doorindex; else for(tmp = doorindex; tmp > broom->fdoor; tmp--) doors[tmp] = doors[tmp-1]; doorindex++; doors[tmp].x = x; doors[tmp].y = y; for( ; broom->hx >= 0; broom++) broom->fdoor++; } /* Only called from makerooms() */ maker(lowx,ddx,lowy,ddy) schar lowx,ddx,lowy,ddy; { register struct mkroom *croom; register x, y, hix = lowx+ddx, hiy = lowy+ddy; register xlim = XLIM + secret, ylim = YLIM + secret; if(nroom >= MAXNROFROOMS) return(0); if(lowx < XLIM) lowx = XLIM; if(lowy < YLIM) lowy = YLIM; if(hix > COLNO-XLIM-1) hix = COLNO-XLIM-1; if(hiy > ROWNO-YLIM-1) hiy = ROWNO-YLIM-1; chk: if(hix <= lowx || hiy <= lowy) return(0); /* check area around room (and make room smaller if necessary) */ for(x = lowx - xlim; x <= hix + xlim; x++) { for(y = lowy - ylim; y <= hiy + ylim; y++) { if(levl[x][y].typ) { #ifdef WIZARD if(wizard && !secret) pline("Strange area [%d,%d] in maker()",x,y); #endif WIZARD if(!rn2(3)) return(0); if(x < lowx) lowx = x+xlim+1; else hix = x-xlim-1; if(y < lowy) lowy = y+ylim+1; else hiy = y-ylim-1; goto chk; } } } croom = &rooms[nroom]; /* on low levels the room is lit (usually) */ /* secret vaults are always lit */ if((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1)) { for(x = lowx-1; x <= hix+1; x++) for(y = lowy-1; y <= hiy+1; y++) levl[x][y].lit = 1; croom->rlit = 1; } else croom->rlit = 0; croom->lx = lowx; croom->hx = hix; croom->ly = lowy; croom->hy = hiy; croom->rtype = croom->doorct = croom->fdoor = 0; for(x = lowx-1; x <= hix+1; x++) for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) { levl[x][y].scrsym = '-'; levl[x][y].typ = HWALL; } for(x = lowx-1; x <= hix+1; x += (hix-lowx+2)) for(y = lowy; y <= hiy; y++) { levl[x][y].scrsym = '|'; levl[x][y].typ = VWALL; } for(x = lowx; x <= hix; x++) for(y = lowy; y <= hiy; y++) { levl[x][y].scrsym = '.'; levl[x][y].typ = ROOM; } smeq[nroom] = nroom; croom++; croom->hx = -1; nroom++; return(1); } makecorridors() { register a,b; nxcor = 0; for(a = 0; a < nroom-1; a++) join(a, a+1); for(a = 0; a < nroom-2; a++) if(smeq[a] != smeq[a+2]) join(a, a+2); for(a = 0; a < nroom; a++) for(b = 0; b < nroom; b++) if(smeq[a] != smeq[b]) join(a, b); if(nroom > 2) for(nxcor = rn2(nroom) + 4; nxcor; nxcor--) { a = rn2(nroom); b = rn2(nroom-2); if(b >= a) b += 2; join(a, b); } } join(a,b) register a,b; { coord cc,tt; register tx, ty, xx, yy; register struct rm *crm; register struct mkroom *croom, *troom; register dx, dy, dix, diy, cct; croom = &rooms[a]; troom = &rooms[b]; /* find positions cc and tt for doors in croom and troom and direction for a corridor between them */ if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return; if(troom->lx > croom->hx) { dx = 1; dy = 0; xx = croom->hx+1; tx = troom->lx-1; cc = finddpos(xx,croom->ly,xx,croom->hy); tt = finddpos(tx,troom->ly,tx,troom->hy); } else if(troom->hy < croom->ly) { dy = -1; dx = 0; yy = croom->ly-1; cc = finddpos(croom->lx,yy,croom->hx,yy); ty = troom->hy+1; tt = finddpos(troom->lx,ty,troom->hx,ty); } else if(troom->hx < croom->lx) { dx = -1; dy = 0; xx = croom->lx-1; tx = troom->hx+1; cc = finddpos(xx,croom->ly,xx,croom->hy); tt = finddpos(tx,troom->ly,tx,troom->hy); } else { dy = 1; dx = 0; yy = croom->hy+1; ty = troom->ly-1; cc = finddpos(croom->lx,yy,croom->hx,yy); tt = finddpos(troom->lx,ty,troom->hx,ty); } xx = cc.x; yy = cc.y; tx = tt.x - dx; ty = tt.y - dy; if(nxcor && levl[xx+dx][yy+dy].typ) return; dodoor(xx,yy,croom); cct = 0; while(xx != tx || yy != ty) { xx += dx; yy += dy; /* loop: dig corridor at [xx,yy] and find new [xx,yy] */ if(cct++ > 500 || (nxcor && !rn2(35))) return; if(xx == COLNO-1 || xx == 0 || yy == 0 || yy == ROWNO-1) return; /* impossible */ crm = &levl[xx][yy]; if(!(crm->typ)) { if(rn2(100)) { crm->typ = CORR; crm->scrsym = CORR_SYM; if(nxcor && !rn2(50)) (void) mkobj_at(ROCK_SYM, xx, yy); } else { crm->typ = SCORR; crm->scrsym = ' '; } } else if(crm->typ != CORR && crm->typ != SCORR) { /* strange ... */ return; } /* find next corridor position */ dix = abs(xx-tx); diy = abs(yy-ty); /* do we have to change direction ? */ if(dy && dix > diy) { register ddx = (xx > tx) ? -1 : 1; crm = &levl[xx+ddx][yy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) { dx = ddx; dy = 0; continue; } } else if(dx && diy > dix) { register ddy = (yy > ty) ? -1 : 1; crm = &levl[xx][yy+ddy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) { dy = ddy; dx = 0; continue; } } /* continue straight on? */ crm = &levl[xx+dx][yy+dy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) continue; /* no, what must we do now?? */ if(dx) { dx = 0; dy = (ty < yy) ? -1 : 1; crm = &levl[xx+dx][yy+dy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) continue; dy = -dy; continue; } else { dy = 0; dx = (tx < xx) ? -1 : 1; crm = &levl[xx+dx][yy+dy]; if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) continue; dx = -dx; continue; } } /* we succeeded in digging the corridor */ dodoor(tt.x, tt.y, troom); if(smeq[a] < smeq[b]) smeq[b] = smeq[a]; else smeq[a] = smeq[b]; } make_niches() { register int ct = rn2(nroom/2 + 1)+1; while(ct--) makeniche(FALSE); } makevtele() { makeniche(TRUE); } makeniche(with_trap) boolean with_trap; { register struct mkroom *aroom; register struct rm *rm; register int vct = 8; coord dd; register dy,xx,yy; register struct trap *ttmp; if(doorindex < DOORMAX) while(vct--) { aroom = &rooms[rn2(nroom-1)]; if(aroom->rtype != 0) continue; /* not an ordinary room */ if(aroom->doorct == 1 && rn2(5)) continue; if(rn2(2)) { dy = 1; dd = finddpos(aroom->lx,aroom->hy+1,aroom->hx,aroom->hy+1); } else { dy = -1; dd = finddpos(aroom->lx,aroom->ly-1,aroom->hx,aroom->ly-1); } xx = dd.x; yy = dd.y; if((rm = &levl[xx][yy+dy])->typ) continue; if(with_trap || !rn2(4)) { rm->typ = SCORR; rm->scrsym = ' '; if(with_trap) { ttmp = maketrap(xx, yy+dy, TELEP_TRAP); ttmp->once = 1; make_engr_at(xx,yy-dy,"ad ae?ar um"); } dosdoor(xx,yy,aroom,SDOOR); } else { rm->typ = CORR; rm->scrsym = CORR_SYM; if(rn2(7)) dosdoor(xx,yy,aroom,rn2(5) ? SDOOR : DOOR); else { mksobj_at(SCR_TELEPORTATION,xx,yy+dy); if(!rn2(3)) (void) mkobj_at(0,xx,yy+dy); } } return; } } /* make a trap somewhere (in croom if mazeflag = 0) */ mktrap(num,mazeflag,croom) register num,mazeflag; register struct mkroom *croom; { register struct trap *ttmp; register int kind,nopierc,nomimic,fakedoor,fakegold,tryct = 0; register xchar mx,my; extern char fut_geno[]; if(!num || num >= TRAPNUM) { nopierc = (dlevel < 4) ? 1 : 0; nomimic = (dlevel < 9 || goldseen ) ? 1 : 0; if(index(fut_geno, 'M')) nomimic = 1; kind = rn2(TRAPNUM - nopierc - nomimic); /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */ } else kind = num; if(kind == MIMIC) { register struct monst *mtmp; fakedoor = (!rn2(3) && !mazeflag); fakegold = (!fakedoor && !rn2(2)); if(fakegold) goldseen = TRUE; do { if(++tryct > 200) return; if(fakedoor) { /* note: fakedoor maybe on actual door */ if(rn2(2)){ if(rn2(2)) mx = croom->hx+1; else mx = croom->lx-1; my = somey(); } else { if(rn2(2)) my = croom->hy+1; else my = croom->ly-1; mx = somex(); } } else if(mazeflag) { extern coord mazexy(); coord mm; mm = mazexy(); mx = mm.x; my = mm.y; } else { mx = somex(); my = somey(); } } while(m_at(mx,my) || levl[mx][my].typ == STAIRS); if(mtmp = makemon(PM_MIMIC,mx,my)) { mtmp->mimic = 1; mtmp->mappearance = fakegold ? '$' : fakedoor ? '+' : (mazeflag && rn2(2)) ? AMULET_SYM : "=/)%?![<>" [ rn2(9) ]; } return; } do { if(++tryct > 200) return; if(mazeflag){ extern coord mazexy(); coord mm; mm = mazexy(); mx = mm.x; my = mm.y; } else { mx = somex(); my = somey(); } } while(t_at(mx, my) || levl[mx][my].typ == STAIRS); ttmp = maketrap(mx, my, kind); if(mazeflag && !rn2(10) && ttmp->ttyp < PIERC) ttmp->tseen = 1; } //E*O*F hack.mklev.c// exit 0