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. */
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. */
13 /* #define DEBUG */ /* uncomment for debugging */
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);
27 #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
29 /* mode values for findtravelpath() */
30 #define TRAVP_TRAVEL 0
34 static anything tmp_anything;
40 tmp_anything = zeroany;
41 tmp_anything.a_uint = ui;
49 tmp_anything = zeroany;
50 tmp_anything.a_long = lng;
58 tmp_anything = zeroany;
59 tmp_anything.a_monst = mtmp;
67 tmp_anything = zeroany;
68 tmp_anything.a_obj = obj;
73 revive_nasty(x, y, msg)
77 register struct obj *otmp, *otmp2;
80 boolean revived = FALSE;
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);
92 revived = revive_corpse(otmp);
96 /* this location might not be safe, if not, move revived monster */
99 if (mtmp && !goodpos(x, y, mtmp, 0)
100 && enexto(&cc, x, y, mtmp->data)) {
101 rloc_to(mtmp, cc.x, cc.y);
103 /* else impossible? */
112 register xchar rx, ry, sx, sy;
113 register struct obj *otmp;
114 register struct trap *ttmp;
115 register struct monst *mtmp;
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);
123 rx = u.ux + 2 * u.dx; /* boulder destination position */
124 ry = u.uy + 2 * u.dy;
126 if (Levitation || Is_airlevel(&u.uz)) {
128 feel_location(sx, sy);
130 You("don't have enough leverage to push %s.", the(xname(otmp)));
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? */
136 if (verysmall(youmonst.data) && !u.usteed) {
138 feel_location(sx, sy);
140 pline("You're too small to push that %s.", xname(otmp));
142 You("
\8f¬
\82³
\82·
\82¬
\82Ä%s
\82ð
\89\9f\82¹
\82È
\82¢
\81D",xname(otmp));
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)) {
152 /* KMH -- Sokoban doesn't let you push boulders diagonally */
153 if (Sokoban && u.dx && u.dy) {
155 feel_location(sx, sy);
157 pline("%s won't roll diagonally on this %s.",
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));
165 if (revive_nasty(rx, ry, "You sense movement on the other side."))
167 if (revive_nasty(rx, ry, "
\94½
\91Î
\91¤
\82É
\93®
\82«
\82ð
\8a´
\82¶
\82½
\81D"))
170 if (mtmp && !noncorporeal(mtmp->data)
172 || !(ttmp && is_pit(ttmp->ttyp)))) {
173 boolean deliver_part1 = FALSE;
176 feel_location(sx, sy);
177 if (canspotmon(mtmp)) {
179 pline("There's %s on the other side.", a_monnam(mtmp));
181 pline("
\94½
\91Î
\91¤
\82É%s
\82ª
\82¢
\82é
\81D", a_monnam(mtmp));
182 deliver_part1 = TRUE;
185 You_hear("a monster behind %s.", the(xname(otmp)));
187 pline("%s
\82Ì
\94w
\8cã
\82É
\89ö
\95¨
\82Ì
\8bC
\94z
\82ª
\82·
\82é
\81D", the(xname(otmp)));
189 deliver_part1 = TRUE;
190 map_invisible(rx, ry);
193 char you_or_steed[BUFSZ];
197 u.usteed ? y_monnam(u.usteed) : "you");
200 u.usteed ? y_monnam(u.usteed) : "
\82 \82È
\82½");
203 pline("%s%s cannot move %s.",
205 ? "Perhaps that's why "
209 : upstart(you_or_steed),
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",
217 ? "
\82½
\82Ô
\82ñ
\82±
\82ê
\82ª
\81C"
221 : upstart(you_or_steed),
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) {
238 obj_extract_self(otmp);
239 place_object(otmp, rx, ry);
242 pline("KAABLAMM!!! %s %s land mine.",
243 Tobjnam(otmp, "trigger"),
244 ttmp->madeby_u ? "your" : "a");
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",
248 ttmp->madeby_u ? "
\82 \82È
\82½
\82Ì
\8ed
\8a|
\82¯
\82½" : "");
250 blow_up_landmine(ttmp);
251 /* if the boulder remains, it should fill the pit */
252 fill_pit(u.ux, u.uy);
255 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
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 */
265 viz_array[ry][rx] |= IN_SIGHT;
267 if (!flooreffects(otmp, rx, ry, "fall")) {
269 if (!flooreffects(otmp, rx, ry, "
\97\8e\82¿
\82é")) {
270 place_object(otmp, rx, ry);
274 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
279 pline("Kerplunk! You no longer feel %s.",
281 pline("
\83h
\83T
\83b
\81I
\82 \82È
\82½
\82Í
\82à
\82¤%s
\82ð
\8a´
\82¶
\82ç
\82ê
\82È
\82¢
\81D",
285 pline("%s%s and %s a %s in the %s!",
286 Tobjnam(otmp, (ttmp->ttyp == TRAPDOOR)
289 (ttmp->ttyp == TRAPDOOR) ? "" : " into",
290 otense(otmp, "plug"),
291 (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
294 pline("%s
\82Í
\97\8e\82¿
\82Ä%s
\82Ì%s
\82ð
\96\84\82ß
\82½
\81I",
297 (ttmp->ttyp == TRAPDOOR) ? "
\97\8e\82µ
\94à" : "
\8c\8a");
302 levl[rx][ry].wall_info &= ~W_NONDIGGABLE;
303 levl[rx][ry].candig = 1;
306 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
309 int newlev = 0; /* lint suppression */
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 */
320 pline("%s pushes %s and suddenly it disappears!",
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)));
326 You("push %s and suddenly it disappears!",
328 pline("
\82 \82È
\82½
\82ª%s
\82ð
\89\9f\82·
\82Æ
\81C
\93Ë
\91R
\82»
\82ê
\82Í
\8fÁ
\96Å
\82µ
\82½
\81I",
330 if (ttmp->ttyp == TELEP_TRAP) {
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;
341 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
344 break; /* boulder not affected by this trap */
348 if (closed_door(rx, ry))
350 if (boulder_hits_pool(otmp, rx, ry, TRUE))
353 * Re-link at top of fobj chain so that pile order is preserved
354 * when level is restored.
358 place_object(otmp, otmp->ox, otmp->oy);
362 #ifdef LINT /* static long lastmovetime; */
366 /* note: reset to zero after save/restore cycle */
367 static NEARDATA long lastmovetime;
371 if (moves > lastmovetime + 2 || moves < lastmovetime)
373 pline("With %s effort you move %s.",
374 throws_rocks(youmonst.data) ? "little"
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è",
382 exercise(A_STR, TRUE);
385 pline("%s moves %s.", upstart(y_monnam(u.usteed)),
388 pline("%s
\82Í%s
\82ð
\93®
\82©
\82µ
\82½
\81D", upstart(y_monnam(u.usteed)),
391 lastmovetime = moves;
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) */
399 feel_location(rx, ry);
400 feel_location(sx, sy);
408 pline("%s tries to move %s, but cannot.",
409 upstart(y_monnam(u.usteed)), the(xname(otmp)));
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)));
416 You("try to move %s, but in vain.", the(xname(otmp)));
418 You("%s
\82ð
\93®
\82©
\82»
\82¤
\82Æ
\82µ
\82½
\82ª
\81C
\82¾
\82ß
\82¾
\82Á
\82½
\81D", the(xname(otmp)));
420 feel_location(sx, sy);
422 if (throws_rocks(youmonst.data)) {
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));
433 if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
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));
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¹");
445 * willpickup: you easily pick it up
446 * canpickup: you could easily pick it up
447 * otherwise: you easily push it aside
450 pline("However, you %seasily %s.",
451 (willpickup || !canpickup) ? "" : "could ",
452 (willpickup || canpickup) ? "pick it up"
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½");
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))) {
472 "However, you can squeeze yourself into a small opening.");
474 "
\82µ
\82©
\82µ
\81C
\82 \82È
\82½
\82Í
\8f¬
\82³
\82¢
\8c\84\8aÔ
\82É
\82±
\82¶
\93ü
\82Á
\82½
\81D");
487 * Chew on a wall, door, or boulder. [What about statues?]
488 * Returns TRUE if still eating, FALSE when done.
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;
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));
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)))) {
507 You("hurt your teeth on the %s.",
508 (lev->typ == IRONBARS)
514 You("%s
\82Å
\8e\95\82ð
\92É
\82ß
\82½
\81D",
515 (lev->typ == IRONBARS)
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;
535 You("start chewing %s %s.",
536 (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
545 : (lev->typ == IRONBARS)
549 You("%s%s
\82Í
\82¶
\82ß
\82½
\81D",
556 : lev->typ == IRONBARS
559 (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
561 : "
\82É
\8c\8a\82ð
\82 \82¯");
563 watch_dig((struct monst *) 0, x, y, FALSE);
565 } else if ((context.digging.effort += (30 + u.udaminc)) <= 100) {
568 You("%s chewing on the %s.",
569 context.digging.chew ? "continue" : "begin",
576 : (lev->typ == IRONBARS)
580 You("%s
\82ð
\8a\9a\82Ý%s
\81D",
587 : lev->typ == IRONBARS
590 context.digging.chew ? "
\91±
\82¯
\82½" : "
\82Í
\82¶
\82ß
\82½");
592 context.digging.chew = TRUE;
593 watch_dig((struct monst *) 0, x, y, FALSE);
597 /* Okay, you've chewed through something */
599 u.uhunger += rnd(20);
602 delobj(boulder); /* boulder goes bye-bye */
604 You("eat the boulder."); /* yum */
606 You("
\8aâ
\82ð
\90H
\82×
\82½
\81D"); /* yum */
610 * The location could still block because of
611 * 1. More than one boulder
612 * 2. Boulder stuck in a wall/stone/door.
614 * [perhaps use does_block() below (from vision.c)]
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));
625 } else if (IS_WALL(lev->typ)) {
626 if (*in_rooms(x, y, SHOPBASE)) {
627 add_damage(x, y, SHOP_WALL_DMG);
631 dmgtxt = "
\8f\9d\82Â
\82¯
\82é";
634 digtxt = "chew a hole in the wall.";
636 digtxt = "
\95Ç
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
637 if (level.flags.is_maze_lev) {
639 } else if (level.flags.is_cavernous_lev && !in_town(x, y)) {
643 lev->doormask = D_NODOOR;
645 } else if (IS_TREE(lev->typ)) {
647 digtxt = "chew through the tree.";
649 digtxt = "
\96Ø
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
651 } else if (lev->typ == IRONBARS) {
653 digtxt = "eat through the bars.";
655 digtxt = "
\93S
\82Ì
\96_
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
657 } else if (lev->typ == SDOOR) {
658 if (lev->doormask & D_TRAPPED) {
659 lev->doormask = D_NODOOR;
661 b_trapped("secret door", 0);
663 b_trapped("
\94é
\96§
\82Ì
\94à", 0);
666 digtxt = "chew through the secret door.";
668 digtxt = "
\94é
\96§
\82Ì
\94à
\82ð
\8a\9a\82Ý
\8dÓ
\82¢
\82½
\81D";
669 lev->doormask = D_BROKEN;
673 } else if (IS_DOOR(lev->typ)) {
674 if (*in_rooms(x, y, SHOPBASE)) {
675 add_damage(x, y, SHOP_DOOR_COST);
681 if (lev->doormask & D_TRAPPED) {
682 lev->doormask = D_NODOOR;
684 b_trapped("door", 0);
686 b_trapped("
\94à", 0);
689 digtxt = "chew through the door.";
691 digtxt = "
\94à
\82ð
\8dÓ
\82¢
\82½
\81D";
692 lev->doormask = D_BROKEN;
695 } else { /* STONE or SCORR */
697 digtxt = "chew a passage through the rock.";
699 digtxt = "
\8aâ
\82ð
\8a\9a\82Ý
\8dÓ
\82¢
\82Ä
\92Ê
\82è
\94²
\82¯
\82½
\81D";
703 unblock_point(x, y); /* vision */
706 You1(digtxt); /* after newsym */
708 pay_for_damage(dmgtxt, FALSE);
709 (void) memset((genericptr_t) &context.digging, 0,
710 sizeof (struct dig_info));
716 register struct obj *obj;
717 register xchar ox, oy;
719 /* optimize by leaving on the fobj chain? */
721 newsym(obj->ox, obj->oy);
722 place_object(obj, ox, oy);
727 static NEARDATA const char fell_on_sink[] = "fell onto a sink";
729 static NEARDATA const char fell_on_sink[] = "
\97¬
\82µ
\91ä
\82É
\97\8e\82¿
\82Ä";
734 register struct obj *obj;
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 */
748 You((innate_lev || blockd_lev) ? "wobble unsteadily for a moment."
750 You((innate_lev || blockd_lev) ? "
\82¿
\82å
\82Á
\82Æ
\82Ó
\82ç
\82Â
\82¢
\82½
\81D"
752 : "gain control of your flight.");
754 : "
\94ò
\8ds
\92\86\82Ì
\90§
\8cä
\82ð
\8eæ
\82è
\82à
\82Ç
\82µ
\82½
\81D");
756 long save_ELev = ELevitation, save_HLev = HLevitation;
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;
764 You("crash to the floor!");
766 You("
\8f°
\82É
\92@
\82«
\82Â
\82¯
\82ç
\82ê
\82½
\81I");
767 dmg = rn1(8, 25 - (int) ACURR(A_CON));
769 losehp(Maybe_Half_Phys(dmg), fell_on_sink, NO_KILLER_PREFIX);
771 losehp(Maybe_Half_Phys(dmg), fell_on_sink, KILLED_BY);
773 exercise(A_DEX, FALSE);
775 selftouch("Falling, you");
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)) {
781 You("fell on %s.", doname(obj));
783 You("%s
\82Ì
\8fã
\82É
\97\8e\82¿
\82½
\81D",doname(obj));
785 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
788 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
791 exercise(A_CON, FALSE);
793 ELevitation = save_ELev;
794 HLevitation = save_HLev;
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]).
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).
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);
815 /* remove worn levitation items */
816 ELevitation &= ~W_ARTI;
817 HLevitation &= ~(I_SPECIAL | TIMEOUT);
819 if (uleft && uleft->otyp == RIN_LEVITATION) {
824 if (uright && uright->otyp == RIN_LEVITATION) {
835 /* probably moot; we're either still levitating or went
836 through float_down(), but make sure BFlying is up to date */
840 /* intended to be called only on ROCKs or TREEs */
845 struct rm *lev = &levl[x][y];
847 return (boolean) !((IS_STWALL(lev->typ) || IS_TREE(lev->typ))
848 && (lev->wall_info & W_NONDIGGABLE));
855 return (boolean) !(IS_STWALL(levl[x][y].typ)
856 && (levl[x][y].wall_info & W_NONPASSWALL));
861 struct permonst *mdat;
864 return (boolean) ((Sokoban && sobj_at(BOULDER, x, y))
865 || (IS_ROCK(levl[x][y].typ)
866 && (!tunnels(mdat) || needspick(mdat)
868 && !(passes_walls(mdat) && may_passwall(x, y))));
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 */
876 cant_squeeze_thru(mon)
880 struct permonst *ptr = mon->data;
884 && !(amorphous(ptr) || is_whirly(ptr) || noncorporeal(ptr)
885 || slithy(ptr) || can_fog(mon)))
888 /* lugging too much junk? */
889 amt = (mon == &youmonst) ? inv_weight() + weight_cap()
890 : curr_mon_load(mon);
894 /* Sokoban restriction applies to hero only */
895 if (mon == &youmonst && Sokoban)
898 /* can squeeze through */
906 return (boolean) (Invocation_lev(&u.uz)
907 && x == inv_pos.x && y == inv_pos.y);
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
914 test_move(ux, uy, dx, dy, mode)
920 register struct rm *tmpr = &levl[x][y];
921 register struct rm *ust;
923 context.door_opened = FALSE;
925 * Check for physical obstacles. First, the place we are going.
927 if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) {
928 if (Blind && mode == DO_MOVE)
930 if (Passes_walls && may_passwall(x, y)) {
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 */
939 pline("There is an obstacle there.");
941 pline("
\8fá
\8aQ
\95¨
\82ª
\82 \82é
\81D");
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)) {
949 if (!(Passes_walls || passes_bars(youmonst.data))) {
950 if (mode == DO_MOVE && iflags.mention_walls)
952 You("cannot pass through the bars.");
954 You("
\93S
\82Ì
\96_
\82ð
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
957 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
959 if (mode == DO_MOVE && still_chewing(x, y))
961 } else if (flags.autodig && !context.run && !context.nopick && uwep
963 /* MRKR: Automatic digging when wielding the appropriate tool */
965 (void) use_pick_axe2(uwep);
968 if (mode == DO_MOVE) {
969 if (is_db_wall(x, y))
971 pline("That drawbridge is up!");
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))
978 pline_The("Sokoban walls resist your ability.");
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)
984 (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "a wall"
985 : IS_TREE(tmpr->typ) ? "a tree"
988 pline("
\82±
\82ê
\82Í%s
\82¾
\81D",
989 (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "
\95Ç"
990 : IS_TREE(tmpr->typ) ? "
\96Ø"
996 } else if (IS_DOOR(tmpr->typ)) {
997 if (closed_door(x, y)) {
998 if (Blind && mode == DO_MOVE)
1002 } else if (can_ooze(&youmonst)) {
1003 if (mode == DO_MOVE)
1005 You("ooze under the door.");
1007 You("
\83h
\83A
\82Ì
\89º
\82©
\82ç
\82É
\82¶
\82Ý
\8fo
\82½
\81D");
1008 } else if (Underwater) {
1009 if (mode == DO_MOVE)
1011 pline("There is an obstacle there.");
1013 pline("
\8fá
\8aQ
\95¨
\82ª
\82 \82é
\81D");
1015 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
1017 if (mode == DO_MOVE && still_chewing(x, y))
1020 if (mode == DO_MOVE) {
1021 if (amorphous(youmonst.data))
1024 "try to ooze under the door, but can't squeeze your possessions through.");
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 =
1031 } else if (x == ux || y == uy) {
1032 if (Blind || Stunned || ACURR(A_DEX) < 10
1036 You_cant("lead %s through that closed door.",
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));
1042 pline("Ouch! You bump into a door.");
1044 pline("
\82¢
\82Ä
\82Á
\81I
\93ª
\82ð
\94à
\82É
\82Ô
\82Â
\82¯
\82½
\81D");
1045 exercise(A_DEX, FALSE);
1049 pline("That door is closed.");
1051 pline("
\94à
\82Í
\95Â
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D");
1053 } else if (mode == TEST_TRAV || mode == TEST_TRAP)
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) {
1064 feel_location(x, y);
1065 if (Underwater || iflags.mention_walls)
1067 You_cant("move diagonally into an intact doorway.");
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");
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)) {
1080 if (mode == DO_MOVE)
1082 You("cannot pass that way.");
1084 You("
\92Ê
\82è
\82Ê
\82¯
\82Å
\82«
\82È
\82¢
\81D");
1087 if (mode == DO_MOVE)
1089 You("are carrying too much to get through.");
1091 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1094 if (mode == DO_MOVE)
1096 Your("body is too large to fit through.");
1098 Your("
\91Ì
\82ª
\91å
\82«
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1101 break; /* can squeeze through */
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)
1107 pline("%s is in your way.", Monnam(m_at(ux, y)));
1109 pline("
\93¹
\82Ì
\93r
\92\86\82É%s
\82ª
\82¢
\82é
\81D", Monnam(m_at(ux, y)));
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);
1120 || (!Levitation && !Flying && !is_clinger(youmonst.data)
1121 && is_pool_or_lava(x, y) && levl[x][y].seenv))
1122 return (mode == TEST_TRAP);
1125 if (mode == TEST_TRAP)
1126 return FALSE; /* do not move through traps */
1128 ust = &levl[ux][uy];
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)
1136 You_cant("move diagonally out of an intact doorway.");
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");
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)
1147 pline("A boulder blocks your path.");
1149 pline("
\8b\90\8aâ
\82ª
\93¹
\82ð
\82Ó
\82³
\82¢
\82Å
\82¢
\82é
\81D");
1152 if (mode == DO_MOVE) {
1153 /* tunneling monsters will chew before pushing */
1154 if (tunnels(youmonst.data) && !needspick(youmonst.data)
1156 if (still_chewing(x, y))
1158 } else if (moverock() < 0)
1160 } else if (mode == TEST_TRAV) {
1163 /* never travel through boulders in Sokoban */
1167 /* don't pick two boulders in a row, unless there's a way thru */
1168 if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
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))
1177 /* assume you'll be able to push it when you get there... */
1180 /* OK, it is a legal place to move. */
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.
1191 findtravelpath(mode)
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))) {
1199 if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
1200 if (mode == TRAVP_TRAVEL) {
1204 iflags.travelcc.x = iflags.travelcc.y = 0;
1208 if (mode == TRAVP_TRAVEL)
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 */
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.
1225 if (mode == TRAVP_GUESS || mode == TRAVP_VALID) {
1238 (void) memset((genericptr_t) travel, 0, sizeof travel);
1239 travelstepx[0][0] = tx;
1240 travelstepy[0][0] = ty;
1245 for (i = 0; i < n; i++) {
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;
1254 for (dir = 0; dir < dirmax; ++dir) {
1255 int nx = x + xdir[ordered[dir]];
1256 int ny = y + ydir[ordered[dir]];
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.
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.
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.
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.
1291 * By limiting the travel matrix here, space a in the
1292 * example above is never included in it, preventing
1296 || ((mode == TRAVP_GUESS) && !couldsee(nx, ny)))
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! */
1309 alreadyrepeated = TRUE;
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) {
1321 if (mode == TRAVP_TRAVEL
1322 && x == u.tx && y == u.ty) {
1324 /* reset run so domove run checks work */
1326 iflags.travelcc.x = iflags.travelcc.y = 0;
1330 } else if (!travel[nx][ny]) {
1331 travelstepx[1 - set][nn] = nx;
1332 travelstepy[1 - set][nn] = ny;
1333 travel[nx][ny] = radius;
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]);
1348 if (flags.runmode == RUN_CRAWL) {
1352 tmp_at(DISP_END, 0);
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;
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);
1375 /* prefer non-zigzag path */
1380 } else if (nxtdist < dist && couldsee(tx, ty)) {
1384 d2 = dist2(ux, uy, tx, ty);
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))
1397 if (iflags.trav_debug) {
1398 /* Use of warning glyph is arbitrary. It stands out. */
1399 tmp_at(DISP_ALL, warning_to_glyph(2));
1402 if (flags.runmode == RUN_CRAWL) {
1408 tmp_at(DISP_END, 0);
1417 mode = TRAVP_TRAVEL;
1431 is_valid_travelpt(x,y)
1437 int g = glyph_at(x,y);
1439 if (x == u.ux && y == u.uy)
1441 if (isok(x,y) && glyph_is_cmap(g) && S_stone == glyph_to_cmap(g)
1442 && !levl[x][y].seenv)
1446 ret = findtravelpath(TRAVP_VALID);
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) */
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> */
1460 boolean anchored = FALSE;
1461 const char *predicament, *culprit;
1462 char *steedname = !u.usteed ? (char *) 0 : y_monnam(u.usteed);
1465 return TRUE; /* sanity check */
1468 * Note: caller should call reset_utrap() when we set u.utrap to 0.
1471 switch (u.utraptype) {
1473 if (flags.verbose) {
1475 predicament = "caught in a bear trap";
1477 predicament = "
\8cF
\82Ìã©
\82É
\82Â
\82©
\82Ü
\82Á
\82½";
1480 Norep("%s is %s.", upstart(steedname), predicament);
1482 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1485 Norep("You are %s.", predicament);
1487 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1489 /* [why does diagonal movement give quickest escape?] */
1490 if ((u.dx && u.dy) || !rn2(5))
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 */
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() */
1507 pline("Sting cuts through the web!");
1509 pline("
\83X
\83e
\83B
\83\93\83O
\82Í
\82
\82à
\82Ì
\91\83\82ð
\90Ø
\82è
\82³
\82¢
\82½
\81I");
1513 if (flags.verbose) {
1515 predicament = "stuck to the web";
1517 predicament = "
\82
\82à
\82Ì
\91\83\82É
\82Ð
\82Á
\82©
\82©
\82Á
\82½";
1520 Norep("%s is %s.", upstart(steedname), predicament);
1522 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1525 Norep("You are %s.", predicament);
1527 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1532 pline("%s breaks out of the web.", upstart(steedname));
1534 pline("%s
\82Í
\82
\82à
\82Ì
\91\83\82ð
\89ó
\82µ
\82½
\81D", upstart(steedname));
1537 You("disentangle yourself.");
1539 You("
\8e©
\95ª
\82Å
\82Ù
\82Ç
\82¢
\82½
\81D");
1543 if (flags.verbose) {
1545 predicament = "stuck in the lava";
1547 predicament = "
\97n
\8aâ
\82É
\82Í
\82Ü
\82Á
\82½";
1550 Norep("%s is %s.", upstart(steedname), predicament);
1552 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1555 Norep("You are %s.", predicament);
1557 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1559 if (!is_lava(x, y)) {
1561 if ((u.utrap & 0xff) == 0) {
1565 You("lead %s to the edge of the %s.", steedname,
1568 You("%s
\82ð%s
\82Ì
\92[
\82Ü
\82Å
\93±
\82¢
\82½
\81D", steedname,
1569 hliquid("
\97n
\8aâ"));
1573 You("pull yourself to the edge of the %s.",
1576 You("%s
\82Ì
\92[
\82Ü
\82Å
\82©
\82ë
\82¤
\82¶
\82Ä
\81C
\82½
\82Ç
\82è
\82Â
\82¢
\82½
\81D",
1577 hliquid("
\97n
\8aâ"));
1585 anchored = (u.utraptype == TT_BURIEDBALL);
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 */
1600 Norep("You move within the chain's reach.");
1602 Norep("
\8d½
\82ª
\93Í
\82
\94Í
\88Í
\82É
\88Ú
\93®
\82Å
\82«
\82é
\81D");
1607 if (flags.verbose) {
1610 predicament = "chained to the";
1611 culprit = "buried ball";
1613 predicament = "
\82Æ
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é";
1614 culprit = "
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é
\8b\85";
1618 predicament = "stuck in the";
1619 culprit = surface(u.ux, u.uy);
1621 predicament = "
\82É
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é";
1622 culprit = surface(u.ux, u.uy);
1628 Norep("You and %s are %s %s.", steedname, predicament,
1631 Norep("
\82 \82È
\82½
\82Æ%s
\82Í%s%s
\81D", steedname, culprit,
1636 Norep("%s is %s %s.", upstart(steedname), predicament,
1639 Norep("%s
\82Í%s%s
\81D", steedname, culprit,
1644 Norep("You are %s %s.", predicament, culprit);
1646 Norep("
\82 \82È
\82½
\82Í%s
\82É%s
\81D", culprit, predicament);
1652 pline("%s finally %s free.", upstart(steedname),
1653 !anchored ? "lurches" : "wrenches the ball");
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Ä");
1660 You("finally %s free.",
1661 !anchored ? "wriggle" : "wrench the ball");
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Ä");
1667 buried_ball_to_punishment();
1671 impossible("trapmove: stuck in unknown trap? (%d)",
1681 if (!youmonst.data->mmove) {
1683 You("are rooted %s.",
1684 Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
1688 You("
\82»
\82Ì
\8fê
\82É
\97§
\82¿
\82·
\82
\82ñ
\82¾
\81D");
1699 int ux1 = u.ux, uy1 = u.uy;
1701 domove_succeeded = 0L;
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;
1712 register struct monst *mtmp;
1713 register struct rm *tmpr;
1714 register xchar x, y;
1715 struct trap *trap = NULL;
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);
1724 if (context.travel) {
1725 if (!findtravelpath(FALSE))
1726 (void) findtravelpath(TRUE);
1727 context.travel1 = 0;
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) {
1737 You("don't have enough stamina to move.");
1739 You("
\82Ö
\82Æ
\82Ö
\82Æ
\82Å
\93®
\82¯
\82È
\82¢
\81D");
1740 exercise(A_CON, FALSE);
1743 You("collapse under your load.");
1745 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\93|
\82ê
\82½
\81D");
1751 u.ux = x = u.ustuck->mx;
1752 u.uy = y = u.ustuck->my;
1755 if (Is_airlevel(&u.uz) && rn2(4) && !Levitation && !Flying) {
1759 You("tumble in place.");
1761 You("
\82»
\82Ì
\8fê
\82Å
\93|
\82ê
\82½
\81D");
1762 exercise(A_DEX, FALSE);
1766 You_cant("control your movements very well.");
1768 You("
\82¤
\82Ü
\82
\95à
\82¯
\82È
\82¢
\81D");
1772 pline("It's hard to walk in thin air.");
1774 pline("
\8bó
\92\86\82ð
\95à
\82
\82Ì
\82Í
\93ï
\82µ
\82¢
\81D");
1775 exercise(A_DEX, TRUE);
1781 /* check slippery ice */
1782 on_ice = !Levitation && is_ice(u.ux, u.uy);
1784 static int skates = 0;
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)) {
1792 } else if (!rn2(Cold_resistance ? 3 : 2)) {
1793 HFumbling |= FROMOUTSIDE;
1794 HFumbling &= ~TIMEOUT;
1795 HFumbling += 1; /* slip on next move */
1798 if (!on_ice && (HFumbling & FROMOUTSIDE))
1799 HFumbling &= ~FROMOUTSIDE;
1803 if (Stunned || (Confusion && !rn2(5))) {
1804 register int tries = 0;
1814 } while (!isok(x, y) || bad_rock(youmonst.data, x, y));
1816 /* turbulence might alter your actual destination */
1819 if (!u.dx && !u.dy) {
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 */
1835 You("are carrying too much to climb out of the water.");
1837 You("
\90\85\82©
\82ç
\8fã
\82ª
\82é
\82É
\82Í
\89×
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\82¢
\82é
\81D");
1843 if (iflags.mention_walls) {
1844 int dx = u.dx, dy = u.dy;
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 */
1852 else if (isok(u.ux, y))
1856 You("have already gone as far %s as possible.",
1857 directionname(xytod(dx, dy)));
1859 You("
\82·
\82Å
\82É
\82Å
\82«
\82é
\82¾
\82¯%s
\82É
\93®
\82¢
\82Ä
\82¢
\82é
\81D",
1860 directionname(xytod(dx, dy)));
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);
1875 You("stop in front of %s.",
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) {
1881 You("stop at the edge of the %s.",
1882 hliquid(is_pool(x,y) ? "water" : "lava"));
1884 You("%s
\82Ì
\92[
\82Å
\8e~
\82Ü
\82Á
\82½
\81D.",
1885 hliquid(is_pool(x,y) ? "
\90\85" : "
\97n
\8aâ"));
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 ... ) */
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.
1905 You("release %s.", mon_nam(u.ustuck));
1907 You("%s
\82ð
\95ú
\82µ
\82½
\81D", mon_nam(u.ustuck));
1910 /* If holder is asleep or paralyzed:
1911 * 37.5% chance of getting away,
1912 * 12.5% chance of waking/releasing it;
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.
1919 switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
1925 You("pull free from %s.", mon_nam(u.ustuck));
1927 You("%s
\82ð
\82Ð
\82«
\82Í
\82È
\82µ
\82½
\81D", mon_nam(u.ustuck));
1931 if (!u.ustuck->mcanmove) {
1932 /* it's free to move on next turn */
1933 u.ustuck->mfrozen = 1;
1934 u.ustuck->msleeping = 0;
1938 if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf)
1941 You("cannot escape from %s!", mon_nam(u.ustuck));
1943 You("%s
\82©
\82ç
\93¦
\82°
\82ç
\82ê
\82È
\82¢
\81I", mon_nam(u.ustuck));
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))) {
1973 /* attack monster */
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)
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
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.
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
1999 stumble_onto_mimic(mtmp);
2000 else if (mtmp->mpeaceful && !Hallucination)
2001 /* m_monnam(): "dog" or "Fido", no "invisible dog" or "it" */
2003 pline("Pardon me, %s.", m_monnam(mtmp));
2005 pline("
\82¿
\82å
\82Á
\82Æ
\82²
\82ß
\82ñ
\82È
\82³
\82¢
\82æ
\81C%s
\82³
\82ñ
\81D", m_monnam(mtmp));
2008 You("move right into %s.", mon_nam(mtmp));
2010 You("%s
\82Ì
\82»
\82Î
\82É
\88Ú
\93®
\82µ
\82½
\81D", mon_nam(mtmp));
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_ */
2023 if (context.forcefight && levl[x][y].typ == IRONBARS && uwep) {
2024 struct obj *obj = uwep;
2026 if (breaktest(obj)) {
2028 obj = splitobj(obj, 1L);
2030 setuwep((struct obj *)0);
2033 hit_bars(&obj, u.ux, u.uy, x, y, TRUE, TRUE);
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 */
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);
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
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);
2068 /* about to become known empty -- remove 'I' if present */
2071 map_object(boulder, TRUE);
2073 glyph = glyph_at(x, y); /* might have just changed */
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 */
2083 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
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ë");
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") */
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");
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¨");
2107 /* note: 'solid' is misleadingly named and catches pools
2108 of water and lava as well as rock and walls */
2111 Strcpy(buf, "thin air");
2113 Strcpy(buf, "
\89½
\82à
\82È
\82¢
\8bó
\92\86");
2117 !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
2118 explo ? "explode at" : "attack", buf);
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½");
2128 u.mh = -1; /* dead in the current form */
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)) {
2144 boolean moved = trapmove(x, y, trap);
2147 reset_utrap(TRUE); /* might resume levitation or flight */
2148 /* might not have escaped, or did escape but remain in same spot */
2153 if (!test_move(u.ux, u.uy, x - u.ux, y - u.uy, DO_MOVE)) {
2154 if (!context.door_opened) {
2161 /* Move ball and chain. */
2163 if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy,
2164 &cause_delay, TRUE))
2167 /* Check regions entering/leaving */
2168 if (!in_out_region(x, y))
2171 /* now move the hero */
2175 /* Move your steed, too */
2177 u.usteed->mx = u.ux;
2178 u.usteed->my = u.uy;
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.
2192 * Ceiling-hiding pets are skipped by this section of code, to
2193 * be caught by the normal falling-monster code.
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;
2201 m_unleash(mtmp, TRUE);
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))
2215 else if (!mtmp->mtame)
2216 newsym(mtmp->mx, mtmp->my);
2217 u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
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 */
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;
2230 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2232 You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp)));
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 */
2241 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2243 You("stop. %s won't fit into the same spot that you're at.",
2244 upstart(y_monnam(mtmp)));
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",
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 */
2255 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2257 You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
2259 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
2261 char pnambuf[BUFSZ];
2263 /* save its current description in case of polymorph */
2264 Strcpy(pnambuf, y_monnam(mtmp));
2266 remove_monster(x, y);
2267 place_monster(mtmp, u.ux0, u.uy0);
2269 newsym(u.ux0, u.uy0);
2272 You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
2277 mtmp->mtame ? "
\82Æ
\8fê
\8f\8a\82ð
\93ü
\82ê
\8a·
\82í
\82Á" : "
\82ð
\95|
\82ª
\82ç
\82¹");
2280 /* check for displacing it into pools and traps */
2281 switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
2284 case 1: /* trapped */
2285 case 3: /* changed levels */
2286 /* there's already been a trap message, reinforce it */
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
2298 /* minliquid() and mintrap() call mondead() rather than
2299 killed() so we duplicate some of the latter here */
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 */
2308 /* That's no way to treat a pet! Your god gets angry.
2310 * [This has always been pretty iffy. Why does your
2311 * patron deity care at all, let alone enough to get mad?]
2315 You_feel("guilty about losing your pet like this.");
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");
2323 pline("that's strange, unknown mintrap result!");
2329 reset_occupations();
2331 if (context.run < 8)
2332 if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ)
2333 || IS_FURNITURE(tmpr->typ))
2337 if (hides_under(youmonst.data) || youmonst.data->mlet == S_EEL
2339 (void) hideunder(&youmonst);
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...
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;
2350 check_leash(u.ux0, u.uy0);
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));
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();
2363 if (Punished) /* put back ball and chain */
2364 move_bc(0, bc_control, ballx, bally, chainx, chainy);
2369 /* delay next move because of ball dragging */
2370 /* must come after we finished picking up, in spoteffects() */
2374 multi_reason = "dragging an iron ball";
2376 multi_reason = "
\93S
\8b\85\82É
\88ø
\82«
\82¸
\82ç
\82ê
\82Ä
\82¢
\82é
\8e\9e\82É";
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)) {
2387 if (flags.runmode == RUN_CRAWL) {
2398 maybe_smudge_engr(x1,y1,x2,y2)
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);
2412 /* combat increases metabolism */
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 */
2420 if ((moves % 3L) != 0L && near_capacity() >= HVY_ENCUMBER) {
2421 int *hp = (!Upolyd ? &u.uhp : &u.mh);
2427 You("pass out from exertion!");
2429 You("
\8bC
\90â
\82µ
\82½
\81D");
2430 exercise(A_CON, FALSE);
2431 fall_asleep(-10, FALSE);
2434 return (boolean) (multi < 0); /* might have fainted (forced to sleep) */
2438 invocation_message()
2440 /* a special clue-msg when on the Invocation position */
2441 if (invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
2443 struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
2445 nomul(0); /* stop running or travelling */
2448 Sprintf(buf, "beneath %s", y_monnam(u.usteed));
2450 Sprintf(buf, "%s
\82Ì
\89º
\82É", y_monnam(u.usteed));
2451 else if (Levitation || Flying)
2453 Strcpy(buf, "beneath you");
2455 Strcpy(buf, "
\89º
\95û
\82É");
2458 Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
2460 Strcpy(buf, "
\91«
\8c³
\82É");
2463 You_feel("a strange vibration %s.", buf);
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)
2469 pline("%s %s!", The(xname(otmp)),
2470 Blind ? "throbs palpably" : "glows with a strange light");
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");
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 */
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;
2490 /* called from spoteffects(), stop levitating but skip float_down() */
2493 You_cant("levitate in here.");
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)
2504 /* the same terrain that blocks levitation also blocks flight */
2508 You_cant("fly in here.");
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...] */
2520 You("start flying.");
2522 You("
\94ò
\82Ñ
\82Í
\82¶
\82ß
\82½
\81D");
2524 if ((!Levitation ^ was_levitating) || (!Flying ^ was_flying))
2525 context.botl = TRUE; /* update Lev/Fly status condition */
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 */
2532 pooleffects(newspot)
2533 boolean newspot; /* true if called by spoteffects */
2535 /* check for leaving water */
2537 boolean still_inwater = FALSE; /* assume we're getting out */
2539 if (!is_pool(u.ux, u.uy)) {
2540 if (Is_waterlevel(&u.uz))
2542 You("pop into an air bubble.");
2544 You("
\82Ð
\82å
\82¢
\82Æ
\8bó
\8bC
\82Ì
\96A
\82É
\93ü
\82Á
\82½
\81D");
2545 else if (is_lava(u.ux, u.uy))
2547 You("leave the %s...", hliquid("water")); /* oops! */
2549 You("%s
\90\85\82©
\82ç
\94²
\82¯
\82¾
\82µ
\82½
\81D
\81D
\81D", hliquid("
\90\85")); /* oops! */
2553 You("are on solid %s again.",
2554 is_ice(u.ux, u.uy) ? "ice" : "land");
2556 You("
\8cÅ
\82¢%s
\82Ì
\8fã
\82É
\82Ü
\82½
\96ß
\82Á
\82½
\81D",
2557 is_ice(u.ux, u.uy) ? "
\95X" : "
\92n
\96Ê");
2559 } else if (Is_waterlevel(&u.uz)) {
2560 still_inwater = TRUE;
2561 } else if (Levitation) {
2563 You("pop out of the %s like a cork!", hliquid("water"));
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) {
2568 You("fly out of the %s.", hliquid("water"));
2570 You("%s
\82©
\82ç
\94ò
\82Ñ
\82¾
\82µ
\82½
\81D", hliquid("
\90\85"));
2571 } else if (Wwalking) {
2573 You("slowly rise above the surface.");
2575 You("
\82ä
\82Á
\82
\82è
\90\85\96Ê
\82Ü
\82Å
\8fã
\82ª
\82Á
\82½
\81D");
2577 still_inwater = TRUE;
2579 if (!still_inwater) {
2580 boolean was_underwater = (Underwater && !Is_waterlevel(&u.uz));
2582 u.uinwater = 0; /* leave the water */
2583 if (was_underwater) { /* restore vision */
2585 vision_full_recalc = 1;
2590 /* check for entering water or lava */
2591 if (!u.ustuck && !Levitation && !Flying && is_pool_or_lava(u.ux, u.uy)) {
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) */
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))
2605 /* even if we actually end up at same location, float_down()
2606 has already done spoteffect()'s trap and pickup actions */
2608 check_special_room(FALSE); /* spoteffects */
2613 /* if hiding on ceiling then don't automatically enter pool */
2614 if (Upolyd && ceiling_hider(&mons[u.umonnum]) && u.uundetected)
2617 /* drown(),lava_effects() return true if hero changes
2618 location while surviving the problem */
2619 if (is_lava(u.ux, u.uy)) {
2622 } else if (!Wwalking
2623 && (newspot || !u.uinwater || !(Swimming || Amphibious))) {
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;
2642 struct trap *trap = t_at(u.ux, u.uy);
2643 int trapflag = iflags.failing_untrap ? FAILEDUNTRAP : 0;
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))
2656 spotterrain = levl[u.ux][u.uy].typ;
2657 spotloc.x = u.ux, spotloc.y = u.uy;
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))
2663 if (pooleffects(TRUE))
2666 check_special_room(FALSE);
2667 if (IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
2669 if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
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 */
2690 * If not a pit, pickup before triggering trap.
2691 * If pit, trigger trap before pickup.
2693 pit = (trap && is_pit(trap->ttyp));
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.
2706 if (!spottrap || spottraptyp != trap->ttyp) {
2708 spottraptyp = trap->ttyp;
2709 dotrap(trap, trapflag); /* fall into arrow trap, etc. */
2710 spottrap = (struct trap *) 0;
2711 spottraptyp = NO_TRAP;
2717 /* Warning alerts you to ice danger */
2718 if (Warning && is_ice(u.ux, u.uy)) {
2719 static const char *const icewarnings[] = {
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 */
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 */
2730 long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
2732 if (time_left && time_left < 15L)
2733 pline("%s", icewarnings[(time_left < 5L) ? 2
2734 : (time_left < 10L) ? 1
2737 if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
2738 mtmp->mundetected = mtmp->msleeping = 0;
2739 switch (mtmp->data->mlet) {
2742 pline("%s suddenly drops from the %s!", Amonnam(mtmp),
2743 ceiling(u.ux, u.uy));
2745 pline("%s
\82ª
\93Ë
\91R%s
\82©
\82ç
\97\8e\82¿
\82Ä
\82«
\82½
\81I", Amonnam(mtmp),
2746 ceiling(u.ux,u.uy));
2748 if (mtmp->mtame) { /* jumps to greet you, not attack */
2750 } else if (uarmh && is_metallic(uarmh)) {
2752 pline("Its blow glances off your %s.",
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)) {
2758 You("are almost hit by %s!",
2759 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
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));
2768 You("are hit by %s!",
2769 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2771 You("
\97\8e\82¿
\82Ä
\82«
\82½%s
\82É
\93\96\82½
\82Á
\82½
\81I",
2772 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2775 if (Half_physical_damage)
2776 dmg = (dmg + 1) / 2;
2777 mdamageu(mtmp, dmg);
2780 default: /* monster surprises you. */
2783 pline("%s jumps near you from the %s.", Amonnam(mtmp),
2784 ceiling(u.ux, u.uy));
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));
2789 else if (mtmp->mpeaceful) {
2793 You("%s
\82ð
\8bÁ
\82©
\82µ
\82½
\81I",
2794 Blind && !sensemon(mtmp) ? something : a_monnam(mtmp));
2795 mtmp->mpeaceful = 0;
2798 pline("%s attacks you by surprise!", Amonnam(mtmp));
2800 pline("%s
\82Í
\8bÁ
\82¢
\82Ä
\82 \82È
\82½
\82ð
\8dU
\8c\82\82µ
\82½
\81I", Amonnam(mtmp));
2803 mnexto(mtmp); /* have to move the monster */
2806 if (!--inspoteffects) {
2807 spotterrain = STONE; /* 0 */
2808 spotloc.x = spotloc.y = 0;
2813 /* returns first matching monster */
2814 STATIC_OVL struct monst *
2815 monstinroom(mdat, roomno)
2816 struct permonst *mdat;
2819 register struct monst *mtmp;
2821 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2822 if (DEADMONSTER(mtmp))
2824 if (mtmp->data == mdat
2825 && index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
2828 return (struct monst *) 0;
2832 in_rooms(x, y, typewanted)
2833 register xchar x, y;
2834 register int typewanted;
2837 char rno, *ptr = &buf[4];
2838 int typefound, min_x, min_y, max_x, max_y_offset, step;
2839 register struct rm *lev;
2841 #define goodtype(rno) \
2843 || (typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted \
2844 || (typewanted == SHOPBASE && typefound > SHOPBASE))
2846 switch (rno = levl[x][y].roomno) {
2855 default: /* i.e. a regular room # */
2865 else if (x >= COLNO)
2872 max_y_offset -= step;
2873 } else if ((min_y + max_y_offset) >= ROWNO)
2874 max_y_offset -= step;
2876 for (x = min_x; x <= max_x; x += step) {
2877 lev = &levl[x][min_y];
2879 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2883 if (y > max_y_offset)
2885 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2889 if (y > max_y_offset)
2891 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2898 /* is (x,y) in a town? */
2903 s_level *slev = Is_special(&u.uz);
2904 register struct mkroom *sroom;
2905 boolean has_subrooms = FALSE;
2907 if (!slev || !slev->flags.town)
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.
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))
2922 return !has_subrooms;
2927 register boolean newlev;
2929 char *ptr1, *ptr2, *ptr3, *ptr4;
2931 Strcpy(u.urooms0, u.urooms);
2932 Strcpy(u.ushops0, u.ushops);
2935 u.uentered[0] = '\0';
2937 u.ushops_entered[0] = '\0';
2938 Strcpy(u.ushops_left, u.ushops0);
2941 Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
2943 for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
2944 ptr4 = &u.ushops_entered[0];
2946 if (!index(u.urooms0, *ptr1))
2948 if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
2950 if (!index(u.ushops0, *ptr1))
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))
2965 /* possibly deliver a one-time room entry message */
2967 check_special_room(newlev)
2968 register boolean newlev;
2970 register struct monst *mtmp;
2973 move_update(newlev);
2976 u_left_shop(u.ushops_left, newlev);
2978 if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
2979 return; /* no entrance messages necessary */
2981 /* Did we just enter a shop? */
2982 if (*u.ushops_entered)
2983 u_entered_shop(u.ushops_entered);
2985 for (ptr = &u.uentered[0]; *ptr; ptr++) {
2986 int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
2987 boolean msg_given = TRUE;
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 */
2996 pline("Welcome to David's treasure zoo!");
2998 pline("
\83f
\83r
\83b
\83g
\95ó
\94 \93®
\95¨
\89\80\82É
\82æ
\82¤
\82±
\82»
\81I");
3002 pline("It %s rather %s down here.", Blind ? "feels" : "looks",
3003 Blind ? "humid" : "muddy");
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¾");
3012 You("enter an opulent throne room!");
3014 You("
\89Ø
\82â
\82©
\82È
\8bÊ
\8dÀ
\82Ì
\8aÔ
\82É
\93ü
\82Á
\82½
\81I");
3018 You("enter a leprechaun hall!");
3020 You("
\83\8c\83v
\83\89\83R
\81[
\83\93\83z
\81[
\83\8b\82É
\93ü
\82Á
\82½
\81I");
3025 const char *run = locomotion(youmonst.data, "Run");
3026 pline("%s away! %s away!", run, run);
3028 pline("
\93¦
\82°
\82ë
\81I
\93¦
\82°
\82ë
\81I");
3032 You("have an uncanny feeling...");
3034 You("
\95s
\8bC
\96¡
\82È
\8a´
\82¶
\82ª
\82µ
\82½
\81D
\81D
\81D");
3038 You("enter a giant beehive!");
3040 You("
\8b\90\91å
\82È
\96I
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
3044 You("enter a disgusting nest!");
3046 You("
\82Þ
\82Á
\82Æ
\82·
\82é
\8fL
\82¢
\82Ì
\82·
\82é
\92¹
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
3050 You("enter an anthole!");
3052 You("
\83A
\83\8a\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
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))
3060 You("enter a military barracks!");
3062 You("
\8cR
\91à
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81I");
3065 You("enter an abandoned barracks.");
3067 You("
\95ú
\92u
\82³
\82ê
\82½
\82Ü
\82Ü
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81D");
3070 struct monst *oracle = monstinroom(&mons[PM_ORACLE], roomno);
3072 if (!oracle->mpeaceful)
3074 verbalize("You're in Delphi, %s.", plname);
3076 verbalize("
\82¨
\82Ü
\82¦
\82Í
\83f
\83\8b\83t
\83@
\83C
\82Ì
\90_
\91õ
\8f\8a\82É
\82¢
\82é
\81D");
3079 verbalize("%s, %s, welcome to Delphi!",
3080 Hello((struct monst *) 0), plname);
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",
3090 intemple(roomno + ROOMOFFSET);
3093 msg_given = (rt == TEMPLE);
3098 room_discovered(roomno);
3101 rooms[roomno].rtype = OROOM;
3102 if (!search_special(rt)) {
3103 /* No more room of that type */
3106 level.flags.has_court = 0;
3109 level.flags.has_swamp = 0;
3112 level.flags.has_morgue = 0;
3115 level.flags.has_zoo = 0;
3118 level.flags.has_barracks = 0;
3121 level.flags.has_temple = 0;
3124 level.flags.has_beehive = 0;
3128 if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
3129 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
3130 if (DEADMONSTER(mtmp))
3132 if (!Stealth && !rn2(3))
3133 mtmp->msleeping = 0;
3142 1 = cannot pickup, time taken
3143 0 = cannot pickup, no time taken
3144 -1 = do normal pickup
3145 -2 = loot the monster */
3149 /* uswallow case added by GAN 01/29/87 */
3151 if (!u.ustuck->minvent) {
3152 if (is_animal(u.ustuck->data)) {
3154 You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
3156 You("%s
\82Ì
\90ã
\82ð
\8fE
\82Á
\82½
\81D", mon_nam(u.ustuck));
3158 pline("But it's kind of slimy, so you drop it.");
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");
3163 You("don't %s anything in here to pick up.",
3164 Blind ? "feel" : "see");
3166 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82ª
\82È
\82¢%s
\81D",
3167 Blind ? "
\82æ
\82¤
\82¾" : "");
3171 return -2; /* loot the monster inventory */
3174 if (is_pool(u.ux, u.uy)) {
3175 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
3176 || (Flying && !Breathless)) {
3178 You("cannot dive into the %s to pick things up.",
3181 You("
\95¨
\82ð
\8fE
\82¢
\82 \82°
\82é
\82½
\82ß
\82É%s
\82É
\94ò
\82Ñ
\82±
\82ß
\82È
\82¢
\81D",
3185 } else if (!Underwater) {
3187 You_cant("even see the bottom, let alone pick up %s.", something);
3189 pline("
\92ê
\82³
\82¦
\8c©
\82¦
\82È
\82¢
\81C
\8fE
\82¤
\82Ì
\82Í
\82â
\82ß
\82æ
\82¤
\81D");
3193 if (is_lava(u.ux, u.uy)) {
3194 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
3195 || (Flying && !Breathless)) {
3197 You_cant("reach the bottom to pick things up.");
3199 You_cant("
\95¨
\82ð
\8fE
\82¢
\8fã
\82°
\82é
\82½
\82ß
\82É
\92ê
\82Ü
\82Å
\82¢
\82¯
\82È
\82¢
\81D");
3201 } else if (!likes_lava(youmonst.data)) {
3203 You("would burn to a crisp trying to pick things up.");
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");
3209 if (!OBJ_AT(u.ux, u.uy)) {
3210 register struct rm *lev = &levl[u.ux][u.uy];
3212 if (IS_THRONE(lev->typ))
3214 pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
3216 pline("
\82±
\82ê
\82Í%s
\8fd
\82¢
\81I", lev->looted ? "
\82©
\82È
\82è" : "
\82·
\82²
\82");
3217 else if (IS_SINK(lev->typ))
3219 pline_The("plumbing connects it to the floor.");
3221 pline_The("
\94z
\8aÇ
\82Í
\8f°
\82É
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é
\81D");
3222 else if (IS_GRAVE(lev->typ))
3224 You("don't need a gravestone. Yet.");
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))
3229 You("could drink the %s...", hliquid("water"));
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))
3234 pline("It won't come off the hinges.");
3236 pline("
\83q
\83\93\83W
\82ð
\8aO
\82¹
\82È
\82¢
\81D");
3237 else if (IS_ALTAR(lev->typ))
3239 pline("Moving the altar would be a very bad idea.");
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)
3244 pline_The("stairs are solidly fixed to the %s.",
3245 surface(u.ux, u.uy));
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));
3252 There("is nothing here to pick up.");
3254 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82Í
\82È
\82¢
\81D");
3257 if (!can_reach_floor(TRUE)) {
3258 struct trap *traphere = t_at(u.ux, u.uy);
3260 && (uteetering_at_seen_pit(traphere) || uescaped_shaft(traphere)))
3262 You("cannot reach the bottom of the %s.",
3263 is_pit(traphere->ttyp) ? "pit" : "abyss");
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");
3268 else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
3270 else if (Blind && !can_reach_floor(TRUE))
3272 You("cannot reach anything here.");
3274 You("
\89½
\82É
\82à
\93Í
\82©
\82È
\82¢
\81D");
3277 You("cannot reach the %s.", surface(u.ux, u.uy));
3279 You("%s
\82É
\82½
\82Ç
\82è
\82Â
\82
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D", surface(u.ux, u.uy));
3282 return -1; /* can do normal pickup */
3285 /* the ',' command */
3289 int count, tmpcount, ret;
3291 /* awful kludge to work around parse()'s pre-decrement */
3292 count = (multi || (save_cm && *save_cm == cmd_from_func(dopickup)))
3294 multi = 0; /* always reset */
3296 if ((ret = pickup_checks()) >= 0) {
3298 } else if (ret == -2) {
3300 return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
3301 } /* else ret == -1 */
3303 return pickup(-count);
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 */
3313 int i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
3314 int corrct = 0, noturn = 0;
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) {
3322 You("cannot move diagonally.");
3324 You("
\8eÎ
\82ß
\82É
\88Ú
\93®
\82Å
\82«
\82È
\82¢
\81D");
3329 if (Blind || context.run == 0)
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))
3335 if (NODIAG(u.umonnum) && x != u.ux && y != u.uy)
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)
3347 pline("%s blocks your path.", upstart(a_monnam(mtmp)));
3349 pline("%s
\82ª
\93¹
\82ð
\82Ó
\82³
\82¢
\82Å
\82¢
\82é
\81D", a_monnam(mtmp));
3354 if (levl[x][y].typ == STONE)
3356 if (x == u.ux - u.dx && y == u.uy - u.dy)
3359 if (IS_ROCK(levl[x][y].typ) || levl[x][y].typ == ROOM
3360 || IS_AIR(levl[x][y].typ)) {
3362 } else if (closed_door(x, y) || (mtmp && is_door_mappear(mtmp))) {
3363 if (x != u.ux && y != u.uy)
3365 if (context.run != 1) {
3366 if (iflags.mention_walls)
3368 You("stop in front of the door.");
3370 You("
\94à
\82Ì
\8eè
\91O
\82Å
\8e~
\82Ü
\82Á
\82½
\81D");
3374 } else if (levl[x][y].typ == CORR) {
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);
3382 if (corrct == 1 && dist2(x, y, x0, y0) != 1)
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);
3402 You("stop in front of %s.",
3404 You("%s
\82Ì
\8eè
\91O
\82Å
\8e~
\82Ü
\82Á
\82½
\81D",
3405 an(defsyms[trap_to_defsym(tt)].explanation));
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
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
3420 if (iflags.mention_walls)
3422 You("stop at the edge of the %s.",
3423 hliquid(is_pool(x,y) ? "water" : "lava"));
3425 You("%s
\82Ì
\92[
\82Å
\8e~
\82Ü
\82Á
\82½
\81D",
3426 hliquid(is_pool(x,y) ? "
\90\85" : "
\97n
\8aâ"));
3431 } else { /* e.g. objects or trap or stairs */
3432 if (context.run == 1)
3434 if (context.run == 8)
3438 if (((x == u.ux - u.dx) && (y != u.uy + u.dy))
3439 || ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
3445 } /* end for loops */
3447 if (corrct > 1 && context.run == 2) {
3448 if (iflags.mention_walls)
3450 pline_The("corridor widens here.");
3452 pline("
\92Ê
\98H
\82Í
\82±
\82±
\82Å
\8dL
\82
\82È
\82Á
\82Ä
\82¢
\82é
\81D");
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 */
3459 if (u.dx == y0 - u.uy && u.dy == u.ux - x0)
3460 i = 2; /* straight turn right */
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 */
3467 i = 1; /* half turn right */
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 */
3473 i = -1; /* half turn left */
3476 i += u.last_str_turn;
3477 if (i <= 2 && i >= -2) {
3478 u.last_str_turn = i;
3485 /* check for a doorway which lacks its door (NODOOR or BROKEN) */
3490 struct rm *lev_p = &levl[x][y];
3492 if (!IS_DOOR(lev_p->typ))
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))
3498 return !(lev_p->doormask & ~(D_NODOOR | D_BROKEN));
3501 /* used by drown() to check whether hero can crawl from water to <x,y> */
3503 crawl_destination(x, y)
3506 /* is location ok in general? */
3507 if (!goodpos(x, y, &youmonst, 0))
3510 /* orthogonal movement is unrestricted when destination is ok */
3511 if (x == u.ux || y == u.uy)
3514 /* diagonal movement has some restrictions */
3515 if (NODIAG(u.umonnum))
3516 return FALSE; /* poly'd into a grid bug... */
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)))
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));
3527 /* something like lookaround, but we are not running */
3528 /* react only to monsters that might hit us */
3533 register struct monst *mtmp;
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))
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))
3557 return; /* This is a bug fix by ab@unido */
3558 u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
3562 multi_reason = NULL;
3563 context.travel = context.travel1 = context.mv = context.run = 0;
3566 /* called when a non-movement, multi-turn action has completed */
3569 const char *msg_override;
3571 multi = 0; /* caller will usually have done this already */
3573 nomovemsg = msg_override;
3574 else if (!nomovemsg)
3575 nomovemsg = You_can_move_again;
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) */
3584 if (Upolyd && !strncmpi(nomovemsg, "You survived that ", 18))
3585 You("are %s.", an(mons[u.umonnum].mname)); /* (ignore Hallu) */
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) */
3593 multi_reason = NULL;
3595 int NDECL((*f)) = afternmv;
3597 /* clear afternmv before calling it (to override the
3598 encumbrance hack for levitation--see weight_cap()) */
3599 afternmv = (int NDECL((*))) 0;
3601 /* for finishing Armor/Boots/&c_on() */
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 };
3613 if (moves <= wailmsg + 50)
3617 if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) {
3622 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3625 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3630 pline("%s is about to die.", who);
3632 pline("%s
\82Í
\8e\80\82É
\82©
\82¯
\82Ä
\82¢
\82é
\81D", who);
3634 for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
3635 if (u.uprops[powers[i]].intrinsic & INTRINSIC)
3639 pline((powercnt >= 4) ? "%s, all your powers will be lost..."
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"
3643 : "%s, your life force is running out.",
3645 : "%s
\81C
\82 \82È
\82½
\82Ì
\90¶
\96½
\97Í
\82Í
\90s
\82«
\82æ
\82¤
\82Æ
\82µ
\82Ä
\82¢
\82é
\81D
\81D
\81D",
3650 You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
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"
3654 : "the howling of the CwnAnnwn...");
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");
3661 losehp(n, knam, k_format)
3663 register const char *knam;
3673 else if (n > 0 && u.mh * 10 < u.mhmax && Unchanging)
3679 if (u.uhp > u.uhpmax)
3680 u.uhpmax = u.uhp; /* perhaps n was negative */
3682 context.travel = context.travel1 = context.mv = context.run = 0;
3685 killer.format = k_format;
3686 if (killer.name != knam) /* the thing that killed you */
3687 Strcpy(killer.name, knam ? knam : "");
3691 pline("
\82 \82È
\82½
\82Í
\8e\80\82É
\82Ü
\82µ
\82½
\81D
\81D
\81D");
3693 } else if (n > 0 && u.uhp * 10 < u.uhpmax) {
3701 long carrcap, save_ELev = ELevitation, save_BLev = BLevitation;
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 */
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;
3715 carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
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);
3728 if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
3729 || (u.usteed && strongmonst(u.usteed->data))) {
3730 carrcap = MAX_CARR_CAP;
3732 if (carrcap > MAX_CARR_CAP)
3733 carrcap = MAX_CARR_CAP;
3735 if (EWounded_legs & LEFT_SIDE)
3737 if (EWounded_legs & RIGHT_SIDE)
3744 if (ELevitation != save_ELev || BLevitation != save_BLev) {
3745 ELevitation = save_ELev;
3746 BLevitation = save_BLev;
3750 return (int) carrcap;
3753 static int wc; /* current weight_cap(); valid after call to inv_weight() */
3755 /* returns how far beyond the normal capacity the player is currently. */
3756 /* inv_weight() is negative if the player is below normal capacity. */
3760 register struct obj *otmp = invent;
3761 register int wt = 0;
3764 if (otmp->oclass == COIN_CLASS)
3765 wt += (int) (((long) otmp->quan + 50L) / 100L);
3766 else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
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.
3779 calc_capacity(xtra_wt)
3782 int cap, wt = inv_weight() + xtra_wt;
3785 return UNENCUMBERED;
3788 cap = (wt * 2 / wc) + 1;
3789 return min(cap, OVERLOADED);
3795 return calc_capacity(0);
3801 int wt = inv_weight();
3803 return (wt - (2 * wc));
3810 if (near_capacity() >= EXT_ENCUMBER) {
3815 You_cant("do that while carrying so much stuff.");
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");
3827 register struct obj *otmp = invent;
3828 register int ct = 0;
3831 if (incl_gold || otmp->invlet != GOLD_SYM)
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. */
3847 /* Must change when silver & copper is implemented: */
3848 if (otmp->oclass == COIN_CLASS)