Ejemplo n.º 1
0
/*
 * Does falling drawbridge or portcullis miss etmp?
 */
static boolean e_missed(struct entity *etmp, boolean chunks)
{
	int misses;

	if (automiss(etmp))
		return TRUE;

	if (is_flyer(etmp->edata) &&
	    (is_u(etmp)? !Sleeping :
	     (etmp->emon->mcanmove && !etmp->emon->msleeping)))
						 /* flying requires mobility */
		misses = 5;	/* out of 8 */
	else if (is_floater(etmp->edata) ||
		    (is_u(etmp) && Levitation))	 /* doesn't require mobility */
		misses = 3;
	else if (chunks && is_pool(level, etmp->ex, etmp->ey))
		misses = 2;				    /* sitting ducks */
	else
		misses = 0;

	if (is_db_wall(etmp->ex, etmp->ey))
		misses -= 3;				    /* less airspace */


	return (boolean)((misses >= rnd(8))? TRUE : FALSE);
}
Ejemplo n.º 2
0
/*
 * Does falling drawbridge or portcullis miss etmp?
 */
static boolean
e_missed(struct entity *etmp, boolean chunks)
{
    int misses;

    if (automiss(etmp))
        return TRUE;

    if (flying(etmp->emon) &&
        (is_u(etmp) ? !u_helpless(hm_all)
         : (etmp->emon->mcanmove && !etmp->emon->msleeping)))
        /* flying requires mobility */
        misses = 5;     /* out of 8 */
    else if (levitates(etmp->emon) || (is_u(etmp) && Levitation))
        /* doesn't require mobility */
        misses = 3;
    else if (chunks && is_pool(level, etmp->ex, etmp->ey))
        misses = 2;     /* sitting ducks */
    else
        misses = 0;

    if (is_db_wall(etmp->ex, etmp->ey))
        misses -= 3;    /* less airspace */

    enum rng rng = is_u(etmp) ? rng_survive_dbridge : rng_main;

    return (boolean) ((misses > rn2_on_rng(8, rng)) ? TRUE : FALSE);
}
Ejemplo n.º 3
0
/*
 * Simple-minded "can it be here?" routine
 */
static boolean
e_survives_at(struct entity *etmp, int x, int y)
{
    if (noncorporeal(etmp->edata))
        return TRUE;
    if (is_pool(level, x, y))
        return (boolean) (waterwalks(etmp->emon) || unbreathing(etmp->emon) ||
                          swims(etmp->emon) || flying(etmp->emon) ||
                          levitates(etmp->emon));
    /* must force call to lava_effects in e_died if is_u */
    if (is_lava(level, x, y))
        return (boolean) (likes_lava(etmp->edata) || flying(etmp->emon) ||
                          levitates(etmp->emon));
    if (is_db_wall(x, y))
        return !!phasing(etmp->emon);
    return TRUE;
}
Ejemplo n.º 4
0
/*
 * Simple-minded "can it be here?" routine
 */
static boolean e_survives_at(struct entity *etmp, int x, int y)
{
	if (noncorporeal(etmp->edata))
		return TRUE;
	if (is_pool(level, x, y))
		return (boolean)((is_u(etmp) &&
				(Wwalking || Amphibious || Swimming ||
				Flying || Levitation)) ||
			is_swimmer(etmp->edata) || is_flyer(etmp->edata) ||
			is_floater(etmp->edata));
	/* must force call to lava_effects in e_died if is_u */
	if (is_lava(level, x, y))
		return (boolean)((is_u(etmp) && (Levitation || Flying)) ||
			    likes_lava(etmp->edata) || is_flyer(etmp->edata));
	if (is_db_wall(x, y))
		return((boolean)(is_u(etmp) ? Passes_walls :
			passes_walls(etmp->edata)));
	return TRUE;
}
Ejemplo n.º 5
0
/*
 * Can etmp jump from death?
 */
static boolean e_jumps(struct entity *etmp)
{
	int tmp = 4;		/* out of 10 */

	if (is_u(etmp)? (Sleeping || Fumbling) :
		        (!etmp->emon->mcanmove || etmp->emon->msleeping ||
			 !etmp->edata->mmove   || etmp->emon->wormno))
		return FALSE;

	if (is_u(etmp)? Confusion : etmp->emon->mconf)
		tmp -= 2;

	if (is_u(etmp)? Stunned : etmp->emon->mstun)
		tmp -= 3;

	if (is_db_wall(etmp->ex, etmp->ey))
		tmp -= 2;			    /* less room to maneuver */

	return (boolean)((tmp >= rnd(10))? TRUE : FALSE);
}
Ejemplo n.º 6
0
/*
 * Can etmp jump from death?
 */
static boolean
e_jumps(struct entity *etmp)
{
    int tmp = 4;        /* out of 10 */

    if (is_u(etmp) ? (Sleeping || Fumbling)
        : (!etmp->emon->mcanmove || etmp->emon->msleeping || !etmp->edata->mmove
           || etmp->emon->wormno))
        return FALSE;

    if (is_u(etmp) ? Confusion : etmp->emon->mconf)
        tmp -= 2;

    if (is_u(etmp) ? Stunned : etmp->emon->mstun)
        tmp -= 3;

    if (is_db_wall(etmp->ex, etmp->ey))
        tmp -= 2;       /* less room to maneuver */

    enum rng rng = is_u(etmp) ? rng_survive_dbridge : rng_main;

    return (boolean) ((tmp > rn2_on_rng(10, rng)) ? TRUE : FALSE);
}
Ejemplo n.º 7
0
static void do_entity(struct entity *etmp)
{
	int newx, newy, at_portcullis, oldx, oldy;
	boolean must_jump = FALSE, relocates = FALSE, e_inview;
	struct rm *crm;

	if (!etmp->edata)
		return;

	e_inview = e_canseemon(level, etmp);
	oldx = etmp->ex;
	oldy = etmp->ey;
	at_portcullis = is_db_wall(oldx, oldy);
	crm = &level->locations[oldx][oldy];

	if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
		if (e_inview && (at_portcullis || IS_DRAWBRIDGE(crm->typ)))
			pline("The %s passes through %s!",
			      at_portcullis ? "portcullis" : "drawbridge",
			      e_nam(etmp));
		if (is_u(etmp)) spoteffects(FALSE);
		return;
	}
	if (e_missed(etmp, FALSE)) {
		if (at_portcullis)
			pline("The portcullis misses %s!",
			      e_nam(etmp));
		if (e_survives_at(etmp, oldx, oldy))
			return;
		else {
			if (at_portcullis)
				must_jump = TRUE;
			else
				relocates = TRUE; /* just ride drawbridge in */
		}
	} else {
		if (crm->typ == DRAWBRIDGE_DOWN) {
			pline("%s crushed underneath the drawbridge.",
			      E_phrase(etmp, "are"));		  /* no jump */
			e_died(etmp, e_inview? 3 : 2, CRUSHING);/* no corpse */
			return;   /* Note: Beyond this point, we know we're  */
		}		  /* not at an opened drawbridge, since all  */
		must_jump = TRUE; /* *missable* creatures survive on the     */
	}			  /* square, and all the unmissed ones die.  */
	if (must_jump) {
	    if (at_portcullis) {
		if (e_jumps(etmp)) {
		    relocates = TRUE;
		} else {
		    if (e_inview)
			pline("%s crushed by the falling portcullis!",
			      E_phrase(etmp, "are"));
		    else if (flags.soundok)
			You_hear("a crushing sound.");
		    e_died(etmp, e_inview? 3 : 2, CRUSHING);
		    /* no corpse */
		    return;
		}
	    } else { /* tries to jump off bridge to original square */
		relocates = !e_jumps(etmp);
	    }
	}

/*
 * Here's where we try to do relocation.  Assumes that etmp is not arriving
 * at the portcullis square while the drawbridge is falling, since this square
 * would be inaccessible (i.e. etmp started on drawbridge square) or
 * unnecessary (i.e. etmp started here) in such a situation.
 */
	newx = oldx;
	newy = oldy;
	find_drawbridge(&newx, &newy);
	if ((newx == oldx) && (newy == oldy))
		get_wall_for_db(&newx, &newy);
	if (relocates && (e_at(newx, newy))) {

/*
 * Standoff problem:  one or both entities must die, and/or both switch
 * places.  Avoid infinite recursion by checking first whether the other
 * entity is staying put.  Clean up if we happen to move/die in recursion.
 */
		struct entity *other;

		other = e_at(newx, newy);
		if (e_survives_at(other, newx, newy) && automiss(other)) {
			relocates = FALSE;	      /* "other" won't budge */
		} else {

			while ((e_at(newx, newy) != 0) &&
			       (e_at(newx, newy) != etmp))
				do_entity(other);
			if (e_at(oldx, oldy) != etmp) {
			    return;
			}
		}
	}
	if (relocates && !e_at(newx, newy)) {/* if e_at() entity = worm tail */
		if (!is_u(etmp)) {
			remove_monster(level, etmp->ex, etmp->ey);
			place_monster(etmp->emon, newx, newy);
			update_monster_region(etmp->emon);
		} else {
			u.ux = newx;
			u.uy = newy;
		}
		etmp->ex = newx;
		etmp->ey = newy;
		e_inview = e_canseemon(level, etmp);
	}
	if (is_db_wall(etmp->ex, etmp->ey)) {
		if (e_inview) {
			if (is_u(etmp)) {
				pline("You tumble towards the closed portcullis!");
				if (automiss(etmp))
					pline("You pass through it!");
				else
					pline("The drawbridge closes in...");
			} else
				pline("%s behind the drawbridge.",
				      E_phrase(etmp, "disappear"));
		}
		if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
			killer_format = KILLED_BY_AN;
			killer = "closing drawbridge";
			e_died(etmp, 0, CRUSHING);	       /* no message */
			return;
		}
	} else {
		if (is_pool(level, etmp->ex, etmp->ey) && !e_inview)
			if (flags.soundok)
				You_hear("a splash.");
		if (e_survives_at(etmp, etmp->ex, etmp->ey)) {
			if (e_inview && !is_flyer(etmp->edata) &&
			    !is_floater(etmp->edata))
				pline("%s from the bridge.",
				      E_phrase(etmp, "fall"));
			return;
		}
		if (is_pool(level, etmp->ex, etmp->ey) || is_lava(level, etmp->ex, etmp->ey))
		    if (e_inview && !is_u(etmp)) {
			/* drown() will supply msgs if nec. */
			boolean lava = is_lava(level, etmp->ex, etmp->ey);

			if (Hallucination)
			    pline("%s the %s and disappears.",
				  E_phrase(etmp, "drink"),
				  lava ? "lava" : "moat");
			else
			    pline("%s into the %s.",
				  E_phrase(etmp, "fall"),
				  lava ? "lava" : "moat");
		    }
		killer_format = NO_KILLER_PREFIX;
		killer = "fell from a drawbridge";
		e_died(etmp, e_inview ? 3 : 2,      /* CRUSHING is arbitrary */
		       (is_pool(level, etmp->ex, etmp->ey)) ? DROWNING :
		       (is_lava(level, etmp->ex, etmp->ey)) ? BURNING :
						       CRUSHING); /*no corpse*/
		return;
	}
}
Ejemplo n.º 8
0
/* try to open a door */
int
doopen(const struct nh_cmd_arg *arg)
{
    coord cc;
    struct rm *door;
    struct monst *mtmp;
    schar dx, dy, dz;

    if (nohands(youmonst.data)) {
        pline(msgc_cancelled, "You can't open, close, or unlock anything "
              "-- you have no hands!");
        return 0;
    }

    if (u.utrap && u.utraptype == TT_PIT) {
        pline(msgc_cancelled, "You can't reach over the edge of the pit.");
        return 0;
    }

    if (!getargdir(arg, NULL, &dx, &dy, &dz))
        return 0;

    cc.x = youmonst.mx + dx;
    cc.y = youmonst.my + dy;
    if (!isok(cc.x, cc.y))
        return 0;

    if ((cc.x == youmonst.mx) && (cc.y == youmonst.my))
        return 0;

    if ((mtmp = m_at(level, cc.x, cc.y)) && mtmp->m_ap_type == M_AP_FURNITURE &&
        (mtmp->mappearance == S_hcdoor || mtmp->mappearance == S_vcdoor) &&
        !Protection_from_shape_changers) {

        stumble_onto_mimic(mtmp, cc.x - youmonst.mx, cc.y - youmonst.my);
        return 1;
    }

    door = &level->locations[cc.x][cc.y];

    if (!IS_DOOR(door->typ)) {
        if (is_db_wall(cc.x, cc.y)) {
            pline(msgc_cancelled,
                  "There is no obvious way to open the drawbridge.");
            return 0;
        }
        pline(msgc_mispaste, "You %s no door there.", Blind ? "feel" : "see");
        return 0;
    }

    if (door->doormask == D_ISOPEN) {
        struct nh_cmd_arg newarg;
        arg_from_delta(dx, dy, dz, &newarg);
        return doclose(&newarg);
    }

    if (!(door->doormask & D_CLOSED)) {
        const char *mesg;

        switch (door->doormask) {
        case D_BROKEN:
            mesg = " is broken";
            break;
        case D_NODOOR:
            mesg = "way has no door";
            break;
        case D_ISOPEN:
            mesg = " is already open";
            break;
        default:
            if (last_command_was("open") && door->mem_door_l) {

                /* With the "open" command given explicitly (rather than
                   implicitly via doorbumping), unlock the door. */
                struct obj *bestpick = get_current_unlock_tool();
                struct nh_cmd_arg newarg;

                arg_from_delta(dx, dy, dz, &newarg);
                if (!bestpick)
                    pline(msgc_cancelled,
                          "You have nothing to unlock that with.");
                else if (!bestpick->lastused)
                    /* not msgc_controlhelp, or many players would get
                       no message */
                    pline(msgc_hint,
                          "Use an unlocking tool manually so I know "
                          "which one you want to use.");
                else
                    return pick_lock(bestpick, &newarg);
            }
            door->mem_door_l = 1;
            map_background(cc.x, cc.y, TRUE);
            mesg = " is locked";
            break;
        }
        pline(msgc_cancelled, "This door%s.", mesg);
        if (Blind)
            feel_location(cc.x, cc.y);
        return 0;
    }

    if (verysmall(youmonst.data)) {
        pline(msgc_cancelled, "You're too small to pull the door open.");
        return 0;
    }

    /* door is known to be CLOSED */
    if (rnl(20) < (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3) {
        pline(msgc_actionok, "The door opens.");
        if (door->doormask & D_TRAPPED) {
            b_trapped("door", FINGER);
            door->doormask = D_NODOOR;
            if (*in_rooms(level, cc.x, cc.y, SHOPBASE))
                add_damage(cc.x, cc.y, 0L);
        } else
            door->doormask = D_ISOPEN;
        if (Blind)
            feel_location(cc.x, cc.y);  /* the hero knows she opened it */
        else
            newsym(cc.x, cc.y);
        unblock_point(cc.x, cc.y);      /* vision: new see through there */
    } else {
        exercise(A_STR, TRUE);
        door->mem_door_l = 1;
        map_background(cc.x, cc.y, TRUE);
        pline(msgc_failrandom, "The door resists!");
    }

    return 1;
}