OSDN Git Service

fix #36579
[jnethack/source.git] / src / hack.c
1 /* NetHack 3.6  hack.c  $NHDT-Date: 1446604111 2015/11/04 02:28:31 $  $NHDT-Branch: master $:$NHDT-Revision: 1.155 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016            */
8 /* JNetHack may be freely redistributed.  See license for details. */
9
10 #include "hack.h"
11
12 /* #define DEBUG */ /* uncomment for debugging */
13
14 STATIC_DCL void NDECL(maybe_wail);
15 STATIC_DCL int NDECL(moverock);
16 STATIC_DCL int FDECL(still_chewing, (XCHAR_P, XCHAR_P));
17 STATIC_DCL void NDECL(dosinkfall);
18 STATIC_DCL boolean FDECL(findtravelpath, (BOOLEAN_P));
19 STATIC_DCL boolean FDECL(trapmove, (int, int, struct trap *));
20 STATIC_DCL void NDECL(switch_terrain);
21 STATIC_DCL struct monst *FDECL(monstinroom, (struct permonst *, int));
22 STATIC_DCL boolean FDECL(doorless_door, (int, int));
23 STATIC_DCL void FDECL(move_update, (BOOLEAN_P));
24
25 #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
26
27 static anything tmp_anything;
28
29 anything *
30 uint_to_any(ui)
31 unsigned ui;
32 {
33     tmp_anything = zeroany;
34     tmp_anything.a_uint = ui;
35     return &tmp_anything;
36 }
37
38 anything *
39 long_to_any(lng)
40 long lng;
41 {
42     tmp_anything = zeroany;
43     tmp_anything.a_long = lng;
44     return &tmp_anything;
45 }
46
47 anything *
48 monst_to_any(mtmp)
49 struct monst *mtmp;
50 {
51     tmp_anything = zeroany;
52     tmp_anything.a_monst = mtmp;
53     return &tmp_anything;
54 }
55
56 anything *
57 obj_to_any(obj)
58 struct obj *obj;
59 {
60     tmp_anything = zeroany;
61     tmp_anything.a_obj = obj;
62     return &tmp_anything;
63 }
64
65 boolean
66 revive_nasty(x, y, msg)
67 int x, y;
68 const char *msg;
69 {
70     register struct obj *otmp, *otmp2;
71     struct monst *mtmp;
72     coord cc;
73     boolean revived = FALSE;
74
75     for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
76         otmp2 = otmp->nexthere;
77         if (otmp->otyp == CORPSE
78             && (is_rider(&mons[otmp->corpsenm])
79                 || otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
80             /* move any living monster already at that location */
81             if ((mtmp = m_at(x, y)) && enexto(&cc, x, y, mtmp->data))
82                 rloc_to(mtmp, cc.x, cc.y);
83             if (msg)
84                 Norep("%s", msg);
85             revived = revive_corpse(otmp);
86         }
87     }
88
89     /* this location might not be safe, if not, move revived monster */
90     if (revived) {
91         mtmp = m_at(x, y);
92         if (mtmp && !goodpos(x, y, mtmp, 0)
93             && enexto(&cc, x, y, mtmp->data)) {
94             rloc_to(mtmp, cc.x, cc.y);
95         }
96         /* else impossible? */
97     }
98
99     return revived;
100 }
101
102 STATIC_OVL int
103 moverock()
104 {
105     register xchar rx, ry, sx, sy;
106     register struct obj *otmp;
107     register struct trap *ttmp;
108     register struct monst *mtmp;
109
110     sx = u.ux + u.dx, sy = u.uy + u.dy; /* boulder starting position */
111     while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
112         /* make sure that this boulder is visible as the top object */
113         if (otmp != level.objects[sx][sy])
114             movobj(otmp, sx, sy);
115
116         rx = u.ux + 2 * u.dx; /* boulder destination position */
117         ry = u.uy + 2 * u.dy;
118         nomul(0);
119         if (Levitation || Is_airlevel(&u.uz)) {
120             if (Blind)
121                 feel_location(sx, sy);
122 /*JP
123             You("don't have enough leverage to push %s.", the(xname(otmp)));
124 */
125             You("\91Ì\82ª\95\82\82¢\82Ä\82¢\82é\82Ì\82Å%s\82ð\89\9f\82¹\82È\82¢\81D", the(xname(otmp)));
126             /* Give them a chance to climb over it? */
127             return -1;
128         }
129         if (verysmall(youmonst.data) && !u.usteed) {
130             if (Blind)
131                 feel_location(sx, sy);
132 /*JP
133             pline("You're too small to push that %s.", xname(otmp));
134 */
135             You("\8f¬\82³\82·\82¬\82Ä%s\82ð\89\9f\82¹\82È\82¢\81D",xname(otmp));
136             goto cannot_push;
137         }
138         if (isok(rx, ry) && !IS_ROCK(levl[rx][ry].typ)
139             && levl[rx][ry].typ != IRONBARS
140             && (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy)
141                 || doorless_door(rx, ry)) && !sobj_at(BOULDER, rx, ry)) {
142             ttmp = t_at(rx, ry);
143             mtmp = m_at(rx, ry);
144
145             /* KMH -- Sokoban doesn't let you push boulders diagonally */
146             if (Sokoban && u.dx && u.dy) {
147                 if (Blind)
148                     feel_location(sx, sy);
149 /*JP
150                 pline("%s won't roll diagonally on this %s.",
151 */
152                 pline("%s\82Ì\8fã\82Å\82Í%s\82Í\8eÎ\82ß\82É\89\9f\82¹\82È\82¢\81D",
153                       The(xname(otmp)), surface(sx, sy));
154                 goto cannot_push;
155             }
156
157 /*JP
158             if (revive_nasty(rx, ry, "You sense movement on the other side."))
159 */
160             if (revive_nasty(rx, ry, "\94½\91Î\91¤\82É\93®\82«\82ð\8a´\82\82½\81D"))
161                 return -1;
162
163             if (mtmp && !noncorporeal(mtmp->data)
164                 && (!mtmp->mtrapped
165                     || !(ttmp && ((ttmp->ttyp == PIT)
166                                   || (ttmp->ttyp == SPIKED_PIT))))) {
167                 if (Blind)
168                     feel_location(sx, sy);
169                 if (canspotmon(mtmp))
170 /*JP
171                     pline("There's %s on the other side.", a_monnam(mtmp));
172 */
173                     pline("\94½\91Î\91¤\82É%s\82ª\82¢\82é\81D", a_monnam(mtmp));
174                 else {
175 /*JP
176                     You_hear("a monster behind %s.", the(xname(otmp)));
177 */
178                     pline("%s\82Ì\94w\8cã\82É\89ö\95¨\82Ì\8bC\94z\82ª\82·\82é\81D", the(xname(otmp)));
179                     map_invisible(rx, ry);
180                 }
181                 if (flags.verbose)
182 #if 0 /*JP*/
183                     pline("Perhaps that's why %s cannot move it.",
184                           u.usteed ? y_monnam(u.usteed) : "you");
185 #else
186                     pline("\82½\82Ô\82ñ\82±\82ê\82ª\81C\8aâ\82ð\93®\82©\82¹\82È\82¢\97\9d\97R\82¾\81D");
187 #endif
188                 goto cannot_push;
189             }
190
191             if (ttmp) {
192                 /* if a trap operates on the boulder, don't attempt
193                    to move any others at this location; return -1
194                    if another boulder is in hero's way, or 0 if he
195                    should advance to the vacated boulder position */
196                 switch (ttmp->ttyp) {
197                 case LANDMINE:
198                     if (rn2(10)) {
199                         obj_extract_self(otmp);
200                         place_object(otmp, rx, ry);
201                         newsym(sx, sy);
202 #if 0 /*JP*/
203                         pline("KAABLAMM!!!  %s %s land mine.",
204                               Tobjnam(otmp, "trigger"),
205                               ttmp->madeby_u ? "your" : "a");
206 #else
207                         pline("\82¿\82ã\82Ç\81[\82ñ\81I\81I%s\82Å%s\92n\97\8b\82Ì\8bN\94\9a\83X\83C\83b\83`\82ª\93ü\82Á\82½\81D",
208                               xname(otmp),
209                               ttmp->madeby_u ? "\82 \82È\82½\82Ì\8ed\8a|\82¯\82½" : "");
210 #endif
211                         blow_up_landmine(ttmp);
212                         /* if the boulder remains, it should fill the pit */
213                         fill_pit(u.ux, u.uy);
214                         if (cansee(rx, ry))
215                             newsym(rx, ry);
216                         return sobj_at(BOULDER, sx, sy) ? -1 : 0;
217                     }
218                     break;
219                 case SPIKED_PIT:
220                 case PIT:
221                     obj_extract_self(otmp);
222                     /* vision kludge to get messages right;
223                        the pit will temporarily be seen even
224                        if this is one among multiple boulders */
225                     if (!Blind)
226                         viz_array[ry][rx] |= IN_SIGHT;
227 /*JP
228                     if (!flooreffects(otmp, rx, ry, "fall")) {
229 */
230                     if (!flooreffects(otmp, rx, ry, "\97\8e\82¿\82é")) {
231                         place_object(otmp, rx, ry);
232                     }
233                     if (mtmp && !Blind)
234                         newsym(rx, ry);
235                     return sobj_at(BOULDER, sx, sy) ? -1 : 0;
236                 case HOLE:
237                 case TRAPDOOR:
238                     if (Blind)
239 /*JP
240                         pline("Kerplunk!  You no longer feel %s.",
241 */
242                         pline("\83h\83T\83b\81I\82 \82È\82½\82Í\82à\82¤%s\82ð\8a´\82\82ç\82ê\82È\82¢\81D",
243                               the(xname(otmp)));
244                     else
245 #if 0 /*JP*/
246                         pline("%s%s and %s a %s in the %s!",
247                               Tobjnam(otmp, (ttmp->ttyp == TRAPDOOR)
248                                                 ? "trigger"
249                                                 : "fall"),
250                               (ttmp->ttyp == TRAPDOOR) ? "" : " into",
251                               otense(otmp, "plug"),
252                               (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
253                               surface(rx, ry));
254 #else
255                         pline("%s\82Í\97\8e\82¿\82Ä%s\82Ì%s\82ð\96\84\82ß\82½\81I",
256                               xname(otmp),
257                               surface(rx, ry),
258                               (ttmp->ttyp == TRAPDOOR) ? "\97\8e\82µ\94à" : "\8c\8a");
259 #endif
260                     deltrap(ttmp);
261                     delobj(otmp);
262                     bury_objs(rx, ry);
263                     levl[rx][ry].wall_info &= ~W_NONDIGGABLE;
264                     levl[rx][ry].candig = 1;
265                     if (cansee(rx, ry))
266                         newsym(rx, ry);
267                     return sobj_at(BOULDER, sx, sy) ? -1 : 0;
268                 case LEVEL_TELEP:
269                 case TELEP_TRAP: {
270                     int newlev = 0; /* lint suppression */
271                     d_level dest;
272
273                     if (ttmp->ttyp == LEVEL_TELEP) {
274                         newlev = random_teleport_level();
275                         if (newlev == depth(&u.uz) || In_endgame(&u.uz))
276                             /* trap didn't work; skip "disappears" message */
277                             goto dopush;
278                     }
279                     if (u.usteed)
280 /*JP
281                         pline("%s pushes %s and suddenly it disappears!",
282 */
283                         pline("%s\82ª%s\82ð\89\9f\82·\82Æ\81C\93Ë\91R\82»\82ê\82Í\8fÁ\96Å\82µ\82½\81I",
284                               upstart(y_monnam(u.usteed)), the(xname(otmp)));
285                     else
286 /*JP
287                         You("push %s and suddenly it disappears!",
288 */
289                         pline("\82 \82È\82½\82ª%s\82ð\89\9f\82·\82Æ\81C\93Ë\91R\82»\82ê\82Í\8fÁ\96Å\82µ\82½\81I",
290                             the(xname(otmp)));
291                     if (ttmp->ttyp == TELEP_TRAP) {
292                         (void) rloco(otmp);
293                     } else {
294                         obj_extract_self(otmp);
295                         add_to_migration(otmp);
296                         get_level(&dest, newlev);
297                         otmp->ox = dest.dnum;
298                         otmp->oy = dest.dlevel;
299                         otmp->owornmask = (long) MIGR_RANDOM;
300                     }
301                     seetrap(ttmp);
302                     return sobj_at(BOULDER, sx, sy) ? -1 : 0;
303                 }
304                 default:
305                     break; /* boulder not affected by this trap */
306                 }
307             }
308
309             if (closed_door(rx, ry))
310                 goto nopushmsg;
311             if (boulder_hits_pool(otmp, rx, ry, TRUE))
312                 continue;
313             /*
314              * Re-link at top of fobj chain so that pile order is preserved
315              * when level is restored.
316              */
317             if (otmp != fobj) {
318                 remove_object(otmp);
319                 place_object(otmp, otmp->ox, otmp->oy);
320             }
321
322             {
323 #ifdef LINT /* static long lastmovetime; */
324                 long lastmovetime;
325                 lastmovetime = 0;
326 #else
327                 /* note: reset to zero after save/restore cycle */
328                 static NEARDATA long lastmovetime;
329 #endif
330             dopush:
331                 if (!u.usteed) {
332                     if (moves > lastmovetime + 2 || moves < lastmovetime)
333 #if 0 /*JP*/
334                         pline("With %s effort you move %s.",
335                               throws_rocks(youmonst.data) ? "little"
336                                                           : "great",
337                               the(xname(otmp)));
338 #else
339                         pline("%s\97Í\82ð\82±\82ß\82Ä%s\82ð\89\9f\82µ\82½\81D",
340                               throws_rocks(youmonst.data) ? "\8f­\82µ" : "\82©\82È\82è",
341                               the(xname(otmp)));
342 #endif
343                     exercise(A_STR, TRUE);
344                 } else
345 #if 0 /*JP*/
346                     pline("%s moves %s.", upstart(y_monnam(u.usteed)),
347                           the(xname(otmp)));
348 #else
349                     pline("%s\82Í%s\82ð\93®\82©\82µ\82½\81D", upstart(y_monnam(u.usteed)),
350                           xname(otmp));
351 #endif
352                 lastmovetime = moves;
353             }
354
355             /* Move the boulder *after* the message. */
356             if (glyph_is_invisible(levl[rx][ry].glyph))
357                 unmap_object(rx, ry);
358             movobj(otmp, rx, ry); /* does newsym(rx,ry) */
359             if (Blind) {
360                 feel_location(rx, ry);
361                 feel_location(sx, sy);
362             } else {
363                 newsym(sx, sy);
364             }
365         } else {
366         nopushmsg:
367             if (u.usteed)
368 #if 0 /*JP*/
369                 pline("%s tries to move %s, but cannot.",
370                       upstart(y_monnam(u.usteed)), the(xname(otmp)));
371 #else
372                 pline("%s\82Í%s\82ð\93®\82©\82»\82¤\82Æ\82µ\82½\82ª\8fo\97\88\82È\82©\82Á\82½\81D",
373                       upstart(y_monnam(u.usteed)), the(xname(otmp)));
374 #endif
375             else
376 /*JP
377                 You("try to move %s, but in vain.", the(xname(otmp)));
378 */
379                 You("%s\82ð\93®\82©\82»\82¤\82Æ\82µ\82½\82ª\81C\82¾\82ß\82¾\82Á\82½\81D", the(xname(otmp)));
380             if (Blind)
381                 feel_location(sx, sy);
382         cannot_push:
383             if (throws_rocks(youmonst.data)) {
384                 if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
385 #if 0 /*JP*/
386                     You("aren't skilled enough to %s %s from %s.",
387                         (flags.pickup && !Sokoban) ? "pick up" : "push aside",
388                         the(xname(otmp)), y_monnam(u.usteed));
389 #else
390                     You("%s\82É%s\82ð%s\82é\82Ù\82Ç\8bZ\97Ê\82ª\82È\82¢\81D",
391                         y_monnam(u.usteed),
392                         the(xname(otmp)), 
393                         (flags.pickup && !Sokoban) ? "\8fE\82í\82¹" : "\89\9f\82³\82¹");
394 #endif
395                 } else {
396 #if 0 /*JP*/
397                     pline("However, you can easily %s.",
398                           (flags.pickup && !Sokoban) ? "pick it up"
399                                                      : "push it aside");
400 #else
401                     pline("\82µ\82©\82µ\81C\82 \82È\82½\82Í\8aÈ\92P\82É\82»\82ê\82ð%s\81D",
402                           (flags.pickup && !Sokoban)
403                           ? "\8fE\82¦\82½" : "\95Ê\82Ì\95û\82É\89\9f\82¹\82½");
404 #endif
405                     sokoban_guilt();
406                     break;
407                 }
408                 break;
409             }
410
411             if (!u.usteed
412                 && (((!invent || inv_weight() <= -850)
413                      && (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ)
414                                             && IS_ROCK(levl[sx][u.uy].typ))))
415                     || verysmall(youmonst.data))) {
416                 pline(
417 /*JP
418                    "However, you can squeeze yourself into a small opening.");
419 */
420                     "\82µ\82©\82µ\81C\82 \82È\82½\82Í\8f¬\82³\82¢\8c\84\8aÔ\82É\82±\82\93ü\82Á\82½\81D");
421                 sokoban_guilt();
422                 break;
423             } else
424                 return -1;
425         }
426     }
427     return 0;
428 }
429
430 /*
431  *  still_chewing()
432  *
433  *  Chew on a wall, door, or boulder.  Returns TRUE if still eating, FALSE
434  *  when done.
435  */
436 STATIC_OVL int
437 still_chewing(x, y)
438 xchar x, y;
439 {
440     struct rm *lev = &levl[x][y];
441     struct obj *boulder = sobj_at(BOULDER, x, y);
442     const char *digtxt = (char *) 0, *dmgtxt = (char *) 0;
443
444     if (context.digging.down) /* not continuing previous dig (w/ pick-axe) */
445         (void) memset((genericptr_t) &context.digging, 0,
446                       sizeof(struct dig_info));
447
448     if (!boulder && IS_ROCK(lev->typ) && !may_dig(x, y)) {
449 #if 0 /*JP*/
450         You("hurt your teeth on the %s.",
451             (lev->typ == IRONBARS)
452                 ? "bars"
453                 : IS_TREE(lev->typ)
454                     ? "tree"
455                     : "hard stone");
456 #else
457         You("%s\82Å\8e\95\82ð\92É\82ß\82½\81D",
458             (lev->typ == IRONBARS)
459             ? "\93S\82Ì\96_"
460             : IS_TREE(lev->typ)
461                 ? "\96Ø"
462                 : "\8cÅ\82¢\8aâ");
463 #endif
464         nomul(0);
465         return 1;
466     } else if (context.digging.pos.x != x || context.digging.pos.y != y
467                || !on_level(&context.digging.level, &u.uz)) {
468         context.digging.down = FALSE;
469         context.digging.chew = TRUE;
470         context.digging.warned = FALSE;
471         context.digging.pos.x = x;
472         context.digging.pos.y = y;
473         assign_level(&context.digging.level, &u.uz);
474         /* solid rock takes more work & time to dig through */
475         context.digging.effort =
476             (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc;
477 #if 0 /*JP*/
478         You("start chewing %s %s.",
479             (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
480                 ? "on a"
481                 : "a hole in the",
482             boulder
483                 ? "boulder"
484                 : IS_TREE(lev->typ)
485                     ? "tree"
486                     : IS_ROCK(lev->typ)
487                         ? "rock"
488                         : lev->typ == IRONBARS
489                             ? "bar"
490                             : "door");
491 #else
492         You("%s%s\82Í\82\82ß\82½\81D",
493             boulder
494             ? "\8aâ"
495             : IS_TREE(lev->typ)
496               ? "\96Ø"
497               : IS_ROCK(lev->typ)
498                 ? "\90Î"
499                 : lev->typ == IRONBARS
500                   ? "\93S\82Ì\96_"
501                   : "\94à",
502             (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
503               ? "\82ð\8a\9a\82Ý"
504               : "\82É\8c\8a\82ð\82 \82¯");
505 #endif
506         watch_dig((struct monst *) 0, x, y, FALSE);
507         return 1;
508     } else if ((context.digging.effort += (30 + u.udaminc)) <= 100) {
509         if (flags.verbose)
510 #if 0 /*JP*/
511             You("%s chewing on the %s.",
512                 context.digging.chew ? "continue" : "begin",
513                 boulder
514                     ? "boulder"
515                     : IS_TREE(lev->typ)
516                         ? "tree"
517                         : IS_ROCK(lev->typ)
518                             ? "rock"
519                             : (lev->typ == IRONBARS)
520                                 ? "bars"
521                                 : "door");
522 #else
523             You("%s\82ð\8a\9a\82Ý%s\81D",
524                 boulder
525                 ? "\8aâ"
526                 : IS_TREE(lev->typ)
527                   ? "\96Ø"
528                   : IS_ROCK(lev->typ)
529                     ? "\90Î"
530                     : lev->typ == IRONBARS
531                       ? "\93S\82Ì\96_"
532                       : "\94à",
533                 context.digging.chew ? "\91±\82¯\82½" : "\82Í\82\82ß\82½");
534 #endif
535         context.digging.chew = TRUE;
536         watch_dig((struct monst *) 0, x, y, FALSE);
537         return 1;
538     }
539
540     /* Okay, you've chewed through something */
541     u.uconduct.food++;
542     u.uhunger += rnd(20);
543
544     if (boulder) {
545         delobj(boulder);         /* boulder goes bye-bye */
546 #if 0 /*JP*/
547         You("eat the boulder."); /* yum */
548 #else
549         You("\8aâ\82ð\90H\82×\82½\81D"); /* yum */
550 #endif
551
552         /*
553          *  The location could still block because of
554          *      1. More than one boulder
555          *      2. Boulder stuck in a wall/stone/door.
556          *
557          *  [perhaps use does_block() below (from vision.c)]
558          */
559         if (IS_ROCK(lev->typ) || closed_door(x, y)
560             || sobj_at(BOULDER, x, y)) {
561             block_point(x, y); /* delobj will unblock the point */
562             /* reset dig state */
563             (void) memset((genericptr_t) &context.digging, 0,
564                           sizeof(struct dig_info));
565             return 1;
566         }
567
568     } else if (IS_WALL(lev->typ)) {
569         if (*in_rooms(x, y, SHOPBASE)) {
570             add_damage(x, y, 10L * ACURRSTR);
571 /*JP
572             dmgtxt = "damage";
573 */
574             dmgtxt = "\8f\9d\82Â\82¯\82é";
575         }
576 /*JP
577         digtxt = "chew a hole in the wall.";
578 */
579         digtxt = "\95Ç\82É\8c\8a\82ð\8aJ\82¯\82½\81D";
580         if (level.flags.is_maze_lev) {
581             lev->typ = ROOM;
582         } else if (level.flags.is_cavernous_lev && !in_town(x, y)) {
583             lev->typ = CORR;
584         } else {
585             lev->typ = DOOR;
586             lev->doormask = D_NODOOR;
587         }
588     } else if (IS_TREE(lev->typ)) {
589 /*JP
590         digtxt = "chew through the tree.";
591 */
592         digtxt = "\96Ø\82É\8c\8a\82ð\8aJ\82¯\82½\81D";
593         lev->typ = ROOM;
594     } else if (lev->typ == IRONBARS) {
595 /*JP
596         digtxt = "eat through the bars.";
597 */
598         digtxt = "\93S\82Ì\96_\82É\8c\8a\82ð\8aJ\82¯\82½\81D";
599         dissolve_bars(x, y);
600     } else if (lev->typ == SDOOR) {
601         if (lev->doormask & D_TRAPPED) {
602             lev->doormask = D_NODOOR;
603 /*JP
604             b_trapped("secret door", 0);
605 */
606             b_trapped("\94é\96§\82Ì\94à", 0);
607         } else {
608 /*JP
609             digtxt = "chew through the secret door.";
610 */
611             digtxt = "\94é\96§\82Ì\94à\82ð\8a\9a\82Ý\8dÓ\82¢\82½\81D";
612             lev->doormask = D_BROKEN;
613         }
614         lev->typ = DOOR;
615
616     } else if (IS_DOOR(lev->typ)) {
617         if (*in_rooms(x, y, SHOPBASE)) {
618             add_damage(x, y, 400L);
619 /*JP
620             dmgtxt = "break";
621 */
622             dmgtxt = "\89ó\82·";
623         }
624         if (lev->doormask & D_TRAPPED) {
625             lev->doormask = D_NODOOR;
626 /*JP
627             b_trapped("door", 0);
628 */
629             b_trapped("\94à", 0);
630         } else {
631 /*JP
632             digtxt = "chew through the door.";
633 */
634             digtxt = "\94à\82ð\8dÓ\82¢\82½\81D";
635             lev->doormask = D_BROKEN;
636         }
637
638     } else { /* STONE or SCORR */
639 /*JP
640         digtxt = "chew a passage through the rock.";
641 */
642         digtxt = "\8aâ\82ð\8a\9a\82Ý\8dÓ\82¢\82Ä\92Ê\82è\94²\82¯\82½\81D";
643         lev->typ = CORR;
644     }
645
646     unblock_point(x, y); /* vision */
647     newsym(x, y);
648     if (digtxt)
649         You1(digtxt); /* after newsym */
650     if (dmgtxt)
651         pay_for_damage(dmgtxt, FALSE);
652     (void) memset((genericptr_t) &context.digging, 0,
653                   sizeof(struct dig_info));
654     return 0;
655 }
656
657 void
658 movobj(obj, ox, oy)
659 register struct obj *obj;
660 register xchar ox, oy;
661 {
662     /* optimize by leaving on the fobj chain? */
663     remove_object(obj);
664     newsym(obj->ox, obj->oy);
665     place_object(obj, ox, oy);
666     newsym(ox, oy);
667 }
668
669 /*JP
670 static NEARDATA const char fell_on_sink[] = "fell onto a sink";
671 */
672 static NEARDATA const char fell_on_sink[] = "\97¬\82µ\91ä\82É\97\8e\82¿\82Ä";
673
674 STATIC_OVL void
675 dosinkfall()
676 {
677     register struct obj *obj;
678     int dmg;
679     boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
680             innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L),
681             ufall = (!innate_lev && !(HFlying || EFlying)); /* BFlying */
682
683     if (!ufall) {
684 /*JP
685         You(innate_lev ? "wobble unsteadily for a moment."
686 */
687         You(innate_lev ? "\82¿\82å\82Á\82Æ\82Ó\82ç\82Â\82¢\82½\81D"
688 /*JP
689                        : "gain control of your flight.");
690 */
691                        : "\94ò\8ds\92\86\82Ì\90§\8cä\82ð\8eæ\82è\82à\82Ç\82µ\82½\81D");
692     } else {
693         long save_ELev = ELevitation, save_HLev = HLevitation;
694
695         /* fake removal of levitation in advance so that final
696            disclosure will be right in case this turns out to
697            be fatal; fortunately the fact that rings and boots
698            are really still worn has no effect on bones data */
699         ELevitation = HLevitation = 0L;
700 /*JP
701         You("crash to the floor!");
702 */
703         You("\8f°\82É\92@\82«\82Â\82¯\82ç\82ê\82½\81I");
704         dmg = rn1(8, 25 - (int) ACURR(A_CON));
705 #if 0 /*JP*/
706         losehp(Maybe_Half_Phys(dmg), fell_on_sink, NO_KILLER_PREFIX);
707 #else
708         losehp(Maybe_Half_Phys(dmg), fell_on_sink, KILLED_BY);
709 #endif
710         exercise(A_DEX, FALSE);
711 /*JP
712         selftouch("Falling, you");
713 */
714         selftouch("\97\8e\82¿\82È\82ª\82ç\81C\82 \82È\82½\82Í");
715         for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
716             if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) {
717 /*JP
718                 You("fell on %s.", doname(obj));
719 */
720                 You("%s\82Ì\8fã\82É\97\8e\82¿\82½\81D",doname(obj));
721 #if 0 /*JP*/
722                 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
723                        NO_KILLER_PREFIX);
724 #else
725                 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
726                        KILLED_BY);
727 #endif
728                 exercise(A_CON, FALSE);
729             }
730         ELevitation = save_ELev;
731         HLevitation = save_HLev;
732     }
733
734     /*
735      * Interrupt multi-turn putting on/taking off of armor (in which
736      * case we reached the sink due to being teleported while busy;
737      * in 3.4.3, Boots_on()/Boots_off() [called via (*aftermv)() when
738      * 'multi' reaches 0] triggered a crash if we were donning/doffing
739      * levitation boots [because the Boots_off() below causes 'uarmf'
740      * to be null by the time 'aftermv' gets called]).
741      *
742      * Interrupt donning/doffing if we fall onto the sink, or if the
743      * code below is going to remove levitation boots even when we
744      * haven't fallen (innate floating or flying becoming unblocked).
745      */
746     if (ufall || lev_boots) {
747         (void) stop_donning(lev_boots ? uarmf : (struct obj *) 0);
748         /* recalculate in case uarmf just got set to null */
749         lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS);
750     }
751
752     /* remove worn levitation items */
753     ELevitation &= ~W_ARTI;
754     HLevitation &= ~(I_SPECIAL | TIMEOUT);
755     HLevitation++;
756     if (uleft && uleft->otyp == RIN_LEVITATION) {
757         obj = uleft;
758         Ring_off(obj);
759         off_msg(obj);
760     }
761     if (uright && uright->otyp == RIN_LEVITATION) {
762         obj = uright;
763         Ring_off(obj);
764         off_msg(obj);
765     }
766     if (lev_boots) {
767         obj = uarmf;
768         (void) Boots_off();
769         off_msg(obj);
770     }
771     HLevitation--;
772     /* probably moot; we're either still levitating or went
773        through float_down(), but make sure BFlying is up to date */
774     float_vs_flight();
775 }
776
777 /* intended to be called only on ROCKs or TREEs */
778 boolean
779 may_dig(x, y)
780 register xchar x, y;
781 {
782     struct rm *lev = &levl[x][y];
783
784     return (boolean) !((IS_STWALL(lev->typ) || IS_TREE(lev->typ))
785                        && (lev->wall_info & W_NONDIGGABLE));
786 }
787
788 boolean
789 may_passwall(x, y)
790 register xchar x, y;
791 {
792     return (boolean) !(IS_STWALL(levl[x][y].typ)
793                        && (levl[x][y].wall_info & W_NONPASSWALL));
794 }
795
796 boolean
797 bad_rock(mdat, x, y)
798 struct permonst *mdat;
799 register xchar x, y;
800 {
801     return (boolean) ((Sokoban && sobj_at(BOULDER, x, y))
802                       || (IS_ROCK(levl[x][y].typ)
803                           && (!tunnels(mdat) || needspick(mdat)
804                               || !may_dig(x, y))
805                           && !(passes_walls(mdat) && may_passwall(x, y))));
806 }
807
808 /* caller has already decided that it's a tight diagonal; check whether a
809    monster--who might be the hero--can fit through, and if not then return
810    the reason why:  1: can't fit, 2: possessions won't fit, 3: sokoban */
811 int /* returns 0 if we can squeeze through */
812     cant_squeeze_thru(mon)
813 struct monst *mon;
814 {
815     int amt;
816     struct permonst *ptr = mon->data;
817
818     /* too big? */
819     if (bigmonst(ptr)
820         && !(amorphous(ptr) || is_whirly(ptr) || noncorporeal(ptr)
821              || slithy(ptr) || can_fog(mon)))
822         return 1;
823
824     /* lugging too much junk? */
825     amt =
826         (mon == &youmonst) ? inv_weight() + weight_cap() : curr_mon_load(mon);
827     if (amt > 600)
828         return 2;
829
830     /* Sokoban restriction applies to hero only */
831     if (mon == &youmonst && Sokoban)
832         return 3;
833
834     /* can squeeze through */
835     return 0;
836 }
837
838 boolean
839 invocation_pos(x, y)
840 xchar x, y;
841 {
842     return (boolean) (Invocation_lev(&u.uz)
843                       && x == inv_pos.x && y == inv_pos.y);
844 }
845
846 /* return TRUE if (dx,dy) is an OK place to move
847  * mode is one of DO_MOVE, TEST_MOVE or TEST_TRAV
848  */
849 boolean
850 test_move(ux, uy, dx, dy, mode)
851 int ux, uy, dx, dy;
852 int mode;
853 {
854     int x = ux + dx;
855     int y = uy + dy;
856     register struct rm *tmpr = &levl[x][y];
857     register struct rm *ust;
858
859     context.door_opened = FALSE;
860     /*
861      *  Check for physical obstacles.  First, the place we are going.
862      */
863     if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) {
864         if (Blind && mode == DO_MOVE)
865             feel_location(x, y);
866         if (Passes_walls && may_passwall(x, y)) {
867             ; /* do nothing */
868         } else if (tmpr->typ == IRONBARS) {
869             if ((dmgtype(youmonst.data, AD_RUST)
870                  || dmgtype(youmonst.data, AD_CORR)) && mode == DO_MOVE
871                 && still_chewing(x, y)) {
872                 return FALSE;
873             }
874             if (!(Passes_walls || passes_bars(youmonst.data))) {
875                 if (iflags.mention_walls)
876 /*JP
877                     You("cannot pass through the bars.");
878 */
879                     You("\93S\82Ì\96_\82ð\92Ê\82è\94²\82¯\82ç\82ê\82È\82¢\81D");
880                 return FALSE;
881             }
882         } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
883             /* Eat the rock. */
884             if (mode == DO_MOVE && still_chewing(x, y))
885                 return FALSE;
886         } else if (flags.autodig && !context.run && !context.nopick && uwep
887                    && is_pick(uwep)) {
888             /* MRKR: Automatic digging when wielding the appropriate tool */
889             if (mode == DO_MOVE)
890                 (void) use_pick_axe2(uwep);
891             return FALSE;
892         } else {
893             if (mode == DO_MOVE) {
894                 if (Is_stronghold(&u.uz) && is_db_wall(x, y))
895 /*JP
896                     pline_The("drawbridge is up!");
897 */
898                     pline("\92µ\82Ë\8b´\82Í\8fã\82Á\82Ä\82¢\82é\81I");
899                 /* sokoban restriction stays even after puzzle is solved */
900                 else if (Passes_walls && !may_passwall(x, y)
901                          && In_sokoban(&u.uz))
902 /*JP
903                     pline_The("Sokoban walls resist your ability.");
904 */
905                     pline_The("\91q\8cÉ\94Ô\82Ì\95Ç\82Í\82 \82È\82½\82Ì\94\\97Í\82É\92ï\8dR\82µ\82½\81D");
906                 else if (iflags.mention_walls)
907 /*JP
908                     pline("It's a wall.");
909 */
910                     pline("\82±\82ê\82Í\95Ç\82¾\81D");
911             }
912             return FALSE;
913         }
914     } else if (IS_DOOR(tmpr->typ)) {
915         if (closed_door(x, y)) {
916             if (Blind && mode == DO_MOVE)
917                 feel_location(x, y);
918             if (Passes_walls)
919                 ; /* do nothing */
920             else if (can_ooze(&youmonst)) {
921                 if (mode == DO_MOVE)
922 /*JP
923                     You("ooze under the door.");
924 */
925                     You("\83h\83A\82Ì\89º\82©\82ç\82É\82\82Ý\8fo\82½\81D");
926             } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
927                 /* Eat the door. */
928                 if (mode == DO_MOVE && still_chewing(x, y))
929                     return FALSE;
930             } else {
931                 if (mode == DO_MOVE) {
932                     if (amorphous(youmonst.data))
933                         You(
934 /*JP
935    "try to ooze under the door, but can't squeeze your possessions through.");
936 */
937    "\83h\83A\82Ì\89º\82©\82ç\82É\82\82Ý\8fo\82æ\82¤\82Æ\82µ\82½\81C\82µ\82©\82µ\8e\9d\82¿\95¨\82Í\82»\82¤\82Í\82¢\82©\82È\82¢\81D");
938                     if (flags.autoopen && !context.run && !Confusion
939                         && !Stunned && !Fumbling) {
940                         context.door_opened = context.move =
941                             doopen_indir(x, y);
942                     } else if (x == ux || y == uy) {
943                         if (Blind || Stunned || ACURR(A_DEX) < 10
944                             || Fumbling) {
945                             if (u.usteed) {
946 /*JP
947                                 You_cant("lead %s through that closed door.",
948 */
949                                 You_cant("%s\82É\95Â\82Ü\82Á\82½\94à\82ð\92Ê\89ß\82³\82¹\82é\82±\82Æ\82Í\82Å\82«\82È\82¢\81D",
950                                          y_monnam(u.usteed));
951                             } else {
952 /*JP
953                                 pline("Ouch!  You bump into a door.");
954 */
955                                 pline("\82¢\82Ä\82Á\81I\93ª\82ð\94à\82É\82Ô\82Â\82¯\82½\81D");
956                                 exercise(A_DEX, FALSE);
957                             }
958                         } else
959 /*JP
960                             pline("That door is closed.");
961 */
962                             pline("\94à\82Í\95Â\82Ü\82Á\82Ä\82¢\82é\81D");
963                     }
964                 } else if (mode == TEST_TRAV)
965                     goto testdiag;
966                 return FALSE;
967             }
968         } else {
969         testdiag:
970             if (dx && dy && !Passes_walls
971                 && (!doorless_door(x, y) || block_door(x, y))) {
972                 /* Diagonal moves into a door are not allowed. */
973                 if (Blind && mode == DO_MOVE)
974                     feel_location(x, y);
975                 return FALSE;
976             }
977         }
978     }
979     if (dx && dy && bad_rock(youmonst.data, ux, y)
980         && bad_rock(youmonst.data, x, uy)) {
981         /* Move at a diagonal. */
982         switch (cant_squeeze_thru(&youmonst)) {
983         case 3:
984             if (mode == DO_MOVE)
985 /*JP
986                 You("cannot pass that way.");
987 */
988                 You("\92Ê\82è\82Ê\82¯\82Å\82«\82È\82¢\81D");
989             return FALSE;
990         case 2:
991             if (mode == DO_MOVE)
992 /*JP
993                 You("are carrying too much to get through.");
994 */
995                 pline("\95¨\82ð\8e\9d\82¿\82·\82¬\82Ä\92Ê\82è\82Ê\82¯\82ç\82ê\82È\82¢\81D");
996             return FALSE;
997         case 1:
998             if (mode == DO_MOVE)
999 /*JP
1000                 Your("body is too large to fit through.");
1001 */
1002                 Your("\91Ì\82ª\91å\82«\82·\82¬\82Ä\92Ê\82è\82Ê\82¯\82ç\82ê\82È\82¢\81D");
1003             return FALSE;
1004         default:
1005             break; /* can squeeze through */
1006         }
1007     } else if (dx && dy && worm_cross(ux, uy, x, y)) {
1008         /* consecutive long worm segments are at <ux,y> and <x,uy> */
1009         if (mode == DO_MOVE)
1010 /*JP
1011             pline("%s is in your way.", Monnam(m_at(ux, y)));
1012 */
1013             pline("\93¹\82Ì\93r\92\86\82É%s\82ª\82¢\82é\81D", Monnam(m_at(ux, y)));
1014         return FALSE;
1015     }
1016     /* Pick travel path that does not require crossing a trap.
1017      * Avoid water and lava using the usual running rules.
1018      * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
1019     if (context.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
1020         struct trap *t = t_at(x, y);
1021
1022         if ((t && t->tseen)
1023             || (!Levitation && !Flying && !is_clinger(youmonst.data)
1024                 && is_pool_or_lava(x, y) && levl[x][y].seenv))
1025             return FALSE;
1026     }
1027
1028     ust = &levl[ux][uy];
1029
1030     /* Now see if other things block our way . . */
1031     if (dx && dy && !Passes_walls && IS_DOOR(ust->typ)
1032         && (!doorless_door(ux, uy) || block_entry(x, y))) {
1033         /* Can't move at a diagonal out of a doorway with door. */
1034         return FALSE;
1035     }
1036
1037     if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
1038         if (!(Blind || Hallucination) && (context.run >= 2)
1039             && mode != TEST_TRAV)
1040             return FALSE;
1041         if (mode == DO_MOVE) {
1042             /* tunneling monsters will chew before pushing */
1043             if (tunnels(youmonst.data) && !needspick(youmonst.data)
1044                 && !Sokoban) {
1045                 if (still_chewing(x, y))
1046                     return FALSE;
1047             } else if (moverock() < 0)
1048                 return FALSE;
1049         } else if (mode == TEST_TRAV) {
1050             struct obj *obj;
1051
1052             /* don't pick two boulders in a row, unless there's a way thru */
1053             if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
1054                 if (!Passes_walls
1055                     && !(tunnels(youmonst.data) && !needspick(youmonst.data))
1056                     && !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK)
1057                     && !((obj = carrying(WAN_DIGGING))
1058                          && !objects[obj->otyp].oc_name_known))
1059                     return FALSE;
1060             }
1061         }
1062         /* assume you'll be able to push it when you get there... */
1063     }
1064
1065     /* OK, it is a legal place to move. */
1066     return TRUE;
1067 }
1068
1069 #ifdef DEBUG
1070 static boolean trav_debug = FALSE;
1071
1072 /* in this case, toggle display of travel debug info */
1073 int wiz_debug_cmd_traveldisplay()
1074 {
1075     trav_debug = !trav_debug;
1076     return 0;
1077 }
1078 #endif /* DEBUG */
1079
1080 /*
1081  * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
1082  * A shortest path is returned.  If guess is TRUE, consider various
1083  * inaccessible locations as valid intermediate path points.
1084  * Returns TRUE if a path was found.
1085  */
1086 STATIC_OVL boolean
1087 findtravelpath(guess)
1088 boolean guess;
1089 {
1090     /* if travel to adjacent, reachable location, use normal movement rules */
1091     if (!guess && context.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1
1092         && !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
1093         context.run = 0;
1094         if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
1095             u.dx = u.tx - u.ux;
1096             u.dy = u.ty - u.uy;
1097             nomul(0);
1098             iflags.travelcc.x = iflags.travelcc.y = -1;
1099             return TRUE;
1100         }
1101         context.run = 8;
1102     }
1103     if (u.tx != u.ux || u.ty != u.uy) {
1104         xchar travel[COLNO][ROWNO];
1105         xchar travelstepx[2][COLNO * ROWNO];
1106         xchar travelstepy[2][COLNO * ROWNO];
1107         xchar tx, ty, ux, uy;
1108         int n = 1;      /* max offset in travelsteps */
1109         int set = 0;    /* two sets current and previous */
1110         int radius = 1; /* search radius */
1111         int i;
1112
1113         /* If guessing, first find an "obvious" goal location.  The obvious
1114          * goal is the position the player knows of, or might figure out
1115          * (couldsee) that is closest to the target on a straight path.
1116          */
1117         if (guess) {
1118             tx = u.ux;
1119             ty = u.uy;
1120             ux = u.tx;
1121             uy = u.ty;
1122         } else {
1123             tx = u.tx;
1124             ty = u.ty;
1125             ux = u.ux;
1126             uy = u.uy;
1127         }
1128
1129     noguess:
1130         (void) memset((genericptr_t) travel, 0, sizeof(travel));
1131         travelstepx[0][0] = tx;
1132         travelstepy[0][0] = ty;
1133
1134         while (n != 0) {
1135             int nn = 0;
1136
1137             for (i = 0; i < n; i++) {
1138                 int dir;
1139                 int x = travelstepx[set][i];
1140                 int y = travelstepy[set][i];
1141                 static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
1142                 /* no diagonal movement for grid bugs */
1143                 int dirmax = NODIAG(u.umonnum) ? 4 : 8;
1144
1145                 for (dir = 0; dir < dirmax; ++dir) {
1146                     int nx = x + xdir[ordered[dir]];
1147                     int ny = y + ydir[ordered[dir]];
1148
1149                     if (!isok(nx, ny))
1150                         continue;
1151                     if ((!Passes_walls && !can_ooze(&youmonst)
1152                          && closed_door(x, y)) || sobj_at(BOULDER, x, y)) {
1153                         /* closed doors and boulders usually
1154                          * cause a delay, so prefer another path */
1155                         if (travel[x][y] > radius - 3) {
1156                             travelstepx[1 - set][nn] = x;
1157                             travelstepy[1 - set][nn] = y;
1158                             /* don't change travel matrix! */
1159                             nn++;
1160                             continue;
1161                         }
1162                     }
1163                     if (test_move(x, y, nx - x, ny - y, TEST_TRAV)
1164                         && (levl[nx][ny].seenv
1165                             || (!Blind && couldsee(nx, ny)))) {
1166                         if (nx == ux && ny == uy) {
1167                             if (!guess) {
1168                                 u.dx = x - ux;
1169                                 u.dy = y - uy;
1170                                 if (x == u.tx && y == u.ty) {
1171                                     nomul(0);
1172                                     /* reset run so domove run checks work */
1173                                     context.run = 8;
1174                                     iflags.travelcc.x = iflags.travelcc.y =
1175                                         -1;
1176                                 }
1177                                 return TRUE;
1178                             }
1179                         } else if (!travel[nx][ny]) {
1180                             travelstepx[1 - set][nn] = nx;
1181                             travelstepy[1 - set][nn] = ny;
1182                             travel[nx][ny] = radius;
1183                             nn++;
1184                         }
1185                     }
1186                 }
1187             }
1188
1189 #ifdef DEBUG
1190             if (trav_debug) {
1191                 /* Use of warning glyph is arbitrary. It stands out. */
1192                 tmp_at(DISP_ALL, warning_to_glyph(1));
1193                 for (i = 0; i < nn; ++i) {
1194                     tmp_at(travelstepx[1 - set][i], travelstepy[1 - set][i]);
1195                 }
1196                 delay_output();
1197                 if (flags.runmode == RUN_CRAWL) {
1198                     delay_output();
1199                     delay_output();
1200                 }
1201                 tmp_at(DISP_END, 0);
1202             }
1203 #endif /* DEBUG */
1204
1205             n = nn;
1206             set = 1 - set;
1207             radius++;
1208         }
1209
1210         /* if guessing, find best location in travel matrix and go there */
1211         if (guess) {
1212             int px = tx, py = ty; /* pick location */
1213             int dist, nxtdist, d2, nd2;
1214
1215             dist = distmin(ux, uy, tx, ty);
1216             d2 = dist2(ux, uy, tx, ty);
1217             for (tx = 1; tx < COLNO; ++tx)
1218                 for (ty = 0; ty < ROWNO; ++ty)
1219                     if (travel[tx][ty]) {
1220                         nxtdist = distmin(ux, uy, tx, ty);
1221                         if (nxtdist == dist && couldsee(tx, ty)) {
1222                             nd2 = dist2(ux, uy, tx, ty);
1223                             if (nd2 < d2) {
1224                                 /* prefer non-zigzag path */
1225                                 px = tx;
1226                                 py = ty;
1227                                 d2 = nd2;
1228                             }
1229                         } else if (nxtdist < dist && couldsee(tx, ty)) {
1230                             px = tx;
1231                             py = ty;
1232                             dist = nxtdist;
1233                             d2 = dist2(ux, uy, tx, ty);
1234                         }
1235                     }
1236
1237             if (px == u.ux && py == u.uy) {
1238                 /* no guesses, just go in the general direction */
1239                 u.dx = sgn(u.tx - u.ux);
1240                 u.dy = sgn(u.ty - u.uy);
1241                 if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
1242                     return TRUE;
1243                 goto found;
1244             }
1245 #ifdef DEBUG
1246             if (trav_debug) {
1247                 /* Use of warning glyph is arbitrary. It stands out. */
1248                 tmp_at(DISP_ALL, warning_to_glyph(2));
1249                 tmp_at(px, py);
1250                 delay_output();
1251                 if (flags.runmode == RUN_CRAWL) {
1252                     delay_output();
1253                     delay_output();
1254                     delay_output();
1255                     delay_output();
1256                 }
1257                 tmp_at(DISP_END, 0);
1258             }
1259 #endif /* DEBUG */
1260             tx = px;
1261             ty = py;
1262             ux = u.ux;
1263             uy = u.uy;
1264             set = 0;
1265             n = radius = 1;
1266             guess = FALSE;
1267             goto noguess;
1268         }
1269         return FALSE;
1270     }
1271
1272 found:
1273     u.dx = 0;
1274     u.dy = 0;
1275     nomul(0);
1276     return FALSE;
1277 }
1278
1279 /* try to escape being stuck in a trapped state by walking out of it;
1280    return true iff moving should continue to intended destination
1281    (all failures and most successful escapes leave hero at original spot) */
1282 STATIC_OVL boolean
1283 trapmove(x, y, desttrap)
1284 int x, y;              /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
1285 struct trap *desttrap; /* nonnull if another trap at <x,y> */
1286 {
1287     boolean anchored;
1288     const char *predicament, *culprit;
1289     char *steedname = !u.usteed ? (char *) 0 : y_monnam(u.usteed);
1290
1291     if (!u.utrap)
1292         return TRUE; /* sanity check */
1293
1294     switch (u.utraptype) {
1295     case TT_BEARTRAP:
1296         if (flags.verbose) {
1297 /*JP
1298             predicament = "caught in a bear trap";
1299 */
1300             predicament = "\8cF\82Ìã©\82É\82Â\82©\82Ü\82Á\82½";
1301             if (u.usteed)
1302 /*JP
1303                 Norep("%s is %s.", upstart(steedname), predicament);
1304 */
1305                 Norep("%s\82Í%s\81D", upstart(steedname), predicament);
1306             else
1307 /*JP
1308                 Norep("You are %s.", predicament);
1309 */
1310                 Norep("\82 \82È\82½\82Í%s\81D", predicament);
1311         }
1312         /* [why does diagonal movement give quickest escape?] */
1313         if ((u.dx && u.dy) || !rn2(5))
1314             u.utrap--;
1315         break;
1316     case TT_PIT:
1317         if (desttrap && desttrap->tseen
1318             && (desttrap->ttyp == PIT || desttrap->ttyp == SPIKED_PIT))
1319             return TRUE; /* move into adjacent pit */
1320         /* try to escape; position stays same regardless of success */
1321         climb_pit();
1322         break;
1323     case TT_WEB:
1324         if (uwep && uwep->oartifact == ART_STING) {
1325             u.utrap = 0;
1326 /*JP
1327             pline("Sting cuts through the web!");
1328 */
1329             pline("\83X\83e\83B\83\93\83O\82Í\82­\82à\82Ì\91\83\82ð\90Ø\82è\82³\82¢\82½\81I");
1330             break; /* escape trap but don't move */
1331         }
1332         if (--u.utrap) {
1333             if (flags.verbose) {
1334 /*JP
1335                 predicament = "stuck to the web";
1336 */
1337                 predicament = "\82­\82à\82Ì\91\83\82É\82Ð\82Á\82©\82©\82Á\82½";
1338                 if (u.usteed)
1339 /*JP
1340                     Norep("%s is %s.", upstart(steedname), predicament);
1341 */
1342                     Norep("%s\82Í%s\81D", upstart(steedname), predicament);
1343                 else
1344 /*JP
1345                     Norep("You are %s.", predicament);
1346 */
1347                     Norep("\82 \82È\82½\82Í%s\81D", predicament);
1348             }
1349         } else {
1350             if (u.usteed)
1351 /*JP
1352                 pline("%s breaks out of the web.", upstart(steedname));
1353 */
1354                 pline("%s\82Í\82­\82à\82Ì\91\83\82ð\89ó\82µ\82½\81D", upstart(steedname));
1355             else
1356 /*JP
1357                 You("disentangle yourself.");
1358 */
1359                 You("\8e©\95ª\82Å\82Ù\82Ç\82¢\82½\81D");
1360         }
1361         break;
1362     case TT_LAVA:
1363         if (flags.verbose) {
1364 /*JP
1365             predicament = "stuck in the lava";
1366 */
1367             predicament = "\97n\8aâ\82É\82Í\82Ü\82Á\82½";
1368             if (u.usteed)
1369 /*JP
1370                 Norep("%s is %s.", upstart(steedname), predicament);
1371 */
1372                 Norep("%s\82Í%s\81D", upstart(steedname), predicament);
1373             else
1374 /*JP
1375                 Norep("You are %s.", predicament);
1376 */
1377                 Norep("\82 \82È\82½\82Í%s\81D", predicament);
1378         }
1379         if (!is_lava(x, y)) {
1380             u.utrap--;
1381             if ((u.utrap & 0xff) == 0) {
1382                 u.utrap = 0;
1383                 if (u.usteed)
1384 /*JP
1385                     You("lead %s to the edge of the lava.", steedname);
1386 */
1387                     You("%s\82ð\97n\8aâ\82Ì\92[\82Ü\82Å\93±\82¢\82½\81D", steedname);
1388                 else
1389 /*JP
1390                     You("pull yourself to the edge of the lava.");
1391 */
1392                     You("\97n\8aâ\82Ì\92[\82Ü\82Å\82©\82ë\82¤\82\82Ä\81C\82½\82Ç\82è\82Â\82¢\82½\81D");
1393             }
1394         }
1395         u.umoved = TRUE;
1396         break;
1397     case TT_INFLOOR:
1398     case TT_BURIEDBALL:
1399         anchored = (u.utraptype == TT_BURIEDBALL);
1400         if (anchored) {
1401             coord cc;
1402
1403             cc.x = u.ux, cc.y = u.uy;
1404             /* can move normally within radius 1 of buried ball */
1405             if (buried_ball(&cc) && dist2(x, y, cc.x, cc.y) <= 2) {
1406                 /* ugly hack: we need to issue some message here
1407                    in case "you are chained to the buried ball"
1408                    was the most recent message given, otherwise
1409                    our next attempt to move out of tether range
1410                    after this successful move would have its
1411                    can't-do-that message suppressed by Norep */
1412                 if (flags.verbose)
1413 /*JP
1414                     Norep("You move within the chain's reach.");
1415 */
1416                     Norep("\8d½\82ª\93Í\82­\94Í\88Í\82É\88Ú\93®\82Å\82«\82é\81D");
1417                 return TRUE;
1418             }
1419         }
1420         if (--u.utrap) {
1421             if (flags.verbose) {
1422                 if (anchored) {
1423 #if 0 /*JP*/
1424                     predicament = "chained to the";
1425                     culprit = "buried ball";
1426 #else
1427                     predicament = "\82Æ\82Â\82È\82ª\82Á\82Ä\82¢\82é";
1428                     culprit = "\96\84\82Ü\82Á\82Ä\82¢\82é\8b\85";
1429 #endif
1430                 } else {
1431 #if 0 /*JP*/
1432                     predicament = "stuck in the";
1433                     culprit = surface(u.ux, u.uy);
1434 #else
1435                     predicament = "\82É\96\84\82Ü\82Á\82Ä\82¢\82é";
1436                     culprit = surface(u.ux, u.uy);
1437 #endif
1438                 }
1439                 if (u.usteed) {
1440                     if (anchored)
1441 #if 0 /*JP*/
1442                         Norep("You and %s are %s %s.", steedname, predicament,
1443                               culprit);
1444 #else
1445                         Norep("\82 \82È\82½\82Æ%s\82Í%s%s\81D", steedname, culprit,
1446                               predicament);
1447 #endif
1448                     else
1449 #if 0 /*JP*/
1450                         Norep("%s is %s %s.", upstart(steedname), predicament,
1451                               culprit);
1452 #else
1453                         Norep("%s\82Í%s%s\81D", steedname, culprit,
1454                               predicament);
1455 #endif
1456                 } else
1457 /*JP
1458                     Norep("You are %s %s.", predicament, culprit);
1459 */
1460                     Norep("\82 \82È\82½\82Í%s\82É%s\81D", culprit, predicament);
1461             }
1462         } else {
1463             if (u.usteed)
1464 #if 0 /*JP*/
1465                 pline("%s finally %s free.", upstart(steedname),
1466                       !anchored ? "lurches" : "wrenches the ball");
1467 #else
1468                 pline("%s\82Í%s\82â\82Á\82Æ\8e©\97R\82É\82È\82Á\82½\81D", upstart(steedname),
1469                       !anchored ? "\82à\82ª\82¢\82Ä" : "\93S\8b\85\82ð\82à\82¬\8eæ\82Á\82Ä");
1470 #endif
1471             else
1472 #if 0 /*JP*/
1473                 You("finally %s free.",
1474                     !anchored ? "wriggle" : "wrench the ball");
1475 #else
1476                 You("%s\82â\82Á\82Æ\8e©\97R\82É\82È\82Á\82½\81D",
1477                     !anchored ? "\82à\82ª\82¢\82Ä" : "\93S\8b\85\82ð\82à\82¬\8eæ\82Á\82Ä");
1478 #endif
1479             if (anchored)
1480                 buried_ball_to_punishment();
1481         }
1482         break;
1483     default:
1484         impossible("trapmove: stuck in unknown trap? (%d)",
1485                    (int) u.utraptype);
1486         break;
1487     }
1488     return FALSE;
1489 }
1490
1491 boolean
1492 u_rooted()
1493 {
1494     if (!youmonst.data->mmove) {
1495 #if 0 /*JP*/
1496         You("are rooted %s.",
1497             Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
1498                 ? "in place"
1499                 : "to the ground");
1500 #else
1501         You("\82»\82Ì\8fê\82É\97§\82¿\82·\82­\82ñ\82¾\81D");
1502 #endif
1503         nomul(0);
1504         return TRUE;
1505     }
1506     return FALSE;
1507 }
1508
1509 void
1510 domove()
1511 {
1512     register struct monst *mtmp;
1513     register struct rm *tmpr;
1514     register xchar x, y;
1515     struct trap *trap = NULL;
1516     int wtcap;
1517     boolean on_ice;
1518     xchar chainx = 0, chainy = 0,
1519           ballx = 0, bally = 0;         /* ball&chain new positions */
1520     int bc_control = 0;                 /* control for ball&chain */
1521     boolean cause_delay = FALSE;        /* dragging ball will skip a move */
1522
1523     u_wipe_engr(rnd(5));
1524
1525     if (context.travel) {
1526         if (!findtravelpath(FALSE))
1527             (void) findtravelpath(TRUE);
1528         context.travel1 = 0;
1529     }
1530
1531     if (((wtcap = near_capacity()) >= OVERLOADED
1532          || (wtcap > SLT_ENCUMBER
1533              && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1534                         : (u.uhp < 10 && u.uhp != u.uhpmax))))
1535         && !Is_airlevel(&u.uz)) {
1536         if (wtcap < OVERLOADED) {
1537 /*JP
1538             You("don't have enough stamina to move.");
1539 */
1540             You("\82Ö\82Æ\82Ö\82Æ\82Å\93®\82¯\82È\82¢\81D");
1541             exercise(A_CON, FALSE);
1542         } else
1543 /*JP
1544             You("collapse under your load.");
1545 */
1546             pline("\95¨\82ð\8e\9d\82¿\82·\82¬\82Ä\93|\82ê\82½\81D");
1547         nomul(0);
1548         return;
1549     }
1550     if (u.uswallow) {
1551         u.dx = u.dy = 0;
1552         u.ux = x = u.ustuck->mx;
1553         u.uy = y = u.ustuck->my;
1554         mtmp = u.ustuck;
1555     } else {
1556         if (Is_airlevel(&u.uz) && rn2(4) && !Levitation && !Flying) {
1557             switch (rn2(3)) {
1558             case 0:
1559 /*JP
1560                 You("tumble in place.");
1561 */
1562                 You("\82»\82Ì\8fê\82Å\93|\82ê\82½\81D");
1563                 exercise(A_DEX, FALSE);
1564                 break;
1565             case 1:
1566 /*JP
1567                 You_cant("control your movements very well.");
1568 */
1569                 You("\82¤\82Ü\82­\95à\82¯\82È\82¢\81D");
1570                 break;
1571             case 2:
1572 /*JP
1573                 pline("It's hard to walk in thin air.");
1574 */
1575                 pline("\8bó\92\86\82ð\95à\82­\82Ì\82Í\93ï\82µ\82¢\81D");
1576                 exercise(A_DEX, TRUE);
1577                 break;
1578             }
1579             return;
1580         }
1581
1582         /* check slippery ice */
1583         on_ice = !Levitation && is_ice(u.ux, u.uy);
1584         if (on_ice) {
1585             static int skates = 0;
1586             if (!skates)
1587                 skates = find_skates();
1588             if ((uarmf && uarmf->otyp == skates) || resists_cold(&youmonst)
1589                 || Flying || is_floater(youmonst.data)
1590                 || is_clinger(youmonst.data) || is_whirly(youmonst.data))
1591                 on_ice = FALSE;
1592             else if (!rn2(Cold_resistance ? 3 : 2)) {
1593                 HFumbling |= FROMOUTSIDE;
1594                 HFumbling &= ~TIMEOUT;
1595                 HFumbling += 1; /* slip on next move */
1596             }
1597         }
1598         if (!on_ice && (HFumbling & FROMOUTSIDE))
1599             HFumbling &= ~FROMOUTSIDE;
1600
1601         x = u.ux + u.dx;
1602         y = u.uy + u.dy;
1603         if (Stunned || (Confusion && !rn2(5))) {
1604             register int tries = 0;
1605
1606             do {
1607                 if (tries++ > 50) {
1608                     nomul(0);
1609                     return;
1610                 }
1611                 confdir();
1612                 x = u.ux + u.dx;
1613                 y = u.uy + u.dy;
1614             } while (!isok(x, y) || bad_rock(youmonst.data, x, y));
1615         }
1616         /* turbulence might alter your actual destination */
1617         if (u.uinwater) {
1618             water_friction();
1619             if (!u.dx && !u.dy) {
1620                 nomul(0);
1621                 return;
1622             }
1623             x = u.ux + u.dx;
1624             y = u.uy + u.dy;
1625         }
1626         if (!isok(x, y)) {
1627             nomul(0);
1628             return;
1629         }
1630         if (((trap = t_at(x, y)) && trap->tseen)
1631             || (Blind && !Levitation && !Flying && !is_clinger(youmonst.data)
1632                 && is_pool_or_lava(x, y) && levl[x][y].seenv)) {
1633             if (context.run >= 2) {
1634                 nomul(0);
1635                 context.move = 0;
1636                 return;
1637             } else
1638                 nomul(0);
1639         }
1640
1641         if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
1642             if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
1643                 /* perhaps it fled (or was teleported or ... ) */
1644                 u.ustuck = 0;
1645             } else if (sticks(youmonst.data)) {
1646                 /* When polymorphed into a sticking monster,
1647                  * u.ustuck means it's stuck to you, not you to it.
1648                  */
1649 /*JP
1650                 You("release %s.", mon_nam(u.ustuck));
1651 */
1652                 You("%s\82ð\95ú\82µ\82½\81D", mon_nam(u.ustuck));
1653                 u.ustuck = 0;
1654             } else {
1655                 /* If holder is asleep or paralyzed:
1656                  *      37.5% chance of getting away,
1657                  *      12.5% chance of waking/releasing it;
1658                  * otherwise:
1659                  *       7.5% chance of getting away.
1660                  * [strength ought to be a factor]
1661                  * If holder is tame and there is no conflict,
1662                  * guaranteed escape.
1663                  */
1664                 switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
1665                 case 0:
1666                 case 1:
1667                 case 2:
1668                 pull_free:
1669 /*JP
1670                     You("pull free from %s.", mon_nam(u.ustuck));
1671 */
1672                     You("%s\82ð\82Ð\82«\82Í\82È\82µ\82½\81D", mon_nam(u.ustuck));
1673                     u.ustuck = 0;
1674                     break;
1675                 case 3:
1676                     if (!u.ustuck->mcanmove) {
1677                         /* it's free to move on next turn */
1678                         u.ustuck->mfrozen = 1;
1679                         u.ustuck->msleeping = 0;
1680                     }
1681                 /*FALLTHRU*/
1682                 default:
1683                     if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf)
1684                         goto pull_free;
1685 /*JP
1686                     You("cannot escape from %s!", mon_nam(u.ustuck));
1687 */
1688                     You("%s\82©\82ç\93¦\82°\82ç\82ê\82È\82¢\81I", mon_nam(u.ustuck));
1689                     nomul(0);
1690                     return;
1691                 }
1692             }
1693         }
1694
1695         mtmp = m_at(x, y);
1696         if (mtmp) {
1697             /* Don't attack if you're running, and can see it */
1698             /* We should never get here if forcefight */
1699             if (context.run && ((!Blind && mon_visible(mtmp)
1700                                  && ((mtmp->m_ap_type != M_AP_FURNITURE
1701                                       && mtmp->m_ap_type != M_AP_OBJECT)
1702                                      || Protection_from_shape_changers))
1703                                 || sensemon(mtmp))) {
1704                 nomul(0);
1705                 context.move = 0;
1706                 return;
1707             }
1708         }
1709     }
1710
1711     u.ux0 = u.ux;
1712     u.uy0 = u.uy;
1713     bhitpos.x = x;
1714     bhitpos.y = y;
1715     tmpr = &levl[x][y];
1716
1717     /* attack monster */
1718     if (mtmp) {
1719         nomul(0);
1720         /* only attack if we know it's there */
1721         /* or if we used the 'F' command to fight blindly */
1722         /* or if it hides_under, in which case we call attack() to print
1723          * the Wait! message.
1724          * This is different from ceiling hiders, who aren't handled in
1725          * attack().
1726          */
1727
1728         /* If they used a 'm' command, trying to move onto a monster
1729          * prints the below message and wastes a turn.  The exception is
1730          * if the monster is unseen and the player doesn't remember an
1731          * invisible monster--then, we fall through to attack() and
1732          * attack_check(), which still wastes a turn, but prints a
1733          * different message and makes the player remember the monster.
1734          */
1735         if (context.nopick
1736             && (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))) {
1737             if (mtmp->m_ap_type && !Protection_from_shape_changers
1738                 && !sensemon(mtmp))
1739                 stumble_onto_mimic(mtmp);
1740             else if (mtmp->mpeaceful && !Hallucination)
1741 /*JP
1742                 pline("Pardon me, %s.", m_monnam(mtmp));
1743 */
1744                 pline("\82¿\82å\82Á\82Æ\82²\82ß\82ñ\82È\82³\82¢\82æ\81C%s\82³\82ñ\81D", m_monnam(mtmp));
1745             else
1746 /*JP
1747                 You("move right into %s.", mon_nam(mtmp));
1748 */
1749                 You("%s\82Ì\82»\82Î\82É\88Ú\93®\82µ\82½\81D", mon_nam(mtmp));
1750             return;
1751         }
1752         if (context.forcefight || !mtmp->mundetected || sensemon(mtmp)
1753             || ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)
1754                 && !is_safepet(mtmp))) {
1755             /* try to attack; note that it might evade */
1756             /* also, we don't attack tame when _safepet_ */
1757             if (attack(mtmp))
1758                 return;
1759         }
1760     }
1761
1762     /* specifying 'F' with no monster wastes a turn */
1763     if (context.forcefight
1764         /* remembered an 'I' && didn't use a move command */
1765         || (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
1766         struct obj *boulder = 0;
1767         boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
1768                 solid = !accessible(x, y);
1769         int glyph = glyph_at(x, y); /* might be monster */
1770         char buf[BUFSZ];
1771
1772         if (!Underwater) {
1773             boulder = sobj_at(BOULDER, x, y);
1774             /* if a statue is displayed at the target location,
1775                player is attempting to attack it [and boulder
1776                handling below is suitable for handling that] */
1777             if (glyph_is_statue(glyph)
1778                 || (Hallucination && glyph_is_monster(glyph)))
1779                 boulder = sobj_at(STATUE, x, y);
1780
1781             /* force fight at boulder/statue or wall/door while wielding
1782                pick:  start digging to break the boulder or wall */
1783             if (context.forcefight
1784                 /* can we dig? */
1785                 && uwep && dig_typ(uwep, x, y)
1786                 /* should we dig? */
1787                 && !glyph_is_invisible(glyph) && !glyph_is_monster(glyph)) {
1788                 (void) use_pick_axe2(uwep);
1789                 return;
1790             }
1791         }
1792
1793         /* about to become known empty -- remove 'I' if present */
1794         unmap_object(x, y);
1795         if (boulder)
1796             map_object(boulder, TRUE);
1797         newsym(x, y);
1798         glyph = glyph_at(x, y); /* might have just changed */
1799
1800         if (boulder)
1801             Strcpy(buf, ansimpleoname(boulder));
1802         else if (Underwater && !is_pool(x, y))
1803             /* Underwater, targetting non-water; the map just shows blank
1804                because you don't see remembered terrain while underwater;
1805                although the hero can attack an adjacent monster this way,
1806                assume he can't reach out far enough to distinguish terrain */
1807 #if 0 /*JP*/
1808             Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
1809                              ? "an air bubble"
1810                              : "nothing");
1811 #else
1812             Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
1813                              ? "\8bó\8bC\82Ì\96A"
1814                              : "\89½\82à\82È\82¢\82Æ\82±\82ë");
1815 #endif
1816         else if (solid)
1817             /* glyph might indicate unseen terrain if hero is blind;
1818                unlike searching, this won't reveal what that terrain is
1819                (except for solid rock, where the glyph would otherwise
1820                yield ludicrous "dark part of a room") */
1821 #if 0 /*JP*/
1822             Strcpy(buf,
1823                    (levl[x][y].typ == STONE)
1824                        ? "solid rock"
1825                        : glyph_is_cmap(glyph)
1826                             ? the(defsyms[glyph_to_cmap(glyph)].explanation)
1827                             : (const char *) "an unknown obstacle");
1828 #else
1829             Strcpy(buf,
1830                    (levl[x][y].typ == STONE)
1831                        ? "\90Î"
1832                        : glyph_is_cmap(glyph)
1833                             ? the(defsyms[glyph_to_cmap(glyph)].explanation)
1834                             : (const char *) "\95s\96¾\82È\8fá\8aQ\95¨");
1835 #endif
1836         /* note: 'solid' is misleadingly named and catches pools
1837            of water and lava as well as rock and walls */
1838         else
1839 /*JP
1840             Strcpy(buf, "thin air");
1841 */
1842             Strcpy(buf, "\89½\82à\82È\82¢\8bó\92\86");
1843 #if 0 /*JP*/
1844         You("%s%s %s.",
1845             !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
1846             explo ? "explode at" : "attack", buf);
1847 #else
1848         You("%s%s%s.",
1849             !(boulder || solid) ? "" : !explo ? "\8cø\89Ê\82È\82­" : "\82Þ\82¾\82É",
1850             buf, explo ? "\82Å\94\9a\94­\82µ\82½" : "\82ð\8dU\8c\82\82µ\82½");
1851 #endif
1852
1853         nomul(0);
1854         if (explo) {
1855             wake_nearby();
1856             u.mh = -1; /* dead in the current form */
1857             rehumanize();
1858         }
1859         return;
1860     }
1861     if (glyph_is_invisible(levl[x][y].glyph)) {
1862         unmap_object(x, y);
1863         newsym(x, y);
1864     }
1865     /* not attacking an animal, so we try to move */
1866     if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
1867         nomul(0);
1868         return;
1869     }
1870
1871     if (u_rooted())
1872         return;
1873
1874     if (u.utrap) {
1875         if (!trapmove(x, y, trap))
1876             return;
1877     }
1878
1879     if (!test_move(u.ux, u.uy, x - u.ux, y - u.uy, DO_MOVE)) {
1880         if (!context.door_opened) {
1881             context.move = 0;
1882             nomul(0);
1883         }
1884         return;
1885     }
1886
1887     /* Move ball and chain.  */
1888     if (Punished)
1889         if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy,
1890                        &cause_delay, TRUE))
1891             return;
1892
1893     /* Check regions entering/leaving */
1894     if (!in_out_region(x, y))
1895         return;
1896
1897     /* now move the hero */
1898     mtmp = m_at(x, y);
1899     u.ux += u.dx;
1900     u.uy += u.dy;
1901     /* Move your steed, too */
1902     if (u.usteed) {
1903         u.usteed->mx = u.ux;
1904         u.usteed->my = u.uy;
1905         exercise_steed();
1906     }
1907
1908     /*
1909      * If safepet at destination then move the pet to the hero's
1910      * previous location using the same conditions as in attack().
1911      * there are special extenuating circumstances:
1912      * (1) if the pet dies then your god angers,
1913      * (2) if the pet gets trapped then your god may disapprove,
1914      * (3) if the pet was already trapped and you attempt to free it
1915      * not only do you encounter the trap but you may frighten your
1916      * pet causing it to go wild!  moral: don't abuse this privilege.
1917      *
1918      * Ceiling-hiding pets are skipped by this section of code, to
1919      * be caught by the normal falling-monster code.
1920      */
1921     if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
1922         /* if trapped, there's a chance the pet goes wild */
1923         if (mtmp->mtrapped) {
1924             if (!rn2(mtmp->mtame)) {
1925                 mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
1926                 if (mtmp->mleashed)
1927                     m_unleash(mtmp, TRUE);
1928                 growl(mtmp);
1929             } else {
1930                 yelp(mtmp);
1931             }
1932         }
1933         mtmp->mundetected = 0;
1934         if (mtmp->m_ap_type)
1935             seemimic(mtmp);
1936         else if (!mtmp->mtame)
1937             newsym(mtmp->mx, mtmp->my);
1938
1939         if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
1940             && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
1941             && sobj_at(BOULDER, trap->tx, trap->ty)) {
1942             /* can't swap places with pet pinned in a pit by a boulder */
1943             u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
1944         } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
1945             /* can't swap places when pet can't move to your spot */
1946             u.ux = u.ux0, u.uy = u.uy0;
1947 /*JP
1948             You("stop.  %s can't move diagonally.", upstart(y_monnam(mtmp)));
1949 */
1950             You("\8e~\82Ü\82Á\82½\81D%s\82Í\8eÎ\82ß\82É\93®\82¯\82È\82¢\81D", upstart(y_monnam(mtmp)));
1951         } else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0)
1952                    && bad_rock(mtmp->data, u.ux0, y)
1953                    && (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
1954             /* can't swap places when pet won't fit thru the opening */
1955             u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
1956 /*JP
1957             You("stop.  %s won't fit through.", upstart(y_monnam(mtmp)));
1958 */
1959             You("\8e~\82Ü\82Á\82½\81D%s\82Í\92Ê\82è\94²\82¯\82ç\82ê\82È\82¢\81D", upstart(y_monnam(mtmp)));
1960         } else {
1961             char pnambuf[BUFSZ];
1962
1963             /* save its current description in case of polymorph */
1964             Strcpy(pnambuf, y_monnam(mtmp));
1965             mtmp->mtrapped = 0;
1966             remove_monster(x, y);
1967             place_monster(mtmp, u.ux0, u.uy0);
1968             newsym(x, y);
1969             newsym(u.ux0, u.uy0);
1970
1971 #if 0 /*JP*/
1972             You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
1973                 pnambuf);
1974 #else
1975             You("%s%s\82½\81D",
1976                 pnambuf,
1977                 mtmp->mtame ? "\82Æ\8fê\8f\8a\82ð\93ü\82ê\8a·\82í\82Á" : "\82ð\95|\82ª\82ç\82¹");
1978 #endif
1979
1980             /* check for displacing it into pools and traps */
1981             switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
1982             case 0:
1983                 break;
1984             case 1: /* trapped */
1985             case 3: /* changed levels */
1986                 /* there's already been a trap message, reinforce it */
1987                 abuse_dog(mtmp);
1988                 adjalign(-3);
1989                 break;
1990             case 2:
1991                 /* drowned or died...
1992                  * you killed your pet by direct action, so get experience
1993                  * and possibly penalties;
1994                  * we want the level gain message, if it happens, to occur
1995                  * before the guilt message below
1996                  */
1997                 {
1998                     /* minliquid() and mintrap() call mondead() rather than
1999                        killed() so we duplicate some of the latter here */
2000                     int tmp, mndx;
2001
2002                     u.uconduct.killer++;
2003                     mndx = monsndx(mtmp->data);
2004                     tmp = experience(mtmp, (int) mvitals[mndx].died);
2005                     more_experienced(tmp, 0);
2006                     newexplevel(); /* will decide if you go up */
2007                 }
2008                 /* That's no way to treat a pet!  Your god gets angry.
2009                  *
2010                  * [This has always been pretty iffy.  Why does your
2011                  * patron deity care at all, let alone enough to get mad?]
2012                  */
2013                 if (rn2(4)) {
2014 /*JP
2015                     You_feel("guilty about losing your pet like this.");
2016 */
2017                     pline("\82±\82Ì\82æ\82¤\82È\8c`\82Å\83y\83b\83g\82ð\8e¸\82¤\82Æ\82Í\8dß\90[\82¢\82±\82Æ\82¾\82Æ\8ev\82Á\82½\81D");
2018                     u.ugangr++;
2019                     adjalign(-15);
2020                 }
2021                 break;
2022             default:
2023                 pline("that's strange, unknown mintrap result!");
2024                 break;
2025             }
2026         }
2027     }
2028
2029     reset_occupations();
2030     if (context.run) {
2031         if (context.run < 8)
2032             if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ)
2033                 || IS_FURNITURE(tmpr->typ))
2034                 nomul(0);
2035     }
2036
2037     if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) || u.dx
2038         || u.dy)
2039         (void) hideunder(&youmonst);
2040
2041     /*
2042      * Mimics (or whatever) become noticeable if they move and are
2043      * imitating something that doesn't move.  We could extend this
2044      * to non-moving monsters...
2045      */
2046     if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
2047                            || youmonst.m_ap_type == M_AP_FURNITURE))
2048         youmonst.m_ap_type = M_AP_NOTHING;
2049
2050     check_leash(u.ux0, u.uy0);
2051
2052     if (u.ux0 != u.ux || u.uy0 != u.uy) {
2053         u.umoved = TRUE;
2054         /* Clean old position -- vision_recalc() will print our new one. */
2055         newsym(u.ux0, u.uy0);
2056         /* Since the hero has moved, adjust what can be seen/unseen. */
2057         vision_recalc(1); /* Do the work now in the recover time. */
2058         invocation_message();
2059     }
2060
2061     if (Punished) /* put back ball and chain */
2062         move_bc(0, bc_control, ballx, bally, chainx, chainy);
2063
2064     spoteffects(TRUE);
2065
2066     /* delay next move because of ball dragging */
2067     /* must come after we finished picking up, in spoteffects() */
2068     if (cause_delay) {
2069         nomul(-2);
2070         multi_reason = "dragging an iron ball";
2071         nomovemsg = "";
2072     }
2073
2074     if (context.run && flags.runmode != RUN_TPORT) {
2075         /* display every step or every 7th step depending upon mode */
2076         if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
2077             if (flags.time)
2078                 context.botl = 1;
2079             curs_on_u();
2080             delay_output();
2081             if (flags.runmode == RUN_CRAWL) {
2082                 delay_output();
2083                 delay_output();
2084                 delay_output();
2085                 delay_output();
2086             }
2087         }
2088     }
2089 }
2090
2091 /* combat increases metabolism */
2092 boolean
2093 overexertion()
2094 {
2095     /* this used to be part of domove() when moving to a monster's
2096        position, but is now called by attack() so that it doesn't
2097        execute if you decline to attack a peaceful monster */
2098     gethungry();
2099     if ((moves % 3L) != 0L && near_capacity() >= HVY_ENCUMBER) {
2100         int *hp = (!Upolyd ? &u.uhp : &u.mh);
2101
2102         if (*hp > 1) {
2103             *hp -= 1;
2104         } else {
2105 /*JP
2106             You("pass out from exertion!");
2107 */
2108             You("\8bC\90â\82µ\82½\81D");
2109             exercise(A_CON, FALSE);
2110             fall_asleep(-10, FALSE);
2111         }
2112     }
2113     return (boolean) (multi < 0); /* might have fainted (forced to sleep) */
2114 }
2115
2116 void
2117 invocation_message()
2118 {
2119     /* a special clue-msg when on the Invocation position */
2120     if (invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
2121         char buf[BUFSZ];
2122         struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
2123
2124         nomul(0); /* stop running or travelling */
2125         if (u.usteed)
2126 /*JP
2127             Sprintf(buf, "beneath %s", y_monnam(u.usteed));
2128 */
2129             Sprintf(buf, "%s\82Ì\89º\82É", y_monnam(u.usteed));
2130         else if (Levitation || Flying)
2131 /*JP
2132             Strcpy(buf, "beneath you");
2133 */
2134             Strcpy(buf, "\89º\95û\82É");
2135         else
2136 /*JP
2137             Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
2138 */
2139             Strcpy(buf, "\91«\8c³\82É");
2140
2141 /*JP
2142         You_feel("a strange vibration %s.", buf);
2143 */
2144         You("%s\8aï\96­\82È\90U\93®\82ð\8a´\82\82½\81D", buf);
2145         u.uevent.uvibrated = 1;
2146         if (otmp && otmp->spe == 7 && otmp->lamplit)
2147 #if 0 /*JP*/
2148             pline("%s %s!", The(xname(otmp)),
2149                   Blind ? "throbs palpably" : "glows with a strange light");
2150 #else
2151             pline("%s\82Í%s\82µ\82½\81I", The(xname(otmp)),
2152                   Blind ? "\82©\82·\82©\82É\90U\93®" : "\8aï\96­\82È\8cõ\82ð\94­");
2153 #endif
2154     }
2155 }
2156
2157 /* moving onto different terrain;
2158    might be going into solid rock, inhibiting levitation or flight,
2159    or coming back out of such, reinstating levitation/flying */
2160 STATIC_OVL void
2161 switch_terrain()
2162 {
2163     struct rm *lev = &levl[u.ux][u.uy];
2164     boolean blocklev = (IS_ROCK(lev->typ) || closed_door(u.ux, u.uy)
2165                         || (Is_waterlevel(&u.uz) && lev->typ == WATER));
2166
2167     if (blocklev) {
2168         /* called from spoteffects(), skip float_down() */
2169         if (Levitation)
2170 /*JP
2171             You_cant("levitate in here.");
2172 */
2173             You_cant("\82±\82±\82Å\82Í\95\82\97V\82Å\82«\82È\82¢\81D");
2174         BLevitation |= FROMOUTSIDE;
2175     } else if (BLevitation) {
2176         BLevitation &= ~FROMOUTSIDE;
2177         if (Levitation)
2178             float_up();
2179     }
2180     /* the same terrain that blocks levitation also blocks flight */
2181     if (blocklev) {
2182         if (Flying)
2183 /*JP
2184             You_cant("fly in here.");
2185 */
2186             You_cant("\82±\82±\82Å\82Í\94ò\82×\82È\82¢\81D");
2187         BFlying |= FROMOUTSIDE;
2188     } else if (BFlying) {
2189         BFlying &= ~FROMOUTSIDE;
2190         float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
2191         /* [minor bug: we don't know whether this is beginning flight or
2192            resuming it; that could be tracked so that this message could
2193            be adjusted to "resume flying", but isn't worth the effort...] */
2194         if (Flying)
2195 /*JP
2196             You("start flying.");
2197 */
2198             You("\94ò\82Ñ\82Í\82\82ß\82½\81D");
2199     }
2200 }
2201
2202 /* extracted from spoteffects; called by spoteffects to check for entering or
2203    leaving a pool of water/lava, and by moveloop to check for staying on one
2204
2205    returns true to skip rest of spoteffects */
2206 boolean
2207 pooleffects(newspot)
2208 boolean newspot;             /* true if called by spoteffects */
2209 {
2210     /* check for leaving water */
2211     if (u.uinwater) {
2212         boolean still_inwater = FALSE; /* assume we're getting out */
2213
2214         if (!is_pool(u.ux, u.uy)) {
2215             if (Is_waterlevel(&u.uz))
2216 /*JP
2217                 You("pop into an air bubble.");
2218 */
2219                 You("\82Ð\82å\82¢\82Æ\8bó\8bC\82Ì\96A\82É\93ü\82Á\82½\81D");
2220             else if (is_lava(u.ux, u.uy))
2221 #if 0 /*JP*/
2222                 You("leave the water..."); /* oops! */
2223 #else
2224                 You("\90\85\82©\82ç\94²\82¯\82¾\82µ\82½\81D\81D\81D");  /* oops! */
2225 #endif
2226             else
2227 #if 0 /*JP*/
2228                 You("are on solid %s again.",
2229                     is_ice(u.ux, u.uy) ? "ice" : "land");
2230 #else
2231                 You("\8cÅ\82¢%s\82Ì\8fã\82É\82Ü\82½\96ß\82Á\82½\81D",
2232                     is_ice(u.ux, u.uy) ? "\95X" : "\92n\96Ê");
2233 #endif
2234         } else if (Is_waterlevel(&u.uz)) {
2235             still_inwater = TRUE;
2236         } else if (Levitation) {
2237 /*JP
2238             You("pop out of the water like a cork!");
2239 */
2240             You("\83R\83\8b\83N\82Ì\82æ\82¤\82É\94ò\82Ñ\82¾\82µ\82½\81I");
2241         } else if (Flying) {
2242 /*JP
2243             You("fly out of the water.");
2244 */
2245             You("\90\85\82©\82ç\94ò\82Ñ\82¾\82µ\82½\81D");
2246         } else if (Wwalking) {
2247 /*JP
2248             You("slowly rise above the surface.");
2249 */
2250             You("\82ä\82Á\82­\82è\90\85\96Ê\82Ü\82Å\8fã\82ª\82Á\82½\81D");
2251         } else {
2252             still_inwater = TRUE;
2253         }
2254         if (!still_inwater) {
2255             boolean was_underwater = (Underwater && !Is_waterlevel(&u.uz));
2256
2257             u.uinwater = 0;       /* leave the water */
2258             if (was_underwater) { /* restore vision */
2259                 docrt();
2260                 vision_full_recalc = 1;
2261             }
2262         }
2263     }
2264
2265     /* check for entering water or lava */
2266     if (!u.ustuck && !Levitation && !Flying && is_pool_or_lava(u.ux, u.uy)) {
2267         if (u.usteed
2268             && (is_flyer(u.usteed->data) || is_floater(u.usteed->data)
2269                 || is_clinger(u.usteed->data))) {
2270             /* floating or clinging steed keeps hero safe (is_flyer() test
2271                is redundant; it can't be true since Flying yielded false) */
2272             return FALSE;
2273         } else if (u.usteed) {
2274             /* steed enters pool */
2275             dismount_steed(Underwater ? DISMOUNT_FELL : DISMOUNT_GENERIC);
2276             /* dismount_steed() -> float_down() -> pickup()
2277                (float_down doesn't do autopickup on Air or Water) */
2278             if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
2279                 return FALSE;
2280             /* even if we actually end up at same location, float_down()
2281                has already done spoteffect()'s trap and pickup actions */
2282             if (newspot)
2283                 check_special_room(FALSE); /* spoteffects */
2284             return TRUE;
2285         }
2286         /* not mounted */
2287
2288         /* drown(),lava_effects() return true if hero changes
2289            location while surviving the problem */
2290         if (is_lava(u.ux, u.uy)) {
2291             if (lava_effects())
2292                 return TRUE;
2293         } else if (!Wwalking
2294                    && (newspot || !u.uinwater || !(Swimming || Amphibious))) {
2295             if (drown())
2296                 return TRUE;
2297         }
2298     }
2299     return FALSE;
2300 }
2301
2302 void
2303 spoteffects(pick)
2304 boolean pick;
2305 {
2306     static int inspoteffects = 0;
2307     static coord spotloc;
2308     static int spotterrain;
2309     static struct trap *spottrap = (struct trap *) 0;
2310     static unsigned spottraptyp = NO_TRAP;
2311     struct trap *trap = t_at(u.ux, u.uy);
2312     register struct monst *mtmp;
2313
2314     /* prevent recursion from affecting the hero all over again
2315        [hero poly'd to iron golem enters water here, drown() inflicts
2316        damage that triggers rehumanize() which calls spoteffects()...] */
2317     if (inspoteffects && u.ux == spotloc.x && u.uy == spotloc.y
2318         /* except when reason is transformed terrain (ice -> water) */
2319         && spotterrain == levl[u.ux][u.uy].typ
2320         /* or transformed trap (land mine -> pit) */
2321         && (!spottrap || !trap || trap->ttyp == spottraptyp))
2322         return;
2323
2324     ++inspoteffects;
2325     spotterrain = levl[u.ux][u.uy].typ;
2326     spotloc.x = u.ux, spotloc.y = u.uy;
2327
2328     /* moving onto different terrain might cause Levitation to toggle */
2329     if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
2330         switch_terrain();
2331
2332     if (pooleffects(TRUE))
2333         goto spotdone;
2334
2335     check_special_room(FALSE);
2336     if (IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
2337         dosinkfall();
2338     if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
2339         boolean pit;
2340
2341         /* if levitation is due to time out at the end of this
2342            turn, allowing it to do so could give the perception
2343            that a trap here is being triggered twice, so adjust
2344            the timeout to prevent that */
2345         if (trap && (HLevitation & TIMEOUT) == 1L && !ELevitation
2346             && !(HLevitation & ~TIMEOUT)) {
2347             if (rn2(2)) { /* defer timeout */
2348                 incr_itimeout(&HLevitation, 1L);
2349             } else { /* timeout early */
2350                 if (float_down(I_SPECIAL | TIMEOUT, 0L)) {
2351                     /* levitation has ended; we've already triggered
2352                        any trap and [usually] performed autopickup */
2353                     trap = 0;
2354                     pick = FALSE;
2355                 }
2356             }
2357         }
2358         /*
2359      * If not a pit, pickup before triggering trap.
2360      * If pit, trigger trap before pickup.
2361      */
2362         pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
2363         if (pick && !pit)
2364             (void) pickup(1);
2365
2366         if (trap) {
2367             /*
2368          * dotrap on a fire trap calls melt_ice() which triggers
2369          * spoteffects() (again) which can trigger the same fire
2370          * trap (again). Use static spottrap to prevent that.
2371          * We track spottraptyp because some traps morph
2372          * (landmine to pit) and any new trap type
2373          * should get triggered.
2374          */
2375             if (!spottrap || spottraptyp != trap->ttyp) {
2376                 spottrap = trap;
2377                 spottraptyp = trap->ttyp;
2378                 dotrap(trap, 0); /* fall into arrow trap, etc. */
2379                 spottrap = (struct trap *) 0;
2380                 spottraptyp = NO_TRAP;
2381             }
2382         }
2383         if (pick && pit)
2384             (void) pickup(1);
2385     }
2386     /* Warning alerts you to ice danger */
2387     if (Warning && is_ice(u.ux, u.uy)) {
2388         static const char *const icewarnings[] = {
2389 #if 0 /*JP*/
2390             "The ice seems very soft and slushy.",
2391             "You feel the ice shift beneath you!",
2392             "The ice, is gonna BREAK!", /* The Dead Zone */
2393 #else
2394             "\95X\82Í\82Æ\82Ä\82à\93î\82ç\82©\82­\82Ä\97n\82¯\82»\82¤\82¾\81D",
2395             "\82 \82È\82½\82Ì\89º\82Ì\95X\82ª\93®\82¢\82½\82æ\82¤\82È\8bC\82ª\82µ\82½\81I",
2396             "\95X\82ª\89ó\82ê\82é\82¼\81I", /* The Dead Zone */
2397 #endif
2398         };
2399         long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
2400         if (time_left && time_left < 15L)
2401             pline1((time_left < 5L) ? icewarnings[2] : (time_left < 10L)
2402                                                            ? icewarnings[1]
2403                                                            : icewarnings[0]);
2404     }
2405     if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
2406         mtmp->mundetected = mtmp->msleeping = 0;
2407         switch (mtmp->data->mlet) {
2408         case S_PIERCER:
2409 #if 0 /*JP*/
2410             pline("%s suddenly drops from the %s!", Amonnam(mtmp),
2411                   ceiling(u.ux, u.uy));
2412 #else
2413             pline("%s\82ª\93Ë\91R%s\82©\82ç\97\8e\82¿\82Ä\82«\82½\81I",
2414                   Amonnam(mtmp), ceiling(u.ux,u.uy));
2415 #endif
2416             if (mtmp->mtame) /* jumps to greet you, not attack */
2417                 ;
2418             else if (uarmh && is_metallic(uarmh))
2419 /*JP
2420                 pline("Its blow glances off your %s.",
2421 */
2422                 pline("\8dU\8c\82\82Í\82 \82È\82½\82Ì%s\82ð\82©\82·\82ß\82½\82¾\82¯\82¾\82Á\82½\81D",
2423                       helm_simple_name(uarmh));
2424             else if (u.uac + 3 <= rnd(20))
2425 #if 0 /*JP*/
2426                 You("are almost hit by %s!",
2427                     x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2428 #else
2429                 You("\97\8e\82¿\82Ä\82«\82½%s\82É\82à\82¤\8f­\82µ\82Å\93\96\82½\82é\82Æ\82±\82ë\82¾\82Á\82½\81D",
2430                     x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2431 #endif
2432             else {
2433                 int dmg;
2434 #if 0 /*JP*/
2435                 You("are hit by %s!",
2436                     x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2437 #else
2438                 You("\97\8e\82¿\82Ä\82«\82½%s\82É\93\96\82½\82Á\82½\81I",
2439                     x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2440 #endif
2441                 dmg = d(4, 6);
2442                 if (Half_physical_damage)
2443                     dmg = (dmg + 1) / 2;
2444                 mdamageu(mtmp, dmg);
2445             }
2446             break;
2447         default: /* monster surprises you. */
2448             if (mtmp->mtame)
2449 #if 0 /*JP*/
2450                 pline("%s jumps near you from the %s.", Amonnam(mtmp),
2451                       ceiling(u.ux, u.uy));
2452 #else
2453                 pline("%s\82ª%s\82©\82ç\82 \82È\82½\82Ì\8bß\82­\82É\94ò\82ñ\82Å\82«\82½\81D", Amonnam(mtmp),
2454                       ceiling(u.ux,u.uy));
2455 #endif
2456             else if (mtmp->mpeaceful) {
2457 /*JP
2458                 You("surprise %s!",
2459 */
2460                 You("%s\82ð\8bÁ\82©\82µ\82½\81I",
2461                     Blind && !sensemon(mtmp) ? something : a_monnam(mtmp));
2462                 mtmp->mpeaceful = 0;
2463             } else
2464 /*JP
2465                 pline("%s attacks you by surprise!", Amonnam(mtmp));
2466 */
2467                 pline("%s\82Í\8bÁ\82¢\82Ä\82 \82È\82½\82ð\8dU\8c\82\82µ\82½\81I", Amonnam(mtmp));
2468             break;
2469         }
2470         mnexto(mtmp); /* have to move the monster */
2471     }
2472 spotdone:
2473     if (!--inspoteffects) {
2474         spotterrain = STONE; /* 0 */
2475         spotloc.x = spotloc.y = 0;
2476     }
2477     return;
2478 }
2479
2480 /* returns first matching monster */
2481 STATIC_OVL struct monst *
2482 monstinroom(mdat, roomno)
2483 struct permonst *mdat;
2484 int roomno;
2485 {
2486     register struct monst *mtmp;
2487
2488     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2489         if (DEADMONSTER(mtmp))
2490             continue;
2491         if (mtmp->data == mdat
2492             && index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
2493             return mtmp;
2494     }
2495     return (struct monst *) 0;
2496 }
2497
2498 char *
2499 in_rooms(x, y, typewanted)
2500 register xchar x, y;
2501 register int typewanted;
2502 {
2503     static char buf[5];
2504     char rno, *ptr = &buf[4];
2505     int typefound, min_x, min_y, max_x, max_y_offset, step;
2506     register struct rm *lev;
2507
2508 #define goodtype(rno)                                               \
2509     (!typewanted                                                    \
2510      || ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) \
2511      || ((typewanted == SHOPBASE) && (typefound > SHOPBASE)))
2512
2513     switch (rno = levl[x][y].roomno) {
2514     case NO_ROOM:
2515         return ptr;
2516     case SHARED:
2517         step = 2;
2518         break;
2519     case SHARED_PLUS:
2520         step = 1;
2521         break;
2522     default: /* i.e. a regular room # */
2523         if (goodtype(rno))
2524             *(--ptr) = rno;
2525         return ptr;
2526     }
2527
2528     min_x = x - 1;
2529     max_x = x + 1;
2530     if (x < 1)
2531         min_x += step;
2532     else if (x >= COLNO)
2533         max_x -= step;
2534
2535     min_y = y - 1;
2536     max_y_offset = 2;
2537     if (min_y < 0) {
2538         min_y += step;
2539         max_y_offset -= step;
2540     } else if ((min_y + max_y_offset) >= ROWNO)
2541         max_y_offset -= step;
2542
2543     for (x = min_x; x <= max_x; x += step) {
2544         lev = &levl[x][min_y];
2545         y = 0;
2546         if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
2547             && goodtype(rno))
2548             *(--ptr) = rno;
2549         y += step;
2550         if (y > max_y_offset)
2551             continue;
2552         if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
2553             && goodtype(rno))
2554             *(--ptr) = rno;
2555         y += step;
2556         if (y > max_y_offset)
2557             continue;
2558         if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
2559             && goodtype(rno))
2560             *(--ptr) = rno;
2561     }
2562     return ptr;
2563 }
2564
2565 /* is (x,y) in a town? */
2566 boolean
2567 in_town(x, y)
2568 register int x, y;
2569 {
2570     s_level *slev = Is_special(&u.uz);
2571     register struct mkroom *sroom;
2572     boolean has_subrooms = FALSE;
2573
2574     if (!slev || !slev->flags.town)
2575         return FALSE;
2576
2577     /*
2578      * See if (x,y) is in a room with subrooms, if so, assume it's the
2579      * town.  If there are no subrooms, the whole level is in town.
2580      */
2581     for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
2582         if (sroom->nsubrooms > 0) {
2583             has_subrooms = TRUE;
2584             if (inside_room(sroom, x, y))
2585                 return TRUE;
2586         }
2587     }
2588
2589     return !has_subrooms;
2590 }
2591
2592 STATIC_OVL void
2593 move_update(newlev)
2594 register boolean newlev;
2595 {
2596     char *ptr1, *ptr2, *ptr3, *ptr4;
2597
2598     Strcpy(u.urooms0, u.urooms);
2599     Strcpy(u.ushops0, u.ushops);
2600     if (newlev) {
2601         u.urooms[0] = '\0';
2602         u.uentered[0] = '\0';
2603         u.ushops[0] = '\0';
2604         u.ushops_entered[0] = '\0';
2605         Strcpy(u.ushops_left, u.ushops0);
2606         return;
2607     }
2608     Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
2609
2610     for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
2611         ptr4 = &u.ushops_entered[0];
2612          *ptr1; ptr1++) {
2613         if (!index(u.urooms0, *ptr1))
2614             *(ptr2++) = *ptr1;
2615         if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
2616             *(ptr3++) = *ptr1;
2617             if (!index(u.ushops0, *ptr1))
2618                 *(ptr4++) = *ptr1;
2619         }
2620     }
2621     *ptr2 = '\0';
2622     *ptr3 = '\0';
2623     *ptr4 = '\0';
2624
2625     /* filter u.ushops0 -> u.ushops_left */
2626     for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
2627         if (!index(u.ushops, *ptr1))
2628             *(ptr2++) = *ptr1;
2629     *ptr2 = '\0';
2630 }
2631
2632 void
2633 check_special_room(newlev)
2634 register boolean newlev;
2635 {
2636     register struct monst *mtmp;
2637     char *ptr;
2638
2639     move_update(newlev);
2640
2641     if (*u.ushops0)
2642         u_left_shop(u.ushops_left, newlev);
2643
2644     if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
2645         return; /* no entrance messages necessary */
2646
2647     /* Did we just enter a shop? */
2648     if (*u.ushops_entered)
2649         u_entered_shop(u.ushops_entered);
2650
2651     for (ptr = &u.uentered[0]; *ptr; ptr++) {
2652         int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
2653         boolean msg_given = TRUE;
2654
2655         /* Did we just enter some other special room? */
2656         /* vault.c insists that a vault remain a VAULT,
2657          * and temples should remain TEMPLEs,
2658          * but everything else gives a message only the first time */
2659         switch (rt) {
2660         case ZOO:
2661 /*JP
2662             pline("Welcome to David's treasure zoo!");
2663 */
2664             pline("\83f\83r\83b\83g\95ó\94 \93®\95¨\89\80\82É\82æ\82¤\82±\82»\81I");
2665             break;
2666         case SWAMP:
2667 #if 0 /*JP*/
2668             pline("It %s rather %s down here.", Blind ? "feels" : "looks",
2669                   Blind ? "humid" : "muddy");
2670 #else
2671                     pline("\82©\82È\82è%s\81D",
2672                           Blind ? "\8e¼\8bC\82ª\82 \82é\8fê\8f\8a\82Ì\82æ\82¤\82¾"
2673                                 : "\82Ç\82ë\82Ç\82ë\82µ\82Ä\82¢\82é\8fê\8f\8a\82¾");
2674 #endif
2675             break;
2676         case COURT:
2677 /*JP
2678             You("enter an opulent throne room!");
2679 */
2680             You("\89Ø\82â\82©\82È\8bÊ\8dÀ\82Ì\8aÔ\82É\93ü\82Á\82½\81I");
2681             break;
2682         case LEPREHALL:
2683 /*JP
2684             You("enter a leprechaun hall!");
2685 */
2686             You("\83\8c\83v\83\89\83R\81[\83\93\83z\81[\83\8b\82É\93ü\82Á\82½\81I");
2687             break;
2688         case MORGUE:
2689             if (midnight()) {
2690 #if 0 /*JP*/
2691                 const char *run = locomotion(youmonst.data, "Run");
2692                 pline("%s away!  %s away!", run, run);
2693 #else
2694                 pline("\93¦\82°\82ë\81I\93¦\82°\82ë\81I");
2695 #endif
2696             } else
2697 /*JP
2698                 You("have an uncanny feeling...");
2699 */
2700                 You("\95s\8bC\96¡\82È\8a´\82\82ª\82µ\82½\81D\81D\81D");
2701             break;
2702         case BEEHIVE:
2703 /*JP
2704             You("enter a giant beehive!");
2705 */
2706             You("\8b\90\91å\82È\96I\82Ì\91\83\82É\93ü\82Á\82½\81I");
2707             break;
2708         case COCKNEST:
2709 /*JP
2710             You("enter a disgusting nest!");
2711 */
2712             You("\82Þ\82Á\82Æ\82·\82é\8fL\82¢\82Ì\82·\82é\92¹\82Ì\91\83\82É\93ü\82Á\82½\81I");
2713             break;
2714         case ANTHOLE:
2715 /*JP
2716             You("enter an anthole!");
2717 */
2718             You("\83A\83\8a\82Ì\91\83\82É\93ü\82Á\82½\81I");
2719             break;
2720         case BARRACKS:
2721             if (monstinroom(&mons[PM_SOLDIER], roomno)
2722                 || monstinroom(&mons[PM_SERGEANT], roomno)
2723                 || monstinroom(&mons[PM_LIEUTENANT], roomno)
2724                 || monstinroom(&mons[PM_CAPTAIN], roomno))
2725 /*JP
2726                 You("enter a military barracks!");
2727 */
2728                 You("\8cR\91à\82Ì\95ºäq\82É\93ü\82Á\82½\81I");
2729             else
2730 /*JP
2731                 You("enter an abandoned barracks.");
2732 */
2733                 You("\95ú\92u\82³\82ê\82½\82Ü\82Ü\82Ì\95ºäq\82É\93ü\82Á\82½\81D");
2734             break;
2735         case DELPHI: {
2736             struct monst *oracle = monstinroom(&mons[PM_ORACLE], roomno);
2737             if (oracle) {
2738                 if (!oracle->mpeaceful)
2739 /*JP
2740                     verbalize("You're in Delphi, %s.", plname);
2741 */
2742                     verbalize("\82¨\82Ü\82¦\82Í\83f\83\8b\83t\83@\83C\82Ì\90_\91õ\8f\8a\82É\82¢\82é\81D");
2743                 else
2744 #if 0 /*JP*/
2745                     verbalize("%s, %s, welcome to Delphi!",
2746                               Hello((struct monst *) 0), plname);
2747 #else
2748                     verbalize("\82¨\82¨%s\81C\83f\83\8b\83t\83@\83C\82Ì\90_\91õ\8f\8a\82É\82æ\82­\82¼\82Ü\82¢\82ç\82ê\82½\81I",
2749                               plname);
2750 #endif
2751             } else
2752                 msg_given = FALSE;
2753             break;
2754         }
2755         case TEMPLE:
2756             intemple(roomno + ROOMOFFSET);
2757         /*FALLTHRU*/
2758         default:
2759             msg_given = (rt == TEMPLE);
2760             rt = 0;
2761             break;
2762         }
2763         if (msg_given)
2764             room_discovered(roomno);
2765
2766         if (rt != 0) {
2767             rooms[roomno].rtype = OROOM;
2768             if (!search_special(rt)) {
2769                 /* No more room of that type */
2770                 switch (rt) {
2771                 case COURT:
2772                     level.flags.has_court = 0;
2773                     break;
2774                 case SWAMP:
2775                     level.flags.has_swamp = 0;
2776                     break;
2777                 case MORGUE:
2778                     level.flags.has_morgue = 0;
2779                     break;
2780                 case ZOO:
2781                     level.flags.has_zoo = 0;
2782                     break;
2783                 case BARRACKS:
2784                     level.flags.has_barracks = 0;
2785                     break;
2786                 case TEMPLE:
2787                     level.flags.has_temple = 0;
2788                     break;
2789                 case BEEHIVE:
2790                     level.flags.has_beehive = 0;
2791                     break;
2792                 }
2793             }
2794             if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
2795                 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2796                     if (DEADMONSTER(mtmp))
2797                         continue;
2798                     if (!Stealth && !rn2(3))
2799                         mtmp->msleeping = 0;
2800                 }
2801         }
2802     }
2803
2804     return;
2805 }
2806
2807 int
2808 dopickup()
2809 {
2810     int count;
2811     struct trap *traphere = t_at(u.ux, u.uy);
2812     /* awful kludge to work around parse()'s pre-decrement */
2813     count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
2814     multi = 0; /* always reset */
2815     /* uswallow case added by GAN 01/29/87 */
2816     if (u.uswallow) {
2817         if (!u.ustuck->minvent) {
2818             if (is_animal(u.ustuck->data)) {
2819 /*JP
2820                 You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
2821 */
2822                 You("%s\82Ì\90ã\82ð\8fE\82Á\82½\81D", mon_nam(u.ustuck));
2823 /*JP
2824                 pline("But it's kind of slimy, so you drop it.");
2825 */
2826                 pline("\82µ\82©\82µ\81C\82»\82ê\82Í\82Ê\82é\82Ê\82é\82µ\82Ä\95s\89õ\82¾\82Á\82½\82Ì\82Å\8eÌ\82Ä\82Ä\82µ\82Ü\82Á\82½\81D");
2827             } else
2828 #if 0 /*JP*/
2829                 You("don't %s anything in here to pick up.",
2830                     Blind ? "feel" : "see");
2831 #else
2832                 pline("\82±\82±\82É\82Í\8fE\82¦\82é\82à\82Ì\82ª\82È\82¢%s\81D",
2833                     Blind ? "\82æ\82¤\82¾" : "");
2834 #endif
2835             return 1;
2836         } else {
2837             int tmpcount = -count;
2838             return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
2839         }
2840     }
2841     if (is_pool(u.ux, u.uy)) {
2842         if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
2843             || (Flying && !Breathless)) {
2844 /*JP
2845             You("cannot dive into the water to pick things up.");
2846 */
2847             You("\95¨\82ð\8fE\82¢\82 \82°\82é\82½\82ß\82É\90\85\82É\94ò\82Ñ\82±\82ß\82È\82¢\81D");
2848             return 0;
2849         } else if (!Underwater) {
2850 /*JP
2851             You_cant("even see the bottom, let alone pick up %s.", something);
2852 */
2853             pline("\92ê\82³\82¦\8c©\82¦\82È\82¢\81C\8fE\82¤\82Ì\82Í\82â\82ß\82æ\82¤\81D");
2854             return 0;
2855         }
2856     }
2857     if (is_lava(u.ux, u.uy)) {
2858         if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
2859             || (Flying && !Breathless)) {
2860 /*JP
2861             You_cant("reach the bottom to pick things up.");
2862 */
2863             You_cant("\95¨\82ð\8fE\82¢\8fã\82°\82é\82½\82ß\82É\92ê\82Ü\82Å\82¢\82¯\82È\82¢\81D");
2864             return 0;
2865         } else if (!likes_lava(youmonst.data)) {
2866 /*JP
2867             You("would burn to a crisp trying to pick things up.");
2868 */
2869             You("\8fE\82¢\8fã\82°\82æ\82¤\82Æ\82µ\82½\82ç\8aÛ\8fÅ\82°\82É\82È\82Á\82Ä\82µ\82Ü\82¤\82¾\82ë\82¤\81D");
2870             return 0;
2871         }
2872     }
2873     if (!OBJ_AT(u.ux, u.uy)) {
2874         register struct rm *lev = &levl[u.ux][u.uy];
2875         if (IS_THRONE(lev->typ))
2876 /*JP
2877             pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
2878 */
2879             pline("\82±\82ê\82Í%s\8fd\82¢\81I", lev->looted ? "\82©\82È\82è" : "\82·\82²\82­");
2880         else if (IS_SINK(lev->typ))
2881 /*JP
2882             pline_The("plumbing connects it to the floor.");
2883 */
2884             pline_The("\94z\8aÇ\82Í\8f°\82É\82Â\82È\82ª\82Á\82Ä\82¢\82é\81D");
2885         else if (IS_GRAVE(lev->typ))
2886 /*JP
2887             You("don't need a gravestone.  Yet.");
2888 */
2889             pline("\82 \82È\82½\82É\82Í\95æ\90Î\82Í\95s\97v\82¾\81D\81D\81D\8d¡\82Ì\82Æ\82±\82ë\81D");
2890         else if (IS_FOUNTAIN(lev->typ))
2891 /*JP
2892             You("could drink the water...");
2893 */
2894             You("\90\85\82ð\88ù\82ß\82È\82¢\81D\81D\81D");
2895         else if (IS_DOOR(lev->typ) && (lev->doormask & D_ISOPEN))
2896 /*JP
2897             pline("It won't come off the hinges.");
2898 */
2899             pline("\83q\83\93\83W\82ð\8aO\82¹\82È\82¢\81D");
2900         else
2901 /*JP
2902             There("is nothing here to pick up.");
2903 */
2904             pline("\82±\82±\82É\82Í\8fE\82¦\82é\82à\82Ì\82Í\82È\82¢\81D");
2905         return 0;
2906     }
2907     if (!can_reach_floor(TRUE)) {
2908         if (traphere && uteetering_at_seen_pit(traphere))
2909 /*JP
2910             You("cannot reach the bottom of the pit.");
2911 */
2912             You("\97\8e\82µ\8c\8a\82Ì\92ê\82É%s\82ª\93Í\82©\82È\82©\82Á\82½\81D", body_part(HAND));
2913         else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
2914             rider_cant_reach();
2915         else if (Blind && !can_reach_floor(TRUE))
2916 /*JP
2917             You("cannot reach anything here.");
2918 */
2919             You("\89½\82É\82à\93Í\82©\82È\82¢\81D");
2920         else
2921 /*JP
2922             You("cannot reach the %s.", surface(u.ux, u.uy));
2923 */
2924             You("%s\82É\82½\82Ç\82è\82Â\82­\82±\82Æ\82ª\82Å\82«\82È\82¢\81D", surface(u.ux, u.uy));
2925         return 0;
2926     }
2927
2928     return pickup(-count);
2929 }
2930
2931 /* stop running if we see something interesting */
2932 /* turn around a corner if that is the only way we can proceed */
2933 /* do not turn left or right twice */
2934 void
2935 lookaround()
2936 {
2937     register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
2938     register int corrct = 0, noturn = 0;
2939     register struct monst *mtmp;
2940     register struct trap *trap;
2941
2942     /* Grid bugs stop if trying to move diagonal, even if blind.  Maybe */
2943     /* they polymorphed while in the middle of a long move. */
2944     if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
2945         nomul(0);
2946         return;
2947     }
2948
2949     if (Blind || context.run == 0)
2950         return;
2951     for (x = u.ux - 1; x <= u.ux + 1; x++)
2952         for (y = u.uy - 1; y <= u.uy + 1; y++) {
2953             if (!isok(x, y))
2954                 continue;
2955
2956             if (u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy)
2957                 continue;
2958
2959             if (x == u.ux && y == u.uy)
2960                 continue;
2961
2962             if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
2963                 && mtmp->m_ap_type != M_AP_OBJECT
2964                 && (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
2965                 if ((context.run != 1 && !mtmp->mtame)
2966                     || (x == u.ux + u.dx && y == u.uy + u.dy))
2967                     goto stop;
2968             }
2969
2970             if (levl[x][y].typ == STONE)
2971                 continue;
2972             if (x == u.ux - u.dx && y == u.uy - u.dy)
2973                 continue;
2974
2975             if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM)
2976                 || IS_AIR(levl[x][y].typ))
2977                 continue;
2978             else if (closed_door(x, y)
2979                      || (mtmp && is_door_mappear(mtmp))) {
2980                 if (x != u.ux && y != u.uy)
2981                     continue;
2982                 if (context.run != 1)
2983                     goto stop;
2984                 goto bcorr;
2985             } else if (levl[x][y].typ == CORR) {
2986             bcorr:
2987                 if (levl[u.ux][u.uy].typ != ROOM) {
2988                     if (context.run == 1 || context.run == 3
2989                         || context.run == 8) {
2990                         i = dist2(x, y, u.ux + u.dx, u.uy + u.dy);
2991                         if (i > 2)
2992                             continue;
2993                         if (corrct == 1 && dist2(x, y, x0, y0) != 1)
2994                             noturn = 1;
2995                         if (i < i0) {
2996                             i0 = i;
2997                             x0 = x;
2998                             y0 = y;
2999                             m0 = mtmp ? 1 : 0;
3000                         }
3001                     }
3002                     corrct++;
3003                 }
3004                 continue;
3005             } else if ((trap = t_at(x, y)) && trap->tseen) {
3006                 if (context.run == 1)
3007                     goto bcorr; /* if you must */
3008                 if (x == u.ux + u.dx && y == u.uy + u.dy)
3009                     goto stop;
3010                 continue;
3011             } else if (is_pool_or_lava(x, y)) {
3012                 /* water and lava only stop you if directly in front, and stop
3013                  * you even if you are running
3014                  */
3015                 if (!Levitation && !Flying && !is_clinger(youmonst.data)
3016                     && x == u.ux + u.dx && y == u.uy + u.dy)
3017                     /* No Wwalking check; otherwise they'd be able
3018                      * to test boots by trying to SHIFT-direction
3019                      * into a pool and seeing if the game allowed it
3020                      */
3021                     goto stop;
3022                 continue;
3023             } else { /* e.g. objects or trap or stairs */
3024                 if (context.run == 1)
3025                     goto bcorr;
3026                 if (context.run == 8)
3027                     continue;
3028                 if (mtmp)
3029                     continue; /* d */
3030                 if (((x == u.ux - u.dx) && (y != u.uy + u.dy))
3031                     || ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
3032                     continue;
3033             }
3034         stop:
3035             nomul(0);
3036             return;
3037         } /* end for loops */
3038
3039     if (corrct > 1 && context.run == 2)
3040         goto stop;
3041     if ((context.run == 1 || context.run == 3 || context.run == 8) && !noturn
3042         && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) {
3043         /* make sure that we do not turn too far */
3044         if (i0 == 2) {
3045             if (u.dx == y0 - u.uy && u.dy == u.ux - x0)
3046                 i = 2; /* straight turn right */
3047             else
3048                 i = -2; /* straight turn left */
3049         } else if (u.dx && u.dy) {
3050             if ((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
3051                 i = -1; /* half turn left */
3052             else
3053                 i = 1; /* half turn right */
3054         } else {
3055             if ((x0 - u.ux == y0 - u.uy && !u.dy)
3056                 || (x0 - u.ux != y0 - u.uy && u.dy))
3057                 i = 1; /* half turn right */
3058             else
3059                 i = -1; /* half turn left */
3060         }
3061
3062         i += u.last_str_turn;
3063         if (i <= 2 && i >= -2) {
3064             u.last_str_turn = i;
3065             u.dx = x0 - u.ux;
3066             u.dy = y0 - u.uy;
3067         }
3068     }
3069 }
3070
3071 /* check for a doorway which lacks its door (NODOOR or BROKEN) */
3072 STATIC_OVL boolean
3073 doorless_door(x, y)
3074 int x, y;
3075 {
3076     struct rm *lev_p = &levl[x][y];
3077
3078     if (!IS_DOOR(lev_p->typ))
3079         return FALSE;
3080     /* all rogue level doors are doorless but disallow diagonal access, so
3081        we treat them as if their non-existant doors were actually present */
3082     if (Is_rogue_level(&u.uz))
3083         return FALSE;
3084     return !(lev_p->doormask & ~(D_NODOOR | D_BROKEN));
3085 }
3086
3087 /* used by drown() to check whether hero can crawl from water to <x,y> */
3088 boolean
3089 crawl_destination(x, y)
3090 int x, y;
3091 {
3092     /* is location ok in general? */
3093     if (!goodpos(x, y, &youmonst, 0))
3094         return FALSE;
3095
3096     /* orthogonal movement is unrestricted when destination is ok */
3097     if (x == u.ux || y == u.uy)
3098         return TRUE;
3099
3100     /* diagonal movement has some restrictions */
3101     if (NODIAG(u.umonnum))
3102         return FALSE; /* poly'd into a grid bug... */
3103     if (Passes_walls)
3104         return TRUE; /* or a xorn... */
3105     /* pool could be next to a door, conceivably even inside a shop */
3106     if (IS_DOOR(levl[x][y].typ) && (!doorless_door(x, y) || block_door(x, y)))
3107         return FALSE;
3108     /* finally, are we trying to squeeze through a too-narrow gap? */
3109     return !(bad_rock(youmonst.data, u.ux, y)
3110              && bad_rock(youmonst.data, x, u.uy));
3111 }
3112
3113 /* something like lookaround, but we are not running */
3114 /* react only to monsters that might hit us */
3115 int
3116 monster_nearby()
3117 {
3118     register int x, y;
3119     register struct monst *mtmp;
3120
3121     /* Also see the similar check in dochugw() in monmove.c */
3122     for (x = u.ux - 1; x <= u.ux + 1; x++)
3123         for (y = u.uy - 1; y <= u.uy + 1; y++) {
3124             if (!isok(x, y))
3125                 continue;
3126             if (x == u.ux && y == u.uy)
3127                 continue;
3128             if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
3129                 && mtmp->m_ap_type != M_AP_OBJECT
3130                 && (!mtmp->mpeaceful || Hallucination)
3131                 && (!is_hider(mtmp->data) || !mtmp->mundetected)
3132                 && !noattacks(mtmp->data) && mtmp->mcanmove
3133                 && !mtmp->msleeping  /* aplvax!jcn */
3134                 && !onscary(u.ux, u.uy, mtmp) && canspotmon(mtmp))
3135                 return 1;
3136         }
3137     return 0;
3138 }
3139
3140 void
3141 nomul(nval)
3142 register int nval;
3143 {
3144     if (multi < nval)
3145         return;              /* This is a bug fix by ab@unido */
3146     u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
3147     u.usleep = 0;
3148     multi = nval;
3149     if (nval == 0)
3150         multi_reason = NULL;
3151     context.travel = context.travel1 = context.mv = context.run = 0;
3152 }
3153
3154 /* called when a non-movement, multi-turn action has completed */
3155 void
3156 unmul(msg_override)
3157 const char *msg_override;
3158 {
3159     multi = 0; /* caller will usually have done this already */
3160     if (msg_override)
3161         nomovemsg = msg_override;
3162     else if (!nomovemsg)
3163         nomovemsg = You_can_move_again;
3164     if (*nomovemsg)
3165         pline1(nomovemsg);
3166     nomovemsg = 0;
3167     u.usleep = 0;
3168     multi_reason = NULL;
3169     if (afternmv)
3170         (*afternmv)();
3171     afternmv = 0;
3172 }
3173
3174 STATIC_OVL void
3175 maybe_wail()
3176 {
3177     static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES,
3178                               SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
3179                               TELEPORT_CONTROL, STEALTH, FAST, INVIS };
3180
3181     if (moves <= wailmsg + 50)
3182         return;
3183
3184     wailmsg = moves;
3185     if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) {
3186         const char *who;
3187         int i, powercnt;
3188
3189 #if 0 /*JP*/
3190         who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3191                                                            : "Elf";
3192 #else
3193         who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3194                                                            : "\83G\83\8b\83t";
3195 #endif
3196         if (u.uhp == 1) {
3197 /*JP
3198             pline("%s is about to die.", who);
3199 */
3200             pline("%s\82Í\8e\80\82É\82©\82¯\82Ä\82¢\82é\81D", who);
3201         } else {
3202             for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
3203                 if (u.uprops[powers[i]].intrinsic & INTRINSIC)
3204                     ++powercnt;
3205
3206 /*JP
3207             pline(powercnt >= 4 ? "%s, all your powers will be lost..."
3208 */
3209             pline(powercnt >= 4 ? "%s\81C\82 \82È\82½\82Ì\91S\82Ä\82Ì\97Í\82Í\8e¸\82í\82ê\82Â\82Â\82 \82é\81D\81D\81D"
3210 /*JP
3211                                 : "%s, your life force is running out.",
3212 */
3213                                 : "%s\81C\82 \82È\82½\82Ì\90\96½\97Í\82Í\90s\82«\82æ\82¤\82Æ\82µ\82Ä\82¢\82é\81D\81D\81D",
3214                   who);
3215         }
3216     } else {
3217 /*JP
3218         You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
3219 */
3220         You_hear(u.uhp == 1 ? "\83o\83\93\83V\81[\82Ì\82·\82·\82è\8b\83\82«\82ª\95·\82±\82¦\82é\81D\81D\81D"
3221 /*JP
3222                             : "the howling of the CwnAnnwn...");
3223 */
3224                             : "\83N\81[\83\93\81E\83A\83\93\83k\81[\83\93\82Ì\89\93\96i\82ª\95·\82±\82¦\82é\81D\81D\81D");
3225     }
3226 }
3227
3228 void
3229 losehp(n, knam, k_format)
3230 register int n;
3231 register const char *knam;
3232 boolean k_format;
3233 {
3234     if (Upolyd) {
3235         u.mh -= n;
3236         if (u.mhmax < u.mh)
3237             u.mhmax = u.mh;
3238         context.botl = 1;
3239         if (u.mh < 1)
3240             rehumanize();
3241         else if (n > 0 && u.mh * 10 < u.mhmax && Unchanging)
3242             maybe_wail();
3243         return;
3244     }
3245
3246     u.uhp -= n;
3247     if (u.uhp > u.uhpmax)
3248         u.uhpmax = u.uhp; /* perhaps n was negative */
3249     context.botl = 1;
3250     if (u.uhp < 1) {
3251         killer.format = k_format;
3252         if (killer.name != knam) /* the thing that killed you */
3253             Strcpy(killer.name, knam ? knam : "");
3254 /*JP
3255         You("die...");
3256 */
3257         pline("\82 \82È\82½\82Í\8e\80\82É\82Ü\82µ\82½\81D\81D\81D");
3258         done(DIED);
3259     } else if (n > 0 && u.uhp * 10 < u.uhpmax) {
3260         maybe_wail();
3261     }
3262 }
3263
3264 int
3265 weight_cap()
3266 {
3267     register long carrcap;
3268
3269     carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
3270     if (Upolyd) {
3271         /* consistent with can_carry() in mon.c */
3272         if (youmonst.data->mlet == S_NYMPH)
3273             carrcap = MAX_CARR_CAP;
3274         else if (!youmonst.data->cwt)
3275             carrcap = (carrcap * (long) youmonst.data->msize) / MZ_HUMAN;
3276         else if (!strongmonst(youmonst.data)
3277                  || (strongmonst(youmonst.data)
3278                      && (youmonst.data->cwt > WT_HUMAN)))
3279             carrcap = (carrcap * (long) youmonst.data->cwt / WT_HUMAN);
3280     }
3281
3282     if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
3283         || (u.usteed && strongmonst(u.usteed->data)))
3284         carrcap = MAX_CARR_CAP;
3285     else {
3286         if (carrcap > MAX_CARR_CAP)
3287             carrcap = MAX_CARR_CAP;
3288         if (!Flying) {
3289             if (EWounded_legs & LEFT_SIDE)
3290                 carrcap -= 100;
3291             if (EWounded_legs & RIGHT_SIDE)
3292                 carrcap -= 100;
3293         }
3294         if (carrcap < 0)
3295             carrcap = 0;
3296     }
3297     return (int) carrcap;
3298 }
3299
3300 static int wc; /* current weight_cap(); valid after call to inv_weight() */
3301
3302 /* returns how far beyond the normal capacity the player is currently. */
3303 /* inv_weight() is negative if the player is below normal capacity. */
3304 int
3305 inv_weight()
3306 {
3307     register struct obj *otmp = invent;
3308     register int wt = 0;
3309
3310     while (otmp) {
3311         if (otmp->oclass == COIN_CLASS)
3312             wt += (int) (((long) otmp->quan + 50L) / 100L);
3313         else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
3314             wt += otmp->owt;
3315         otmp = otmp->nobj;
3316     }
3317     wc = weight_cap();
3318     return (wt - wc);
3319 }
3320
3321 /*
3322  * Returns 0 if below normal capacity, or the number of "capacity units"
3323  * over the normal capacity the player is loaded.  Max is 5.
3324  */
3325 int
3326 calc_capacity(xtra_wt)
3327 int xtra_wt;
3328 {
3329     int cap, wt = inv_weight() + xtra_wt;
3330
3331     if (wt <= 0)
3332         return UNENCUMBERED;
3333     if (wc <= 1)
3334         return OVERLOADED;
3335     cap = (wt * 2 / wc) + 1;
3336     return min(cap, OVERLOADED);
3337 }
3338
3339 int
3340 near_capacity()
3341 {
3342     return calc_capacity(0);
3343 }
3344
3345 int
3346 max_capacity()
3347 {
3348     int wt = inv_weight();
3349
3350     return (wt - (2 * wc));
3351 }
3352
3353 boolean
3354 check_capacity(str)
3355 const char *str;
3356 {
3357     if (near_capacity() >= EXT_ENCUMBER) {
3358         if (str)
3359             pline1(str);
3360         else
3361 /*JP
3362             You_cant("do that while carrying so much stuff.");
3363 */
3364             You("\91ò\8eR\82à\82Ì\82ð\8e\9d\82¿\82·\82¬\82Ä\82¢\82é\82Ì\82Å\81C\82»\82ñ\82È\82±\82Æ\82Í\82Å\82«\82È\82¢\81D");
3365         return 1;
3366     }
3367     return 0;
3368 }
3369
3370 int
3371 inv_cnt(incl_gold)
3372 boolean incl_gold;
3373 {
3374     register struct obj *otmp = invent;
3375     register int ct = 0;
3376
3377     while (otmp) {
3378         if (incl_gold || otmp->invlet != GOLD_SYM)
3379             ct++;
3380         otmp = otmp->nobj;
3381     }
3382     return ct;
3383 }
3384
3385 /* Counts the money in an object chain. */
3386 /* Intended use is for your or some monsters inventory, */
3387 /* now that u.gold/m.gold is gone.*/
3388 /* Counting money in a container might be possible too. */
3389 long
3390 money_cnt(otmp)
3391 struct obj *otmp;
3392 {
3393     while (otmp) {
3394         /* Must change when silver & copper is implemented: */
3395         if (otmp->oclass == COIN_CLASS)
3396             return otmp->quan;
3397         otmp = otmp->nobj;
3398     }
3399     return 0L;
3400 }
3401
3402 /*hack.c*/