OSDN Git Service

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