OSDN Git Service

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