OSDN Git Service

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