OSDN Git Service

update year to 2020
[jnethack/source.git] / src / dbridge.c
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. */
4
5 /*
6  * This file contains the drawbridge manipulation (create, open, close,
7  * destroy).
8  *
9  * Added comprehensive monster-handling, and the "entity" structure to
10  * deal with players as well. - 11/89
11  *
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.)
18  */
19
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. */
24
25 #include "hack.h"
26
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 *));
40
41 boolean
42 is_pool(x, y)
43 int x, y;
44 {
45     schar ltyp;
46
47     if (!isok(x, y))
48         return FALSE;
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))
54         return TRUE;
55     return FALSE;
56 }
57
58 boolean
59 is_lava(x, y)
60 int x, y;
61 {
62     schar ltyp;
63
64     if (!isok(x, y))
65         return FALSE;
66     ltyp = levl[x][y].typ;
67     if (ltyp == LAVAPOOL
68         || (ltyp == DRAWBRIDGE_UP
69             && (levl[x][y].drawbridgemask & DB_UNDER) == DB_LAVA))
70         return TRUE;
71     return FALSE;
72 }
73
74 boolean
75 is_pool_or_lava(x, y)
76 int x, y;
77 {
78     if (is_pool(x, y) || is_lava(x, y))
79         return TRUE;
80     else
81         return FALSE;
82 }
83
84 boolean
85 is_ice(x, y)
86 int x, y;
87 {
88     schar ltyp;
89
90     if (!isok(x, y))
91         return FALSE;
92     ltyp = levl[x][y].typ;
93     if (ltyp == ICE || (ltyp == DRAWBRIDGE_UP
94                         && (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE))
95         return TRUE;
96     return FALSE;
97 }
98
99 boolean
100 is_moat(x, y)
101 int x, y;
102 {
103     schar ltyp;
104
105     if (!isok(x, y))
106         return FALSE;
107     ltyp = levl[x][y].typ;
108     if (!Is_juiblex_level(&u.uz)
109         && (ltyp == MOAT
110             || (ltyp == DRAWBRIDGE_UP
111                 && (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT)))
112         return TRUE;
113     return FALSE;
114 }
115
116 schar
117 db_under_typ(mask)
118 int mask;
119 {
120     switch (mask & DB_UNDER) {
121     case DB_ICE:
122         return ICE;
123     case DB_LAVA:
124         return LAVAPOOL;
125     case DB_MOAT:
126         return MOAT;
127     default:
128         return STONE;
129     }
130 }
131
132 /*
133  * We want to know whether a wall (or a door) is the portcullis (passageway)
134  * of an eventual drawbridge.
135  *
136  * Return value:  the direction of the drawbridge.
137  */
138
139 int
140 is_drawbridge_wall(x, y)
141 int x, y;
142 {
143     struct rm *lev;
144
145     lev = &levl[x][y];
146     if (lev->typ != DOOR && lev->typ != DBWALL)
147         return -1;
148
149     if (IS_DRAWBRIDGE(levl[x + 1][y].typ)
150         && (levl[x + 1][y].drawbridgemask & DB_DIR) == DB_WEST)
151         return DB_WEST;
152     if (IS_DRAWBRIDGE(levl[x - 1][y].typ)
153         && (levl[x - 1][y].drawbridgemask & DB_DIR) == DB_EAST)
154         return DB_EAST;
155     if (IS_DRAWBRIDGE(levl[x][y - 1].typ)
156         && (levl[x][y - 1].drawbridgemask & DB_DIR) == DB_SOUTH)
157         return DB_SOUTH;
158     if (IS_DRAWBRIDGE(levl[x][y + 1].typ)
159         && (levl[x][y + 1].drawbridgemask & DB_DIR) == DB_NORTH)
160         return DB_NORTH;
161
162     return -1;
163 }
164
165 /*
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).
169  */
170 boolean
171 is_db_wall(x, y)
172 int x, y;
173 {
174     return (boolean) (levl[x][y].typ == DBWALL);
175 }
176
177 /*
178  * Return true with x,y pointing to the drawbridge if x,y initially indicate
179  * a drawbridge or drawbridge wall.
180  */
181 boolean
182 find_drawbridge(x, y)
183 int *x, *y;
184 {
185     int dir;
186
187     if (IS_DRAWBRIDGE(levl[*x][*y].typ))
188         return TRUE;
189     dir = is_drawbridge_wall(*x, *y);
190     if (dir >= 0) {
191         switch (dir) {
192         case DB_NORTH:
193             (*y)++;
194             break;
195         case DB_SOUTH:
196             (*y)--;
197             break;
198         case DB_EAST:
199             (*x)--;
200             break;
201         case DB_WEST:
202             (*x)++;
203             break;
204         }
205         return TRUE;
206     }
207     return FALSE;
208 }
209
210 /*
211  * Find the drawbridge wall associated with a drawbridge.
212  */
213 STATIC_OVL void
214 get_wall_for_db(x, y)
215 int *x, *y;
216 {
217     switch (levl[*x][*y].drawbridgemask & DB_DIR) {
218     case DB_NORTH:
219         (*y)--;
220         break;
221     case DB_SOUTH:
222         (*y)++;
223         break;
224     case DB_EAST:
225         (*x)++;
226         break;
227     case DB_WEST:
228         (*x)--;
229         break;
230     }
231 }
232
233 /*
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.
237  */
238 boolean
239 create_drawbridge(x, y, dir, flag)
240 int x, y, dir;
241 boolean flag;
242 {
243     int x2, y2;
244     boolean horiz;
245     boolean lava = levl[x][y].typ == LAVAPOOL; /* assume initialized map */
246
247     x2 = x;
248     y2 = y;
249     switch (dir) {
250     case DB_NORTH:
251         horiz = TRUE;
252         y2--;
253         break;
254     case DB_SOUTH:
255         horiz = TRUE;
256         y2++;
257         break;
258     case DB_EAST:
259         horiz = FALSE;
260         x2++;
261         break;
262     default:
263         impossible("bad direction in create_drawbridge");
264         /*FALLTHRU*/
265     case DB_WEST:
266         horiz = FALSE;
267         x2--;
268         break;
269     }
270     if (!IS_WALL(levl[x2][y2].typ))
271         return FALSE;
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;
276     } else {
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;
281     }
282     levl[x][y].horizontal = !horiz;
283     levl[x2][y2].horizontal = horiz;
284     levl[x][y].drawbridgemask = dir;
285     if (lava)
286         levl[x][y].drawbridgemask |= DB_LAVA;
287     return  TRUE;
288 }
289
290 struct entity {
291     struct monst *emon;     /* youmonst for the player */
292     struct permonst *edata; /* must be non-zero for record to be valid */
293     int ex, ey;
294 };
295
296 #define ENTITIES 2
297
298 static NEARDATA struct entity occupants[ENTITIES];
299
300 STATIC_OVL
301 struct entity *
302 e_at(x, y)
303 int x, y;
304 {
305     int entitycnt;
306
307     for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++)
308         if ((occupants[entitycnt].edata) && (occupants[entitycnt].ex == x)
309             && (occupants[entitycnt].ey == y))
310             break;
311     debugpline1("entitycnt = %d", entitycnt);
312 #ifdef D_DEBUG
313     wait_synch();
314 #endif
315     return (entitycnt == ENTITIES) ? (struct entity *) 0
316                                    : &(occupants[entitycnt]);
317 }
318
319 STATIC_OVL void
320 m_to_e(mtmp, x, y, etmp)
321 struct monst *mtmp;
322 int x, y;
323 struct entity *etmp;
324 {
325     etmp->emon = mtmp;
326     if (mtmp) {
327         etmp->ex = x;
328         etmp->ey = y;
329         if (mtmp->wormno && (x != mtmp->mx || y != mtmp->my))
330             etmp->edata = &mons[PM_LONG_WORM_TAIL];
331         else
332             etmp->edata = mtmp->data;
333     } else
334         etmp->edata = (struct permonst *) 0;
335 }
336
337 STATIC_OVL void
338 u_to_e(etmp)
339 struct entity *etmp;
340 {
341     etmp->emon = &youmonst;
342     etmp->ex = u.ux;
343     etmp->ey = u.uy;
344     etmp->edata = youmonst.data;
345 }
346
347 STATIC_OVL void
348 set_entity(x, y, etmp)
349 int x, y;
350 struct entity *etmp;
351 {
352     if ((x == u.ux) && (y == u.uy))
353         u_to_e(etmp);
354     else if (MON_AT(x, y))
355         m_to_e(m_at(x, y), x, y, etmp);
356     else
357         etmp->edata = (struct permonst *) 0;
358 }
359
360 #define is_u(etmp) (etmp->emon == &youmonst)
361 #define e_canseemon(etmp) \
362     (is_u(etmp) ? (boolean) TRUE : canseemon(etmp->emon))
363
364 /*
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.
367  */
368
369 /* #define e_strg(etmp, func) (is_u(etmp)? (char *)0 : func(etmp->emon)) */
370
371 STATIC_OVL const char *
372 e_nam(etmp)
373 struct entity *etmp;
374 {
375 /*JP
376     return is_u(etmp) ? "you" : mon_nam(etmp->emon);
377 */
378     return is_u(etmp) ? "\82 \82È\82½" : mon_nam(etmp->emon);
379 }
380
381 /*
382  * Generates capitalized entity name, makes 2nd -> 3rd person conversion on
383  * verb, where necessary.
384  */
385 STATIC_OVL const char *
386 E_phrase(etmp, verb)
387 struct entity *etmp;
388 const char *verb;
389 {
390     static char wholebuf[80];
391
392 #if 0 /*JP*/
393     Strcpy(wholebuf, is_u(etmp) ? "You" : Monnam(etmp->emon));
394     if (!verb || !*verb)
395         return wholebuf;
396     Strcat(wholebuf, " ");
397     if (is_u(etmp))
398         Strcat(wholebuf, verb);
399     else
400         Strcat(wholebuf, vtense((char *) 0, verb));
401     return wholebuf;
402 #else
403     Strcpy(wholebuf, is_u(etmp) ? "\82 \82È\82½" : Monnam(etmp->emon));
404     return wholebuf;
405 #endif
406 }
407
408 /*
409  * Simple-minded "can it be here?" routine
410  */
411 STATIC_OVL boolean
412 e_survives_at(etmp, x, y)
413 struct entity *etmp;
414 int x, y;
415 {
416     if (noncorporeal(etmp->edata))
417         return TRUE;
418     if (is_pool(x, y))
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 */
425     if (is_lava(x, y))
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));
432     return TRUE;
433 }
434
435 STATIC_OVL void
436 e_died(etmp, xkill_flags, how)
437 struct entity *etmp;
438 int xkill_flags, how;
439 {
440     if (is_u(etmp)) {
441         if (how == DROWNING) {
442             killer.name[0] = 0; /* drown() sets its own killer */
443             (void) drown();
444         } else if (how == BURNING) {
445             killer.name[0] = 0; /* lava_effects() sets own killer */
446             (void) lava_effects();
447         } else {
448             coord xy;
449
450             /* use more specific killer if specified */
451             if (!killer.name[0]) {
452                 killer.format = KILLED_BY_AN;
453 /*JP
454                 Strcpy(killer.name, "falling drawbridge");
455 */
456                 Strcpy(killer.name, "\8d~\82è\82Ä\82«\82½\92µ\82Ë\8b´\82Å");
457             }
458             done(how);
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)) {
462 #if 0 /*JP:T*/
463                     pline("A %s force teleports you away...",
464                           Hallucination ? "normal" : "strange");
465 #else
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È");
468 #endif
469                     teleds(xy.x, xy.y, FALSE);
470                 }
471                 /* otherwise on top of the drawbridge is the
472                  * only viable spot in the dungeon, so stay there
473                  */
474             }
475         }
476         /* we might have crawled out of the moat to survive */
477         etmp->ex = u.ux, etmp->ey = u.uy;
478     } else {
479         int entitycnt;
480
481         killer.name[0] = 0;
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;
492
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;
498         }
499 #undef mk_message
500 #undef mk_corpse
501     }
502 }
503
504 /*
505  * These are never directly affected by a bridge or portcullis.
506  */
507 STATIC_OVL boolean
508 automiss(etmp)
509 struct entity *etmp;
510 {
511     return (boolean) ((is_u(etmp) ? Passes_walls : passes_walls(etmp->edata))
512                       || noncorporeal(etmp->edata));
513 }
514
515 /*
516  * Does falling drawbridge or portcullis miss etmp?
517  */
518 STATIC_OVL boolean
519 e_missed(etmp, chunks)
520 struct entity *etmp;
521 boolean chunks;
522 {
523     int misses;
524
525     if (chunks) {
526         debugpline0("Do chunks miss?");
527     }
528     if (automiss(etmp))
529         return TRUE;
530
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 */
538         misses = 3;
539     else if (chunks && is_pool(etmp->ex, etmp->ey))
540         misses = 2; /* sitting ducks */
541     else
542         misses = 0;
543
544     if (is_db_wall(etmp->ex, etmp->ey))
545         misses -= 3; /* less airspace */
546
547     debugpline1("Miss chance = %d (out of 8)", misses);
548
549     return (misses >= rnd(8)) ? TRUE : FALSE;
550 }
551
552 /*
553  * Can etmp jump from death?
554  */
555 STATIC_OVL boolean
556 e_jumps(etmp)
557 struct entity *etmp;
558 {
559     int tmp = 4; /* out of 10 */
560
561     if (is_u(etmp) ? (Unaware || Fumbling)
562                    : (!etmp->emon->mcanmove || etmp->emon->msleeping
563                       || !etmp->edata->mmove || etmp->emon->wormno))
564         return FALSE;
565
566     if (is_u(etmp) ? Confusion : etmp->emon->mconf)
567         tmp -= 2;
568
569     if (is_u(etmp) ? Stunned : etmp->emon->mstun)
570         tmp -= 3;
571
572     if (is_db_wall(etmp->ex, etmp->ey))
573         tmp -= 2; /* less room to maneuver */
574
575     debugpline2("%s to jump (%d chances in 10)", E_phrase(etmp, "try"), tmp);
576     return (tmp >= rnd(10)) ? TRUE : FALSE;
577 }
578
579 STATIC_OVL void
580 do_entity(etmp)
581 struct entity *etmp;
582 {
583     int newx, newy, at_portcullis, oldx, oldy;
584     boolean must_jump = FALSE, relocates = FALSE, e_inview;
585     struct rm *crm;
586
587     if (!etmp->edata)
588         return;
589
590     e_inview = e_canseemon(etmp);
591     oldx = etmp->ex;
592     oldy = etmp->ey;
593     at_portcullis = is_db_wall(oldx, oldy);
594     crm = &levl[oldx][oldy];
595
596     if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
597         if (e_inview && (at_portcullis || IS_DRAWBRIDGE(crm->typ)))
598 #if 0 /*JP:T*/
599             pline_The("%s passes through %s!",
600                       at_portcullis ? "portcullis" : "drawbridge",
601                       e_nam(etmp));
602 #else
603             pline_The("%s\82Í%s\82ð\92Ê\82è\94²\82¯\82½\81I",
604                       at_portcullis ? "\97\8e\82µ\8ai\8eq" : "\92µ\82Ë\8b´",
605                       e_nam(etmp));
606 #endif
607         if (is_u(etmp))
608             spoteffects(FALSE);
609         return;
610     }
611     if (e_missed(etmp, FALSE)) {
612         if (at_portcullis) {
613 /*JP
614             pline_The("portcullis misses %s!", e_nam(etmp));
615 */
616             pline("\97\8e\82µ\8ai\8eq\82Í%s\82É\96½\92\86\82µ\82È\82©\82Á\82½\81I", e_nam(etmp));
617         } else {
618             debugpline1("The drawbridge misses %s!", e_nam(etmp));
619         }
620         if (e_survives_at(etmp, oldx, oldy)) {
621             return;
622         } else {
623             debugpline0("Mon can't survive here");
624             if (at_portcullis)
625                 must_jump = TRUE;
626             else
627                 relocates = TRUE; /* just ride drawbridge in */
628         }
629     } else {
630         if (crm->typ == DRAWBRIDGE_DOWN) {
631             if (is_u(etmp)) {
632 #if 0 /*JP*/
633                 killer.format = NO_KILLER_PREFIX;
634                 Strcpy(killer.name,
635                        "crushed to death underneath a drawbridge");
636 #else
637                 killer.format = KILLED_BY;
638                 Strcpy(killer.name,
639                        "\92µ\82Ë\8b´\82Ì\89º\95~\82É\82È\82Á\82Ä");
640 #endif
641             }
642 /*JP
643             pline("%s crushed underneath the drawbridge.",
644 */
645             pline("%s\82Í\92µ\82Ë\8b´\82Ì\89º\95~\82É\82È\82Á\82½\81D",
646                   E_phrase(etmp, "are"));             /* no jump */
647             e_died(etmp,
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.  */
654     if (must_jump) {
655         if (at_portcullis) {
656             if (e_jumps(etmp)) {
657                 relocates = TRUE;
658                 debugpline0("Jump succeeds!");
659             } else {
660                 if (e_inview)
661 /*JP
662                     pline("%s crushed by the falling portcullis!",
663 */
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"));
666                 else if (!Deaf)
667 /*JP
668                     You_hear("a crushing sound.");
669 */
670                     You_hear("\89½\82©\82ª\92×\82ê\82é\89¹\82ð\95·\82¢\82½\81D");
671                 e_died(etmp,
672                        XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG
673                                                   : XKILL_NOMSG),
674                        CRUSHING);
675                 /* no corpse */
676                 return;
677             }
678         } else { /* tries to jump off bridge to original square */
679             relocates = !e_jumps(etmp);
680             debugpline1("Jump %s!", (relocates) ? "fails" : "succeeds");
681         }
682     }
683
684     /*
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.
690      */
691     debugpline0("Doing relocation.");
692     newx = oldx;
693     newy = oldy;
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))) {
699         /*
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.
704          */
705         struct entity *other;
706
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"));
712         } else {
713             debugpline1("Handling %s", e_nam(other));
714             while ((e_at(newx, newy) != 0) && (e_at(newx, newy) != etmp))
715                 do_entity(other);
716             debugpline1("Checking existence of %s", e_nam(etmp));
717 #ifdef D_DEBUG
718             wait_synch();
719 #endif
720             if (e_at(oldx, oldy) != etmp) {
721                 debugpline1("%s moved or died in recursion somewhere",
722                             E_phrase(etmp, "have"));
723 #ifdef D_DEBUG
724                 wait_synch();
725 #endif
726                 return;
727             }
728         }
729     }
730     if (relocates && !e_at(newx, newy)) { /* if e_at() entity = worm tail */
731         debugpline1("Moving %s", e_nam(etmp));
732         if (!is_u(etmp)) {
733             remove_monster(etmp->ex, etmp->ey);
734             place_monster(etmp->emon, newx, newy);
735             update_monster_region(etmp->emon);
736         } else {
737             u.ux = newx;
738             u.uy = newy;
739         }
740         etmp->ex = newx;
741         etmp->ey = newy;
742         e_inview = e_canseemon(etmp);
743     }
744     debugpline1("Final disposition of %s", e_nam(etmp));
745 #ifdef D_DEBUG
746     wait_synch();
747 #endif
748     if (is_db_wall(etmp->ex, etmp->ey)) {
749         debugpline1("%s in portcullis chamber", E_phrase(etmp, "are"));
750 #ifdef D_DEBUG
751         wait_synch();
752 #endif
753         if (e_inview) {
754             if (is_u(etmp)) {
755 /*JP
756                 You("tumble towards the closed portcullis!");
757 */
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");
759                 if (automiss(etmp))
760 /*JP
761                     You("pass through it!");
762 */
763                     You("\92Ê\82è\82Ê\82¯\82½\81I");
764                 else
765 /*JP
766                     pline_The("drawbridge closes in...");
767 */
768                     pline_The("\92µ\82Ë\8b´\82Í\95Â\82\82½\81D\81D\81D");
769             } else
770 /*JP
771                 pline("%s behind the drawbridge.",
772 */
773                 pline("%s\82Í\92µ\82Ë\8b´\82Ì\97 \82É\88Ú\93®\82µ\82½\81D",
774                       E_phrase(etmp, "disappear"));
775         }
776         if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
777             killer.format = KILLED_BY_AN;
778 /*JP
779             Strcpy(killer.name, "closing drawbridge");
780 */
781             Strcpy(killer.name, "\95Â\82\82Ä\82¢\82­\92µ\82Ë\8b´\82É\8b·\82Ü\82ê\82Ä");
782             e_died(etmp, XKILL_NOMSG, CRUSHING);
783             return;
784         }
785         debugpline1("%s in here", E_phrase(etmp, "survive"));
786     } else {
787         debugpline1("%s on drawbridge square", E_phrase(etmp, "are"));
788         if (is_pool(etmp->ex, etmp->ey) && !e_inview)
789             if (!Deaf)
790 /*JP
791                 You_hear("a splash.");
792 */
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))
797 /*JP
798                 pline("%s from the bridge.", E_phrase(etmp, "fall"));
799 */
800                 pline("%s\82Í\8b´\82©\82ç\97\8e\82¿\82½\81D", E_phrase(etmp, "fall"));
801             return;
802         }
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);
809
810                 if (Hallucination)
811 #if 0 /*JP:T*/
812                     pline("%s the %s and disappears.",
813                           E_phrase(etmp, "drink"), lava ? "lava" : "moat");
814 #else
815                     pline("%s\82Í%s\82ð\88ù\82Ý\81C\8fÁ\82¦\82½\81D",
816                           E_phrase(etmp, "drink"), lava ? "\97n\8aâ" : "\96x");
817 #endif
818                 else
819 #if 0 /*JP:T*/
820                     pline("%s into the %s.", E_phrase(etmp, "fall"),
821                           lava ? hliquid("lava") : "moat");
822 #else
823                     pline("%s\82Í%s\82Ì\92\86\82É\97\8e\82¿\82½\81D", E_phrase(etmp, "fall"),
824                           lava ? hliquid("\97n\8aâ") : "\96x");
825 #endif
826             }
827 #if 0 /*JP:T*/
828         killer.format = NO_KILLER_PREFIX;
829         Strcpy(killer.name, "fell from a drawbridge");
830 #else
831         killer.format = KILLED_BY;
832         Strcpy(killer.name, "\92µ\82Ë\8b´\82©\82ç\97\8e\82¿\82Ä");
833 #endif
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*/
839         return;
840     }
841 }
842
843 /* clear stale reason for death before returning */
844 #define nokiller() (killer.name[0] = '\0', killer.format = 0)
845
846 /*
847  * Close the drawbridge located at x,y
848  */
849 void
850 close_drawbridge(x, y)
851 int x, y;
852 {
853     register struct rm *lev1, *lev2;
854     struct trap *t;
855     int x2, y2;
856
857     lev1 = &levl[x][y];
858     if (lev1->typ != DRAWBRIDGE_DOWN)
859         return;
860     x2 = x;
861     y2 = y;
862     get_wall_for_db(&x2, &y2);
863     if (cansee(x, y) || cansee(x2, y2))
864 #if 0 /*JP*/
865         You_see("a drawbridge %s up!",
866                 (((u.ux == x || u.uy == y) && !Underwater)
867                  || distu(x2, y2) < distu(x, y))
868                     ? "coming"
869                     : "going");
870 #else
871         pline("\92µ\82Ë\8b´\82ª\8fã\82ª\82Á\82Ä\82¢\82­\82Ì\82ª\8c©\82¦\82½\81I");
872 #endif
873     else /* "5 gears turn" for castle drawbridge tune */
874 /*JP
875         You_hear("chains rattling and gears turning.");
876 */
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];
880     lev2->typ = DBWALL;
881     switch (lev1->drawbridgemask & DB_DIR) {
882     case DB_NORTH:
883     case DB_SOUTH:
884         lev2->horizontal = TRUE;
885         break;
886     case DB_WEST:
887     case DB_EAST:
888         lev2->horizontal = FALSE;
889         break;
890     }
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)
898 /*JP
899         You_hear("smashing and crushing.");
900 */
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);
904     delallobj(x, y);
905     delallobj(x2, y2);
906     if ((t = t_at(x, y)) != 0)
907         deltrap(t);
908     if ((t = t_at(x2, y2)) != 0)
909         deltrap(t);
910     del_engr_at(x, y);
911     del_engr_at(x2, y2);
912     newsym(x, y);
913     newsym(x2, y2);
914     block_point(x2, y2); /* vision */
915     nokiller();
916 }
917
918 /*
919  * Open the drawbridge located at x,y
920  */
921 void
922 open_drawbridge(x, y)
923 int x, y;
924 {
925     register struct rm *lev1, *lev2;
926     struct trap *t;
927     int x2, y2;
928
929     lev1 = &levl[x][y];
930     if (lev1->typ != DRAWBRIDGE_UP)
931         return;
932     x2 = x;
933     y2 = y;
934     get_wall_for_db(&x2, &y2);
935     if (cansee(x, y) || cansee(x2, y2))
936 #if 0 /*JP*/
937         You_see("a drawbridge %s down!",
938                 (distu(x2, y2) < distu(x, y)) ? "going" : "coming");
939 #else
940         pline("\92µ\82Ë\8b´\82ª\89º\82ª\82é\82Ì\82ª\8c©\82¦\82½\81I");
941 #endif
942     else /* "5 gears turn" for castle drawbridge tune */
943 /*JP
944         You_hear("gears turning and chains rattling.");
945 */
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];
949     lev2->typ = DOOR;
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);
957     delallobj(x, y);
958     if ((t = t_at(x, y)) != 0)
959         deltrap(t);
960     if ((t = t_at(x2, y2)) != 0)
961         deltrap(t);
962     del_engr_at(x, y);
963     del_engr_at(x2, y2);
964     newsym(x, y);
965     newsym(x2, y2);
966     unblock_point(x2, y2); /* vision */
967     if (Is_stronghold(&u.uz))
968         u.uevent.uopened_dbridge = TRUE;
969     nokiller();
970 }
971
972 /*
973  * Let's destroy the drawbridge located at x,y
974  */
975 void
976 destroy_drawbridge(x, y)
977 int x, y;
978 {
979     register struct rm *lev1, *lev2;
980     struct trap *t;
981     struct obj *otmp;
982     int x2, y2, i;
983     boolean e_inview;
984     struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);
985
986     lev1 = &levl[x][y];
987     if (!IS_DRAWBRIDGE(lev1->typ))
988         return;
989     x2 = x;
990     y2 = y;
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) {
995         struct obj *otmp2;
996         boolean lava = (lev1->drawbridgemask & DB_UNDER) == DB_LAVA;
997
998         if (lev1->typ == DRAWBRIDGE_UP) {
999             if (cansee(x2, y2))
1000 #if 0 /*JP:T*/
1001                 pline_The("portcullis of the drawbridge falls into the %s!",
1002                           lava ? hliquid("lava") : "moat");
1003 #else
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");
1006 #endif
1007             else if (!Deaf)
1008 /*JP
1009                 You_hear("a loud *SPLASH*!");
1010 */
1011                 You_hear("\91å\82«\82È\83o\83b\83V\83\83\81[\83\93\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81I");
1012         } else {
1013             if (cansee(x, y))
1014 #if 0 /*JP:T*/
1015                 pline_The("drawbridge collapses into the %s!",
1016                           lava ? hliquid("lava") : "moat");
1017 #else
1018                 pline("\92µ\82Ë\8b´\82Í%s\82É\82­\82¸\82ê\97\8e\82¿\82½\81I",
1019                           lava ? hliquid("\97n\8aâ") : "\96x");
1020 #endif
1021             else if (!Deaf)
1022 /*JP
1023                 You_hear("a loud *SPLASH*!");
1024 */
1025                 You_hear("\91å\82«\82È\83o\83b\83V\83\83\81[\83\93\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81I");
1026         }
1027         lev1->typ = lava ? LAVAPOOL : MOAT;
1028         lev1->drawbridgemask = 0;
1029         if ((otmp2 = sobj_at(BOULDER, x, y)) != 0) {
1030             obj_extract_self(otmp2);
1031 /*JP
1032             (void) flooreffects(otmp2, x, y, "fall");
1033 */
1034             (void) flooreffects(otmp2, x, y, "\97\8e\82¿\82é");
1035         }
1036     } else {
1037         if (cansee(x, y))
1038 /*JP
1039             pline_The("drawbridge disintegrates!");
1040 */
1041             pline("\92µ\82Ë\8b´\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81I");
1042         else
1043 /*JP
1044             You_hear("a loud *CRASH*!");
1045 */
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);
1049     }
1050     wake_nearto(x, y, 500);
1051     lev2->typ = DOOR;
1052     lev2->doormask = D_NODOOR;
1053     if ((t = t_at(x, y)) != 0)
1054         deltrap(t);
1055     if ((t = t_at(x2, y2)) != 0)
1056         deltrap(t);
1057     del_engr_at(x, y);
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,
1064                          FALSE);
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);
1068     }
1069     newsym(x, y);
1070     newsym(x2, y2);
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;
1075
1076     set_entity(x2, y2, etmp2); /* currently only automissers can be here */
1077     if (etmp2->edata) {
1078         e_inview = e_canseemon(etmp2);
1079         if (!automiss(etmp2)) {
1080             if (e_inview)
1081 /*JP
1082                 pline("%s blown apart by flying debris.",
1083 */
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;
1087 /*JP
1088             Strcpy(killer.name, "exploding drawbridge");
1089 */
1090             Strcpy(killer.name, "\92µ\82Ë\8b´\82Ì\94\9a\94­\82Å");
1091             e_died(etmp2,
1092                    XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
1093                    CRUSHING); /*no corpse*/
1094         } /* nothing which is vulnerable can survive this */
1095     }
1096     set_entity(x, y, etmp1);
1097     if (etmp1->edata) {
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 */
1102             if (is_u(etmp1))
1103                 spoteffects(FALSE);
1104             else
1105                 (void) minliquid(etmp1->emon);
1106         } else {
1107             if (e_inview) {
1108                 if (!is_u(etmp1) && Hallucination)
1109 /*JP
1110                     pline("%s into some heavy metal!",
1111 */
1112                     pline("%s\82Í\8fd\8bà\91®\82É\96\84\82à\82ê\82½\81I",
1113                           E_phrase(etmp1, "get"));
1114                 else
1115 /*JP
1116                     pline("%s hit by a huge chunk of metal!",
1117 */
1118                     pline("\91å\82«\82È\93S\82Ì\89ò\82ª%s\82É\96½\92\86\82µ\82½\81I",
1119                           E_phrase(etmp1, "are"));
1120             } else {
1121                 if (!Deaf && !is_u(etmp1) && !is_pool(x, y)) {
1122 /*JP
1123                     You_hear("a crushing sound.");
1124 */
1125                     You_hear("\83K\83\89\83\93\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
1126                 } else {
1127                     debugpline1("%s from shrapnel", E_phrase(etmp1, "die"));
1128                 }
1129             }
1130             killer.format = KILLED_BY_AN;
1131 /*JP
1132             Strcpy(killer.name, "collapsing drawbridge");
1133 */
1134             Strcpy(killer.name, "\83o\83\89\83o\83\89\82É\82È\82Á\82½\92µ\82Ë\8b´\82Å");
1135             e_died(etmp1,
1136                    XKILL_NOCORPSE | (e_inview ? XKILL_GIVEMSG : XKILL_NOMSG),
1137                    CRUSHING); /*no corpse*/
1138             if (levl[etmp1->ex][etmp1->ey].typ == MOAT)
1139                 do_entity(etmp1);
1140         }
1141     }
1142     nokiller();
1143 }
1144
1145 /*dbridge.c*/