1 /* NetHack 3.6 dbridge.c $NHDT-Date: 1449269914 2015/12/04 22:58:34 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.35 $ */
2 /* Copyright (c) 1989 by Jean-Christophe Collet */
3 /* NetHack may be freely redistributed. See license for details. */
6 * This file contains the drawbridge manipulation (create, open, close,
9 * Added comprehensive monster-handling, and the "entity" structure to
10 * deal with players as well. - 11/89
12 * Any traps and/or engravings at either the portcullis or span location
13 * are destroyed whenever the bridge is lowered, raised, or destroyed.
14 * (Engraving handling could be extended to flag whether an engraving on
15 * the DB_UNDER surface is hidden by the lowered bridge, or one on the
16 * bridge itself is hidden because the bridge has been raised, but that
17 * seems like an awful lot of effort for very little gain.)
22 STATIC_DCL
void FDECL(get_wall_for_db
, (int *, int *));
23 STATIC_DCL
struct entity
*FDECL(e_at
, (int, int));
24 STATIC_DCL
void FDECL(m_to_e
, (struct monst
*, int, int, struct entity
*));
25 STATIC_DCL
void FDECL(u_to_e
, (struct entity
*));
26 STATIC_DCL
void FDECL(set_entity
, (int, int, struct entity
*));
27 STATIC_DCL
const char *FDECL(e_nam
, (struct entity
*));
28 STATIC_DCL
const char *FDECL(E_phrase
, (struct entity
*, const char *));
29 STATIC_DCL boolean
FDECL(e_survives_at
, (struct entity
*, int, int));
30 STATIC_DCL
void FDECL(e_died
, (struct entity
*, int, int));
31 STATIC_DCL boolean
FDECL(automiss
, (struct entity
*));
32 STATIC_DCL boolean
FDECL(e_missed
, (struct entity
*, BOOLEAN_P
));
33 STATIC_DCL boolean
FDECL(e_jumps
, (struct entity
*));
34 STATIC_DCL
void FDECL(do_entity
, (struct entity
*));
44 ltyp
= levl
[x
][y
].typ
;
45 /* The ltyp == MOAT is not redundant with is_moat, because the
46 * Juiblex level does not have moats, although it has MOATs. There
47 * is probably a better way to express this. */
48 if (ltyp
== POOL
|| ltyp
== MOAT
|| ltyp
== WATER
|| is_moat(x
, y
))
61 ltyp
= levl
[x
][y
].typ
;
63 || (ltyp
== DRAWBRIDGE_UP
64 && (levl
[x
][y
].drawbridgemask
& DB_UNDER
) == DB_LAVA
))
73 if (is_pool(x
, y
) || is_lava(x
, y
))
87 ltyp
= levl
[x
][y
].typ
;
88 if (ltyp
== ICE
|| (ltyp
== DRAWBRIDGE_UP
89 && (levl
[x
][y
].drawbridgemask
& DB_UNDER
) == DB_ICE
))
102 ltyp
= levl
[x
][y
].typ
;
103 if (!Is_juiblex_level(&u
.uz
)
105 || (ltyp
== DRAWBRIDGE_UP
106 && (levl
[x
][y
].drawbridgemask
& DB_UNDER
) == DB_MOAT
)))
115 switch (mask
& DB_UNDER
) {
128 * We want to know whether a wall (or a door) is the portcullis (passageway)
129 * of an eventual drawbridge.
131 * Return value: the direction of the drawbridge.
135 is_drawbridge_wall(x
, y
)
141 if (lev
->typ
!= DOOR
&& lev
->typ
!= DBWALL
)
144 if (IS_DRAWBRIDGE(levl
[x
+ 1][y
].typ
)
145 && (levl
[x
+ 1][y
].drawbridgemask
& DB_DIR
) == DB_WEST
)
147 if (IS_DRAWBRIDGE(levl
[x
- 1][y
].typ
)
148 && (levl
[x
- 1][y
].drawbridgemask
& DB_DIR
) == DB_EAST
)
150 if (IS_DRAWBRIDGE(levl
[x
][y
- 1].typ
)
151 && (levl
[x
][y
- 1].drawbridgemask
& DB_DIR
) == DB_SOUTH
)
153 if (IS_DRAWBRIDGE(levl
[x
][y
+ 1].typ
)
154 && (levl
[x
][y
+ 1].drawbridgemask
& DB_DIR
) == DB_NORTH
)
161 * Use is_db_wall where you want to verify that a
162 * drawbridge "wall" is UP in the location x, y
163 * (instead of UP or DOWN, as with is_drawbridge_wall).
169 return (boolean
) (levl
[x
][y
].typ
== DBWALL
);
173 * Return true with x,y pointing to the drawbridge if x,y initially indicate
174 * a drawbridge or drawbridge wall.
177 find_drawbridge(x
, y
)
182 if (IS_DRAWBRIDGE(levl
[*x
][*y
].typ
))
184 dir
= is_drawbridge_wall(*x
, *y
);
206 * Find the drawbridge wall associated with a drawbridge.
209 get_wall_for_db(x
, y
)
212 switch (levl
[*x
][*y
].drawbridgemask
& DB_DIR
) {
229 * Creation of a drawbridge at pos x,y.
230 * dir is the direction.
231 * flag must be put to TRUE if we want the drawbridge to be opened.
235 create_drawbridge(x
, y
, dir
, flag
)
241 boolean lava
= levl
[x
][y
].typ
== LAVAPOOL
; /* assume initialized map */
259 impossible("bad direction in create_drawbridge");
266 if (!IS_WALL(levl
[x2
][y2
].typ
))
268 if (flag
) { /* We want the bridge open */
269 levl
[x
][y
].typ
= DRAWBRIDGE_DOWN
;
270 levl
[x2
][y2
].typ
= DOOR
;
271 levl
[x2
][y2
].doormask
= D_NODOOR
;
273 levl
[x
][y
].typ
= DRAWBRIDGE_UP
;
274 levl
[x2
][y2
].typ
= DBWALL
;
275 /* Drawbridges are non-diggable. */
276 levl
[x2
][y2
].wall_info
= W_NONDIGGABLE
;
278 levl
[x
][y
].horizontal
= !horiz
;
279 levl
[x2
][y2
].horizontal
= horiz
;
280 levl
[x
][y
].drawbridgemask
= dir
;
282 levl
[x
][y
].drawbridgemask
|= DB_LAVA
;
287 struct monst
*emon
; /* youmonst for the player */
288 struct permonst
*edata
; /* must be non-zero for record to be valid */
294 static NEARDATA
struct entity occupants
[ENTITIES
];
303 for (entitycnt
= 0; entitycnt
< ENTITIES
; entitycnt
++)
304 if ((occupants
[entitycnt
].edata
) && (occupants
[entitycnt
].ex
== x
)
305 && (occupants
[entitycnt
].ey
== y
))
307 debugpline1("entitycnt = %d", entitycnt
);
311 return (entitycnt
== ENTITIES
) ? (struct entity
*) 0
312 : &(occupants
[entitycnt
]);
316 m_to_e(mtmp
, x
, y
, etmp
)
325 if (mtmp
->wormno
&& (x
!= mtmp
->mx
|| y
!= mtmp
->my
))
326 etmp
->edata
= &mons
[PM_LONG_WORM_TAIL
];
328 etmp
->edata
= mtmp
->data
;
330 etmp
->edata
= (struct permonst
*) 0;
337 etmp
->emon
= &youmonst
;
340 etmp
->edata
= youmonst
.data
;
344 set_entity(x
, y
, etmp
)
348 if ((x
== u
.ux
) && (y
== u
.uy
))
350 else if (MON_AT(x
, y
))
351 m_to_e(m_at(x
, y
), x
, y
, etmp
);
353 etmp
->edata
= (struct permonst
*) 0;
356 #define is_u(etmp) (etmp->emon == &youmonst)
357 #define e_canseemon(etmp) \
358 (is_u(etmp) ? (boolean) TRUE : canseemon(etmp->emon))
361 * e_strg is a utility routine which is not actually in use anywhere, since
362 * the specialized routines below suffice for all current purposes.
365 /* #define e_strg(etmp, func) (is_u(etmp)? (char *)0 : func(etmp->emon)) */
367 STATIC_OVL
const char *
371 return is_u(etmp
) ? "you" : mon_nam(etmp
->emon
);
375 * Generates capitalized entity name, makes 2nd -> 3rd person conversion on
376 * verb, where necessary.
379 STATIC_OVL
const char *
384 static char wholebuf
[80];
386 Strcpy(wholebuf
, is_u(etmp
) ? "You" : Monnam(etmp
->emon
));
389 Strcat(wholebuf
, " ");
391 Strcat(wholebuf
, verb
);
393 Strcat(wholebuf
, vtense((char *) 0, verb
));
398 * Simple-minded "can it be here?" routine
402 e_survives_at(etmp
, x
, y
)
406 if (noncorporeal(etmp
->edata
))
409 return (boolean
) ((is_u(etmp
) && (Wwalking
|| Amphibious
|| Swimming
410 || Flying
|| Levitation
))
411 || is_swimmer(etmp
->edata
)
412 || is_flyer(etmp
->edata
)
413 || is_floater(etmp
->edata
));
414 /* must force call to lava_effects in e_died if is_u */
416 return (boolean
) ((is_u(etmp
) && (Levitation
|| Flying
))
417 || likes_lava(etmp
->edata
)
418 || is_flyer(etmp
->edata
));
419 if (is_db_wall(x
, y
))
420 return (boolean
) (is_u(etmp
) ? Passes_walls
421 : passes_walls(etmp
->edata
));
426 e_died(etmp
, xkill_flags
, how
)
428 int xkill_flags
, how
;
431 if (how
== DROWNING
) {
432 killer
.name
[0] = 0; /* drown() sets its own killer */
434 } else if (how
== BURNING
) {
435 killer
.name
[0] = 0; /* lava_effects() sets own killer */
436 (void) lava_effects();
440 /* use more specific killer if specified */
441 if (!killer
.name
[0]) {
442 killer
.format
= KILLED_BY_AN
;
443 Strcpy(killer
.name
, "falling drawbridge");
446 /* So, you didn't die */
447 if (!e_survives_at(etmp
, etmp
->ex
, etmp
->ey
)) {
448 if (enexto(&xy
, etmp
->ex
, etmp
->ey
, etmp
->edata
)) {
449 pline("A %s force teleports you away...",
450 Hallucination
? "normal" : "strange");
451 teleds(xy
.x
, xy
.y
, FALSE
);
453 /* otherwise on top of the drawbridge is the
454 * only viable spot in the dungeon, so stay there
458 /* we might have crawled out of the moat to survive */
459 etmp
->ex
= u
.ux
, etmp
->ey
= u
.uy
;
464 /* fake "digested to death" damage-type suppresses corpse */
465 #define mk_message(dest) (((dest & XKILL_NOMSG) != 0) ? (char *) 0 : "")
466 #define mk_corpse(dest) (((dest & XKILL_NOCORPSE) != 0) ? AD_DGST : AD_PHYS)
467 /* if monsters are moving, one of them caused the destruction */
468 if (context
.mon_moving
)
469 monkilled(etmp
->emon
,
470 mk_message(xkill_flags
), mk_corpse(xkill_flags
));
471 else /* you caused it */
472 xkilled(etmp
->emon
, xkill_flags
);
473 etmp
->edata
= (struct permonst
*) 0;
475 /* dead long worm handling */
476 for (entitycnt
= 0; entitycnt
< ENTITIES
; entitycnt
++) {
477 if (etmp
!= &(occupants
[entitycnt
])
478 && etmp
->emon
== occupants
[entitycnt
].emon
)
479 occupants
[entitycnt
].edata
= (struct permonst
*) 0;
487 * These are never directly affected by a bridge or portcullis.
494 return (boolean
) ((is_u(etmp
) ? Passes_walls
: passes_walls(etmp
->edata
))
495 || noncorporeal(etmp
->edata
));
499 * Does falling drawbridge or portcullis miss etmp?
503 e_missed(etmp
, chunks
)
510 debugpline0("Do chunks miss?");
515 if (is_flyer(etmp
->edata
)
516 && (is_u(etmp
) ? !Unaware
517 : (etmp
->emon
->mcanmove
&& !etmp
->emon
->msleeping
)))
518 /* flying requires mobility */
519 misses
= 5; /* out of 8 */
520 else if (is_floater(etmp
->edata
)
521 || (is_u(etmp
) && Levitation
)) /* doesn't require mobility */
523 else if (chunks
&& is_pool(etmp
->ex
, etmp
->ey
))
524 misses
= 2; /* sitting ducks */
528 if (is_db_wall(etmp
->ex
, etmp
->ey
))
529 misses
-= 3; /* less airspace */
531 debugpline1("Miss chance = %d (out of 8)", misses
);
533 return (misses
>= rnd(8)) ? TRUE
: FALSE
;
537 * Can etmp jump from death?
544 int tmp
= 4; /* out of 10 */
546 if (is_u(etmp
) ? (Unaware
|| Fumbling
)
547 : (!etmp
->emon
->mcanmove
|| etmp
->emon
->msleeping
548 || !etmp
->edata
->mmove
|| etmp
->emon
->wormno
))
551 if (is_u(etmp
) ? Confusion
: etmp
->emon
->mconf
)
554 if (is_u(etmp
) ? Stunned
: etmp
->emon
->mstun
)
557 if (is_db_wall(etmp
->ex
, etmp
->ey
))
558 tmp
-= 2; /* less room to maneuver */
560 debugpline2("%s to jump (%d chances in 10)", E_phrase(etmp
, "try"), tmp
);
561 return (tmp
>= rnd(10)) ? TRUE
: FALSE
;
568 int newx
, newy
, at_portcullis
, oldx
, oldy
;
569 boolean must_jump
= FALSE
, relocates
= FALSE
, e_inview
;
575 e_inview
= e_canseemon(etmp
);
578 at_portcullis
= is_db_wall(oldx
, oldy
);
579 crm
= &levl
[oldx
][oldy
];
581 if (automiss(etmp
) && e_survives_at(etmp
, oldx
, oldy
)) {
582 if (e_inview
&& (at_portcullis
|| IS_DRAWBRIDGE(crm
->typ
)))
583 pline_The("%s passes through %s!",
584 at_portcullis
? "portcullis" : "drawbridge",
590 if (e_missed(etmp
, FALSE
)) {
592 pline_The("portcullis misses %s!", e_nam(etmp
));
594 debugpline1("The drawbridge misses %s!", e_nam(etmp
));
596 if (e_survives_at(etmp
, oldx
, oldy
)) {
599 debugpline0("Mon can't survive here");
603 relocates
= TRUE
; /* just ride drawbridge in */
606 if (crm
->typ
== DRAWBRIDGE_DOWN
) {
607 pline("%s crushed underneath the drawbridge.",
608 E_phrase(etmp
, "are")); /* no jump */
610 XKILL_NOCORPSE
| (e_inview
? XKILL_GIVEMSG
: XKILL_NOMSG
),
611 CRUSHING
); /* no corpse */
612 return; /* Note: Beyond this point, we know we're */
613 } /* not at an opened drawbridge, since all */
614 must_jump
= TRUE
; /* *missable* creatures survive on the */
615 } /* square, and all the unmissed ones die. */
620 debugpline0("Jump succeeds!");
623 pline("%s crushed by the falling portcullis!",
624 E_phrase(etmp
, "are"));
626 You_hear("a crushing sound.");
628 XKILL_NOCORPSE
| (e_inview
? XKILL_GIVEMSG
634 } else { /* tries to jump off bridge to original square */
635 relocates
= !e_jumps(etmp
);
636 debugpline1("Jump %s!", (relocates
) ? "fails" : "succeeds");
641 * Here's where we try to do relocation. Assumes that etmp is not
643 * at the portcullis square while the drawbridge is falling, since this
645 * would be inaccessible (i.e. etmp started on drawbridge square) or
646 * unnecessary (i.e. etmp started here) in such a situation.
648 debugpline0("Doing relocation.");
651 (void) find_drawbridge(&newx
, &newy
);
652 if ((newx
== oldx
) && (newy
== oldy
))
653 get_wall_for_db(&newx
, &newy
);
654 debugpline0("Checking new square for occupancy.");
655 if (relocates
&& (e_at(newx
, newy
))) {
657 * Standoff problem: one or both entities must die, and/or both
659 * places. Avoid infinite recursion by checking first whether the
661 * entity is staying put. Clean up if we happen to move/die in
664 struct entity
*other
;
666 other
= e_at(newx
, newy
);
667 debugpline1("New square is occupied by %s", e_nam(other
));
668 if (e_survives_at(other
, newx
, newy
) && automiss(other
)) {
669 relocates
= FALSE
; /* "other" won't budge */
670 debugpline1("%s suicide.", E_phrase(etmp
, "commit"));
672 debugpline1("Handling %s", e_nam(other
));
673 while ((e_at(newx
, newy
) != 0) && (e_at(newx
, newy
) != etmp
))
675 debugpline1("Checking existence of %s", e_nam(etmp
));
679 if (e_at(oldx
, oldy
) != etmp
) {
680 debugpline1("%s moved or died in recursion somewhere",
681 E_phrase(etmp
, "have"));
689 if (relocates
&& !e_at(newx
, newy
)) { /* if e_at() entity = worm tail */
690 debugpline1("Moving %s", e_nam(etmp
));
692 remove_monster(etmp
->ex
, etmp
->ey
);
693 place_monster(etmp
->emon
, newx
, newy
);
694 update_monster_region(etmp
->emon
);
701 e_inview
= e_canseemon(etmp
);
703 debugpline1("Final disposition of %s", e_nam(etmp
));
707 if (is_db_wall(etmp
->ex
, etmp
->ey
)) {
708 debugpline1("%s in portcullis chamber", E_phrase(etmp
, "are"));
714 You("tumble towards the closed portcullis!");
716 You("pass through it!");
718 pline_The("drawbridge closes in...");
720 pline("%s behind the drawbridge.",
721 E_phrase(etmp
, "disappear"));
723 if (!e_survives_at(etmp
, etmp
->ex
, etmp
->ey
)) {
724 killer
.format
= KILLED_BY_AN
;
725 Strcpy(killer
.name
, "closing drawbridge");
726 e_died(etmp
, XKILL_NOMSG
, CRUSHING
);
729 debugpline1("%s in here", E_phrase(etmp
, "survive"));
731 debugpline1("%s on drawbridge square", E_phrase(etmp
, "are"));
732 if (is_pool(etmp
->ex
, etmp
->ey
) && !e_inview
)
734 You_hear("a splash.");
735 if (e_survives_at(etmp
, etmp
->ex
, etmp
->ey
)) {
736 if (e_inview
&& !is_flyer(etmp
->edata
)
737 && !is_floater(etmp
->edata
))
738 pline("%s from the bridge.", E_phrase(etmp
, "fall"));
741 debugpline1("%s cannot survive on the drawbridge square",
742 E_phrase(etmp
, NULL
));
743 if (is_pool(etmp
->ex
, etmp
->ey
) || is_lava(etmp
->ex
, etmp
->ey
))
744 if (e_inview
&& !is_u(etmp
)) {
745 /* drown() will supply msgs if nec. */
746 boolean lava
= is_lava(etmp
->ex
, etmp
->ey
);
749 pline("%s the %s and disappears.",
750 E_phrase(etmp
, "drink"), lava
? "lava" : "moat");
752 pline("%s into the %s.", E_phrase(etmp
, "fall"),
753 lava
? hliquid("lava") : "moat");
755 killer
.format
= NO_KILLER_PREFIX
;
756 Strcpy(killer
.name
, "fell from a drawbridge");
757 e_died(etmp
, /* CRUSHING is arbitrary */
758 XKILL_NOCORPSE
| (e_inview
? XKILL_GIVEMSG
: XKILL_NOMSG
),
759 is_pool(etmp
->ex
, etmp
->ey
) ? DROWNING
760 : is_lava(etmp
->ex
, etmp
->ey
) ? BURNING
761 : CRUSHING
); /*no corpse*/
767 * Close the drawbridge located at x,y
771 close_drawbridge(x
, y
)
774 register struct rm
*lev1
, *lev2
;
779 if (lev1
->typ
!= DRAWBRIDGE_DOWN
)
783 get_wall_for_db(&x2
, &y2
);
784 if (cansee(x
, y
) || cansee(x2
, y2
))
785 You_see("a drawbridge %s up!",
786 (((u
.ux
== x
|| u
.uy
== y
) && !Underwater
)
787 || distu(x2
, y2
) < distu(x
, y
))
790 else /* "5 gears turn" for castle drawbridge tune */
791 You_hear("chains rattling and gears turning.");
792 lev1
->typ
= DRAWBRIDGE_UP
;
793 lev2
= &levl
[x2
][y2
];
795 switch (lev1
->drawbridgemask
& DB_DIR
) {
798 lev2
->horizontal
= TRUE
;
802 lev2
->horizontal
= FALSE
;
805 lev2
->wall_info
= W_NONDIGGABLE
;
806 set_entity(x
, y
, &(occupants
[0]));
807 set_entity(x2
, y2
, &(occupants
[1]));
808 do_entity(&(occupants
[0])); /* Do set_entity after first */
809 set_entity(x2
, y2
, &(occupants
[1])); /* do_entity for worm tail */
810 do_entity(&(occupants
[1]));
811 if (OBJ_AT(x
, y
) && !Deaf
)
812 You_hear("smashing and crushing.");
813 (void) revive_nasty(x
, y
, (char *) 0);
814 (void) revive_nasty(x2
, y2
, (char *) 0);
817 if ((t
= t_at(x
, y
)) != 0)
819 if ((t
= t_at(x2
, y2
)) != 0)
825 block_point(x2
, y2
); /* vision */
829 * Open the drawbridge located at x,y
833 open_drawbridge(x
, y
)
836 register struct rm
*lev1
, *lev2
;
841 if (lev1
->typ
!= DRAWBRIDGE_UP
)
845 get_wall_for_db(&x2
, &y2
);
846 if (cansee(x
, y
) || cansee(x2
, y2
))
847 You_see("a drawbridge %s down!",
848 (distu(x2
, y2
) < distu(x
, y
)) ? "going" : "coming");
849 else /* "5 gears turn" for castle drawbridge tune */
850 You_hear("gears turning and chains rattling.");
851 lev1
->typ
= DRAWBRIDGE_DOWN
;
852 lev2
= &levl
[x2
][y2
];
854 lev2
->doormask
= D_NODOOR
;
855 set_entity(x
, y
, &(occupants
[0]));
856 set_entity(x2
, y2
, &(occupants
[1]));
857 do_entity(&(occupants
[0])); /* do set_entity after first */
858 set_entity(x2
, y2
, &(occupants
[1])); /* do_entity for worm tails */
859 do_entity(&(occupants
[1]));
860 (void) revive_nasty(x
, y
, (char *) 0);
862 if ((t
= t_at(x
, y
)) != 0)
864 if ((t
= t_at(x2
, y2
)) != 0)
870 unblock_point(x2
, y2
); /* vision */
871 if (Is_stronghold(&u
.uz
))
872 u
.uevent
.uopened_dbridge
= TRUE
;
876 * Let's destroy the drawbridge located at x,y
880 destroy_drawbridge(x
, y
)
883 register struct rm
*lev1
, *lev2
;
888 struct entity
*etmp1
= &(occupants
[0]), *etmp2
= &(occupants
[1]);
891 if (!IS_DRAWBRIDGE(lev1
->typ
))
895 get_wall_for_db(&x2
, &y2
);
896 lev2
= &levl
[x2
][y2
];
897 if ((lev1
->drawbridgemask
& DB_UNDER
) == DB_MOAT
898 || (lev1
->drawbridgemask
& DB_UNDER
) == DB_LAVA
) {
900 boolean lava
= (lev1
->drawbridgemask
& DB_UNDER
) == DB_LAVA
;
901 if (lev1
->typ
== DRAWBRIDGE_UP
) {
903 pline_The("portcullis of the drawbridge falls into the %s!",
904 lava
? hliquid("lava") : "moat");
906 You_hear("a loud *SPLASH*!");
909 pline_The("drawbridge collapses into the %s!",
910 lava
? hliquid("lava") : "moat");
912 You_hear("a loud *SPLASH*!");
914 lev1
->typ
= lava
? LAVAPOOL
: MOAT
;
915 lev1
->drawbridgemask
= 0;
916 if ((otmp2
= sobj_at(BOULDER
, x
, y
)) != 0) {
917 obj_extract_self(otmp2
);
918 (void) flooreffects(otmp2
, x
, y
, "fall");
922 pline_The("drawbridge disintegrates!");
924 You_hear("a loud *CRASH*!");
925 lev1
->typ
= ((lev1
->drawbridgemask
& DB_ICE
) ? ICE
: ROOM
);
926 lev1
->icedpool
= ((lev1
->drawbridgemask
& DB_ICE
) ? ICED_MOAT
: 0);
928 wake_nearto(x
, y
, 500);
930 lev2
->doormask
= D_NODOOR
;
931 if ((t
= t_at(x
, y
)) != 0)
933 if ((t
= t_at(x2
, y2
)) != 0)
937 for (i
= rn2(6); i
> 0; --i
) { /* scatter some debris */
938 /* doesn't matter if we happen to pick <x,y2> or <x2,y>;
939 since drawbridges are never placed diagonally, those
940 pairings will always match one of <x,y> or <x2,y2> */
941 otmp
= mksobj_at(IRON_CHAIN
, rn2(2) ? x
: x2
, rn2(2) ? y
: y2
, TRUE
,
943 /* a force of 5 here would yield a radius of 2 for
944 iron chain; anything less produces a radius of 1 */
945 (void) scatter(otmp
->ox
, otmp
->oy
, 1, MAY_HIT
, otmp
);
949 if (!does_block(x2
, y2
, lev2
))
950 unblock_point(x2
, y2
); /* vision */
951 if (Is_stronghold(&u
.uz
))
952 u
.uevent
.uopened_dbridge
= TRUE
;
954 set_entity(x2
, y2
, etmp2
); /* currently only automissers can be here */
956 e_inview
= e_canseemon(etmp2
);
957 if (!automiss(etmp2
)) {
959 pline("%s blown apart by flying debris.",
960 E_phrase(etmp2
, "are"));
961 killer
.format
= KILLED_BY_AN
;
962 Strcpy(killer
.name
, "exploding drawbridge");
964 XKILL_NOCORPSE
| (e_inview
? XKILL_GIVEMSG
: XKILL_NOMSG
),
965 CRUSHING
); /*no corpse*/
966 } /* nothing which is vulnerable can survive this */
968 set_entity(x
, y
, etmp1
);
970 e_inview
= e_canseemon(etmp1
);
971 if (e_missed(etmp1
, TRUE
)) {
972 debugpline1("%s spared!", E_phrase(etmp1
, "are"));
973 /* if there is water or lava here, fall in now */
977 (void) minliquid(etmp1
->emon
);
980 if (!is_u(etmp1
) && Hallucination
)
981 pline("%s into some heavy metal!",
982 E_phrase(etmp1
, "get"));
984 pline("%s hit by a huge chunk of metal!",
985 E_phrase(etmp1
, "are"));
987 if (!Deaf
&& !is_u(etmp1
) && !is_pool(x
, y
)) {
988 You_hear("a crushing sound.");
990 debugpline1("%s from shrapnel", E_phrase(etmp1
, "die"));
993 killer
.format
= KILLED_BY_AN
;
994 Strcpy(killer
.name
, "collapsing drawbridge");
996 XKILL_NOCORPSE
| (e_inview
? XKILL_GIVEMSG
: XKILL_NOMSG
),
997 CRUSHING
); /*no corpse*/
998 if (levl
[etmp1
->ex
][etmp1
->ey
].typ
== MOAT
)