1 /* NetHack 3.6 hack.c $NHDT-Date: 1518861490 2018/02/17 09:58:10 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.182 $ */
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-2016 */
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 void NDECL(switch_terrain);
22 STATIC_DCL struct monst *FDECL(monstinroom, (struct permonst *, int));
23 STATIC_DCL boolean FDECL(doorless_door, (int, int));
24 STATIC_DCL void FDECL(move_update, (BOOLEAN_P));
26 #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
28 /* mode values for findtravelpath() */
29 #define TRAVP_TRAVEL 0
33 static anything tmp_anything;
39 tmp_anything = zeroany;
40 tmp_anything.a_uint = ui;
48 tmp_anything = zeroany;
49 tmp_anything.a_long = lng;
57 tmp_anything = zeroany;
58 tmp_anything.a_monst = mtmp;
66 tmp_anything = zeroany;
67 tmp_anything.a_obj = obj;
72 revive_nasty(x, y, msg)
76 register struct obj *otmp, *otmp2;
79 boolean revived = FALSE;
81 for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
82 otmp2 = otmp->nexthere;
83 if (otmp->otyp == CORPSE
84 && (is_rider(&mons[otmp->corpsenm])
85 || otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
86 /* move any living monster already at that location */
87 if ((mtmp = m_at(x, y)) && enexto(&cc, x, y, mtmp->data))
88 rloc_to(mtmp, cc.x, cc.y);
91 revived = revive_corpse(otmp);
95 /* this location might not be safe, if not, move revived monster */
98 if (mtmp && !goodpos(x, y, mtmp, 0)
99 && enexto(&cc, x, y, mtmp->data)) {
100 rloc_to(mtmp, cc.x, cc.y);
102 /* else impossible? */
111 register xchar rx, ry, sx, sy;
112 register struct obj *otmp;
113 register struct trap *ttmp;
114 register struct monst *mtmp;
116 sx = u.ux + u.dx, sy = u.uy + u.dy; /* boulder starting position */
117 while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
118 /* make sure that this boulder is visible as the top object */
119 if (otmp != level.objects[sx][sy])
120 movobj(otmp, sx, sy);
122 rx = u.ux + 2 * u.dx; /* boulder destination position */
123 ry = u.uy + 2 * u.dy;
125 if (Levitation || Is_airlevel(&u.uz)) {
127 feel_location(sx, sy);
129 You("don't have enough leverage to push %s.", the(xname(otmp)));
131 You("
\91Ì
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82Å%s
\82ð
\89\9f\82¹
\82È
\82¢
\81D", the(xname(otmp)));
132 /* Give them a chance to climb over it? */
135 if (verysmall(youmonst.data) && !u.usteed) {
137 feel_location(sx, sy);
139 pline("You're too small to push that %s.", xname(otmp));
141 You("
\8f¬
\82³
\82·
\82¬
\82Ä%s
\82ð
\89\9f\82¹
\82È
\82¢
\81D",xname(otmp));
144 if (isok(rx, ry) && !IS_ROCK(levl[rx][ry].typ)
145 && levl[rx][ry].typ != IRONBARS
146 && (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy)
147 || doorless_door(rx, ry)) && !sobj_at(BOULDER, rx, ry)) {
151 /* KMH -- Sokoban doesn't let you push boulders diagonally */
152 if (Sokoban && u.dx && u.dy) {
154 feel_location(sx, sy);
156 pline("%s won't roll diagonally on this %s.",
158 pline("%s
\82Ì
\8fã
\82Å
\82Í%s
\82Í
\8eÎ
\82ß
\82É
\89\9f\82¹
\82È
\82¢
\81D",
159 The(xname(otmp)), surface(sx, sy));
164 if (revive_nasty(rx, ry, "You sense movement on the other side."))
166 if (revive_nasty(rx, ry, "
\94½
\91Î
\91¤
\82É
\93®
\82«
\82ð
\8a´
\82¶
\82½
\81D"))
169 if (mtmp && !noncorporeal(mtmp->data)
171 || !(ttmp && ((ttmp->ttyp == PIT)
172 || (ttmp->ttyp == SPIKED_PIT))))) {
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. Returns TRUE if still eating, FALSE
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));
469 if (!boulder && IS_ROCK(lev->typ) && !may_dig(x, y)) {
471 You("hurt your teeth on the %s.",
472 (lev->typ == IRONBARS)
478 You("%s
\82Å
\8e\95\82ð
\92É
\82ß
\82½
\81D",
479 (lev->typ == IRONBARS)
487 } else if (context.digging.pos.x != x || context.digging.pos.y != y
488 || !on_level(&context.digging.level, &u.uz)) {
489 context.digging.down = FALSE;
490 context.digging.chew = TRUE;
491 context.digging.warned = FALSE;
492 context.digging.pos.x = x;
493 context.digging.pos.y = y;
494 assign_level(&context.digging.level, &u.uz);
495 /* solid rock takes more work & time to dig through */
496 context.digging.effort =
497 (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc;
499 You("start chewing %s %s.",
500 (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
509 : (lev->typ == IRONBARS)
513 You("%s%s
\82Í
\82¶
\82ß
\82½
\81D",
520 : lev->typ == IRONBARS
523 (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
525 : "
\82É
\8c\8a\82ð
\82 \82¯");
527 watch_dig((struct monst *) 0, x, y, FALSE);
529 } else if ((context.digging.effort += (30 + u.udaminc)) <= 100) {
532 You("%s chewing on the %s.",
533 context.digging.chew ? "continue" : "begin",
540 : (lev->typ == IRONBARS)
544 You("%s
\82ð
\8a\9a\82Ý%s
\81D",
551 : lev->typ == IRONBARS
554 context.digging.chew ? "
\91±
\82¯
\82½" : "
\82Í
\82¶
\82ß
\82½");
556 context.digging.chew = TRUE;
557 watch_dig((struct monst *) 0, x, y, FALSE);
561 /* Okay, you've chewed through something */
563 u.uhunger += rnd(20);
566 delobj(boulder); /* boulder goes bye-bye */
568 You("eat the boulder."); /* yum */
570 You("
\8aâ
\82ð
\90H
\82×
\82½
\81D"); /* yum */
574 * The location could still block because of
575 * 1. More than one boulder
576 * 2. Boulder stuck in a wall/stone/door.
578 * [perhaps use does_block() below (from vision.c)]
580 if (IS_ROCK(lev->typ) || closed_door(x, y)
581 || sobj_at(BOULDER, x, y)) {
582 block_point(x, y); /* delobj will unblock the point */
583 /* reset dig state */
584 (void) memset((genericptr_t) &context.digging, 0,
585 sizeof (struct dig_info));
589 } else if (IS_WALL(lev->typ)) {
590 if (*in_rooms(x, y, SHOPBASE)) {
591 add_damage(x, y, SHOP_WALL_DMG);
595 dmgtxt = "
\8f\9d\82Â
\82¯
\82é";
598 digtxt = "chew a hole in the wall.";
600 digtxt = "
\95Ç
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
601 if (level.flags.is_maze_lev) {
603 } else if (level.flags.is_cavernous_lev && !in_town(x, y)) {
607 lev->doormask = D_NODOOR;
609 } else if (IS_TREE(lev->typ)) {
611 digtxt = "chew through the tree.";
613 digtxt = "
\96Ø
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
615 } else if (lev->typ == IRONBARS) {
617 digtxt = "eat through the bars.";
619 digtxt = "
\93S
\82Ì
\96_
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
621 } else if (lev->typ == SDOOR) {
622 if (lev->doormask & D_TRAPPED) {
623 lev->doormask = D_NODOOR;
625 b_trapped("secret door", 0);
627 b_trapped("
\94é
\96§
\82Ì
\94à", 0);
630 digtxt = "chew through the secret door.";
632 digtxt = "
\94é
\96§
\82Ì
\94à
\82ð
\8a\9a\82Ý
\8dÓ
\82¢
\82½
\81D";
633 lev->doormask = D_BROKEN;
637 } else if (IS_DOOR(lev->typ)) {
638 if (*in_rooms(x, y, SHOPBASE)) {
639 add_damage(x, y, SHOP_DOOR_COST);
645 if (lev->doormask & D_TRAPPED) {
646 lev->doormask = D_NODOOR;
648 b_trapped("door", 0);
650 b_trapped("
\94à", 0);
653 digtxt = "chew through the door.";
655 digtxt = "
\94à
\82ð
\8dÓ
\82¢
\82½
\81D";
656 lev->doormask = D_BROKEN;
659 } else { /* STONE or SCORR */
661 digtxt = "chew a passage through the rock.";
663 digtxt = "
\8aâ
\82ð
\8a\9a\82Ý
\8dÓ
\82¢
\82Ä
\92Ê
\82è
\94²
\82¯
\82½
\81D";
667 unblock_point(x, y); /* vision */
670 You1(digtxt); /* after newsym */
672 pay_for_damage(dmgtxt, FALSE);
673 (void) memset((genericptr_t) &context.digging, 0,
674 sizeof (struct dig_info));
680 register struct obj *obj;
681 register xchar ox, oy;
683 /* optimize by leaving on the fobj chain? */
685 newsym(obj->ox, obj->oy);
686 place_object(obj, ox, oy);
691 static NEARDATA const char fell_on_sink[] = "fell onto a sink";
693 static NEARDATA const char fell_on_sink[] = "
\97¬
\82µ
\91ä
\82É
\97\8e\82¿
\82Ä";
698 register struct obj *obj;
700 boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
701 innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L),
702 ufall = (!innate_lev && !(HFlying || EFlying)); /* BFlying */
706 You(innate_lev ? "wobble unsteadily for a moment."
708 You(innate_lev ? "
\82¿
\82å
\82Á
\82Æ
\82Ó
\82ç
\82Â
\82¢
\82½
\81D"
710 : "gain control of your flight.");
712 : "
\94ò
\8ds
\92\86\82Ì
\90§
\8cä
\82ð
\8eæ
\82è
\82à
\82Ç
\82µ
\82½
\81D");
714 long save_ELev = ELevitation, save_HLev = HLevitation;
716 /* fake removal of levitation in advance so that final
717 disclosure will be right in case this turns out to
718 be fatal; fortunately the fact that rings and boots
719 are really still worn has no effect on bones data */
720 ELevitation = HLevitation = 0L;
722 You("crash to the floor!");
724 You("
\8f°
\82É
\92@
\82«
\82Â
\82¯
\82ç
\82ê
\82½
\81I");
725 dmg = rn1(8, 25 - (int) ACURR(A_CON));
727 losehp(Maybe_Half_Phys(dmg), fell_on_sink, NO_KILLER_PREFIX);
729 losehp(Maybe_Half_Phys(dmg), fell_on_sink, KILLED_BY);
731 exercise(A_DEX, FALSE);
733 selftouch("Falling, you");
735 selftouch("
\97\8e\82¿
\82È
\82ª
\82ç
\81C
\82 \82È
\82½
\82Í");
736 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
737 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) {
739 You("fell on %s.", doname(obj));
741 You("%s
\82Ì
\8fã
\82É
\97\8e\82¿
\82½
\81D",doname(obj));
743 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
746 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
749 exercise(A_CON, FALSE);
751 ELevitation = save_ELev;
752 HLevitation = save_HLev;
756 * Interrupt multi-turn putting on/taking off of armor (in which
757 * case we reached the sink due to being teleported while busy;
758 * in 3.4.3, Boots_on()/Boots_off() [called via (*afternmv)() when
759 * 'multi' reaches 0] triggered a crash if we were donning/doffing
760 * levitation boots [because the Boots_off() below causes 'uarmf'
761 * to be null by the time 'afternmv' gets called]).
763 * Interrupt donning/doffing if we fall onto the sink, or if the
764 * code below is going to remove levitation boots even when we
765 * haven't fallen (innate floating or flying becoming unblocked).
767 if (ufall || lev_boots) {
768 (void) stop_donning(lev_boots ? uarmf : (struct obj *) 0);
769 /* recalculate in case uarmf just got set to null */
770 lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS);
773 /* remove worn levitation items */
774 ELevitation &= ~W_ARTI;
775 HLevitation &= ~(I_SPECIAL | TIMEOUT);
777 if (uleft && uleft->otyp == RIN_LEVITATION) {
782 if (uright && uright->otyp == RIN_LEVITATION) {
793 /* probably moot; we're either still levitating or went
794 through float_down(), but make sure BFlying is up to date */
798 /* intended to be called only on ROCKs or TREEs */
803 struct rm *lev = &levl[x][y];
805 return (boolean) !((IS_STWALL(lev->typ) || IS_TREE(lev->typ))
806 && (lev->wall_info & W_NONDIGGABLE));
813 return (boolean) !(IS_STWALL(levl[x][y].typ)
814 && (levl[x][y].wall_info & W_NONPASSWALL));
819 struct permonst *mdat;
822 return (boolean) ((Sokoban && sobj_at(BOULDER, x, y))
823 || (IS_ROCK(levl[x][y].typ)
824 && (!tunnels(mdat) || needspick(mdat)
826 && !(passes_walls(mdat) && may_passwall(x, y))));
829 /* caller has already decided that it's a tight diagonal; check whether a
830 monster--who might be the hero--can fit through, and if not then return
831 the reason why: 1: can't fit, 2: possessions won't fit, 3: sokoban
832 returns 0 if we can squeeze through */
834 cant_squeeze_thru(mon)
838 struct permonst *ptr = mon->data;
842 && !(amorphous(ptr) || is_whirly(ptr) || noncorporeal(ptr)
843 || slithy(ptr) || can_fog(mon)))
846 /* lugging too much junk? */
847 amt = (mon == &youmonst) ? inv_weight() + weight_cap()
848 : curr_mon_load(mon);
852 /* Sokoban restriction applies to hero only */
853 if (mon == &youmonst && Sokoban)
856 /* can squeeze through */
864 return (boolean) (Invocation_lev(&u.uz)
865 && x == inv_pos.x && y == inv_pos.y);
868 /* return TRUE if (dx,dy) is an OK place to move
869 * mode is one of DO_MOVE, TEST_MOVE, TEST_TRAV, or TEST_TRAP
872 test_move(ux, uy, dx, dy, mode)
878 register struct rm *tmpr = &levl[x][y];
879 register struct rm *ust;
881 context.door_opened = FALSE;
883 * Check for physical obstacles. First, the place we are going.
885 if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) {
886 if (Blind && mode == DO_MOVE)
888 if (Passes_walls && may_passwall(x, y)) {
890 } else if (Underwater) {
891 /* note: if water_friction() changes direction due to
892 turbulence, new target destination will always be water,
893 so we won't get here, hence don't need to worry about
894 "there" being somewhere the player isn't sure of */
897 pline("There is an obstacle there.");
899 pline("
\8fá
\8aQ
\95¨
\82ª
\82 \82é
\81D");
901 } else if (tmpr->typ == IRONBARS) {
902 if ((dmgtype(youmonst.data, AD_RUST)
903 || dmgtype(youmonst.data, AD_CORR)) && mode == DO_MOVE
904 && still_chewing(x, y)) {
907 if (!(Passes_walls || passes_bars(youmonst.data))) {
908 if (mode == DO_MOVE && iflags.mention_walls)
910 You("cannot pass through the bars.");
912 You("
\93S
\82Ì
\96_
\82ð
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
915 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
917 if (mode == DO_MOVE && still_chewing(x, y))
919 } else if (flags.autodig && !context.run && !context.nopick && uwep
921 /* MRKR: Automatic digging when wielding the appropriate tool */
923 (void) use_pick_axe2(uwep);
926 if (mode == DO_MOVE) {
927 if (is_db_wall(x, y))
929 pline("That drawbridge is up!");
931 pline("
\92µ
\82Ë
\8b´
\82Í
\8fã
\82Á
\82Ä
\82¢
\82é
\81I");
932 /* sokoban restriction stays even after puzzle is solved */
933 else if (Passes_walls && !may_passwall(x, y)
934 && In_sokoban(&u.uz))
936 pline_The("Sokoban walls resist your ability.");
938 pline_The("
\91q
\8cÉ
\94Ô
\82Ì
\95Ç
\82Í
\82 \82È
\82½
\82Ì
\94\
\97Í
\82É
\92ï
\8dR
\82µ
\82½
\81D");
939 else if (iflags.mention_walls)
942 (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "a wall"
943 : IS_TREE(tmpr->typ) ? "a tree"
946 pline("
\82±
\82ê
\82Í%s
\82¾
\81D",
947 (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "
\95Ç"
948 : IS_TREE(tmpr->typ) ? "
\96Ø"
954 } else if (IS_DOOR(tmpr->typ)) {
955 if (closed_door(x, y)) {
956 if (Blind && mode == DO_MOVE)
960 } else if (can_ooze(&youmonst)) {
963 You("ooze under the door.");
965 You("
\83h
\83A
\82Ì
\89º
\82©
\82ç
\82É
\82¶
\82Ý
\8fo
\82½
\81D");
966 } else if (Underwater) {
969 pline("There is an obstacle there.");
971 pline("
\8fá
\8aQ
\95¨
\82ª
\82 \82é
\81D");
973 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
975 if (mode == DO_MOVE && still_chewing(x, y))
978 if (mode == DO_MOVE) {
979 if (amorphous(youmonst.data))
982 "try to ooze under the door, but can't squeeze your possessions through.");
984 "
\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");
985 if (flags.autoopen && !context.run && !Confusion
986 && !Stunned && !Fumbling) {
987 context.door_opened = context.move =
989 } else if (x == ux || y == uy) {
990 if (Blind || Stunned || ACURR(A_DEX) < 10
994 You_cant("lead %s through that closed door.",
996 You_cant("%s
\82É
\95Â
\82Ü
\82Á
\82½
\94à
\82ð
\92Ê
\89ß
\82³
\82¹
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
1000 pline("Ouch! You bump into a door.");
1002 pline("
\82¢
\82Ä
\82Á
\81I
\93ª
\82ð
\94à
\82É
\82Ô
\82Â
\82¯
\82½
\81D");
1003 exercise(A_DEX, FALSE);
1007 pline("That door is closed.");
1009 pline("
\94à
\82Í
\95Â
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D");
1011 } else if (mode == TEST_TRAV || mode == TEST_TRAP)
1017 if (dx && dy && !Passes_walls
1018 && (!doorless_door(x, y) || block_door(x, y))) {
1019 /* Diagonal moves into a door are not allowed. */
1020 if (mode == DO_MOVE) {
1022 feel_location(x, y);
1023 if (Underwater || iflags.mention_walls)
1025 You_cant("move diagonally into an intact doorway.");
1027 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");
1033 if (dx && dy && bad_rock(youmonst.data, ux, y)
1034 && bad_rock(youmonst.data, x, uy)) {
1035 /* Move at a diagonal. */
1036 switch (cant_squeeze_thru(&youmonst)) {
1038 if (mode == DO_MOVE)
1040 You("cannot pass that way.");
1042 You("
\92Ê
\82è
\82Ê
\82¯
\82Å
\82«
\82È
\82¢
\81D");
1045 if (mode == DO_MOVE)
1047 You("are carrying too much to get through.");
1049 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1052 if (mode == DO_MOVE)
1054 Your("body is too large to fit through.");
1056 Your("
\91Ì
\82ª
\91å
\82«
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1059 break; /* can squeeze through */
1061 } else if (dx && dy && worm_cross(ux, uy, x, y)) {
1062 /* consecutive long worm segments are at <ux,y> and <x,uy> */
1063 if (mode == DO_MOVE)
1065 pline("%s is in your way.", Monnam(m_at(ux, y)));
1067 pline("
\93¹
\82Ì
\93r
\92\86\82É%s
\82ª
\82¢
\82é
\81D", Monnam(m_at(ux, y)));
1070 /* Pick travel path that does not require crossing a trap.
1071 * Avoid water and lava using the usual running rules.
1072 * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
1073 if (context.run == 8 && (mode != DO_MOVE)
1074 && (x != u.ux || y != u.uy)) {
1075 struct trap *t = t_at(x, y);
1078 || (!Levitation && !Flying && !is_clinger(youmonst.data)
1079 && is_pool_or_lava(x, y) && levl[x][y].seenv))
1080 return (mode == TEST_TRAP);
1083 if (mode == TEST_TRAP)
1084 return FALSE; /* do not move through traps */
1086 ust = &levl[ux][uy];
1088 /* Now see if other things block our way . . */
1089 if (dx && dy && !Passes_walls && IS_DOOR(ust->typ)
1090 && (!doorless_door(ux, uy) || block_entry(x, y))) {
1091 /* Can't move at a diagonal out of a doorway with door. */
1092 if (mode == DO_MOVE && iflags.mention_walls)
1094 You_cant("move diagonally out of an intact doorway.");
1096 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");
1100 if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
1101 if (!(Blind || Hallucination) && (context.run >= 2)
1102 && mode != TEST_TRAV) {
1103 if (mode == DO_MOVE && iflags.mention_walls)
1105 pline("A boulder blocks your path.");
1107 pline("
\8b\90\8aâ
\82ª
\93¹
\82ð
\82Ó
\82³
\82¢
\82Å
\82¢
\82é
\81D");
1110 if (mode == DO_MOVE) {
1111 /* tunneling monsters will chew before pushing */
1112 if (tunnels(youmonst.data) && !needspick(youmonst.data)
1114 if (still_chewing(x, y))
1116 } else if (moverock() < 0)
1118 } else if (mode == TEST_TRAV) {
1121 /* never travel through boulders in Sokoban */
1125 /* don't pick two boulders in a row, unless there's a way thru */
1126 if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
1128 && !(tunnels(youmonst.data) && !needspick(youmonst.data))
1129 && !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK)
1130 && !((obj = carrying(WAN_DIGGING))
1131 && !objects[obj->otyp].oc_name_known))
1135 /* assume you'll be able to push it when you get there... */
1138 /* OK, it is a legal place to move. */
1143 static boolean trav_debug = FALSE;
1145 /* in this case, toggle display of travel debug info */
1146 int wiz_debug_cmd_traveldisplay()
1148 trav_debug = !trav_debug;
1154 * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
1155 * A shortest path is returned. If guess is TRUE, consider various
1156 * inaccessible locations as valid intermediate path points.
1157 * Returns TRUE if a path was found.
1160 findtravelpath(mode)
1163 /* if travel to adjacent, reachable location, use normal movement rules */
1164 if ((mode == TRAVP_TRAVEL || mode == TRAVP_VALID) && context.travel1
1165 && distmin(u.ux, u.uy, u.tx, u.ty) == 1
1166 && !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
1168 if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
1169 if (mode == TRAVP_TRAVEL) {
1173 iflags.travelcc.x = iflags.travelcc.y = -1;
1177 if (mode == TRAVP_TRAVEL)
1180 if (u.tx != u.ux || u.ty != u.uy) {
1181 xchar travel[COLNO][ROWNO];
1182 xchar travelstepx[2][COLNO * ROWNO];
1183 xchar travelstepy[2][COLNO * ROWNO];
1184 xchar tx, ty, ux, uy;
1185 int n = 1; /* max offset in travelsteps */
1186 int set = 0; /* two sets current and previous */
1187 int radius = 1; /* search radius */
1190 /* If guessing, first find an "obvious" goal location. The obvious
1191 * goal is the position the player knows of, or might figure out
1192 * (couldsee) that is closest to the target on a straight path.
1194 if (mode == TRAVP_GUESS || mode == TRAVP_VALID) {
1207 (void) memset((genericptr_t) travel, 0, sizeof(travel));
1208 travelstepx[0][0] = tx;
1209 travelstepy[0][0] = ty;
1214 for (i = 0; i < n; i++) {
1216 int x = travelstepx[set][i];
1217 int y = travelstepy[set][i];
1218 static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
1219 /* no diagonal movement for grid bugs */
1220 int dirmax = NODIAG(u.umonnum) ? 4 : 8;
1221 boolean alreadyrepeated = FALSE;
1223 for (dir = 0; dir < dirmax; ++dir) {
1224 int nx = x + xdir[ordered[dir]];
1225 int ny = y + ydir[ordered[dir]];
1228 * When guessing and trying to travel as close as possible
1229 * to an unreachable target space, don't include spaces
1230 * that would never be picked as a guessed target in the
1231 * travel matrix describing hero-reachable spaces.
1232 * This stops travel from getting confused and moving
1233 * the hero back and forth in certain degenerate
1234 * configurations of sight-blocking obstacles, e.g.
1236 * T 1. Dig this out and carry enough to not be
1237 * #### able to squeeze through diagonal gaps.
1238 * #--.--- Stand at @ and target travel at space T.
1242 * T 2. couldsee() marks spaces marked a and x
1243 * #### as eligible guess spaces to move the hero
1244 * a--.--- towards. Space a is closest to T, so it
1245 * @xxxxx gets chosen. Travel system moves @ right
1246 * |xxxxx to travel to space a.
1248 * T 3. couldsee() marks spaces marked b, c and x
1249 * #### as eligible guess spaces to move the hero
1250 * a--c--- towards. Since findtravelpath() is called
1251 * b@xxxx repeatedly during travel, it doesn't
1252 * |xxxxx remember that it wanted to go to space a,
1253 * so in comparing spaces b and c, b is
1254 * chosen, since it seems like the closest
1255 * eligible space to T. Travel system moves @
1256 * left to go to space b.
1260 * By limiting the travel matrix here, space a in the
1261 * example above is never included in it, preventing
1265 || ((mode == TRAVP_GUESS) && !couldsee(nx, ny)))
1267 if ((!Passes_walls && !can_ooze(&youmonst)
1268 && closed_door(x, y)) || sobj_at(BOULDER, x, y)
1269 || test_move(x, y, nx-x, ny-y, TEST_TRAP)) {
1270 /* closed doors and boulders usually
1271 * cause a delay, so prefer another path */
1272 if (travel[x][y] > radius - 3) {
1273 if (!alreadyrepeated) {
1274 travelstepx[1 - set][nn] = x;
1275 travelstepy[1 - set][nn] = y;
1276 /* don't change travel matrix! */
1278 alreadyrepeated = TRUE;
1283 if (test_move(x, y, nx - x, ny - y, TEST_TRAV)
1284 && (levl[nx][ny].seenv
1285 || (!Blind && couldsee(nx, ny)))) {
1286 if (nx == ux && ny == uy) {
1287 if (mode == TRAVP_TRAVEL || mode == TRAVP_VALID) {
1290 if (mode == TRAVP_TRAVEL
1291 && x == u.tx && y == u.ty) {
1293 /* reset run so domove run checks work */
1295 iflags.travelcc.x = iflags.travelcc.y = -1;
1299 } else if (!travel[nx][ny]) {
1300 travelstepx[1 - set][nn] = nx;
1301 travelstepy[1 - set][nn] = ny;
1302 travel[nx][ny] = radius;
1311 /* Use of warning glyph is arbitrary. It stands out. */
1312 tmp_at(DISP_ALL, warning_to_glyph(1));
1313 for (i = 0; i < nn; ++i) {
1314 tmp_at(travelstepx[1 - set][i], travelstepy[1 - set][i]);
1317 if (flags.runmode == RUN_CRAWL) {
1321 tmp_at(DISP_END, 0);
1330 /* if guessing, find best location in travel matrix and go there */
1331 if (mode == TRAVP_GUESS) {
1332 int px = tx, py = ty; /* pick location */
1333 int dist, nxtdist, d2, nd2;
1335 dist = distmin(ux, uy, tx, ty);
1336 d2 = dist2(ux, uy, tx, ty);
1337 for (tx = 1; tx < COLNO; ++tx)
1338 for (ty = 0; ty < ROWNO; ++ty)
1339 if (travel[tx][ty]) {
1340 nxtdist = distmin(ux, uy, tx, ty);
1341 if (nxtdist == dist && couldsee(tx, ty)) {
1342 nd2 = dist2(ux, uy, tx, ty);
1344 /* prefer non-zigzag path */
1349 } else if (nxtdist < dist && couldsee(tx, ty)) {
1353 d2 = dist2(ux, uy, tx, ty);
1357 if (px == u.ux && py == u.uy) {
1358 /* no guesses, just go in the general direction */
1359 u.dx = sgn(u.tx - u.ux);
1360 u.dy = sgn(u.ty - u.uy);
1361 if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
1367 /* Use of warning glyph is arbitrary. It stands out. */
1368 tmp_at(DISP_ALL, warning_to_glyph(2));
1371 if (flags.runmode == RUN_CRAWL) {
1377 tmp_at(DISP_END, 0);
1386 mode = TRAVP_TRAVEL;
1400 is_valid_travelpt(x,y)
1406 int g = glyph_at(x,y);
1407 if (x == u.ux && y == u.uy)
1409 if (isok(x,y) && glyph_is_cmap(g) && S_stone == glyph_to_cmap(g)
1410 && !levl[x][y].seenv)
1414 ret = findtravelpath(TRAVP_VALID);
1420 /* try to escape being stuck in a trapped state by walking out of it;
1421 return true iff moving should continue to intended destination
1422 (all failures and most successful escapes leave hero at original spot) */
1424 trapmove(x, y, desttrap)
1425 int x, y; /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
1426 struct trap *desttrap; /* nonnull if another trap at <x,y> */
1428 boolean anchored = FALSE;
1429 const char *predicament, *culprit;
1430 char *steedname = !u.usteed ? (char *) 0 : y_monnam(u.usteed);
1433 return TRUE; /* sanity check */
1435 switch (u.utraptype) {
1437 if (flags.verbose) {
1439 predicament = "caught in a bear trap";
1441 predicament = "
\8cF
\82Ìã©
\82É
\82Â
\82©
\82Ü
\82Á
\82½";
1444 Norep("%s is %s.", upstart(steedname), predicament);
1446 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1449 Norep("You are %s.", predicament);
1451 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1453 /* [why does diagonal movement give quickest escape?] */
1454 if ((u.dx && u.dy) || !rn2(5))
1460 if (desttrap && desttrap->tseen
1461 && (desttrap->ttyp == PIT || desttrap->ttyp == SPIKED_PIT))
1462 return TRUE; /* move into adjacent pit */
1463 /* try to escape; position stays same regardless of success */
1467 if (uwep && uwep->oartifact == ART_STING) {
1470 pline("Sting cuts through the web!");
1472 pline("
\83X
\83e
\83B
\83\93\83O
\82Í
\82
\82à
\82Ì
\91\83\82ð
\90Ø
\82è
\82³
\82¢
\82½
\81I");
1473 break; /* escape trap but don't move */
1476 if (flags.verbose) {
1478 predicament = "stuck to the web";
1480 predicament = "
\82
\82à
\82Ì
\91\83\82É
\82Ð
\82Á
\82©
\82©
\82Á
\82½";
1483 Norep("%s is %s.", upstart(steedname), predicament);
1485 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1488 Norep("You are %s.", predicament);
1490 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1495 pline("%s breaks out of the web.", upstart(steedname));
1497 pline("%s
\82Í
\82
\82à
\82Ì
\91\83\82ð
\89ó
\82µ
\82½
\81D", upstart(steedname));
1500 You("disentangle yourself.");
1502 You("
\8e©
\95ª
\82Å
\82Ù
\82Ç
\82¢
\82½
\81D");
1506 if (flags.verbose) {
1508 predicament = "stuck in the lava";
1510 predicament = "
\97n
\8aâ
\82É
\82Í
\82Ü
\82Á
\82½";
1513 Norep("%s is %s.", upstart(steedname), predicament);
1515 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1518 Norep("You are %s.", predicament);
1520 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1522 if (!is_lava(x, y)) {
1524 if ((u.utrap & 0xff) == 0) {
1528 You("lead %s to the edge of the %s.", steedname,
1531 You("%s
\82ð%s
\82Ì
\92[
\82Ü
\82Å
\93±
\82¢
\82½
\81D", steedname,
1532 hliquid("
\97n
\8aâ"));
1536 You("pull yourself to the edge of the %s.",
1539 You("%s
\82Ì
\92[
\82Ü
\82Å
\82©
\82ë
\82¤
\82¶
\82Ä
\81C
\82½
\82Ç
\82è
\82Â
\82¢
\82½
\81D",
1540 hliquid("
\97n
\8aâ"));
1548 anchored = (u.utraptype == TT_BURIEDBALL);
1552 cc.x = u.ux, cc.y = u.uy;
1553 /* can move normally within radius 1 of buried ball */
1554 if (buried_ball(&cc) && dist2(x, y, cc.x, cc.y) <= 2) {
1555 /* ugly hack: we need to issue some message here
1556 in case "you are chained to the buried ball"
1557 was the most recent message given, otherwise
1558 our next attempt to move out of tether range
1559 after this successful move would have its
1560 can't-do-that message suppressed by Norep */
1563 Norep("You move within the chain's reach.");
1565 Norep("
\8d½
\82ª
\93Í
\82
\94Í
\88Í
\82É
\88Ú
\93®
\82Å
\82«
\82é
\81D");
1570 if (flags.verbose) {
1573 predicament = "chained to the";
1574 culprit = "buried ball";
1576 predicament = "
\82Æ
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é";
1577 culprit = "
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é
\8b\85";
1581 predicament = "stuck in the";
1582 culprit = surface(u.ux, u.uy);
1584 predicament = "
\82É
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é";
1585 culprit = surface(u.ux, u.uy);
1591 Norep("You and %s are %s %s.", steedname, predicament,
1594 Norep("
\82 \82È
\82½
\82Æ%s
\82Í%s%s
\81D", steedname, culprit,
1599 Norep("%s is %s %s.", upstart(steedname), predicament,
1602 Norep("%s
\82Í%s%s
\81D", steedname, culprit,
1607 Norep("You are %s %s.", predicament, culprit);
1609 Norep("
\82 \82È
\82½
\82Í%s
\82É%s
\81D", culprit, predicament);
1615 pline("%s finally %s free.", upstart(steedname),
1616 !anchored ? "lurches" : "wrenches the ball");
1618 pline("%s
\82Í%s
\82â
\82Á
\82Æ
\8e©
\97R
\82É
\82È
\82Á
\82½
\81D", upstart(steedname),
1619 !anchored ? "
\82à
\82ª
\82¢
\82Ä" : "
\93S
\8b\85\82ð
\82à
\82¬
\8eæ
\82Á
\82Ä");
1623 You("finally %s free.",
1624 !anchored ? "wriggle" : "wrench the ball");
1626 You("%s
\82â
\82Á
\82Æ
\8e©
\97R
\82É
\82È
\82Á
\82½
\81D",
1627 !anchored ? "
\82à
\82ª
\82¢
\82Ä" : "
\93S
\8b\85\82ð
\82à
\82¬
\8eæ
\82Á
\82Ä");
1630 buried_ball_to_punishment();
1634 impossible("trapmove: stuck in unknown trap? (%d)",
1644 if (!youmonst.data->mmove) {
1646 You("are rooted %s.",
1647 Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
1651 You("
\82»
\82Ì
\8fê
\82É
\97§
\82¿
\82·
\82
\82ñ
\82¾
\81D");
1662 register struct monst *mtmp;
1663 register struct rm *tmpr;
1664 register xchar x, y;
1665 struct trap *trap = NULL;
1668 xchar chainx = 0, chainy = 0,
1669 ballx = 0, bally = 0; /* ball&chain new positions */
1670 int bc_control = 0; /* control for ball&chain */
1671 boolean cause_delay = FALSE; /* dragging ball will skip a move */
1673 u_wipe_engr(rnd(5));
1675 if (context.travel) {
1676 if (!findtravelpath(FALSE))
1677 (void) findtravelpath(TRUE);
1678 context.travel1 = 0;
1681 if (((wtcap = near_capacity()) >= OVERLOADED
1682 || (wtcap > SLT_ENCUMBER
1683 && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1684 : (u.uhp < 10 && u.uhp != u.uhpmax))))
1685 && !Is_airlevel(&u.uz)) {
1686 if (wtcap < OVERLOADED) {
1688 You("don't have enough stamina to move.");
1690 You("
\82Ö
\82Æ
\82Ö
\82Æ
\82Å
\93®
\82¯
\82È
\82¢
\81D");
1691 exercise(A_CON, FALSE);
1694 You("collapse under your load.");
1696 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\93|
\82ê
\82½
\81D");
1702 u.ux = x = u.ustuck->mx;
1703 u.uy = y = u.ustuck->my;
1706 if (Is_airlevel(&u.uz) && rn2(4) && !Levitation && !Flying) {
1710 You("tumble in place.");
1712 You("
\82»
\82Ì
\8fê
\82Å
\93|
\82ê
\82½
\81D");
1713 exercise(A_DEX, FALSE);
1717 You_cant("control your movements very well.");
1719 You("
\82¤
\82Ü
\82
\95à
\82¯
\82È
\82¢
\81D");
1723 pline("It's hard to walk in thin air.");
1725 pline("
\8bó
\92\86\82ð
\95à
\82
\82Ì
\82Í
\93ï
\82µ
\82¢
\81D");
1726 exercise(A_DEX, TRUE);
1732 /* check slippery ice */
1733 on_ice = !Levitation && is_ice(u.ux, u.uy);
1735 static int skates = 0;
1738 skates = find_skates();
1739 if ((uarmf && uarmf->otyp == skates) || resists_cold(&youmonst)
1740 || Flying || is_floater(youmonst.data)
1741 || is_clinger(youmonst.data) || is_whirly(youmonst.data)) {
1743 } else if (!rn2(Cold_resistance ? 3 : 2)) {
1744 HFumbling |= FROMOUTSIDE;
1745 HFumbling &= ~TIMEOUT;
1746 HFumbling += 1; /* slip on next move */
1749 if (!on_ice && (HFumbling & FROMOUTSIDE))
1750 HFumbling &= ~FROMOUTSIDE;
1754 if (Stunned || (Confusion && !rn2(5))) {
1755 register int tries = 0;
1765 } while (!isok(x, y) || bad_rock(youmonst.data, x, y));
1767 /* turbulence might alter your actual destination */
1770 if (!u.dx && !u.dy) {
1781 if (((trap = t_at(x, y)) && trap->tseen)
1782 || (Blind && !Levitation && !Flying && !is_clinger(youmonst.data)
1783 && is_pool_or_lava(x, y) && levl[x][y].seenv)) {
1784 if (context.run >= 2) {
1785 if (iflags.mention_walls) {
1786 if (trap && trap->tseen) {
1787 int tt = what_trap(trap->ttyp);
1789 You("stop in front of %s.",
1791 You("%s
\82Ì
\8eè
\91O
\82Å
\8e~
\82Ü
\82Á
\82½
\81D",
1792 an(defsyms[trap_to_defsym(tt)].explanation));
1793 } else if (is_pool_or_lava(x,y) && levl[x][y].seenv) {
1795 You("stop at the edge of the %s.",
1796 hliquid(is_pool(x,y) ? "water" : "lava"));
1798 You("%s
\82Ì
\92[
\82Å
\8e~
\82Ü
\82Á
\82½
\81D.",
1799 hliquid(is_pool(x,y) ? "
\90\85" : "
\97n
\8aâ"));
1810 if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
1811 if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
1812 /* perhaps it fled (or was teleported or ... ) */
1814 } else if (sticks(youmonst.data)) {
1815 /* When polymorphed into a sticking monster,
1816 * u.ustuck means it's stuck to you, not you to it.
1819 You("release %s.", mon_nam(u.ustuck));
1821 You("%s
\82ð
\95ú
\82µ
\82½
\81D", mon_nam(u.ustuck));
1824 /* If holder is asleep or paralyzed:
1825 * 37.5% chance of getting away,
1826 * 12.5% chance of waking/releasing it;
1828 * 7.5% chance of getting away.
1829 * [strength ought to be a factor]
1830 * If holder is tame and there is no conflict,
1831 * guaranteed escape.
1833 switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
1839 You("pull free from %s.", mon_nam(u.ustuck));
1841 You("%s
\82ð
\82Ð
\82«
\82Í
\82È
\82µ
\82½
\81D", mon_nam(u.ustuck));
1845 if (!u.ustuck->mcanmove) {
1846 /* it's free to move on next turn */
1847 u.ustuck->mfrozen = 1;
1848 u.ustuck->msleeping = 0;
1852 if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf)
1855 You("cannot escape from %s!", mon_nam(u.ustuck));
1857 You("%s
\82©
\82ç
\93¦
\82°
\82ç
\82ê
\82È
\82¢
\81I", mon_nam(u.ustuck));
1865 if (mtmp && !is_safepet(mtmp)) {
1866 /* Don't attack if you're running, and can see it */
1867 /* It's fine to displace pets, though */
1868 /* We should never get here if forcefight */
1869 if (context.run && ((!Blind && mon_visible(mtmp)
1870 && ((mtmp->m_ap_type != M_AP_FURNITURE
1871 && mtmp->m_ap_type != M_AP_OBJECT)
1872 || Protection_from_shape_changers))
1873 || sensemon(mtmp))) {
1887 /* attack monster */
1889 /* don't stop travel when displacing pets; if the
1890 displace fails for some reason, attack() in uhitm.c
1891 will stop travel rather than domove */
1892 if (!is_safepet(mtmp) || context.forcefight)
1894 /* only attack if we know it's there */
1895 /* or if we used the 'F' command to fight blindly */
1896 /* or if it hides_under, in which case we call attack() to print
1897 * the Wait! message.
1898 * This is different from ceiling hiders, who aren't handled in
1902 /* If they used a 'm' command, trying to move onto a monster
1903 * prints the below message and wastes a turn. The exception is
1904 * if the monster is unseen and the player doesn't remember an
1905 * invisible monster--then, we fall through to attack() and
1906 * attack_check(), which still wastes a turn, but prints a
1907 * different message and makes the player remember the monster.
1909 if (context.nopick && !context.travel
1910 && (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))) {
1911 if (mtmp->m_ap_type && !Protection_from_shape_changers
1913 stumble_onto_mimic(mtmp);
1914 else if (mtmp->mpeaceful && !Hallucination)
1915 /* m_monnam(): "dog" or "Fido", no "invisible dog" or "it" */
1917 pline("Pardon me, %s.", m_monnam(mtmp));
1919 pline("
\82¿
\82å
\82Á
\82Æ
\82²
\82ß
\82ñ
\82È
\82³
\82¢
\82æ
\81C%s
\82³
\82ñ
\81D", m_monnam(mtmp));
1922 You("move right into %s.", mon_nam(mtmp));
1924 You("%s
\82Ì
\82»
\82Î
\82É
\88Ú
\93®
\82µ
\82½
\81D", mon_nam(mtmp));
1927 if (context.forcefight || !mtmp->mundetected || sensemon(mtmp)
1928 || ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)
1929 && !is_safepet(mtmp))) {
1930 /* try to attack; note that it might evade */
1931 /* also, we don't attack tame when _safepet_ */
1937 if (context.forcefight && levl[x][y].typ == IRONBARS && uwep) {
1938 struct obj *obj = uwep;
1940 if (breaktest(obj)) {
1942 obj = splitobj(obj, 1L);
1944 setuwep((struct obj *)0);
1947 hit_bars(&obj, u.ux, u.uy, x, y, TRUE, TRUE);
1951 /* specifying 'F' with no monster wastes a turn */
1952 if (context.forcefight
1953 /* remembered an 'I' && didn't use a move command */
1954 || (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
1955 struct obj *boulder = 0;
1956 boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
1957 solid = !accessible(x, y);
1958 int glyph = glyph_at(x, y); /* might be monster */
1962 boulder = sobj_at(BOULDER, x, y);
1963 /* if a statue is displayed at the target location,
1964 player is attempting to attack it [and boulder
1965 handling below is suitable for handling that] */
1966 if (glyph_is_statue(glyph)
1967 || (Hallucination && glyph_is_monster(glyph)))
1968 boulder = sobj_at(STATUE, x, y);
1970 /* force fight at boulder/statue or wall/door while wielding
1971 pick: start digging to break the boulder or wall */
1972 if (context.forcefight
1974 && uwep && dig_typ(uwep, x, y)
1975 /* should we dig? */
1976 && !glyph_is_invisible(glyph) && !glyph_is_monster(glyph)) {
1977 (void) use_pick_axe2(uwep);
1982 /* about to become known empty -- remove 'I' if present */
1985 map_object(boulder, TRUE);
1987 glyph = glyph_at(x, y); /* might have just changed */
1990 Strcpy(buf, ansimpleoname(boulder));
1991 } else if (Underwater && !is_pool(x, y)) {
1992 /* Underwater, targetting non-water; the map just shows blank
1993 because you don't see remembered terrain while underwater;
1994 although the hero can attack an adjacent monster this way,
1995 assume he can't reach out far enough to distinguish terrain */
1997 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
2001 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
2002 ? "
\8bó
\8bC
\82Ì
\96A"
2003 : "
\89½
\82à
\82È
\82¢
\82Æ
\82±
\82ë");
2006 /* glyph might indicate unseen terrain if hero is blind;
2007 unlike searching, this won't reveal what that terrain is
2008 (except for solid rock, where the glyph would otherwise
2009 yield ludicrous "dark part of a room") */
2011 Strcpy(buf, (levl[x][y].typ == STONE) ? "solid rock"
2012 : glyph_is_cmap(glyph)
2013 ? the(defsyms[glyph_to_cmap(glyph)].explanation)
2014 : (const char *) "an unknown obstacle");
2016 Strcpy(buf, (levl[x][y].typ == STONE) ? "
\90Î"
2017 : glyph_is_cmap(glyph)
2018 ? the(defsyms[glyph_to_cmap(glyph)].explanation)
2019 : (const char *) "
\95s
\96¾
\82È
\8fá
\8aQ
\95¨");
2021 /* note: 'solid' is misleadingly named and catches pools
2022 of water and lava as well as rock and walls */
2025 Strcpy(buf, "thin air");
2027 Strcpy(buf, "
\89½
\82à
\82È
\82¢
\8bó
\92\86");
2031 !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
2032 explo ? "explode at" : "attack", buf);
2035 !(boulder || solid) ? "" : !explo ? "
\8cø
\89Ê
\82È
\82" : "
\82Þ
\82¾
\82É",
2036 buf, explo ? "
\82Å
\94\9a\94
\82µ
\82½" : "
\82ð
\8dU
\8c\82\82µ
\82½");
2042 u.mh = -1; /* dead in the current form */
2047 (void) unmap_invisible(x, y);
2048 /* not attacking an animal, so we try to move */
2049 if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
2058 if (!trapmove(x, y, trap))
2062 if (!test_move(u.ux, u.uy, x - u.ux, y - u.uy, DO_MOVE)) {
2063 if (!context.door_opened) {
2070 /* Move ball and chain. */
2072 if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy,
2073 &cause_delay, TRUE))
2076 /* Check regions entering/leaving */
2077 if (!in_out_region(x, y))
2080 /* now move the hero */
2084 /* Move your steed, too */
2086 u.usteed->mx = u.ux;
2087 u.usteed->my = u.uy;
2092 * If safepet at destination then move the pet to the hero's
2093 * previous location using the same conditions as in attack().
2094 * there are special extenuating circumstances:
2095 * (1) if the pet dies then your god angers,
2096 * (2) if the pet gets trapped then your god may disapprove,
2097 * (3) if the pet was already trapped and you attempt to free it
2098 * not only do you encounter the trap but you may frighten your
2099 * pet causing it to go wild! moral: don't abuse this privilege.
2101 * Ceiling-hiding pets are skipped by this section of code, to
2102 * be caught by the normal falling-monster code.
2104 if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
2105 /* if trapped, there's a chance the pet goes wild */
2106 if (mtmp->mtrapped) {
2107 if (!rn2(mtmp->mtame)) {
2108 mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
2110 m_unleash(mtmp, TRUE);
2117 /* seemimic/newsym should be done before moving hero, otherwise
2118 the display code will draw the hero here before we possibly
2119 cancel the swap below (we can ignore steed mx,my here) */
2120 u.ux = u.ux0, u.uy = u.uy0;
2121 mtmp->mundetected = 0;
2122 if (mtmp->m_ap_type)
2124 else if (!mtmp->mtame)
2125 newsym(mtmp->mx, mtmp->my);
2126 u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
2128 if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
2129 && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
2130 && sobj_at(BOULDER, trap->tx, trap->ty)) {
2131 /* can't swap places with pet pinned in a pit by a boulder */
2132 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
2134 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2135 } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
2136 /* can't swap places when pet can't move to your spot */
2137 u.ux = u.ux0, u.uy = u.uy0;
2139 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2141 You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp)));
2143 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\8eÎ
\82ß
\82É
\93®
\82¯
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
2144 } else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0)
2145 && bad_rock(mtmp->data, u.ux0, y)
2146 && (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
2147 /* can't swap places when pet won't fit thru the opening */
2148 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
2150 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2152 You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
2154 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
2156 char pnambuf[BUFSZ];
2158 /* save its current description in case of polymorph */
2159 Strcpy(pnambuf, y_monnam(mtmp));
2161 remove_monster(x, y);
2162 place_monster(mtmp, u.ux0, u.uy0);
2164 newsym(u.ux0, u.uy0);
2167 You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
2172 mtmp->mtame ? "
\82Æ
\8fê
\8f\8a\82ð
\93ü
\82ê
\8a·
\82í
\82Á" : "
\82ð
\95|
\82ª
\82ç
\82¹");
2175 /* check for displacing it into pools and traps */
2176 switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
2179 case 1: /* trapped */
2180 case 3: /* changed levels */
2181 /* there's already been a trap message, reinforce it */
2186 /* drowned or died...
2187 * you killed your pet by direct action, so get experience
2188 * and possibly penalties;
2189 * we want the level gain message, if it happens, to occur
2190 * before the guilt message below
2193 /* minliquid() and mintrap() call mondead() rather than
2194 killed() so we duplicate some of the latter here */
2197 u.uconduct.killer++;
2198 mndx = monsndx(mtmp->data);
2199 tmp = experience(mtmp, (int) mvitals[mndx].died);
2200 more_experienced(tmp, 0);
2201 newexplevel(); /* will decide if you go up */
2203 /* That's no way to treat a pet! Your god gets angry.
2205 * [This has always been pretty iffy. Why does your
2206 * patron deity care at all, let alone enough to get mad?]
2210 You_feel("guilty about losing your pet like this.");
2212 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");
2218 pline("that's strange, unknown mintrap result!");
2224 reset_occupations();
2226 if (context.run < 8)
2227 if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ)
2228 || IS_FURNITURE(tmpr->typ))
2232 if (hides_under(youmonst.data) || youmonst.data->mlet == S_EEL
2234 (void) hideunder(&youmonst);
2237 * Mimics (or whatever) become noticeable if they move and are
2238 * imitating something that doesn't move. We could extend this
2239 * to non-moving monsters...
2241 if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
2242 || youmonst.m_ap_type == M_AP_FURNITURE))
2243 youmonst.m_ap_type = M_AP_NOTHING;
2245 check_leash(u.ux0, u.uy0);
2247 if (u.ux0 != u.ux || u.uy0 != u.uy) {
2249 /* Clean old position -- vision_recalc() will print our new one. */
2250 newsym(u.ux0, u.uy0);
2251 /* Since the hero has moved, adjust what can be seen/unseen. */
2252 vision_recalc(1); /* Do the work now in the recover time. */
2253 invocation_message();
2256 if (Punished) /* put back ball and chain */
2257 move_bc(0, bc_control, ballx, bally, chainx, chainy);
2262 /* delay next move because of ball dragging */
2263 /* must come after we finished picking up, in spoteffects() */
2267 multi_reason = "dragging an iron ball";
2269 multi_reason = "
\93S
\8b\85\82É
\88ø
\82«
\82¸
\82ç
\82ê
\82Ä
\82¢
\82é
\8e\9e\82É";
2273 if (context.run && flags.runmode != RUN_TPORT) {
2274 /* display every step or every 7th step depending upon mode */
2275 if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
2280 if (flags.runmode == RUN_CRAWL) {
2290 /* combat increases metabolism */
2294 /* this used to be part of domove() when moving to a monster's
2295 position, but is now called by attack() so that it doesn't
2296 execute if you decline to attack a peaceful monster */
2298 if ((moves % 3L) != 0L && near_capacity() >= HVY_ENCUMBER) {
2299 int *hp = (!Upolyd ? &u.uhp : &u.mh);
2305 You("pass out from exertion!");
2307 You("
\8bC
\90â
\82µ
\82½
\81D");
2308 exercise(A_CON, FALSE);
2309 fall_asleep(-10, FALSE);
2312 return (boolean) (multi < 0); /* might have fainted (forced to sleep) */
2316 invocation_message()
2318 /* a special clue-msg when on the Invocation position */
2319 if (invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
2321 struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
2323 nomul(0); /* stop running or travelling */
2326 Sprintf(buf, "beneath %s", y_monnam(u.usteed));
2328 Sprintf(buf, "%s
\82Ì
\89º
\82É", y_monnam(u.usteed));
2329 else if (Levitation || Flying)
2331 Strcpy(buf, "beneath you");
2333 Strcpy(buf, "
\89º
\95û
\82É");
2336 Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
2338 Strcpy(buf, "
\91«
\8c³
\82É");
2341 You_feel("a strange vibration %s.", buf);
2343 You("%s
\8aï
\96
\82È
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D", buf);
2344 u.uevent.uvibrated = 1;
2345 if (otmp && otmp->spe == 7 && otmp->lamplit)
2347 pline("%s %s!", The(xname(otmp)),
2348 Blind ? "throbs palpably" : "glows with a strange light");
2350 pline("%s
\82Í%s
\82µ
\82½
\81I", The(xname(otmp)),
2351 Blind ? "
\82©
\82·
\82©
\82É
\90U
\93®" : "
\8aï
\96
\82È
\8cõ
\82ð
\94");
2356 /* moving onto different terrain;
2357 might be going into solid rock, inhibiting levitation or flight,
2358 or coming back out of such, reinstating levitation/flying */
2362 struct rm *lev = &levl[u.ux][u.uy];
2363 boolean blocklev = (IS_ROCK(lev->typ) || closed_door(u.ux, u.uy)
2364 || (Is_waterlevel(&u.uz) && lev->typ == WATER));
2367 /* called from spoteffects(), skip float_down() */
2370 You_cant("levitate in here.");
2372 You_cant("
\82±
\82±
\82Å
\82Í
\95\82\97V
\82Å
\82«
\82È
\82¢
\81D");
2373 BLevitation |= FROMOUTSIDE;
2374 } else if (BLevitation) {
2375 BLevitation &= ~FROMOUTSIDE;
2379 /* the same terrain that blocks levitation also blocks flight */
2383 You_cant("fly in here.");
2385 You_cant("
\82±
\82±
\82Å
\82Í
\94ò
\82×
\82È
\82¢
\81D");
2386 BFlying |= FROMOUTSIDE;
2387 } else if (BFlying) {
2388 BFlying &= ~FROMOUTSIDE;
2389 float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
2390 /* [minor bug: we don't know whether this is beginning flight or
2391 resuming it; that could be tracked so that this message could
2392 be adjusted to "resume flying", but isn't worth the effort...] */
2395 You("start flying.");
2397 You("
\94ò
\82Ñ
\82Í
\82¶
\82ß
\82½
\81D");
2401 /* extracted from spoteffects; called by spoteffects to check for entering or
2402 leaving a pool of water/lava, and by moveloop to check for staying on one;
2403 returns true to skip rest of spoteffects */
2405 pooleffects(newspot)
2406 boolean newspot; /* true if called by spoteffects */
2408 /* check for leaving water */
2410 boolean still_inwater = FALSE; /* assume we're getting out */
2412 if (!is_pool(u.ux, u.uy)) {
2413 if (Is_waterlevel(&u.uz))
2415 You("pop into an air bubble.");
2417 You("
\82Ð
\82å
\82¢
\82Æ
\8bó
\8bC
\82Ì
\96A
\82É
\93ü
\82Á
\82½
\81D");
2418 else if (is_lava(u.ux, u.uy))
2420 You("leave the %s...", hliquid("water")); /* oops! */
2422 You("%s
\90\85\82©
\82ç
\94²
\82¯
\82¾
\82µ
\82½
\81D
\81D
\81D", hliquid("
\90\85")); /* oops! */
2426 You("are on solid %s again.",
2427 is_ice(u.ux, u.uy) ? "ice" : "land");
2429 You("
\8cÅ
\82¢%s
\82Ì
\8fã
\82É
\82Ü
\82½
\96ß
\82Á
\82½
\81D",
2430 is_ice(u.ux, u.uy) ? "
\95X" : "
\92n
\96Ê");
2432 } else if (Is_waterlevel(&u.uz)) {
2433 still_inwater = TRUE;
2434 } else if (Levitation) {
2436 You("pop out of the %s like a cork!", hliquid("water"));
2438 You("
\83R
\83\8b\83N
\82Ì
\82æ
\82¤
\82É%s
\82©
\82ç
\94ò
\82Ñ
\82¾
\82µ
\82½
\81I", hliquid("
\90\85"));
2439 } else if (Flying) {
2441 You("fly out of the %s.", hliquid("water"));
2443 You("%s
\82©
\82ç
\94ò
\82Ñ
\82¾
\82µ
\82½
\81D", hliquid("
\90\85"));
2444 } else if (Wwalking) {
2446 You("slowly rise above the surface.");
2448 You("
\82ä
\82Á
\82
\82è
\90\85\96Ê
\82Ü
\82Å
\8fã
\82ª
\82Á
\82½
\81D");
2450 still_inwater = TRUE;
2452 if (!still_inwater) {
2453 boolean was_underwater = (Underwater && !Is_waterlevel(&u.uz));
2455 u.uinwater = 0; /* leave the water */
2456 if (was_underwater) { /* restore vision */
2458 vision_full_recalc = 1;
2463 /* check for entering water or lava */
2464 if (!u.ustuck && !Levitation && !Flying && is_pool_or_lava(u.ux, u.uy)) {
2466 && (is_flyer(u.usteed->data) || is_floater(u.usteed->data)
2467 || is_clinger(u.usteed->data))) {
2468 /* floating or clinging steed keeps hero safe (is_flyer() test
2469 is redundant; it can't be true since Flying yielded false) */
2471 } else if (u.usteed) {
2472 /* steed enters pool */
2473 dismount_steed(Underwater ? DISMOUNT_FELL : DISMOUNT_GENERIC);
2474 /* dismount_steed() -> float_down() -> pickup()
2475 (float_down doesn't do autopickup on Air or Water) */
2476 if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
2478 /* even if we actually end up at same location, float_down()
2479 has already done spoteffect()'s trap and pickup actions */
2481 check_special_room(FALSE); /* spoteffects */
2486 /* drown(),lava_effects() return true if hero changes
2487 location while surviving the problem */
2488 if (is_lava(u.ux, u.uy)) {
2491 } else if (!Wwalking
2492 && (newspot || !u.uinwater || !(Swimming || Amphibious))) {
2504 static int inspoteffects = 0;
2505 static coord spotloc;
2506 static int spotterrain;
2507 static struct trap *spottrap = (struct trap *) 0;
2508 static unsigned spottraptyp = NO_TRAP;
2511 struct trap *trap = t_at(u.ux, u.uy);
2513 /* prevent recursion from affecting the hero all over again
2514 [hero poly'd to iron golem enters water here, drown() inflicts
2515 damage that triggers rehumanize() which calls spoteffects()...] */
2516 if (inspoteffects && u.ux == spotloc.x && u.uy == spotloc.y
2517 /* except when reason is transformed terrain (ice -> water) */
2518 && spotterrain == levl[u.ux][u.uy].typ
2519 /* or transformed trap (land mine -> pit) */
2520 && (!spottrap || !trap || trap->ttyp == spottraptyp))
2524 spotterrain = levl[u.ux][u.uy].typ;
2525 spotloc.x = u.ux, spotloc.y = u.uy;
2527 /* moving onto different terrain might cause Levitation to toggle */
2528 if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
2531 if (pooleffects(TRUE))
2534 check_special_room(FALSE);
2535 if (IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
2537 if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
2540 /* if levitation is due to time out at the end of this
2541 turn, allowing it to do so could give the perception
2542 that a trap here is being triggered twice, so adjust
2543 the timeout to prevent that */
2544 if (trap && (HLevitation & TIMEOUT) == 1L
2545 && !(ELevitation || (HLevitation & ~(I_SPECIAL | TIMEOUT)))) {
2546 if (rn2(2)) { /* defer timeout */
2547 incr_itimeout(&HLevitation, 1L);
2548 } else { /* timeout early */
2549 if (float_down(I_SPECIAL | TIMEOUT, 0L)) {
2550 /* levitation has ended; we've already triggered
2551 any trap and [usually] performed autopickup */
2558 * If not a pit, pickup before triggering trap.
2559 * If pit, trigger trap before pickup.
2561 pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
2567 * dotrap on a fire trap calls melt_ice() which triggers
2568 * spoteffects() (again) which can trigger the same fire
2569 * trap (again). Use static spottrap to prevent that.
2570 * We track spottraptyp because some traps morph
2571 * (landmine to pit) and any new trap type
2572 * should get triggered.
2574 if (!spottrap || spottraptyp != trap->ttyp) {
2576 spottraptyp = trap->ttyp;
2577 dotrap(trap, 0); /* fall into arrow trap, etc. */
2578 spottrap = (struct trap *) 0;
2579 spottraptyp = NO_TRAP;
2585 /* Warning alerts you to ice danger */
2586 if (Warning && is_ice(u.ux, u.uy)) {
2587 static const char *const icewarnings[] = {
2589 "The ice seems very soft and slushy.",
2590 "You feel the ice shift beneath you!",
2591 "The ice, is gonna BREAK!", /* The Dead Zone */
2593 "
\95X
\82Í
\82Æ
\82Ä
\82à
\93î
\82ç
\82©
\82
\82Ä
\97n
\82¯
\82»
\82¤
\82¾
\81D",
2594 "
\82 \82È
\82½
\82Ì
\89º
\82Ì
\95X
\82ª
\93®
\82¢
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81I",
2595 "
\95X
\82ª
\89ó
\82ê
\82é
\82¼
\81I", /* The Dead Zone */
2598 long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
2600 if (time_left && time_left < 15L)
2601 pline("%s", icewarnings[(time_left < 5L) ? 2
2602 : (time_left < 10L) ? 1
2605 if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
2606 mtmp->mundetected = mtmp->msleeping = 0;
2607 switch (mtmp->data->mlet) {
2610 pline("%s suddenly drops from the %s!", Amonnam(mtmp),
2611 ceiling(u.ux, u.uy));
2613 pline("%s
\82ª
\93Ë
\91R%s
\82©
\82ç
\97\8e\82¿
\82Ä
\82«
\82½
\81I", Amonnam(mtmp),
2614 ceiling(u.ux,u.uy));
2616 if (mtmp->mtame) { /* jumps to greet you, not attack */
2618 } else if (uarmh && is_metallic(uarmh)) {
2620 pline("Its blow glances off your %s.",
2622 pline("
\8dU
\8c\82\82Í
\82 \82È
\82½
\82Ì%s
\82ð
\82©
\82·
\82ß
\82½
\82¾
\82¯
\82¾
\82Á
\82½
\81D",
2623 helm_simple_name(uarmh));
2624 } else if (u.uac + 3 <= rnd(20)) {
2626 You("are almost hit by %s!",
2627 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2629 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",
2630 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2636 You("are hit by %s!",
2637 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2639 You("
\97\8e\82¿
\82Ä
\82«
\82½%s
\82É
\93\96\82½
\82Á
\82½
\81I",
2640 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2643 if (Half_physical_damage)
2644 dmg = (dmg + 1) / 2;
2645 mdamageu(mtmp, dmg);
2648 default: /* monster surprises you. */
2651 pline("%s jumps near you from the %s.", Amonnam(mtmp),
2652 ceiling(u.ux, u.uy));
2654 pline("%s
\82ª%s
\82©
\82ç
\82 \82È
\82½
\82Ì
\8bß
\82
\82É
\94ò
\82ñ
\82Å
\82«
\82½
\81D", Amonnam(mtmp),
2655 ceiling(u.ux,u.uy));
2657 else if (mtmp->mpeaceful) {
2661 You("%s
\82ð
\8bÁ
\82©
\82µ
\82½
\81I",
2662 Blind && !sensemon(mtmp) ? something : a_monnam(mtmp));
2663 mtmp->mpeaceful = 0;
2666 pline("%s attacks you by surprise!", Amonnam(mtmp));
2668 pline("%s
\82Í
\8bÁ
\82¢
\82Ä
\82 \82È
\82½
\82ð
\8dU
\8c\82\82µ
\82½
\81I", Amonnam(mtmp));
2671 mnexto(mtmp); /* have to move the monster */
2674 if (!--inspoteffects) {
2675 spotterrain = STONE; /* 0 */
2676 spotloc.x = spotloc.y = 0;
2681 /* returns first matching monster */
2682 STATIC_OVL struct monst *
2683 monstinroom(mdat, roomno)
2684 struct permonst *mdat;
2687 register struct monst *mtmp;
2689 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2690 if (DEADMONSTER(mtmp))
2692 if (mtmp->data == mdat
2693 && index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
2696 return (struct monst *) 0;
2700 in_rooms(x, y, typewanted)
2701 register xchar x, y;
2702 register int typewanted;
2705 char rno, *ptr = &buf[4];
2706 int typefound, min_x, min_y, max_x, max_y_offset, step;
2707 register struct rm *lev;
2709 #define goodtype(rno) \
2711 || (typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted \
2712 || (typewanted == SHOPBASE && typefound > SHOPBASE))
2714 switch (rno = levl[x][y].roomno) {
2723 default: /* i.e. a regular room # */
2733 else if (x >= COLNO)
2740 max_y_offset -= step;
2741 } else if ((min_y + max_y_offset) >= ROWNO)
2742 max_y_offset -= step;
2744 for (x = min_x; x <= max_x; x += step) {
2745 lev = &levl[x][min_y];
2747 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2751 if (y > max_y_offset)
2753 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2757 if (y > max_y_offset)
2759 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2766 /* is (x,y) in a town? */
2771 s_level *slev = Is_special(&u.uz);
2772 register struct mkroom *sroom;
2773 boolean has_subrooms = FALSE;
2775 if (!slev || !slev->flags.town)
2779 * See if (x,y) is in a room with subrooms, if so, assume it's the
2780 * town. If there are no subrooms, the whole level is in town.
2782 for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
2783 if (sroom->nsubrooms > 0) {
2784 has_subrooms = TRUE;
2785 if (inside_room(sroom, x, y))
2790 return !has_subrooms;
2795 register boolean newlev;
2797 char *ptr1, *ptr2, *ptr3, *ptr4;
2799 Strcpy(u.urooms0, u.urooms);
2800 Strcpy(u.ushops0, u.ushops);
2803 u.uentered[0] = '\0';
2805 u.ushops_entered[0] = '\0';
2806 Strcpy(u.ushops_left, u.ushops0);
2809 Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
2811 for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
2812 ptr4 = &u.ushops_entered[0];
2814 if (!index(u.urooms0, *ptr1))
2816 if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
2818 if (!index(u.ushops0, *ptr1))
2826 /* filter u.ushops0 -> u.ushops_left */
2827 for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
2828 if (!index(u.ushops, *ptr1))
2833 /* possibly deliver a one-time room entry message */
2835 check_special_room(newlev)
2836 register boolean newlev;
2838 register struct monst *mtmp;
2841 move_update(newlev);
2844 u_left_shop(u.ushops_left, newlev);
2846 if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
2847 return; /* no entrance messages necessary */
2849 /* Did we just enter a shop? */
2850 if (*u.ushops_entered)
2851 u_entered_shop(u.ushops_entered);
2853 for (ptr = &u.uentered[0]; *ptr; ptr++) {
2854 int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
2855 boolean msg_given = TRUE;
2857 /* Did we just enter some other special room? */
2858 /* vault.c insists that a vault remain a VAULT,
2859 * and temples should remain TEMPLEs,
2860 * but everything else gives a message only the first time */
2864 pline("Welcome to David's treasure zoo!");
2866 pline("
\83f
\83r
\83b
\83g
\95ó
\94 \93®
\95¨
\89\80\82É
\82æ
\82¤
\82±
\82»
\81I");
2870 pline("It %s rather %s down here.", Blind ? "feels" : "looks",
2871 Blind ? "humid" : "muddy");
2873 pline("
\82©
\82È
\82è%s
\81D",
2874 Blind ? "
\8e¼
\8bC
\82ª
\82 \82é
\8fê
\8f\8a\82Ì
\82æ
\82¤
\82¾"
2875 : "
\82Ç
\82ë
\82Ç
\82ë
\82µ
\82Ä
\82¢
\82é
\8fê
\8f\8a\82¾");
2880 You("enter an opulent throne room!");
2882 You("
\89Ø
\82â
\82©
\82È
\8bÊ
\8dÀ
\82Ì
\8aÔ
\82É
\93ü
\82Á
\82½
\81I");
2886 You("enter a leprechaun hall!");
2888 You("
\83\8c\83v
\83\89\83R
\81[
\83\93\83z
\81[
\83\8b\82É
\93ü
\82Á
\82½
\81I");
2893 const char *run = locomotion(youmonst.data, "Run");
2894 pline("%s away! %s away!", run, run);
2896 pline("
\93¦
\82°
\82ë
\81I
\93¦
\82°
\82ë
\81I");
2900 You("have an uncanny feeling...");
2902 You("
\95s
\8bC
\96¡
\82È
\8a´
\82¶
\82ª
\82µ
\82½
\81D
\81D
\81D");
2906 You("enter a giant beehive!");
2908 You("
\8b\90\91å
\82È
\96I
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2912 You("enter a disgusting nest!");
2914 You("
\82Þ
\82Á
\82Æ
\82·
\82é
\8fL
\82¢
\82Ì
\82·
\82é
\92¹
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2918 You("enter an anthole!");
2920 You("
\83A
\83\8a\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2923 if (monstinroom(&mons[PM_SOLDIER], roomno)
2924 || monstinroom(&mons[PM_SERGEANT], roomno)
2925 || monstinroom(&mons[PM_LIEUTENANT], roomno)
2926 || monstinroom(&mons[PM_CAPTAIN], roomno))
2928 You("enter a military barracks!");
2930 You("
\8cR
\91à
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81I");
2933 You("enter an abandoned barracks.");
2935 You("
\95ú
\92u
\82³
\82ê
\82½
\82Ü
\82Ü
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81D");
2938 struct monst *oracle = monstinroom(&mons[PM_ORACLE], roomno);
2940 if (!oracle->mpeaceful)
2942 verbalize("You're in Delphi, %s.", plname);
2944 verbalize("
\82¨
\82Ü
\82¦
\82Í
\83f
\83\8b\83t
\83@
\83C
\82Ì
\90_
\91õ
\8f\8a\82É
\82¢
\82é
\81D");
2947 verbalize("%s, %s, welcome to Delphi!",
2948 Hello((struct monst *) 0), plname);
2950 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",
2958 intemple(roomno + ROOMOFFSET);
2961 msg_given = (rt == TEMPLE);
2966 room_discovered(roomno);
2969 rooms[roomno].rtype = OROOM;
2970 if (!search_special(rt)) {
2971 /* No more room of that type */
2974 level.flags.has_court = 0;
2977 level.flags.has_swamp = 0;
2980 level.flags.has_morgue = 0;
2983 level.flags.has_zoo = 0;
2986 level.flags.has_barracks = 0;
2989 level.flags.has_temple = 0;
2992 level.flags.has_beehive = 0;
2996 if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
2997 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2998 if (DEADMONSTER(mtmp))
3000 if (!Stealth && !rn2(3))
3001 mtmp->msleeping = 0;
3009 /* the ',' command */
3013 int count, tmpcount;
3014 struct trap *traphere = t_at(u.ux, u.uy);
3016 /* awful kludge to work around parse()'s pre-decrement */
3017 count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
3018 multi = 0; /* always reset */
3019 /* uswallow case added by GAN 01/29/87 */
3021 if (!u.ustuck->minvent) {
3022 if (is_animal(u.ustuck->data)) {
3024 You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
3026 You("%s
\82Ì
\90ã
\82ð
\8fE
\82Á
\82½
\81D", mon_nam(u.ustuck));
3028 pline("But it's kind of slimy, so you drop it.");
3030 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");
3033 You("don't %s anything in here to pick up.",
3034 Blind ? "feel" : "see");
3036 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82ª
\82È
\82¢%s
\81D",
3037 Blind ? "
\82æ
\82¤
\82¾" : "");
3042 return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
3045 if (is_pool(u.ux, u.uy)) {
3046 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
3047 || (Flying && !Breathless)) {
3049 You("cannot dive into the %s to pick things up.",
3052 You("
\95¨
\82ð
\8fE
\82¢
\82 \82°
\82é
\82½
\82ß
\82É%s
\82É
\94ò
\82Ñ
\82±
\82ß
\82È
\82¢
\81D",
3056 } else if (!Underwater) {
3058 You_cant("even see the bottom, let alone pick up %s.", something);
3060 pline("
\92ê
\82³
\82¦
\8c©
\82¦
\82È
\82¢
\81C
\8fE
\82¤
\82Ì
\82Í
\82â
\82ß
\82æ
\82¤
\81D");
3064 if (is_lava(u.ux, u.uy)) {
3065 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
3066 || (Flying && !Breathless)) {
3068 You_cant("reach the bottom to pick things up.");
3070 You_cant("
\95¨
\82ð
\8fE
\82¢
\8fã
\82°
\82é
\82½
\82ß
\82É
\92ê
\82Ü
\82Å
\82¢
\82¯
\82È
\82¢
\81D");
3072 } else if (!likes_lava(youmonst.data)) {
3074 You("would burn to a crisp trying to pick things up.");
3076 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");
3080 if (!OBJ_AT(u.ux, u.uy)) {
3081 register struct rm *lev = &levl[u.ux][u.uy];
3083 if (IS_THRONE(lev->typ))
3085 pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
3087 pline("
\82±
\82ê
\82Í%s
\8fd
\82¢
\81I", lev->looted ? "
\82©
\82È
\82è" : "
\82·
\82²
\82");
3088 else if (IS_SINK(lev->typ))
3090 pline_The("plumbing connects it to the floor.");
3092 pline_The("
\94z
\8aÇ
\82Í
\8f°
\82É
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é
\81D");
3093 else if (IS_GRAVE(lev->typ))
3095 You("don't need a gravestone. Yet.");
3097 pline("
\82 \82È
\82½
\82É
\82Í
\95æ
\90Î
\82Í
\95s
\97v
\82¾
\81D
\81D
\81D
\8d¡
\82Ì
\82Æ
\82±
\82ë
\81D");
3098 else if (IS_FOUNTAIN(lev->typ))
3100 You("could drink the %s...", hliquid("water"));
3102 You("%s
\82ð
\88ù
\82ß
\82È
\82¢
\81D
\81D
\81D", hliquid("
\90\85"));
3103 else if (IS_DOOR(lev->typ) && (lev->doormask & D_ISOPEN))
3105 pline("It won't come off the hinges.");
3107 pline("
\83q
\83\93\83W
\82ð
\8aO
\82¹
\82È
\82¢
\81D");
3110 There("is nothing here to pick up.");
3112 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82Í
\82È
\82¢
\81D");
3115 if (!can_reach_floor(TRUE)) {
3116 if (traphere && uteetering_at_seen_pit(traphere))
3118 You("cannot reach the bottom of the pit.");
3120 You("
\97\8e\82µ
\8c\8a\82Ì
\92ê
\82É%s
\82ª
\93Í
\82©
\82È
\82©
\82Á
\82½
\81D", body_part(HAND));
3121 else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
3123 else if (Blind && !can_reach_floor(TRUE))
3125 You("cannot reach anything here.");
3127 You("
\89½
\82É
\82à
\93Í
\82©
\82È
\82¢
\81D");
3130 You("cannot reach the %s.", surface(u.ux, u.uy));
3132 You("%s
\82É
\82½
\82Ç
\82è
\82Â
\82
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D", surface(u.ux, u.uy));
3136 return pickup(-count);
3139 /* stop running if we see something interesting */
3140 /* turn around a corner if that is the only way we can proceed */
3141 /* do not turn left or right twice */
3146 int i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
3147 int corrct = 0, noturn = 0;
3151 /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
3152 /* they polymorphed while in the middle of a long move. */
3153 if (NODIAG(u.umonnum) && u.dx && u.dy) {
3155 You("cannot move diagonally.");
3157 You("
\8eÎ
\82ß
\82É
\88Ú
\93®
\82Å
\82«
\82È
\82¢
\81D");
3162 if (Blind || context.run == 0)
3164 for (x = u.ux - 1; x <= u.ux + 1; x++)
3165 for (y = u.uy - 1; y <= u.uy + 1; y++) {
3166 if (!isok(x, y) || (x == u.ux && y == u.uy))
3168 if (NODIAG(u.umonnum) && x != u.ux && y != u.uy)
3171 if ((mtmp = m_at(x, y)) != 0
3172 && mtmp->m_ap_type != M_AP_FURNITURE
3173 && mtmp->m_ap_type != M_AP_OBJECT
3174 && (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
3175 if ((context.run != 1 && !mtmp->mtame)
3176 || (x == u.ux + u.dx && y == u.uy + u.dy
3177 && !context.travel)) {
3178 if (iflags.mention_walls)
3180 pline("%s blocks your path.", upstart(a_monnam(mtmp)));
3182 pline("%s
\82ª
\93¹
\82ð
\82Ó
\82³
\82¢
\82Å
\82¢
\82é
\81D", a_monnam(mtmp));
3187 if (levl[x][y].typ == STONE)
3189 if (x == u.ux - u.dx && y == u.uy - u.dy)
3192 if (IS_ROCK(levl[x][y].typ) || levl[x][y].typ == ROOM
3193 || IS_AIR(levl[x][y].typ)) {
3195 } else if (closed_door(x, y) || (mtmp && is_door_mappear(mtmp))) {
3196 if (x != u.ux && y != u.uy)
3198 if (context.run != 1) {
3199 if (iflags.mention_walls)
3201 You("stop in front of the door.");
3203 You("
\94à
\82Ì
\8eè
\91O
\82Å
\8e~
\82Ü
\82Á
\82½
\81D");
3207 } else if (levl[x][y].typ == CORR) {
3209 if (levl[u.ux][u.uy].typ != ROOM) {
3210 if (context.run == 1 || context.run == 3
3211 || context.run == 8) {
3212 i = dist2(x, y, u.ux + u.dx, u.uy + u.dy);
3215 if (corrct == 1 && dist2(x, y, x0, y0) != 1)
3227 } else if ((trap = t_at(x, y)) && trap->tseen) {
3228 if (context.run == 1)
3229 goto bcorr; /* if you must */
3230 if (x == u.ux + u.dx && y == u.uy + u.dy) {
3231 if (iflags.mention_walls) {
3232 int tt = what_trap(trap->ttyp);
3234 You("stop in front of %s.",
3236 You("%s
\82Ì
\8eè
\91O
\82Å
\8e~
\82Ü
\82Á
\82½
\81D",
3237 an(defsyms[trap_to_defsym(tt)].explanation));
3242 } else if (is_pool_or_lava(x, y)) {
3243 /* water and lava only stop you if directly in front, and stop
3244 * you even if you are running
3246 if (!Levitation && !Flying && !is_clinger(youmonst.data)
3247 && x == u.ux + u.dx && y == u.uy + u.dy) {
3248 /* No Wwalking check; otherwise they'd be able
3249 * to test boots by trying to SHIFT-direction
3250 * into a pool and seeing if the game allowed it
3252 if (iflags.mention_walls)
3254 You("stop at the edge of the %s.",
3255 hliquid(is_pool(x,y) ? "water" : "lava"));
3257 You("%s
\82Ì
\92[
\82Å
\8e~
\82Ü
\82Á
\82½
\81D",
3258 hliquid(is_pool(x,y) ? "
\90\85" : "
\97n
\8aâ"));
3263 } else { /* e.g. objects or trap or stairs */
3264 if (context.run == 1)
3266 if (context.run == 8)
3270 if (((x == u.ux - u.dx) && (y != u.uy + u.dy))
3271 || ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
3277 } /* end for loops */
3279 if (corrct > 1 && context.run == 2) {
3280 if (iflags.mention_walls)
3282 pline_The("corridor widens here.");
3284 pline("
\92Ê
\98H
\82Í
\82±
\82±
\82Å
\8dL
\82
\82È
\82Á
\82Ä
\82¢
\82é
\81D");
3287 if ((context.run == 1 || context.run == 3 || context.run == 8) && !noturn
3288 && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) {
3289 /* make sure that we do not turn too far */
3291 if (u.dx == y0 - u.uy && u.dy == u.ux - x0)
3292 i = 2; /* straight turn right */
3294 i = -2; /* straight turn left */
3295 } else if (u.dx && u.dy) {
3296 if ((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
3297 i = -1; /* half turn left */
3299 i = 1; /* half turn right */
3301 if ((x0 - u.ux == y0 - u.uy && !u.dy)
3302 || (x0 - u.ux != y0 - u.uy && u.dy))
3303 i = 1; /* half turn right */
3305 i = -1; /* half turn left */
3308 i += u.last_str_turn;
3309 if (i <= 2 && i >= -2) {
3310 u.last_str_turn = i;
3317 /* check for a doorway which lacks its door (NODOOR or BROKEN) */
3322 struct rm *lev_p = &levl[x][y];
3324 if (!IS_DOOR(lev_p->typ))
3326 /* all rogue level doors are doorless but disallow diagonal access, so
3327 we treat them as if their non-existant doors were actually present */
3328 if (Is_rogue_level(&u.uz))
3330 return !(lev_p->doormask & ~(D_NODOOR | D_BROKEN));
3333 /* used by drown() to check whether hero can crawl from water to <x,y> */
3335 crawl_destination(x, y)
3338 /* is location ok in general? */
3339 if (!goodpos(x, y, &youmonst, 0))
3342 /* orthogonal movement is unrestricted when destination is ok */
3343 if (x == u.ux || y == u.uy)
3346 /* diagonal movement has some restrictions */
3347 if (NODIAG(u.umonnum))
3348 return FALSE; /* poly'd into a grid bug... */
3350 return TRUE; /* or a xorn... */
3351 /* pool could be next to a door, conceivably even inside a shop */
3352 if (IS_DOOR(levl[x][y].typ) && (!doorless_door(x, y) || block_door(x, y)))
3354 /* finally, are we trying to squeeze through a too-narrow gap? */
3355 return !(bad_rock(youmonst.data, u.ux, y)
3356 && bad_rock(youmonst.data, x, u.uy));
3359 /* something like lookaround, but we are not running */
3360 /* react only to monsters that might hit us */
3365 register struct monst *mtmp;
3367 /* Also see the similar check in dochugw() in monmove.c */
3368 for (x = u.ux - 1; x <= u.ux + 1; x++)
3369 for (y = u.uy - 1; y <= u.uy + 1; y++) {
3370 if (!isok(x, y) || (x == u.ux && y == u.uy))
3372 if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
3373 && mtmp->m_ap_type != M_AP_OBJECT
3374 && (!mtmp->mpeaceful || Hallucination)
3375 && (!is_hider(mtmp->data) || !mtmp->mundetected)
3376 && !noattacks(mtmp->data) && mtmp->mcanmove
3377 && !mtmp->msleeping /* aplvax!jcn */
3378 && !onscary(u.ux, u.uy, mtmp) && canspotmon(mtmp))
3389 return; /* This is a bug fix by ab@unido */
3390 u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
3394 multi_reason = NULL;
3395 context.travel = context.travel1 = context.mv = context.run = 0;
3398 /* called when a non-movement, multi-turn action has completed */
3401 const char *msg_override;
3403 multi = 0; /* caller will usually have done this already */
3405 nomovemsg = msg_override;
3406 else if (!nomovemsg)
3407 nomovemsg = You_can_move_again;
3412 multi_reason = NULL;
3414 int NDECL((*f)) = afternmv;
3415 /* clear afternmv before calling it (to override the
3416 encumbrance hack for levitation--see weight_cap()) */
3417 afternmv = (int NDECL((*))) 0;
3425 static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES,
3426 SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
3427 TELEPORT_CONTROL, STEALTH, FAST, INVIS };
3429 if (moves <= wailmsg + 50)
3433 if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) {
3438 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3441 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3446 pline("%s is about to die.", who);
3448 pline("%s
\82Í
\8e\80\82É
\82©
\82¯
\82Ä
\82¢
\82é
\81D", who);
3450 for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
3451 if (u.uprops[powers[i]].intrinsic & INTRINSIC)
3455 pline((powercnt >= 4) ? "%s, all your powers will be lost..."
3457 pline((powercnt >= 4) ? "%s
\81C
\82 \82È
\82½
\82Ì
\91S
\82Ä
\82Ì
\97Í
\82Í
\8e¸
\82í
\82ê
\82Â
\82Â
\82 \82é
\81D
\81D
\81D"
3459 : "%s, your life force is running out.",
3461 : "%s
\81C
\82 \82È
\82½
\82Ì
\90¶
\96½
\97Í
\82Í
\90s
\82«
\82æ
\82¤
\82Æ
\82µ
\82Ä
\82¢
\82é
\81D
\81D
\81D",
3466 You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
3468 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"
3470 : "the howling of the CwnAnnwn...");
3472 : "
\83N
\81[
\83\93\81E
\83A
\83\93\83k
\81[
\83\93\82Ì
\89\93\96i
\82ª
\95·
\82±
\82¦
\82é
\81D
\81D
\81D");
3477 losehp(n, knam, k_format)
3479 register const char *knam;
3489 else if (n > 0 && u.mh * 10 < u.mhmax && Unchanging)
3495 if (u.uhp > u.uhpmax)
3496 u.uhpmax = u.uhp; /* perhaps n was negative */
3498 context.travel = context.travel1 = context.mv = context.run = 0;
3501 killer.format = k_format;
3502 if (killer.name != knam) /* the thing that killed you */
3503 Strcpy(killer.name, knam ? knam : "");
3507 pline("
\82 \82È
\82½
\82Í
\8e\80\82É
\82Ü
\82µ
\82½
\81D
\81D
\81D");
3509 } else if (n > 0 && u.uhp * 10 < u.uhpmax) {
3517 long carrcap, save_ELev = ELevitation;
3519 /* boots take multiple turns to wear but any properties they
3520 confer are enabled at the start rather than the end; that
3521 causes message sequencing issues for boots of levitation
3522 so defer their encumbrance benefit until they're fully worn */
3523 if (afternmv == Boots_on && (ELevitation & W_ARMF) != 0L) {
3524 ELevitation &= ~W_ARMF;
3525 float_vs_flight(); /* in case Levitation is blocking Flying */
3528 carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
3530 /* consistent with can_carry() in mon.c */
3531 if (youmonst.data->mlet == S_NYMPH)
3532 carrcap = MAX_CARR_CAP;
3533 else if (!youmonst.data->cwt)
3534 carrcap = (carrcap * (long) youmonst.data->msize) / MZ_HUMAN;
3535 else if (!strongmonst(youmonst.data)
3536 || (strongmonst(youmonst.data)
3537 && (youmonst.data->cwt > WT_HUMAN)))
3538 carrcap = (carrcap * (long) youmonst.data->cwt / WT_HUMAN);
3541 if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
3542 || (u.usteed && strongmonst(u.usteed->data))) {
3543 carrcap = MAX_CARR_CAP;
3545 if (carrcap > MAX_CARR_CAP)
3546 carrcap = MAX_CARR_CAP;
3548 if (EWounded_legs & LEFT_SIDE)
3550 if (EWounded_legs & RIGHT_SIDE)
3557 if (ELevitation != save_ELev) {
3558 ELevitation = save_ELev;
3562 return (int) carrcap;
3565 static int wc; /* current weight_cap(); valid after call to inv_weight() */
3567 /* returns how far beyond the normal capacity the player is currently. */
3568 /* inv_weight() is negative if the player is below normal capacity. */
3572 register struct obj *otmp = invent;
3573 register int wt = 0;
3576 if (otmp->oclass == COIN_CLASS)
3577 wt += (int) (((long) otmp->quan + 50L) / 100L);
3578 else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
3587 * Returns 0 if below normal capacity, or the number of "capacity units"
3588 * over the normal capacity the player is loaded. Max is 5.
3591 calc_capacity(xtra_wt)
3594 int cap, wt = inv_weight() + xtra_wt;
3597 return UNENCUMBERED;
3600 cap = (wt * 2 / wc) + 1;
3601 return min(cap, OVERLOADED);
3607 return calc_capacity(0);
3613 int wt = inv_weight();
3615 return (wt - (2 * wc));
3622 if (near_capacity() >= EXT_ENCUMBER) {
3627 You_cant("do that while carrying so much stuff.");
3629 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");
3639 register struct obj *otmp = invent;
3640 register int ct = 0;
3643 if (incl_gold || otmp->invlet != GOLD_SYM)
3650 /* Counts the money in an object chain. */
3651 /* Intended use is for your or some monster's inventory, */
3652 /* now that u.gold/m.gold is gone.*/
3653 /* Counting money in a container might be possible too. */
3659 /* Must change when silver & copper is implemented: */
3660 if (otmp->oclass == COIN_CLASS)