Blindfold removal fix
[slashemextended.git] / src / dbridge.c
bloba274d8fc3651105e44049c4caad9207caadd1705
1 /* SCCS Id: @(#)dbridge.c 3.4 2003/02/08 */
2 /* Copyright (c) 1989 by Jean-Christophe Collet */
3 /* NetHack may be freely redistributed. See license for details. */
5 /*
6 * This file contains the drawbridge manipulation (create, open, close,
7 * destroy).
9 * Added comprehensive monster-handling, and the "entity" structure to
10 * deal with players as well. - 11/89
13 #include "hack.h"
15 #ifdef OVLB
16 STATIC_DCL void get_wall_for_db(int *, int *);
17 STATIC_DCL struct entity *e_at(int, int);
18 STATIC_DCL void m_to_e(struct monst *, int, int, struct entity *);
19 STATIC_DCL void u_to_e(struct entity *);
20 STATIC_DCL void set_entity(int, int, struct entity *);
21 STATIC_DCL const char *e_nam(struct entity *);
22 #ifdef D_DEBUG
23 static const char *Enam(struct entity *); /* unused */
24 #endif
25 STATIC_DCL const char *E_phrase(struct entity *, const char *);
26 STATIC_DCL boolean e_survives_at(struct entity *, int, int);
27 STATIC_DCL void e_died(struct entity *, int, int);
28 STATIC_DCL boolean automiss(struct entity *);
29 STATIC_DCL boolean e_missed(struct entity *, BOOLEAN_P);
30 STATIC_DCL boolean e_jumps(struct entity *);
31 STATIC_DCL void do_entity(struct entity *);
32 #endif /* OVLB */
34 #ifdef OVL0
36 boolean
37 is_pool(x,y)
38 int x,y;
40 schar ltyp;
42 if (!isok(x,y)) return FALSE;
43 ltyp = levl[x][y].typ;
44 if (ltyp == POOL || ltyp == MOAT || ltyp == WATER) return TRUE;
45 if (ltyp == DRAWBRIDGE_UP &&
46 (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE;
47 return FALSE;
50 boolean
51 is_waterypool(x,y)
52 int x,y;
54 schar ltyp;
56 if (!isok(x,y)) return FALSE;
57 ltyp = levl[x][y].typ;
58 if (ltyp == POOL || ltyp == MOAT || ltyp == WATER || ltyp == CRYSTALWATER || ltyp == MOORLAND || ltyp == URINELAKE) return TRUE;
59 if (ltyp == DRAWBRIDGE_UP &&
60 (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE;
61 return FALSE;
64 boolean
65 is_drowningpool(x,y)
66 int x,y;
68 schar ltyp;
70 if (!isok(x,y)) return FALSE;
71 ltyp = levl[x][y].typ;
72 if (ltyp == POOL || ltyp == MOAT || ltyp == WATER || ltyp == CRYSTALWATER || ltyp == WATERTUNNEL) return TRUE;
73 if (ltyp == DRAWBRIDGE_UP &&
74 (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE;
75 return FALSE;
78 boolean
79 is_lava(x,y)
80 int x,y;
82 schar ltyp;
84 if (!isok(x,y)) return FALSE;
85 ltyp = levl[x][y].typ;
86 if (ltyp == LAVAPOOL
87 || (ltyp == DRAWBRIDGE_UP
88 && (levl[x][y].drawbridgemask & DB_UNDER) == DB_LAVA)) return TRUE;
89 return FALSE;
92 boolean
93 is_watertunnel(x,y)
94 int x,y;
96 schar ltyp;
98 if (!isok(x,y)) return FALSE;
99 ltyp = levl[x][y].typ;
100 if (ltyp == WATERTUNNEL) return TRUE;
101 return FALSE;
104 boolean
105 is_crystalwater(x,y)
106 int x,y;
108 schar ltyp;
110 if (!isok(x,y)) return FALSE;
111 ltyp = levl[x][y].typ;
112 if (ltyp == CRYSTALWATER) return TRUE;
113 return FALSE;
116 boolean
117 is_moorland(x,y)
118 int x,y;
120 schar ltyp;
122 if (!isok(x,y)) return FALSE;
123 ltyp = levl[x][y].typ;
124 if (ltyp == MOORLAND) return TRUE;
125 return FALSE;
128 boolean
129 is_pavedfloor(x,y)
130 int x,y;
132 schar ltyp;
134 if (!isok(x,y)) return FALSE;
135 ltyp = levl[x][y].typ;
136 if (ltyp == PAVEDFLOOR) return TRUE;
137 return FALSE;
140 boolean
141 is_highway(x,y)
142 int x,y;
144 schar ltyp;
146 if (!isok(x,y)) return FALSE;
147 ltyp = levl[x][y].typ;
148 if (ltyp == HIGHWAY) return TRUE;
149 return FALSE;
152 boolean
153 is_urinelake(x,y)
154 int x,y;
156 schar ltyp;
158 if (!isok(x,y)) return FALSE;
159 ltyp = levl[x][y].typ;
160 if (ltyp == URINELAKE) return TRUE;
161 return FALSE;
164 boolean
165 is_shiftingsand(x,y)
166 int x,y;
168 schar ltyp;
170 if (!isok(x,y)) return FALSE;
171 ltyp = levl[x][y].typ;
172 if (ltyp == SHIFTINGSAND) return TRUE;
173 return FALSE;
176 boolean
177 is_styxriver(x,y)
178 int x,y;
180 schar ltyp;
182 if (!isok(x,y)) return FALSE;
183 ltyp = levl[x][y].typ;
184 if (ltyp == STYXRIVER) return TRUE;
185 return FALSE;
188 boolean
189 is_wagon(x,y)
190 int x,y;
192 schar ltyp;
194 if (!isok(x,y)) return FALSE;
195 ltyp = levl[x][y].typ;
196 if (ltyp == WAGON) return TRUE;
197 return FALSE;
200 boolean
201 is_burningwagon(x,y)
202 int x,y;
204 schar ltyp;
206 if (!isok(x,y)) return FALSE;
207 ltyp = levl[x][y].typ;
208 if (ltyp == BURNINGWAGON) return TRUE;
209 return FALSE;
212 boolean
213 is_well(x,y)
214 int x,y;
216 schar ltyp;
218 if (!isok(x,y)) return FALSE;
219 ltyp = levl[x][y].typ;
220 if (ltyp == WELL) return TRUE;
221 return FALSE;
224 boolean
225 is_poisonedwell(x,y)
226 int x,y;
228 schar ltyp;
230 if (!isok(x,y)) return FALSE;
231 ltyp = levl[x][y].typ;
232 if (ltyp == POISONEDWELL) return TRUE;
233 return FALSE;
236 boolean
237 is_pentagram(x,y)
238 int x,y;
240 schar ltyp;
242 if (!isok(x,y)) return FALSE;
243 ltyp = levl[x][y].typ;
244 if (ltyp == PENTAGRAM) return TRUE;
245 return FALSE;
248 boolean
249 is_carvedbed(x,y)
250 int x,y;
252 schar ltyp;
254 if (!isok(x,y)) return FALSE;
255 ltyp = levl[x][y].typ;
256 if (ltyp == CARVEDBED) return TRUE;
257 return FALSE;
260 boolean
261 is_table(x,y)
262 int x,y;
264 schar ltyp;
266 if (!isok(x,y)) return FALSE;
267 ltyp = levl[x][y].typ;
268 if (ltyp == WOODENTABLE) return TRUE;
269 return FALSE;
272 boolean
273 isimportantlocation(x,y)
274 int x,y;
276 schar ltyp;
278 if (!isok(x,y)) return FALSE;
279 ltyp = levl[x][y].typ;
280 if (ltyp == STAIRS) return TRUE;
281 if (invocation_pos(x, y)) return TRUE;
282 return FALSE;
285 boolean
286 is_mattress(x,y)
287 int x,y;
289 schar ltyp;
291 if (!isok(x,y)) return FALSE;
292 ltyp = levl[x][y].typ;
293 if (ltyp == STRAWMATTRESS) return TRUE;
294 return FALSE;
297 boolean
298 is_nethermist(x,y)
299 int x,y;
301 schar ltyp;
303 if (!isok(x,y)) return FALSE;
304 ltyp = levl[x][y].typ;
305 if (ltyp == NETHERMIST) return TRUE;
306 return FALSE;
309 boolean
310 is_stalactite(x,y)
311 int x,y;
313 schar ltyp;
315 if (!isok(x,y)) return FALSE;
316 ltyp = levl[x][y].typ;
317 if (ltyp == STALACTITE) return TRUE;
318 return FALSE;
321 boolean
322 is_raincloud(x,y)
323 int x,y;
325 schar ltyp;
327 if (!isok(x,y)) return FALSE;
328 ltyp = levl[x][y].typ;
329 if (ltyp == RAINCLOUD) return TRUE;
330 return FALSE;
333 boolean
334 is_bubble(x,y)
335 int x,y;
337 schar ltyp;
339 if (!isok(x,y)) return FALSE;
340 ltyp = levl[x][y].typ;
341 if (ltyp == BUBBLES) return TRUE;
342 return FALSE;
345 boolean
346 is_ash(x,y)
347 int x,y;
349 schar ltyp;
351 if (!isok(x,y)) return FALSE;
352 ltyp = levl[x][y].typ;
353 if (ltyp == ASH) return TRUE;
354 return FALSE;
357 boolean
358 is_sand(x,y)
359 int x,y;
361 schar ltyp;
363 if (!isok(x,y)) return FALSE;
364 ltyp = levl[x][y].typ;
365 if (ltyp == SAND) return TRUE;
366 return FALSE;
369 boolean
370 is_farmland(x,y)
371 int x,y;
373 schar ltyp;
375 if (!isok(x,y)) return FALSE;
376 ltyp = levl[x][y].typ;
377 if (ltyp == FARMLAND) return TRUE;
378 return FALSE;
381 boolean
382 is_grassland(x,y)
383 int x,y;
385 schar ltyp;
387 if (!isok(x,y)) return FALSE;
388 ltyp = levl[x][y].typ;
389 if (ltyp == GRASSLAND) return TRUE;
390 return FALSE;
393 boolean
394 is_snow(x,y)
395 int x,y;
397 schar ltyp;
399 if (!isok(x,y)) return FALSE;
400 ltyp = levl[x][y].typ;
401 if (ltyp == SNOW) return TRUE;
402 return FALSE;
405 boolean
406 is_ice(x,y)
407 int x,y;
409 schar ltyp;
411 if (!isok(x,y)) return FALSE;
412 ltyp = levl[x][y].typ;
413 if (ltyp == ICE
414 || (ltyp == DRAWBRIDGE_UP
415 && (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE)) return TRUE;
416 return FALSE;
419 #endif /* OVL0 */
421 #ifdef OVL1
424 * We want to know whether a wall (or a door) is the portcullis (passageway)
425 * of an eventual drawbridge.
427 * Return value: the direction of the drawbridge.
431 is_drawbridge_wall(x,y)
432 int x,y;
434 struct rm *lev;
436 lev = &levl[x][y];
437 if (lev->typ != DOOR && lev->typ != DBWALL)
438 return (-1);
440 if (IS_DRAWBRIDGE(levl[x+1][y].typ) &&
441 (levl[x+1][y].drawbridgemask & DB_DIR) == DB_WEST)
442 return (DB_WEST);
443 if (IS_DRAWBRIDGE(levl[x-1][y].typ) &&
444 (levl[x-1][y].drawbridgemask & DB_DIR) == DB_EAST)
445 return (DB_EAST);
446 if (IS_DRAWBRIDGE(levl[x][y-1].typ) &&
447 (levl[x][y-1].drawbridgemask & DB_DIR) == DB_SOUTH)
448 return (DB_SOUTH);
449 if (IS_DRAWBRIDGE(levl[x][y+1].typ) &&
450 (levl[x][y+1].drawbridgemask & DB_DIR) == DB_NORTH)
451 return (DB_NORTH);
453 return (-1);
457 * Use is_db_wall where you want to verify that a
458 * drawbridge "wall" is UP in the location x, y
459 * (instead of UP or DOWN, as with is_drawbridge_wall).
461 boolean
462 is_db_wall(x,y)
463 int x,y;
465 return((boolean)( levl[x][y].typ == DBWALL ));
470 * Return true with x,y pointing to the drawbridge if x,y initially indicate
471 * a drawbridge or drawbridge wall.
473 boolean
474 find_drawbridge(x,y)
475 int *x,*y;
477 int dir;
479 if (IS_DRAWBRIDGE(levl[*x][*y].typ))
480 return TRUE;
481 dir = is_drawbridge_wall(*x,*y);
482 if (dir >= 0) {
483 switch(dir) {
484 case DB_NORTH: (*y)++; break;
485 case DB_SOUTH: (*y)--; break;
486 case DB_EAST: (*x)--; break;
487 case DB_WEST: (*x)++; break;
489 return TRUE;
491 return FALSE;
494 #endif /* OVL1 */
495 #ifdef OVLB
498 * Find the drawbridge wall associated with a drawbridge.
500 STATIC_OVL void
501 get_wall_for_db(x,y)
502 int *x,*y;
504 switch (levl[*x][*y].drawbridgemask & DB_DIR) {
505 case DB_NORTH: (*y)--; break;
506 case DB_SOUTH: (*y)++; break;
507 case DB_EAST: (*x)++; break;
508 case DB_WEST: (*x)--; break;
513 * Creation of a drawbridge at pos x,y.
514 * dir is the direction.
515 * flag must be put to TRUE if we want the drawbridge to be opened.
518 boolean
519 create_drawbridge(x,y,dir,flag)
520 int x,y,dir;
521 boolean flag;
523 int x2,y2;
524 boolean horiz;
525 boolean lava = levl[x][y].typ == LAVAPOOL; /* assume initialized map */
527 x2 = x; y2 = y;
528 switch(dir) {
529 case DB_NORTH:
530 horiz = TRUE;
531 y2--;
532 break;
533 case DB_SOUTH:
534 horiz = TRUE;
535 y2++;
536 break;
537 case DB_EAST:
538 horiz = FALSE;
539 x2++;
540 break;
541 default:
542 impossible("bad direction in create_drawbridge");
543 /* fall through */
544 case DB_WEST:
545 horiz = FALSE;
546 x2--;
547 break;
549 if (!IS_WALL(levl[x2][y2].typ))
550 return(FALSE);
551 if (flag) { /* We want the bridge open */
552 levl[x][y].typ = DRAWBRIDGE_DOWN;
553 levl[x2][y2].typ = DOOR;
554 levl[x2][y2].doormask = D_NODOOR;
555 } else {
556 levl[x][y].typ = DRAWBRIDGE_UP;
557 levl[x2][y2].typ = DBWALL;
558 /* Drawbridges are non-diggable. */
559 levl[x2][y2].wall_info = W_NONDIGGABLE;
561 levl[x][y].horizontal = !horiz;
562 levl[x2][y2].horizontal = horiz;
563 levl[x][y].drawbridgemask = dir;
564 if(lava) levl[x][y].drawbridgemask |= DB_LAVA;
565 return(TRUE);
568 struct entity {
569 struct monst *emon; /* youmonst for the player */
570 struct permonst *edata; /* must be non-zero for record to be valid */
571 int ex, ey;
574 #define ENTITIES 2
576 static NEARDATA struct entity occupants[ENTITIES];
578 STATIC_OVL
579 struct entity *
580 e_at(x, y)
581 int x, y;
583 int entitycnt;
585 for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++)
586 if ((occupants[entitycnt].edata) &&
587 (occupants[entitycnt].ex == x) &&
588 (occupants[entitycnt].ey == y))
589 break;
590 #ifdef D_DEBUG
591 pline("entitycnt = %d", entitycnt);
592 wait_synch();
593 #endif
594 return((entitycnt == ENTITIES)?
595 (struct entity *)0 : &(occupants[entitycnt]));
598 STATIC_OVL void
599 m_to_e(mtmp, x, y, etmp)
600 struct monst *mtmp;
601 int x, y;
602 struct entity *etmp;
604 etmp->emon = mtmp;
605 if (mtmp) {
606 etmp->ex = x;
607 etmp->ey = y;
608 if (mtmp->wormno && (x != mtmp->mx || y != mtmp->my))
609 etmp->edata = &mons[PM_LONG_WORM_TAIL];
610 else
611 etmp->edata = mtmp->data;
612 } else
613 etmp->edata = (struct permonst *)0;
616 STATIC_OVL void
617 u_to_e(etmp)
618 struct entity *etmp;
620 etmp->emon = &youmonst;
621 etmp->ex = u.ux;
622 etmp->ey = u.uy;
623 etmp->edata = youmonst.data;
626 STATIC_OVL void
627 set_entity(x, y, etmp)
628 int x, y;
629 struct entity *etmp;
631 if ((x == u.ux) && (y == u.uy))
632 u_to_e(etmp);
633 else if (MON_AT(x, y))
634 m_to_e(m_at(x, y), x, y, etmp);
635 else
636 etmp->edata = (struct permonst *)0;
639 #define is_u(etmp) (etmp->emon == &youmonst)
640 #define e_canseemon(etmp) (is_u(etmp) ? (boolean)TRUE : canseemon(etmp->emon))
643 * e_strg is a utility routine which is not actually in use anywhere, since
644 * the specialized routines below suffice for all current purposes.
647 /* #define e_strg(etmp, func) (is_u(etmp)? (char *)0 : func(etmp->emon)) */
649 STATIC_OVL const char *
650 e_nam(etmp)
651 struct entity *etmp;
653 return(is_u(etmp)? "you" : mon_nam(etmp->emon));
656 #ifdef D_DEBUG
658 * Enam is another unused utility routine: E_phrase is preferable.
661 static const char *
662 Enam(etmp)
663 struct entity *etmp;
665 return(is_u(etmp)? "You" : Monnam(etmp->emon));
667 #endif /* D_DEBUG */
670 * Generates capitalized entity name, makes 2nd -> 3rd person conversion on
671 * verb, where necessary.
674 STATIC_OVL const char *
675 E_phrase(etmp, verb)
676 struct entity *etmp;
677 const char *verb;
679 static char wholebuf[80];
681 strcpy(wholebuf, is_u(etmp) ? "You" : Monnam(etmp->emon));
682 if (!*verb) return(wholebuf);
683 strcat(wholebuf, " ");
684 if (is_u(etmp))
685 strcat(wholebuf, verb);
686 else
687 strcat(wholebuf, vtense((char *)0, verb));
688 return(wholebuf);
692 * Simple-minded "can it be here?" routine
695 STATIC_OVL boolean
696 e_survives_at(etmp, x, y)
697 struct entity *etmp;
698 int x, y;
700 if (noncorporeal(etmp->edata))
701 return(TRUE);
702 if (is_pool(x, y))
703 return((boolean)((is_u(etmp) &&
704 (Wwalking || Race_if(PM_KORONST) || Amphibious || Swimming ||
705 Flying || Levitation)) ||
706 is_swimmer(etmp->edata) || is_flyer(etmp->edata) ||
707 is_floater(etmp->edata)));
708 /* must force call to lava_effects in e_died if is_u */
709 if (is_lava(x, y))
710 return (boolean)((is_u(etmp) && (Levitation || Flying)) ||
711 likes_lava(etmp->edata) || is_flyer(etmp->edata));
712 if (is_db_wall(x, y))
713 return((boolean)(is_u(etmp) ? Passes_walls :
714 passes_walls(etmp->edata)));
715 return(TRUE);
718 STATIC_OVL void
719 e_died(etmp, dest, how)
720 struct entity *etmp;
721 int dest, how;
723 if (is_u(etmp)) {
724 if (how == DROWNING) {
725 killer = 0; /* drown() sets its own killer */
726 (void) drown();
727 } else if (how == BURNING) {
728 killer = 0; /* lava_effects() sets its own killer */
729 (void) lava_effects();
730 } else if (uwep && uwep->oartifact == ART_BRIDGEBANE) {
731 pline("Somehow, the drawbridge fails to kill you!");
732 } else if (uleft && uleft->otyp == RIN_IMMUNITY_TO_DRAWBRIDGES) {
733 pline("Somehow, the drawbridge fails to kill you!");
734 } else if (uright && uright->otyp == RIN_IMMUNITY_TO_DRAWBRIDGES) {
735 pline("Somehow, the drawbridge fails to kill you!");
736 } else {
737 coord xy;
738 u.youaredead = 1;
740 /* use more specific killer if specified */
741 if (!killer) {
742 killer_format = KILLED_BY_AN;
743 killer = "falling drawbridge";
745 done(how);
746 u.youaredead = 0;
747 /* So, you didn't die */
748 if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
749 if (enexto(&xy, etmp->ex, etmp->ey, etmp->edata)) {
750 pline("A %s force teleports you away...",
751 FunnyHallu ? "normal" : "strange");
752 teleds(xy.x, xy.y, FALSE);
754 /* otherwise on top of the drawbridge is the
755 * only viable spot in the dungeon, so stay there
759 /* we might have crawled out of the moat to survive */
760 etmp->ex = u.ux, etmp->ey = u.uy;
761 } else {
762 int entitycnt;
764 killer = 0;
765 /* fake "digested to death" damage-type suppresses corpse */
766 #define mk_message(dest) ((dest & 1) ? "" : (char *)0)
767 #define mk_corpse(dest) ((dest & 2) ? AD_DGST : AD_PHYS)
768 /* if monsters are moving, one of them caused the destruction */
769 if (flags.mon_moving)
770 monkilled(etmp->emon, mk_message(dest), mk_corpse(dest));
771 else /* you caused it */
772 xkilled(etmp->emon, dest);
773 etmp->edata = (struct permonst *)0;
775 /* dead long worm handling */
776 for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++) {
777 if (etmp != &(occupants[entitycnt]) &&
778 etmp->emon == occupants[entitycnt].emon)
779 occupants[entitycnt].edata = (struct permonst *)0;
781 #undef mk_message
782 #undef mk_corpse
788 * These are never directly affected by a bridge or portcullis.
791 STATIC_OVL boolean
792 automiss(etmp)
793 struct entity *etmp;
795 return (boolean)((is_u(etmp) ? Passes_walls :
796 passes_walls(etmp->edata)) || noncorporeal(etmp->edata));
800 * Does falling drawbridge or portcullis miss etmp?
803 STATIC_OVL boolean
804 e_missed(etmp, chunks)
805 struct entity *etmp;
806 boolean chunks;
808 int misses;
810 #ifdef D_DEBUG
811 if (chunks)
812 pline("Do chunks miss?");
813 #endif
814 if (automiss(etmp))
815 return(TRUE);
817 if (is_flyer(etmp->edata) &&
818 (is_u(etmp)? !Sleeping :
819 (etmp->emon->mcanmove && !etmp->emon->msleeping)))
820 /* flying requires mobility */
821 misses = 5; /* out of 8 */
822 else if (is_floater(etmp->edata) ||
823 (is_u(etmp) && Levitation)) /* doesn't require mobility */
824 misses = 3;
825 else if (chunks && is_pool(etmp->ex, etmp->ey))
826 misses = 2; /* sitting ducks */
827 else
828 misses = 0;
830 if (is_db_wall(etmp->ex, etmp->ey))
831 misses -= 3; /* less airspace */
833 #ifdef D_DEBUG
834 pline("Miss chance = %d (out of 8)", misses);
835 #endif
837 return((boolean)((misses >= rnd(8))? TRUE : FALSE));
841 * Can etmp jump from death?
844 STATIC_OVL boolean
845 e_jumps(etmp)
846 struct entity *etmp;
848 int tmp = 4; /* out of 10 */
850 if (is_u(etmp)? (Sleeping || Fumbling) :
851 (!etmp->emon->mcanmove || etmp->emon->msleeping ||
852 !etmp->edata->mmove || etmp->emon->wormno))
853 return(FALSE);
855 if (is_u(etmp)? Confusion : etmp->emon->mconf)
856 tmp -= 2;
858 if (is_u(etmp)? Stunned : etmp->emon->mstun)
859 tmp -= 3;
861 if (is_db_wall(etmp->ex, etmp->ey))
862 tmp -= 2; /* less room to maneuver */
864 #ifdef D_DEBUG
865 pline("%s to jump (%d chances in 10)", E_phrase(etmp, "try"), tmp);
866 #endif
867 return((boolean)((tmp >= rnd(10))? TRUE : FALSE));
870 STATIC_OVL void
871 do_entity(etmp)
872 struct entity *etmp;
874 int newx, newy, at_portcullis, oldx, oldy;
875 boolean must_jump = FALSE, relocates = FALSE, e_inview;
876 struct rm *crm;
878 if (!etmp->edata)
879 return;
881 e_inview = e_canseemon(etmp);
882 oldx = etmp->ex;
883 oldy = etmp->ey;
884 at_portcullis = is_db_wall(oldx, oldy);
885 crm = &levl[oldx][oldy];
887 if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
888 if (e_inview && (at_portcullis || IS_DRAWBRIDGE(crm->typ)))
889 pline_The("%s passes through %s!",
890 at_portcullis ? "portcullis" : "drawbridge",
891 e_nam(etmp));
892 if (is_u(etmp)) spoteffects(FALSE);
893 return;
895 if (e_missed(etmp, FALSE)) {
896 if (at_portcullis)
897 pline_The("portcullis misses %s!",
898 e_nam(etmp));
899 #ifdef D_DEBUG
900 else
901 pline_The("drawbridge misses %s!",
902 e_nam(etmp));
903 #endif
904 if (e_survives_at(etmp, oldx, oldy))
905 return;
906 else {
907 #ifdef D_DEBUG
908 pline("Mon can't survive here");
909 #endif
910 if (at_portcullis)
911 must_jump = TRUE;
912 else
913 relocates = TRUE; /* just ride drawbridge in */
915 } else {
916 if (crm->typ == DRAWBRIDGE_DOWN) {
917 pline("%s crushed underneath the drawbridge.",
918 E_phrase(etmp, "are")); /* no jump */
919 e_died(etmp, e_inview? 3 : 2, CRUSHING);/* no corpse */
920 return; /* Note: Beyond this point, we know we're */
921 } /* not at an opened drawbridge, since all */
922 must_jump = TRUE; /* *missable* creatures survive on the */
923 } /* square, and all the unmissed ones die. */
924 if (must_jump) {
925 if (at_portcullis) {
926 if (e_jumps(etmp)) {
927 relocates = TRUE;
928 #ifdef D_DEBUG
929 pline("Jump succeeds!");
930 #endif
931 } else {
932 if (e_inview)
933 pline("%s crushed by the falling portcullis!",
934 E_phrase(etmp, "are"));
935 else if (flags.soundok)
936 You_hear("a crushing sound.");
937 e_died(etmp, e_inview? 3 : 2, CRUSHING);
938 /* no corpse */
939 return;
941 } else { /* tries to jump off bridge to original square */
942 relocates = !e_jumps(etmp);
943 #ifdef D_DEBUG
944 pline("Jump %s!", (relocates)? "fails" : "succeeds");
945 #endif
950 * Here's where we try to do relocation. Assumes that etmp is not arriving
951 * at the portcullis square while the drawbridge is falling, since this square
952 * would be inaccessible (i.e. etmp started on drawbridge square) or
953 * unnecessary (i.e. etmp started here) in such a situation.
955 #ifdef D_DEBUG
956 pline("Doing relocation.");
957 #endif
958 newx = oldx;
959 newy = oldy;
960 (void)find_drawbridge(&newx, &newy);
961 if ((newx == oldx) && (newy == oldy))
962 get_wall_for_db(&newx, &newy);
963 #ifdef D_DEBUG
964 pline("Checking new square for occupancy.");
965 #endif
966 if (relocates && (e_at(newx, newy))) {
969 * Standoff problem: one or both entities must die, and/or both switch
970 * places. Avoid infinite recursion by checking first whether the other
971 * entity is staying put. Clean up if we happen to move/die in recursion.
973 struct entity *other;
975 other = e_at(newx, newy);
976 #ifdef D_DEBUG
977 pline("New square is occupied by %s", e_nam(other));
978 #endif
979 if (e_survives_at(other, newx, newy) && automiss(other)) {
980 relocates = FALSE; /* "other" won't budge */
981 #ifdef D_DEBUG
982 pline("%s suicide.", E_phrase(etmp, "commit"));
983 #endif
984 } else {
986 #ifdef D_DEBUG
987 pline("Handling %s", e_nam(other));
988 #endif
989 while ((e_at(newx, newy) != 0) &&
990 (e_at(newx, newy) != etmp))
991 do_entity(other);
992 #ifdef D_DEBUG
993 pline("Checking existence of %s", e_nam(etmp));
994 wait_synch();
995 #endif
996 if (e_at(oldx, oldy) != etmp) {
997 #ifdef D_DEBUG
998 pline("%s moved or died in recursion somewhere",
999 E_phrase(etmp, "have"));
1000 wait_synch();
1001 #endif
1002 return;
1006 if (relocates && !e_at(newx, newy)) {/* if e_at() entity = worm tail */
1007 #ifdef D_DEBUG
1008 pline("Moving %s", e_nam(etmp));
1009 #endif
1010 if (!is_u(etmp)) {
1011 remove_monster(etmp->ex, etmp->ey);
1012 place_monster(etmp->emon, newx, newy);
1013 update_monster_region(etmp->emon);
1014 } else {
1015 u.ux = newx;
1016 u.uy = newy;
1018 etmp->ex = newx;
1019 etmp->ey = newy;
1020 e_inview = e_canseemon(etmp);
1022 #ifdef D_DEBUG
1023 pline("Final disposition of %s", e_nam(etmp));
1024 wait_synch();
1025 #endif
1026 if (is_db_wall(etmp->ex, etmp->ey)) {
1027 #ifdef D_DEBUG
1028 pline("%s in portcullis chamber", E_phrase(etmp, "are"));
1029 wait_synch();
1030 #endif
1031 if (e_inview) {
1032 if (is_u(etmp)) {
1033 You("tumble towards the closed portcullis!");
1034 if (automiss(etmp))
1035 You("pass through it!");
1036 else
1037 pline_The("drawbridge closes in...");
1038 } else
1039 pline("%s behind the drawbridge.",
1040 E_phrase(etmp, "disappear"));
1042 if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
1043 killer_format = KILLED_BY_AN;
1044 killer = "closing drawbridge";
1045 e_died(etmp, 0, CRUSHING); /* no message */
1046 return;
1048 #ifdef D_DEBUG
1049 pline("%s in here", E_phrase(etmp, "survive"));
1050 #endif
1051 } else {
1052 #ifdef D_DEBUG
1053 pline("%s on drawbridge square", E_phrase(etmp, "are"));
1054 #endif
1055 if (is_pool(etmp->ex, etmp->ey) && !e_inview)
1056 if (flags.soundok)
1057 You_hear("a splash.");
1058 if (e_survives_at(etmp, etmp->ex, etmp->ey)) {
1059 if (e_inview && !is_flyer(etmp->edata) &&
1060 !is_floater(etmp->edata))
1061 pline("%s from the bridge.",
1062 E_phrase(etmp, "fall"));
1063 return;
1065 #ifdef D_DEBUG
1066 pline("%s cannot survive on the drawbridge square",Enam(etmp));
1067 #endif
1068 if (is_pool(etmp->ex, etmp->ey) || is_lava(etmp->ex, etmp->ey))
1069 if (e_inview && !is_u(etmp)) {
1070 /* drown() will supply msgs if nec. */
1071 boolean lava = is_lava(etmp->ex, etmp->ey);
1073 if (FunnyHallu)
1074 pline("%s the %s and disappears.",
1075 E_phrase(etmp, "drink"),
1076 lava ? "lava" : "moat");
1077 else
1078 pline("%s into the %s.",
1079 E_phrase(etmp, "fall"),
1080 lava ? "lava" : "moat");
1082 killer_format = NO_KILLER_PREFIX;
1083 killer = "fell from a drawbridge";
1084 e_died(etmp, e_inview ? 3 : 2, /* CRUSHING is arbitrary */
1085 (is_pool(etmp->ex, etmp->ey)) ? DROWNING :
1086 (is_lava(etmp->ex, etmp->ey)) ? BURNING :
1087 CRUSHING); /*no corpse*/
1088 return;
1093 * Close the drawbridge located at x,y
1096 void
1097 close_drawbridge(x,y)
1098 int x,y;
1100 register struct rm *lev1, *lev2;
1101 struct trap *t;
1102 int x2, y2;
1104 lev1 = &levl[x][y];
1105 if (lev1->typ != DRAWBRIDGE_DOWN) return;
1106 if (m_at(x,y) && bigmonst(m_at(x,y)->data)) {
1107 pline("A monster blocks the drawbridge with its weight.");
1108 return; /* Sorry Patric, but I decided "big" monsters are supposed to big enough so they resist crushing. */
1110 if (rn2(3)==0) {
1111 pline("The mechanism seems to have something stuck in it and won't close.");
1112 return; /* And the odds of this happening may well be higher to further stop the player's exploits. --Amy */
1114 x2 = x; y2 = y;
1115 get_wall_for_db(&x2,&y2);
1116 if (cansee(x,y) || cansee(x2,y2))
1117 You("see a drawbridge %s up!",
1118 (((u.ux == x || u.uy == y) && !Underwater) ||
1119 distu(x2,y2) < distu(x,y)) ? "coming" : "going");
1120 lev1->typ = DRAWBRIDGE_UP;
1121 lev2 = &levl[x2][y2];
1122 lev2->typ = DBWALL;
1123 switch (lev1->drawbridgemask & DB_DIR) {
1124 case DB_NORTH:
1125 case DB_SOUTH:
1126 lev2->horizontal = TRUE;
1127 break;
1128 case DB_WEST:
1129 case DB_EAST:
1130 lev2->horizontal = FALSE;
1131 break;
1133 lev2->wall_info = W_NONDIGGABLE;
1134 set_entity(x, y, &(occupants[0]));
1135 set_entity(x2, y2, &(occupants[1]));
1136 do_entity(&(occupants[0])); /* Do set_entity after first */
1137 set_entity(x2, y2, &(occupants[1])); /* do_entity for worm tail */
1138 do_entity(&(occupants[1]));
1139 if(OBJ_AT(x,y) && flags.soundok)
1140 You_hear("smashing and crushing.");
1141 (void) revive_nasty(x,y,(char *)0);
1142 (void) revive_nasty(x2,y2,(char *)0);
1143 delallobj(x, y);
1144 delallobj(x2, y2);
1145 if ((t = t_at(x, y)) != 0) deltrap(t);
1146 if ((t = t_at(x2, y2)) != 0) deltrap(t);
1147 newsym(x, y);
1148 newsym(x2, y2);
1149 block_point(x2,y2); /* vision */
1153 * Open the drawbridge located at x,y
1156 void
1157 open_drawbridge(x,y)
1158 int x,y;
1160 register struct rm *lev1, *lev2;
1161 struct trap *t;
1162 int x2, y2;
1164 lev1 = &levl[x][y];
1165 if (lev1->typ != DRAWBRIDGE_UP) return;
1166 x2 = x; y2 = y;
1167 get_wall_for_db(&x2,&y2);
1168 if (cansee(x,y) || cansee(x2,y2))
1169 You("see a drawbridge %s down!",
1170 (distu(x2,y2) < distu(x,y)) ? "going" : "coming");
1171 lev1->typ = DRAWBRIDGE_DOWN;
1172 lev2 = &levl[x2][y2];
1173 lev2->typ = DOOR;
1174 lev2->doormask = D_NODOOR;
1175 set_entity(x, y, &(occupants[0]));
1176 set_entity(x2, y2, &(occupants[1]));
1177 do_entity(&(occupants[0])); /* do set_entity after first */
1178 set_entity(x2, y2, &(occupants[1])); /* do_entity for worm tails */
1179 do_entity(&(occupants[1]));
1180 (void) revive_nasty(x,y,(char *)0);
1181 delallobj(x, y);
1182 if ((t = t_at(x, y)) != 0) deltrap(t);
1183 if ((t = t_at(x2, y2)) != 0) deltrap(t);
1184 newsym(x, y);
1185 newsym(x2, y2);
1186 unblock_point(x2,y2); /* vision */
1187 if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE;
1191 * Let's destroy the drawbridge located at x,y
1194 void
1195 destroy_drawbridge(x,y)
1196 int x,y;
1198 register struct rm *lev1, *lev2;
1199 struct trap *t;
1200 int x2, y2;
1201 boolean e_inview;
1202 struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);
1204 lev1 = &levl[x][y];
1205 if (!IS_DRAWBRIDGE(lev1->typ))
1206 return;
1207 x2 = x; y2 = y;
1208 get_wall_for_db(&x2,&y2);
1209 lev2 = &levl[x2][y2];
1210 if ((lev1->drawbridgemask & DB_UNDER) == DB_MOAT ||
1211 (lev1->drawbridgemask & DB_UNDER) == DB_LAVA) {
1212 struct obj *otmp;
1213 boolean lava = (lev1->drawbridgemask & DB_UNDER) == DB_LAVA;
1214 if (lev1->typ == DRAWBRIDGE_UP) {
1215 if (cansee(x2,y2))
1216 pline_The("portcullis of the drawbridge falls into the %s!",
1217 lava ? "lava" : "moat");
1218 else if (flags.soundok)
1219 You_hear("a loud *SPLASH*!");
1220 } else {
1221 if (cansee(x,y))
1222 pline_The("drawbridge collapses into the %s!",
1223 lava ? "lava" : "moat");
1224 else if (flags.soundok)
1225 You_hear("a loud *SPLASH*!");
1227 lev1->typ = lava ? LAVAPOOL : MOAT;
1228 lev1->drawbridgemask = 0;
1229 if ((otmp = sobj_at(BOULDER,x,y)) != 0) {
1230 obj_extract_self(otmp);
1231 (void) flooreffects(otmp,x,y,"fall");
1233 } else {
1234 if (cansee(x,y))
1235 pline_The("drawbridge disintegrates!");
1236 else
1237 You_hear("a loud *CRASH*!");
1238 lev1->typ =
1239 ((lev1->drawbridgemask & DB_ICE) ? ICE : ROOM);
1240 lev1->icedpool =
1241 ((lev1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
1243 wake_nearto(x, y, 500);
1244 lev2->typ = DOOR;
1245 lev2->doormask = D_NODOOR;
1246 if ((t = t_at(x, y)) != 0) deltrap(t);
1247 if ((t = t_at(x2, y2)) != 0) deltrap(t);
1248 newsym(x,y);
1249 newsym(x2,y2);
1250 if (!does_block(x2,y2,lev2)) unblock_point(x2,y2); /* vision */
1251 if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE;
1253 set_entity(x2, y2, etmp2); /* currently only automissers can be here */
1254 if (etmp2->edata) {
1255 e_inview = e_canseemon(etmp2);
1256 if (!automiss(etmp2)) {
1257 if (e_inview)
1258 pline("%s blown apart by flying debris.",
1259 E_phrase(etmp2, "are"));
1260 killer_format = KILLED_BY_AN;
1261 killer = "exploding drawbridge";
1262 e_died(etmp2, e_inview? 3 : 2, CRUSHING); /*no corpse*/
1263 } /* nothing which is vulnerable can survive this */
1265 set_entity(x, y, etmp1);
1266 if (etmp1->edata) {
1267 e_inview = e_canseemon(etmp1);
1268 if (e_missed(etmp1, TRUE)) {
1269 #ifdef D_DEBUG
1270 pline("%s spared!", E_phrase(etmp1, "are"));
1271 #endif
1272 } else {
1273 if (e_inview) {
1274 if (!is_u(etmp1) && FunnyHallu)
1275 pline("%s into some heavy metal!",
1276 E_phrase(etmp1, "get"));
1277 else
1278 pline("%s hit by a huge chunk of metal!",
1279 E_phrase(etmp1, "are"));
1280 } else {
1281 if (flags.soundok && !is_u(etmp1) && !is_pool(x,y))
1282 You_hear("a crushing sound.");
1283 #ifdef D_DEBUG
1284 else
1285 pline("%s from shrapnel",
1286 E_phrase(etmp1, "die"));
1287 #endif
1289 killer_format = KILLED_BY_AN;
1290 killer = "collapsing drawbridge";
1291 e_died(etmp1, e_inview? 3 : 2, CRUSHING); /*no corpse*/
1292 if(lev1->typ == MOAT) do_entity(etmp1);
1297 #endif /* OVLB */
1299 /*dbridge.c*/