1 /* NetHack 3.6 dbridge.c $NHDT-Date: 1503355815 2017/08/21 22:50:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.39 $ */
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.)
20 /* JNetHack Copyright */
21 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
22 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
23 /* JNetHack may be freely redistributed. See license for details. */
27 STATIC_DCL void FDECL(get_wall_for_db, (int *, int *));
28 STATIC_DCL struct entity *FDECL(e_at, (int, int));
29 STATIC_DCL void FDECL(m_to_e, (struct monst *, int, int, struct entity *));
30 STATIC_DCL void FDECL(u_to_e, (struct entity *));
31 STATIC_DCL void FDECL(set_entity, (int, int, struct entity *));
32 STATIC_DCL const char *FDECL(e_nam, (struct entity *));
33 STATIC_DCL const char *FDECL(E_phrase, (struct entity *, const char *));
34 STATIC_DCL boolean FDECL(e_survives_at, (struct entity *, int, int));
35 STATIC_DCL void FDECL(e_died, (struct entity *, int, int));
36 STATIC_DCL boolean FDECL(automiss, (struct entity *));
37 STATIC_DCL boolean FDECL(e_missed, (struct entity *, BOOLEAN_P));
38 STATIC_DCL boolean FDECL(e_jumps, (struct entity *));
39 STATIC_DCL void FDECL(do_entity, (struct entity *));
49 ltyp = levl[x][y].typ;
50 /* The ltyp == MOAT is not redundant with is_moat, because the
51 * Juiblex level does not have moats, although it has MOATs. There
52 * is probably a better way to express this. */
53 if (ltyp == POOL || ltyp == MOAT || ltyp == WATER || is_moat(x, y))
66 ltyp = levl[x][y].typ;
68 || (ltyp == DRAWBRIDGE_UP
69 && (levl[x][y].drawbridgemask & DB_UNDER) == DB_LAVA))
78 if (is_pool(x, y) || is_lava(x, y))
92 ltyp = levl[x][y].typ;
93 if (ltyp == ICE || (ltyp == DRAWBRIDGE_UP
94 && (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE))
107 ltyp = levl[x][y].typ;
108 if (!Is_juiblex_level(&u.uz)
110 || (ltyp == DRAWBRIDGE_UP
111 && (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT)))
120 switch (mask & DB_UNDER) {
133 * We want to know whether a wall (or a door) is the portcullis (passageway)
134 * of an eventual drawbridge.
136 * Return value: the direction of the drawbridge.
140 is_drawbridge_wall(x, y)
146 if (lev->typ != DOOR && lev->typ != DBWALL)
149 if (IS_DRAWBRIDGE(levl[x + 1][y].typ)
150 && (levl[x + 1][y].drawbridgemask & DB_DIR) == DB_WEST)
152 if (IS_DRAWBRIDGE(levl[x - 1][y].typ)
153 && (levl[x - 1][y].drawbridgemask & DB_DIR) == DB_EAST)
155 if (IS_DRAWBRIDGE(levl[x][y - 1].typ)
156 && (levl[x][y - 1].drawbridgemask & DB_DIR) == DB_SOUTH)
158 if (IS_DRAWBRIDGE(levl[x][y + 1].typ)
159 && (levl[x][y + 1].drawbridgemask & DB_DIR) == DB_NORTH)
166 * Use is_db_wall where you want to verify that a
167 * drawbridge "wall" is UP in the location x, y
168 * (instead of UP or DOWN, as with is_drawbridge_wall).
174 return (boolean) (levl[x][y].typ == DBWALL);
178 * Return true with x,y pointing to the drawbridge if x,y initially indicate
179 * a drawbridge or drawbridge wall.
182 find_drawbridge(x, y)
187 if (IS_DRAWBRIDGE(levl[*x][*y].typ))
189 dir = is_drawbridge_wall(*x, *y);
211 * Find the drawbridge wall associated with a drawbridge.
214 get_wall_for_db(x, y)
217 switch (levl[*x][*y].drawbridgemask & DB_DIR) {
234 * Creation of a drawbridge at pos x,y.
235 * dir is the direction.
236 * flag must be put to TRUE if we want the drawbridge to be opened.
239 create_drawbridge(x, y, dir, flag)
245 boolean lava = levl[x][y].typ == LAVAPOOL; /* assume initialized map */
263 impossible("bad direction in create_drawbridge");
270 if (!IS_WALL(levl[x2][y2].typ))
272 if (flag) { /* We want the bridge open */
273 levl[x][y].typ = DRAWBRIDGE_DOWN;
274 levl[x2][y2].typ = DOOR;
275 levl[x2][y2].doormask = D_NODOOR;
277 levl[x][y].typ = DRAWBRIDGE_UP;
278 levl[x2][y2].typ = DBWALL;
279 /* Drawbridges are non-diggable. */
280 levl[x2][y2].wall_info = W_NONDIGGABLE;
282 levl[x][y].horizontal = !horiz;
283 levl[x2][y2].horizontal = horiz;
284 levl[x][y].drawbridgemask = dir;
286 levl[x][y].drawbridgemask |= DB_LAVA;
291 struct monst *emon; /* youmonst for the player */
292 struct permonst *edata; /* must be non-zero for record to be valid */
298 static NEARDATA struct entity occupants[ENTITIES];
307 for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++)
308 if ((occupants[entitycnt].edata) && (occupants[entitycnt].ex == x)
309 && (occupants[entitycnt].ey == y))
311 debugpline1("entitycnt = %d", entitycnt);
315 return (entitycnt == ENTITIES) ? (struct entity *) 0
316 : &(occupants[entitycnt]);
320 m_to_e(mtmp, x, y, etmp)
329 if (mtmp->wormno && (x != mtmp->mx || y != mtmp->my))
330 etmp->edata = &mons[PM_LONG_WORM_TAIL];
332 etmp->edata = mtmp->data;
334 etmp->edata = (struct permonst *) 0;
341 etmp->emon = &youmonst;
344 etmp->edata = youmonst.data;
348 set_entity(x, y, etmp)
352 if ((x == u.ux) && (y == u.uy))
354 else if (MON_AT(x, y))
355 m_to_e(m_at(x, y), x, y, etmp);
357 etmp->edata = (struct permonst *) 0;
360 #define is_u(etmp) (etmp->emon == &youmonst)
361 #define e_canseemon(etmp) \
362 (is_u(etmp) ? (boolean) TRUE : canseemon(etmp->emon))
365 * e_strg is a utility routine which is not actually in use anywhere, since
366 * the specialized routines below suffice for all current purposes.
369 /* #define e_strg(etmp, func) (is_u(etmp)? (char *)0 : func(etmp->emon)) */
371 STATIC_OVL const char *
376 return is_u(etmp) ? "you" : mon_nam(etmp->emon);
378 return is_u(etmp) ? "
\82 \82È
\82½" : mon_nam(etmp->emon);
382 * Generates capitalized entity name, makes 2nd -> 3rd person conversion on
383 * verb, where necessary.
385 STATIC_OVL const char *
390 static char wholebuf[80];
393 Strcpy(wholebuf, is_u(etmp) ? "You" : Monnam(etmp->emon));
396 Strcat(wholebuf, " ");
398 Strcat(wholebuf, verb);
400 Strcat(wholebuf, vtense((char *) 0, verb));
403 Strcpy(wholebuf, is_u(etmp) ? "
\82 \82È
\82½" : Monnam(etmp->emon));
409 * Simple-minded "can it be here?" routine
412 e_survives_at(etmp, x, y)
416 if (noncorporeal(etmp->edata))
419 return (boolean) ((is_u(etmp) && (Wwalking || Amphibious || Swimming
420 || Flying || Levitation))
421 || is_swimmer(etmp->edata)
422 || is_flyer(etmp->edata)
423 || is_floater(etmp->edata));
424 /* must force call to lava_effects in e_died if is_u */
426 return (boolean) ((is_u(etmp) && (Levitation || Flying))
427 || likes_lava(etmp->edata)
428 || is_flyer(etmp->edata));
429 if (is_db_wall(x, y))
430 return (boolean) (is_u(etmp) ? Passes_walls
431 : passes_walls(etmp->edata));
436 e_died(etmp, xkill_flags, how)
438 int xkill_flags, how;
441 if (how == DROWNING) {
442 killer.name[0] = 0; /* drown() sets its own killer */
444 } else if (how == BURNING) {
445 killer.name[0] = 0; /* lava_effects() sets own killer */
446 (void) lava_effects();
450 /* use more specific killer if specified */
451 if (!killer.name[0]) {
452 killer.format = KILLED_BY_AN;
454 Strcpy(killer.name, "falling drawbridge");
456 Strcpy(killer.name, "
\8d~
\82è
\82Ä
\82«
\82½
\92µ
\82Ë
\8b´
\82Å");
459 /* So, you didn't die */
460 if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
461 if (enexto(&xy, etmp->ex, etmp->ey, etmp->edata)) {
463 pline("A %s force teleports you away...",
464 Hallucination ? "normal" : "strange");
466 pline("%s
\97Í
\82ª
\82 \82È
\82½
\82ð
\89\93\82
\82É
\89^
\82ñ
\82¾
\81D
\81D
\81D",
467 Hallucination ? "
\95\81\92Ê
\82Ì" : "
\8aï
\96
\82È");
469 teleds(xy.x, xy.y, FALSE);
471 /* otherwise on top of the drawbridge is the
472 * only viable spot in the dungeon, so stay there
476 /* we might have crawled out of the moat to survive */
477 etmp->ex = u.ux, etmp->ey = u.uy;
482 /* fake "digested to death" damage-type suppresses corpse */
483 #define mk_message(dest) (((dest & XKILL_NOMSG) != 0) ? (char *) 0 : "")
484 #define mk_corpse(dest) (((dest & XKILL_NOCORPSE) != 0) ? AD_DGST : AD_PHYS)
485 /* if monsters are moving, one of them caused the destruction */
486 if (context.mon_moving)
487 monkilled(etmp->emon,
488 mk_message(xkill_flags), mk_corpse(xkill_flags));
489 else /* you caused it */
490 xkilled(etmp->emon, xkill_flags);
491 etmp->edata = (struct permonst *) 0;
493 /* dead long worm handling */
494 for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++) {
495 if (etmp != &(occupants[entitycnt])
496 && etmp->emon == occupants[entitycnt].emon)
497 occupants[entitycnt].edata = (struct permonst *) 0;
505 * These are never directly affected by a bridge or portcullis.
511 return (boolean) ((is_u(etmp) ? Passes_walls : passes_walls(etmp->edata))
512 || noncorporeal(etmp->edata));
516 * Does falling drawbridge or portcullis miss etmp?
519 e_missed(etmp, chunks)
526 debugpline0("Do chunks miss?");
531 if (is_flyer(etmp->edata)
532 && (is_u(etmp) ? !Unaware
533 : (etmp->emon->mcanmove && !etmp->emon->msleeping)))
534 /* flying requires mobility */
535 misses = 5; /* out of 8 */
536 else if (is_floater(etmp->edata)
537 || (is_u(etmp) && Levitation)) /* doesn't require mobility */
539 else if (chunks && is_pool(etmp->ex, etmp->ey))
540 misses = 2; /* sitting ducks */
544 if (is_db_wall(etmp->ex, etmp->ey))
545 misses -= 3; /* less airspace */
547 debugpline1("Miss chance = %d (out of 8)", misses);
549 return (misses >= rnd(8)) ? TRUE : FALSE;
553 * Can etmp jump from death?
559 int tmp = 4; /* out of 10 */
561 if (is_u(etmp) ? (Unaware || Fumbling)
562 : (!etmp->emon->mcanmove || etmp->emon->msleeping
563 || !etmp->edata->mmove || etmp->emon->wormno))
566 if (is_u(etmp) ? Confusion : etmp->emon->mconf)
569 if (is_u(etmp) ? Stunned : etmp->emon->mstun)
572 if (is_db_wall(etmp->ex, etmp->ey))
573 tmp -= 2; /* less room to maneuver */
575 debugpline2("%s to jump (%d chances in 10)", E_phrase(etmp, "try"), tmp);
576 return (tmp >= rnd(10)) ? TRUE : FALSE;
583 int newx, newy, at_portcullis, oldx, oldy;
584 boolean must_jump = FALSE, relocates = FALSE, e_inview;
590 e_inview = e_canseemon(etmp);
593 at_portcullis = is_db_wall(oldx, oldy);
594 crm = &levl[oldx][oldy];
596 if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
597 if (e_inview && (at_portcullis || IS_DRAWBRIDGE(crm->typ)))
599 pline_The("%s passes through %s!",
600 at_portcullis ? "portcullis" : "drawbridge",
603 pline_The("%s
\82Í%s
\82ð
\92Ê
\82è
\94²
\82¯
\82½
\81I",
604 at_portcullis ? "
\97\8e\82µ
\8ai
\8eq" : "
\92µ
\82Ë
\8b´",
611 if (e_missed(etmp, FALSE)) {
614 pline_The("portcullis misses %s!", e_nam(etmp));
616 pline("
\97\8e\82µ
\8ai
\8eq
\82Í%s
\82É
\96½
\92\86\82µ
\82È
\82©
\82Á
\82½
\81I", e_nam(etmp));
618 debugpline1("The drawbridge misses %s!", e_nam(etmp));
620 if (e_survives_at(etmp, oldx, oldy)) {
623 debugpline0("Mon can't survive here");
627 relocates = TRUE; /* just ride drawbridge in */
630 if (crm->typ == DRAWBRIDGE_DOWN) {
633 killer.format = NO_KILLER_PREFIX;
635 "crushed to death underneath a drawbridge");
637 killer.format = KILLED_BY;
639 "
\92µ
\82Ë
\8b´
\82Ì
\89º
\95~
\82É
\82È
\82Á
\82Ä");
643 pline("%s crushed underneath the drawbridge.",
645 pline("%s
\82Í
\92µ
\82Ë
\8b´
\82Ì
\89º
\95~
\82É
\82È
\82Á
\82½
\81D",
646 E_phrase(etmp, "are")); /* no jump */
648 XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
649 CRUSHING); /* no corpse */
650 return; /* Note: Beyond this point, we know we're */
651 } /* not at an opened drawbridge, since all */
652 must_jump = TRUE; /* *missable* creatures survive on the */
653 } /* square, and all the unmissed ones die. */
658 debugpline0("Jump succeeds!");
662 pline("%s crushed by the falling portcullis!",
664 pline("%s
\82Í
\97\8e\82¿
\82Ä
\82«
\82½
\97\8e\82µ
\8ai
\8eq
\82É
\92×
\82³
\82ê
\82½
\81I",
665 E_phrase(etmp, "are"));
668 You_hear("a crushing sound.");
670 You_hear("
\89½
\82©
\82ª
\92×
\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81D");
672 XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG
678 } else { /* tries to jump off bridge to original square */
679 relocates = !e_jumps(etmp);
680 debugpline1("Jump %s!", (relocates) ? "fails" : "succeeds");
685 * Here's where we try to do relocation. Assumes that etmp is not
686 * arriving at the portcullis square while the drawbridge is
687 * falling, since this square would be inaccessible (i.e. etmp
688 * started on drawbridge square) or unnecessary (i.e. etmp started
689 * here) in such a situation.
691 debugpline0("Doing relocation.");
694 (void) find_drawbridge(&newx, &newy);
695 if ((newx == oldx) && (newy == oldy))
696 get_wall_for_db(&newx, &newy);
697 debugpline0("Checking new square for occupancy.");
698 if (relocates && (e_at(newx, newy))) {
700 * Standoff problem: one or both entities must die, and/or
701 * both switch places. Avoid infinite recursion by checking
702 * first whether the other entity is staying put. Clean up if
703 * we happen to move/die in recursion.
705 struct entity *other;
707 other = e_at(newx, newy);
708 debugpline1("New square is occupied by %s", e_nam(other));
709 if (e_survives_at(other, newx, newy) && automiss(other)) {
710 relocates = FALSE; /* "other" won't budge */
711 debugpline1("%s suicide.", E_phrase(etmp, "commit"));
713 debugpline1("Handling %s", e_nam(other));
714 while ((e_at(newx, newy) != 0) && (e_at(newx, newy) != etmp))
716 debugpline1("Checking existence of %s", e_nam(etmp));
720 if (e_at(oldx, oldy) != etmp) {
721 debugpline1("%s moved or died in recursion somewhere",
722 E_phrase(etmp, "have"));
730 if (relocates && !e_at(newx, newy)) { /* if e_at() entity = worm tail */
731 debugpline1("Moving %s", e_nam(etmp));
733 remove_monster(etmp->ex, etmp->ey);
734 place_monster(etmp->emon, newx, newy);
735 update_monster_region(etmp->emon);
742 e_inview = e_canseemon(etmp);
744 debugpline1("Final disposition of %s", e_nam(etmp));
748 if (is_db_wall(etmp->ex, etmp->ey)) {
749 debugpline1("%s in portcullis chamber", E_phrase(etmp, "are"));
756 You("tumble towards the closed portcullis!");
758 You("
\95Â
\82Ü
\82è
\82©
\82¯
\82Ì
\97\8e\82µ
\8ai
\8eq
\82ð
\82±
\82ë
\82Ô
\82æ
\82¤
\82É
\82·
\82è
\82Ê
\82¯
\82½
\81I");
761 You("pass through it!");
763 You("
\92Ê
\82è
\82Ê
\82¯
\82½
\81I");
766 pline_The("drawbridge closes in...");
768 pline_The("
\92µ
\82Ë
\8b´
\82Í
\95Â
\82¶
\82½
\81D
\81D
\81D");
771 pline("%s behind the drawbridge.",
773 pline("%s
\82Í
\92µ
\82Ë
\8b´
\82Ì
\97 \82É
\88Ú
\93®
\82µ
\82½
\81D",
774 E_phrase(etmp, "disappear"));
776 if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
777 killer.format = KILLED_BY_AN;
779 Strcpy(killer.name, "closing drawbridge");
781 Strcpy(killer.name, "
\95Â
\82¶
\82Ä
\82¢
\82
\92µ
\82Ë
\8b´
\82É
\8b·
\82Ü
\82ê
\82Ä");
782 e_died(etmp, XKILL_NOMSG, CRUSHING);
785 debugpline1("%s in here", E_phrase(etmp, "survive"));
787 debugpline1("%s on drawbridge square", E_phrase(etmp, "are"));
788 if (is_pool(etmp->ex, etmp->ey) && !e_inview)
791 You_hear("a splash.");
793 You_hear("
\83p
\83V
\83\83\83p
\83V
\83\83\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
794 if (e_survives_at(etmp, etmp->ex, etmp->ey)) {
795 if (e_inview && !is_flyer(etmp->edata)
796 && !is_floater(etmp->edata))
798 pline("%s from the bridge.", E_phrase(etmp, "fall"));
800 pline("%s
\82Í
\8b´
\82©
\82ç
\97\8e\82¿
\82½
\81D", E_phrase(etmp, "fall"));
803 debugpline1("%s cannot survive on the drawbridge square",
804 E_phrase(etmp, NULL));
805 if (is_pool(etmp->ex, etmp->ey) || is_lava(etmp->ex, etmp->ey))
806 if (e_inview && !is_u(etmp)) {
807 /* drown() will supply msgs if nec. */
808 boolean lava = is_lava(etmp->ex, etmp->ey);
812 pline("%s the %s and disappears.",
813 E_phrase(etmp, "drink"), lava ? "lava" : "moat");
815 pline("%s
\82Í%s
\82ð
\88ù
\82Ý
\81C
\8fÁ
\82¦
\82½
\81D",
816 E_phrase(etmp, "drink"), lava ? "
\97n
\8aâ" : "
\96x");
820 pline("%s into the %s.", E_phrase(etmp, "fall"),
821 lava ? hliquid("lava") : "moat");
823 pline("%s
\82Í%s
\82Ì
\92\86\82É
\97\8e\82¿
\82½
\81D", E_phrase(etmp, "fall"),
824 lava ? hliquid("
\97n
\8aâ") : "
\96x");
828 killer.format = NO_KILLER_PREFIX;
829 Strcpy(killer.name, "fell from a drawbridge");
831 killer.format = KILLED_BY;
832 Strcpy(killer.name, "
\92µ
\82Ë
\8b´
\82©
\82ç
\97\8e\82¿
\82Ä");
834 e_died(etmp, /* CRUSHING is arbitrary */
835 XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
836 is_pool(etmp->ex, etmp->ey) ? DROWNING
837 : is_lava(etmp->ex, etmp->ey) ? BURNING
838 : CRUSHING); /*no corpse*/
843 /* clear stale reason for death before returning */
844 #define nokiller() (killer.name[0] = '\0', killer.format = 0)
847 * Close the drawbridge located at x,y
850 close_drawbridge(x, y)
853 register struct rm *lev1, *lev2;
858 if (lev1->typ != DRAWBRIDGE_DOWN)
862 get_wall_for_db(&x2, &y2);
863 if (cansee(x, y) || cansee(x2, y2))
865 You_see("a drawbridge %s up!",
866 (((u.ux == x || u.uy == y) && !Underwater)
867 || distu(x2, y2) < distu(x, y))
871 pline("
\92µ
\82Ë
\8b´
\82ª
\8fã
\82ª
\82Á
\82Ä
\82¢
\82
\82Ì
\82ª
\8c©
\82¦
\82½
\81I");
873 else /* "5 gears turn" for castle drawbridge tune */
875 You_hear("chains rattling and gears turning.");
877 You_hear("
\8e\95\8eÔ
\82ª
\89ñ
\82è
\83`
\83F
\81[
\83\93\82ª
\83K
\83\89\83K
\83\89\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
878 lev1->typ = DRAWBRIDGE_UP;
879 lev2 = &levl[x2][y2];
881 switch (lev1->drawbridgemask & DB_DIR) {
884 lev2->horizontal = TRUE;
888 lev2->horizontal = FALSE;
891 lev2->wall_info = W_NONDIGGABLE;
892 set_entity(x, y, &(occupants[0]));
893 set_entity(x2, y2, &(occupants[1]));
894 do_entity(&(occupants[0])); /* Do set_entity after first */
895 set_entity(x2, y2, &(occupants[1])); /* do_entity for worm tail */
896 do_entity(&(occupants[1]));
897 if (OBJ_AT(x, y) && !Deaf)
899 You_hear("smashing and crushing.");
901 You_hear("
\83K
\83V
\83\83\83\93\81C
\83K
\83\89\83\93\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
902 (void) revive_nasty(x, y, (char *) 0);
903 (void) revive_nasty(x2, y2, (char *) 0);
906 if ((t = t_at(x, y)) != 0)
908 if ((t = t_at(x2, y2)) != 0)
914 block_point(x2, y2); /* vision */
919 * Open the drawbridge located at x,y
922 open_drawbridge(x, y)
925 register struct rm *lev1, *lev2;
930 if (lev1->typ != DRAWBRIDGE_UP)
934 get_wall_for_db(&x2, &y2);
935 if (cansee(x, y) || cansee(x2, y2))
937 You_see("a drawbridge %s down!",
938 (distu(x2, y2) < distu(x, y)) ? "going" : "coming");
940 pline("
\92µ
\82Ë
\8b´
\82ª
\89º
\82ª
\82é
\82Ì
\82ª
\8c©
\82¦
\82½
\81I");
942 else /* "5 gears turn" for castle drawbridge tune */
944 You_hear("gears turning and chains rattling.");
946 You_hear("
\8e\95\8eÔ
\82ª
\89ñ
\82è
\83`
\83F
\81[
\83\93\82ª
\83K
\83\89\83K
\83\89\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
947 lev1->typ = DRAWBRIDGE_DOWN;
948 lev2 = &levl[x2][y2];
950 lev2->doormask = D_NODOOR;
951 set_entity(x, y, &(occupants[0]));
952 set_entity(x2, y2, &(occupants[1]));
953 do_entity(&(occupants[0])); /* do set_entity after first */
954 set_entity(x2, y2, &(occupants[1])); /* do_entity for worm tails */
955 do_entity(&(occupants[1]));
956 (void) revive_nasty(x, y, (char *) 0);
958 if ((t = t_at(x, y)) != 0)
960 if ((t = t_at(x2, y2)) != 0)
966 unblock_point(x2, y2); /* vision */
967 if (Is_stronghold(&u.uz))
968 u.uevent.uopened_dbridge = TRUE;
973 * Let's destroy the drawbridge located at x,y
976 destroy_drawbridge(x, y)
979 register struct rm *lev1, *lev2;
984 struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);
987 if (!IS_DRAWBRIDGE(lev1->typ))
991 get_wall_for_db(&x2, &y2);
992 lev2 = &levl[x2][y2];
993 if ((lev1->drawbridgemask & DB_UNDER) == DB_MOAT
994 || (lev1->drawbridgemask & DB_UNDER) == DB_LAVA) {
996 boolean lava = (lev1->drawbridgemask & DB_UNDER) == DB_LAVA;
998 if (lev1->typ == DRAWBRIDGE_UP) {
1001 pline_The("portcullis of the drawbridge falls into the %s!",
1002 lava ? hliquid("lava") : "moat");
1004 pline("
\92µ
\82Ë
\8b´
\82Ì
\97\8e\82µ
\8ai
\8eq
\82ª%s
\82É
\97\8e\82¿
\82½
\81I",
1005 lava ? hliquid("
\97n
\8aâ") : "
\96x");
1009 You_hear("a loud *SPLASH*!");
1011 You_hear("
\91å
\82«
\82È
\83o
\83b
\83V
\83\83\81[
\83\93\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81I");
1015 pline_The("drawbridge collapses into the %s!",
1016 lava ? hliquid("lava") : "moat");
1018 pline("
\92µ
\82Ë
\8b´
\82Í%s
\82É
\82
\82¸
\82ê
\97\8e\82¿
\82½
\81I",
1019 lava ? hliquid("
\97n
\8aâ") : "
\96x");
1023 You_hear("a loud *SPLASH*!");
1025 You_hear("
\91å
\82«
\82È
\83o
\83b
\83V
\83\83\81[
\83\93\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81I");
1027 lev1->typ = lava ? LAVAPOOL : MOAT;
1028 lev1->drawbridgemask = 0;
1029 if ((otmp2 = sobj_at(BOULDER, x, y)) != 0) {
1030 obj_extract_self(otmp2);
1032 (void) flooreffects(otmp2, x, y, "fall");
1034 (void) flooreffects(otmp2, x, y, "
\97\8e\82¿
\82é");
1039 pline_The("drawbridge disintegrates!");
1041 pline("
\92µ
\82Ë
\8b´
\82Í
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½
\81I");
1044 You_hear("a loud *CRASH*!");
1046 You_hear("
\91å
\82«
\82È
\83K
\83V
\83\83\81[
\83\93\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81I");
1047 lev1->typ = ((lev1->drawbridgemask & DB_ICE) ? ICE : ROOM);
1048 lev1->icedpool = ((lev1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
1050 wake_nearto(x, y, 500);
1052 lev2->doormask = D_NODOOR;
1053 if ((t = t_at(x, y)) != 0)
1055 if ((t = t_at(x2, y2)) != 0)
1058 del_engr_at(x2, y2);
1059 for (i = rn2(6); i > 0; --i) { /* scatter some debris */
1060 /* doesn't matter if we happen to pick <x,y2> or <x2,y>;
1061 since drawbridges are never placed diagonally, those
1062 pairings will always match one of <x,y> or <x2,y2> */
1063 otmp = mksobj_at(IRON_CHAIN, rn2(2) ? x : x2, rn2(2) ? y : y2, TRUE,
1065 /* a force of 5 here would yield a radius of 2 for
1066 iron chain; anything less produces a radius of 1 */
1067 (void) scatter(otmp->ox, otmp->oy, 1, MAY_HIT, otmp);
1071 if (!does_block(x2, y2, lev2))
1072 unblock_point(x2, y2); /* vision */
1073 if (Is_stronghold(&u.uz))
1074 u.uevent.uopened_dbridge = TRUE;
1076 set_entity(x2, y2, etmp2); /* currently only automissers can be here */
1078 e_inview = e_canseemon(etmp2);
1079 if (!automiss(etmp2)) {
1082 pline("%s blown apart by flying debris.",
1084 pline("%s
\82Í
\94ò
\82Ñ
\8eU
\82Á
\82½
\8a¢âI
\82Ì
\94j
\95Ð
\82ð
\97\81\82Ñ
\82½
\81D",
1085 E_phrase(etmp2, "are"));
1086 killer.format = KILLED_BY_AN;
1088 Strcpy(killer.name, "exploding drawbridge");
1090 Strcpy(killer.name, "
\92µ
\82Ë
\8b´
\82Ì
\94\9a\94
\82Å");
1092 XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
1093 CRUSHING); /*no corpse*/
1094 } /* nothing which is vulnerable can survive this */
1096 set_entity(x, y, etmp1);
1098 e_inview = e_canseemon(etmp1);
1099 if (e_missed(etmp1, TRUE)) {
1100 debugpline1("%s spared!", E_phrase(etmp1, "are"));
1101 /* if there is water or lava here, fall in now */
1105 (void) minliquid(etmp1->emon);
1108 if (!is_u(etmp1) && Hallucination)
1110 pline("%s into some heavy metal!",
1112 pline("%s
\82Í
\8fd
\8bà
\91®
\82É
\96\84\82à
\82ê
\82½
\81I",
1113 E_phrase(etmp1, "get"));
1116 pline("%s hit by a huge chunk of metal!",
1118 pline("
\91å
\82«
\82È
\93S
\82Ì
\89ò
\82ª%s
\82É
\96½
\92\86\82µ
\82½
\81I",
1119 E_phrase(etmp1, "are"));
1121 if (!Deaf && !is_u(etmp1) && !is_pool(x, y)) {
1123 You_hear("a crushing sound.");
1125 You_hear("
\83K
\83\89\83\93\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");
1127 debugpline1("%s from shrapnel", E_phrase(etmp1, "die"));
1130 killer.format = KILLED_BY_AN;
1132 Strcpy(killer.name, "collapsing drawbridge");
1134 Strcpy(killer.name, "
\83o
\83\89\83o
\83\89\82É
\82È
\82Á
\82½
\92µ
\82Ë
\8b´
\82Å");
1136 XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
1137 CRUSHING); /*no corpse*/
1138 if (levl[etmp1->ex][etmp1->ey].typ == MOAT)