1 /* NetHack 3.6 hack.c $NHDT-Date: 1551137618 2019/02/25 23:33:38 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.208 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Derek S. Ray, 2015. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
9 /* JNetHack may be freely redistributed. See license for details. */
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)))) {
174 feel_location(sx, sy);
175 if (canspotmon(mtmp)) {
177 pline("There's %s on the other side.", a_monnam(mtmp));
179 pline("
\94½
\91Î
\91¤
\82É%s
\82ª
\82¢
\82é
\81D", a_monnam(mtmp));
182 You_hear("a monster behind %s.", the(xname(otmp)));
184 pline("%s
\82Ì
\94w
\8cã
\82É
\89ö
\95¨
\82Ì
\8bC
\94z
\82ª
\82·
\82é
\81D", the(xname(otmp)));
185 map_invisible(rx, ry);
189 pline("Perhaps that's why %s cannot move it.",
190 u.usteed ? y_monnam(u.usteed) : "you");
192 pline("
\82½
\82Ô
\82ñ
\82±
\82ê
\82ª
\81C
\8aâ
\82ð
\93®
\82©
\82¹
\82È
\82¢
\97\9d\97R
\82¾
\81D");
198 /* if a trap operates on the boulder, don't attempt
199 to move any others at this location; return -1
200 if another boulder is in hero's way, or 0 if he
201 should advance to the vacated boulder position */
202 switch (ttmp->ttyp) {
205 obj_extract_self(otmp);
206 place_object(otmp, rx, ry);
209 pline("KAABLAMM!!! %s %s land mine.",
210 Tobjnam(otmp, "trigger"),
211 ttmp->madeby_u ? "your" : "a");
213 pline("
\82¿
\82ã
\82Ç
\81[
\82ñ
\81I
\81I%s
\82Å%s
\92n
\97\8b\82Ì
\8bN
\94\9a\83X
\83C
\83b
\83`
\82ª
\93ü
\82Á
\82½
\81D",
215 ttmp->madeby_u ? "
\82 \82È
\82½
\82Ì
\8ed
\8a|
\82¯
\82½" : "");
217 blow_up_landmine(ttmp);
218 /* if the boulder remains, it should fill the pit */
219 fill_pit(u.ux, u.uy);
222 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
227 obj_extract_self(otmp);
228 /* vision kludge to get messages right;
229 the pit will temporarily be seen even
230 if this is one among multiple boulders */
232 viz_array[ry][rx] |= IN_SIGHT;
234 if (!flooreffects(otmp, rx, ry, "fall")) {
236 if (!flooreffects(otmp, rx, ry, "
\97\8e\82¿
\82é")) {
237 place_object(otmp, rx, ry);
241 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
246 pline("Kerplunk! You no longer feel %s.",
248 pline("
\83h
\83T
\83b
\81I
\82 \82È
\82½
\82Í
\82à
\82¤%s
\82ð
\8a´
\82¶
\82ç
\82ê
\82È
\82¢
\81D",
252 pline("%s%s and %s a %s in the %s!",
253 Tobjnam(otmp, (ttmp->ttyp == TRAPDOOR)
256 (ttmp->ttyp == TRAPDOOR) ? "" : " into",
257 otense(otmp, "plug"),
258 (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
261 pline("%s
\82Í
\97\8e\82¿
\82Ä%s
\82Ì%s
\82ð
\96\84\82ß
\82½
\81I",
264 (ttmp->ttyp == TRAPDOOR) ? "
\97\8e\82µ
\94à" : "
\8c\8a");
269 levl[rx][ry].wall_info &= ~W_NONDIGGABLE;
270 levl[rx][ry].candig = 1;
273 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
276 int newlev = 0; /* lint suppression */
279 if (ttmp->ttyp == LEVEL_TELEP) {
280 newlev = random_teleport_level();
281 if (newlev == depth(&u.uz) || In_endgame(&u.uz))
282 /* trap didn't work; skip "disappears" message */
287 pline("%s pushes %s and suddenly it disappears!",
289 pline("%s
\82ª%s
\82ð
\89\9f\82·
\82Æ
\81C
\93Ë
\91R
\82»
\82ê
\82Í
\8fÁ
\96Å
\82µ
\82½
\81I",
290 upstart(y_monnam(u.usteed)), the(xname(otmp)));
293 You("push %s and suddenly it disappears!",
295 pline("
\82 \82È
\82½
\82ª%s
\82ð
\89\9f\82·
\82Æ
\81C
\93Ë
\91R
\82»
\82ê
\82Í
\8fÁ
\96Å
\82µ
\82½
\81I",
297 if (ttmp->ttyp == TELEP_TRAP) {
300 obj_extract_self(otmp);
301 add_to_migration(otmp);
302 get_level(&dest, newlev);
303 otmp->ox = dest.dnum;
304 otmp->oy = dest.dlevel;
305 otmp->owornmask = (long) MIGR_RANDOM;
308 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
311 break; /* boulder not affected by this trap */
315 if (closed_door(rx, ry))
317 if (boulder_hits_pool(otmp, rx, ry, TRUE))
320 * Re-link at top of fobj chain so that pile order is preserved
321 * when level is restored.
325 place_object(otmp, otmp->ox, otmp->oy);
329 #ifdef LINT /* static long lastmovetime; */
333 /* note: reset to zero after save/restore cycle */
334 static NEARDATA long lastmovetime;
338 if (moves > lastmovetime + 2 || moves < lastmovetime)
340 pline("With %s effort you move %s.",
341 throws_rocks(youmonst.data) ? "little"
345 pline("%s
\97Í
\82ð
\82±
\82ß
\82Ä%s
\82ð
\89\9f\82µ
\82½
\81D",
346 throws_rocks(youmonst.data) ? "
\8f
\82µ" : "
\82©
\82È
\82è",
349 exercise(A_STR, TRUE);
352 pline("%s moves %s.", upstart(y_monnam(u.usteed)),
355 pline("%s
\82Í%s
\82ð
\93®
\82©
\82µ
\82½
\81D", upstart(y_monnam(u.usteed)),
358 lastmovetime = moves;
361 /* Move the boulder *after* the message. */
362 if (glyph_is_invisible(levl[rx][ry].glyph))
363 unmap_object(rx, ry);
364 movobj(otmp, rx, ry); /* does newsym(rx,ry) */
366 feel_location(rx, ry);
367 feel_location(sx, sy);
375 pline("%s tries to move %s, but cannot.",
376 upstart(y_monnam(u.usteed)), the(xname(otmp)));
378 pline("%s
\82Í%s
\82ð
\93®
\82©
\82»
\82¤
\82Æ
\82µ
\82½
\82ª
\8fo
\97\88\82È
\82©
\82Á
\82½
\81D",
379 upstart(y_monnam(u.usteed)), the(xname(otmp)));
383 You("try to move %s, but in vain.", the(xname(otmp)));
385 You("%s
\82ð
\93®
\82©
\82»
\82¤
\82Æ
\82µ
\82½
\82ª
\81C
\82¾
\82ß
\82¾
\82Á
\82½
\81D", the(xname(otmp)));
387 feel_location(sx, sy);
389 if (throws_rocks(youmonst.data)) {
391 canpickup = (!Sokoban
392 /* similar exception as in can_lift():
393 when poly'd into a giant, you can
394 pick up a boulder if you have a free
395 slot or into the overflow ('#') slot
396 unless already carrying at least one */
397 && (inv_cnt(FALSE) < 52 || !carrying(BOULDER))),
398 willpickup = (canpickup && autopick_testobj(otmp, TRUE));
400 if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
402 You("aren't skilled enough to %s %s from %s.",
403 willpickup ? "pick up" : "push aside",
404 the(xname(otmp)), y_monnam(u.usteed));
406 You("%s
\82É%s
\82ð%s
\82é
\82Ù
\82Ç
\8bZ
\97Ê
\82ª
\82È
\82¢
\81D",
407 y_monnam(u.usteed), the(xname(otmp)),
408 willpickup ? "
\8fE
\82í
\82¹" : "
\89\9f\82³
\82¹");
412 * willpickup: you easily pick it up
413 * canpickup: you could easily pick it up
414 * otherwise: you easily push it aside
417 pline("However, you %seasily %s.",
418 (willpickup || !canpickup) ? "" : "could ",
419 (willpickup || canpickup) ? "pick it up"
422 pline("
\82µ
\82©
\82µ
\81C
\82 \82È
\82½
\82Í
\8aÈ
\92P
\82É
\82»
\82ê
\82ð%s
\81D",
423 (willpickup || canpickup) ?
424 "
\8fE
\82¦
\82½" : "
\95Ê
\82Ì
\95û
\82É
\89\9f\82¹
\82½");
433 && (((!invent || inv_weight() <= -850)
434 && (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ)
435 && IS_ROCK(levl[sx][u.uy].typ))))
436 || verysmall(youmonst.data))) {
439 "However, you can squeeze yourself into a small opening.");
441 "
\82µ
\82©
\82µ
\81C
\82 \82È
\82½
\82Í
\8f¬
\82³
\82¢
\8c\84\8aÔ
\82É
\82±
\82¶
\93ü
\82Á
\82½
\81D");
454 * Chew on a wall, door, or boulder. [What about statues?]
455 * Returns TRUE if still eating, FALSE when done.
461 struct rm *lev = &levl[x][y];
462 struct obj *boulder = sobj_at(BOULDER, x, y);
463 const char *digtxt = (char *) 0, *dmgtxt = (char *) 0;
465 if (context.digging.down) /* not continuing previous dig (w/ pick-axe) */
466 (void) memset((genericptr_t) &context.digging, 0,
467 sizeof (struct dig_info));
470 && ((IS_ROCK(lev->typ) && !may_dig(x, y))
471 /* may_dig() checks W_NONDIGGABLE but doesn't handle iron bars */
472 || (lev->typ == IRONBARS && (lev->wall_info & W_NONDIGGABLE)))) {
474 You("hurt your teeth on the %s.",
475 (lev->typ == IRONBARS)
481 You("%s
\82Å
\8e\95\82ð
\92É
\82ß
\82½
\81D",
482 (lev->typ == IRONBARS)
490 } else if (context.digging.pos.x != x || context.digging.pos.y != y
491 || !on_level(&context.digging.level, &u.uz)) {
492 context.digging.down = FALSE;
493 context.digging.chew = TRUE;
494 context.digging.warned = FALSE;
495 context.digging.pos.x = x;
496 context.digging.pos.y = y;
497 assign_level(&context.digging.level, &u.uz);
498 /* solid rock takes more work & time to dig through */
499 context.digging.effort =
500 (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc;
502 You("start chewing %s %s.",
503 (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
512 : (lev->typ == IRONBARS)
516 You("%s%s
\82Í
\82¶
\82ß
\82½
\81D",
523 : lev->typ == IRONBARS
526 (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
528 : "
\82É
\8c\8a\82ð
\82 \82¯");
530 watch_dig((struct monst *) 0, x, y, FALSE);
532 } else if ((context.digging.effort += (30 + u.udaminc)) <= 100) {
535 You("%s chewing on the %s.",
536 context.digging.chew ? "continue" : "begin",
543 : (lev->typ == IRONBARS)
547 You("%s
\82ð
\8a\9a\82Ý%s
\81D",
554 : lev->typ == IRONBARS
557 context.digging.chew ? "
\91±
\82¯
\82½" : "
\82Í
\82¶
\82ß
\82½");
559 context.digging.chew = TRUE;
560 watch_dig((struct monst *) 0, x, y, FALSE);
564 /* Okay, you've chewed through something */
566 u.uhunger += rnd(20);
569 delobj(boulder); /* boulder goes bye-bye */
571 You("eat the boulder."); /* yum */
573 You("
\8aâ
\82ð
\90H
\82×
\82½
\81D"); /* yum */
577 * The location could still block because of
578 * 1. More than one boulder
579 * 2. Boulder stuck in a wall/stone/door.
581 * [perhaps use does_block() below (from vision.c)]
583 if (IS_ROCK(lev->typ) || closed_door(x, y)
584 || sobj_at(BOULDER, x, y)) {
585 block_point(x, y); /* delobj will unblock the point */
586 /* reset dig state */
587 (void) memset((genericptr_t) &context.digging, 0,
588 sizeof (struct dig_info));
592 } else if (IS_WALL(lev->typ)) {
593 if (*in_rooms(x, y, SHOPBASE)) {
594 add_damage(x, y, SHOP_WALL_DMG);
598 dmgtxt = "
\8f\9d\82Â
\82¯
\82é";
601 digtxt = "chew a hole in the wall.";
603 digtxt = "
\95Ç
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
604 if (level.flags.is_maze_lev) {
606 } else if (level.flags.is_cavernous_lev && !in_town(x, y)) {
610 lev->doormask = D_NODOOR;
612 } else if (IS_TREE(lev->typ)) {
614 digtxt = "chew through the tree.";
616 digtxt = "
\96Ø
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
618 } else if (lev->typ == IRONBARS) {
620 digtxt = "eat through the bars.";
622 digtxt = "
\93S
\82Ì
\96_
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
624 } else if (lev->typ == SDOOR) {
625 if (lev->doormask & D_TRAPPED) {
626 lev->doormask = D_NODOOR;
628 b_trapped("secret door", 0);
630 b_trapped("
\94é
\96§
\82Ì
\94à", 0);
633 digtxt = "chew through the secret door.";
635 digtxt = "
\94é
\96§
\82Ì
\94à
\82ð
\8a\9a\82Ý
\8dÓ
\82¢
\82½
\81D";
636 lev->doormask = D_BROKEN;
640 } else if (IS_DOOR(lev->typ)) {
641 if (*in_rooms(x, y, SHOPBASE)) {
642 add_damage(x, y, SHOP_DOOR_COST);
648 if (lev->doormask & D_TRAPPED) {
649 lev->doormask = D_NODOOR;
651 b_trapped("door", 0);
653 b_trapped("
\94à", 0);
656 digtxt = "chew through the door.";
658 digtxt = "
\94à
\82ð
\8dÓ
\82¢
\82½
\81D";
659 lev->doormask = D_BROKEN;
662 } else { /* STONE or SCORR */
664 digtxt = "chew a passage through the rock.";
666 digtxt = "
\8aâ
\82ð
\8a\9a\82Ý
\8dÓ
\82¢
\82Ä
\92Ê
\82è
\94²
\82¯
\82½
\81D";
670 unblock_point(x, y); /* vision */
673 You1(digtxt); /* after newsym */
675 pay_for_damage(dmgtxt, FALSE);
676 (void) memset((genericptr_t) &context.digging, 0,
677 sizeof (struct dig_info));
683 register struct obj *obj;
684 register xchar ox, oy;
686 /* optimize by leaving on the fobj chain? */
688 newsym(obj->ox, obj->oy);
689 place_object(obj, ox, oy);
694 static NEARDATA const char fell_on_sink[] = "fell onto a sink";
696 static NEARDATA const char fell_on_sink[] = "
\97¬
\82µ
\91ä
\82É
\97\8e\82¿
\82Ä";
701 register struct obj *obj;
703 boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
704 innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L),
705 /* to handle being chained to buried iron ball, trying to
706 levitate but being blocked, then moving onto adjacent sink;
707 no need to worry about being blocked by terrain because we
708 couldn't be over a sink at the same time */
709 blockd_lev = (BLevitation == I_SPECIAL),
710 ufall = (!innate_lev && !blockd_lev
711 && !(HFlying || EFlying)); /* BFlying */
715 You((innate_lev || blockd_lev) ? "wobble unsteadily for a moment."
717 You((innate_lev || blockd_lev) ? "
\82¿
\82å
\82Á
\82Æ
\82Ó
\82ç
\82Â
\82¢
\82½
\81D"
719 : "gain control of your flight.");
721 : "
\94ò
\8ds
\92\86\82Ì
\90§
\8cä
\82ð
\8eæ
\82è
\82à
\82Ç
\82µ
\82½
\81D");
723 long save_ELev = ELevitation, save_HLev = HLevitation;
725 /* fake removal of levitation in advance so that final
726 disclosure will be right in case this turns out to
727 be fatal; fortunately the fact that rings and boots
728 are really still worn has no effect on bones data */
729 ELevitation = HLevitation = 0L;
731 You("crash to the floor!");
733 You("
\8f°
\82É
\92@
\82«
\82Â
\82¯
\82ç
\82ê
\82½
\81I");
734 dmg = rn1(8, 25 - (int) ACURR(A_CON));
736 losehp(Maybe_Half_Phys(dmg), fell_on_sink, NO_KILLER_PREFIX);
738 losehp(Maybe_Half_Phys(dmg), fell_on_sink, KILLED_BY);
740 exercise(A_DEX, FALSE);
742 selftouch("Falling, you");
744 selftouch("
\97\8e\82¿
\82È
\82ª
\82ç
\81C
\82 \82È
\82½
\82Í");
745 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
746 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) {
748 You("fell on %s.", doname(obj));
750 You("%s
\82Ì
\8fã
\82É
\97\8e\82¿
\82½
\81D",doname(obj));
752 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
755 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
758 exercise(A_CON, FALSE);
760 ELevitation = save_ELev;
761 HLevitation = save_HLev;
765 * Interrupt multi-turn putting on/taking off of armor (in which
766 * case we reached the sink due to being teleported while busy;
767 * in 3.4.3, Boots_on()/Boots_off() [called via (*afternmv)() when
768 * 'multi' reaches 0] triggered a crash if we were donning/doffing
769 * levitation boots [because the Boots_off() below causes 'uarmf'
770 * to be null by the time 'afternmv' gets called]).
772 * Interrupt donning/doffing if we fall onto the sink, or if the
773 * code below is going to remove levitation boots even when we
774 * haven't fallen (innate floating or flying becoming unblocked).
776 if (ufall || lev_boots) {
777 (void) stop_donning(lev_boots ? uarmf : (struct obj *) 0);
778 /* recalculate in case uarmf just got set to null */
779 lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS);
782 /* remove worn levitation items */
783 ELevitation &= ~W_ARTI;
784 HLevitation &= ~(I_SPECIAL | TIMEOUT);
786 if (uleft && uleft->otyp == RIN_LEVITATION) {
791 if (uright && uright->otyp == RIN_LEVITATION) {
802 /* probably moot; we're either still levitating or went
803 through float_down(), but make sure BFlying is up to date */
807 /* intended to be called only on ROCKs or TREEs */
812 struct rm *lev = &levl[x][y];
814 return (boolean) !((IS_STWALL(lev->typ) || IS_TREE(lev->typ))
815 && (lev->wall_info & W_NONDIGGABLE));
822 return (boolean) !(IS_STWALL(levl[x][y].typ)
823 && (levl[x][y].wall_info & W_NONPASSWALL));
828 struct permonst *mdat;
831 return (boolean) ((Sokoban && sobj_at(BOULDER, x, y))
832 || (IS_ROCK(levl[x][y].typ)
833 && (!tunnels(mdat) || needspick(mdat)
835 && !(passes_walls(mdat) && may_passwall(x, y))));
838 /* caller has already decided that it's a tight diagonal; check whether a
839 monster--who might be the hero--can fit through, and if not then return
840 the reason why: 1: can't fit, 2: possessions won't fit, 3: sokoban
841 returns 0 if we can squeeze through */
843 cant_squeeze_thru(mon)
847 struct permonst *ptr = mon->data;
851 && !(amorphous(ptr) || is_whirly(ptr) || noncorporeal(ptr)
852 || slithy(ptr) || can_fog(mon)))
855 /* lugging too much junk? */
856 amt = (mon == &youmonst) ? inv_weight() + weight_cap()
857 : curr_mon_load(mon);
861 /* Sokoban restriction applies to hero only */
862 if (mon == &youmonst && Sokoban)
865 /* can squeeze through */
873 return (boolean) (Invocation_lev(&u.uz)
874 && x == inv_pos.x && y == inv_pos.y);
877 /* return TRUE if (dx,dy) is an OK place to move
878 * mode is one of DO_MOVE, TEST_MOVE, TEST_TRAV, or TEST_TRAP
881 test_move(ux, uy, dx, dy, mode)
887 register struct rm *tmpr = &levl[x][y];
888 register struct rm *ust;
890 context.door_opened = FALSE;
892 * Check for physical obstacles. First, the place we are going.
894 if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) {
895 if (Blind && mode == DO_MOVE)
897 if (Passes_walls && may_passwall(x, y)) {
899 } else if (Underwater) {
900 /* note: if water_friction() changes direction due to
901 turbulence, new target destination will always be water,
902 so we won't get here, hence don't need to worry about
903 "there" being somewhere the player isn't sure of */
906 pline("There is an obstacle there.");
908 pline("
\8fá
\8aQ
\95¨
\82ª
\82 \82é
\81D");
910 } else if (tmpr->typ == IRONBARS) {
911 if ((dmgtype(youmonst.data, AD_RUST)
912 || dmgtype(youmonst.data, AD_CORR)) && mode == DO_MOVE
913 && still_chewing(x, y)) {
916 if (!(Passes_walls || passes_bars(youmonst.data))) {
917 if (mode == DO_MOVE && iflags.mention_walls)
919 You("cannot pass through the bars.");
921 You("
\93S
\82Ì
\96_
\82ð
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
924 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
926 if (mode == DO_MOVE && still_chewing(x, y))
928 } else if (flags.autodig && !context.run && !context.nopick && uwep
930 /* MRKR: Automatic digging when wielding the appropriate tool */
932 (void) use_pick_axe2(uwep);
935 if (mode == DO_MOVE) {
936 if (is_db_wall(x, y))
938 pline("That drawbridge is up!");
940 pline("
\92µ
\82Ë
\8b´
\82Í
\8fã
\82Á
\82Ä
\82¢
\82é
\81I");
941 /* sokoban restriction stays even after puzzle is solved */
942 else if (Passes_walls && !may_passwall(x, y)
943 && In_sokoban(&u.uz))
945 pline_The("Sokoban walls resist your ability.");
947 pline_The("
\91q
\8cÉ
\94Ô
\82Ì
\95Ç
\82Í
\82 \82È
\82½
\82Ì
\94\
\97Í
\82É
\92ï
\8dR
\82µ
\82½
\81D");
948 else if (iflags.mention_walls)
951 (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "a wall"
952 : IS_TREE(tmpr->typ) ? "a tree"
955 pline("
\82±
\82ê
\82Í%s
\82¾
\81D",
956 (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "
\95Ç"
957 : IS_TREE(tmpr->typ) ? "
\96Ø"
963 } else if (IS_DOOR(tmpr->typ)) {
964 if (closed_door(x, y)) {
965 if (Blind && mode == DO_MOVE)
969 } else if (can_ooze(&youmonst)) {
972 You("ooze under the door.");
974 You("
\83h
\83A
\82Ì
\89º
\82©
\82ç
\82É
\82¶
\82Ý
\8fo
\82½
\81D");
975 } else if (Underwater) {
978 pline("There is an obstacle there.");
980 pline("
\8fá
\8aQ
\95¨
\82ª
\82 \82é
\81D");
982 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
984 if (mode == DO_MOVE && still_chewing(x, y))
987 if (mode == DO_MOVE) {
988 if (amorphous(youmonst.data))
991 "try to ooze under the door, but can't squeeze your possessions through.");
993 "
\83h
\83A
\82Ì
\89º
\82©
\82ç
\82É
\82¶
\82Ý
\8fo
\82æ
\82¤
\82Æ
\82µ
\82½
\81C
\82µ
\82©
\82µ
\8e\9d\82¿
\95¨
\82Í
\82»
\82¤
\82Í
\82¢
\82©
\82È
\82¢
\81D");
994 if (flags.autoopen && !context.run && !Confusion
995 && !Stunned && !Fumbling) {
996 context.door_opened = context.move =
998 } else if (x == ux || y == uy) {
999 if (Blind || Stunned || ACURR(A_DEX) < 10
1003 You_cant("lead %s through that closed door.",
1005 You_cant("%s
\82É
\95Â
\82Ü
\82Á
\82½
\94à
\82ð
\92Ê
\89ß
\82³
\82¹
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
1006 y_monnam(u.usteed));
1009 pline("Ouch! You bump into a door.");
1011 pline("
\82¢
\82Ä
\82Á
\81I
\93ª
\82ð
\94à
\82É
\82Ô
\82Â
\82¯
\82½
\81D");
1012 exercise(A_DEX, FALSE);
1016 pline("That door is closed.");
1018 pline("
\94à
\82Í
\95Â
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D");
1020 } else if (mode == TEST_TRAV || mode == TEST_TRAP)
1026 if (dx && dy && !Passes_walls
1027 && (!doorless_door(x, y) || block_door(x, y))) {
1028 /* Diagonal moves into a door are not allowed. */
1029 if (mode == DO_MOVE) {
1031 feel_location(x, y);
1032 if (Underwater || iflags.mention_walls)
1034 You_cant("move diagonally into an intact doorway.");
1036 You_cant("
\89ó
\82ê
\82Ä
\82¢
\82È
\82¢
\94à
\82É
\8eÎ
\82ß
\82É
\88Ú
\93®
\82·
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D");
1042 if (dx && dy && bad_rock(youmonst.data, ux, y)
1043 && bad_rock(youmonst.data, x, uy)) {
1044 /* Move at a diagonal. */
1045 switch (cant_squeeze_thru(&youmonst)) {
1047 if (mode == DO_MOVE)
1049 You("cannot pass that way.");
1051 You("
\92Ê
\82è
\82Ê
\82¯
\82Å
\82«
\82È
\82¢
\81D");
1054 if (mode == DO_MOVE)
1056 You("are carrying too much to get through.");
1058 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1061 if (mode == DO_MOVE)
1063 Your("body is too large to fit through.");
1065 Your("
\91Ì
\82ª
\91å
\82«
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1068 break; /* can squeeze through */
1070 } else if (dx && dy && worm_cross(ux, uy, x, y)) {
1071 /* consecutive long worm segments are at <ux,y> and <x,uy> */
1072 if (mode == DO_MOVE)
1074 pline("%s is in your way.", Monnam(m_at(ux, y)));
1076 pline("
\93¹
\82Ì
\93r
\92\86\82É%s
\82ª
\82¢
\82é
\81D", Monnam(m_at(ux, y)));
1079 /* Pick travel path that does not require crossing a trap.
1080 * Avoid water and lava using the usual running rules.
1081 * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
1082 if (context.run == 8 && (mode != DO_MOVE)
1083 && (x != u.ux || y != u.uy)) {
1084 struct trap *t = t_at(x, y);
1087 || (!Levitation && !Flying && !is_clinger(youmonst.data)
1088 && is_pool_or_lava(x, y) && levl[x][y].seenv))
1089 return (mode == TEST_TRAP);
1092 if (mode == TEST_TRAP)
1093 return FALSE; /* do not move through traps */
1095 ust = &levl[ux][uy];
1097 /* Now see if other things block our way . . */
1098 if (dx && dy && !Passes_walls && IS_DOOR(ust->typ)
1099 && (!doorless_door(ux, uy) || block_entry(x, y))) {
1100 /* Can't move at a diagonal out of a doorway with door. */
1101 if (mode == DO_MOVE && iflags.mention_walls)
1103 You_cant("move diagonally out of an intact doorway.");
1105 You_cant("
\89ó
\82ê
\82Ä
\82¢
\82È
\82¢
\94à
\82©
\82ç
\8eÎ
\82ß
\82É
\88Ú
\93®
\82·
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D");
1109 if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
1110 if (!(Blind || Hallucination) && (context.run >= 2)
1111 && mode != TEST_TRAV) {
1112 if (mode == DO_MOVE && iflags.mention_walls)
1114 pline("A boulder blocks your path.");
1116 pline("
\8b\90\8aâ
\82ª
\93¹
\82ð
\82Ó
\82³
\82¢
\82Å
\82¢
\82é
\81D");
1119 if (mode == DO_MOVE) {
1120 /* tunneling monsters will chew before pushing */
1121 if (tunnels(youmonst.data) && !needspick(youmonst.data)
1123 if (still_chewing(x, y))
1125 } else if (moverock() < 0)
1127 } else if (mode == TEST_TRAV) {
1130 /* never travel through boulders in Sokoban */
1134 /* don't pick two boulders in a row, unless there's a way thru */
1135 if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
1137 && !(tunnels(youmonst.data) && !needspick(youmonst.data))
1138 && !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK)
1139 && !((obj = carrying(WAN_DIGGING))
1140 && !objects[obj->otyp].oc_name_known))
1144 /* assume you'll be able to push it when you get there... */
1147 /* OK, it is a legal place to move. */
1152 * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
1153 * A shortest path is returned. If guess is TRUE, consider various
1154 * inaccessible locations as valid intermediate path points.
1155 * Returns TRUE if a path was found.
1158 findtravelpath(mode)
1161 /* if travel to adjacent, reachable location, use normal movement rules */
1162 if ((mode == TRAVP_TRAVEL || mode == TRAVP_VALID) && context.travel1
1163 && distmin(u.ux, u.uy, u.tx, u.ty) == 1
1164 && !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
1166 if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
1167 if (mode == TRAVP_TRAVEL) {
1171 iflags.travelcc.x = iflags.travelcc.y = 0;
1175 if (mode == TRAVP_TRAVEL)
1178 if (u.tx != u.ux || u.ty != u.uy) {
1179 xchar travel[COLNO][ROWNO];
1180 xchar travelstepx[2][COLNO * ROWNO];
1181 xchar travelstepy[2][COLNO * ROWNO];
1182 xchar tx, ty, ux, uy;
1183 int n = 1; /* max offset in travelsteps */
1184 int set = 0; /* two sets current and previous */
1185 int radius = 1; /* search radius */
1188 /* If guessing, first find an "obvious" goal location. The obvious
1189 * goal is the position the player knows of, or might figure out
1190 * (couldsee) that is closest to the target on a straight path.
1192 if (mode == TRAVP_GUESS || mode == TRAVP_VALID) {
1205 (void) memset((genericptr_t) travel, 0, sizeof travel);
1206 travelstepx[0][0] = tx;
1207 travelstepy[0][0] = ty;
1212 for (i = 0; i < n; i++) {
1214 int x = travelstepx[set][i];
1215 int y = travelstepy[set][i];
1216 static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
1217 /* no diagonal movement for grid bugs */
1218 int dirmax = NODIAG(u.umonnum) ? 4 : 8;
1219 boolean alreadyrepeated = FALSE;
1221 for (dir = 0; dir < dirmax; ++dir) {
1222 int nx = x + xdir[ordered[dir]];
1223 int ny = y + ydir[ordered[dir]];
1226 * When guessing and trying to travel as close as possible
1227 * to an unreachable target space, don't include spaces
1228 * that would never be picked as a guessed target in the
1229 * travel matrix describing hero-reachable spaces.
1230 * This stops travel from getting confused and moving
1231 * the hero back and forth in certain degenerate
1232 * configurations of sight-blocking obstacles, e.g.
1234 * T 1. Dig this out and carry enough to not be
1235 * #### able to squeeze through diagonal gaps.
1236 * #--.--- Stand at @ and target travel at space T.
1240 * T 2. couldsee() marks spaces marked a and x
1241 * #### as eligible guess spaces to move the hero
1242 * a--.--- towards. Space a is closest to T, so it
1243 * @xxxxx gets chosen. Travel system moves @ right
1244 * |xxxxx to travel to space a.
1246 * T 3. couldsee() marks spaces marked b, c and x
1247 * #### as eligible guess spaces to move the hero
1248 * a--c--- towards. Since findtravelpath() is called
1249 * b@xxxx repeatedly during travel, it doesn't
1250 * |xxxxx remember that it wanted to go to space a,
1251 * so in comparing spaces b and c, b is
1252 * chosen, since it seems like the closest
1253 * eligible space to T. Travel system moves @
1254 * left to go to space b.
1258 * By limiting the travel matrix here, space a in the
1259 * example above is never included in it, preventing
1263 || ((mode == TRAVP_GUESS) && !couldsee(nx, ny)))
1265 if ((!Passes_walls && !can_ooze(&youmonst)
1266 && closed_door(x, y)) || sobj_at(BOULDER, x, y)
1267 || test_move(x, y, nx-x, ny-y, TEST_TRAP)) {
1268 /* closed doors and boulders usually
1269 * cause a delay, so prefer another path */
1270 if (travel[x][y] > radius - 3) {
1271 if (!alreadyrepeated) {
1272 travelstepx[1 - set][nn] = x;
1273 travelstepy[1 - set][nn] = y;
1274 /* don't change travel matrix! */
1276 alreadyrepeated = TRUE;
1281 if (test_move(x, y, nx - x, ny - y, TEST_TRAV)
1282 && (levl[nx][ny].seenv
1283 || (!Blind && couldsee(nx, ny)))) {
1284 if (nx == ux && ny == uy) {
1285 if (mode == TRAVP_TRAVEL || mode == TRAVP_VALID) {
1288 if (mode == TRAVP_TRAVEL
1289 && x == u.tx && y == u.ty) {
1291 /* reset run so domove run checks work */
1293 iflags.travelcc.x = iflags.travelcc.y = 0;
1297 } else if (!travel[nx][ny]) {
1298 travelstepx[1 - set][nn] = nx;
1299 travelstepy[1 - set][nn] = ny;
1300 travel[nx][ny] = radius;
1308 if (iflags.trav_debug) {
1309 /* Use of warning glyph is arbitrary. It stands out. */
1310 tmp_at(DISP_ALL, warning_to_glyph(1));
1311 for (i = 0; i < nn; ++i) {
1312 tmp_at(travelstepx[1 - set][i], travelstepy[1 - set][i]);
1315 if (flags.runmode == RUN_CRAWL) {
1319 tmp_at(DISP_END, 0);
1328 /* if guessing, find best location in travel matrix and go there */
1329 if (mode == TRAVP_GUESS) {
1330 int px = tx, py = ty; /* pick location */
1331 int dist, nxtdist, d2, nd2;
1333 dist = distmin(ux, uy, tx, ty);
1334 d2 = dist2(ux, uy, tx, ty);
1335 for (tx = 1; tx < COLNO; ++tx)
1336 for (ty = 0; ty < ROWNO; ++ty)
1337 if (travel[tx][ty]) {
1338 nxtdist = distmin(ux, uy, tx, ty);
1339 if (nxtdist == dist && couldsee(tx, ty)) {
1340 nd2 = dist2(ux, uy, tx, ty);
1342 /* prefer non-zigzag path */
1347 } else if (nxtdist < dist && couldsee(tx, ty)) {
1351 d2 = dist2(ux, uy, tx, ty);
1355 if (px == u.ux && py == u.uy) {
1356 /* no guesses, just go in the general direction */
1357 u.dx = sgn(u.tx - u.ux);
1358 u.dy = sgn(u.ty - u.uy);
1359 if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
1364 if (iflags.trav_debug) {
1365 /* Use of warning glyph is arbitrary. It stands out. */
1366 tmp_at(DISP_ALL, warning_to_glyph(2));
1369 if (flags.runmode == RUN_CRAWL) {
1375 tmp_at(DISP_END, 0);
1384 mode = TRAVP_TRAVEL;
1398 is_valid_travelpt(x,y)
1404 int g = glyph_at(x,y);
1405 if (x == u.ux && y == u.uy)
1407 if (isok(x,y) && glyph_is_cmap(g) && S_stone == glyph_to_cmap(g)
1408 && !levl[x][y].seenv)
1412 ret = findtravelpath(TRAVP_VALID);
1418 /* try to escape being stuck in a trapped state by walking out of it;
1419 return true iff moving should continue to intended destination
1420 (all failures and most successful escapes leave hero at original spot) */
1422 trapmove(x, y, desttrap)
1423 int x, y; /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
1424 struct trap *desttrap; /* nonnull if another trap at <x,y> */
1426 boolean anchored = FALSE;
1427 const char *predicament, *culprit;
1428 char *steedname = !u.usteed ? (char *) 0 : y_monnam(u.usteed);
1431 return TRUE; /* sanity check */
1434 * Note: caller should call reset_utrap() when we set u.utrap to 0.
1437 switch (u.utraptype) {
1439 if (flags.verbose) {
1441 predicament = "caught in a bear trap";
1443 predicament = "
\8cF
\82Ìã©
\82É
\82Â
\82©
\82Ü
\82Á
\82½";
1446 Norep("%s is %s.", upstart(steedname), predicament);
1448 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1451 Norep("You are %s.", predicament);
1453 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1455 /* [why does diagonal movement give quickest escape?] */
1456 if ((u.dx && u.dy) || !rn2(5))
1462 if (desttrap && desttrap->tseen
1463 && is_pit(desttrap->ttyp))
1464 return TRUE; /* move into adjacent pit */
1465 /* try to escape; position stays same regardless of success */
1469 if (uwep && uwep->oartifact == ART_STING) {
1470 /* escape trap but don't move and don't destroy it */
1471 u.utrap = 0; /* caller will call reset_utrap() */
1473 pline("Sting cuts through the web!");
1475 pline("
\83X
\83e
\83B
\83\93\83O
\82Í
\82
\82à
\82Ì
\91\83\82ð
\90Ø
\82è
\82³
\82¢
\82½
\81I");
1479 if (flags.verbose) {
1481 predicament = "stuck to the web";
1483 predicament = "
\82
\82à
\82Ì
\91\83\82É
\82Ð
\82Á
\82©
\82©
\82Á
\82½";
1486 Norep("%s is %s.", upstart(steedname), predicament);
1488 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1491 Norep("You are %s.", predicament);
1493 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1498 pline("%s breaks out of the web.", upstart(steedname));
1500 pline("%s
\82Í
\82
\82à
\82Ì
\91\83\82ð
\89ó
\82µ
\82½
\81D", upstart(steedname));
1503 You("disentangle yourself.");
1505 You("
\8e©
\95ª
\82Å
\82Ù
\82Ç
\82¢
\82½
\81D");
1509 if (flags.verbose) {
1511 predicament = "stuck in the lava";
1513 predicament = "
\97n
\8aâ
\82É
\82Í
\82Ü
\82Á
\82½";
1516 Norep("%s is %s.", upstart(steedname), predicament);
1518 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1521 Norep("You are %s.", predicament);
1523 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1525 if (!is_lava(x, y)) {
1527 if ((u.utrap & 0xff) == 0) {
1531 You("lead %s to the edge of the %s.", steedname,
1534 You("%s
\82ð%s
\82Ì
\92[
\82Ü
\82Å
\93±
\82¢
\82½
\81D", steedname,
1535 hliquid("
\97n
\8aâ"));
1539 You("pull yourself to the edge of the %s.",
1542 You("%s
\82Ì
\92[
\82Ü
\82Å
\82©
\82ë
\82¤
\82¶
\82Ä
\81C
\82½
\82Ç
\82è
\82Â
\82¢
\82½
\81D",
1543 hliquid("
\97n
\8aâ"));
1551 anchored = (u.utraptype == TT_BURIEDBALL);
1555 cc.x = u.ux, cc.y = u.uy;
1556 /* can move normally within radius 1 of buried ball */
1557 if (buried_ball(&cc) && dist2(x, y, cc.x, cc.y) <= 2) {
1558 /* ugly hack: we need to issue some message here
1559 in case "you are chained to the buried ball"
1560 was the most recent message given, otherwise
1561 our next attempt to move out of tether range
1562 after this successful move would have its
1563 can't-do-that message suppressed by Norep */
1566 Norep("You move within the chain's reach.");
1568 Norep("
\8d½
\82ª
\93Í
\82
\94Í
\88Í
\82É
\88Ú
\93®
\82Å
\82«
\82é
\81D");
1573 if (flags.verbose) {
1576 predicament = "chained to the";
1577 culprit = "buried ball";
1579 predicament = "
\82Æ
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é";
1580 culprit = "
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é
\8b\85";
1584 predicament = "stuck in the";
1585 culprit = surface(u.ux, u.uy);
1587 predicament = "
\82É
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é";
1588 culprit = surface(u.ux, u.uy);
1594 Norep("You and %s are %s %s.", steedname, predicament,
1597 Norep("
\82 \82È
\82½
\82Æ%s
\82Í%s%s
\81D", steedname, culprit,
1602 Norep("%s is %s %s.", upstart(steedname), predicament,
1605 Norep("%s
\82Í%s%s
\81D", steedname, culprit,
1610 Norep("You are %s %s.", predicament, culprit);
1612 Norep("
\82 \82È
\82½
\82Í%s
\82É%s
\81D", culprit, predicament);
1618 pline("%s finally %s free.", upstart(steedname),
1619 !anchored ? "lurches" : "wrenches the ball");
1621 pline("%s
\82Í%s
\82â
\82Á
\82Æ
\8e©
\97R
\82É
\82È
\82Á
\82½
\81D", upstart(steedname),
1622 !anchored ? "
\82à
\82ª
\82¢
\82Ä" : "
\93S
\8b\85\82ð
\82à
\82¬
\8eæ
\82Á
\82Ä");
1626 You("finally %s free.",
1627 !anchored ? "wriggle" : "wrench the ball");
1629 You("%s
\82â
\82Á
\82Æ
\8e©
\97R
\82É
\82È
\82Á
\82½
\81D",
1630 !anchored ? "
\82à
\82ª
\82¢
\82Ä" : "
\93S
\8b\85\82ð
\82à
\82¬
\8eæ
\82Á
\82Ä");
1633 buried_ball_to_punishment();
1637 impossible("trapmove: stuck in unknown trap? (%d)",
1647 if (!youmonst.data->mmove) {
1649 You("are rooted %s.",
1650 Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
1654 You("
\82»
\82Ì
\8fê
\82É
\97§
\82¿
\82·
\82
\82ñ
\82¾
\81D");
1665 int ux1 = u.ux, uy1 = u.uy;
1667 domove_succeeded = 0L;
1669 /* domove_succeeded is available for making assessments now */
1670 if ((domove_succeeded & (DOMOVE_RUSH | DOMOVE_WALK)) != 0)
1671 maybe_smudge_engr(ux1, uy1, u.ux, u.uy);
1672 domove_attempting = 0L;
1678 register struct monst *mtmp;
1679 register struct rm *tmpr;
1680 register xchar x, y;
1681 struct trap *trap = NULL;
1684 xchar chainx = 0, chainy = 0,
1685 ballx = 0, bally = 0; /* ball&chain new positions */
1686 int bc_control = 0; /* control for ball&chain */
1687 boolean cause_delay = FALSE; /* dragging ball will skip a move */
1689 if (context.travel) {
1690 if (!findtravelpath(FALSE))
1691 (void) findtravelpath(TRUE);
1692 context.travel1 = 0;
1695 if (((wtcap = near_capacity()) >= OVERLOADED
1696 || (wtcap > SLT_ENCUMBER
1697 && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1698 : (u.uhp < 10 && u.uhp != u.uhpmax))))
1699 && !Is_airlevel(&u.uz)) {
1700 if (wtcap < OVERLOADED) {
1702 You("don't have enough stamina to move.");
1704 You("
\82Ö
\82Æ
\82Ö
\82Æ
\82Å
\93®
\82¯
\82È
\82¢
\81D");
1705 exercise(A_CON, FALSE);
1708 You("collapse under your load.");
1710 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\93|
\82ê
\82½
\81D");
1716 u.ux = x = u.ustuck->mx;
1717 u.uy = y = u.ustuck->my;
1720 if (Is_airlevel(&u.uz) && rn2(4) && !Levitation && !Flying) {
1724 You("tumble in place.");
1726 You("
\82»
\82Ì
\8fê
\82Å
\93|
\82ê
\82½
\81D");
1727 exercise(A_DEX, FALSE);
1731 You_cant("control your movements very well.");
1733 You("
\82¤
\82Ü
\82
\95à
\82¯
\82È
\82¢
\81D");
1737 pline("It's hard to walk in thin air.");
1739 pline("
\8bó
\92\86\82ð
\95à
\82
\82Ì
\82Í
\93ï
\82µ
\82¢
\81D");
1740 exercise(A_DEX, TRUE);
1746 /* check slippery ice */
1747 on_ice = !Levitation && is_ice(u.ux, u.uy);
1749 static int skates = 0;
1752 skates = find_skates();
1753 if ((uarmf && uarmf->otyp == skates) || resists_cold(&youmonst)
1754 || Flying || is_floater(youmonst.data)
1755 || is_clinger(youmonst.data) || is_whirly(youmonst.data)) {
1757 } else if (!rn2(Cold_resistance ? 3 : 2)) {
1758 HFumbling |= FROMOUTSIDE;
1759 HFumbling &= ~TIMEOUT;
1760 HFumbling += 1; /* slip on next move */
1763 if (!on_ice && (HFumbling & FROMOUTSIDE))
1764 HFumbling &= ~FROMOUTSIDE;
1768 if (Stunned || (Confusion && !rn2(5))) {
1769 register int tries = 0;
1779 } while (!isok(x, y) || bad_rock(youmonst.data, x, y));
1781 /* turbulence might alter your actual destination */
1784 if (!u.dx && !u.dy) {
1791 /* are we trying to move out of water while carrying too much? */
1792 if (isok(x, y) && !is_pool(x, y) && !Is_waterlevel(&u.uz)
1793 && wtcap > (Swimming ? MOD_ENCUMBER : SLT_ENCUMBER)) {
1794 /* when escaping from drowning you need to be unencumbered
1795 in order to crawl out of water, but when not drowning,
1796 doing so while encumbered is feasible; if in an aquatic
1797 form, stressed or less is allowed; otherwise (magical
1798 breathing), only burdened is allowed */
1799 You("are carrying too much to climb out of the water.");
1808 if (((trap = t_at(x, y)) && trap->tseen)
1809 || (Blind && !Levitation && !Flying && !is_clinger(youmonst.data)
1810 && is_pool_or_lava(x, y) && levl[x][y].seenv)) {
1811 if (context.run >= 2) {
1812 if (iflags.mention_walls) {
1813 if (trap && trap->tseen) {
1814 int tt = what_trap(trap->ttyp, rn2_on_display_rng);
1817 You("stop in front of %s.",
1819 You("%s
\82Ì
\8eè
\91O
\82Å
\8e~
\82Ü
\82Á
\82½
\81D",
1820 an(defsyms[trap_to_defsym(tt)].explanation));
1821 } else if (is_pool_or_lava(x,y) && levl[x][y].seenv) {
1823 You("stop at the edge of the %s.",
1824 hliquid(is_pool(x,y) ? "water" : "lava"));
1826 You("%s
\82Ì
\92[
\82Å
\8e~
\82Ü
\82Á
\82½
\81D.",
1827 hliquid(is_pool(x,y) ? "
\90\85" : "
\97n
\8aâ"));
1838 if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
1839 if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
1840 /* perhaps it fled (or was teleported or ... ) */
1842 } else if (sticks(youmonst.data)) {
1843 /* When polymorphed into a sticking monster,
1844 * u.ustuck means it's stuck to you, not you to it.
1847 You("release %s.", mon_nam(u.ustuck));
1849 You("%s
\82ð
\95ú
\82µ
\82½
\81D", mon_nam(u.ustuck));
1852 /* If holder is asleep or paralyzed:
1853 * 37.5% chance of getting away,
1854 * 12.5% chance of waking/releasing it;
1856 * 7.5% chance of getting away.
1857 * [strength ought to be a factor]
1858 * If holder is tame and there is no conflict,
1859 * guaranteed escape.
1861 switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
1867 You("pull free from %s.", mon_nam(u.ustuck));
1869 You("%s
\82ð
\82Ð
\82«
\82Í
\82È
\82µ
\82½
\81D", mon_nam(u.ustuck));
1873 if (!u.ustuck->mcanmove) {
1874 /* it's free to move on next turn */
1875 u.ustuck->mfrozen = 1;
1876 u.ustuck->msleeping = 0;
1880 if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf)
1883 You("cannot escape from %s!", mon_nam(u.ustuck));
1885 You("%s
\82©
\82ç
\93¦
\82°
\82ç
\82ê
\82È
\82¢
\81I", mon_nam(u.ustuck));
1893 if (mtmp && !is_safepet(mtmp)) {
1894 /* Don't attack if you're running, and can see it */
1895 /* It's fine to displace pets, though */
1896 /* We should never get here if forcefight */
1897 if (context.run && ((!Blind && mon_visible(mtmp)
1898 && ((M_AP_TYPE(mtmp) != M_AP_FURNITURE
1899 && M_AP_TYPE(mtmp) != M_AP_OBJECT)
1900 || Protection_from_shape_changers))
1901 || sensemon(mtmp))) {
1915 /* attack monster */
1917 /* don't stop travel when displacing pets; if the
1918 displace fails for some reason, attack() in uhitm.c
1919 will stop travel rather than domove */
1920 if (!is_safepet(mtmp) || context.forcefight)
1922 /* only attack if we know it's there */
1923 /* or if we used the 'F' command to fight blindly */
1924 /* or if it hides_under, in which case we call attack() to print
1925 * the Wait! message.
1926 * This is different from ceiling hiders, who aren't handled in
1930 /* If they used a 'm' command, trying to move onto a monster
1931 * prints the below message and wastes a turn. The exception is
1932 * if the monster is unseen and the player doesn't remember an
1933 * invisible monster--then, we fall through to attack() and
1934 * attack_check(), which still wastes a turn, but prints a
1935 * different message and makes the player remember the monster.
1937 if (context.nopick && !context.travel
1938 && (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))) {
1939 if (M_AP_TYPE(mtmp) && !Protection_from_shape_changers
1941 stumble_onto_mimic(mtmp);
1942 else if (mtmp->mpeaceful && !Hallucination)
1943 /* m_monnam(): "dog" or "Fido", no "invisible dog" or "it" */
1945 pline("Pardon me, %s.", m_monnam(mtmp));
1947 pline("
\82¿
\82å
\82Á
\82Æ
\82²
\82ß
\82ñ
\82È
\82³
\82¢
\82æ
\81C%s
\82³
\82ñ
\81D", m_monnam(mtmp));
1950 You("move right into %s.", mon_nam(mtmp));
1952 You("%s
\82Ì
\82»
\82Î
\82É
\88Ú
\93®
\82µ
\82½
\81D", mon_nam(mtmp));
1955 if (context.forcefight || !mtmp->mundetected || sensemon(mtmp)
1956 || ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)
1957 && !is_safepet(mtmp))) {
1958 /* try to attack; note that it might evade */
1959 /* also, we don't attack tame when _safepet_ */
1965 if (context.forcefight && levl[x][y].typ == IRONBARS && uwep) {
1966 struct obj *obj = uwep;
1968 if (breaktest(obj)) {
1970 obj = splitobj(obj, 1L);
1972 setuwep((struct obj *)0);
1975 hit_bars(&obj, u.ux, u.uy, x, y, TRUE, TRUE);
1979 /* specifying 'F' with no monster wastes a turn */
1980 if (context.forcefight
1981 /* remembered an 'I' && didn't use a move command */
1982 || (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
1983 struct obj *boulder = 0;
1984 boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
1985 solid = !accessible(x, y);
1986 int glyph = glyph_at(x, y); /* might be monster */
1990 boulder = sobj_at(BOULDER, x, y);
1991 /* if a statue is displayed at the target location,
1992 player is attempting to attack it [and boulder
1993 handling below is suitable for handling that] */
1994 if (glyph_is_statue(glyph)
1995 || (Hallucination && glyph_is_monster(glyph)))
1996 boulder = sobj_at(STATUE, x, y);
1998 /* force fight at boulder/statue or wall/door while wielding
1999 pick: start digging to break the boulder or wall */
2000 if (context.forcefight
2002 && uwep && dig_typ(uwep, x, y)
2003 /* should we dig? */
2004 && !glyph_is_invisible(glyph) && !glyph_is_monster(glyph)) {
2005 (void) use_pick_axe2(uwep);
2010 /* about to become known empty -- remove 'I' if present */
2013 map_object(boulder, TRUE);
2015 glyph = glyph_at(x, y); /* might have just changed */
2018 Strcpy(buf, ansimpleoname(boulder));
2019 } else if (Underwater && !is_pool(x, y)) {
2020 /* Underwater, targetting non-water; the map just shows blank
2021 because you don't see remembered terrain while underwater;
2022 although the hero can attack an adjacent monster this way,
2023 assume he can't reach out far enough to distinguish terrain */
2025 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
2029 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
2030 ? "
\8bó
\8bC
\82Ì
\96A"
2031 : "
\89½
\82à
\82È
\82¢
\82Æ
\82±
\82ë");
2034 /* glyph might indicate unseen terrain if hero is blind;
2035 unlike searching, this won't reveal what that terrain is
2036 (except for solid rock, where the glyph would otherwise
2037 yield ludicrous "dark part of a room") */
2039 Strcpy(buf, (levl[x][y].typ == STONE) ? "solid rock"
2040 : glyph_is_cmap(glyph)
2041 ? the(defsyms[glyph_to_cmap(glyph)].explanation)
2042 : (const char *) "an unknown obstacle");
2044 Strcpy(buf, (levl[x][y].typ == STONE) ? "
\90Î"
2045 : glyph_is_cmap(glyph)
2046 ? the(defsyms[glyph_to_cmap(glyph)].explanation)
2047 : (const char *) "
\95s
\96¾
\82È
\8fá
\8aQ
\95¨");
2049 /* note: 'solid' is misleadingly named and catches pools
2050 of water and lava as well as rock and walls */
2053 Strcpy(buf, "thin air");
2055 Strcpy(buf, "
\89½
\82à
\82È
\82¢
\8bó
\92\86");
2059 !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
2060 explo ? "explode at" : "attack", buf);
2063 !(boulder || solid) ? "" : !explo ? "
\8cø
\89Ê
\82È
\82" : "
\82Þ
\82¾
\82É",
2064 buf, explo ? "
\82Å
\94\9a\94
\82µ
\82½" : "
\82ð
\8dU
\8c\82\82µ
\82½");
2070 u.mh = -1; /* dead in the current form */
2075 (void) unmap_invisible(x, y);
2076 /* not attacking an animal, so we try to move */
2077 if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
2086 boolean moved = trapmove(x, y, trap);
2089 reset_utrap(TRUE); /* might resume levitation or flight */
2090 /* might not have escaped, or did escape but remain in same spot */
2095 if (!test_move(u.ux, u.uy, x - u.ux, y - u.uy, DO_MOVE)) {
2096 if (!context.door_opened) {
2103 /* Move ball and chain. */
2105 if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy,
2106 &cause_delay, TRUE))
2109 /* Check regions entering/leaving */
2110 if (!in_out_region(x, y))
2113 /* now move the hero */
2117 /* Move your steed, too */
2119 u.usteed->mx = u.ux;
2120 u.usteed->my = u.uy;
2125 * If safepet at destination then move the pet to the hero's
2126 * previous location using the same conditions as in attack().
2127 * there are special extenuating circumstances:
2128 * (1) if the pet dies then your god angers,
2129 * (2) if the pet gets trapped then your god may disapprove,
2130 * (3) if the pet was already trapped and you attempt to free it
2131 * not only do you encounter the trap but you may frighten your
2132 * pet causing it to go wild! moral: don't abuse this privilege.
2134 * Ceiling-hiding pets are skipped by this section of code, to
2135 * be caught by the normal falling-monster code.
2137 if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
2138 /* if trapped, there's a chance the pet goes wild */
2139 if (mtmp->mtrapped) {
2140 if (!rn2(mtmp->mtame)) {
2141 mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
2143 m_unleash(mtmp, TRUE);
2150 /* seemimic/newsym should be done before moving hero, otherwise
2151 the display code will draw the hero here before we possibly
2152 cancel the swap below (we can ignore steed mx,my here) */
2153 u.ux = u.ux0, u.uy = u.uy0;
2154 mtmp->mundetected = 0;
2155 if (M_AP_TYPE(mtmp))
2157 else if (!mtmp->mtame)
2158 newsym(mtmp->mx, mtmp->my);
2159 u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
2161 if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
2162 && is_pit(trap->ttyp)
2163 && sobj_at(BOULDER, trap->tx, trap->ty)) {
2164 /* can't swap places with pet pinned in a pit by a boulder */
2165 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
2167 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2168 } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
2169 /* can't swap places when pet can't move to your spot */
2170 u.ux = u.ux0, u.uy = u.uy0;
2172 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2174 You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp)));
2176 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\8eÎ
\82ß
\82É
\93®
\82¯
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
2177 } else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0)
2178 && bad_rock(mtmp->data, u.ux0, y)
2179 && (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
2180 /* can't swap places when pet won't fit thru the opening */
2181 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
2183 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2185 You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
2187 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
2189 char pnambuf[BUFSZ];
2191 /* save its current description in case of polymorph */
2192 Strcpy(pnambuf, y_monnam(mtmp));
2194 remove_monster(x, y);
2195 place_monster(mtmp, u.ux0, u.uy0);
2197 newsym(u.ux0, u.uy0);
2200 You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
2205 mtmp->mtame ? "
\82Æ
\8fê
\8f\8a\82ð
\93ü
\82ê
\8a·
\82í
\82Á" : "
\82ð
\95|
\82ª
\82ç
\82¹");
2208 /* check for displacing it into pools and traps */
2209 switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
2212 case 1: /* trapped */
2213 case 3: /* changed levels */
2214 /* there's already been a trap message, reinforce it */
2219 /* drowned or died...
2220 * you killed your pet by direct action, so get experience
2221 * and possibly penalties;
2222 * we want the level gain message, if it happens, to occur
2223 * before the guilt message below
2226 /* minliquid() and mintrap() call mondead() rather than
2227 killed() so we duplicate some of the latter here */
2230 u.uconduct.killer++;
2231 mndx = monsndx(mtmp->data);
2232 tmp = experience(mtmp, (int) mvitals[mndx].died);
2233 more_experienced(tmp, 0);
2234 newexplevel(); /* will decide if you go up */
2236 /* That's no way to treat a pet! Your god gets angry.
2238 * [This has always been pretty iffy. Why does your
2239 * patron deity care at all, let alone enough to get mad?]
2243 You_feel("guilty about losing your pet like this.");
2245 pline("
\82±
\82Ì
\82æ
\82¤
\82È
\8c`
\82Å
\83y
\83b
\83g
\82ð
\8e¸
\82¤
\82Æ
\82Í
\8dß
\90[
\82¢
\82±
\82Æ
\82¾
\82Æ
\8ev
\82Á
\82½
\81D");
2251 pline("that's strange, unknown mintrap result!");
2257 reset_occupations();
2259 if (context.run < 8)
2260 if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ)
2261 || IS_FURNITURE(tmpr->typ))
2265 if (hides_under(youmonst.data) || youmonst.data->mlet == S_EEL
2267 (void) hideunder(&youmonst);
2270 * Mimics (or whatever) become noticeable if they move and are
2271 * imitating something that doesn't move. We could extend this
2272 * to non-moving monsters...
2274 if ((u.dx || u.dy) && (U_AP_TYPE == M_AP_OBJECT
2275 || U_AP_TYPE == M_AP_FURNITURE))
2276 youmonst.m_ap_type = M_AP_NOTHING;
2278 check_leash(u.ux0, u.uy0);
2280 if (u.ux0 != u.ux || u.uy0 != u.uy) {
2281 /* let caller know so that an evaluation may take place */
2282 domove_succeeded |= (domove_attempting & (DOMOVE_RUSH | DOMOVE_WALK));
2284 /* Clean old position -- vision_recalc() will print our new one. */
2285 newsym(u.ux0, u.uy0);
2286 /* Since the hero has moved, adjust what can be seen/unseen. */
2287 vision_recalc(1); /* Do the work now in the recover time. */
2288 invocation_message();
2291 if (Punished) /* put back ball and chain */
2292 move_bc(0, bc_control, ballx, bally, chainx, chainy);
2297 /* delay next move because of ball dragging */
2298 /* must come after we finished picking up, in spoteffects() */
2302 multi_reason = "dragging an iron ball";
2304 multi_reason = "
\93S
\8b\85\82É
\88ø
\82«
\82¸
\82ç
\82ê
\82Ä
\82¢
\82é
\8e\9e\82É";
2308 if (context.run && flags.runmode != RUN_TPORT) {
2309 /* display every step or every 7th step depending upon mode */
2310 if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
2315 if (flags.runmode == RUN_CRAWL) {
2326 maybe_smudge_engr(x1,y1,x2,y2)
2331 if (can_reach_floor(TRUE)) {
2332 if ((ep = engr_at(x1, y1)) && ep->engr_type != HEADSTONE)
2333 wipe_engr_at(x1, y1, rnd(5), FALSE);
2334 if ((x2 != x1 || y2 != y1)
2335 && (ep = engr_at(x2, y2)) && ep->engr_type != HEADSTONE)
2336 wipe_engr_at(x2, y2, rnd(5), FALSE);
2340 /* combat increases metabolism */
2344 /* this used to be part of domove() when moving to a monster's
2345 position, but is now called by attack() so that it doesn't
2346 execute if you decline to attack a peaceful monster */
2348 if ((moves % 3L) != 0L && near_capacity() >= HVY_ENCUMBER) {
2349 int *hp = (!Upolyd ? &u.uhp : &u.mh);
2355 You("pass out from exertion!");
2357 You("
\8bC
\90â
\82µ
\82½
\81D");
2358 exercise(A_CON, FALSE);
2359 fall_asleep(-10, FALSE);
2362 return (boolean) (multi < 0); /* might have fainted (forced to sleep) */
2366 invocation_message()
2368 /* a special clue-msg when on the Invocation position */
2369 if (invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
2371 struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
2373 nomul(0); /* stop running or travelling */
2376 Sprintf(buf, "beneath %s", y_monnam(u.usteed));
2378 Sprintf(buf, "%s
\82Ì
\89º
\82É", y_monnam(u.usteed));
2379 else if (Levitation || Flying)
2381 Strcpy(buf, "beneath you");
2383 Strcpy(buf, "
\89º
\95û
\82É");
2386 Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
2388 Strcpy(buf, "
\91«
\8c³
\82É");
2391 You_feel("a strange vibration %s.", buf);
2393 You("%s
\8aï
\96
\82È
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D", buf);
2394 u.uevent.uvibrated = 1;
2395 if (otmp && otmp->spe == 7 && otmp->lamplit)
2397 pline("%s %s!", The(xname(otmp)),
2398 Blind ? "throbs palpably" : "glows with a strange light");
2400 pline("%s
\82Í%s
\82µ
\82½
\81I", The(xname(otmp)),
2401 Blind ? "
\82©
\82·
\82©
\82É
\90U
\93®" : "
\8aï
\96
\82È
\8cõ
\82ð
\94");
2406 /* moving onto different terrain;
2407 might be going into solid rock, inhibiting levitation or flight,
2408 or coming back out of such, reinstating levitation/flying */
2412 struct rm *lev = &levl[u.ux][u.uy];
2413 boolean blocklev = (IS_ROCK(lev->typ) || closed_door(u.ux, u.uy)
2414 || (Is_waterlevel(&u.uz) && lev->typ == WATER)),
2415 was_levitating = !!Levitation, was_flying = !!Flying;
2418 /* called from spoteffects(), stop levitating but skip float_down() */
2421 You_cant("levitate in here.");
2423 You_cant("
\82±
\82±
\82Å
\82Í
\95\82\97V
\82Å
\82«
\82È
\82¢
\81D");
2424 BLevitation |= FROMOUTSIDE;
2425 } else if (BLevitation) {
2426 BLevitation &= ~FROMOUTSIDE;
2427 /* we're probably levitating now; if not, we must be chained
2428 to a buried iron ball so get float_up() feedback for that */
2429 if (Levitation || BLevitation)
2432 /* the same terrain that blocks levitation also blocks flight */
2436 You_cant("fly in here.");
2438 You_cant("
\82±
\82±
\82Å
\82Í
\94ò
\82×
\82È
\82¢
\81D");
2439 BFlying |= FROMOUTSIDE;
2440 } else if (BFlying) {
2441 BFlying &= ~FROMOUTSIDE;
2442 float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
2443 /* [minor bug: we don't know whether this is beginning flight or
2444 resuming it; that could be tracked so that this message could
2445 be adjusted to "resume flying", but isn't worth the effort...] */
2448 You("start flying.");
2450 You("
\94ò
\82Ñ
\82Í
\82¶
\82ß
\82½
\81D");
2452 if ((!Levitation ^ was_levitating) || (!Flying ^ was_flying))
2453 context.botl = TRUE; /* update Lev/Fly status condition */
2456 /* extracted from spoteffects; called by spoteffects to check for entering or
2457 leaving a pool of water/lava, and by moveloop to check for staying on one;
2458 returns true to skip rest of spoteffects */
2460 pooleffects(newspot)
2461 boolean newspot; /* true if called by spoteffects */
2463 /* check for leaving water */
2465 boolean still_inwater = FALSE; /* assume we're getting out */
2467 if (!is_pool(u.ux, u.uy)) {
2468 if (Is_waterlevel(&u.uz))
2470 You("pop into an air bubble.");
2472 You("
\82Ð
\82å
\82¢
\82Æ
\8bó
\8bC
\82Ì
\96A
\82É
\93ü
\82Á
\82½
\81D");
2473 else if (is_lava(u.ux, u.uy))
2475 You("leave the %s...", hliquid("water")); /* oops! */
2477 You("%s
\90\85\82©
\82ç
\94²
\82¯
\82¾
\82µ
\82½
\81D
\81D
\81D", hliquid("
\90\85")); /* oops! */
2481 You("are on solid %s again.",
2482 is_ice(u.ux, u.uy) ? "ice" : "land");
2484 You("
\8cÅ
\82¢%s
\82Ì
\8fã
\82É
\82Ü
\82½
\96ß
\82Á
\82½
\81D",
2485 is_ice(u.ux, u.uy) ? "
\95X" : "
\92n
\96Ê");
2487 } else if (Is_waterlevel(&u.uz)) {
2488 still_inwater = TRUE;
2489 } else if (Levitation) {
2491 You("pop out of the %s like a cork!", hliquid("water"));
2493 You("
\83R
\83\8b\83N
\82Ì
\82æ
\82¤
\82É%s
\82©
\82ç
\94ò
\82Ñ
\82¾
\82µ
\82½
\81I", hliquid("
\90\85"));
2494 } else if (Flying) {
2496 You("fly out of the %s.", hliquid("water"));
2498 You("%s
\82©
\82ç
\94ò
\82Ñ
\82¾
\82µ
\82½
\81D", hliquid("
\90\85"));
2499 } else if (Wwalking) {
2501 You("slowly rise above the surface.");
2503 You("
\82ä
\82Á
\82
\82è
\90\85\96Ê
\82Ü
\82Å
\8fã
\82ª
\82Á
\82½
\81D");
2505 still_inwater = TRUE;
2507 if (!still_inwater) {
2508 boolean was_underwater = (Underwater && !Is_waterlevel(&u.uz));
2510 u.uinwater = 0; /* leave the water */
2511 if (was_underwater) { /* restore vision */
2513 vision_full_recalc = 1;
2518 /* check for entering water or lava */
2519 if (!u.ustuck && !Levitation && !Flying && is_pool_or_lava(u.ux, u.uy)) {
2521 && (is_flyer(u.usteed->data) || is_floater(u.usteed->data)
2522 || is_clinger(u.usteed->data))) {
2523 /* floating or clinging steed keeps hero safe (is_flyer() test
2524 is redundant; it can't be true since Flying yielded false) */
2526 } else if (u.usteed) {
2527 /* steed enters pool */
2528 dismount_steed(Underwater ? DISMOUNT_FELL : DISMOUNT_GENERIC);
2529 /* dismount_steed() -> float_down() -> pickup()
2530 (float_down doesn't do autopickup on Air or Water) */
2531 if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
2533 /* even if we actually end up at same location, float_down()
2534 has already done spoteffect()'s trap and pickup actions */
2536 check_special_room(FALSE); /* spoteffects */
2541 /* drown(),lava_effects() return true if hero changes
2542 location while surviving the problem */
2543 if (is_lava(u.ux, u.uy)) {
2546 } else if (!Wwalking
2547 && (newspot || !u.uinwater || !(Swimming || Amphibious))) {
2559 static int inspoteffects = 0;
2560 static coord spotloc;
2561 static int spotterrain;
2562 static struct trap *spottrap = (struct trap *) 0;
2563 static unsigned spottraptyp = NO_TRAP;
2566 struct trap *trap = t_at(u.ux, u.uy);
2567 int trapflag = iflags.failing_untrap ? FAILEDUNTRAP : 0;
2569 /* prevent recursion from affecting the hero all over again
2570 [hero poly'd to iron golem enters water here, drown() inflicts
2571 damage that triggers rehumanize() which calls spoteffects()...] */
2572 if (inspoteffects && u.ux == spotloc.x && u.uy == spotloc.y
2573 /* except when reason is transformed terrain (ice -> water) */
2574 && spotterrain == levl[u.ux][u.uy].typ
2575 /* or transformed trap (land mine -> pit) */
2576 && (!spottrap || !trap || trap->ttyp == spottraptyp))
2580 spotterrain = levl[u.ux][u.uy].typ;
2581 spotloc.x = u.ux, spotloc.y = u.uy;
2583 /* moving onto different terrain might cause Lev or Fly to toggle */
2584 if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
2587 if (pooleffects(TRUE))
2590 check_special_room(FALSE);
2591 if (IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
2593 if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
2596 /* if levitation is due to time out at the end of this
2597 turn, allowing it to do so could give the perception
2598 that a trap here is being triggered twice, so adjust
2599 the timeout to prevent that */
2600 if (trap && (HLevitation & TIMEOUT) == 1L
2601 && !(ELevitation || (HLevitation & ~(I_SPECIAL | TIMEOUT)))) {
2602 if (rn2(2)) { /* defer timeout */
2603 incr_itimeout(&HLevitation, 1L);
2604 } else { /* timeout early */
2605 if (float_down(I_SPECIAL | TIMEOUT, 0L)) {
2606 /* levitation has ended; we've already triggered
2607 any trap and [usually] performed autopickup */
2614 * If not a pit, pickup before triggering trap.
2615 * If pit, trigger trap before pickup.
2617 pit = (trap && is_pit(trap->ttyp));
2623 * dotrap on a fire trap calls melt_ice() which triggers
2624 * spoteffects() (again) which can trigger the same fire
2625 * trap (again). Use static spottrap to prevent that.
2626 * We track spottraptyp because some traps morph
2627 * (landmine to pit) and any new trap type
2628 * should get triggered.
2630 if (!spottrap || spottraptyp != trap->ttyp) {
2632 spottraptyp = trap->ttyp;
2633 dotrap(trap, trapflag); /* fall into arrow trap, etc. */
2634 spottrap = (struct trap *) 0;
2635 spottraptyp = NO_TRAP;
2641 /* Warning alerts you to ice danger */
2642 if (Warning && is_ice(u.ux, u.uy)) {
2643 static const char *const icewarnings[] = {
2645 "The ice seems very soft and slushy.",
2646 "You feel the ice shift beneath you!",
2647 "The ice, is gonna BREAK!", /* The Dead Zone */
2649 "
\95X
\82Í
\82Æ
\82Ä
\82à
\93î
\82ç
\82©
\82
\82Ä
\97n
\82¯
\82»
\82¤
\82¾
\81D",
2650 "
\82 \82È
\82½
\82Ì
\89º
\82Ì
\95X
\82ª
\93®
\82¢
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81I",
2651 "
\95X
\82ª
\89ó
\82ê
\82é
\82¼
\81I", /* The Dead Zone */
2654 long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
2656 if (time_left && time_left < 15L)
2657 pline("%s", icewarnings[(time_left < 5L) ? 2
2658 : (time_left < 10L) ? 1
2661 if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
2662 mtmp->mundetected = mtmp->msleeping = 0;
2663 switch (mtmp->data->mlet) {
2666 pline("%s suddenly drops from the %s!", Amonnam(mtmp),
2667 ceiling(u.ux, u.uy));
2669 pline("%s
\82ª
\93Ë
\91R%s
\82©
\82ç
\97\8e\82¿
\82Ä
\82«
\82½
\81I", Amonnam(mtmp),
2670 ceiling(u.ux,u.uy));
2672 if (mtmp->mtame) { /* jumps to greet you, not attack */
2674 } else if (uarmh && is_metallic(uarmh)) {
2676 pline("Its blow glances off your %s.",
2678 pline("
\8dU
\8c\82\82Í
\82 \82È
\82½
\82Ì%s
\82ð
\82©
\82·
\82ß
\82½
\82¾
\82¯
\82¾
\82Á
\82½
\81D",
2679 helm_simple_name(uarmh));
2680 } else if (u.uac + 3 <= rnd(20)) {
2682 You("are almost hit by %s!",
2683 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2685 You("
\97\8e\82¿
\82Ä
\82«
\82½%s
\82É
\82à
\82¤
\8f
\82µ
\82Å
\93\96\82½
\82é
\82Æ
\82±
\82ë
\82¾
\82Á
\82½
\81D",
2686 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2692 You("are hit by %s!",
2693 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2695 You("
\97\8e\82¿
\82Ä
\82«
\82½%s
\82É
\93\96\82½
\82Á
\82½
\81I",
2696 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2699 if (Half_physical_damage)
2700 dmg = (dmg + 1) / 2;
2701 mdamageu(mtmp, dmg);
2704 default: /* monster surprises you. */
2707 pline("%s jumps near you from the %s.", Amonnam(mtmp),
2708 ceiling(u.ux, u.uy));
2710 pline("%s
\82ª%s
\82©
\82ç
\82 \82È
\82½
\82Ì
\8bß
\82
\82É
\94ò
\82ñ
\82Å
\82«
\82½
\81D", Amonnam(mtmp),
2711 ceiling(u.ux,u.uy));
2713 else if (mtmp->mpeaceful) {
2717 You("%s
\82ð
\8bÁ
\82©
\82µ
\82½
\81I",
2718 Blind && !sensemon(mtmp) ? something : a_monnam(mtmp));
2719 mtmp->mpeaceful = 0;
2722 pline("%s attacks you by surprise!", Amonnam(mtmp));
2724 pline("%s
\82Í
\8bÁ
\82¢
\82Ä
\82 \82È
\82½
\82ð
\8dU
\8c\82\82µ
\82½
\81I", Amonnam(mtmp));
2727 mnexto(mtmp); /* have to move the monster */
2730 if (!--inspoteffects) {
2731 spotterrain = STONE; /* 0 */
2732 spotloc.x = spotloc.y = 0;
2737 /* returns first matching monster */
2738 STATIC_OVL struct monst *
2739 monstinroom(mdat, roomno)
2740 struct permonst *mdat;
2743 register struct monst *mtmp;
2745 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2746 if (DEADMONSTER(mtmp))
2748 if (mtmp->data == mdat
2749 && index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
2752 return (struct monst *) 0;
2756 in_rooms(x, y, typewanted)
2757 register xchar x, y;
2758 register int typewanted;
2761 char rno, *ptr = &buf[4];
2762 int typefound, min_x, min_y, max_x, max_y_offset, step;
2763 register struct rm *lev;
2765 #define goodtype(rno) \
2767 || (typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted \
2768 || (typewanted == SHOPBASE && typefound > SHOPBASE))
2770 switch (rno = levl[x][y].roomno) {
2779 default: /* i.e. a regular room # */
2789 else if (x >= COLNO)
2796 max_y_offset -= step;
2797 } else if ((min_y + max_y_offset) >= ROWNO)
2798 max_y_offset -= step;
2800 for (x = min_x; x <= max_x; x += step) {
2801 lev = &levl[x][min_y];
2803 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2807 if (y > max_y_offset)
2809 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2813 if (y > max_y_offset)
2815 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2822 /* is (x,y) in a town? */
2827 s_level *slev = Is_special(&u.uz);
2828 register struct mkroom *sroom;
2829 boolean has_subrooms = FALSE;
2831 if (!slev || !slev->flags.town)
2835 * See if (x,y) is in a room with subrooms, if so, assume it's the
2836 * town. If there are no subrooms, the whole level is in town.
2838 for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
2839 if (sroom->nsubrooms > 0) {
2840 has_subrooms = TRUE;
2841 if (inside_room(sroom, x, y))
2846 return !has_subrooms;
2851 register boolean newlev;
2853 char *ptr1, *ptr2, *ptr3, *ptr4;
2855 Strcpy(u.urooms0, u.urooms);
2856 Strcpy(u.ushops0, u.ushops);
2859 u.uentered[0] = '\0';
2861 u.ushops_entered[0] = '\0';
2862 Strcpy(u.ushops_left, u.ushops0);
2865 Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
2867 for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
2868 ptr4 = &u.ushops_entered[0];
2870 if (!index(u.urooms0, *ptr1))
2872 if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
2874 if (!index(u.ushops0, *ptr1))
2882 /* filter u.ushops0 -> u.ushops_left */
2883 for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
2884 if (!index(u.ushops, *ptr1))
2889 /* possibly deliver a one-time room entry message */
2891 check_special_room(newlev)
2892 register boolean newlev;
2894 register struct monst *mtmp;
2897 move_update(newlev);
2900 u_left_shop(u.ushops_left, newlev);
2902 if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
2903 return; /* no entrance messages necessary */
2905 /* Did we just enter a shop? */
2906 if (*u.ushops_entered)
2907 u_entered_shop(u.ushops_entered);
2909 for (ptr = &u.uentered[0]; *ptr; ptr++) {
2910 int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
2911 boolean msg_given = TRUE;
2913 /* Did we just enter some other special room? */
2914 /* vault.c insists that a vault remain a VAULT,
2915 * and temples should remain TEMPLEs,
2916 * but everything else gives a message only the first time */
2920 pline("Welcome to David's treasure zoo!");
2922 pline("
\83f
\83r
\83b
\83g
\95ó
\94 \93®
\95¨
\89\80\82É
\82æ
\82¤
\82±
\82»
\81I");
2926 pline("It %s rather %s down here.", Blind ? "feels" : "looks",
2927 Blind ? "humid" : "muddy");
2929 pline("
\82©
\82È
\82è%s
\81D",
2930 Blind ? "
\8e¼
\8bC
\82ª
\82 \82é
\8fê
\8f\8a\82Ì
\82æ
\82¤
\82¾"
2931 : "
\82Ç
\82ë
\82Ç
\82ë
\82µ
\82Ä
\82¢
\82é
\8fê
\8f\8a\82¾");
2936 You("enter an opulent throne room!");
2938 You("
\89Ø
\82â
\82©
\82È
\8bÊ
\8dÀ
\82Ì
\8aÔ
\82É
\93ü
\82Á
\82½
\81I");
2942 You("enter a leprechaun hall!");
2944 You("
\83\8c\83v
\83\89\83R
\81[
\83\93\83z
\81[
\83\8b\82É
\93ü
\82Á
\82½
\81I");
2949 const char *run = locomotion(youmonst.data, "Run");
2950 pline("%s away! %s away!", run, run);
2952 pline("
\93¦
\82°
\82ë
\81I
\93¦
\82°
\82ë
\81I");
2956 You("have an uncanny feeling...");
2958 You("
\95s
\8bC
\96¡
\82È
\8a´
\82¶
\82ª
\82µ
\82½
\81D
\81D
\81D");
2962 You("enter a giant beehive!");
2964 You("
\8b\90\91å
\82È
\96I
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2968 You("enter a disgusting nest!");
2970 You("
\82Þ
\82Á
\82Æ
\82·
\82é
\8fL
\82¢
\82Ì
\82·
\82é
\92¹
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2974 You("enter an anthole!");
2976 You("
\83A
\83\8a\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2979 if (monstinroom(&mons[PM_SOLDIER], roomno)
2980 || monstinroom(&mons[PM_SERGEANT], roomno)
2981 || monstinroom(&mons[PM_LIEUTENANT], roomno)
2982 || monstinroom(&mons[PM_CAPTAIN], roomno))
2984 You("enter a military barracks!");
2986 You("
\8cR
\91à
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81I");
2989 You("enter an abandoned barracks.");
2991 You("
\95ú
\92u
\82³
\82ê
\82½
\82Ü
\82Ü
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81D");
2994 struct monst *oracle = monstinroom(&mons[PM_ORACLE], roomno);
2996 if (!oracle->mpeaceful)
2998 verbalize("You're in Delphi, %s.", plname);
3000 verbalize("
\82¨
\82Ü
\82¦
\82Í
\83f
\83\8b\83t
\83@
\83C
\82Ì
\90_
\91õ
\8f\8a\82É
\82¢
\82é
\81D");
3003 verbalize("%s, %s, welcome to Delphi!",
3004 Hello((struct monst *) 0), plname);
3006 verbalize("
\82¨
\82¨%s
\81C
\83f
\83\8b\83t
\83@
\83C
\82Ì
\90_
\91õ
\8f\8a\82É
\82æ
\82
\82¼
\82Ü
\82¢
\82ç
\82ê
\82½
\81I",
3014 intemple(roomno + ROOMOFFSET);
3017 msg_given = (rt == TEMPLE);
3022 room_discovered(roomno);
3025 rooms[roomno].rtype = OROOM;
3026 if (!search_special(rt)) {
3027 /* No more room of that type */
3030 level.flags.has_court = 0;
3033 level.flags.has_swamp = 0;
3036 level.flags.has_morgue = 0;
3039 level.flags.has_zoo = 0;
3042 level.flags.has_barracks = 0;
3045 level.flags.has_temple = 0;
3048 level.flags.has_beehive = 0;
3052 if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
3053 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
3054 if (DEADMONSTER(mtmp))
3056 if (!Stealth && !rn2(3))
3057 mtmp->msleeping = 0;
3066 1 = cannot pickup, time taken
3067 0 = cannot pickup, no time taken
3068 -1 = do normal pickup
3069 -2 = loot the monster */
3073 /* uswallow case added by GAN 01/29/87 */
3075 if (!u.ustuck->minvent) {
3076 if (is_animal(u.ustuck->data)) {
3078 You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
3080 You("%s
\82Ì
\90ã
\82ð
\8fE
\82Á
\82½
\81D", mon_nam(u.ustuck));
3082 pline("But it's kind of slimy, so you drop it.");
3084 pline("
\82µ
\82©
\82µ
\81C
\82»
\82ê
\82Í
\82Ê
\82é
\82Ê
\82é
\82µ
\82Ä
\95s
\89õ
\82¾
\82Á
\82½
\82Ì
\82Å
\8eÌ
\82Ä
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D");
3087 You("don't %s anything in here to pick up.",
3088 Blind ? "feel" : "see");
3090 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82ª
\82È
\82¢%s
\81D",
3091 Blind ? "
\82æ
\82¤
\82¾" : "");
3095 return -2; /* loot the monster inventory */
3098 if (is_pool(u.ux, u.uy)) {
3099 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
3100 || (Flying && !Breathless)) {
3102 You("cannot dive into the %s to pick things up.",
3105 You("
\95¨
\82ð
\8fE
\82¢
\82 \82°
\82é
\82½
\82ß
\82É%s
\82É
\94ò
\82Ñ
\82±
\82ß
\82È
\82¢
\81D",
3109 } else if (!Underwater) {
3111 You_cant("even see the bottom, let alone pick up %s.", something);
3113 pline("
\92ê
\82³
\82¦
\8c©
\82¦
\82È
\82¢
\81C
\8fE
\82¤
\82Ì
\82Í
\82â
\82ß
\82æ
\82¤
\81D");
3117 if (is_lava(u.ux, u.uy)) {
3118 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
3119 || (Flying && !Breathless)) {
3121 You_cant("reach the bottom to pick things up.");
3123 You_cant("
\95¨
\82ð
\8fE
\82¢
\8fã
\82°
\82é
\82½
\82ß
\82É
\92ê
\82Ü
\82Å
\82¢
\82¯
\82È
\82¢
\81D");
3125 } else if (!likes_lava(youmonst.data)) {
3127 You("would burn to a crisp trying to pick things up.");
3129 You("
\8fE
\82¢
\8fã
\82°
\82æ
\82¤
\82Æ
\82µ
\82½
\82ç
\8aÛ
\8fÅ
\82°
\82É
\82È
\82Á
\82Ä
\82µ
\82Ü
\82¤
\82¾
\82ë
\82¤
\81D");
3133 if (!OBJ_AT(u.ux, u.uy)) {
3134 register struct rm *lev = &levl[u.ux][u.uy];
3136 if (IS_THRONE(lev->typ))
3138 pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
3140 pline("
\82±
\82ê
\82Í%s
\8fd
\82¢
\81I", lev->looted ? "
\82©
\82È
\82è" : "
\82·
\82²
\82");
3141 else if (IS_SINK(lev->typ))
3143 pline_The("plumbing connects it to the floor.");
3145 pline_The("
\94z
\8aÇ
\82Í
\8f°
\82É
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é
\81D");
3146 else if (IS_GRAVE(lev->typ))
3148 You("don't need a gravestone. Yet.");
3150 pline("
\82 \82È
\82½
\82É
\82Í
\95æ
\90Î
\82Í
\95s
\97v
\82¾
\81D
\81D
\81D
\8d¡
\82Ì
\82Æ
\82±
\82ë
\81D");
3151 else if (IS_FOUNTAIN(lev->typ))
3153 You("could drink the %s...", hliquid("water"));
3155 You("%s
\82ð
\88ù
\82ß
\82È
\82¢
\81D
\81D
\81D", hliquid("
\90\85"));
3156 else if (IS_DOOR(lev->typ) && (lev->doormask & D_ISOPEN))
3158 pline("It won't come off the hinges.");
3160 pline("
\83q
\83\93\83W
\82ð
\8aO
\82¹
\82È
\82¢
\81D");
3161 else if (IS_ALTAR(lev->typ))
3162 pline("Moving the altar would be a very bad idea.");
3163 else if (lev->typ == STAIRS)
3164 pline_The("stairs are solidly fixed to the %s.",
3165 surface(u.ux, u.uy));
3168 There("is nothing here to pick up.");
3170 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82Í
\82È
\82¢
\81D");
3173 if (!can_reach_floor(TRUE)) {
3174 struct trap *traphere = t_at(u.ux, u.uy);
3175 if (traphere && uteetering_at_seen_pit(traphere))
3177 You("cannot reach the bottom of the pit.");
3179 You("
\97\8e\82µ
\8c\8a\82Ì
\92ê
\82É%s
\82ª
\93Í
\82©
\82È
\82©
\82Á
\82½
\81D", body_part(HAND));
3180 else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
3182 else if (Blind && !can_reach_floor(TRUE))
3184 You("cannot reach anything here.");
3186 You("
\89½
\82É
\82à
\93Í
\82©
\82È
\82¢
\81D");
3189 You("cannot reach the %s.", surface(u.ux, u.uy));
3191 You("%s
\82É
\82½
\82Ç
\82è
\82Â
\82
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D", surface(u.ux, u.uy));
3194 return -1; /* can do normal pickup */
3197 /* the ',' command */
3201 int count, tmpcount, ret;
3203 /* awful kludge to work around parse()'s pre-decrement */
3204 count = (multi || (save_cm && *save_cm == cmd_from_func(dopickup)))
3206 multi = 0; /* always reset */
3208 if ((ret = pickup_checks() >= 0))
3210 else if (ret == -2) {
3212 return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
3213 } /* else ret == -1 */
3215 return pickup(-count);
3218 /* stop running if we see something interesting */
3219 /* turn around a corner if that is the only way we can proceed */
3220 /* do not turn left or right twice */
3225 int i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
3226 int corrct = 0, noturn = 0;
3230 /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
3231 /* they polymorphed while in the middle of a long move. */
3232 if (NODIAG(u.umonnum) && u.dx && u.dy) {
3234 You("cannot move diagonally.");
3236 You("
\8eÎ
\82ß
\82É
\88Ú
\93®
\82Å
\82«
\82È
\82¢
\81D");
3241 if (Blind || context.run == 0)
3243 for (x = u.ux - 1; x <= u.ux + 1; x++)
3244 for (y = u.uy - 1; y <= u.uy + 1; y++) {
3245 if (!isok(x, y) || (x == u.ux && y == u.uy))
3247 if (NODIAG(u.umonnum) && x != u.ux && y != u.uy)
3250 if ((mtmp = m_at(x, y)) != 0
3251 && M_AP_TYPE(mtmp) != M_AP_FURNITURE
3252 && M_AP_TYPE(mtmp) != M_AP_OBJECT
3253 && (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
3254 if ((context.run != 1 && !mtmp->mtame)
3255 || (x == u.ux + u.dx && y == u.uy + u.dy
3256 && !context.travel)) {
3257 if (iflags.mention_walls)
3259 pline("%s blocks your path.", upstart(a_monnam(mtmp)));
3261 pline("%s
\82ª
\93¹
\82ð
\82Ó
\82³
\82¢
\82Å
\82¢
\82é
\81D", a_monnam(mtmp));
3266 if (levl[x][y].typ == STONE)
3268 if (x == u.ux - u.dx && y == u.uy - u.dy)
3271 if (IS_ROCK(levl[x][y].typ) || levl[x][y].typ == ROOM
3272 || IS_AIR(levl[x][y].typ)) {
3274 } else if (closed_door(x, y) || (mtmp && is_door_mappear(mtmp))) {
3275 if (x != u.ux && y != u.uy)
3277 if (context.run != 1) {
3278 if (iflags.mention_walls)
3280 You("stop in front of the door.");
3282 You("
\94à
\82Ì
\8eè
\91O
\82Å
\8e~
\82Ü
\82Á
\82½
\81D");
3286 } else if (levl[x][y].typ == CORR) {
3288 if (levl[u.ux][u.uy].typ != ROOM) {
3289 if (context.run == 1 || context.run == 3
3290 || context.run == 8) {
3291 i = dist2(x, y, u.ux + u.dx, u.uy + u.dy);
3294 if (corrct == 1 && dist2(x, y, x0, y0) != 1)
3306 } else if ((trap = t_at(x, y)) && trap->tseen) {
3307 if (context.run == 1)
3308 goto bcorr; /* if you must */
3309 if (x == u.ux + u.dx && y == u.uy + u.dy) {
3310 if (iflags.mention_walls) {
3311 int tt = what_trap(trap->ttyp, rn2_on_display_rng);
3313 You("stop in front of %s.",
3315 You("%s
\82Ì
\8eè
\91O
\82Å
\8e~
\82Ü
\82Á
\82½
\81D",
3316 an(defsyms[trap_to_defsym(tt)].explanation));
3321 } else if (is_pool_or_lava(x, y)) {
3322 /* water and lava only stop you if directly in front, and stop
3323 * you even if you are running
3325 if (!Levitation && !Flying && !is_clinger(youmonst.data)
3326 && x == u.ux + u.dx && y == u.uy + u.dy) {
3327 /* No Wwalking check; otherwise they'd be able
3328 * to test boots by trying to SHIFT-direction
3329 * into a pool and seeing if the game allowed it
3331 if (iflags.mention_walls)
3333 You("stop at the edge of the %s.",
3334 hliquid(is_pool(x,y) ? "water" : "lava"));
3336 You("%s
\82Ì
\92[
\82Å
\8e~
\82Ü
\82Á
\82½
\81D",
3337 hliquid(is_pool(x,y) ? "
\90\85" : "
\97n
\8aâ"));
3342 } else { /* e.g. objects or trap or stairs */
3343 if (context.run == 1)
3345 if (context.run == 8)
3349 if (((x == u.ux - u.dx) && (y != u.uy + u.dy))
3350 || ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
3356 } /* end for loops */
3358 if (corrct > 1 && context.run == 2) {
3359 if (iflags.mention_walls)
3361 pline_The("corridor widens here.");
3363 pline("
\92Ê
\98H
\82Í
\82±
\82±
\82Å
\8dL
\82
\82È
\82Á
\82Ä
\82¢
\82é
\81D");
3366 if ((context.run == 1 || context.run == 3 || context.run == 8) && !noturn
3367 && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) {
3368 /* make sure that we do not turn too far */
3370 if (u.dx == y0 - u.uy && u.dy == u.ux - x0)
3371 i = 2; /* straight turn right */
3373 i = -2; /* straight turn left */
3374 } else if (u.dx && u.dy) {
3375 if ((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
3376 i = -1; /* half turn left */
3378 i = 1; /* half turn right */
3380 if ((x0 - u.ux == y0 - u.uy && !u.dy)
3381 || (x0 - u.ux != y0 - u.uy && u.dy))
3382 i = 1; /* half turn right */
3384 i = -1; /* half turn left */
3387 i += u.last_str_turn;
3388 if (i <= 2 && i >= -2) {
3389 u.last_str_turn = i;
3396 /* check for a doorway which lacks its door (NODOOR or BROKEN) */
3401 struct rm *lev_p = &levl[x][y];
3403 if (!IS_DOOR(lev_p->typ))
3405 /* all rogue level doors are doorless but disallow diagonal access, so
3406 we treat them as if their non-existant doors were actually present */
3407 if (Is_rogue_level(&u.uz))
3409 return !(lev_p->doormask & ~(D_NODOOR | D_BROKEN));
3412 /* used by drown() to check whether hero can crawl from water to <x,y> */
3414 crawl_destination(x, y)
3417 /* is location ok in general? */
3418 if (!goodpos(x, y, &youmonst, 0))
3421 /* orthogonal movement is unrestricted when destination is ok */
3422 if (x == u.ux || y == u.uy)
3425 /* diagonal movement has some restrictions */
3426 if (NODIAG(u.umonnum))
3427 return FALSE; /* poly'd into a grid bug... */
3429 return TRUE; /* or a xorn... */
3430 /* pool could be next to a door, conceivably even inside a shop */
3431 if (IS_DOOR(levl[x][y].typ) && (!doorless_door(x, y) || block_door(x, y)))
3433 /* finally, are we trying to squeeze through a too-narrow gap? */
3434 return !(bad_rock(youmonst.data, u.ux, y)
3435 && bad_rock(youmonst.data, x, u.uy));
3438 /* something like lookaround, but we are not running */
3439 /* react only to monsters that might hit us */
3444 register struct monst *mtmp;
3446 /* Also see the similar check in dochugw() in monmove.c */
3447 for (x = u.ux - 1; x <= u.ux + 1; x++)
3448 for (y = u.uy - 1; y <= u.uy + 1; y++) {
3449 if (!isok(x, y) || (x == u.ux && y == u.uy))
3451 if ((mtmp = m_at(x, y)) && M_AP_TYPE(mtmp) != M_AP_FURNITURE
3452 && M_AP_TYPE(mtmp) != M_AP_OBJECT
3453 && (!mtmp->mpeaceful || Hallucination)
3454 && (!is_hider(mtmp->data) || !mtmp->mundetected)
3455 && !noattacks(mtmp->data) && mtmp->mcanmove
3456 && !mtmp->msleeping /* aplvax!jcn */
3457 && !onscary(u.ux, u.uy, mtmp) && canspotmon(mtmp))
3468 return; /* This is a bug fix by ab@unido */
3469 u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
3473 multi_reason = NULL;
3474 context.travel = context.travel1 = context.mv = context.run = 0;
3477 /* called when a non-movement, multi-turn action has completed */
3480 const char *msg_override;
3482 multi = 0; /* caller will usually have done this already */
3484 nomovemsg = msg_override;
3485 else if (!nomovemsg)
3486 nomovemsg = You_can_move_again;
3488 pline("%s", nomovemsg);
3491 multi_reason = NULL;
3493 int NDECL((*f)) = afternmv;
3495 /* clear afternmv before calling it (to override the
3496 encumbrance hack for levitation--see weight_cap()) */
3497 afternmv = (int NDECL((*))) 0;
3499 /* for finishing Armor/Boots/&c_on() */
3507 static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES,
3508 SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
3509 TELEPORT_CONTROL, STEALTH, FAST, INVIS };
3511 if (moves <= wailmsg + 50)
3515 if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) {
3520 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3523 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3528 pline("%s is about to die.", who);
3530 pline("%s
\82Í
\8e\80\82É
\82©
\82¯
\82Ä
\82¢
\82é
\81D", who);
3532 for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
3533 if (u.uprops[powers[i]].intrinsic & INTRINSIC)
3537 pline((powercnt >= 4) ? "%s, all your powers will be lost..."
3539 pline((powercnt >= 4) ? "%s
\81C
\82 \82È
\82½
\82Ì
\91S
\82Ä
\82Ì
\97Í
\82Í
\8e¸
\82í
\82ê
\82Â
\82Â
\82 \82é
\81D
\81D
\81D"
3541 : "%s, your life force is running out.",
3543 : "%s
\81C
\82 \82È
\82½
\82Ì
\90¶
\96½
\97Í
\82Í
\90s
\82«
\82æ
\82¤
\82Æ
\82µ
\82Ä
\82¢
\82é
\81D
\81D
\81D",
3548 You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
3550 You_hear(u.uhp == 1 ? "
\83o
\83\93\83V
\81[
\82Ì
\82·
\82·
\82è
\8b\83\82«
\82ª
\95·
\82±
\82¦
\82é
\81D
\81D
\81D"
3552 : "the howling of the CwnAnnwn...");
3554 : "
\83N
\81[
\83\93\81E
\83A
\83\93\83k
\81[
\83\93\82Ì
\89\93\96i
\82ª
\95·
\82±
\82¦
\82é
\81D
\81D
\81D");
3559 losehp(n, knam, k_format)
3561 register const char *knam;
3571 else if (n > 0 && u.mh * 10 < u.mhmax && Unchanging)
3577 if (u.uhp > u.uhpmax)
3578 u.uhpmax = u.uhp; /* perhaps n was negative */
3580 context.travel = context.travel1 = context.mv = context.run = 0;
3583 killer.format = k_format;
3584 if (killer.name != knam) /* the thing that killed you */
3585 Strcpy(killer.name, knam ? knam : "");
3589 pline("
\82 \82È
\82½
\82Í
\8e\80\82É
\82Ü
\82µ
\82½
\81D
\81D
\81D");
3591 } else if (n > 0 && u.uhp * 10 < u.uhpmax) {
3599 long carrcap, save_ELev = ELevitation, save_BLev = BLevitation;
3601 /* boots take multiple turns to wear but any properties they
3602 confer are enabled at the start rather than the end; that
3603 causes message sequencing issues for boots of levitation
3604 so defer their encumbrance benefit until they're fully worn */
3605 if (afternmv == Boots_on && (ELevitation & W_ARMF) != 0L) {
3606 ELevitation &= ~W_ARMF;
3607 float_vs_flight(); /* in case Levitation is blocking Flying */
3609 /* levitation is blocked by being trapped in the floor, but it still
3610 functions enough in that situation to enhance carrying capacity */
3611 BLevitation &= ~I_SPECIAL;
3613 carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
3615 /* consistent with can_carry() in mon.c */
3616 if (youmonst.data->mlet == S_NYMPH)
3617 carrcap = MAX_CARR_CAP;
3618 else if (!youmonst.data->cwt)
3619 carrcap = (carrcap * (long) youmonst.data->msize) / MZ_HUMAN;
3620 else if (!strongmonst(youmonst.data)
3621 || (strongmonst(youmonst.data)
3622 && (youmonst.data->cwt > WT_HUMAN)))
3623 carrcap = (carrcap * (long) youmonst.data->cwt / WT_HUMAN);
3626 if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
3627 || (u.usteed && strongmonst(u.usteed->data))) {
3628 carrcap = MAX_CARR_CAP;
3630 if (carrcap > MAX_CARR_CAP)
3631 carrcap = MAX_CARR_CAP;
3633 if (EWounded_legs & LEFT_SIDE)
3635 if (EWounded_legs & RIGHT_SIDE)
3642 if (ELevitation != save_ELev || BLevitation != save_BLev) {
3643 ELevitation = save_ELev;
3644 BLevitation = save_BLev;
3648 return (int) carrcap;
3651 static int wc; /* current weight_cap(); valid after call to inv_weight() */
3653 /* returns how far beyond the normal capacity the player is currently. */
3654 /* inv_weight() is negative if the player is below normal capacity. */
3658 register struct obj *otmp = invent;
3659 register int wt = 0;
3662 if (otmp->oclass == COIN_CLASS)
3663 wt += (int) (((long) otmp->quan + 50L) / 100L);
3664 else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
3673 * Returns 0 if below normal capacity, or the number of "capacity units"
3674 * over the normal capacity the player is loaded. Max is 5.
3677 calc_capacity(xtra_wt)
3680 int cap, wt = inv_weight() + xtra_wt;
3683 return UNENCUMBERED;
3686 cap = (wt * 2 / wc) + 1;
3687 return min(cap, OVERLOADED);
3693 return calc_capacity(0);
3699 int wt = inv_weight();
3701 return (wt - (2 * wc));
3708 if (near_capacity() >= EXT_ENCUMBER) {
3713 You_cant("do that while carrying so much stuff.");
3715 You("
\91ò
\8eR
\82à
\82Ì
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\82¢
\82é
\82Ì
\82Å
\81C
\82»
\82ñ
\82È
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D");
3725 register struct obj *otmp = invent;
3726 register int ct = 0;
3729 if (incl_gold || otmp->invlet != GOLD_SYM)
3736 /* Counts the money in an object chain. */
3737 /* Intended use is for your or some monster's inventory, */
3738 /* now that u.gold/m.gold is gone.*/
3739 /* Counting money in a container might be possible too. */
3745 /* Must change when silver & copper is implemented: */
3746 if (otmp->oclass == COIN_CLASS)