OSDN Git Service

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