예제 #1
0
/*
 * Is (x,y) a good position of mtmp?  If mtmp is NULL, then is (x,y) good
 * for an object?
 *
 * This function will only look at mtmp->mdat, so makemon, mplayer, etc can
 * call it to generate new monster positions with fake monster structures.
 */
boolean goodpos(struct level *lev, int x, int y, struct monst *mtmp, unsigned gpflags)
{
	const struct permonst *mdat = NULL;
	boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0);

	if (!isok(x, y)) return FALSE;

	/* in many cases, we're trying to create a new monster, which
	 * can't go on top of the player or any existing monster.
	 * however, occasionally we are relocating engravings or objects,
	 * which could be co-located and thus get restricted a bit too much.
	 * oh well.
	 */
	if (mtmp != &youmonst && x == u.ux && y == u.uy
			&& (!u.usteed || mtmp != u.usteed))
		return FALSE;

	if (mtmp) {
	    struct monst *mtmp2 = m_at(lev, x,y);

	    /* Be careful with long worms.  A monster may be placed back in
	     * its own location.  Normally, if m_at() returns the same monster
	     * that we're trying to place, the monster is being placed in its
	     * own location.  However, that is not correct for worm segments,
	     * because all the segments of the worm return the same m_at().
	     * Actually we overdo the check a little bit--a worm can't be placed
	     * in its own location, period.  If we just checked for mtmp->mx
	     * != x || mtmp->my != y, we'd miss the case where we're called
	     * to place the worm segment and the worm's head is at x,y.
	     */
	    if (mtmp2 && (mtmp2 != mtmp || mtmp->wormno))
		return FALSE;

	    mdat = mtmp->data;
	    if (is_pool(lev, x,y) && !ignorewater) {
		if (mtmp == &youmonst)
			return !!(HLevitation || Flying || Wwalking ||
					Swimming || Amphibious);
		else	return (is_flyer(mdat) || is_swimmer(mdat) ||
							is_clinger(mdat));
	    } else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) {
		return FALSE;
	    } else if (is_lava(lev, x,y)) {
		if (mtmp == &youmonst)
		    return !!HLevitation;
		else
		    return is_flyer(mdat) || likes_lava(mdat);
	    }
	    if (passes_walls(mdat) && may_passwall(lev, x,y)) return TRUE;
	}
	if (!ACCESSIBLE(lev->locations[x][y].typ)) {
		if (!(is_pool(lev, x,y) && ignorewater)) return FALSE;
	}

	if (closed_door(lev, x, y) && (!mdat || !amorphous(mdat)))
		return FALSE;
	if (sobj_at(BOULDER, lev, x, y) && (!mdat || !throws_rocks(mdat)))
		return FALSE;
	return TRUE;
}
예제 #2
0
파일: makemon.c 프로젝트: msharov/bsd-games
int goodpos(int x, int y)
{			       // used only in mnexto and rloc
    return !(x < 1 || x > COLNO - 2 || y < 1 || y > ROWNO - 2 || m_at(x, y) || !ACCESSIBLE(_level->l[x][y].typ)
	      || (x == _u.ux && y == _u.uy)
	      || sobj_at(ENORMOUS_ROCK, x, y)
	    );
}
예제 #3
0
static Boolean teleok(Short x, Short y)
{	/* might throw him into a POOL */
  return( !OUT_OF_BOUNDS(x,y) &&
	  !IS_ROCK(get_cell_type(floor_info[x][y])) &&
	  !mon_at(x,y) &&
	  !sobj_at(ENORMOUS_ROCK,x,y) &&
	  !trap_at(x,y)
	  );
  /* Note: gold is permitted (because of vaults) */
}
예제 #4
0
bool
goodpos(int x, int 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)
		  ));
}
예제 #5
0
/* used only in mnexto and rloc */
int
goodpos(int x, int y)
{
	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)
	));
}
예제 #6
0
/* make a swarm of undead around mm; uses the main RNG */
void
mkundead(struct level *lev, coord *mm, boolean revive_corpses, int mm_flags)
{
    int cnt = (level_difficulty(&lev->z) + 1) / 10 + rnd(5);
    const struct permonst *mdat;
    struct obj *otmp;
    coord cc;

    while (cnt--) {
        mdat = morguemon(&lev->z, rng_main);
        if (enexto(&cc, lev, mm->x, mm->y, mdat) &&
            (!revive_corpses || !(otmp = sobj_at(CORPSE, lev, cc.x, cc.y)) ||
             !revive(otmp)))
            makemon(mdat, lev, cc.x, cc.y, mm_flags);
    }
    lev->flags.graveyard = TRUE;        /* reduced chance for undead corpse */
}
예제 #7
0
/* make a swarm of undead around mm */
void 
mkundead (coord *mm, bool revive_corpses, int mm_flags)
{
        int cnt = (level_difficulty() + 1)/10 + rnd(5);
        struct permonst *mdat;
        struct obj *otmp;
        coord cc;

        while (cnt--) {
            mdat = morguemon();
            if (enexto(&cc, mm->x, mm->y, mdat) &&
                    (!revive_corpses ||
                     !(otmp = sobj_at(CORPSE, cc.x, cc.y)) ||
                     !revive(otmp)))
                (void) makemon(mdat, cc.x, cc.y, mm_flags);
        }
        level.flags.graveyard = true;   /* reduced chance for undead corpse */
}
예제 #8
0
/*
 * Try to find a dismount point adjacent to the steed's location.
 * If all else fails, try enexto().  Use enexto() as a last resort because
 * enexto() chooses its point randomly, possibly even outside the
 * room's walls, which is not what we want.
 * Adapted from mail daemon code.
 */
static boolean
landing_spot(coord * spot,      /* landing position (we fill it in) */
             int reason, int forceit)
{
    int i = 0, x, y, distance, min_distance = -1;
    boolean found = FALSE;
    struct trap *t;

    /* avoid known traps (i == 0) and boulders, but allow them as a backup */
    if (reason != DISMOUNT_BYCHOICE || Stunned || Confusion || Fumbling)
        i = 1;
    for (; !found && i < 2; ++i) {
        for (x = u.ux - 1; x <= u.ux + 1; x++)
            for (y = u.uy - 1; y <= u.uy + 1; y++) {
                if (!isok(x, y) || (x == u.ux && y == u.uy))
                    continue;

                if (ACCESSIBLE(level->locations[x][y].typ) &&
                    !MON_AT(level, x, y) && !closed_door(level, x, y)) {
                    distance = distu(x, y);
                    if (min_distance < 0 || distance < min_distance ||
                        (distance == min_distance && rn2(2))) {
                        if (i > 0 ||
                            (((t = t_at(level, x, y)) == 0 || !t->tseen) &&
                             (!sobj_at(BOULDER, level, x, y) ||
                              throws_rocks(youmonst.data)))) {
                            spot->x = x;
                            spot->y = y;
                            min_distance = distance;
                            found = TRUE;
                        }
                    }
                }
            }
    }

    /* If we didn't find a good spot and forceit is on, try enexto(). */
    if (forceit && min_distance < 0 &&
        !enexto(spot, level, u.ux, u.uy, youmonst.data))
        return FALSE;

    return found;
}
예제 #9
0
/*
 * shk_move: return 1: he moved  0: he didnt  -1: let m_move do it
 * (what about "return 2" ???
 */
Short shk_move(monst_t *shkp)
{
  monst_t *mtmp;
  permonst_t *mdat = shkp->data;
  UChar gx,gy,omx,omy,nx,ny,nix,niy;
  Int8 appr,i;
  Short udist;
  Short z;
  Int8 shkroom,chi,chcnt,cnt;
  Boolean uondoor=false, satdoor, avoid=false, badinv;
  coord poss[9];
  Short info[9];
  obj_t *ib = NULL;

  omx = shkp->mx;
  omy = shkp->my;

  if ((udist = dist(omx,omy)) < 3) {
    if (ANGRY(shkp)) {
      hit_you(shkp, dice(mdat->damn, mdat->damd)+1);
      return 0;
    }
    if (ESHK(shkp)->following) {
      if (StrNCompare(ESHK(shkp)->customer, plname, PL_NSIZ)) {
	StrPrintF(ScratchBuffer, "Hello %s! I was looking for %s.",
		  plname, ESHK(shkp)->customer);
	message(ScratchBuffer);
	ESHK(shkp)->following = false;
	return 0;
      }
      if (!ESHK(shkp)->robbed) {	/* impossible? */
	ESHK(shkp)->following = false;
	return 0;
      }
      if (moves > followmsg+4) {
	StrPrintF(ScratchBuffer, "Hello %s! Didn't you forget to pay?",
		  plname);
	message(ScratchBuffer);
	followmsg = moves;
      }
      if (udist < 2)
	return 0;
    }
  }

  shkroom = inroom(omx,omy);
  appr = 1;
  gx = ESHK(shkp)->shk.x;
  gy = ESHK(shkp)->shk.y;
  satdoor = (gx == omx && gy == omy);
  if (ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){
    gx = you.ux;
    gy = you.uy;
    if (shkroom < 0 || shkroom != inroom(you.ux,you.uy))
      if (udist > 4)
	return -1;	/* leave it to m_move */
  } else if (ANGRY(shkp)) {
    Long saveBlind = Blind;
    Blind = 0;
    if ((shkp->mcansee_and_blinded & M_CAN_SEE) && !Invis && cansee(omx,omy)) {
      gx = you.ux;
      gy = you.uy;
    }
    Blind = saveBlind;
    avoid = false;
  } else {
#define	GDIST(x,y)	((x-gx)*(x-gx)+(y-gy)*(y-gy))
    if (Invis)
      avoid = false;
    else {
      uondoor = (you.ux == ESHK(shkp)->shd.x &&
		 you.uy == ESHK(shkp)->shd.y);
      if (uondoor) {
	if (ESHK(shkp)->billct) {
	  StrPrintF(ScratchBuffer,
		    "Hello %s! Will you please pay before leaving?", plname);
	  message(ScratchBuffer);
	}
	badinv = (carrying(PICK_AXE) || carrying(ICE_BOX));
	if (satdoor && badinv)
	  return 0;
	avoid = !badinv;
      } else {
	avoid = (you.uinshop && dist(gx,gy) > 8);
	badinv = false;
      }

      if (((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
	  && GDIST(omx,omy) < 3) {
	if (!badinv && !online(omx,omy))
	  return 0;
	if (satdoor)
	  appr = gx = gy = 0;
      }
    }
  }
  if (omx == gx && omy == gy)
    return 0;
  if (shkp->bitflags & M_IS_CONFUSED) {
    avoid = false;
    appr = 0;
  }
  nix = omx;
  niy = omy;
  cnt = mfindpos(shkp,poss,info,ALLOW_SSM);
  if (avoid && uondoor) {		/* perhaps we cannot avoid him */
    for (i=0; i<cnt; i++)
      if (!(info[i] & NOTONL)) goto notonl_ok;
    avoid = false;
  notonl_ok:
    ;
  }
  chi = -1;
  chcnt = 0;
  for (i = 0 ; i < cnt ; i++) {
    nx = poss[i].x;
    ny = poss[i].y;
    if (get_cell_type(floor_info[nx][ny]) == ROOM
	|| shkroom != ESHK(shkp)->shoproom
	|| ESHK(shkp)->following) {
#ifdef STUPID
      /* cater for stupid compilers */
      Short zz;
#endif STUPID
      if (uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) {
	nix = nx; niy = ny; chi = i; break;
      }
      if (avoid && (info[i] & NOTONL))
	continue;
      if ((!appr && !rund(++chcnt)) ||
#ifdef STUPID
	  (appr && (zz = GDIST(nix,niy)) && zz > GDIST(nx,ny))
#else
	  (appr && GDIST(nx,ny) < GDIST(nix,niy))
#endif STUPID
	  ) {
	nix = nx;
	niy = ny;
	chi = i;
      }
    }
  }
  if (nix != omx || niy != omy) {
    if (info[chi] & ALLOW_M){
      mtmp = mon_at(nix,niy);
      if (hitmm(shkp,mtmp) == 1 && rund(3) &&
	  hitmm(mtmp,shkp) == 2) return 2;
      return 0;
    } else if (info[chi] & ALLOW_U){
      hit_you(shkp, dice(mdat->damn, mdat->damd)+1);
      return 0;
    }
    shkp->mx = nix;
    shkp->my = niy;
    pmon(shkp);
    if (ib) {
      unlink_obj(ib);//freeobj
      mpickobj(shkp, ib);
    }
    return 1;
  }
  return 0;
}
예제 #10
0
/*
 * Let's destroy the drawbridge located at x,y
 */
void destroy_drawbridge(int x, int y)
{
	struct rm *loc1, *loc2;
	struct trap *t;
	int x2, y2;
	int db_u;
	boolean e_inview;
	struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);

	loc1 = &level->locations[x][y];
	if (!IS_DRAWBRIDGE(loc1->typ))
		return;
	x2 = x; y2 = y;
	get_wall_for_db(&x2,&y2);
	loc2 = &level->locations[x2][y2];
	db_u = (loc1->drawbridgemask & DB_UNDER);
	if (db_u == DB_MOAT || db_u == DB_LAVA || db_u == DB_BOG) {
		struct obj *otmp;
		int where = (db_u == DB_LAVA) ? 0 :
			    (db_u == DB_MOAT) ? 1 : 2;
		static char *wstr[3] = { "lava", "moat", "swamp" };
		if (loc1->typ == DRAWBRIDGE_UP) {
			if (cansee(x2,y2))
			    pline("The portcullis of the drawbridge falls into the %s!",
				  wstr[where]);
			else if (flags.soundok)
				You_hear("a loud *SPLASH*!");
		} else {
			if (cansee(x,y))
			    pline("The drawbridge collapses into the %s!",
				  wstr[where]);
			else if (flags.soundok)
				You_hear("a loud *SPLASH*!");
		}
		loc1->typ = (where == 0) ? LAVAPOOL :
			    (where == 1) ? MOAT : BOG;
		loc1->drawbridgemask = 0;
		if ((otmp = sobj_at(BOULDER, level, x,y)) != 0) {
		    obj_extract_self(otmp);
		    flooreffects(otmp,x,y,"fall");
		}
	} else {
		if (cansee(x,y))
			pline("The drawbridge disintegrates!");
		else
			You_hear("a loud *CRASH*!");
		loc1->typ =
			((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM);
		loc1->icedpool =
			((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
	}
	wake_nearto(x, y, 500);
	loc2->typ = DOOR;
	loc2->doormask = D_NODOOR;
	if ((t = t_at(level, x, y)) != 0) deltrap(level, t);
	if ((t = t_at(level, x2, y2)) != 0) deltrap(level, t);
	newsym(x,y);
	newsym(x2,y2);
	if (!does_block(level, x2, y2, NULL)) unblock_point(x2,y2); /* vision */
	if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE;

	set_entity(x2, y2, etmp2); /* currently only automissers can be here */
	if (etmp2->edata) {
		e_inview = e_canseemon(level, etmp2);
		if (!automiss(etmp2)) {
			if (e_inview)
				pline("%s blown apart by flying debris.",
				      E_phrase(etmp2, "are"));
			killer_format = KILLED_BY_AN;
			killer = "exploding drawbridge";
			e_died(etmp2, e_inview? 3 : 2, CRUSHING); /*no corpse*/
		}	     /* nothing which is vulnerable can survive this */
	}
	set_entity(x, y, etmp1);
	if (etmp1->edata) {
		e_inview = e_canseemon(level, etmp1);
		if (!e_missed(etmp1, TRUE)) {
			if (e_inview) {
			    if (!is_u(etmp1) && Hallucination)
				pline("%s into some heavy metal!",
				      E_phrase(etmp1, "get"));
			    else
				pline("%s hit by a huge chunk of metal!",
				      E_phrase(etmp1, "are"));
			} else {
			    if (flags.soundok && !is_u(etmp1) && !is_pool(level, x,y))
				You_hear("a crushing sound.");
			}
			killer_format = KILLED_BY_AN;
			killer = "collapsing drawbridge";
			e_died(etmp1, e_inview? 3 : 2, CRUSHING); /*no corpse*/
			if (loc1->typ == MOAT) do_entity(etmp1);
		}
	}
}
예제 #11
0
static int
dig()
{
	struct rm *lev;
	int dpx = dig_pos.x, dpy = dig_pos.y;

	/* perhaps a nymph stole his pick-axe while he was busy digging */
	/* or perhaps he teleported away */
	if(u.uswallow || !uwep || uwep->otyp != PICK_AXE ||
	    dig_level != dlevel ||
	    ((dig_down && (dpx != u.ux || dpy != u.uy)) ||
	     (!dig_down && dist(dpx,dpy) > 2)))
		return(0);

	dig_effort += 10 + abon() + uwep->spe + rn2(5);
	if(dig_down) {
		if(!xdnstair) {
			pline("The floor here seems too hard to dig in.");
			return(0);
		}
		if(dig_effort > 250) {
			dighole();
			return(0);	/* done with digging */
		}
		if(dig_effort > 50) {
			struct trap *ttmp = t_at(dpx,dpy);

			if(!ttmp) {
				ttmp = maketrap(dpx,dpy,PIT);
				ttmp->tseen = 1;
				pline("You have dug a pit.");
				u.utrap = rn1(4,2);
				u.utraptype = TT_PIT;
				return(0);
			}
		}
	} else
	if (dig_effort > 100) {
		char *digtxt;
		struct obj *obj;

		lev = &levl[dpx][dpy];
		if ((obj = sobj_at(ENORMOUS_ROCK, dpx, dpy))) {
			fracture_rock(obj);
			digtxt = "The rock falls apart.";
		} else if(!lev->typ || lev->typ == SCORR) {
			lev->typ = CORR;
			digtxt = "You succeeded in cutting away some rock.";
		} else if(lev->typ == HWALL || lev->typ == VWALL
					    || lev->typ == SDOOR) {
			lev->typ = xdnstair ? DOOR : ROOM;
			digtxt = "You just made an opening in the wall.";
		} else
		  digtxt = "Now what exactly was it that you were digging in?";
		mnewsym(dpx, dpy);
		prl(dpx, dpy);
		pline(digtxt);		/* after mnewsym & prl */
		return(0);
	} else {
		if(IS_WALL(levl[dpx][dpy].typ)) {
			int rno = inroom(dpx,dpy);

			if(rno >= 0 && rooms[rno].rtype >= 8) {
			  pline("This wall seems too hard to dig into.");
			  return(0);
			}
		}
		pline("You hit the rock with all your might.");
	}
	return(1);
}
예제 #12
0
static int
use_pick_axe(struct obj *obj)
{
	char dirsyms[12];
	extern char sdir[];
	char *dsp = dirsyms, *sdp = sdir;
	struct monst *mtmp;
	struct rm *lev;
	int rx, ry, res = 0;

	if(obj != uwep) {
		if(uwep && uwep->cursed) {
			/* Andreas Bormann - ihnp4!decvax!mcvax!unido!ab */
			pline("Since your weapon is welded to your hand,");
			pline("you cannot use that pick-axe.");
			return(0);
		}
		pline("You now wield %s.", doname(obj));
		setuwep(obj);
		res = 1;
	}
	while(*sdp) {
		(void) movecmd(*sdp);	/* sets u.dx and u.dy and u.dz */
		rx = u.ux + u.dx;
		ry = u.uy + u.dy;
		if(u.dz > 0 || (u.dz == 0 && isok(rx, ry) &&
		    (IS_ROCK(levl[rx][ry].typ)
		    || sobj_at(ENORMOUS_ROCK, rx, ry))))
			*dsp++ = *sdp;
		sdp++;
	}
	*dsp = 0;
	pline("In what direction do you want to dig? [%s] ", dirsyms);
	if(!getdir(0))		/* no txt */
		return(res);
	if(u.uswallow && attack(u.ustuck)) /* return(1) */;
	else
	if(u.dz < 0)
		pline("You cannot reach the ceiling.");
	else
	if(u.dz == 0) {
		if(Confusion)
			confdir();
		rx = u.ux + u.dx;
		ry = u.uy + u.dy;
		if((mtmp = m_at(rx, ry)) && attack(mtmp))
			return(1);
		if(!isok(rx, ry)) {
			pline("Clash!");
			return(1);
		}
		lev = &levl[rx][ry];
		if(lev->typ == DOOR)
			pline("Your %s against the door.",
				aobjnam(obj, "clang"));
		else if(!IS_ROCK(lev->typ)
		     && !sobj_at(ENORMOUS_ROCK, rx, ry)) {
			/* ACCESSIBLE or POOL */
			pline("You swing your %s through thin air.",
				aobjnam(obj, (char *) 0));
		} else {
			if(dig_pos.x != rx || dig_pos.y != ry
			    || dig_level != dlevel || dig_down) {
				dig_down = FALSE;
				dig_pos.x = rx;
				dig_pos.y = ry;
				dig_level = dlevel;
				dig_effort = 0;
				pline("You start digging.");
			} else
				pline("You continue digging.");
			occupation = dig;
			occtxt = "digging";
		}
	} else if(Levitation) {
		pline("You cannot reach the floor.");
	} else {
		if(dig_pos.x != u.ux || dig_pos.y != u.uy
		    || dig_level != dlevel || !dig_down) {
			dig_down = TRUE;
			dig_pos.x = u.ux;
			dig_pos.y = u.uy;
			dig_level = dlevel;
			dig_effort = 0;
			pline("You start digging in the floor.");
			if(inshop())
				shopdig(0);
		} else
			pline("You continue digging in the floor.");
		occupation = dig;
		occtxt = "digging";
	}
	return(1);
}
예제 #13
0
/*
 * shk_move: return 1: he moved  0: he didnt  -1: let m_move do it
 */
int
shk_move(struct monst *shkp)
{
	struct monst *mtmp;
	struct permonst *mdat = shkp->data;
	xchar gx, gy, omx, omy, nx, ny, nix, niy;
	schar appr, i;
	int udist;
	int z;
	schar shkroom, chi, chcnt, cnt;
	boolean uondoor = 0, satdoor, avoid = 0, badinv;
	coord poss[9];
	int info[9];
	struct obj *ib = NULL;

	omx = shkp->mx;
	omy = shkp->my;

	if ((udist = dist(omx, omy)) < 3) {
		if (ANGRY(shkp)) {
			hitu(shkp, d(mdat->damn, mdat->damd) + 1);
			return (0);
		}
		if (ESHK(shkp)->following) {
			if (strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)) {
				pline("Hello %s! I was looking for %s.",
				      plname, ESHK(shkp)->customer);
				ESHK(shkp)->following = 0;
				return (0);
			}
			if (!ESHK(shkp)->robbed) {	/* impossible? */
				ESHK(shkp)->following = 0;
				return (0);
			}
			if (moves > followmsg + 4) {
				pline("Hello %s! Didn't you forget to pay?",
				      plname);
				followmsg = moves;
			}
			if (udist < 2)
				return (0);
		}
	}

	shkroom = inroom(omx, omy);
	appr = 1;
	gx = ESHK(shkp)->shk.x;
	gy = ESHK(shkp)->shk.y;
	satdoor = (gx == omx && gy == omy);
	if (ESHK(shkp)->following || ((z = holetime()) >= 0 && z * z <= udist)) {
		gx = u.ux;
		gy = u.uy;
		if (shkroom < 0 || shkroom != inroom(u.ux, u.uy))
			if (udist > 4)
				return (-1);	/* leave it to m_move */
	} else if (ANGRY(shkp)) {
		long saveBlind = Blind;
		Blind = 0;
		if (shkp->mcansee && !Invis && cansee(omx, omy)) {
			gx = u.ux;
			gy = u.uy;
		}
		Blind = saveBlind;
		avoid = FALSE;
	} else {
#define	GDIST(x, y)	((x - gx) * (x - gx) + (y - gy) * (y - gy))
		if (Invis)
			avoid = FALSE;
		else {
			uondoor = (u.ux == ESHK(shkp)->shd.x &&
				   u.uy == ESHK(shkp)->shd.y);
			if (uondoor) {
				if (ESHK(shkp)->billct)
					pline("Hello %s! Will you please pay before leaving?",
					    plname);
				badinv = (carrying(PICK_AXE) || carrying(ICE_BOX));
				if (satdoor && badinv)
					return (0);
				avoid = !badinv;
			} else {
				avoid = (u.uinshop && dist(gx, gy) > 8);
				badinv = FALSE;
			}

			if (((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
			    && GDIST(omx, omy) < 3) {
				if (!badinv && !online(omx, omy))
					return (0);
				if (satdoor)
					appr = gx = gy = 0;
			}
		}
	}
	if (omx == gx && omy == gy)
		return (0);
	if (shkp->mconf) {
		avoid = FALSE;
		appr = 0;
	}
	nix = omx;
	niy = omy;
	cnt = mfndpos(shkp, poss, info, ALLOW_SSM);
	if (avoid && uondoor) {	/* perhaps we cannot avoid him */
		for (i = 0; i < cnt; i++)
			if (!(info[i] & NOTONL))
				goto notonl_ok;
		avoid = FALSE;
notonl_ok:
		;
	}
	chi = -1;
	chcnt = 0;
	for (i = 0; i < cnt; i++) {
		nx = poss[i].x;
		ny = poss[i].y;
		if (levl[nx][ny].typ == ROOM
		    || shkroom != ESHK(shkp)->shoproom
		    || ESHK(shkp)->following) {
#ifdef STUPID
			/* cater for stupid compilers */
			int zz;
#endif /* STUPID */
			if (uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) {
				nix = nx;
				niy = ny;
				chi = i; break;
			}
			if (avoid && (info[i] & NOTONL))
				continue;
			if ((!appr && !rn2(++chcnt)) ||
#ifdef STUPID
			    (appr && (zz = GDIST(nix, niy)) && zz > GDIST(nx, ny))
#else
			    (appr && GDIST(nx, ny) < GDIST(nix, niy))
#endif /* STUPID */
			    ) {
				nix = nx;
				niy = ny;
				chi = i;
			}
		}
	}
	if (nix != omx || niy != omy) {
		if (info[chi] & ALLOW_M) {
			mtmp = m_at(nix, niy);
			if (hitmm(shkp, mtmp) == 1 && rn2(3) &&
			    hitmm(mtmp, shkp) == 2)
				return (2);
			return (0);
		} else if (info[chi] & ALLOW_U) {
			hitu(shkp, d(mdat->damn, mdat->damd) + 1);
			return (0);
		}
		shkp->mx = nix;
		shkp->my = niy;
		pmon(shkp);
		if (ib) {
			freeobj(ib);
			mpickobj(shkp, ib);
		}
		return (1);
	}
	return (0);
}
예제 #14
0
/* Returns 1 if monster died moving, 0 otherwise */
int dochug(struct monst *mtmp)
{
    struct permonst *mdat;
    int tmp = 0;

    if((mtmp->cham != 0) && (rn2(6) == 0)) {
        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);
    }

    if((((moves % 20) == 0) || (index("ViT", mdat->mlet) != 0))
       && (mtmp->mhp < mtmp->orig_hp)) {
        /* Regenerate monsters. */
        ++mtmp->mhp;
    }

    if(mtmp->mfroz != 0) {
        /* Frozen monsters don't do anything. */
        return 0;
    }

    if(mtmp->msleep != 0) {
        /* Wake up a monster, or get out of here. */
        if((cansee(mtmp->mx, mtmp->my) != 0)
	   && (Stealth == 0)
	   && ((index("NL", mdat->mlet) == 0)
	       || (rn2(50) == 0))
	   && ((Aggravate_monster != 0) 
	       || ((rn2(7) == 0) && (mtmp->mimic == 0)))) {
            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 != 0) && (rn2(50) == 0)) {
        mtmp->mconf = 0;
    }

    /* Some monsters teleport */
    if((mtmp->mflee != 0)
       && (index("tNL", mdat->mlet) != 0) 
       && (rn2(40) == 0)) {
        rloc(mtmp);

        return 0;
    }

    if(mdat->mmove < rnd(6)) {
        return 0;
    }

    if((mtmp->mflee != 0)
       || (mtmp->mconf != 0)
       || ((index("BIuy", mdat->mlet) != 0) && (rn2(4) == 0))
       || ((mdat->mlet == 'L') 
           && (u.ugold == 0)
           && ((mtmp->mgold != 0) || (rn2(2) != 0)))
       || (dist(mtmp->mx, mtmp->my) > 2)
       || ((mtmp->mcansee == 0) && (rn2(4) == 0))
       || (mtmp->mpeaceful != 0)) {
        tmp = m_move(mtmp, 0);
        if((tmp != 0) && (mdat->mmove < 12)) {
            if(tmp == 2) {
                return 1;
            }
            else {
                return 0;
            }
        }
    }

    if(tmp == 2) {
        /* Monster died moving */
        return 1;
    }

    if((index("Ea", mdat->mlet) == 0) 
       && (dist(mtmp->mx, mtmp->my) < 3)
       && (mtmp->mpeaceful == 0)
       && (u.uhp > 0)
       && (sengr_at("Elbereth", u.ux, u.uy) == 0)
       && (sobj_at(SCR_SCARE_MONSTER, u.ux, u.uy) == 0)) {
        if(mhitu(mtmp) != 0) {
            /* Monster died (e.g. 'y' or 'F') */
            return 1;
        }   
    }
        
    /* Extra movement for fast monsters */
    if((mdat->mmove - 12) > rnd(12)) {
        tmp = m_move(mtmp, 1);
    }

    if(tmp == 2) {
        return 1;
    }
    else {
        return 0;
    }
}
예제 #15
0
/* Return number of acceptable neighbour positions */
int mfndpos(struct monst *mon, coord poss[9], int info[9], int flag)
{
    int x;
    int y;
    int nx;
    int ny;
    int cnt = 0;
    int tmp;
    struct monst *mtmp;

    x = mon->mx;
    y = mon->my;
    
    if(mon->mconf != 0) {
        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) != 0) {
                    tmp = levl[nx][ny].typ;
                    if(tmp >= DOOR) {
                        if((nx == x)
                           || (ny == y)
                           || ((levl[x][y].typ != DOOR) && (tmp != DOOR))) {
                            info[cnt] = 0;
                            
                            if((nx == u.ux) && (ny == u.uy)) {
                                if((flag & ALLOW_U) == 0) {
                                    continue;
                                }
                                
                                info[cnt] = ALLOW_U;
                            }
                            else {
                                mtmp = m_at(nx, ny);
                                if(mtmp != 0) {
                                    if((flag & ALLOW_M) == 0) {
                                        continue;
                                    }
                                    
                                    info[cnt] = ALLOW_M;
                                }
                                
                                if(mtmp->mtame != 0) {
                                    if((flag & ALLOW_TM) == 0) {
                                        continue;
                                    }
                                    
                                    info[cnt] |= ALLOW_TM;
                                }
                            }
                            
                            if(sobj_at(CLOVE_OF_GARLIC, nx, ny) != 0) {
                                if((flag & NOGARLIC) != 0) {
                                    continue;
                                }
                                
                                info[cnt] |= NOGARLIC;
                            }
                            
                            if((sobj_at(SCR_SCARE_MONSTER, nx, ny) != 0)
                               || ((mon->mpeaceful == 0)
                                   && (sengr_at("Elbereth", nx, ny) != 0))) {
                                if((flag & ALLOW_SSM) == 0) {
                                    continue;
                                }
                                
                                info[cnt] |= ALLOW_SSM;
                            }
                            
                            if(sobj_at(ENORMOUS_ROCK, nx, ny) != 0) {
                                if((flag & ALLOW_ROCK) == 0) {
                                    continue;
                                }
                                
                                info[cnt] |= ALLOW_ROCK;
                            }
                            
                            if((Invis == 0) && (online(nx, ny) != 0)) {
                                if((flag & NOTONL) != 0) {
                                    continue;
                                }
                                
                                info[cnt] |= NOTONL;
                            }
                            
                            /* We cannot avoid traps of an unknown kind */
                            struct gen *gtmp = g_at(nx, ny, ftrap);
                            int tt;
                            
                            if(gtmp != NULL) {
                                tt = 1 << (gtmp->gflag & ~SEEN);
                                
                                if((mon->mtrapseen & tt) != 0) {
                                    if((flag & tt) == 0) {
                                        continue;
                                    }
                                    
                                    info[cnt] |= tt;
                                }
                            }

                            poss[cnt].x = nx;
                            poss[cnt].y = ny;
                            ++cnt;
                        }
                    }
                }
            }
        }
    }

    return cnt;
}
예제 #16
0
파일: dbridge.c 프로젝트: FredrIQ/fiqhack
/*
 * Let's destroy the drawbridge located at x,y
 */
void
destroy_drawbridge(int x, int y)
{
    struct rm *loc1, *loc2;
    struct trap *t;
    int x2, y2;
    boolean e_inview;
    struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);

    loc1 = &level->locations[x][y];
    if (!IS_DRAWBRIDGE(loc1->typ))
        return;
    x2 = x;
    y2 = y;
    get_wall_for_db(&x2, &y2);
    loc2 = &level->locations[x2][y2];
    if ((loc1->drawbridgemask & DB_UNDER) == DB_MOAT ||
        (loc1->drawbridgemask & DB_UNDER) == DB_LAVA) {
        struct obj *otmp;
        boolean lava = (loc1->drawbridgemask & DB_UNDER) == DB_LAVA;

        if (loc1->typ == DRAWBRIDGE_UP) {
            if (cansee(x2, y2))
                pline(msgc_consequence,
                      "The portcullis of the drawbridge falls into the %s!",
                      lava ? "lava" : waterbody_name(x2, y2));
            else
                You_hear(msgc_levelsound, "a loud *SPLASH*!");
        } else {
            if (cansee(x, y))
                pline(msgc_consequence,
                      "The drawbridge collapses into the %s!",
                      lava ? "lava" : waterbody_name(x, y));
            else
                You_hear(msgc_levelsound, "a loud *SPLASH*!");
        }
        loc1->typ = lava ? LAVAPOOL : MOAT;
        loc1->drawbridgemask = 0;
        if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) {
            obj_extract_self(otmp);
            flooreffects(otmp, x, y, "fall");
        }
    } else {
        if (cansee(x, y))
            pline(msgc_consequence, "The drawbridge disintegrates!");
        else
            You_hear(msgc_levelsound, "a loud *CRASH*!");
        loc1->typ = ((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM);
        loc1->icedpool = ((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
    }
    wake_nearto(x, y, 500);
    loc2->typ = DOOR;
    loc2->doormask = D_NODOOR;
    if ((t = t_at(level, x, y)) != 0)
        deltrap(level, t);
    if ((t = t_at(level, x2, y2)) != 0)
        deltrap(level, t);
    newsym(x, y);
    newsym(x2, y2);
    if (!does_block(level, x2, y2))
        unblock_point(x2, y2);  /* vision */
    if (Is_stronghold(&u.uz))
        u.uevent.uopened_dbridge = TRUE;

    set_entity(x2, y2, etmp2);  /* currently only automissers can be here */
    if (etmp2->edata) {
        enum msg_channel hit_msgc;
        if (is_u(etmp2))
            hit_msgc = msgc_fatal_predone;
        else if (etmp2->emon->mtame && canspotmon(etmp2->emon))
            hit_msgc = msgc_petfatal;
        else
            hit_msgc = msgc_monneutral;
        
        e_inview = e_canseemon(etmp2);
        if (!automiss(etmp2)) {
            if (e_inview)
                pline(hit_msgc, "%s blown apart by flying debris.",
                      E_phrase(etmp2, "are"));
            e_died(etmp2, e_inview ? 3 : 2, CRUSHING,
                   killer_msg(CRUSHING, "an exploding drawbridge"));
        }       /* nothing which is vulnerable can survive this */
    }
    set_entity(x, y, etmp1);
    if (etmp1->edata) {
        enum msg_channel hit_msgc;
        if (is_u(etmp1))
            hit_msgc = msgc_fatal_predone;
        else if (etmp1->emon->mtame && canspotmon(etmp1->emon))
            hit_msgc = msgc_petfatal;
        else
            hit_msgc = msgc_monneutral;
        
        e_inview = e_canseemon(etmp1);
        if (!e_missed(etmp1, TRUE)) {
            if (e_inview) {
                if (!is_u(etmp1) && Hallucination)
                    pline(hit_msgc, "%s into some heavy metal!",
                          E_phrase(etmp1, "get"));
                else
                    pline(hit_msgc, "%s hit by a huge chunk of metal!",
                          E_phrase(etmp1, "are"));
            } else {
                if (!is_u(etmp1) && !is_pool(level, x, y))
                    You_hear(msgc_levelsound, "a crushing sound.");
            }
            e_died(etmp1, e_inview ? 3 : 2, CRUSHING,
                   killer_msg(CRUSHING, "a collapsing drawbridge"));
            /* if (loc1->typ == MOAT) do_entity(etmp1); */
        }
        if (is_u(etmp1))
            spoteffects(FALSE);
        else if (!DEADMONSTER(etmp1->emon))
            minliquid(etmp1->emon);
    }
}
예제 #17
0
파일: dbridge.c 프로젝트: FredrIQ/nhfourk
/*
 * Let's destroy the drawbridge located at x,y
 */
void
destroy_drawbridge(int x, int y)
{
    struct rm *loc1, *loc2;
    struct trap *t;
    struct obj *chain;
    int x2, y2, i;
    boolean e_inview;
    struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);

    loc1 = &level->locations[x][y];
    if (!IS_DRAWBRIDGE(loc1->typ))
        return;
    x2 = x;
    y2 = y;
    get_wall_for_db(&x2, &y2);
    loc2 = &level->locations[x2][y2];
    if ((loc1->drawbridgemask & DB_UNDER) == DB_MOAT ||
        (loc1->drawbridgemask & DB_UNDER) == DB_LAVA) {
        struct obj *otmp;
        boolean lava = (loc1->drawbridgemask & DB_UNDER) == DB_LAVA;

        if (loc1->typ == DRAWBRIDGE_UP) {
            if (cansee(x2, y2))
                pline("The portcullis of the drawbridge falls into the %s!",
                      lava ? "lava" : waterbody_name(x2, y2));
            else
                You_hear("a loud *SPLASH*!");
        } else {
            if (cansee(x, y))
                pline("The drawbridge collapses into the %s!",
                      lava ? "lava" : waterbody_name(x, y));
            else
                You_hear("a loud *SPLASH*!");
        }
        loc1->typ = lava ? LAVAPOOL : MOAT;
        loc1->drawbridgemask = 0;
        if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) {
            obj_extract_self(otmp);
            flooreffects(otmp, x, y, "fall");
        }
    } else {
        if (cansee(x, y))
            pline("The drawbridge disintegrates!");
        else
            You_hear("a loud *CRASH*!");
        loc1->typ = ((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM);
        loc1->icedpool = ((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
    }
    wake_nearto(x, y, 500);
    loc2->typ = DOOR;
    loc2->doormask = D_NODOOR;
    if ((t = t_at(level, x, y)) != 0)
        deltrap(level, t);
    if ((t = t_at(level, x2, y2)) != 0)
        deltrap(level, t);
    del_engr_at(level, x, y);
    del_engr_at(level, x2, y2);
    for (i = rn2(6); i > 0; --i) {  /* scatter some debris */
        /* doesn't matter if we happen to pick <x,y2> or <x2,y>;
           since drawbridges are never placed diagonally, those
           pairings will always match one of <x,y> or <x2,y2> */
        chain = mksobj_at(IRON_CHAIN, level,
                          rn2(2) ? x : x2, rn2(2) ? y : y2,
                          TRUE, FALSE, rng_main);
        /* a force of 5 here would yield a radius of 2 for
           iron chain; anything less produces a radius of 1 */
        (void) scatter(chain->ox, chain->oy, 1, MAY_HIT, chain);
    }
    newsym(x, y);
    newsym(x2, y2);
    if (!does_block(level, x2, y2))
        unblock_point(x2, y2);  /* vision */
    if (Is_stronghold(&u.uz))
        u.uevent.uopened_dbridge = TRUE;

    set_entity(x2, y2, etmp2);  /* currently only automissers can be here */
    if (etmp2->edata) {
        e_inview = e_canseemon(etmp2);
        if (!automiss(etmp2)) {
            if (e_inview)
                pline("%s blown apart by flying debris.",
                      E_phrase(etmp2, "are"));
            e_died(etmp2, e_inview ? 3 : 2, CRUSHING,
                   killer_msg(CRUSHING, "an exploding drawbridge"));
        }       /* nothing which is vulnerable can survive this */
    }
    set_entity(x, y, etmp1);
    if (etmp1->edata) {
        e_inview = e_canseemon(etmp1);
        if (!e_missed(etmp1, TRUE)) {
            if (e_inview) {
                if (!is_u(etmp1) && Hallucination)
                    pline("%s into some heavy metal!", E_phrase(etmp1, "get"));
                else
                    pline("%s hit by a huge chunk of metal!",
                          E_phrase(etmp1, "are"));
            } else {
                if (!is_u(etmp1) && !is_pool(level, x, y))
                    You_hear("a crushing sound.");
            }
            e_died(etmp1, e_inview ? 3 : 2, CRUSHING,
                   killer_msg(CRUSHING, "a collapsing drawbridge"));
            /* if (loc1->typ == MOAT) do_entity(etmp1); */
        }
        if (is_u(etmp1))
            spoteffects(FALSE);
        else if (!DEADMONSTER(etmp1->emon))
            minliquid(etmp1->emon);
    }
}
예제 #18
0
/* quick: use cursor && don't search for "more info" */
static int do_look (bool quick) {
    char    out_str[BUFSZ], look_buf[BUFSZ];
    const char *x_str, *firstmatch = 0;
    struct permonst *pm = 0;
    int     i, ans = 0;
    int     sym;                /* typed symbol or converted glyph */
    int     found;              /* count of matching syms found */
    coord   cc;                 /* screen pos of unknown glyph */
    bool save_verbose;       /* saved value of flags.verbose */
    bool from_screen;        /* question from the screen */
    bool need_to_look;       /* need to get explan. from glyph */
    bool hit_trap;           /* true if found trap explanation */
    int skipped_venom;          /* non-zero if we ignored "splash of venom" */
    static const char *mon_interior = "the interior of a monster";

    if (quick) {
        from_screen = true;     /* yes, we want to use the cursor */
    } else {
        i = ynq("Specify unknown object by cursor?");
        if (i == 'q') return 0;
        from_screen = (i == 'y');
    }

    if (from_screen) {
        cc.x = u.ux;
        cc.y = u.uy;
        sym = 0;                /* gcc -Wall lint */
    } else {
        getlin("Specify what? (type the word)", out_str);
        if (out_str[0] == '\0' || out_str[0] == '\033')
            return 0;

        if (out_str[1]) {       /* user typed in a complete string */
            checkfile(out_str, pm, true, true);
            return 0;
        }
        sym = out_str[0];
    }

    /* Save the verbose flag, we change it later. */
    save_verbose = flags.verbose;
    flags.verbose = flags.verbose && !quick;
    /*
     * The user typed one letter, or we're identifying from the screen.
     */
    do {
        /* Reset some variables. */
        need_to_look = false;
        pm = (struct permonst *)0;
        skipped_venom = 0;
        found = 0;
        out_str[0] = '\0';

        if (from_screen) {
            int glyph;  /* glyph at selected position */

            if (flags.verbose)
                pline("Please move the cursor to %s.",
                       what_is_an_unknown_object);
            else
                pline("Pick an object.");

            ans = getpos(&cc, quick, what_is_an_unknown_object);
            if (ans < 0 || cc.x < 0) {
                flags.verbose = save_verbose;
                return 0;       /* done */
            }
            flags.verbose = false;      /* only print long question once */

            /* Convert the glyph at the selected position to a symbol. */
            glyph = glyph_at(cc.x,cc.y);
            if (glyph_is_cmap(glyph)) {
                sym = showsyms[glyph_to_cmap(glyph)];
            } else if (glyph_is_trap(glyph)) {
                sym = showsyms[trap_to_defsym(glyph_to_trap(glyph))];
            } else if (glyph_is_object(glyph)) {
                sym = oc_syms[(int)objects[glyph_to_obj(glyph)].oc_class];
                if (sym == '`' && iflags.bouldersym && (int)glyph_to_obj(glyph) == BOULDER)
                        sym = iflags.bouldersym;
            } else if (glyph_is_monster(glyph)) {
                /* takes care of pets, detected, ridden, and regular mons */
                sym = monsyms[(int)mons[glyph_to_mon(glyph)].mlet];
            } else if (glyph_is_swallow(glyph)) {
                sym = showsyms[glyph_to_swallow(glyph)+S_sw_tl];
            } else if (glyph_is_invisible(glyph)) {
                sym = DEF_INVISIBLE;
            } else if (glyph_is_warning(glyph)) {
                sym = glyph_to_warning(glyph);
                sym = warnsyms[sym];
            } else {
                impossible("do_look:  bad glyph %d at (%d,%d)",
                                                glyph, (int)cc.x, (int)cc.y);
                sym = ' ';
            }
        }

        /*
         * Check all the possibilities, saving all explanations in a buffer.
         * When all have been checked then the string is printed.
         */

        /* Check for monsters */
        for (i = 0; i < MAXMCLASSES; i++) {
            if (sym == (from_screen ? monsyms[i] : def_monsyms[i]) &&
                monexplain[i]) {
                need_to_look = true;
                if (!found) {
                    sprintf(out_str, "%c       %s", sym, an(monexplain[i]));
                    firstmatch = monexplain[i];
                    found++;
                } else {
                    found += append_str(out_str, an(monexplain[i]));
                }
            }
        }
        /* handle '@' as a special case if it refers to you and you're
           playing a character which isn't normally displayed by that
           symbol; firstmatch is assumed to already be set for '@' */
        if ((from_screen ?
                (sym == monsyms[S_HUMAN] && cc.x == u.ux && cc.y == u.uy) :
                (sym == def_monsyms[S_HUMAN] && !iflags.showrace)) &&
            !(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
            found += append_str(out_str, "you");        /* tack on "or you" */

        /*
         * Special case: if identifying from the screen, and we're swallowed,
         * and looking at something other than our own symbol, then just say
         * "the interior of a monster".
         */
        if (u.uswallow && from_screen && is_swallow_sym(sym)) {
            if (!found) {
                sprintf(out_str, "%c       %s", sym, mon_interior);
                firstmatch = mon_interior;
            } else {
                found += append_str(out_str, mon_interior);
            }
            need_to_look = true;
        }

        /* Now check for objects */
        for (i = 1; i < MAXOCLASSES; i++) {
            if (sym == (from_screen ? oc_syms[i] : def_oc_syms[i])) {
                need_to_look = true;
                if (from_screen && i == VENOM_CLASS) {
                    skipped_venom++;
                    continue;
                }
                if (!found) {
                    sprintf(out_str, "%c       %s", sym, an(objexplain[i]));
                    firstmatch = objexplain[i];
                    found++;
                } else {
                    found += append_str(out_str, an(objexplain[i]));
                }
            }
        }

        if (sym == DEF_INVISIBLE) {
            if (!found) {
                sprintf(out_str, "%c       %s", sym, an(invisexplain));
                firstmatch = invisexplain;
                found++;
            } else {
                found += append_str(out_str, an(invisexplain));
            }
        }

#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)

        /* Now check for graphics symbols */
        for (hit_trap = false, i = 0; i < MAXPCHARS; i++) {
            x_str = defsyms[i].explanation;
            if (sym == (from_screen ? showsyms[i] : defsyms[i].sym) && *x_str) {
                /* avoid "an air", "a water", or "a floor of a room" */
                int article = (i == S_room) ? 2 :               /* 2=>"the" */
                              !(strcmp(x_str, "air") == 0 ||    /* 1=>"an"  */
                                strcmp(x_str, "water") == 0);   /* 0=>(none)*/

                if (!found) {
                    if (is_cmap_trap(i)) {
                        sprintf(out_str, "%c       a trap", sym);
                        hit_trap = true;
                    } else {
                        sprintf(out_str, "%c       %s", sym,
                                article == 2 ? the(x_str) :
                                article == 1 ? an(x_str) : x_str);
                    }
                    firstmatch = x_str;
                    found++;
                } else if (!u.uswallow && !(hit_trap && is_cmap_trap(i)) &&
                           !(found >= 3 && is_cmap_drawbridge(i))) {
                    found += append_str(out_str,
                                        article == 2 ? the(x_str) :
                                        article == 1 ? an(x_str) : x_str);
                    if (is_cmap_trap(i)) hit_trap = true;
                }

                if (i == S_altar || is_cmap_trap(i))
                    need_to_look = true;
            }
        }

        /* Now check for warning symbols */
        for (i = 1; i < WARNCOUNT; i++) {
            x_str = def_warnsyms[i].explanation;
            if (sym == (from_screen ? warnsyms[i] : def_warnsyms[i].sym)) {
                if (!found) {
                        sprintf(out_str, "%c       %s",
                                sym, def_warnsyms[i].explanation);
                        firstmatch = def_warnsyms[i].explanation;
                        found++;
                } else {
                        found += append_str(out_str, def_warnsyms[i].explanation);
                }
                /* Kludge: warning trumps boulders on the display.
                   Reveal the boulder too or player can get confused */
                if (from_screen && sobj_at(BOULDER, cc.x, cc.y))
                        strcat(out_str, " co-located with a boulder");
                break;  /* out of for loop*/
            }
        }

        /* if we ignored venom and list turned out to be short, put it back */
        if (skipped_venom && found < 2) {
            x_str = objexplain[VENOM_CLASS];
            if (!found) {
                sprintf(out_str, "%c       %s", sym, an(x_str));
                firstmatch = x_str;
                found++;
            } else {
                found += append_str(out_str, an(x_str));
            }
        }

        /* handle optional boulder symbol as a special case */
        if (iflags.bouldersym && sym == iflags.bouldersym) {
            if (!found) {
                firstmatch = "boulder";
                sprintf(out_str, "%c       %s", sym, an(firstmatch));
                found++;
            } else {
                found += append_str(out_str, "boulder");
            }
        }

        /*
         * If we are looking at the screen, follow multiple possibilities or
         * an ambiguous explanation by something more detailed.
         */
        if (from_screen) {
            if (found > 1 || need_to_look) {
                char monbuf[BUFSZ];
                char temp_buf[BUFSZ];

                pm = lookat(cc.x, cc.y, look_buf, monbuf);
                firstmatch = look_buf;
                if (*firstmatch) {
                    sprintf(temp_buf, " (%s)", firstmatch);
                    (void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
                    found = 1;  /* we have something to look up */
                }
                if (monbuf[0]) {
                    sprintf(temp_buf, " [seen: %s]", monbuf);
                    (void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
                }
            }
        }

        /* Finally, print out our explanation. */
        if (found) {
            pline("%s", out_str);
            /* check the data file for information about this thing */
            if (found == 1 && ans != LOOK_QUICK && ans != LOOK_ONCE &&
                        (ans == LOOK_VERBOSE || (flags.help && !quick))) {
                char temp_buf[BUFSZ];
                strcpy(temp_buf, firstmatch);
                checkfile(temp_buf, pm, false, (bool)(ans == LOOK_VERBOSE));
            }
        } else {
            pline("I've never heard of such things.");
        }

    } while (from_screen && !quick && ans != LOOK_ONCE);

    flags.verbose = save_verbose;
    return 0;
}
예제 #19
0
파일: explode.c 프로젝트: FredrIQ/nhfourk
/* returns number of scattered objects */
long
scatter(int sx, int sy, /* location of objects to scatter */
        int blastforce, /* force behind the scattering */
        unsigned int scflags, struct obj *obj)
{   /* only scatter this obj */
    struct obj *otmp;
    struct level *lev = obj ? obj->olev : level;
    int tmp;
    int farthest = 0;
    uchar typ;
    long qtmp;
    boolean used_up;
    boolean individual_object = obj ? TRUE : FALSE;
    struct monst *mtmp;
    struct scatter_chain *stmp, *stmp2 = 0;
    struct scatter_chain *schain = NULL;
    long total = 0L;
    boolean visible = (lev == level && cansee(sx, sy));

    while ((otmp = individual_object ? obj : lev->objects[sx][sy]) != 0) {
        if (otmp->quan > 1L) {
            qtmp = otmp->quan - 1;
            if (qtmp > LARGEST_INT)
                qtmp = LARGEST_INT;
            qtmp = (long)rnd((int)qtmp);
            otmp = splitobj(otmp, qtmp);
        } else {
            obj = NULL; /* all used */
        }
        obj_extract_self(otmp);
        used_up = FALSE;

        /* 9 in 10 chance of fracturing boulders or statues */
        if ((scflags & MAY_FRACTURE)
                && ((otmp->otyp == BOULDER) || (otmp->otyp == STATUE))
                && rn2(10)) {
            if (otmp->otyp == BOULDER) {
                if (visible)
                    pline("%s apart.", Tobjnam(otmp, "break"));
                fracture_rock(otmp);
                place_object(otmp, lev, sx, sy);
                if ((otmp = sobj_at(BOULDER, lev, sx, sy)) != 0) {
                    /* another boulder here, restack it to the top */
                    obj_extract_self(otmp);
                    place_object(otmp, lev, sx, sy);
                }
            } else {
                struct trap *trap;

                if ((trap = t_at(lev, sx, sy)) && trap->ttyp == STATUE_TRAP)
                    deltrap(lev, trap);
                if (visible)
                    pline("%s.", Tobjnam(otmp, "crumble"));
                break_statue(otmp);
                place_object(otmp, lev, sx, sy); /* put fragments on floor */
            }
            used_up = TRUE;

            /* 1 in 10 chance of destruction of obj; glass, egg destruction */
        } else if ((scflags & MAY_DESTROY) &&
                   (!rn2(10) || (objects[otmp->otyp].oc_material == GLASS ||
                                 otmp->otyp == EGG))) {
            if (breaks(otmp, (xchar) sx, (xchar) sy))
                used_up = TRUE;
        }

        if (!used_up) {
            stmp = malloc(sizeof (struct scatter_chain));
            stmp->next = NULL;
            stmp->obj = otmp;
            stmp->ox = sx;
            stmp->oy = sy;
            tmp = rn2(8);       /* get the direction */
            stmp->dx = xdir[tmp];
            stmp->dy = ydir[tmp];
            tmp = blastforce - (otmp->owt / 40);
            if (tmp < 1)
                tmp = 1;
            stmp->range = rnd(tmp);     /* anywhere up to that determ. by wt */
            if (farthest < stmp->range)
                farthest = stmp->range;
            stmp->stopped = FALSE;
            if (!schain)
                schain = stmp;
            else
                stmp2->next = stmp;
            stmp2 = stmp;
        }
    }

    while (farthest-- > 0) {
        for (stmp = schain; stmp; stmp = stmp->next) {
            if ((stmp->range-- > 0) && (!stmp->stopped)) {
                bhitpos.x = stmp->ox + stmp->dx;
                bhitpos.y = stmp->oy + stmp->dy;
                typ = lev->locations[bhitpos.x][bhitpos.y].typ;
                if (!isok(bhitpos.x, bhitpos.y)) {
                    bhitpos.x -= stmp->dx;
                    bhitpos.y -= stmp->dy;
                    stmp->stopped = TRUE;
                } else if (!ZAP_POS(typ) ||
                           closed_door(lev, bhitpos.x, bhitpos.y)) {
                    bhitpos.x -= stmp->dx;
                    bhitpos.y -= stmp->dy;
                    stmp->stopped = TRUE;
                } else if ((mtmp = m_at(lev, bhitpos.x, bhitpos.y)) != 0) {
                    if (scflags & MAY_HITMON) {
                        stmp->range--;
                        if (ohitmon(mtmp, stmp->obj, 1, FALSE)) {
                            stmp->obj = NULL;
                            stmp->stopped = TRUE;
                        }
                    }
                } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
                    if (scflags & MAY_HITYOU) {
                        int hitvalu, hitu;

                        action_interrupted();

                        hitvalu = 8 + stmp->obj->spe;
                        if (bigmonst(youmonst.data))
                            hitvalu++;
                        hitu =
                            thitu(hitvalu, dmgval(stmp->obj, &youmonst),
                                  stmp->obj, NULL);
                        if (hitu)
                            stmp->range -= 3;
                    }
                } else {
                    if (scflags & VIS_EFFECTS) {
                        /* tmpsym_at(bhitpos.x, bhitpos.y); */
                        /* delay_output(); */
                    }
                }
                stmp->ox = bhitpos.x;
                stmp->oy = bhitpos.y;
            }
        }
    }
    for (stmp = schain; stmp; stmp = stmp2) {
        int x, y;

        stmp2 = stmp->next;
        x = stmp->ox;
        y = stmp->oy;
        if (stmp->obj) {
            if (x != sx || y != sy)
                total += stmp->obj->quan;
            place_object(stmp->obj, lev, x, y);
            stackobj(stmp->obj);
        }
        free(stmp);
        if (lev == level)
            newsym(x, y);
    }

    return total;
}
예제 #20
0
파일: music.c 프로젝트: FredrIQ/fiqhack
/* Generate earthquake :-) of desired force. That is: create random chasms
   (pits). Currently assumes that the player created it (you'll need to change
   at least messages, angering, and kill credit if you generalize it). */
static void
do_earthquake(int force)
{
    int x, y;
    struct monst *mtmp;
    struct obj *otmp;
    struct trap *chasm, *oldtrap;
    int start_x, start_y, end_x, end_y;

    start_x = youmonst.mx - (force * 2);
    start_y = youmonst.my - (force * 2);
    end_x = youmonst.mx + (force * 2);
    end_y = youmonst.my + (force * 2);
    if (start_x < 0)
        start_x = 0;
    if (start_y < 0)
        start_y = 0;
    if (end_x >= COLNO)
        end_x = COLNO - 1;
    if (end_y >= ROWNO)
        end_y = ROWNO - 1;
    for (x = start_x; x <= end_x; x++)
        for (y = start_y; y <= end_y; y++) {
            if ((mtmp = m_at(level, x, y)) != 0) {
                wakeup(mtmp, FALSE);  /* peaceful monster will become hostile */
                if (mtmp->mundetected && is_hider(mtmp->data)) {
                    mtmp->mundetected = 0;
                    if (cansee(x, y))
                        pline(msgc_youdiscover, "%s is shaken loose from %s!",
                              Amonnam(mtmp), mtmp->data == &mons[PM_TRAPPER] ?
                              "its hiding place" : the(ceiling(youmonst.mx, youmonst.my)));
                    else
                        You_hear(msgc_levelsound, "a thumping sound.");
                    if (x == youmonst.mx && y == youmonst.my &&
                        mtmp->data != &mons[PM_TRAPPER])
                        pline(msgc_moncombatgood,
                              "You easily dodge the falling %s.",
                              mon_nam(mtmp));
                    newsym(x, y);
                }
            }
            if (!rn2(14 - force))
                switch (level->locations[x][y].typ) {
                case FOUNTAIN: /* Make the fountain disappear */
                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The fountain falls into a chasm.");
                    goto do_pit;
                case SINK:
                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The kitchen sink falls into a chasm.");
                    goto do_pit;
                case ALTAR:
                    if (level->locations[x][y].altarmask & AM_SANCTUM)
                        break;

                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The altar falls into a chasm.");
                    goto do_pit;
                case GRAVE:
                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The headstone topples into a chasm.");
                    goto do_pit;
                case THRONE:
                    if (cansee(x, y))
                        pline(msgc_consequence,
                              "The throne falls into a chasm.");
                    /* Falls into next case */
                case ROOM:
                case CORR:     /* Try to make a pit */
                    /* Pits, spiked pits, holes, trapdoors, vibrating squares,
                       magic portals are immune.  A bear trap will leave the
                       trap in the pit.  It would be kind of cool to make
                       landmines detonate, but that's more trouble than it's
                       worth. */
                    if ((oldtrap = t_at(level, x, y))) {
                        if (oldtrap->ttyp == PIT || oldtrap->ttyp == SPIKED_PIT
                            || oldtrap->ttyp == HOLE ||
                            oldtrap->ttyp == TRAPDOOR ||
                            oldtrap->ttyp == VIBRATING_SQUARE ||
                            oldtrap->ttyp == MAGIC_PORTAL)
                            break;

                        if (oldtrap->ttyp == BEAR_TRAP) {
                            if (mtmp)
                                mtmp->mtrapped = 0;
                            cnv_trap_obj(level, BEARTRAP, 1, oldtrap);
                        }
                    }

                do_pit:
                    chasm = maketrap(level, x, y, PIT, rng_main);
                    if (!chasm)
                        break;  /* no pit if portal at that location */
                    chasm->tseen = 1;

                    level->locations[x][y].doormask = 0;

                    mtmp = m_at(level, x, y);

                    if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) {
                        if (cansee(x, y))
                            pline(msgc_consequence,
                                  "KADOOM! The boulder falls into a chasm%s!",
                                  ((x == youmonst.mx) &&
                                   (y == youmonst.my)) ? " below you" : "");
                        if (mtmp)
                            mtmp->mtrapped = 0;
                        obj_extract_self(otmp);
                        flooreffects(otmp, x, y, "");
                        break;
                    }

                    /* We have to check whether monsters or player falls in a
                       chasm... */

                    if (mtmp) {
                        if (!flying(mtmp) && !levitates(mtmp) &&
                            !is_clinger(mtmp->data)) {
                            mtmp->mtrapped = 1;
                            if (cansee(x, y))
                                pline(combat_msgc(&youmonst, mtmp, cr_hit),
                                      "%s falls into a chasm!", Monnam(mtmp));
                            else if (humanoid(mtmp->data))
                                You_hear(msgc_levelsound, "a scream!");
                            mselftouch(mtmp, "Falling, ", &youmonst);
                            if (!DEADMONSTER(mtmp))
                                if ((mtmp->mhp -= rnd(6)) <= 0) {
                                    if (!cansee(x, y))
                                        pline(msgc_kill, "It is destroyed!");
                                    else {
                                        pline(msgc_petfatal, "You destroy %s!",
                                              mtmp->mtame ?
                                              x_monnam(mtmp, ARTICLE_THE,
                                                       "poor", mx_name(mtmp) ?
                                                       SUPPRESS_SADDLE : 0,
                                                       FALSE) : mon_nam(mtmp));
                                    }
                                    xkilled(mtmp, 0);
                                }
                        }
                    } else if (!u.utrap && x == youmonst.mx && y == youmonst.my) {
                        if (Levitation || Flying || is_clinger(youmonst.data)) {
                            pline(msgc_noconsequence,
                                  "A chasm opens up under you!");
                            pline(msgc_noconsequence, "You don't fall in!");
                        } else {
                            pline(msgc_badidea, "You fall into a chasm!");
                            u.utrap = rn1(6, 2);
                            u.utraptype = TT_PIT;
                            turnstate.vision_full_recalc = TRUE;
                            losehp(rnd(6), "fell into a chasm");
                            selftouch("Falling, you",
                                      "falling into a chasm while wielding");
                        }
                    } else
                        newsym(x, y);
                    break;
                case DOOR:     /* Make the door collapse */
                    if (level->locations[x][y].doormask == D_NODOOR)
                        goto do_pit;
                    if (cansee(x, y))
                        pline(msgc_consequence, "The door collapses.");
                    if (*in_rooms(level, x, y, SHOPBASE))
                        add_damage(x, y, 0L);
                    level->locations[x][y].doormask = D_NODOOR;
                    unblock_point(x, y);
                    newsym(x, y);
                    break;
                }
        }
}