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
, dest
, 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 & 1) ? "" : (char *) 0)
466 #define mk_corpse(dest) ((dest & 2) ? AD_DGST : AD_PHYS)
467 /* if monsters are moving, one of them caused the destruction */
468 if (context
.mon_moving
)
469 monkilled(etmp
->emon
, mk_message(dest
), mk_corpse(dest
));
470 else /* you caused it */
471 xkilled(etmp
->emon
, dest
);
472 etmp
->edata
= (struct permonst
*) 0;
474 /* dead long worm handling */
475 for (entitycnt
= 0; entitycnt
< ENTITIES
; entitycnt
++) {
476 if (etmp
!= &(occupants
[entitycnt
])
477 && etmp
->emon
== occupants
[entitycnt
].emon
)
478 occupants
[entitycnt
].edata
= (struct permonst
*) 0;
486 * These are never directly affected by a bridge or portcullis.
493 return (boolean
) ((is_u(etmp
) ? Passes_walls
: passes_walls(etmp
->edata
))
494 || noncorporeal(etmp
->edata
));
498 * Does falling drawbridge or portcullis miss etmp?
502 e_missed(etmp
, chunks
)
509 debugpline0("Do chunks miss?");
514 if (is_flyer(etmp
->edata
)
515 && (is_u(etmp
) ? !Unaware
516 : (etmp
->emon
->mcanmove
&& !etmp
->emon
->msleeping
)))
517 /* flying requires mobility */
518 misses
= 5; /* out of 8 */
519 else if (is_floater(etmp
->edata
)
520 || (is_u(etmp
) && Levitation
)) /* doesn't require mobility */
522 else if (chunks
&& is_pool(etmp
->ex
, etmp
->ey
))
523 misses
= 2; /* sitting ducks */
527 if (is_db_wall(etmp
->ex
, etmp
->ey
))
528 misses
-= 3; /* less airspace */
530 debugpline1("Miss chance = %d (out of 8)", misses
);
532 return (misses
>= rnd(8)) ? TRUE
: FALSE
;
536 * Can etmp jump from death?
543 int tmp
= 4; /* out of 10 */
545 if (is_u(etmp
) ? (Unaware
|| Fumbling
)
546 : (!etmp
->emon
->mcanmove
|| etmp
->emon
->msleeping
547 || !etmp
->edata
->mmove
|| etmp
->emon
->wormno
))
550 if (is_u(etmp
) ? Confusion
: etmp
->emon
->mconf
)
553 if (is_u(etmp
) ? Stunned
: etmp
->emon
->mstun
)
556 if (is_db_wall(etmp
->ex
, etmp
->ey
))
557 tmp
-= 2; /* less room to maneuver */
559 debugpline2("%s to jump (%d chances in 10)", E_phrase(etmp
, "try"), tmp
);
560 return (tmp
>= rnd(10)) ? TRUE
: FALSE
;
567 int newx
, newy
, at_portcullis
, oldx
, oldy
;
568 boolean must_jump
= FALSE
, relocates
= FALSE
, e_inview
;
574 e_inview
= e_canseemon(etmp
);
577 at_portcullis
= is_db_wall(oldx
, oldy
);
578 crm
= &levl
[oldx
][oldy
];
580 if (automiss(etmp
) && e_survives_at(etmp
, oldx
, oldy
)) {
581 if (e_inview
&& (at_portcullis
|| IS_DRAWBRIDGE(crm
->typ
)))
582 pline_The("%s passes through %s!",
583 at_portcullis
? "portcullis" : "drawbridge",
589 if (e_missed(etmp
, FALSE
)) {
591 pline_The("portcullis misses %s!", e_nam(etmp
));
593 debugpline1("The drawbridge misses %s!", e_nam(etmp
));
595 if (e_survives_at(etmp
, oldx
, oldy
)) {
598 debugpline0("Mon can't survive here");
602 relocates
= TRUE
; /* just ride drawbridge in */
605 if (crm
->typ
== DRAWBRIDGE_DOWN
) {
606 pline("%s crushed underneath the drawbridge.",
607 E_phrase(etmp
, "are")); /* no jump */
608 e_died(etmp
, e_inview
? 3 : 2, CRUSHING
); /* no corpse */
609 return; /* Note: Beyond this point, we know we're */
610 } /* not at an opened drawbridge, since all */
611 must_jump
= TRUE
; /* *missable* creatures survive on the */
612 } /* square, and all the unmissed ones die. */
617 debugpline0("Jump succeeds!");
620 pline("%s crushed by the falling portcullis!",
621 E_phrase(etmp
, "are"));
623 You_hear("a crushing sound.");
624 e_died(etmp
, e_inview
? 3 : 2, CRUSHING
);
628 } else { /* tries to jump off bridge to original square */
629 relocates
= !e_jumps(etmp
);
630 debugpline1("Jump %s!", (relocates
) ? "fails" : "succeeds");
635 * Here's where we try to do relocation. Assumes that etmp is not
637 * at the portcullis square while the drawbridge is falling, since this
639 * would be inaccessible (i.e. etmp started on drawbridge square) or
640 * unnecessary (i.e. etmp started here) in such a situation.
642 debugpline0("Doing relocation.");
645 (void) find_drawbridge(&newx
, &newy
);
646 if ((newx
== oldx
) && (newy
== oldy
))
647 get_wall_for_db(&newx
, &newy
);
648 debugpline0("Checking new square for occupancy.");
649 if (relocates
&& (e_at(newx
, newy
))) {
651 * Standoff problem: one or both entities must die, and/or both
653 * places. Avoid infinite recursion by checking first whether the
655 * entity is staying put. Clean up if we happen to move/die in
658 struct entity
*other
;
660 other
= e_at(newx
, newy
);
661 debugpline1("New square is occupied by %s", e_nam(other
));
662 if (e_survives_at(other
, newx
, newy
) && automiss(other
)) {
663 relocates
= FALSE
; /* "other" won't budge */
664 debugpline1("%s suicide.", E_phrase(etmp
, "commit"));
666 debugpline1("Handling %s", e_nam(other
));
667 while ((e_at(newx
, newy
) != 0) && (e_at(newx
, newy
) != etmp
))
669 debugpline1("Checking existence of %s", e_nam(etmp
));
673 if (e_at(oldx
, oldy
) != etmp
) {
674 debugpline1("%s moved or died in recursion somewhere",
675 E_phrase(etmp
, "have"));
683 if (relocates
&& !e_at(newx
, newy
)) { /* if e_at() entity = worm tail */
684 debugpline1("Moving %s", e_nam(etmp
));
686 remove_monster(etmp
->ex
, etmp
->ey
);
687 place_monster(etmp
->emon
, newx
, newy
);
688 update_monster_region(etmp
->emon
);
695 e_inview
= e_canseemon(etmp
);
697 debugpline1("Final disposition of %s", e_nam(etmp
));
701 if (is_db_wall(etmp
->ex
, etmp
->ey
)) {
702 debugpline1("%s in portcullis chamber", E_phrase(etmp
, "are"));
708 You("tumble towards the closed portcullis!");
710 You("pass through it!");
712 pline_The("drawbridge closes in...");
714 pline("%s behind the drawbridge.",
715 E_phrase(etmp
, "disappear"));
717 if (!e_survives_at(etmp
, etmp
->ex
, etmp
->ey
)) {
718 killer
.format
= KILLED_BY_AN
;
719 Strcpy(killer
.name
, "closing drawbridge");
720 e_died(etmp
, 0, CRUSHING
); /* no message */
723 debugpline1("%s in here", E_phrase(etmp
, "survive"));
725 debugpline1("%s on drawbridge square", E_phrase(etmp
, "are"));
726 if (is_pool(etmp
->ex
, etmp
->ey
) && !e_inview
)
728 You_hear("a splash.");
729 if (e_survives_at(etmp
, etmp
->ex
, etmp
->ey
)) {
730 if (e_inview
&& !is_flyer(etmp
->edata
)
731 && !is_floater(etmp
->edata
))
732 pline("%s from the bridge.", E_phrase(etmp
, "fall"));
735 debugpline1("%s cannot survive on the drawbridge square",
736 E_phrase(etmp
, NULL
));
737 if (is_pool(etmp
->ex
, etmp
->ey
) || is_lava(etmp
->ex
, etmp
->ey
))
738 if (e_inview
&& !is_u(etmp
)) {
739 /* drown() will supply msgs if nec. */
740 boolean lava
= is_lava(etmp
->ex
, etmp
->ey
);
743 pline("%s the %s and disappears.",
744 E_phrase(etmp
, "drink"), lava
? "lava" : "moat");
746 pline("%s into the %s.", E_phrase(etmp
, "fall"),
747 lava
? "lava" : "moat");
749 killer
.format
= NO_KILLER_PREFIX
;
750 Strcpy(killer
.name
, "fell from a drawbridge");
751 e_died(etmp
, e_inview
? 3 : 2, /* CRUSHING is arbitrary */
752 (is_pool(etmp
->ex
, etmp
->ey
))
754 : (is_lava(etmp
->ex
, etmp
->ey
)) ? BURNING
755 : CRUSHING
); /*no corpse*/
761 * Close the drawbridge located at x,y
765 close_drawbridge(x
, y
)
768 register struct rm
*lev1
, *lev2
;
773 if (lev1
->typ
!= DRAWBRIDGE_DOWN
)
777 get_wall_for_db(&x2
, &y2
);
778 if (cansee(x
, y
) || cansee(x2
, y2
))
779 You_see("a drawbridge %s up!",
780 (((u
.ux
== x
|| u
.uy
== y
) && !Underwater
)
781 || distu(x2
, y2
) < distu(x
, y
))
784 else /* "5 gears turn" for castle drawbridge tune */
785 You_hear("chains rattling and gears turning.");
786 lev1
->typ
= DRAWBRIDGE_UP
;
787 lev2
= &levl
[x2
][y2
];
789 switch (lev1
->drawbridgemask
& DB_DIR
) {
792 lev2
->horizontal
= TRUE
;
796 lev2
->horizontal
= FALSE
;
799 lev2
->wall_info
= W_NONDIGGABLE
;
800 set_entity(x
, y
, &(occupants
[0]));
801 set_entity(x2
, y2
, &(occupants
[1]));
802 do_entity(&(occupants
[0])); /* Do set_entity after first */
803 set_entity(x2
, y2
, &(occupants
[1])); /* do_entity for worm tail */
804 do_entity(&(occupants
[1]));
805 if (OBJ_AT(x
, y
) && !Deaf
)
806 You_hear("smashing and crushing.");
807 (void) revive_nasty(x
, y
, (char *) 0);
808 (void) revive_nasty(x2
, y2
, (char *) 0);
811 if ((t
= t_at(x
, y
)) != 0)
813 if ((t
= t_at(x2
, y2
)) != 0)
819 block_point(x2
, y2
); /* vision */
823 * Open the drawbridge located at x,y
827 open_drawbridge(x
, y
)
830 register struct rm
*lev1
, *lev2
;
835 if (lev1
->typ
!= DRAWBRIDGE_UP
)
839 get_wall_for_db(&x2
, &y2
);
840 if (cansee(x
, y
) || cansee(x2
, y2
))
841 You_see("a drawbridge %s down!",
842 (distu(x2
, y2
) < distu(x
, y
)) ? "going" : "coming");
843 else /* "5 gears turn" for castle drawbridge tune */
844 You_hear("gears turning and chains rattling.");
845 lev1
->typ
= DRAWBRIDGE_DOWN
;
846 lev2
= &levl
[x2
][y2
];
848 lev2
->doormask
= D_NODOOR
;
849 set_entity(x
, y
, &(occupants
[0]));
850 set_entity(x2
, y2
, &(occupants
[1]));
851 do_entity(&(occupants
[0])); /* do set_entity after first */
852 set_entity(x2
, y2
, &(occupants
[1])); /* do_entity for worm tails */
853 do_entity(&(occupants
[1]));
854 (void) revive_nasty(x
, y
, (char *) 0);
856 if ((t
= t_at(x
, y
)) != 0)
858 if ((t
= t_at(x2
, y2
)) != 0)
864 unblock_point(x2
, y2
); /* vision */
865 if (Is_stronghold(&u
.uz
))
866 u
.uevent
.uopened_dbridge
= TRUE
;
870 * Let's destroy the drawbridge located at x,y
874 destroy_drawbridge(x
, y
)
877 register struct rm
*lev1
, *lev2
;
882 struct entity
*etmp1
= &(occupants
[0]), *etmp2
= &(occupants
[1]);
885 if (!IS_DRAWBRIDGE(lev1
->typ
))
889 get_wall_for_db(&x2
, &y2
);
890 lev2
= &levl
[x2
][y2
];
891 if ((lev1
->drawbridgemask
& DB_UNDER
) == DB_MOAT
892 || (lev1
->drawbridgemask
& DB_UNDER
) == DB_LAVA
) {
894 boolean lava
= (lev1
->drawbridgemask
& DB_UNDER
) == DB_LAVA
;
895 if (lev1
->typ
== DRAWBRIDGE_UP
) {
897 pline_The("portcullis of the drawbridge falls into the %s!",
898 lava
? "lava" : "moat");
900 You_hear("a loud *SPLASH*!");
903 pline_The("drawbridge collapses into the %s!",
904 lava
? "lava" : "moat");
906 You_hear("a loud *SPLASH*!");
908 lev1
->typ
= lava
? LAVAPOOL
: MOAT
;
909 lev1
->drawbridgemask
= 0;
910 if ((otmp2
= sobj_at(BOULDER
, x
, y
)) != 0) {
911 obj_extract_self(otmp2
);
912 (void) flooreffects(otmp2
, x
, y
, "fall");
916 pline_The("drawbridge disintegrates!");
918 You_hear("a loud *CRASH*!");
919 lev1
->typ
= ((lev1
->drawbridgemask
& DB_ICE
) ? ICE
: ROOM
);
920 lev1
->icedpool
= ((lev1
->drawbridgemask
& DB_ICE
) ? ICED_MOAT
: 0);
922 wake_nearto(x
, y
, 500);
924 lev2
->doormask
= D_NODOOR
;
925 if ((t
= t_at(x
, y
)) != 0)
927 if ((t
= t_at(x2
, y2
)) != 0)
931 for (i
= rn2(6); i
> 0; --i
) { /* scatter some debris */
932 /* doesn't matter if we happen to pick <x,y2> or <x2,y>;
933 since drawbridges are never placed diagonally, those
934 pairings will always match one of <x,y> or <x2,y2> */
935 otmp
= mksobj_at(IRON_CHAIN
, rn2(2) ? x
: x2
, rn2(2) ? y
: y2
, TRUE
,
937 /* a force of 5 here would yield a radius of 2 for
938 iron chain; anything less produces a radius of 1 */
939 (void) scatter(otmp
->ox
, otmp
->oy
, 1, MAY_HIT
, otmp
);
943 if (!does_block(x2
, y2
, lev2
))
944 unblock_point(x2
, y2
); /* vision */
945 if (Is_stronghold(&u
.uz
))
946 u
.uevent
.uopened_dbridge
= TRUE
;
948 set_entity(x2
, y2
, etmp2
); /* currently only automissers can be here */
950 e_inview
= e_canseemon(etmp2
);
951 if (!automiss(etmp2
)) {
953 pline("%s blown apart by flying debris.",
954 E_phrase(etmp2
, "are"));
955 killer
.format
= KILLED_BY_AN
;
956 Strcpy(killer
.name
, "exploding drawbridge");
957 e_died(etmp2
, e_inview
? 3 : 2, CRUSHING
); /*no corpse*/
958 } /* nothing which is vulnerable can survive this */
960 set_entity(x
, y
, etmp1
);
962 e_inview
= e_canseemon(etmp1
);
963 if (e_missed(etmp1
, TRUE
)) {
964 debugpline1("%s spared!", E_phrase(etmp1
, "are"));
965 /* if there is water or lava here, fall in now */
969 (void) minliquid(etmp1
->emon
);
972 if (!is_u(etmp1
) && Hallucination
)
973 pline("%s into some heavy metal!",
974 E_phrase(etmp1
, "get"));
976 pline("%s hit by a huge chunk of metal!",
977 E_phrase(etmp1
, "are"));
979 if (!Deaf
&& !is_u(etmp1
) && !is_pool(x
, y
)) {
980 You_hear("a crushing sound.");
982 debugpline1("%s from shrapnel", E_phrase(etmp1
, "die"));
985 killer
.format
= KILLED_BY_AN
;
986 Strcpy(killer
.name
, "collapsing drawbridge");
987 e_died(etmp1
, e_inview
? 3 : 2, CRUSHING
); /*no corpse*/
988 if (levl
[etmp1
->ex
][etmp1
->ey
].typ
== MOAT
)