billr@saab.CNA.TEK.COM (Bill Randle) (07/24/89)
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu> Posting-number: Volume 7, Issue 69 Archive-name: NetHack3/Part14 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 14 (of 38)." # Contents: include/coord.h src/monmove.c src/read.c # Wrapped by billr@saab on Sun Jul 23 21:32:57 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'include/coord.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'include/coord.h'\" else echo shar: Extracting \"'include/coord.h'\" \(272 characters\) sed "s/^X//" >'include/coord.h' <<'END_OF_FILE' X/* SCCS Id: @(#)coord.h 3.0 88/04/25 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#ifndef COORD_H X#define COORD_H X Xtypedef struct { X xchar x,y; X} coord; X X#endif /* COORD_H /* */ END_OF_FILE if test 272 -ne `wc -c <'include/coord.h'`; then echo shar: \"'include/coord.h'\" unpacked with wrong size! fi # end of 'include/coord.h' fi if test -f 'src/monmove.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/monmove.c'\" else echo shar: Extracting \"'src/monmove.c'\" \(20241 characters\) sed "s/^X//" >'src/monmove.c' <<'END_OF_FILE' X/* SCCS Id: @(#)monmove.c 3.0 88/11/10 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X#include "mfndpos.h" X#ifdef NAMED_ITEMS X# include "artifact.h" X#endif X Xstatic boolean /* TRUE : mtmp died */ Xmb_trapped(mtmp) Xregister struct monst *mtmp; X{ X if (flags.verbose) { X if (cansee(mtmp->mx, mtmp->my)) X pline("KABOOM!! You see a door explode."); X else if (flags.soundok) X You("hear a distant explosion."); X } X mtmp->mstun = 1; X mtmp->mhp -= rnd(15); X if(mtmp->mhp <= 0) { X mondied(mtmp); X return(TRUE); X } X return(FALSE); X} X Xboolean Xmdig_tunnel(mtmp) /* FALSE: monster died */ Xregister struct monst *mtmp; X{ X register struct rm *here; X register int pile = rnd(12); X boolean canseeit = cansee(mtmp->mx, mtmp->my); X here = &levl[mtmp->mx][mtmp->my]; X X if(IS_ROCK(here->typ)) { X /* Just ate something. */ X if(here->typ == STONE) here->typ = CORR; X else if(IS_WALL(here->typ) && X !(here->diggable & W_NONDIGGABLE)) { X if(flags.soundok && flags.verbose && !rn2(5)) X You("hear the sound of crashing rock."); X here->typ = DOOR; X here->doormask = D_NODOOR; X } X } X /* Eats away door if present & closed or locked */ X else if(IS_DOOR(here->typ) && X (here->doormask & (D_LOCKED | D_CLOSED))) { X if(here->doormask & D_TRAPPED) { X here->doormask = D_NODOOR; X if(mb_trapped(mtmp)) return(FALSE); X } else { X if(!rn2(3) && flags.verbose) /* not too often.. */ X You("feel an unexpected draft of air."); X here->doormask = D_BROKEN; X } X } X else pile = 12; /* it doesn't leave rocks if it didn't dig */ X X /* Left behind a pile? */ X if(pile < 5) { X if(pile == 1) X (void) mksobj_at(BOULDER, mtmp->mx, mtmp->my); X else X (void) mksobj_at(ROCK, mtmp->mx, mtmp->my); X } X if(canseeit) { X here->seen = TRUE; X newsym(mtmp->mx,mtmp->my); X } else X mnewsym(mtmp->mx,mtmp->my); X return(TRUE); X} X Xint Xdochugw(mtmp) X register struct monst *mtmp; X{ X register int x = mtmp->mx; X register int y = mtmp->my; X register int rd = dochug(mtmp); X register int dd; X X if(!rd && !mtmp->mpeaceful && X (dd = dist(mtmp->mx,mtmp->my)) < dist(x,y) && X dd < 100 && !canseemon(mtmp)) { X#ifdef NAMED_ITEMS X /* Note: this assumes we only want to warn against the monster which X * the weapon does extra damage to, as there is no "monster which X * the weapon warns against" field. X */ X if(spec_ability(uwep,SPFX_WARN) && spec_dbon(uwep,mtmp->data,1)) X warnlevel = 100; X else X#endif X if (Warning && mtmp->m_lev > warnlevel) X warnlevel = mtmp->m_lev; X } X return(rd); X} X Xboolean Xonscary(x, y, mtmp) Xint x, y; Xstruct monst *mtmp; X{ X if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee || X mtmp->data->mlet == S_HUMAN || mtmp->mpeaceful) X return(FALSE); X return( X#ifdef ELBERETH X sengr_at("Elbereth", x, y) || X#endif X sobj_at(SCR_SCARE_MONSTER, x, y) != (struct obj *)0); X} X X/* returns 1 if monster died moving, 0 otherwise */ Xint Xdochug(mtmp) X register struct monst *mtmp; X{ X register struct permonst *mdat = mtmp->data; X register int tmp=0, inrange, nearby, scared, seescaryx, X seescaryy; X X/* Pre-movement adjustments */ X X if(mtmp->cham && !rn2(6)) /* polymorph chameleons */ X (void) newcham(mtmp, (struct permonst *)0); X X /* regenerate monsters */ X if((!(moves%20) || regenerates(mdat)) && mtmp->mhp < mtmp->mhpmax) X mtmp->mhp++; X if(mtmp->mspec_used) mtmp->mspec_used--; X X /* polymorph lycanthropes */ X were_change(mtmp); X X if(mtmp->mfroz) { X if (Hallucination) pmon(mtmp); X return(0); /* frozen monsters don't do anything */ X } X X if(mtmp->msleep) /* there is a chance we will wake it */ X if(!disturb(mtmp)) return(0); X X /* not frozen or sleeping: wipe out texts written in the dust */ X wipe_engr_at(mtmp->mx, mtmp->my, 1); X X /* confused monsters get unconfused with small probability */ X if(mtmp->mconf && !rn2(50)) mtmp->mconf = 0; X X /* stunned monsters get un-stunned with larger probability */ X if(mtmp->mstun && !rn2(10)) mtmp->mstun = 0; X X /* some monsters teleport */ X if(mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz) { X rloc(mtmp); X return(0); X } X if(mdat->mmove < rnd(6)) return(0); X X /* fleeing monsters might regain courage */ X if(mtmp->mflee && !mtmp->mfleetim X && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0; X X set_apparxy(mtmp); X /* Must be done after you move and before the monster does. The X * set_apparxy() call in m_move() doesn't suffice since the variables X * inrange, etc... all depend on stuff set by set_apparxy(). X */ X X /* The Wizard's prime directive */ X /* may teleport, so do it before inrange is set */ X if(mtmp->iswiz) X (void) wiz_get_amulet(mtmp); X X inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= X (BOLT_LIM * BOLT_LIM)); X nearby = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) < 3); X /* Note: if your image is displaced, the monster sees the Elbereth X * at your displaced position, thus never attacking your displaced X * position, but possibly attacking you by accident. If you are X * invisible, it sees the Elbereth at your real position, thus never X * running into you by accident but possibly attacking the spot X * where it guesses you are. X */ X if (Invis && !perceives(mdat)) { X seescaryx = mtmp->mux; X seescaryy = mtmp->muy; X } else { X seescaryx = u.ux; X seescaryy = u.uy; X } X scared = (nearby && onscary(seescaryx, seescaryy, mtmp)); X X if(scared && !mtmp->mflee) { X#ifdef POLYSELF X if (!sticks(uasmon)) X#endif X unstuck(mtmp); /* monster lets go when fleeing */ X mtmp->mflee = 1; X mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100)); X } X X#ifdef HARD /* Demonic Blackmail!!! */ X if(nearby && is_demon(mdat) && mtmp->mpeaceful && !mtmp->mtame) { X if (mtmp->mux != u.ux || mtmp->muy != u.uy) { X pline("%s whispers something to thin air.", X cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It"); X#ifdef POLYSELF X if (is_demon(uasmon)) rloc(mtmp); X /* "Good hunting, brother" */ X else X#endif X if (is_lord(mdat) || is_prince(mdat)) { X /* use is_lord instead of is_dlord */ X mtmp->minvis = 0; X /* Why? For the same reason in real demon talk */ X pline("%s gets angry.", Xmonnam(mtmp)); X mtmp->mpeaceful = 0; X /* since no way is an image going to pay it off */ X } X } else if(demon_talk(mtmp)) return(1); /* you paid it off */ X } X#endif X X/* Now the actual movement phase */ X X if(!nearby || mtmp->mflee || scared || X mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) || X (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) || X (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) || X (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) { X X tmp = m_move(mtmp, 0); X nearby = (dist(mtmp->mx, mtmp->my) < 3); /* recalc */ X scared = (nearby && onscary(seescaryx, seescaryy, mtmp)); X switch (tmp) { X X case 0: /* no movement, but it can still attack you */ X case 3: /* absolutely no movement */ X /* for pets, case 0 and 3 are equivalent */ X /* During hallucination, monster appearance should X * still change - even if it doesn't move. X */ X if(Hallucination) pmon(mtmp); X break; X case 1: /* monster moved */ X if(!nearby && ranged_attk(mdat)) break; X else if(mdat->mmove <= 12) return(0); X break; X case 2: /* monster died */ X return(1); X } X X inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= X (BOLT_LIM * BOLT_LIM)); X if(scared && !mtmp->mflee) { X mtmp->mflee = 1; X mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100)); X } X } X X/* Now, attack the player if possible - one attack set per monst */ X X if(inrange && !noattacks(mdat) && X !mtmp->mpeaceful && !mtmp->mtame && u.uhp > 0 && !scared && tmp != 3) X if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */ X X#ifdef WORM X if(mtmp->wormno && !mtmp->mtame) wormhit(mtmp); X#endif X X /* extra movement for fast monsters */ X if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp, 1); X return(tmp == 2); X} X Xstatic const char practical[] = { WEAPON_SYM, GEM_SYM, FOOD_SYM, 0 }; Xstatic const char magical[] = { X AMULET_SYM, POTION_SYM, SCROLL_SYM, WAND_SYM, RING_SYM, X#ifdef SPELLS X SPBOOK_SYM, X#endif X 0 }; Xstatic const char indigestion[] = { BALL_SYM, ROCK_SYM, 0 }; X X#ifdef POLYSELF Xstatic boolean Xitsstuck(mtmp) Xregister struct monst *mtmp; X{ X if (sticks(uasmon) && mtmp==u.ustuck && !u.uswallow) { X kludge("%s cannot escape from you!", Monnam(mtmp)); X return(TRUE); X } X return(FALSE); X} X#endif X Xint Xm_move(mtmp, after) Xregister struct monst *mtmp; Xregister int after; X{ X register struct monst *mtmp2; X register int nx,ny,omx,omy,appr,nearer,cnt,i,j; X xchar gx,gy,nix,niy,chcnt; X schar chi; X boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0; X boolean likerock=0, can_tunnel=0; X struct permonst *ptr = mtmp->data; X schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */ X coord poss[9]; X long info[9]; X long flag; X X if(mtmp->mtrapped) { X i = mintrap(mtmp); X if(i == 2) return(2); /* it died */ X if(i == 1) return(0); /* still in trap, so didn't move */ X } X if(mtmp->mhide && X (levl[mtmp->mx][mtmp->my].omask || levl[mtmp->mx][mtmp->my].gmask) && X rn2(10)) X return(0); /* do not leave hiding place */ X if(mtmp->meating) { X mtmp->meating--; X return(3); /* still eating */ X } X X set_apparxy(mtmp); X /* where does mtmp think you are? */ X /* Not necessary if m_move called from here, but necessary in X * other calls of m_move (i.e. leprechauns dodging) X */ X can_tunnel = tunnels(ptr) && X#ifdef REINCARNATION X dlevel != rogue_level && X#endif X (!needspick(ptr) || m_carrying(mtmp, PICK_AXE)); X#ifdef WORM X if(mtmp->wormno) goto not_special; X#endif X /* my dog gets a special treatment */ X if(mtmp->mtame) return( dog_move(mtmp, after) ); X X /* likewise for shopkeeper */ X if(mtmp->isshk) { X mmoved = shk_move(mtmp); X if(mmoved == -2) return(2); X if(mmoved >= 0) goto postmov; X mmoved = 0; /* follow player outside shop */ X } X X /* and for the guard */ X if(mtmp->isgd) { X mmoved = gd_move(); X goto postmov; X } X X /* and the wiz already got special treatment */ X if(mtmp->iswiz) { X mmoved = 0; X goto postmov; X } X#if defined(ALTARS) && defined(THEOLOGY) X /* and for the priest */ X if(mtmp->ispriest) { X mmoved = pri_move(mtmp); X if(mmoved == -2) return(2); X if(mmoved >= 0) goto postmov; X mmoved = 0; X } X#endif X#ifdef MAIL X if(ptr == &mons[PM_MAIL_DAEMON]) { X if(flags.soundok && canseemon(mtmp)) X pline("\"I'm late!\""); X mongone(mtmp); X return(2); X } X#endif X X /* teleport if that lies in our nature */ X if(ptr == &mons[PM_TENGU] && !rn2(5)) { X if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2)) X rloc(mtmp); X else X mnexto(mtmp); X mmoved = 1; X goto postmov; X } X#ifdef WORM Xnot_special: X#endif X if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1); X appr = 1; X if(mtmp->mflee) appr = -1; X if(mtmp->mconf || (Invis && !perceives(ptr)) || !mtmp->mcansee || X (mtmp->mpeaceful && !mtmp->isshk) || /* allow shks to follow */ X ((ptr->mlet == S_STALKER || ptr->mlet == S_BAT || X ptr->mlet == S_YLIGHT) && !rn2(3))) X appr = 0; X omx = mtmp->mx; X omy = mtmp->my; X gx = mtmp->mux; X gy = mtmp->muy; X if(ptr == &mons[PM_LEPRECHAUN] && appr == 1 && mtmp->mgold > u.ugold) X appr = -1; X X if(can_track(ptr)) { X register coord *cp; X schar mroom; X X mroom = inroom(omx,omy); X if(mroom < 0 || mroom != inroom(u.ux,u.uy)){ X cp = gettrack(omx,omy); X if(cp){ X gx = cp->x; X gy = cp->y; X } X } X } X X#ifdef REINCARNATION X if (dlevel != rogue_level) X#endif X { X register int pctload = (curr_mon_load(mtmp) * 100) / X max_mon_load(mtmp); X X /* look for gold or jewels nearby */ X likegold = (likes_gold(ptr) && pctload < 95); X likegems = (likes_gems(ptr) && pctload < 85); X likeobjs = (likes_objs(ptr) && pctload < 75); X likemagic = (likes_magic(ptr) && pctload < 85); X likerock = (throws_rocks(ptr) && pctload < 50); X conceals = hides_under(ptr); X } X X#define SRCHRADIUS 25 X X { xchar mind = SRCHRADIUS; /* not too far away */ X register int dd; X X /* cut down the search radius if it thinks character is closer. */ X if(dist2(mtmp->mux, mtmp->muy, omx, omy) < SRCHRADIUS && X !mtmp->mtame && !mtmp->mpeaceful) mind /= 2; X X if(likegold){ X register struct gold *gold; X X for(gold = fgold; gold; gold = gold->ngold) X if((dd = dist2(omx,omy,gold->gx,gold->gy)) < mind){ X mind = dd; X gx = gold->gx; X gy = gold->gy; X } X } X if((likegems || likeobjs || likemagic || likerock || conceals) X && (!in_shop(omx, omy) || (!rn2(25) && !mtmp->isshk))) { X register struct obj *otmp; X X for(otmp = fobj; otmp; otmp = otmp->nobj) X if((likeobjs && index(practical, otmp->olet)) || X (likemagic && index(magical, otmp->olet)) || X (likerock && otmp->otyp == BOULDER) || X (likegems && otmp->olet == GEM_SYM && X otmp->otyp < LAST_GEM + 5) || X (conceals && !cansee(otmp->ox,otmp->oy)) || X (ptr == &mons[PM_GELATINOUS_CUBE] && X !index(indigestion, otmp->olet)) X ) { X if(can_carry(mtmp,otmp)) X if(ptr->mlet != S_UNICORN || X objects[otmp->otyp].g_val != 0) X if((dd = dist2(omx,omy,otmp->ox,otmp->oy)) < mind){ X mind = dd; X gx = otmp->ox; X gy = otmp->oy; X } X } X } X if(mind < SRCHRADIUS && appr == -1) { X if(dist2(omx,omy,mtmp->mux,mtmp->muy) < 10) { X gx = mtmp->mux; X gy = mtmp->muy; X } else X appr = 1; X } X } X nix = omx; X niy = omy; X flag = ALLOW_TRAPS; X if (mtmp->mpeaceful) flag |= (ALLOW_SANCT | ALLOW_SSM); X else flag |= ALLOW_U; X if (ptr->mlet == S_UNICORN) flag |= NOTONL; X if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK); X if (can_tunnel) flag |= ALLOW_DIG; X if (is_human(ptr)) flag |= ALLOW_SSM; X if (is_undead(ptr)) flag |= NOGARLIC; X if (throws_rocks(ptr)) flag |= ALLOW_ROCK; X cnt = mfndpos(mtmp, poss, info, flag); X chcnt = 0; X chi = -1; X X for(i=0; i < cnt; i++) { X nx = poss[i].x; X ny = poss[i].y; X X for(j=0; j < MTSZ && j < cnt-1; j++) X if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y) X if(rn2(4*(cnt-j))) goto nxti; X X nearer = (dist2(nx,ny,gx,gy) < dist2(nix,niy,gx,gy)); X X if((appr == 1 && nearer) || (appr == -1 && !nearer) || X !mmoved || (!appr && !rn2(++chcnt))) { X nix = nx; X niy = ny; X chi = i; X mmoved = 1; X } X nxti: ; X } X X if(mmoved) { X#ifdef POLYSELF X if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp)) X return(3); X#endif X if((info[chi] & ALLOW_U) || (nix == u.ux && niy == u.uy)) { X mtmp->mux = u.ux; X mtmp->muy = u.uy; X return(0); X } X /* The monster may attack another based on 1 of 2 conditions: X * 1 - He may be under the "conflict" influence. X * 2 - He may mistake the monster for your (displaced) image. X * Pets get taken care of above and shouldn't reach this code. X */ X if((info[chi] & ALLOW_M) || X (nix == mtmp->mux && niy == mtmp->muy)) { X mtmp2 = X (levl[nix][niy].mmask ? m_at(nix,niy) : (struct monst *)0); X if(mattackm(mtmp, mtmp2) == 1 && rn2(4) && X mtmp2->mlstmv != moves && mattackm(mtmp2, mtmp) == 2) X return(2); X return(3); X } X#ifdef WORM X /* The square now has a worm segment and must keep its mmask */ X if (!mtmp->wormno) X#endif X levl[omx][omy].mmask = 0; X levl[nix][niy].mmask = 1; X mtmp->mx = nix; X mtmp->my = niy; X for(j = MTSZ-1; j > 0; j--) X mtmp->mtrack[j] = mtmp->mtrack[j-1]; X mtmp->mtrack[0].x = omx; X mtmp->mtrack[0].y = omy; X#ifdef WORM X if(mtmp->wormno) worm_move(mtmp); X#endif X } else { X if(ptr->mlet == S_UNICORN && rn2(2)) { X rloc(mtmp); X return(1); X } X#ifdef WORM X if(mtmp->wormno) worm_nomove(mtmp); X#endif X } Xpostmov: X if(mmoved == 1) { X boolean canseeit = cansee(mtmp->mx, mtmp->my); X boolean abstain = (mtmp->mpeaceful && !mtmp->mtame); X X if(mintrap(mtmp) == 2) return(2); /* he died */ X X /* open a door, or crash through it, if you can */ X if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ) X && !passes_walls(ptr) /* doesn't need to open doors */ X && !amorphous(ptr) /* ditto */ X && !can_tunnel /* taken care of below */ X ) { X struct rm *here = &levl[mtmp->mx][mtmp->my]; X boolean btrapped = (here->doormask & D_TRAPPED); X X if(here->doormask & D_LOCKED && mtmp->isshk) { X /* can't lock out shk */ X if(btrapped) { X here->doormask = D_NODOOR; X if(mb_trapped(mtmp)) return(2); X } else { X if (flags.verbose) { X if (canseeit) X You("see a door being unlocked and opened."); X else if (flags.soundok) X You("hear a door being unlocked and opened."); X } X here->doormask = D_ISOPEN; X } X } else if (here->doormask == D_CLOSED && X !nohands(mtmp->data)) { X if(btrapped) { X here->doormask = D_NODOOR; X if(mb_trapped(mtmp)) return(2); X } else { X if (flags.verbose) { X if (canseeit) X You("see a door being opened."); X else if (flags.soundok) X You("hear the sound of a door opening."); X } X here->doormask = D_ISOPEN; X } X } else if(here->doormask & (D_LOCKED | D_CLOSED)) { X /* mfndpos guarantees monster is a giant */ X if(btrapped) { X here->doormask = D_NODOOR; X if(mb_trapped(mtmp)) return(2); X } else { X if (flags.verbose) { X if (canseeit) X You("see a door crash open."); X else if (flags.soundok) X You("hear the sound of a door crashing open."); X } X if (here->doormask & D_LOCKED && !rn2(2)) X here->doormask = D_NODOOR; X else here->doormask = D_BROKEN; X } X } X } X /* Maybe a rock mole just ate something? */ X if(can_tunnel) if(!mdig_tunnel(mtmp)) return(2); /* died? */ X X if(levl[mtmp->mx][mtmp->my].gmask == 1) { X /* Maybe a rock mole just ate some gold */ X if(ptr == &mons[PM_ROCK_MOLE]) meatgold(mtmp); X if(likegold && (!abstain || !rn2(10))) mpickgold(mtmp); X } X if(levl[mtmp->mx][mtmp->my].omask == 1) { X /* Maybe a rock mole just ate some metal object */ X if(ptr == &mons[PM_ROCK_MOLE]) meatgold(mtmp); X /* Maybe a cube ate just about anything */ X if(ptr == &mons[PM_GELATINOUS_CUBE]) meatobj(mtmp); X X if ((!abstain || !rn2(10)) X && (!in_shop(mtmp->mx, mtmp->my) || !rn2(25))) { X if(likeobjs) mpickstuff(mtmp, practical); X if(likemagic) mpickstuff(mtmp, magical); X if(likerock || likegems) mpickgems(mtmp); X } X } X if(mtmp->mhide) mtmp->mundetected = (levl[mtmp->mx][mtmp->my].omask X || levl[mtmp->mx][mtmp->my].gmask); X X /* set also in domove(), hack.c */ X if(u.uswallow && mtmp == u.ustuck) { X u.ux = mtmp->mx; X u.uy = mtmp->my; X if(mtmp->mx != mtmp->mdx || mtmp->my != mtmp->mdy) { X swallowed(0); X mtmp->mdx = mtmp->mx; X mtmp->mdy = mtmp->my; X } X } X } X pmon(mtmp); X return(mmoved); X} X Xvoid Xset_apparxy(mtmp) /* where does mtmp think you are standing? */ X register struct monst *mtmp; X{ X#define notseen (Invis && !perceives(mtmp->data)) X/* add cases as required. eg. Displacement ... */ X register int disp = (notseen ? 1 : Displaced ? 2 : 0); X X/* without something like the following, invis. and displ. are too */ X/* powerful. */ X register boolean gotu = X (notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE); X X/* Monsters which know where you are don't suddenly forget, if you X didn't move away. */ X if (mtmp->mux==u.ux && mtmp->muy==u.uy) gotu = 1; X X/* your dog follows your smell */ X if(!disp || mtmp->mtame || gotu || X/* If invisible but not displaced, staying around gets you 'discovered' */ X (!Displaced && u.dx == 0 && u.dy == 0)) { X mtmp->mux = u.ux; X mtmp->muy = u.uy; X } X else do { X mtmp->mux = u.ux - disp + rn2(2*disp+1); X mtmp->muy = u.uy - disp + rn2(2*disp+1); X } while((mtmp->mux != u.ux || mtmp->muy != u.uy) && X ( (!passes_walls(mtmp->data) && X (!ACCESSIBLE(levl[mtmp->mux][mtmp->muy].typ) || X (IS_DOOR(levl[mtmp->mux][mtmp->muy].typ) && X (levl[mtmp->mux][mtmp->muy].doormask & (D_LOCKED | D_CLOSED)) && X !amorphous(mtmp->data) X )) X ) || X (disp==1 && mtmp->mux == mtmp->mx && mtmp->muy == mtmp->my) X ) X ); X} END_OF_FILE if test 20241 -ne `wc -c <'src/monmove.c'`; then echo shar: \"'src/monmove.c'\" unpacked with wrong size! fi # end of 'src/monmove.c' fi if test -f 'src/read.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/read.c'\" else echo shar: Extracting \"'src/read.c'\" \(30625 characters\) sed "s/^X//" >'src/read.c' <<'END_OF_FILE' X/* SCCS Id: @(#)read.c 3.0 88/04/13 X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ X/* NetHack may be freely redistributed. See license for details. */ X X#include "hack.h" X Xboolean known; X Xstatic const char readable[] = { '#', SCROLL_SYM, X#ifdef SPELLS X SPBOOK_SYM, X#endif X 0 }; X Xstatic void explode P((struct obj *)); Xstatic void do_class_genocide(); X Xint Xdoread() { X register struct obj *scroll; X register boolean confused = (Confusion != 0); X X known = FALSE; X scroll = getobj(readable, "read"); /* "#-" added by GAN 10/22/86 */ X if(!scroll) return(0); X X /* below added to allow reading of fortune cookies */ X if(scroll->otyp == FORTUNE_COOKIE) { X if(flags.verbose) X You("break up the cookie and throw away the pieces."); X outrumor(bcsign(scroll), TRUE); X useup(scroll); X return(1); X } else X if(scroll->olet != SCROLL_SYM X#ifdef SPELLS X && scroll->olet != SPBOOK_SYM X#endif X ) { X pline("That is a silly thing to read."); X return(0); X } X X if(Blind) X#ifdef SPELLS X if (scroll->olet == SPBOOK_SYM) { X pline("Being blind, you cannot read the mystic runes."); X return(0); X } else X#endif X if (!scroll->dknown) { X pline("Being blind, you cannot read the formula on the scroll."); X return(0); X } X#ifdef SPELLS X if(scroll->olet == SPBOOK_SYM) { X if(confused) { X You("cannot grasp the meaning of this tome."); X useup(scroll); X return(0); X } else X return(study_book(scroll)); X } X#endif X if(scroll->otyp != SCR_BLANK_PAPER) { X if(Blind) X pline("As you pronounce the formula on it, the scroll disappears."); X else X pline("As you read the scroll, it disappears."); X if(confused) { X if (Hallucination) X pline("Being so trippy, you screw up..."); X else X pline("Being confused, you mispronounce the magic words..."); X } X } X if(!seffects(scroll)) { X if(!objects[scroll->otyp].oc_name_known) { X if(known && !confused) { X makeknown(scroll->otyp); X more_experienced(0,10); X } else if(!objects[scroll->otyp].oc_uname) X docall(scroll); X } X if(!(scroll->otyp == SCR_BLANK_PAPER) || confused) X useup(scroll); X } X return(1); X} X Xstatic void Xstripspe(obj) Xregister struct obj *obj; X{ X if (obj->blessed) pline(nothing_happens); X else { X if (obj->spe > 0) { X obj->spe = 0; X Your("%s vibrates briefly.",xname(obj)); X } else pline(nothing_happens); X } X} X Xstatic void Xp_glow1(otmp) Xregister struct obj *otmp; X{ X Your("%s %s briefly.", xname(otmp), X Blind ? "vibrates" : "glows"); X} X Xstatic void Xp_glow2(otmp,color) Xregister struct obj *otmp; Xregister char *color; X{ X Your("%s %s%s for a moment.", X xname(otmp), X Blind ? "vibrates" : "glows ", X Blind ? "" : Hallucination ? hcolor() : color); X} X Xint Xseffects(sobj) Xregister struct obj *sobj; X{ X register int cval = 0; X register boolean confused = (Confusion != 0); X X switch(sobj->otyp) { X#ifdef MAIL X case SCR_MAIL: X known = TRUE; X if (sobj->spe) X pline("This seems to be junk mail addressed to the finder of the Eye of Larn."); X /* note to the puzzled: the game Larn actually sends you junk X * mail if you win! X */ X else readmail(/* scroll */); X break; X#endif X case SCR_ENCHANT_ARMOR: X { X register struct obj *otmp = some_armor(); X register schar s = 0; X if(!otmp) { X strange_feeling(sobj, X !Blind ? "Your skin glows then fades." : X "Your skin feels warm for a moment."); X return(1); X } X if(confused) { X if(Blind) X Your("%s feels warm for a moment.", X xname(otmp)); X else X Your("%s is covered by a %s %s %s!", X xname(otmp), X sobj->cursed ? "mottled" : "shimmering", X Hallucination ? hcolor() : X sobj->cursed ? black : "gold", X sobj->cursed ? "glow" : X (is_shield(otmp) ? "layer" : "shield")); X if(!(otmp->rustfree)) X otmp->rustfree = !(sobj->cursed); X break; X } X#ifdef TOLKIEN X if((otmp->spe > ((otmp->otyp == ELVEN_MITHRIL_COAT) ? 5 : 3)) X#else X if((otmp->spe > 3) X#endif X && rn2(otmp->spe) && !sobj->cursed) { X Your("%s violently %s%s for a while, then evaporates.", X xname(otmp), X Blind ? "vibrates" : "glows ", X Blind ? "" : Hallucination ? hcolor() : silver); X if(is_cloak(otmp)) (void) Cloak_off(); X if(is_boots(otmp)) (void) Boots_off(); X if(is_helmet(otmp)) (void) Helmet_off(); X if(is_gloves(otmp)) (void) Gloves_off(); X if(is_shield(otmp)) (void) Shield_off(); X if(otmp == uarm) (void) Armor_gone(); X useup(otmp); X break; X } X s = sobj->blessed ? rnd(3) : sobj->cursed ? -1 : 1; X Your("%s %s%s for a %s.", X xname(otmp), X Blind ? "vibrates" : "glows ", X Blind ? "" : Hallucination ? hcolor() : X sobj->cursed ? black : silver, X (s*s>1) ? "while" : "moment"); X otmp->cursed = sobj->cursed; X otmp->blessed = sobj->blessed; X otmp->spe += s; X adj_abon(otmp, s); X break; X } X case SCR_DESTROY_ARMOR: X { register struct obj *otmp = some_armor(); X X if(confused) { X if(!otmp) { X strange_feeling(sobj,"Your bones itch."); X return(1); X } X p_glow2(otmp,purple); X otmp->rustfree = sobj->cursed; X break; X } X if(!sobj->cursed || (sobj->cursed && (!otmp || !otmp->cursed))) { X if(!destroy_arm(otmp)) { X strange_feeling(sobj,"Your skin itches."); X return(1); X } X } else { /* armor and scroll both cursed */ X Your("%s vibrates", xname(otmp)); X otmp->spe--; X make_stunned(HStun + rn1(10, 10), TRUE); X } X } X break; X case SCR_CONFUSE_MONSTER: X#ifdef SPELLS X case SPE_CONFUSE_MONSTER: X#endif X if(u.usym != S_HUMAN || sobj->cursed) { X if(!HConfusion) You("feel confused."); X make_confused(HConfusion + rnd(100),FALSE); X } else if(confused) { X if(!sobj->blessed) { X Your("%s begin to %s%s.", X makeplural(body_part(HAND)), X Blind ? "tingle" : "glow ", X Blind ? "" : Hallucination ? hcolor() : purple); X make_confused(HConfusion + rnd(100),FALSE); X } else { X pline("A %s%s surrounds your %s.", X Blind ? "" : Hallucination ? hcolor() : red, X Blind ? "faint buzz" : " glow", X body_part(HEAD)); X make_confused(0L,TRUE); X } X } else { X Your("%s%s %s.", X makeplural(body_part(HAND)), X Blind ? "" : " begin to glow", X Blind ? "tingle" : Hallucination ? hcolor() : red); X u.umconf = 1; X } X break; X case SCR_SCARE_MONSTER: X#ifdef SPELLS X case SPE_CAUSE_FEAR: X#endif X { register int ct = 0; X register struct monst *mtmp; X X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) X if(cansee(mtmp->mx,mtmp->my)) { X if(confused || sobj->cursed) X mtmp->mflee = mtmp->mfroz = mtmp->msleep = 0; X else X if (! resist(mtmp, sobj->olet, 0, NOTELL)) X mtmp->mflee = 1; X if(!mtmp->mtame) ct++; /* pets don't laugh at you */ X } X if(!ct) X You("hear %s in the distance.", X (confused || sobj->cursed) ? "sad wailing" : X "maniacal laughter"); X else X#ifdef SPELLS X if(sobj->otyp == SCR_SCARE_MONSTER) X#endif X You("hear %s close by.", X (confused || sobj->cursed) ? "sad wailing" : X "maniacal laughter"); X break; X } X case SCR_BLANK_PAPER: X if(confused) X You("try to read the strange patterns on this scroll, but it disappears."); X else { X pline("This scroll seems to be blank."); X known = TRUE; X } X break; X case SCR_REMOVE_CURSE: X#ifdef SPELLS X case SPE_REMOVE_CURSE: X#endif X { register struct obj *obj; X if(confused) X if (Hallucination) X You("feel the power of the Force against you!"); X else X You("feel like you need some help."); X else X if (Hallucination) X You("feel in touch with the Universal Oneness."); X else X You("feel like someone is helping you."); X X if(sobj->cursed) pline("The scroll disintegrates."); X else { X for(obj = invent; obj ; obj = obj->nobj) X if(sobj->blessed || obj->owornmask || X (obj->otyp == LOADSTONE)) { X if(confused) blessorcurse(obj, 2); X else obj->cursed = 0; X } X } X if(Punished && !confused) unpunish(); X break; X } X case SCR_CREATE_MONSTER: X#if defined(WIZARD) || defined(EXPLORE_MODE) X if (wizard || discover) X known = TRUE; X#endif /* WIZARD || EXPLORE_MODE */ X#ifdef SPELLS X case SPE_CREATE_MONSTER: X#endif X { register int cnt = 1; X X if(!rn2(73)) cnt += rnd(4); X if(confused || sobj->cursed) cnt += 12; X while(cnt--) { X#if defined(WIZARD) || defined(EXPLORE_MODE) X if(wizard || discover) X if (!create_particular()) X#endif /* WIZARD || EXPLORE_MODE */ X (void) makemon (confused ? &mons[PM_ACID_BLOB] : X (struct permonst *) 0, u.ux, u.uy); X } X break; X } X/* break; /*NOTREACHED*/ X case SCR_ENCHANT_WEAPON: X if(uwep && (uwep->olet == WEAPON_SYM || uwep->olet == PICK_AXE) X && confused) { X /* olet check added 10/25/86 GAN */ X if(Blind) X Your("weapon feels warm for a moment."); X else X Your("%s covered by a %s %s %s!", X aobjnam(uwep, "are"), X sobj->cursed ? "mottled" : "shimmering", X Hallucination ? hcolor() : X sobj->cursed ? purple : "gold", X sobj->cursed ? "glow" : "shield"); X uwep->rustfree = !(sobj->cursed); X } else return !chwepon(sobj, bcsign(sobj)*2+1); X break; X case SCR_TAMING: X#ifdef SPELLS X case SPE_CHARM_MONSTER: X#endif X { register int i,j; X register int bd = confused ? 5 : 1; X register struct monst *mtmp; X X for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) X if(levl[u.ux+i][u.uy+j].mmask && (mtmp = m_at(u.ux+i, u.uy+j))) { X if(sobj->cursed) { X if(!mtmp->mtame) mtmp->mpeaceful = 0; X } else { X if (mtmp->isshk) { X if (!mtmp->mpeaceful) { X kludge("%s calms down.", Monnam(mtmp)); X mtmp->mpeaceful = 1; X } X } else if(!resist(mtmp, sobj->olet, 0, NOTELL)) X (void) tamedog(mtmp, (struct obj *) 0); X } X } X break; X } X case SCR_GENOCIDE: X You("have found a scroll of genocide!"); X#ifdef SPELLS X case SPE_GENOCIDE: X#endif X known = TRUE; X if (sobj->blessed) do_class_genocide(); X else do_genocide(!sobj->cursed | (2 * !!Confusion)); X break; X case SCR_LIGHT: X if(!Blind) known = TRUE; X litroom(!confused && !sobj->cursed); X break; X case SCR_TELEPORTATION: X if(confused || sobj->cursed) level_tele(); X else { X register int uroom = inroom(u.ux, u.uy); X X if (sobj->blessed && !Teleport_control) { X known = TRUE; X pline("Do you wish to teleport? "); X if (yn()=='n') break; X } X tele(); X if(uroom != inroom(u.ux, u.uy)) known = TRUE; X if(Teleport_control) known = TRUE; X } X break; X case SCR_GOLD_DETECTION: X if (confused || sobj->cursed) return(trap_detect(sobj)); X else return(gold_detect(sobj)); X case SCR_FOOD_DETECTION: X#ifdef SPELLS X case SPE_DETECT_FOOD: X#endif X if (food_detect(sobj)) X return(1); /* nothing detected */ X break; X case SCR_IDENTIFY: X /* known = TRUE; */ X if(confused) X You("identify this as an identify scroll."); X else X pline("This is an identify scroll."); X if (sobj->blessed || (!sobj->cursed && !rn2(5))) X cval = rn2(5); X /* Note: if rn2(5)==0, identify all items */ X else cval = 1; X useup(sobj); X makeknown(SCR_IDENTIFY); X#ifdef SPELLS X case SPE_IDENTIFY: X#endif X if(!confused) X while(invent && !ggetobj("identify", identify, cval)); X return(1); X case SCR_CHARGING: X { register struct obj *obj; X register int n; X if (confused) { X You("feel charged up!"); X break; X } X known = TRUE; X pline("This is a charging scroll."); X obj = getobj("0#", "charge"); X if (!obj) break; X if (obj->olet != WAND_SYM) { X switch(obj->otyp) { X case MAGIC_MARKER: X if (sobj->cursed) stripspe(obj); X else if (sobj->blessed) { X n = obj->spe; X if (n < 50) obj->spe = 50; X if (n >= 50 && n < 75) obj->spe = 75; X if (n >= 75) obj->spe += 10; X p_glow2(obj,blue); X } else { X if (obj->spe < 50) obj->spe = 50; X else obj->spe++; X p_glow2(obj,white); X } X break; X case LAMP: X if (sobj->cursed) stripspe(obj); X else if (sobj->blessed) { X n = rn2(11); X if (obj->spe < n) obj->spe = n; X else obj->spe += rnd(3); X p_glow2(obj,blue); X } else { X obj->spe++; X p_glow1(obj); X } X break; X case MAGIC_LAMP: X if (sobj->cursed) stripspe(obj); X else if (sobj->blessed) { X if (obj->spe == 1) pline(nothing_happens); X else { X obj->spe = 1; X p_glow1(obj); X } X } else { X if (obj->spe == 1) pline(nothing_happens); X else { X n = rn2(2); X if (!n) { X obj->spe = 1; X p_glow1(obj); X } else pline(nothing_happens); X } X } X break; X case CRYSTAL_BALL: X if (sobj->cursed) stripspe(obj); X else if (sobj->blessed) { X obj->spe = 6; X p_glow2(obj,blue); X } else { X if (obj->spe < 5) { X obj->spe++; X p_glow1(obj); X } else pline(nothing_happens); X } X break; X case BAG_OF_TRICKS: X if (sobj->cursed) stripspe(obj); X else if (sobj->blessed) { X if (obj->spe <= 10) X obj->spe += (5 + rnd(10)); X else obj->spe += (5 + rnd(5)); X p_glow2(obj,blue); X } else { X obj->spe += rnd(5); X p_glow1(obj); X } X break; X default: X pline("The scroll %s%s, and disintegrates.", X Blind ? "vibrates violently" : "glows ", X Blind ? "" : Hallucination ? hcolor() : "dark red"); X } /* switch */ X break; X } X else { X if (obj->otyp == WAN_WISHING) { X if (obj->recharged) { /* recharged once already? */ X explode(obj); X break; X } X if (sobj->cursed) stripspe(obj); X else if (sobj->blessed) { X if (obj->spe != 3) { X obj->spe = 3; X p_glow2(obj,blue); X } else { X explode(obj); X break; X } X } else { X if (obj->spe < 3) { X obj->spe++; X p_glow2(obj,blue); X } else pline(nothing_happens); X } X obj->recharged = 1; /* another recharging disallowed */ X } X else { X if (sobj->cursed) stripspe(obj); X else if (sobj->blessed) { X if (objects[obj->otyp].bits & NODIR) { X n = rn1(5,11); X if (obj->spe < n) obj->spe = n; X else obj->spe++; X } X else { X n = rn1(5,4); X if (obj->spe < n) obj->spe = n; X else obj->spe++; X } X p_glow2(obj,blue); X } else { X obj->spe++; X p_glow1(obj); X } X break; X } X } X } X break; X case SCR_MAGIC_MAPPING: X known = TRUE; X pline("On this scroll %s a map.", confused ? "was" : "is"); X#ifdef SPELLS X case SPE_MAGIC_MAPPING: X#endif X cval = (sobj->cursed && !confused); X if(cval) HConfusion = 1; /* to screw up map */ X do_mapping(); X if(cval) { X HConfusion = 0; /* restore */ X pline("Unfortunately, it is of a very poor quality."); X } X break; X case SCR_AMNESIA: X { register int zx, zy; X X known = TRUE; X for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++) X if(!confused || sobj->cursed || rn2(7)) X if(!cansee(zx,zy)) X levl[zx][zy].seen = levl[zx][zy].new = X levl[zx][zy].scrsym = 0; X docrt(); X if (Hallucination) /* Ommmmmm! */ X Your("mind releases itself from mundane concerns."); X else if (!strncmp(plname, "Maud", 4)) X pline("As your mind turns inward on itself, you forget everything else."); X else if (flags.female) X pline("Who was that Maud person anyway?"); X else X pline("Thinking of Maud you forget everything else."); X#ifdef SPELLS X if(!sobj->blessed) losespells(); X#endif X break; X } X case SCR_FIRE: X { register int num; X register struct monst *mtmp; X/* X * Note: Modifications have been made as of 3.0 to allow for some damage X * under all potential cases. X */ X cval = bcsign(sobj); X useup(sobj); X makeknown(SCR_FIRE); X if(confused) { X if(Fire_resistance) { X shieldeff(u.ux, u.uy); X if(!Blind) X pline("Oh, look, what a pretty fire in your %s.", X makeplural(body_part(HAND))); X else You("feal a pleasant warmth in your %s.", X makeplural(body_part(HAND))); X } else { X pline("The scroll catches fire and you burn your %s.", X makeplural(body_part(HAND))); X losehp(1, "scroll of fire"); X } X return(1); X } X pline("The scroll erupts in a tower of flame!"); X num = rnd(6) - 3 * cval; X if(num <= 0 || Fire_resistance) { X shieldeff(u.ux, u.uy); X You("are uninjured."); X } else { X u.uhpmax -= num; X losehp(num, "scroll of fire"); X } X destroy_item(SCROLL_SYM, AD_FIRE); X#ifdef SPELLS X destroy_item(SPBOOK_SYM, AD_FIRE); X#endif X destroy_item(POTION_SYM, AD_FIRE); X X num = (2*(rn1(3, 3) + 2 * cval) + 1)/3; X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { X if(dist(mtmp->mx,mtmp->my) < 3) { X if (resists_fire(mtmp->data)) continue; X if (u.uswallow) { X if (mtmp != u.ustuck) continue; X pline("%s gets heartburn.", Monnam(u.ustuck)); X num *= 2; X } X mtmp->mhp -= num; /* No saving throw! */ X if(resists_cold(mtmp->data)) X mtmp->mhp -= 3*num; X if(mtmp->mhp < 1) { X killed(mtmp); X break; /* primitive */ X } X } X } X return(1); X } X case SCR_PUNISHMENT: X known = TRUE; X if(confused || sobj->blessed) { X You("feel guilty."); X break; X } X punish(sobj); X break; X default: X impossible("What weird effect is this? (%u)", sobj->otyp); X } X return(0); X} X Xstatic void Xexplode(obj) Xregister struct obj *obj; X{ X Your("%s vibrates violently, and explodes!",xname(obj)); X bell(); X losehp(rn2(2*(u.uhpmax+1)/3),"exploding wand"); X useup(obj); X} X Xint Xidentify(otmp) /* also called by newmail() */ X register struct obj *otmp; X{ X makeknown(otmp->otyp); X otmp->known = otmp->dknown = otmp->bknown = 1; X prinv(otmp); X return(1); X} X Xvoid Xlitroom(on) Xregister boolean on; X{ X register int zx,zy; X X /* first produce the text (provided he is not blind) */ X if(Blind) goto do_it; X if(!on) { X if(u.uswallow || is_maze_lev || levl[u.ux][u.uy].typ == CORR || X !levl[u.ux][u.uy].lit) { X pline("It seems even darker in here than before."); X return; X } else X pline("It suddenly becomes dark in here."); X } else { X if(u.uswallow){ X pline("%s's stomach is lit.", Monnam(u.ustuck)); X return; X } X if(is_maze_lev){ X pline(nothing_happens); X return; X } X if(levl[u.ux][u.uy].typ == CORR) { X pline("The corridor lights up around you, then fades."); X return; X } else if(levl[u.ux][u.uy].lit) { X pline("The light here seems better now."); X return; X } else X pline("The room is lit."); X } X Xdo_it: X if(levl[u.ux][u.uy].lit == on) X return; X if (inroom(u.ux,u.uy) < 0) X return; X getcorners(&seelx,&seehx,&seely,&seehy,&seelx2,&seehx2,&seely2,&seehy2); X X for(zy = seely; zy <= seehy; zy++) X for(zx = seelx; zx <= seehx; zx++) { X levl[zx][zy].lit = on; X if(!Blind && dist(zx,zy) > 2) X if(on) prl(zx,zy); else nosee(zx,zy); X } X for(zy = seely2; zy <= seehy2; zy++) X for(zx = seelx2; zx <= seehx2; zx++) { X levl[zx][zy].lit = on; X if(!Blind && dist(zx,zy) > 2) X if(on) prl(zx,zy); else nosee(zx,zy); X } X if(!on) seehx = 0; X} X Xstatic void Xdo_class_genocide() X{ X register int i, j, immunecnt, gonecnt, goodcnt; X char buf[BUFSZ]; X X for(j=0; ; j++) { X if (j >= 5) { X pline(thats_enough_tries); X return; X } X pline("What class of monsters do you wish to genocide? [type a letter] "); X do { X getlin(buf); X } while (buf[0]=='\033' || strlen(buf) != 1); X immunecnt = gonecnt = goodcnt = 0; X for(i=0; mons[i].mlet; i++) { X if(mons[i].mlet == buf[0]) { X if (!(mons[i].geno & G_GENO)) immunecnt++; X else if(mons[i].geno & G_GENOD) gonecnt++; X else goodcnt++; X } X } X if (!goodcnt && buf[0] != S_HUMAN) { X if (gonecnt) X pline("All such monsters are already nonexistent."); X else if (immunecnt) X You("aren't permitted to genocide such monsters."); X else X pline("That symbol does not represent any monster."); X continue; X } X for(i=0; mons[i].mlet; i++) { X if(mons[i].mlet == buf[0]) { X register struct monst *mtmp, *mtmp2; X char *n = makeplural(mons[i].mname); X X if (&mons[i]==player_mon() || ((mons[i].geno & G_GENO) X && !(mons[i].geno & G_GENOD))) { X /* This check must be first since player monsters might X * have G_GENOD or !G_GENO. X */ X pline("Wiped out all %s.", n); X if (&mons[i] == player_mon()) { X u.uhp = -1; X killer = "scroll of genocide"; X#ifdef POLYSELF X if (u.umonnum >= 0) X You("feel dead inside."); X else X#endif X done("died"); X } X /* for simplicity (and fairness) let's avoid X * alignment changes here... X */ X#ifdef POLYSELF X if (i==u.umonnum) rehumanize(); X#endif X mons[i].geno |= G_GENOD; X for(mtmp = fmon; mtmp; mtmp = mtmp2) { X mtmp2 = mtmp->nmon; X if(mtmp->data == &mons[i]) X mondead(mtmp); X } X } else if (mons[i].geno & G_GENOD) X pline("All %s are already nonexistent.", n); X else X You("aren't permitted to genocide %s%s.", X i == PM_WIZARD_OF_YENDOR ? "the " : "", X type_is_pname(&mons[i]) ? mons[i].mname : n); X } X } X return; X } X} X X#define REALLY 1 X#define PLAYER 2 Xvoid Xdo_genocide(how) Xint how; X/* 0 = no genocide; create monsters (cursed scroll) */ X/* 1 = normal genocide */ X/* 3 = forced genocide of player */ X{ X char buf[BUFSZ]; X register int i, j, killplayer = 0; X register struct permonst *ptr; X register struct monst *mtmp, *mtmp2; X X if (how & PLAYER) { X ptr = player_mon(); X Strcpy(buf, ptr->mname); X killplayer++; X } else { X for(j = 0; ; j++) { X if(j >= 5) { X pline(thats_enough_tries); X return; X } X pline("What monster do you want to genocide? [type the name] "); X getlin(buf); X X if(strlen(buf) && (!strncmp(buf, pl_character, PL_CSIZ))) { X /* Note: pl_character starts with capitals and player_mon does not */ X ptr = player_mon(); X killplayer++; X goto deadmeat; X } else { X i = name_to_mon(buf); X if(i == -1 || (mons[i].geno & G_GENOD)) { X pline("Such creatures do not exist in this world."); X continue; X } X ptr = &mons[i]; X if (ptr == player_mon()) { X killplayer++; X goto deadmeat; X } X if (is_human(ptr)) adjalign(-sgn(u.ualigntyp)); X if (is_demon(ptr)) adjalign(sgn(u.ualigntyp)); X X if(!(ptr->geno & G_GENO)) { X if(flags.soundok) { X if(flags.verbose) X pline("A thunderous voice booms though the caverns:"); X pline("\"No, mortal! That will not be done.\""); X } X continue; X } X break; X } X } X } Xdeadmeat: X if (Hallucination) { X#ifdef POLYSELF X if (u.umonnum != -1) X Strcpy(buf,uasmon->mname); X else X#endif X { X Strcpy(buf, pl_character); X buf[0] += 'a' - 'A'; X } X } else Strcpy(buf,ptr->mname); /* make sure we have standard singular */ X if (how & REALLY) { X pline("Wiped out all %s.", makeplural(buf)); X if(killplayer) { X u.uhp = -1; X killer = "genocide spell"; X#ifdef POLYSELF X /* A polymorphed character will die as soon as he is rehumanized. */ X if(u.umonnum >= 0) You("feel dead inside."); X else X#endif X done("died"); X return; X } X#ifdef POLYSELF X else if ((how & REALLY) && ptr == &mons[u.umonnum]) rehumanize(); X#endif X ptr->geno |= G_GENOD; X for(mtmp = fmon; mtmp; mtmp = mtmp2) { X mtmp2 = mtmp->nmon; X if(mtmp->data == ptr) X mondead(mtmp); X } X } else { X pline("Sent in some %s.", makeplural(buf)); X j = rnd(3) + 3; X for(i=1; i<=j; i++) X (void) makemon(ptr, u.ux, u.uy); X } X} X Xstatic void Xshow_map_spot(x, y) Xregister int x, y; X{ X register struct rm *lev; X register int num; X X if((Confusion != 0) && rn2(7)) return; X lev = &(levl[x][y]); X if((num = lev->typ) == 0) return; X X if(num == SCORR) { X lev->typ = CORR; X lev->scrsym = CORR_SYM; X /* X * magic mapping shouldn't find secret doors, X * especially on the stronghold level X */ X } else if(lev->seen) return; X if(num != ROOM) X { X lev->seen = lev->new = 1; X if(lev->scrsym == STONE_SYM || !lev->scrsym) X newsym(x, y); X else on_scr(x, y); X } X} X Xvoid Xdo_mapping() { X register int zx, zy; X X for(zy = 0; zy < ROWNO; zy++) X for(zx = 0; zx < COLNO; zx++) X show_map_spot(zx, zy); X} X Xvoid Xdo_vicinity_map() { X register int zx, zy; X X for(zy = (u.uy-5 < 0 ? 0 : u.uy-5); X zy < (u.uy+6 > ROWNO ? ROWNO : u.uy+6); zy++) X for(zx = (u.ux-9 < 0 ? 0 : u.ux-9); X zx < (u.ux+10 > COLNO ? COLNO : u.ux+10); zx++) X show_map_spot(zx, zy); X} X Xint Xdestroy_arm(atmp) Xregister struct obj *atmp; X{ X register struct obj *otmp; X X if((otmp = uarmc) && (!atmp || atmp == uarmc)) { X Your("cloak crumbles and turns to dust!"); X (void) Cloak_off(); X useup(otmp); X } else if((otmp = uarm) && (!atmp || atmp == uarm)) { X Your("armor turns to dust and falls to the floor!"); X (void) Armor_gone(); X useup(otmp); X#ifdef SHIRT X } else if((otmp = uarmu) && (!atmp || atmp == uarmu)) { X Your("shirt crumbles into tiny threads and falls apart!"); X useup(otmp); X#endif X } else if((otmp = uarmh) && (!atmp || atmp == uarmh)) { X Your("helmet turns to dust and is blown away!"); X (void) Helmet_off(); X useup(otmp); X } else if((otmp = uarmg) && (!atmp || atmp == uarmg)) { X Your("gloves vanish!"); X (void) Gloves_off(); X useup(otmp); X selftouch("You"); X } else if((otmp = uarmf) && (!atmp || atmp == uarmf)) { X Your("boots disintegrate!"); X (void) Boots_off(); X useup(otmp); X } else if((otmp =uarms) && (!atmp || atmp == uarms)) { X Your("shield crumbles away!"); X (void) Shield_off(); X useup(otmp); X } else return(0); /* could not destroy anything */ X X return(1); X} X X/* the detections are pulled out so they can */ X/* also be used in the crystal ball routine */ X/* returns 1 if nothing was detected */ X/* returns 0 if something was detected */ Xint Xtrap_detect(sobj) Xregister struct obj *sobj; X/* sobj is null if crystal ball, *scroll if gold detection scroll */ X{ X register struct trap *ttmp; X register struct obj *obj; X register int door; X boolean found = FALSE; X coord cc; X X for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) { X if(ttmp->tx != u.ux || ttmp->ty != u.uy) X goto outtrapmap; X else found = TRUE; X } X for(obj = fobj; obj; obj = obj->nobj) { X if ((obj->otyp==LARGE_BOX || obj->otyp==CHEST) && obj->otrapped) X if (obj->ox != u.ux || obj->oy != u.uy) X goto outtrapmap; X else found = TRUE; X } X for(door=0; door<=doorindex; door++) { X cc = doors[door]; X if (levl[cc.x][cc.y].doormask & D_TRAPPED) X if (cc.x != u.ux || cc.x != u.uy) X goto outtrapmap; X else found = TRUE; X } X if(!found) { X char buf[42]; X Sprintf(buf, "Your %s stop itching.", X makeplural(body_part(TOE))); X strange_feeling(sobj,buf); X return(1); X } X /* traps exist, but only under me - no separate display required */ X Your("%s itch.", makeplural(body_part(TOE))); X return(0); Xouttrapmap: X cls(); X#define SYMBOL (uchar)(Hallucination ? rndobjsym() : \ X (sobj && sobj->cursed) ? GOLD_SYM : TRAP_SYM) X#define AT Hallucination || (sobj && sobj->cursed) ? AT_OBJ : AT_MAP X for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) X at(ttmp->tx, ttmp->ty, SYMBOL, AT); X for(obj = fobj; obj; obj = obj->nobj) { X if ((obj->otyp==LARGE_BOX || obj->otyp==CHEST) && obj->otrapped) X at(obj->ox, obj->oy, SYMBOL, AT); X } X for(door=0; door<=doorindex; door++) { X cc = doors[door]; X if (levl[cc.x][cc.y].doormask & D_TRAPPED) X at(cc.x, cc.y, SYMBOL, AT); X } X#undef SYMBOL X#undef AT X prme(); X if (sobj && sobj->cursed) X You("feel very greedy."); X else X You("feel entrapped."); X more(); X docrt(); X return(0); X} X Xint Xgold_detect(sobj) Xregister struct obj *sobj; X{ X register struct gold *gtmp; X X if(!fgold) { X if(sobj) X strange_feeling(sobj, "You feel materially poor."); X return(1); X } else { X known = TRUE; X for(gtmp = fgold; gtmp; gtmp = gtmp->ngold) X if(gtmp->gx != u.ux || gtmp->gy != u.uy) X goto outgoldmap; X /* only under me - no separate display required */ X You("notice some gold between your %s.", X makeplural(body_part(FOOT))); X return(0); X outgoldmap: X cls(); X for(gtmp = fgold; gtmp; gtmp = gtmp->ngold) X at( gtmp->gx, gtmp->gy, X (uchar)(Hallucination ? rndobjsym() : GOLD_SYM), X AT_OBJ); X prme(); X You("feel very greedy, and sense gold!"); X more(); X docrt(); X } X return(0); X} X X/* food_detection is pulled out so that it */ X/* can also be used in the crystal ball routine */ X/* returns 1 if nothing was detected */ X/* returns 0 if something was detected */ Xint Xfood_detect(sobj) Xregister struct obj *sobj; X{ X register boolean confused = (Confusion || (sobj && sobj->cursed)); X register int ct = 0, ctu = 0; X register struct obj *obj; X register char foodsym = confused ? POTION_SYM : FOOD_SYM; X X for(obj = fobj; obj; obj = obj->nobj) X if(obj->olet == foodsym) { X if(obj->ox == u.ux && obj->oy == u.uy) ctu++; X else ct++; X } X if(!ct && !ctu) { X if (sobj) strange_feeling(sobj,"Your nose twitches."); X return(1); X } else if(!ct) { X known = TRUE; X You("%s %s close nearby.", sobj ? "smell" : "sense", X confused ? "something" : "food"); X } else { X known = TRUE; X cls(); X for(obj = fobj; obj; obj = obj->nobj) X if(obj->olet == foodsym) X at(obj->ox, obj->oy, X (uchar)(Hallucination ? rndobjsym() : FOOD_SYM), X AT_OBJ); X prme(); X if (sobj) Your("nose tingles and you smell %s.", X confused ? "something" : "food"); X else You("sense %s.", confused ? "something" : "food"); X more(); X docrt(); X } X return(0); X} X Xvoid Xpunish(sobj) Xregister struct obj *sobj; X{ X You("are being punished for your misbehavior!"); X if(Punished){ X Your("iron ball gets heavier."); X uball->owt += 15 * (1 + sobj->cursed); X return; X } X setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN); X setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL); X uball->spe = 1; /* special ball (see save) */ X} X Xvoid Xunpunish() X{ /* remove the ball and chain */ X freeobj(uchain); X unpobj(uchain); X free((genericptr_t) uchain); X setworn((struct obj *)0, W_CHAIN); X uball->spe = 0; X setworn((struct obj *)0, W_BALL); X} X X/* some creatures have special data structures that only make sense in their X * normal locations -- if the player tries to create one elsewhere, or to revive X * one, the disoriented creature becomes a zombie X */ Xboolean Xcant_create(mtype) Xint *mtype; X{ X X if (*mtype==PM_GUARD || *mtype==PM_SHOPKEEPER X#if defined(ALTARS) && defined(THEOLOGY) X || *mtype==PM_TEMPLE_PRIEST || *mtype==PM_TEMPLE_PRIESTESS X#endif X ) { X *mtype = PM_HUMAN_ZOMBIE; X return TRUE; X } else X return FALSE; X} X X#if defined(WIZARD) || defined(EXPLORE_MODE) Xboolean Xcreate_particular() X{ X char buf[BUFSZ]; X int which; X X do { X pline("Create what kind of monster? [type the name] "); X getlin(buf); X } while(strlen(buf) < 1); X which = name_to_mon(buf); X if (which != -1) { X if (!(mons[which].geno & G_GENOD) && cant_create(&which) && X !Blind) { X if (mons[which].geno & G_GENOD) Xpline("An image of the creature forms, wavers momentarily, then fades."); X else Xpline("The disoriented creature's eyes slowly glaze over."); X } X (void) makemon(&mons[which], u.ux, u.uy); X return TRUE; X } X return FALSE; X} X#endif /* WIZARD || EXPLORE_MODE */ END_OF_FILE if test 30625 -ne `wc -c <'src/read.c'`; then echo shar: \"'src/read.c'\" unpacked with wrong size! fi # end of 'src/read.c' fi echo shar: End of archive 14 \(of 38\). cp /dev/null ark14isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 38 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0