OSDN Git Service

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