This is monmove.c in view mode; [Download] [Up]
/* SCCS Id: @(#)monmove.c 3.0 89/11/21 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ /* Modified by cmarq@cube.net for graphical NEXTSTEP version (added notice: 8/26/94) */ #ifndef LINT # ifndef __STDC__ #define TRAP_H /* comment line for pre-compiled headers */ /* block some unused #defines to avoid overloading some cpp's */ # endif #endif #include "hack.h" #include "mfndpos.h" #ifdef NAMED_ITEMS # include "artifact.h" #endif static void FDECL(distfleeck,(struct monst *,int *,int *,int *)); #ifdef POLYSELF static boolean FDECL(itsstuck,(struct monst *)); #endif #ifdef OVLB boolean /* TRUE : mtmp died */ mb_trapped(mtmp) register struct monst *mtmp; { if (flags.verbose) { if (cansee(mtmp->mx, mtmp->my)) pline("KABOOM!! You see a door explode."); else if (flags.soundok) You("hear a distant explosion."); } mtmp->mstun = 1; mtmp->mhp -= rnd(15); if(mtmp->mhp <= 0) { mondied(mtmp); return(TRUE); } return(FALSE); } boolean mdig_tunnel(mtmp) /* FALSE: monster died */ register struct monst *mtmp; { register struct rm *here; register int pile = rnd(12); boolean canseeit = cansee(mtmp->mx, mtmp->my); here = &levl[mtmp->mx][mtmp->my]; if (here->typ == SDOOR) here->typ = DOOR; if(IS_ROCK(here->typ)) { /* Just ate something. */ if(IS_WALL(here->typ)) { if (!(here->diggable & W_NONDIGGABLE)) { if(flags.soundok && flags.verbose && !rn2(5)) You("hear the sound of crashing rock."); if(!is_maze_lev) { here->typ = DOOR; here->doormask = D_NODOOR; } else here->typ = ROOM; } } else here->typ = CORR; mnewsym(mtmp->mx, mtmp->my); } else /* Eats away door if present & closed or locked */ if(closed_door(mtmp->mx, mtmp->my)) { if(here->doormask & D_TRAPPED) { here->doormask = D_NODOOR; if(mb_trapped(mtmp)) return(FALSE); } else { if(!rn2(3) && flags.verbose) /* not too often.. */ You("feel an unexpected draft of air."); here->doormask = D_BROKEN; } mnewsym(mtmp->mx, mtmp->my); } else /* it doesn't leave rocks if it didn't dig */ return TRUE; /* Left behind a pile? */ if(pile < 5) { if(pile == 1) (void) mksobj_at(BOULDER, mtmp->mx, mtmp->my); else (void) mksobj_at(ROCK, mtmp->mx, mtmp->my); } here->seen = TRUE; /* required for newsym and mnewsym to work */ if(canseeit && mtmp->minvis && !See_invisible) newsym(mtmp->mx,mtmp->my); else mnewsym(mtmp->mx,mtmp->my); here->seen = FALSE; return(TRUE); } #endif /* OVLB */ #ifdef OVL1 int dochugw(mtmp) register struct monst *mtmp; { register int x = mtmp->mx; register int y = mtmp->my; register int rd = dochug(mtmp); register int dd; if(!rd && !mtmp->mpeaceful && (dd = dist(mtmp->mx,mtmp->my)) < dist(x,y) && dd < 100 && !canseemon(mtmp)) { #ifdef NAMED_ITEMS /* Note: this assumes we only want to warn against the monster which * the weapon does extra damage to, as there is no "monster which * the weapon warns against" field. */ if(spec_ability(uwep,SPFX_WARN) && spec_dbon(uwep,mtmp->data,1)) warnlevel = 100; else #endif if (Warning && mtmp->m_lev > warnlevel) warnlevel = mtmp->m_lev; } return(rd); } #endif /* OVL1 */ #ifdef OVL2 boolean onscary(x, y, mtmp) int x, y; struct monst *mtmp; { /* Note: minotaurs must be immune to scare monster to avoid abuse * from creating them and taking their wands, then polymorphing 60 * or so wands to get wishing... */ if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee || mtmp->data->mlet == S_HUMAN || mtmp->mpeaceful || mtmp->data == &mons[PM_MINOTAUR]) return(FALSE); return( #ifdef ELBERETH sengr_at("Elbereth", x, y) || #endif sobj_at(SCR_SCARE_MONSTER, x, y) != (struct obj *)0); } #endif /* OVL2 */ #ifdef OVL1 static void distfleeck(mtmp,inrange,nearby,scared) register struct monst *mtmp; int *inrange, *nearby, *scared; { int seescaryx, seescaryy; *inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= (BOLT_LIM * BOLT_LIM)); *nearby = monnear(mtmp, mtmp->mux, mtmp->muy); /* Note: if your image is displaced, the monster sees the Elbereth * at your displaced position, thus never attacking your displaced * position, but possibly attacking you by accident. If you are * invisible, it sees the Elbereth at your real position, thus never * running into you by accident but possibly attacking the spot * where it guesses you are. */ if (Invis && !perceives(mtmp->data)) { seescaryx = mtmp->mux; seescaryy = mtmp->muy; } else { seescaryx = u.ux; seescaryy = u.uy; } *scared = (*nearby && onscary(seescaryx, seescaryy, mtmp)); if(*scared && !mtmp->mflee) { #ifdef POLYSELF if (!sticks(uasmon)) #endif unstuck(mtmp); /* monster lets go when fleeing */ mtmp->mflee = 1; #ifdef STUPID if (rn2(7)) mtmp->mfleetim = rnd(10); else mtmp->mfleetim = rnd(100); #else mtmp->mfleetim = (rn2(7) ? rnd(10) : rnd(100)); #endif } } /* returns 1 if monster died moving, 0 otherwise */ int dochug(mtmp) register struct monst *mtmp; { register struct permonst *mdat = mtmp->data; register int tmp=0; int inrange, nearby, scared; /* Pre-movement adjustments */ if(mtmp->cham && !rn2(6)) /* polymorph chameleons */ (void) newcham(mtmp, (struct permonst *)0); /* regenerate monsters */ if((!(moves%20) || regenerates(mdat)) && mtmp->mhp < mtmp->mhpmax) mtmp->mhp++; if(mtmp->mspec_used) mtmp->mspec_used--; /* polymorph lycanthropes */ were_change(mtmp); if(!mtmp->mcanmove) { if (Hallucination) pmon(mtmp); return(0); /* frozen monsters don't do anything */ } if(mtmp->msleep) /* there is a chance we will wake it */ if(!disturb(mtmp)) 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; /* stunned monsters get un-stunned with larger probability */ if(mtmp->mstun && !rn2(10)) mtmp->mstun = 0; /* some monsters teleport */ if(mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz) { rloc(mtmp); return(0); } if(mdat->mmove < rnd(6)) return(0); /* fleeing monsters might regain courage */ if(mtmp->mflee && !mtmp->mfleetim && mtmp->mhp == mtmp->mhpmax && !rn2(25)) mtmp->mflee = 0; set_apparxy(mtmp); /* Must be done after you move and before the monster does. The * set_apparxy() call in m_move() doesn't suffice since the variables * inrange, etc... all depend on stuff set by set_apparxy(). */ /* The Wizard's prime directive */ /* may teleport, so do it before inrange is set */ if(mtmp->iswiz) (void) wiz_get_amulet(mtmp); /* check distance and scariness of attacks */ distfleeck(mtmp,&inrange,&nearby,&scared); #ifdef INFERNO /* Demonic Blackmail! */ if(nearby && mdat->msound == MS_BRIBE && mtmp->mpeaceful && !mtmp->mtame) { if (mtmp->mux != u.ux || mtmp->muy != u.uy) { pline("%s whispers something to thin air.", cansee(mtmp->mux, mtmp->muy) ? Monnam(mtmp) : "It"); # ifdef POLYSELF if (is_demon(uasmon)) rloc(mtmp); /* "Good hunting, brother" */ else { # endif mtmp->minvis = 0; /* Why? For the same reason in real demon talk */ pline("%s gets angry.", Xmonnam(mtmp)); mtmp->mpeaceful = 0; /* since no way is an image going to pay it off */ # ifdef POLYSELF } # endif } else if(demon_talk(mtmp)) return(1); /* you paid it off */ } #endif /* Now the actual movement phase */ if(!nearby || mtmp->mflee || scared || mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) || (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) || (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) || (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) { tmp = m_move(mtmp, 0); distfleeck(mtmp,&inrange,&nearby,&scared); /* recalc */ switch (tmp) { case 0: /* no movement, but it can still attack you */ case 3: /* absolutely no movement */ /* for pets, case 0 and 3 are equivalent */ /* During hallucination, monster appearance should * still change - even if it doesn't move. */ if(Hallucination) pmon(mtmp); break; case 1: /* monster moved */ /* Maybe it stepped on a trap and fell asleep... */ if(mtmp->msleep || !mtmp->mcanmove) return(0); if(!nearby && ranged_attk(mdat)) break; else if(mdat->mmove <= 12) return(0); break; case 2: /* monster died */ return(1); } } /* Now, attack the player if possible - one attack set per monst */ if(inrange && !noattacks(mdat) && !mtmp->mpeaceful && !mtmp->mtame && u.uhp > 0 && !scared && tmp != 3) if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */ #ifdef WORM if(mtmp->wormno && !mtmp->mtame) wormhit(mtmp); #endif /* extra emotional attack for vile monsters */ if(inrange && mtmp->data->msound == MS_CUSS && !mtmp->minvis && !mtmp->mpeaceful && !rn2(5)) cuss(mtmp); /* extra movement for fast monsters */ if(mdat->mmove-12 > rnd(12)) tmp = m_move(mtmp, 1); return(tmp == 2); } static const char practical[] = { WEAPON_SYM, GEM_SYM, FOOD_SYM, 0 }; static const char magical[] = { AMULET_SYM, POTION_SYM, SCROLL_SYM, WAND_SYM, RING_SYM, #ifdef SPELLS SPBOOK_SYM, #endif 0 }; static const char indigestion[] = { BALL_SYM, ROCK_SYM, 0 }; #ifdef POLYSELF static boolean itsstuck(mtmp) register struct monst *mtmp; { if (sticks(uasmon) && mtmp==u.ustuck && !u.uswallow) { kludge("%s cannot escape from you!", Monnam(mtmp)); return(TRUE); } return(FALSE); } #endif #endif /* OVL1 */ #ifdef OVL0 int m_move(mtmp, after) register struct monst *mtmp; register int after; { register struct monst *mtmp2; register int nx,ny,omx,omy,appr,nearer,cnt,i,j; xchar gx,gy,nix,niy,chcnt; schar chi; boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0; boolean likerock=0, can_tunnel=0; boolean can_open=0, can_unlock=0, doorbuster=0; struct permonst *ptr = mtmp->data; schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */ coord poss[9]; long info[9]; long flag; if(mtmp->mtrapped) { i = mintrap(mtmp); if(i == 2) return(2); /* it died */ if(i == 1) return(0); /* still in trap, so didn't move */ } if(mtmp->mhide && (OBJ_AT(mtmp->mx, mtmp->my) || levl[mtmp->mx][mtmp->my].gmask) && rn2(10)) return(0); /* do not leave hiding place */ if(mtmp->meating) { mtmp->meating--; return(3); /* still eating */ } set_apparxy(mtmp); /* where does mtmp think you are? */ /* Not necessary if m_move called from this file, but necessary in * other calls of m_move (ex. leprechauns dodging) */ can_tunnel = tunnels(ptr) && #ifdef REINCARNATION dlevel != rogue_level && #endif (!needspick(ptr) || m_carrying(mtmp, PICK_AXE)); can_open = !(nohands(ptr) || verysmall(ptr)); can_unlock = ((can_open && m_carrying(mtmp, SKELETON_KEY)) || mtmp->iswiz); doorbuster = is_giant(ptr); #ifdef WORM if(mtmp->wormno) goto not_special; #endif /* my dog gets special treatment */ if(mtmp->mtame) { mmoved = dog_move(mtmp, after); goto postmov; } /* likewise for shopkeeper */ if(mtmp->isshk) { mmoved = shk_move(mtmp); if(mmoved == -2) return(2); if(mmoved >= 0) goto postmov; mmoved = 0; /* follow player outside shop */ } /* and for the guard */ if(mtmp->isgd) { mmoved = gd_move(mtmp); if(mmoved == -2) return(2); if(mmoved >= 0) goto postmov; mmoved = 0; } /* and the wiz already got special treatment */ if(mtmp->iswiz) { mmoved = 0; goto postmov; } #if defined(ALTARS) && defined(THEOLOGY) /* and for the priest */ if(mtmp->ispriest) { mmoved = pri_move(mtmp); if(mmoved == -2) return(2); if(mmoved >= 0) goto postmov; mmoved = 0; } #endif #ifdef MAIL if(ptr == &mons[PM_MAIL_DAEMON]) { if(flags.soundok && canseemon(mtmp)) verbalize("I'm late!"); mongone(mtmp); return(2); } #endif /* teleport if that lies in our nature */ if(ptr == &mons[PM_TENGU] && !rn2(5)) { if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2)) rloc(mtmp); else mnexto(mtmp); mmoved = 1; goto postmov; } #ifdef WORM not_special: #endif if(!mtmp->mflee && u.uswallow && u.ustuck != mtmp) return(1); appr = 1; if(mtmp->mflee) appr = -1; if(mtmp->mconf || (Invis && !perceives(ptr)) || !mtmp->mcansee || #ifdef POLYSELF (u.usym == S_MIMIC_DEF) || u.uundetected || #endif (mtmp->mpeaceful && !mtmp->isshk) || /* allow shks to follow */ ((ptr->mlet == S_STALKER || ptr->mlet == S_BAT || ptr->mlet == S_YLIGHT) && !rn2(3))) appr = 0; omx = mtmp->mx; omy = mtmp->my; gx = mtmp->mux; gy = mtmp->muy; if(ptr == &mons[PM_LEPRECHAUN] && appr == 1 && mtmp->mgold > u.ugold) appr = -1; if(can_track(ptr)) { 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; } } } #ifdef REINCARNATION if (dlevel != rogue_level) #endif { register int pctload = (curr_mon_load(mtmp) * 100) / max_mon_load(mtmp); /* look for gold or jewels nearby */ likegold = (likes_gold(ptr) && pctload < 95); likegems = (likes_gems(ptr) && pctload < 85); likeobjs = (likes_objs(ptr) && pctload < 75); likemagic = (likes_magic(ptr) && pctload < 85); likerock = (throws_rocks(ptr) && pctload < 50); conceals = hides_under(ptr); } #define SRCHRADIUS 25 { xchar mind = SRCHRADIUS; /* not too far away */ register int dd; /* cut down the search radius if it thinks character is closer. */ if(dist2(mtmp->mux, mtmp->muy, omx, omy) < SRCHRADIUS && !mtmp->mtame && !mtmp->mpeaceful) mind /= 2; if(likegold){ register struct gold *gold; for(gold = fgold; gold; gold = gold->ngold) if((dd = dist2(omx,omy,gold->gx,gold->gy)) < mind){ mind = dd; gx = gold->gx; gy = gold->gy; } } if((likegems || likeobjs || likemagic || likerock || conceals) && (!in_shop(omx, omy) || (!rn2(25) && !mtmp->isshk))) { register struct obj *otmp; for(otmp = fobj; otmp; otmp = otmp->nobj) if((likeobjs && index(practical, otmp->olet)) || (likemagic && index(magical, otmp->olet)) || (likerock && otmp->otyp == BOULDER) || (likegems && otmp->olet == GEM_SYM && otmp->otyp < LAST_GEM + 6) || (conceals && !cansee(otmp->ox,otmp->oy)) || (ptr == &mons[PM_GELATINOUS_CUBE] && !index(indigestion, otmp->olet)) ) { if(can_carry(mtmp,otmp)) if(ptr->mlet != S_UNICORN || objects[otmp->otyp].g_val != 0) if((dd = dist2(omx,omy,otmp->ox,otmp->oy)) < mind){ mind = dd; gx = otmp->ox; gy = otmp->oy; } } } if(mind < SRCHRADIUS && appr == -1) { if(dist2(omx,omy,mtmp->mux,mtmp->muy) < 10) { gx = mtmp->mux; gy = mtmp->muy; } else appr = 1; } } nix = omx; niy = omy; flag = ALLOW_TRAPS; if (mtmp->mpeaceful) flag |= (ALLOW_SANCT | ALLOW_SSM); else flag |= ALLOW_U; if (ptr->mlet == S_UNICORN) flag |= NOTONL; if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK); if (can_tunnel) flag |= ALLOW_DIG; if (is_human(ptr)) flag |= ALLOW_SSM; if (is_undead(ptr)) flag |= NOGARLIC; if (throws_rocks(ptr)) flag |= ALLOW_ROCK; if (can_open) flag |= OPENDOOR; if (can_unlock) flag |= UNLOCKDOOR; if (doorbuster) flag |= BUSTDOOR; cnt = mfndpos(mtmp, poss, info, flag); chcnt = 0; chi = -1; for(i=0; i < cnt; i++) { nx = poss[i].x; ny = poss[i].y; if (appr != 0) for(j=0; j < MTSZ && j < cnt-1; j++) if(nx == mtmp->mtrack[j].x && ny == mtmp->mtrack[j].y) if(rn2(4*(cnt-j))) goto nxti; nearer = (dist2(nx,ny,gx,gy) < dist2(nix,niy,gx,gy)); if((appr == 1 && nearer) || (appr == -1 && !nearer) || (!appr && !rn2(++chcnt)) || !mmoved) { nix = nx; niy = ny; chi = i; mmoved = 1; } nxti: ; } if(mmoved) { #ifdef POLYSELF if (mmoved==1 && (u.ux != nix || u.uy != niy) && itsstuck(mtmp)) return(3); #endif if((info[chi] & ALLOW_U) || (nix == u.ux && niy == u.uy)) { mtmp->mux = u.ux; mtmp->muy = u.uy; return(0); } /* The monster may attack another based on 1 of 2 conditions: * 1 - He may be under the "conflict" influence. * 2 - He may mistake the monster for your (displaced) image. * Pets get taken care of above and shouldn't reach this code. */ if((info[chi] & ALLOW_M) || (nix == mtmp->mux && niy == mtmp->muy)) { int stat; mtmp2 = (MON_AT(nix, niy) ? m_at(nix,niy) : (struct monst *)0); if((stat = mattackm(mtmp, mtmp2)) == 1 && rn2(4) && mtmp2->mlstmv != moves && mattackm(mtmp2, mtmp) == 2) return(2); if(stat == -1) return(2); return(3); } #ifdef WORM /* The square now has a worm segment and must keep its MON_AT() state */ if (!mtmp->wormno) #endif remove_monster(omx, omy); place_monster(mtmp, nix, 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; #ifdef WORM if(mtmp->wormno) worm_move(mtmp); #endif } else { if(ptr->mlet == S_UNICORN && rn2(2)) { rloc(mtmp); return(1); } #ifdef WORM if(mtmp->wormno) worm_nomove(mtmp); #endif } postmov: if(mmoved == 1) { boolean canseeit = cansee(mtmp->mx, mtmp->my); boolean abstain = (mtmp->mpeaceful && !mtmp->mtame); if(mintrap(mtmp) == 2) return(2); /* he died */ /* open a door, or crash through it, if you can */ if(IS_DOOR(levl[mtmp->mx][mtmp->my].typ) && !passes_walls(ptr) /* doesn't need to open doors */ && !can_tunnel /* taken care of below */ ) { struct rm *here = &levl[mtmp->mx][mtmp->my]; boolean btrapped = (here->doormask & D_TRAPPED); if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) { if (flags.verbose && canseeit) pline("%s %ss under the door.", Monnam(mtmp), ptr == &mons[PM_FOG_CLOUD] ? "flow" : "ooze"); } else if(here->doormask & D_LOCKED && can_unlock) { if(btrapped) { here->doormask = D_NODOOR; mnewsym(mtmp->mx, mtmp->my); if (canseeit) prl(mtmp->mx,mtmp->my); if(mb_trapped(mtmp)) return(2); } else { if (flags.verbose) { if (canseeit) You("see a door being unlocked and opened."); else if (flags.soundok) #ifdef NEXT { You("hear a door being unlocked and opened."); WindowSound("Door"); } #else You("hear a door being unlocked and opened."); #endif /* NEXT */ } here->doormask = D_ISOPEN; mnewsym(mtmp->mx, mtmp->my); if (canseeit) prl(mtmp->mx,mtmp->my); } } else if (here->doormask == D_CLOSED && can_open) { if(btrapped) { here->doormask = D_NODOOR; mnewsym(mtmp->mx, mtmp->my); if (canseeit) prl(mtmp->mx,mtmp->my); if(mb_trapped(mtmp)) return(2); } else { if (flags.verbose) { if (canseeit) You("see a door being opened."); else if (flags.soundok) #ifdef NEXT { You("hear the sound of a door opening."); WindowSound("Door"); } #else You("hear the sound of a door opening."); #endif /* NEXT */ } here->doormask = D_ISOPEN; mnewsym(mtmp->mx, mtmp->my); if (canseeit) prl(mtmp->mx,mtmp->my); } } else if (here->doormask & (D_LOCKED|D_CLOSED)) { /* mfndpos guarantees this must be a doorbuster */ if(btrapped) { here->doormask = D_NODOOR; mnewsym(mtmp->mx, mtmp->my); if (canseeit) prl(mtmp->mx,mtmp->my); if(mb_trapped(mtmp)) return(2); } else { if (flags.verbose) { if (canseeit) You("see a door crash open."); else if (flags.soundok) You("hear the sound of a door crashing open."); } if (here->doormask & D_LOCKED && !rn2(2)) here->doormask = D_NODOOR; else here->doormask = D_BROKEN; mnewsym(mtmp->mx, mtmp->my); if (canseeit) prl(mtmp->mx,mtmp->my); } } } /* Maybe a rock mole just ate something? */ if(can_tunnel) if(!mdig_tunnel(mtmp)) return(2); /* died? */ if(levl[mtmp->mx][mtmp->my].gmask == TRUE) { /* Maybe a rock mole just ate some gold */ if(metallivorous(ptr)) meatgold(mtmp); if(likegold && (!abstain || !rn2(10))) mpickgold(mtmp); } if(OBJ_AT(mtmp->mx, mtmp->my)) { /* Maybe a rock mole just ate some metal object */ if(metallivorous(ptr)) meatgold(mtmp); /* Maybe a cube ate just about anything */ if(ptr == &mons[PM_GELATINOUS_CUBE]) meatobj(mtmp); if ((!abstain || !rn2(10)) && (!in_shop(mtmp->mx, mtmp->my) || !rn2(25))) { if(likeobjs) mpickstuff(mtmp, practical); if(likemagic) mpickstuff(mtmp, magical); if(likerock || likegems) mpickgems(mtmp); } } if(mtmp->mhide) mtmp->mundetected = (OBJ_AT(mtmp->mx, mtmp->my) || levl[mtmp->mx][mtmp->my].gmask); /* set also in domove(), hack.c */ if(u.uswallow && mtmp == u.ustuck) { u.ux = mtmp->mx; u.uy = mtmp->my; if(mtmp->mx != mtmp->mdx || mtmp->my != mtmp->mdy) { swallowed(0); newsym(mtmp->mdx,mtmp->mdy); mtmp->mdx = mtmp->mx; mtmp->mdy = mtmp->my; } } pmon(mtmp); } return(mmoved); } #endif /* OVL0 */ #ifdef OVL2 boolean closed_door(x, y) register int x, y; { return(IS_DOOR(levl[x][y].typ) && (levl[x][y].doormask & (D_LOCKED | D_CLOSED))); } boolean accessible(x, y) register int x, y; { return(ACCESSIBLE(levl[x][y].typ) && !closed_door(x, y)); } #endif /* OVL2 */ #ifdef OVL1 void set_apparxy(mtmp) /* where does mtmp think you are standing? */ register struct monst *mtmp; { #define notseen (Invis && !perceives(mtmp->data)) /* add cases as required. eg. Displacement ... */ register int disp = (notseen ? 1 : Displaced ? 2 : 0); /* without something like the following, invis. and displ. are too */ /* powerful. */ register boolean gotu = (notseen ? !rn2(3) : Displaced ? !rn2(4) : FALSE); /* Monsters which know where you are don't suddenly forget, if you didn't move away. */ if (mtmp->mux==u.ux && mtmp->muy==u.uy) gotu = 1; /* your dog follows your smell */ if(!disp || mtmp->mtame || gotu || /* If invisible but not displaced, staying around gets you 'discovered' */ (!Displaced && u.dx == 0 && u.dy == 0)) { mtmp->mux = u.ux; mtmp->muy = u.uy; } else do { mtmp->mux = u.ux - disp + rn2(2*disp+1); mtmp->muy = u.uy - disp + rn2(2*disp+1); } while((mtmp->mux != u.ux || mtmp->muy != u.uy) && ( (!passes_walls(mtmp->data) && (!ACCESSIBLE(levl[mtmp->mux][mtmp->muy].typ) || (closed_door(mtmp->mux, mtmp->muy) && !amorphous(mtmp->data) ) ) ) || (disp==1 && mtmp->mux == mtmp->mx && mtmp->muy == mtmp->my) ) ); } #endif /* OVL1 */ #ifdef OVLB #ifdef STUPID_CPP /* otherwise these functions are macros in rm.h */ /* * Functions for encapsulation of level.monsters references. */ boolean MON_AT(x, y) int x, y; { return(level.monsters[x][y] != (struct monst *)0); } void place_monster(mtmp, x, y) register struct monst *mtmp; int x, y; { level.monsters[x][y] = mtmp; mtmp->mx = x; mtmp->my = y; } void place_worm_seg(mtmp, x, y) register struct monst *mtmp; int x, y; { level.monsters[x][y] = mtmp; } void remove_monster(x, y) int x, y; { level.monsters[x][y] = (struct monst *)0; } struct monst *m_at(x, y) int x, y; { return(level.monsters[x][y]); } #endif /* STUPID_CPP */ #endif /* OVLB */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.