Пример #1
0
/*
 * Open the drawbridge located at x,y
 */
void open_drawbridge(int x, int y)
{
	struct rm *loc1, *loc2;
	struct trap *t;
	int x2, y2;

	loc1 = &level->locations[x][y];
	if (loc1->typ != DRAWBRIDGE_UP) return;
	x2 = x; y2 = y;
	get_wall_for_db(&x2,&y2);
	if (cansee(x,y) || cansee(x2,y2))
		pline("You see a drawbridge %s down!",
		    (distu(x2,y2) < distu(x,y)) ? "going" : "coming");
	loc1->typ = DRAWBRIDGE_DOWN;
	loc2 = &level->locations[x2][y2];
	loc2->typ = DOOR;
	loc2->doormask = D_NODOOR;
	set_entity(x, y, &(occupants[0]));
	set_entity(x2, y2, &(occupants[1]));
	do_entity(&(occupants[0]));		/* do set_entity after first */
	set_entity(x2, y2, &(occupants[1]));	/* do_entity for worm tails */
	do_entity(&(occupants[1]));
	revive_nasty(x,y,NULL);
	delallobj(x, y);
	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);
	unblock_point(x2,y2);	/* vision */
	if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE;
}
Пример #2
0
/*
 * Close the drawbridge located at x,y.
 * Returns TRUE if the drawbridge was closed, FALSE otherwise.
 */
boolean close_drawbridge(int x, int y)
{
	struct rm *loc1, *loc2;
	struct monst *m;
	struct trap *t;
	int x2, y2;

	loc1 = &level->locations[x][y];
	if (loc1->typ != DRAWBRIDGE_DOWN) return FALSE;
	/* A huge monster will block the drawbridge. */
	if ((m = m_at(level, x, y)) && hugemonst(m->data)) {
	    pline("%s blocks the drawbridge with %s weight!",
		  canseemon(level, m) ? Amonnam(m) : "Something",
		  canseemon(level, m) ? mhis(level, m) : "its");
	    return FALSE;
	}
	if (rn2(5) == 0) {
	    pline("The mechanism seems to have something stuck in it and won't close.");
	    return FALSE;
	}
	x2 = x; y2 = y;
	get_wall_for_db(&x2,&y2);
	if (cansee(x,y) || cansee(x2,y2))
		pline("You see a drawbridge %s up!",
		    (((u.ux == x || u.uy == y) && !Underwater) ||
		     distu(x2,y2) < distu(x,y)) ? "coming" : "going");
	loc1->typ = DRAWBRIDGE_UP;
	loc2 = &level->locations[x2][y2];
	loc2->typ = DBWALL;
	switch (loc1->drawbridgemask & DB_DIR) {
		case DB_NORTH:
		case DB_SOUTH:
			loc2->horizontal = TRUE;
			break;
		case DB_WEST:
		case DB_EAST:
			loc2->horizontal = FALSE;
			break;
	}
	loc2->wall_info = W_NONDIGGABLE;
	set_entity(x, y, &(occupants[0]));
	set_entity(x2, y2, &(occupants[1]));
	do_entity(&(occupants[0]));		/* Do set_entity after first */
	set_entity(x2, y2, &(occupants[1]));	/* do_entity for worm tail */
	do_entity(&(occupants[1]));
	if (OBJ_AT(x, y) && flags.soundok)
	    You_hear("smashing and crushing.");
	revive_nasty(x,y,NULL);
	revive_nasty(x2,y2,NULL);
	delallobj(x, y);
	delallobj(x2, y2);
	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);
	block_point(x2,y2);	/* vision */
	return TRUE;
}
Пример #3
0
/*
 * Close the drawbridge located at x,y
 */
void
close_drawbridge(int x, int y)
{
    struct rm *loc1, *loc2;
    struct trap *t;
    int x2, y2;

    loc1 = &level->locations[x][y];
    if (loc1->typ != DRAWBRIDGE_DOWN)
        return;
    x2 = x;
    y2 = y;
    get_wall_for_db(&x2, &y2);
    if (cansee(x, y) || cansee(x2, y2))
        pline("You see a drawbridge %s up!",
              (((u.ux == x || u.uy == y) && !Underwater) ||
               distu(x2, y2) < distu(x, y)) ? "coming" : "going");
    else if (canhear())
        pline("You hear chains rattling and gears turning.");
    loc1->typ = DRAWBRIDGE_UP;
    loc2 = &level->locations[x2][y2];
    loc2->typ = DBWALL;
    switch (loc1->drawbridgemask & DB_DIR) {
    case DB_NORTH:
    case DB_SOUTH:
        loc2->horizontal = TRUE;
        break;
    case DB_WEST:
    case DB_EAST:
        loc2->horizontal = FALSE;
        break;
    }
    loc2->wall_info = W_NONDIGGABLE;
    set_entity(x, y, &(occupants[0]));
    set_entity(x2, y2, &(occupants[1]));
    do_entity(&(occupants[0])); /* Do set_entity after first */
    set_entity(x2, y2, &(occupants[1]));        /* do_entity for worm tail */
    do_entity(&(occupants[1]));
    if (OBJ_AT(x, y))
        You_hear("smashing and crushing.");
    revive_nasty(x, y, NULL);
    revive_nasty(x2, y2, NULL);
    delallobj(x, y);
    delallobj(x2, y2);
    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);
    newsym(x, y);
    newsym(x2, y2);
    block_point(x2, y2);        /* vision */
}
Пример #4
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);
		}
	}
}
Пример #5
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;
	}
}