Ejemplo n.º 1
0
/*
 *  Place the ball & chain under the hero.  Make sure that the ball & chain
 *  variables are set (actually only needed when blind, but what the heck).
 *  It is assumed that when this is called, the ball and chain are NOT
 *  attached to the object list.
 *
 *  Should not be called while swallowed.
 */
void
placebc()
{
    if (!uchain || !uball) {
	impossible("Where are your ball and chain?");
	return;
    }

    (void) flooreffects(uchain, u.ux, u.uy, "");	/* chain might rust */

    if (carried(uball))		/* the ball is carried */
	u.bc_order = BCPOS_DIFFER;
    else {
	/* ball might rust -- already checked when carried */
	(void) flooreffects(uball, u.ux, u.uy, "");
	place_object(uball, u.ux, u.uy);
	u.bc_order = BCPOS_CHAIN;
    }

    place_object(uchain, u.ux, u.uy);

    u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph;   /* pick up glyph */

    newsym(u.ux,u.uy);
}
Ejemplo n.º 2
0
/* drop one object taken from a (possibly dead) monster's inventory */
static void mdrop_obj(struct monst *mon, struct obj *obj, boolean verbosely)
{
    int omx = mon->mx, omy = mon->my;

    if (obj->owornmask) {
	/* perform worn item handling if the monster is still alive */
	if (mon->mhp > 0) {
	    mon->misc_worn_check &= ~obj->owornmask;
	    update_mon_intrinsics(level, mon, obj, FALSE, TRUE);
	 /* obj_no_longer_held(obj); -- done by place_object */
	    if (obj->owornmask & W_WEP) setmnotwielded(mon, obj);
	/* don't charge for an owned saddle on dead steed */
	} else if (mon->mtame && (obj->owornmask & W_SADDLE) && 
		!obj->unpaid && costly_spot(omx, omy)) {
	    obj->no_charge = 1;
	}
	obj->owornmask = 0L;
    }
    if (verbosely && cansee(omx, omy))
	pline("%s drops %s.", Monnam(mon), distant_name(obj, doname));
    if (!flooreffects(obj, omx, omy, "fall")) {
	place_object(obj, level, omx, omy);
	stackobj(obj);
    }
}
Ejemplo n.º 3
0
/* drop one object taken from a (possibly dead) monster's inventory */
static void mdrop_obj (struct monst *mon, struct obj *obj, bool verbosely) {
    int omx = mon->mx, omy = mon->my;

    if (obj->owornmask) {
        /* perform worn item handling if the monster is still alive */
        if (mon->mhp > 0) {
            mon->misc_worn_check &= ~obj->owornmask;
            update_mon_intrinsics(mon, obj, false, true);
            /* obj_no_longer_held(obj); -- done by place_object */
            if (obj->owornmask & W_WEP) setmnotwielded(mon, obj);
            /* don't charge for an owned saddle on dead steed */
        } else if (mon->mtame && (obj->owornmask & W_SADDLE) &&
                !obj->unpaid && costly_spot(omx, omy)) {
            obj->no_charge = 1;
        }
        obj->owornmask = 0L;
    }
    if (verbosely && cansee(omx, omy)) {
        message_monster_object(MSG_M_DROPS_O, mon, obj);
    }
    if (!flooreffects(obj, omx, omy, "fall")) {
        place_object(obj, omx, omy);
        stackobj(obj);
    }
}
Ejemplo n.º 4
0
void rloco(struct obj *obj)
{
	xchar tx, ty, otx, oty;
	boolean restricted_fall;
	int try_limit = 4000;

	if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) {
	    if (revive_corpse(obj)) return;
	}

	obj_extract_self(obj);
	otx = obj->ox;
	oty = obj->oy;
	restricted_fall = (otx == 0 && level->dndest.lx);
	do {
	    tx = rn1(COLNO-3,2);
	    ty = rn2(ROWNO);
	    if (!--try_limit) break;
	} while (!goodpos(level, tx, ty, NULL, 0) ||
		/* bug: this lacks provision for handling the Wizard's tower */
		 (restricted_fall &&
		  (!within_bounded_area(tx, ty, level->dndest.lx, level->dndest.ly,
						level->dndest.hx, level->dndest.hy) ||
		   (level->dndest.nlx &&
		    within_bounded_area(tx, ty, level->dndest.nlx, level->dndest.nly,
						level->dndest.nhx, level->dndest.nhy)))));

	if (flooreffects(obj, tx, ty, "fall")) {
	    return;
	} else if (otx == 0 && oty == 0) {
	    ;	/* fell through a trap door; no update of old loc needed */
	} else {
	    if (costly_spot(otx, oty)
	      && (!costly_spot(tx, ty) ||
		  !strchr(in_rooms(level, tx, ty, 0), *in_rooms(level, otx, oty, 0)))) {
		if (costly_spot(u.ux, u.uy) &&
			    strchr(u.urooms, *in_rooms(level, otx, oty, 0)))
		    addtobill(obj, FALSE, FALSE, FALSE);
		else stolen_value(obj, otx, oty, FALSE, FALSE);
	    }
	    newsym(otx, oty);	/* update old location */
	}
	place_object(obj, level, tx, ty);
	newsym(tx, ty);
}
Ejemplo n.º 5
0
/* Be sure this corresponds with what happens to player-thrown objects in
 * dothrow.c (for consistency). --KAA
 * Returns 0 if object still exists (not destroyed).
 */
static int
drop_throw(struct obj *obj, boolean ohit, int x, int y)
{
    int retvalu = 1;
    int create;
    struct monst *mtmp;
    struct trap *t;

    if (breaks(obj, x, y))
        return 1;

    if (ohit && (is_multigen(obj) || obj->otyp == ROCK))
        create = !rn2(3);
    else
        create = 1;

    if (create &&
        !((mtmp = m_at(level, x, y)) && (mtmp->mtrapped) &&
          (t = t_at(level, x, y)) && (is_pit_trap(t->ttyp)))) {
        int objgone = 0;

        if (down_gate(x, y) != -1)
            objgone = ship_object(obj, x, y, FALSE);
        if (!objgone) {
            if (!flooreffects(obj, x, y, "fall")) {
                /* don't double-dip on damage */
                place_object(obj, level, x, y);
                if (!mtmp && x == u.ux && y == u.uy)
                    mtmp = &youmonst;
                if (mtmp && ohit)
                    passive_obj(mtmp, obj, NULL);
                stackobj(obj);
                retvalu = 0;
            }
        }
    } else
        obfree(obj, NULL);
    return retvalu;
}
Ejemplo n.º 6
0
void
rloco(struct obj *obj)
{
    int tx, ty, otx, oty;

    otx = obj->ox;
    oty = obj->oy;

    if (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm])) {
        if (revive_corpse(obj))
            return;
    }

    obj_extract_self(obj);
    rloco_pos(level, obj, &tx, &ty);

    if (flooreffects(obj, tx, ty, "fall")) {
        return;
    } else if (otx == 0 && oty == 0) {
        ;       /* fell through a trap door; no update of old loc needed */
    } else {
        if (costly_spot(otx, oty)
            && (!costly_spot(tx, ty) ||
                !strchr(in_rooms(level, tx, ty, 0),
                        *in_rooms(level, otx, oty, 0)))) {
            if (costly_spot(u.ux, u.uy) &&
                strchr(u.urooms, *in_rooms(level, otx, oty, 0)))
                addtobill(obj, FALSE, FALSE, FALSE);
            else
                stolen_value(obj, otx, oty, FALSE, FALSE);
        }
        newsym(otx, oty);       /* update old location */
    }
    place_object(obj, level, tx, ty);
    newsym(tx, ty);
}
Ejemplo n.º 7
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);
		}
	}
}
Ejemplo n.º 8
0
/*
 * 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);
    }
}
Ejemplo n.º 9
0
/* 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;
                }
        }
}
Ejemplo n.º 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;
    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);
    }
}