OSDN Git Service

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