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 */
896 pline("There is an obstacle there.");
898 } else if (tmpr->typ == IRONBARS) {
899 if ((dmgtype(youmonst.data, AD_RUST)
900 || dmgtype(youmonst.data, AD_CORR)) && mode == DO_MOVE
901 && still_chewing(x, y)) {
904 if (!(Passes_walls || passes_bars(youmonst.data))) {
905 if (mode == DO_MOVE && iflags.mention_walls)
907 You("cannot pass through the bars.");
909 You("
\93S
\82Ì
\96_
\82ð
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
912 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
914 if (mode == DO_MOVE && still_chewing(x, y))
916 } else if (flags.autodig && !context.run && !context.nopick && uwep
918 /* MRKR: Automatic digging when wielding the appropriate tool */
920 (void) use_pick_axe2(uwep);
923 if (mode == DO_MOVE) {
924 if (is_db_wall(x, y))
926 pline("That drawbridge is up!");
928 pline("
\92µ
\82Ë
\8b´
\82Í
\8fã
\82Á
\82Ä
\82¢
\82é
\81I");
929 /* sokoban restriction stays even after puzzle is solved */
930 else if (Passes_walls && !may_passwall(x, y)
931 && In_sokoban(&u.uz))
933 pline_The("Sokoban walls resist your ability.");
935 pline_The("
\91q
\8cÉ
\94Ô
\82Ì
\95Ç
\82Í
\82 \82È
\82½
\82Ì
\94\
\97Í
\82É
\92ï
\8dR
\82µ
\82½
\81D");
936 else if (iflags.mention_walls)
939 (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "a wall"
940 : IS_TREE(tmpr->typ) ? "a tree"
943 pline("
\82±
\82ê
\82Í%s
\82¾
\81D",
944 (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "
\95Ç"
945 : IS_TREE(tmpr->typ) ? "
\96Ø"
951 } else if (IS_DOOR(tmpr->typ)) {
952 if (closed_door(x, y)) {
953 if (Blind && mode == DO_MOVE)
957 } else if (can_ooze(&youmonst)) {
960 You("ooze under the door.");
962 You("
\83h
\83A
\82Ì
\89º
\82©
\82ç
\82É
\82¶
\82Ý
\8fo
\82½
\81D");
963 } else if (Underwater) {
965 pline("There is an obstacle there.");
967 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
969 if (mode == DO_MOVE && still_chewing(x, y))
972 if (mode == DO_MOVE) {
973 if (amorphous(youmonst.data))
976 "try to ooze under the door, but can't squeeze your possessions through.");
978 "
\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");
979 if (flags.autoopen && !context.run && !Confusion
980 && !Stunned && !Fumbling) {
981 context.door_opened = context.move =
983 } else if (x == ux || y == uy) {
984 if (Blind || Stunned || ACURR(A_DEX) < 10
988 You_cant("lead %s through that closed door.",
990 You_cant("%s
\82É
\95Â
\82Ü
\82Á
\82½
\94à
\82ð
\92Ê
\89ß
\82³
\82¹
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
994 pline("Ouch! You bump into a door.");
996 pline("
\82¢
\82Ä
\82Á
\81I
\93ª
\82ð
\94à
\82É
\82Ô
\82Â
\82¯
\82½
\81D");
997 exercise(A_DEX, FALSE);
1001 pline("That door is closed.");
1003 pline("
\94à
\82Í
\95Â
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D");
1005 } else if (mode == TEST_TRAV || mode == TEST_TRAP)
1011 if (dx && dy && !Passes_walls
1012 && (!doorless_door(x, y) || block_door(x, y))) {
1013 /* Diagonal moves into a door are not allowed. */
1014 if (mode == DO_MOVE) {
1016 feel_location(x, y);
1017 if (Underwater || iflags.mention_walls)
1018 You_cant("move diagonally into an intact doorway.");
1024 if (dx && dy && bad_rock(youmonst.data, ux, y)
1025 && bad_rock(youmonst.data, x, uy)) {
1026 /* Move at a diagonal. */
1027 switch (cant_squeeze_thru(&youmonst)) {
1029 if (mode == DO_MOVE)
1031 You("cannot pass that way.");
1033 You("
\92Ê
\82è
\82Ê
\82¯
\82Å
\82«
\82È
\82¢
\81D");
1036 if (mode == DO_MOVE)
1038 You("are carrying too much to get through.");
1040 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1043 if (mode == DO_MOVE)
1045 Your("body is too large to fit through.");
1047 Your("
\91Ì
\82ª
\91å
\82«
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1050 break; /* can squeeze through */
1052 } else if (dx && dy && worm_cross(ux, uy, x, y)) {
1053 /* consecutive long worm segments are at <ux,y> and <x,uy> */
1054 if (mode == DO_MOVE)
1056 pline("%s is in your way.", Monnam(m_at(ux, y)));
1058 pline("
\93¹
\82Ì
\93r
\92\86\82É%s
\82ª
\82¢
\82é
\81D", Monnam(m_at(ux, y)));
1061 /* Pick travel path that does not require crossing a trap.
1062 * Avoid water and lava using the usual running rules.
1063 * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
1064 if (context.run == 8 && (mode != DO_MOVE)
1065 && (x != u.ux || y != u.uy)) {
1066 struct trap *t = t_at(x, y);
1069 || (!Levitation && !Flying && !is_clinger(youmonst.data)
1070 && is_pool_or_lava(x, y) && levl[x][y].seenv))
1071 return (mode == TEST_TRAP);
1074 if (mode == TEST_TRAP)
1075 return FALSE; /* do not move through traps */
1077 ust = &levl[ux][uy];
1079 /* Now see if other things block our way . . */
1080 if (dx && dy && !Passes_walls && IS_DOOR(ust->typ)
1081 && (!doorless_door(ux, uy) || block_entry(x, y))) {
1082 /* Can't move at a diagonal out of a doorway with door. */
1083 if (mode == DO_MOVE && iflags.mention_walls)
1084 You_cant("move diagonally out of an intact doorway.");
1088 if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
1089 if (!(Blind || Hallucination) && (context.run >= 2)
1090 && mode != TEST_TRAV) {
1091 if (mode == DO_MOVE && iflags.mention_walls)
1092 pline("A boulder blocks your path.");
1095 if (mode == DO_MOVE) {
1096 /* tunneling monsters will chew before pushing */
1097 if (tunnels(youmonst.data) && !needspick(youmonst.data)
1099 if (still_chewing(x, y))
1101 } else if (moverock() < 0)
1103 } else if (mode == TEST_TRAV) {
1106 /* never travel through boulders in Sokoban */
1110 /* don't pick two boulders in a row, unless there's a way thru */
1111 if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
1113 && !(tunnels(youmonst.data) && !needspick(youmonst.data))
1114 && !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK)
1115 && !((obj = carrying(WAN_DIGGING))
1116 && !objects[obj->otyp].oc_name_known))
1120 /* assume you'll be able to push it when you get there... */
1123 /* OK, it is a legal place to move. */
1128 static boolean trav_debug = FALSE;
1130 /* in this case, toggle display of travel debug info */
1131 int wiz_debug_cmd_traveldisplay()
1133 trav_debug = !trav_debug;
1139 * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
1140 * A shortest path is returned. If guess is TRUE, consider various
1141 * inaccessible locations as valid intermediate path points.
1142 * Returns TRUE if a path was found.
1145 findtravelpath(mode)
1148 /* if travel to adjacent, reachable location, use normal movement rules */
1149 if ((mode == TRAVP_TRAVEL || mode == TRAVP_VALID) && context.travel1
1150 && distmin(u.ux, u.uy, u.tx, u.ty) == 1
1151 && !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
1153 if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
1154 if (mode == TRAVP_TRAVEL) {
1158 iflags.travelcc.x = iflags.travelcc.y = -1;
1162 if (mode == TRAVP_TRAVEL)
1165 if (u.tx != u.ux || u.ty != u.uy) {
1166 xchar travel[COLNO][ROWNO];
1167 xchar travelstepx[2][COLNO * ROWNO];
1168 xchar travelstepy[2][COLNO * ROWNO];
1169 xchar tx, ty, ux, uy;
1170 int n = 1; /* max offset in travelsteps */
1171 int set = 0; /* two sets current and previous */
1172 int radius = 1; /* search radius */
1175 /* If guessing, first find an "obvious" goal location. The obvious
1176 * goal is the position the player knows of, or might figure out
1177 * (couldsee) that is closest to the target on a straight path.
1179 if (mode == TRAVP_GUESS || mode == TRAVP_VALID) {
1192 (void) memset((genericptr_t) travel, 0, sizeof(travel));
1193 travelstepx[0][0] = tx;
1194 travelstepy[0][0] = ty;
1199 for (i = 0; i < n; i++) {
1201 int x = travelstepx[set][i];
1202 int y = travelstepy[set][i];
1203 static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
1204 /* no diagonal movement for grid bugs */
1205 int dirmax = NODIAG(u.umonnum) ? 4 : 8;
1206 boolean alreadyrepeated = FALSE;
1208 for (dir = 0; dir < dirmax; ++dir) {
1209 int nx = x + xdir[ordered[dir]];
1210 int ny = y + ydir[ordered[dir]];
1213 * When guessing and trying to travel as close as possible
1214 * to an unreachable target space, don't include spaces
1215 * that would never be picked as a guessed target in the
1216 * travel matrix describing hero-reachable spaces.
1217 * This stops travel from getting confused and moving
1218 * the hero back and forth in certain degenerate
1219 * configurations of sight-blocking obstacles, e.g.
1221 * T 1. Dig this out and carry enough to not be
1222 * #### able to squeeze through diagonal gaps.
1223 * #--.--- Stand at @ and target travel at space T.
1227 * T 2. couldsee() marks spaces marked a and x
1228 * #### as eligible guess spaces to move the hero
1229 * a--.--- towards. Space a is closest to T, so it
1230 * @xxxxx gets chosen. Travel system moves @ right
1231 * |xxxxx to travel to space a.
1233 * T 3. couldsee() marks spaces marked b, c and x
1234 * #### as eligible guess spaces to move the hero
1235 * a--c--- towards. Since findtravelpath() is called
1236 * b@xxxx repeatedly during travel, it doesn't
1237 * |xxxxx remember that it wanted to go to space a,
1238 * so in comparing spaces b and c, b is
1239 * chosen, since it seems like the closest
1240 * eligible space to T. Travel system moves @
1241 * left to go to space b.
1245 * By limiting the travel matrix here, space a in the
1246 * example above is never included in it, preventing
1250 || ((mode == TRAVP_GUESS) && !couldsee(nx, ny)))
1252 if ((!Passes_walls && !can_ooze(&youmonst)
1253 && closed_door(x, y)) || sobj_at(BOULDER, x, y)
1254 || test_move(x, y, nx-x, ny-y, TEST_TRAP)) {
1255 /* closed doors and boulders usually
1256 * cause a delay, so prefer another path */
1257 if (travel[x][y] > radius - 3) {
1258 if (!alreadyrepeated) {
1259 travelstepx[1 - set][nn] = x;
1260 travelstepy[1 - set][nn] = y;
1261 /* don't change travel matrix! */
1263 alreadyrepeated = TRUE;
1268 if (test_move(x, y, nx - x, ny - y, TEST_TRAV)
1269 && (levl[nx][ny].seenv
1270 || (!Blind && couldsee(nx, ny)))) {
1271 if (nx == ux && ny == uy) {
1272 if (mode == TRAVP_TRAVEL || mode == TRAVP_VALID) {
1275 if (mode == TRAVP_TRAVEL
1276 && x == u.tx && y == u.ty) {
1278 /* reset run so domove run checks work */
1280 iflags.travelcc.x = iflags.travelcc.y = -1;
1284 } else if (!travel[nx][ny]) {
1285 travelstepx[1 - set][nn] = nx;
1286 travelstepy[1 - set][nn] = ny;
1287 travel[nx][ny] = radius;
1296 /* Use of warning glyph is arbitrary. It stands out. */
1297 tmp_at(DISP_ALL, warning_to_glyph(1));
1298 for (i = 0; i < nn; ++i) {
1299 tmp_at(travelstepx[1 - set][i], travelstepy[1 - set][i]);
1302 if (flags.runmode == RUN_CRAWL) {
1306 tmp_at(DISP_END, 0);
1315 /* if guessing, find best location in travel matrix and go there */
1316 if (mode == TRAVP_GUESS) {
1317 int px = tx, py = ty; /* pick location */
1318 int dist, nxtdist, d2, nd2;
1320 dist = distmin(ux, uy, tx, ty);
1321 d2 = dist2(ux, uy, tx, ty);
1322 for (tx = 1; tx < COLNO; ++tx)
1323 for (ty = 0; ty < ROWNO; ++ty)
1324 if (travel[tx][ty]) {
1325 nxtdist = distmin(ux, uy, tx, ty);
1326 if (nxtdist == dist && couldsee(tx, ty)) {
1327 nd2 = dist2(ux, uy, tx, ty);
1329 /* prefer non-zigzag path */
1334 } else if (nxtdist < dist && couldsee(tx, ty)) {
1338 d2 = dist2(ux, uy, tx, ty);
1342 if (px == u.ux && py == u.uy) {
1343 /* no guesses, just go in the general direction */
1344 u.dx = sgn(u.tx - u.ux);
1345 u.dy = sgn(u.ty - u.uy);
1346 if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
1352 /* Use of warning glyph is arbitrary. It stands out. */
1353 tmp_at(DISP_ALL, warning_to_glyph(2));
1356 if (flags.runmode == RUN_CRAWL) {
1362 tmp_at(DISP_END, 0);
1371 mode = TRAVP_TRAVEL;
1385 is_valid_travelpt(x,y)
1391 int g = glyph_at(x,y);
1392 if (x == u.ux && y == u.uy)
1394 if (isok(x,y) && glyph_is_cmap(g) && S_stone == glyph_to_cmap(g)
1395 && !levl[x][y].seenv)
1399 ret = findtravelpath(TRAVP_VALID);
1405 /* try to escape being stuck in a trapped state by walking out of it;
1406 return true iff moving should continue to intended destination
1407 (all failures and most successful escapes leave hero at original spot) */
1409 trapmove(x, y, desttrap)
1410 int x, y; /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
1411 struct trap *desttrap; /* nonnull if another trap at <x,y> */
1413 boolean anchored = FALSE;
1414 const char *predicament, *culprit;
1415 char *steedname = !u.usteed ? (char *) 0 : y_monnam(u.usteed);
1418 return TRUE; /* sanity check */
1420 switch (u.utraptype) {
1422 if (flags.verbose) {
1424 predicament = "caught in a bear trap";
1426 predicament = "
\8cF
\82Ìã©
\82É
\82Â
\82©
\82Ü
\82Á
\82½";
1429 Norep("%s is %s.", upstart(steedname), predicament);
1431 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1434 Norep("You are %s.", predicament);
1436 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1438 /* [why does diagonal movement give quickest escape?] */
1439 if ((u.dx && u.dy) || !rn2(5))
1445 if (desttrap && desttrap->tseen
1446 && (desttrap->ttyp == PIT || desttrap->ttyp == SPIKED_PIT))
1447 return TRUE; /* move into adjacent pit */
1448 /* try to escape; position stays same regardless of success */
1452 if (uwep && uwep->oartifact == ART_STING) {
1455 pline("Sting cuts through the web!");
1457 pline("
\83X
\83e
\83B
\83\93\83O
\82Í
\82
\82à
\82Ì
\91\83\82ð
\90Ø
\82è
\82³
\82¢
\82½
\81I");
1458 break; /* escape trap but don't move */
1461 if (flags.verbose) {
1463 predicament = "stuck to the web";
1465 predicament = "
\82
\82à
\82Ì
\91\83\82É
\82Ð
\82Á
\82©
\82©
\82Á
\82½";
1468 Norep("%s is %s.", upstart(steedname), predicament);
1470 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1473 Norep("You are %s.", predicament);
1475 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1480 pline("%s breaks out of the web.", upstart(steedname));
1482 pline("%s
\82Í
\82
\82à
\82Ì
\91\83\82ð
\89ó
\82µ
\82½
\81D", upstart(steedname));
1485 You("disentangle yourself.");
1487 You("
\8e©
\95ª
\82Å
\82Ù
\82Ç
\82¢
\82½
\81D");
1491 if (flags.verbose) {
1493 predicament = "stuck in the lava";
1495 predicament = "
\97n
\8aâ
\82É
\82Í
\82Ü
\82Á
\82½";
1498 Norep("%s is %s.", upstart(steedname), predicament);
1500 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1503 Norep("You are %s.", predicament);
1505 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1507 if (!is_lava(x, y)) {
1509 if ((u.utrap & 0xff) == 0) {
1513 You("lead %s to the edge of the %s.", steedname,
1516 You("%s
\82ð%s
\82Ì
\92[
\82Ü
\82Å
\93±
\82¢
\82½
\81D", steedname,
1517 hliquid("
\97n
\8aâ"));
1521 You("pull yourself to the edge of the %s.",
1524 You("%s
\82Ì
\92[
\82Ü
\82Å
\82©
\82ë
\82¤
\82¶
\82Ä
\81C
\82½
\82Ç
\82è
\82Â
\82¢
\82½
\81D",
1525 hliquid("
\97n
\8aâ"));
1533 anchored = (u.utraptype == TT_BURIEDBALL);
1537 cc.x = u.ux, cc.y = u.uy;
1538 /* can move normally within radius 1 of buried ball */
1539 if (buried_ball(&cc) && dist2(x, y, cc.x, cc.y) <= 2) {
1540 /* ugly hack: we need to issue some message here
1541 in case "you are chained to the buried ball"
1542 was the most recent message given, otherwise
1543 our next attempt to move out of tether range
1544 after this successful move would have its
1545 can't-do-that message suppressed by Norep */
1548 Norep("You move within the chain's reach.");
1550 Norep("
\8d½
\82ª
\93Í
\82
\94Í
\88Í
\82É
\88Ú
\93®
\82Å
\82«
\82é
\81D");
1555 if (flags.verbose) {
1558 predicament = "chained to the";
1559 culprit = "buried ball";
1561 predicament = "
\82Æ
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é";
1562 culprit = "
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é
\8b\85";
1566 predicament = "stuck in the";
1567 culprit = surface(u.ux, u.uy);
1569 predicament = "
\82É
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é";
1570 culprit = surface(u.ux, u.uy);
1576 Norep("You and %s are %s %s.", steedname, predicament,
1579 Norep("
\82 \82È
\82½
\82Æ%s
\82Í%s%s
\81D", steedname, culprit,
1584 Norep("%s is %s %s.", upstart(steedname), predicament,
1587 Norep("%s
\82Í%s%s
\81D", steedname, culprit,
1592 Norep("You are %s %s.", predicament, culprit);
1594 Norep("
\82 \82È
\82½
\82Í%s
\82É%s
\81D", culprit, predicament);
1600 pline("%s finally %s free.", upstart(steedname),
1601 !anchored ? "lurches" : "wrenches the ball");
1603 pline("%s
\82Í%s
\82â
\82Á
\82Æ
\8e©
\97R
\82É
\82È
\82Á
\82½
\81D", upstart(steedname),
1604 !anchored ? "
\82à
\82ª
\82¢
\82Ä" : "
\93S
\8b\85\82ð
\82à
\82¬
\8eæ
\82Á
\82Ä");
1608 You("finally %s free.",
1609 !anchored ? "wriggle" : "wrench the ball");
1611 You("%s
\82â
\82Á
\82Æ
\8e©
\97R
\82É
\82È
\82Á
\82½
\81D",
1612 !anchored ? "
\82à
\82ª
\82¢
\82Ä" : "
\93S
\8b\85\82ð
\82à
\82¬
\8eæ
\82Á
\82Ä");
1615 buried_ball_to_punishment();
1619 impossible("trapmove: stuck in unknown trap? (%d)",
1629 if (!youmonst.data->mmove) {
1631 You("are rooted %s.",
1632 Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
1636 You("
\82»
\82Ì
\8fê
\82É
\97§
\82¿
\82·
\82
\82ñ
\82¾
\81D");
1647 register struct monst *mtmp;
1648 register struct rm *tmpr;
1649 register xchar x, y;
1650 struct trap *trap = NULL;
1653 xchar chainx = 0, chainy = 0,
1654 ballx = 0, bally = 0; /* ball&chain new positions */
1655 int bc_control = 0; /* control for ball&chain */
1656 boolean cause_delay = FALSE; /* dragging ball will skip a move */
1658 u_wipe_engr(rnd(5));
1660 if (context.travel) {
1661 if (!findtravelpath(FALSE))
1662 (void) findtravelpath(TRUE);
1663 context.travel1 = 0;
1666 if (((wtcap = near_capacity()) >= OVERLOADED
1667 || (wtcap > SLT_ENCUMBER
1668 && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1669 : (u.uhp < 10 && u.uhp != u.uhpmax))))
1670 && !Is_airlevel(&u.uz)) {
1671 if (wtcap < OVERLOADED) {
1673 You("don't have enough stamina to move.");
1675 You("
\82Ö
\82Æ
\82Ö
\82Æ
\82Å
\93®
\82¯
\82È
\82¢
\81D");
1676 exercise(A_CON, FALSE);
1679 You("collapse under your load.");
1681 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\93|
\82ê
\82½
\81D");
1687 u.ux = x = u.ustuck->mx;
1688 u.uy = y = u.ustuck->my;
1691 if (Is_airlevel(&u.uz) && rn2(4) && !Levitation && !Flying) {
1695 You("tumble in place.");
1697 You("
\82»
\82Ì
\8fê
\82Å
\93|
\82ê
\82½
\81D");
1698 exercise(A_DEX, FALSE);
1702 You_cant("control your movements very well.");
1704 You("
\82¤
\82Ü
\82
\95à
\82¯
\82È
\82¢
\81D");
1708 pline("It's hard to walk in thin air.");
1710 pline("
\8bó
\92\86\82ð
\95à
\82
\82Ì
\82Í
\93ï
\82µ
\82¢
\81D");
1711 exercise(A_DEX, TRUE);
1717 /* check slippery ice */
1718 on_ice = !Levitation && is_ice(u.ux, u.uy);
1720 static int skates = 0;
1723 skates = find_skates();
1724 if ((uarmf && uarmf->otyp == skates) || resists_cold(&youmonst)
1725 || Flying || is_floater(youmonst.data)
1726 || is_clinger(youmonst.data) || is_whirly(youmonst.data)) {
1728 } else if (!rn2(Cold_resistance ? 3 : 2)) {
1729 HFumbling |= FROMOUTSIDE;
1730 HFumbling &= ~TIMEOUT;
1731 HFumbling += 1; /* slip on next move */
1734 if (!on_ice && (HFumbling & FROMOUTSIDE))
1735 HFumbling &= ~FROMOUTSIDE;
1739 if (Stunned || (Confusion && !rn2(5))) {
1740 register int tries = 0;
1750 } while (!isok(x, y) || bad_rock(youmonst.data, x, y));
1752 /* turbulence might alter your actual destination */
1755 if (!u.dx && !u.dy) {
1766 if (((trap = t_at(x, y)) && trap->tseen)
1767 || (Blind && !Levitation && !Flying && !is_clinger(youmonst.data)
1768 && is_pool_or_lava(x, y) && levl[x][y].seenv)) {
1769 if (context.run >= 2) {
1770 if (iflags.mention_walls) {
1771 if (trap && trap->tseen) {
1772 int tt = what_trap(trap->ttyp);
1773 You("stop in front of %s.",
1774 an(defsyms[trap_to_defsym(tt)].explanation));
1775 } else if (is_pool_or_lava(x,y) && levl[x][y].seenv) {
1776 You("stop at the edge of the %s.",
1777 hliquid(is_pool(x,y) ? "water" : "lava"));
1787 if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
1788 if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
1789 /* perhaps it fled (or was teleported or ... ) */
1791 } else if (sticks(youmonst.data)) {
1792 /* When polymorphed into a sticking monster,
1793 * u.ustuck means it's stuck to you, not you to it.
1796 You("release %s.", mon_nam(u.ustuck));
1798 You("%s
\82ð
\95ú
\82µ
\82½
\81D", mon_nam(u.ustuck));
1801 /* If holder is asleep or paralyzed:
1802 * 37.5% chance of getting away,
1803 * 12.5% chance of waking/releasing it;
1805 * 7.5% chance of getting away.
1806 * [strength ought to be a factor]
1807 * If holder is tame and there is no conflict,
1808 * guaranteed escape.
1810 switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
1816 You("pull free from %s.", mon_nam(u.ustuck));
1818 You("%s
\82ð
\82Ð
\82«
\82Í
\82È
\82µ
\82½
\81D", mon_nam(u.ustuck));
1822 if (!u.ustuck->mcanmove) {
1823 /* it's free to move on next turn */
1824 u.ustuck->mfrozen = 1;
1825 u.ustuck->msleeping = 0;
1829 if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf)
1832 You("cannot escape from %s!", mon_nam(u.ustuck));
1834 You("%s
\82©
\82ç
\93¦
\82°
\82ç
\82ê
\82È
\82¢
\81I", mon_nam(u.ustuck));
1842 if (mtmp && !is_safepet(mtmp)) {
1843 /* Don't attack if you're running, and can see it */
1844 /* It's fine to displace pets, though */
1845 /* We should never get here if forcefight */
1846 if (context.run && ((!Blind && mon_visible(mtmp)
1847 && ((mtmp->m_ap_type != M_AP_FURNITURE
1848 && mtmp->m_ap_type != M_AP_OBJECT)
1849 || Protection_from_shape_changers))
1850 || sensemon(mtmp))) {
1864 /* attack monster */
1866 /* don't stop travel when displacing pets; if the
1867 displace fails for some reason, attack() in uhitm.c
1868 will stop travel rather than domove */
1869 if (!is_safepet(mtmp) || context.forcefight)
1871 /* only attack if we know it's there */
1872 /* or if we used the 'F' command to fight blindly */
1873 /* or if it hides_under, in which case we call attack() to print
1874 * the Wait! message.
1875 * This is different from ceiling hiders, who aren't handled in
1879 /* If they used a 'm' command, trying to move onto a monster
1880 * prints the below message and wastes a turn. The exception is
1881 * if the monster is unseen and the player doesn't remember an
1882 * invisible monster--then, we fall through to attack() and
1883 * attack_check(), which still wastes a turn, but prints a
1884 * different message and makes the player remember the monster.
1886 if (context.nopick && !context.travel
1887 && (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))) {
1888 if (mtmp->m_ap_type && !Protection_from_shape_changers
1890 stumble_onto_mimic(mtmp);
1891 else if (mtmp->mpeaceful && !Hallucination)
1892 /* m_monnam(): "dog" or "Fido", no "invisible dog" or "it" */
1894 pline("Pardon me, %s.", m_monnam(mtmp));
1896 pline("
\82¿
\82å
\82Á
\82Æ
\82²
\82ß
\82ñ
\82È
\82³
\82¢
\82æ
\81C%s
\82³
\82ñ
\81D", m_monnam(mtmp));
1899 You("move right into %s.", mon_nam(mtmp));
1901 You("%s
\82Ì
\82»
\82Î
\82É
\88Ú
\93®
\82µ
\82½
\81D", mon_nam(mtmp));
1904 if (context.forcefight || !mtmp->mundetected || sensemon(mtmp)
1905 || ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)
1906 && !is_safepet(mtmp))) {
1907 /* try to attack; note that it might evade */
1908 /* also, we don't attack tame when _safepet_ */
1914 if (context.forcefight && levl[x][y].typ == IRONBARS && uwep) {
1915 struct obj *obj = uwep;
1917 if (breaktest(obj)) {
1919 obj = splitobj(obj, 1L);
1921 setuwep((struct obj *)0);
1924 hit_bars(&obj, u.ux, u.uy, x, y, TRUE, TRUE);
1928 /* specifying 'F' with no monster wastes a turn */
1929 if (context.forcefight
1930 /* remembered an 'I' && didn't use a move command */
1931 || (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
1932 struct obj *boulder = 0;
1933 boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
1934 solid = !accessible(x, y);
1935 int glyph = glyph_at(x, y); /* might be monster */
1939 boulder = sobj_at(BOULDER, x, y);
1940 /* if a statue is displayed at the target location,
1941 player is attempting to attack it [and boulder
1942 handling below is suitable for handling that] */
1943 if (glyph_is_statue(glyph)
1944 || (Hallucination && glyph_is_monster(glyph)))
1945 boulder = sobj_at(STATUE, x, y);
1947 /* force fight at boulder/statue or wall/door while wielding
1948 pick: start digging to break the boulder or wall */
1949 if (context.forcefight
1951 && uwep && dig_typ(uwep, x, y)
1952 /* should we dig? */
1953 && !glyph_is_invisible(glyph) && !glyph_is_monster(glyph)) {
1954 (void) use_pick_axe2(uwep);
1959 /* about to become known empty -- remove 'I' if present */
1962 map_object(boulder, TRUE);
1964 glyph = glyph_at(x, y); /* might have just changed */
1967 Strcpy(buf, ansimpleoname(boulder));
1968 } else if (Underwater && !is_pool(x, y)) {
1969 /* Underwater, targetting non-water; the map just shows blank
1970 because you don't see remembered terrain while underwater;
1971 although the hero can attack an adjacent monster this way,
1972 assume he can't reach out far enough to distinguish terrain */
1974 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
1978 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
1979 ? "
\8bó
\8bC
\82Ì
\96A"
1980 : "
\89½
\82à
\82È
\82¢
\82Æ
\82±
\82ë");
1983 /* glyph might indicate unseen terrain if hero is blind;
1984 unlike searching, this won't reveal what that terrain is
1985 (except for solid rock, where the glyph would otherwise
1986 yield ludicrous "dark part of a room") */
1988 Strcpy(buf, (levl[x][y].typ == STONE) ? "solid rock"
1989 : glyph_is_cmap(glyph)
1990 ? the(defsyms[glyph_to_cmap(glyph)].explanation)
1991 : (const char *) "an unknown obstacle");
1993 Strcpy(buf, (levl[x][y].typ == STONE) ? "
\90Î"
1994 : glyph_is_cmap(glyph)
1995 ? the(defsyms[glyph_to_cmap(glyph)].explanation)
1996 : (const char *) "
\95s
\96¾
\82È
\8fá
\8aQ
\95¨");
1998 /* note: 'solid' is misleadingly named and catches pools
1999 of water and lava as well as rock and walls */
2002 Strcpy(buf, "thin air");
2004 Strcpy(buf, "
\89½
\82à
\82È
\82¢
\8bó
\92\86");
2008 !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
2009 explo ? "explode at" : "attack", buf);
2012 !(boulder || solid) ? "" : !explo ? "
\8cø
\89Ê
\82È
\82" : "
\82Þ
\82¾
\82É",
2013 buf, explo ? "
\82Å
\94\9a\94
\82µ
\82½" : "
\82ð
\8dU
\8c\82\82µ
\82½");
2019 u.mh = -1; /* dead in the current form */
2024 (void) unmap_invisible(x, y);
2025 /* not attacking an animal, so we try to move */
2026 if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
2035 if (!trapmove(x, y, trap))
2039 if (!test_move(u.ux, u.uy, x - u.ux, y - u.uy, DO_MOVE)) {
2040 if (!context.door_opened) {
2047 /* Move ball and chain. */
2049 if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy,
2050 &cause_delay, TRUE))
2053 /* Check regions entering/leaving */
2054 if (!in_out_region(x, y))
2057 /* now move the hero */
2061 /* Move your steed, too */
2063 u.usteed->mx = u.ux;
2064 u.usteed->my = u.uy;
2069 * If safepet at destination then move the pet to the hero's
2070 * previous location using the same conditions as in attack().
2071 * there are special extenuating circumstances:
2072 * (1) if the pet dies then your god angers,
2073 * (2) if the pet gets trapped then your god may disapprove,
2074 * (3) if the pet was already trapped and you attempt to free it
2075 * not only do you encounter the trap but you may frighten your
2076 * pet causing it to go wild! moral: don't abuse this privilege.
2078 * Ceiling-hiding pets are skipped by this section of code, to
2079 * be caught by the normal falling-monster code.
2081 if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
2082 /* if trapped, there's a chance the pet goes wild */
2083 if (mtmp->mtrapped) {
2084 if (!rn2(mtmp->mtame)) {
2085 mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
2087 m_unleash(mtmp, TRUE);
2094 /* seemimic/newsym should be done before moving hero, otherwise
2095 the display code will draw the hero here before we possibly
2096 cancel the swap below (we can ignore steed mx,my here) */
2097 u.ux = u.ux0, u.uy = u.uy0;
2098 mtmp->mundetected = 0;
2099 if (mtmp->m_ap_type)
2101 else if (!mtmp->mtame)
2102 newsym(mtmp->mx, mtmp->my);
2103 u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
2105 if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
2106 && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
2107 && sobj_at(BOULDER, trap->tx, trap->ty)) {
2108 /* can't swap places with pet pinned in a pit by a boulder */
2109 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
2111 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2112 } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
2113 /* can't swap places when pet can't move to your spot */
2114 u.ux = u.ux0, u.uy = u.uy0;
2116 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2118 You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp)));
2120 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\8eÎ
\82ß
\82É
\93®
\82¯
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
2121 } else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0)
2122 && bad_rock(mtmp->data, u.ux0, y)
2123 && (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
2124 /* can't swap places when pet won't fit thru the opening */
2125 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
2127 u.usteed->mx = u.ux, u.usteed->my = u.uy;
2129 You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
2131 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
2133 char pnambuf[BUFSZ];
2135 /* save its current description in case of polymorph */
2136 Strcpy(pnambuf, y_monnam(mtmp));
2138 remove_monster(x, y);
2139 place_monster(mtmp, u.ux0, u.uy0);
2141 newsym(u.ux0, u.uy0);
2144 You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
2149 mtmp->mtame ? "
\82Æ
\8fê
\8f\8a\82ð
\93ü
\82ê
\8a·
\82í
\82Á" : "
\82ð
\95|
\82ª
\82ç
\82¹");
2152 /* check for displacing it into pools and traps */
2153 switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
2156 case 1: /* trapped */
2157 case 3: /* changed levels */
2158 /* there's already been a trap message, reinforce it */
2163 /* drowned or died...
2164 * you killed your pet by direct action, so get experience
2165 * and possibly penalties;
2166 * we want the level gain message, if it happens, to occur
2167 * before the guilt message below
2170 /* minliquid() and mintrap() call mondead() rather than
2171 killed() so we duplicate some of the latter here */
2174 u.uconduct.killer++;
2175 mndx = monsndx(mtmp->data);
2176 tmp = experience(mtmp, (int) mvitals[mndx].died);
2177 more_experienced(tmp, 0);
2178 newexplevel(); /* will decide if you go up */
2180 /* That's no way to treat a pet! Your god gets angry.
2182 * [This has always been pretty iffy. Why does your
2183 * patron deity care at all, let alone enough to get mad?]
2187 You_feel("guilty about losing your pet like this.");
2189 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");
2195 pline("that's strange, unknown mintrap result!");
2201 reset_occupations();
2203 if (context.run < 8)
2204 if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ)
2205 || IS_FURNITURE(tmpr->typ))
2209 if (hides_under(youmonst.data) || youmonst.data->mlet == S_EEL
2211 (void) hideunder(&youmonst);
2214 * Mimics (or whatever) become noticeable if they move and are
2215 * imitating something that doesn't move. We could extend this
2216 * to non-moving monsters...
2218 if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
2219 || youmonst.m_ap_type == M_AP_FURNITURE))
2220 youmonst.m_ap_type = M_AP_NOTHING;
2222 check_leash(u.ux0, u.uy0);
2224 if (u.ux0 != u.ux || u.uy0 != u.uy) {
2226 /* Clean old position -- vision_recalc() will print our new one. */
2227 newsym(u.ux0, u.uy0);
2228 /* Since the hero has moved, adjust what can be seen/unseen. */
2229 vision_recalc(1); /* Do the work now in the recover time. */
2230 invocation_message();
2233 if (Punished) /* put back ball and chain */
2234 move_bc(0, bc_control, ballx, bally, chainx, chainy);
2239 /* delay next move because of ball dragging */
2240 /* must come after we finished picking up, in spoteffects() */
2244 multi_reason = "dragging an iron ball";
2246 multi_reason = "
\93S
\8b\85\82É
\88ø
\82«
\82¸
\82ç
\82ê
\82Ä
\82¢
\82é
\8e\9e\82É";
2250 if (context.run && flags.runmode != RUN_TPORT) {
2251 /* display every step or every 7th step depending upon mode */
2252 if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
2257 if (flags.runmode == RUN_CRAWL) {
2267 /* combat increases metabolism */
2271 /* this used to be part of domove() when moving to a monster's
2272 position, but is now called by attack() so that it doesn't
2273 execute if you decline to attack a peaceful monster */
2275 if ((moves % 3L) != 0L && near_capacity() >= HVY_ENCUMBER) {
2276 int *hp = (!Upolyd ? &u.uhp : &u.mh);
2282 You("pass out from exertion!");
2284 You("
\8bC
\90â
\82µ
\82½
\81D");
2285 exercise(A_CON, FALSE);
2286 fall_asleep(-10, FALSE);
2289 return (boolean) (multi < 0); /* might have fainted (forced to sleep) */
2293 invocation_message()
2295 /* a special clue-msg when on the Invocation position */
2296 if (invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
2298 struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
2300 nomul(0); /* stop running or travelling */
2303 Sprintf(buf, "beneath %s", y_monnam(u.usteed));
2305 Sprintf(buf, "%s
\82Ì
\89º
\82É", y_monnam(u.usteed));
2306 else if (Levitation || Flying)
2308 Strcpy(buf, "beneath you");
2310 Strcpy(buf, "
\89º
\95û
\82É");
2313 Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
2315 Strcpy(buf, "
\91«
\8c³
\82É");
2318 You_feel("a strange vibration %s.", buf);
2320 You("%s
\8aï
\96
\82È
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D", buf);
2321 u.uevent.uvibrated = 1;
2322 if (otmp && otmp->spe == 7 && otmp->lamplit)
2324 pline("%s %s!", The(xname(otmp)),
2325 Blind ? "throbs palpably" : "glows with a strange light");
2327 pline("%s
\82Í%s
\82µ
\82½
\81I", The(xname(otmp)),
2328 Blind ? "
\82©
\82·
\82©
\82É
\90U
\93®" : "
\8aï
\96
\82È
\8cõ
\82ð
\94");
2333 /* moving onto different terrain;
2334 might be going into solid rock, inhibiting levitation or flight,
2335 or coming back out of such, reinstating levitation/flying */
2339 struct rm *lev = &levl[u.ux][u.uy];
2340 boolean blocklev = (IS_ROCK(lev->typ) || closed_door(u.ux, u.uy)
2341 || (Is_waterlevel(&u.uz) && lev->typ == WATER));
2344 /* called from spoteffects(), skip float_down() */
2347 You_cant("levitate in here.");
2349 You_cant("
\82±
\82±
\82Å
\82Í
\95\82\97V
\82Å
\82«
\82È
\82¢
\81D");
2350 BLevitation |= FROMOUTSIDE;
2351 } else if (BLevitation) {
2352 BLevitation &= ~FROMOUTSIDE;
2356 /* the same terrain that blocks levitation also blocks flight */
2360 You_cant("fly in here.");
2362 You_cant("
\82±
\82±
\82Å
\82Í
\94ò
\82×
\82È
\82¢
\81D");
2363 BFlying |= FROMOUTSIDE;
2364 } else if (BFlying) {
2365 BFlying &= ~FROMOUTSIDE;
2366 float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
2367 /* [minor bug: we don't know whether this is beginning flight or
2368 resuming it; that could be tracked so that this message could
2369 be adjusted to "resume flying", but isn't worth the effort...] */
2372 You("start flying.");
2374 You("
\94ò
\82Ñ
\82Í
\82¶
\82ß
\82½
\81D");
2378 /* extracted from spoteffects; called by spoteffects to check for entering or
2379 leaving a pool of water/lava, and by moveloop to check for staying on one;
2380 returns true to skip rest of spoteffects */
2382 pooleffects(newspot)
2383 boolean newspot; /* true if called by spoteffects */
2385 /* check for leaving water */
2387 boolean still_inwater = FALSE; /* assume we're getting out */
2389 if (!is_pool(u.ux, u.uy)) {
2390 if (Is_waterlevel(&u.uz))
2392 You("pop into an air bubble.");
2394 You("
\82Ð
\82å
\82¢
\82Æ
\8bó
\8bC
\82Ì
\96A
\82É
\93ü
\82Á
\82½
\81D");
2395 else if (is_lava(u.ux, u.uy))
2397 You("leave the %s...", hliquid("water")); /* oops! */
2399 You("%s
\90\85\82©
\82ç
\94²
\82¯
\82¾
\82µ
\82½
\81D
\81D
\81D", hliquid("
\90\85")); /* oops! */
2403 You("are on solid %s again.",
2404 is_ice(u.ux, u.uy) ? "ice" : "land");
2406 You("
\8cÅ
\82¢%s
\82Ì
\8fã
\82É
\82Ü
\82½
\96ß
\82Á
\82½
\81D",
2407 is_ice(u.ux, u.uy) ? "
\95X" : "
\92n
\96Ê");
2409 } else if (Is_waterlevel(&u.uz)) {
2410 still_inwater = TRUE;
2411 } else if (Levitation) {
2413 You("pop out of the %s like a cork!", hliquid("water"));
2415 You("
\83R
\83\8b\83N
\82Ì
\82æ
\82¤
\82É%s
\82©
\82ç
\94ò
\82Ñ
\82¾
\82µ
\82½
\81I", hliquid("
\90\85"));
2416 } else if (Flying) {
2418 You("fly out of the %s.", hliquid("water"));
2420 You("%s
\82©
\82ç
\94ò
\82Ñ
\82¾
\82µ
\82½
\81D", hliquid("
\90\85"));
2421 } else if (Wwalking) {
2423 You("slowly rise above the surface.");
2425 You("
\82ä
\82Á
\82
\82è
\90\85\96Ê
\82Ü
\82Å
\8fã
\82ª
\82Á
\82½
\81D");
2427 still_inwater = TRUE;
2429 if (!still_inwater) {
2430 boolean was_underwater = (Underwater && !Is_waterlevel(&u.uz));
2432 u.uinwater = 0; /* leave the water */
2433 if (was_underwater) { /* restore vision */
2435 vision_full_recalc = 1;
2440 /* check for entering water or lava */
2441 if (!u.ustuck && !Levitation && !Flying && is_pool_or_lava(u.ux, u.uy)) {
2443 && (is_flyer(u.usteed->data) || is_floater(u.usteed->data)
2444 || is_clinger(u.usteed->data))) {
2445 /* floating or clinging steed keeps hero safe (is_flyer() test
2446 is redundant; it can't be true since Flying yielded false) */
2448 } else if (u.usteed) {
2449 /* steed enters pool */
2450 dismount_steed(Underwater ? DISMOUNT_FELL : DISMOUNT_GENERIC);
2451 /* dismount_steed() -> float_down() -> pickup()
2452 (float_down doesn't do autopickup on Air or Water) */
2453 if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
2455 /* even if we actually end up at same location, float_down()
2456 has already done spoteffect()'s trap and pickup actions */
2458 check_special_room(FALSE); /* spoteffects */
2463 /* drown(),lava_effects() return true if hero changes
2464 location while surviving the problem */
2465 if (is_lava(u.ux, u.uy)) {
2468 } else if (!Wwalking
2469 && (newspot || !u.uinwater || !(Swimming || Amphibious))) {
2481 static int inspoteffects = 0;
2482 static coord spotloc;
2483 static int spotterrain;
2484 static struct trap *spottrap = (struct trap *) 0;
2485 static unsigned spottraptyp = NO_TRAP;
2488 struct trap *trap = t_at(u.ux, u.uy);
2490 /* prevent recursion from affecting the hero all over again
2491 [hero poly'd to iron golem enters water here, drown() inflicts
2492 damage that triggers rehumanize() which calls spoteffects()...] */
2493 if (inspoteffects && u.ux == spotloc.x && u.uy == spotloc.y
2494 /* except when reason is transformed terrain (ice -> water) */
2495 && spotterrain == levl[u.ux][u.uy].typ
2496 /* or transformed trap (land mine -> pit) */
2497 && (!spottrap || !trap || trap->ttyp == spottraptyp))
2501 spotterrain = levl[u.ux][u.uy].typ;
2502 spotloc.x = u.ux, spotloc.y = u.uy;
2504 /* moving onto different terrain might cause Levitation to toggle */
2505 if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
2508 if (pooleffects(TRUE))
2511 check_special_room(FALSE);
2512 if (IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
2514 if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
2517 /* if levitation is due to time out at the end of this
2518 turn, allowing it to do so could give the perception
2519 that a trap here is being triggered twice, so adjust
2520 the timeout to prevent that */
2521 if (trap && (HLevitation & TIMEOUT) == 1L
2522 && !(ELevitation || (HLevitation & ~(I_SPECIAL | TIMEOUT)))) {
2523 if (rn2(2)) { /* defer timeout */
2524 incr_itimeout(&HLevitation, 1L);
2525 } else { /* timeout early */
2526 if (float_down(I_SPECIAL | TIMEOUT, 0L)) {
2527 /* levitation has ended; we've already triggered
2528 any trap and [usually] performed autopickup */
2535 * If not a pit, pickup before triggering trap.
2536 * If pit, trigger trap before pickup.
2538 pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
2544 * dotrap on a fire trap calls melt_ice() which triggers
2545 * spoteffects() (again) which can trigger the same fire
2546 * trap (again). Use static spottrap to prevent that.
2547 * We track spottraptyp because some traps morph
2548 * (landmine to pit) and any new trap type
2549 * should get triggered.
2551 if (!spottrap || spottraptyp != trap->ttyp) {
2553 spottraptyp = trap->ttyp;
2554 dotrap(trap, 0); /* fall into arrow trap, etc. */
2555 spottrap = (struct trap *) 0;
2556 spottraptyp = NO_TRAP;
2562 /* Warning alerts you to ice danger */
2563 if (Warning && is_ice(u.ux, u.uy)) {
2564 static const char *const icewarnings[] = {
2566 "The ice seems very soft and slushy.",
2567 "You feel the ice shift beneath you!",
2568 "The ice, is gonna BREAK!", /* The Dead Zone */
2570 "
\95X
\82Í
\82Æ
\82Ä
\82à
\93î
\82ç
\82©
\82
\82Ä
\97n
\82¯
\82»
\82¤
\82¾
\81D",
2571 "
\82 \82È
\82½
\82Ì
\89º
\82Ì
\95X
\82ª
\93®
\82¢
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81I",
2572 "
\95X
\82ª
\89ó
\82ê
\82é
\82¼
\81I", /* The Dead Zone */
2575 long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
2577 if (time_left && time_left < 15L)
2578 pline("%s", icewarnings[(time_left < 5L) ? 2
2579 : (time_left < 10L) ? 1
2582 if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
2583 mtmp->mundetected = mtmp->msleeping = 0;
2584 switch (mtmp->data->mlet) {
2587 pline("%s suddenly drops from the %s!", Amonnam(mtmp),
2588 ceiling(u.ux, u.uy));
2590 pline("%s
\82ª
\93Ë
\91R%s
\82©
\82ç
\97\8e\82¿
\82Ä
\82«
\82½
\81I", Amonnam(mtmp),
2591 ceiling(u.ux,u.uy));
2593 if (mtmp->mtame) { /* jumps to greet you, not attack */
2595 } else if (uarmh && is_metallic(uarmh)) {
2597 pline("Its blow glances off your %s.",
2599 pline("
\8dU
\8c\82\82Í
\82 \82È
\82½
\82Ì%s
\82ð
\82©
\82·
\82ß
\82½
\82¾
\82¯
\82¾
\82Á
\82½
\81D",
2600 helm_simple_name(uarmh));
2601 } else if (u.uac + 3 <= rnd(20)) {
2603 You("are almost hit by %s!",
2604 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2606 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",
2607 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2613 You("are hit by %s!",
2614 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2616 You("
\97\8e\82¿
\82Ä
\82«
\82½%s
\82É
\93\96\82½
\82Á
\82½
\81I",
2617 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2620 if (Half_physical_damage)
2621 dmg = (dmg + 1) / 2;
2622 mdamageu(mtmp, dmg);
2625 default: /* monster surprises you. */
2628 pline("%s jumps near you from the %s.", Amonnam(mtmp),
2629 ceiling(u.ux, u.uy));
2631 pline("%s
\82ª%s
\82©
\82ç
\82 \82È
\82½
\82Ì
\8bß
\82
\82É
\94ò
\82ñ
\82Å
\82«
\82½
\81D", Amonnam(mtmp),
2632 ceiling(u.ux,u.uy));
2634 else if (mtmp->mpeaceful) {
2638 You("%s
\82ð
\8bÁ
\82©
\82µ
\82½
\81I",
2639 Blind && !sensemon(mtmp) ? something : a_monnam(mtmp));
2640 mtmp->mpeaceful = 0;
2643 pline("%s attacks you by surprise!", Amonnam(mtmp));
2645 pline("%s
\82Í
\8bÁ
\82¢
\82Ä
\82 \82È
\82½
\82ð
\8dU
\8c\82\82µ
\82½
\81I", Amonnam(mtmp));
2648 mnexto(mtmp); /* have to move the monster */
2651 if (!--inspoteffects) {
2652 spotterrain = STONE; /* 0 */
2653 spotloc.x = spotloc.y = 0;
2658 /* returns first matching monster */
2659 STATIC_OVL struct monst *
2660 monstinroom(mdat, roomno)
2661 struct permonst *mdat;
2664 register struct monst *mtmp;
2666 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2667 if (DEADMONSTER(mtmp))
2669 if (mtmp->data == mdat
2670 && index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
2673 return (struct monst *) 0;
2677 in_rooms(x, y, typewanted)
2678 register xchar x, y;
2679 register int typewanted;
2682 char rno, *ptr = &buf[4];
2683 int typefound, min_x, min_y, max_x, max_y_offset, step;
2684 register struct rm *lev;
2686 #define goodtype(rno) \
2688 || (typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted \
2689 || (typewanted == SHOPBASE && typefound > SHOPBASE))
2691 switch (rno = levl[x][y].roomno) {
2700 default: /* i.e. a regular room # */
2710 else if (x >= COLNO)
2717 max_y_offset -= step;
2718 } else if ((min_y + max_y_offset) >= ROWNO)
2719 max_y_offset -= step;
2721 for (x = min_x; x <= max_x; x += step) {
2722 lev = &levl[x][min_y];
2724 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2728 if (y > max_y_offset)
2730 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2734 if (y > max_y_offset)
2736 if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
2743 /* is (x,y) in a town? */
2748 s_level *slev = Is_special(&u.uz);
2749 register struct mkroom *sroom;
2750 boolean has_subrooms = FALSE;
2752 if (!slev || !slev->flags.town)
2756 * See if (x,y) is in a room with subrooms, if so, assume it's the
2757 * town. If there are no subrooms, the whole level is in town.
2759 for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
2760 if (sroom->nsubrooms > 0) {
2761 has_subrooms = TRUE;
2762 if (inside_room(sroom, x, y))
2767 return !has_subrooms;
2772 register boolean newlev;
2774 char *ptr1, *ptr2, *ptr3, *ptr4;
2776 Strcpy(u.urooms0, u.urooms);
2777 Strcpy(u.ushops0, u.ushops);
2780 u.uentered[0] = '\0';
2782 u.ushops_entered[0] = '\0';
2783 Strcpy(u.ushops_left, u.ushops0);
2786 Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
2788 for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
2789 ptr4 = &u.ushops_entered[0];
2791 if (!index(u.urooms0, *ptr1))
2793 if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
2795 if (!index(u.ushops0, *ptr1))
2803 /* filter u.ushops0 -> u.ushops_left */
2804 for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
2805 if (!index(u.ushops, *ptr1))
2810 /* possibly deliver a one-time room entry message */
2812 check_special_room(newlev)
2813 register boolean newlev;
2815 register struct monst *mtmp;
2818 move_update(newlev);
2821 u_left_shop(u.ushops_left, newlev);
2823 if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
2824 return; /* no entrance messages necessary */
2826 /* Did we just enter a shop? */
2827 if (*u.ushops_entered)
2828 u_entered_shop(u.ushops_entered);
2830 for (ptr = &u.uentered[0]; *ptr; ptr++) {
2831 int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
2832 boolean msg_given = TRUE;
2834 /* Did we just enter some other special room? */
2835 /* vault.c insists that a vault remain a VAULT,
2836 * and temples should remain TEMPLEs,
2837 * but everything else gives a message only the first time */
2841 pline("Welcome to David's treasure zoo!");
2843 pline("
\83f
\83r
\83b
\83g
\95ó
\94 \93®
\95¨
\89\80\82É
\82æ
\82¤
\82±
\82»
\81I");
2847 pline("It %s rather %s down here.", Blind ? "feels" : "looks",
2848 Blind ? "humid" : "muddy");
2850 pline("
\82©
\82È
\82è%s
\81D",
2851 Blind ? "
\8e¼
\8bC
\82ª
\82 \82é
\8fê
\8f\8a\82Ì
\82æ
\82¤
\82¾"
2852 : "
\82Ç
\82ë
\82Ç
\82ë
\82µ
\82Ä
\82¢
\82é
\8fê
\8f\8a\82¾");
2857 You("enter an opulent throne room!");
2859 You("
\89Ø
\82â
\82©
\82È
\8bÊ
\8dÀ
\82Ì
\8aÔ
\82É
\93ü
\82Á
\82½
\81I");
2863 You("enter a leprechaun hall!");
2865 You("
\83\8c\83v
\83\89\83R
\81[
\83\93\83z
\81[
\83\8b\82É
\93ü
\82Á
\82½
\81I");
2870 const char *run = locomotion(youmonst.data, "Run");
2871 pline("%s away! %s away!", run, run);
2873 pline("
\93¦
\82°
\82ë
\81I
\93¦
\82°
\82ë
\81I");
2877 You("have an uncanny feeling...");
2879 You("
\95s
\8bC
\96¡
\82È
\8a´
\82¶
\82ª
\82µ
\82½
\81D
\81D
\81D");
2883 You("enter a giant beehive!");
2885 You("
\8b\90\91å
\82È
\96I
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2889 You("enter a disgusting nest!");
2891 You("
\82Þ
\82Á
\82Æ
\82·
\82é
\8fL
\82¢
\82Ì
\82·
\82é
\92¹
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2895 You("enter an anthole!");
2897 You("
\83A
\83\8a\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2900 if (monstinroom(&mons[PM_SOLDIER], roomno)
2901 || monstinroom(&mons[PM_SERGEANT], roomno)
2902 || monstinroom(&mons[PM_LIEUTENANT], roomno)
2903 || monstinroom(&mons[PM_CAPTAIN], roomno))
2905 You("enter a military barracks!");
2907 You("
\8cR
\91à
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81I");
2910 You("enter an abandoned barracks.");
2912 You("
\95ú
\92u
\82³
\82ê
\82½
\82Ü
\82Ü
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81D");
2915 struct monst *oracle = monstinroom(&mons[PM_ORACLE], roomno);
2917 if (!oracle->mpeaceful)
2919 verbalize("You're in Delphi, %s.", plname);
2921 verbalize("
\82¨
\82Ü
\82¦
\82Í
\83f
\83\8b\83t
\83@
\83C
\82Ì
\90_
\91õ
\8f\8a\82É
\82¢
\82é
\81D");
2924 verbalize("%s, %s, welcome to Delphi!",
2925 Hello((struct monst *) 0), plname);
2927 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",
2935 intemple(roomno + ROOMOFFSET);
2938 msg_given = (rt == TEMPLE);
2943 room_discovered(roomno);
2946 rooms[roomno].rtype = OROOM;
2947 if (!search_special(rt)) {
2948 /* No more room of that type */
2951 level.flags.has_court = 0;
2954 level.flags.has_swamp = 0;
2957 level.flags.has_morgue = 0;
2960 level.flags.has_zoo = 0;
2963 level.flags.has_barracks = 0;
2966 level.flags.has_temple = 0;
2969 level.flags.has_beehive = 0;
2973 if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
2974 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2975 if (DEADMONSTER(mtmp))
2977 if (!Stealth && !rn2(3))
2978 mtmp->msleeping = 0;
2986 /* the ',' command */
2990 int count, tmpcount;
2991 struct trap *traphere = t_at(u.ux, u.uy);
2993 /* awful kludge to work around parse()'s pre-decrement */
2994 count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
2995 multi = 0; /* always reset */
2996 /* uswallow case added by GAN 01/29/87 */
2998 if (!u.ustuck->minvent) {
2999 if (is_animal(u.ustuck->data)) {
3001 You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
3003 You("%s
\82Ì
\90ã
\82ð
\8fE
\82Á
\82½
\81D", mon_nam(u.ustuck));
3005 pline("But it's kind of slimy, so you drop it.");
3007 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");
3010 You("don't %s anything in here to pick up.",
3011 Blind ? "feel" : "see");
3013 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82ª
\82È
\82¢%s
\81D",
3014 Blind ? "
\82æ
\82¤
\82¾" : "");
3019 return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
3022 if (is_pool(u.ux, u.uy)) {
3023 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
3024 || (Flying && !Breathless)) {
3026 You("cannot dive into the %s to pick things up.",
3029 You("
\95¨
\82ð
\8fE
\82¢
\82 \82°
\82é
\82½
\82ß
\82É%s
\82É
\94ò
\82Ñ
\82±
\82ß
\82È
\82¢
\81D",
3033 } else if (!Underwater) {
3035 You_cant("even see the bottom, let alone pick up %s.", something);
3037 pline("
\92ê
\82³
\82¦
\8c©
\82¦
\82È
\82¢
\81C
\8fE
\82¤
\82Ì
\82Í
\82â
\82ß
\82æ
\82¤
\81D");
3041 if (is_lava(u.ux, u.uy)) {
3042 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
3043 || (Flying && !Breathless)) {
3045 You_cant("reach the bottom to pick things up.");
3047 You_cant("
\95¨
\82ð
\8fE
\82¢
\8fã
\82°
\82é
\82½
\82ß
\82É
\92ê
\82Ü
\82Å
\82¢
\82¯
\82È
\82¢
\81D");
3049 } else if (!likes_lava(youmonst.data)) {
3051 You("would burn to a crisp trying to pick things up.");
3053 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");
3057 if (!OBJ_AT(u.ux, u.uy)) {
3058 register struct rm *lev = &levl[u.ux][u.uy];
3060 if (IS_THRONE(lev->typ))
3062 pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
3064 pline("
\82±
\82ê
\82Í%s
\8fd
\82¢
\81I", lev->looted ? "
\82©
\82È
\82è" : "
\82·
\82²
\82");
3065 else if (IS_SINK(lev->typ))
3067 pline_The("plumbing connects it to the floor.");
3069 pline_The("
\94z
\8aÇ
\82Í
\8f°
\82É
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é
\81D");
3070 else if (IS_GRAVE(lev->typ))
3072 You("don't need a gravestone. Yet.");
3074 pline("
\82 \82È
\82½
\82É
\82Í
\95æ
\90Î
\82Í
\95s
\97v
\82¾
\81D
\81D
\81D
\8d¡
\82Ì
\82Æ
\82±
\82ë
\81D");
3075 else if (IS_FOUNTAIN(lev->typ))
3077 You("could drink the %s...", hliquid("water"));
3079 You("%s
\82ð
\88ù
\82ß
\82È
\82¢
\81D
\81D
\81D", hliquid("
\90\85"));
3080 else if (IS_DOOR(lev->typ) && (lev->doormask & D_ISOPEN))
3082 pline("It won't come off the hinges.");
3084 pline("
\83q
\83\93\83W
\82ð
\8aO
\82¹
\82È
\82¢
\81D");
3087 There("is nothing here to pick up.");
3089 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82Í
\82È
\82¢
\81D");
3092 if (!can_reach_floor(TRUE)) {
3093 if (traphere && uteetering_at_seen_pit(traphere))
3095 You("cannot reach the bottom of the pit.");
3097 You("
\97\8e\82µ
\8c\8a\82Ì
\92ê
\82É%s
\82ª
\93Í
\82©
\82È
\82©
\82Á
\82½
\81D", body_part(HAND));
3098 else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
3100 else if (Blind && !can_reach_floor(TRUE))
3102 You("cannot reach anything here.");
3104 You("
\89½
\82É
\82à
\93Í
\82©
\82È
\82¢
\81D");
3107 You("cannot reach the %s.", surface(u.ux, u.uy));
3109 You("%s
\82É
\82½
\82Ç
\82è
\82Â
\82
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D", surface(u.ux, u.uy));
3113 return pickup(-count);
3116 /* stop running if we see something interesting */
3117 /* turn around a corner if that is the only way we can proceed */
3118 /* do not turn left or right twice */
3123 int i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
3124 int corrct = 0, noturn = 0;
3128 /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
3129 /* they polymorphed while in the middle of a long move. */
3130 if (NODIAG(u.umonnum) && u.dx && u.dy) {
3131 You("cannot move diagonally.");
3136 if (Blind || context.run == 0)
3138 for (x = u.ux - 1; x <= u.ux + 1; x++)
3139 for (y = u.uy - 1; y <= u.uy + 1; y++) {
3140 if (!isok(x, y) || (x == u.ux && y == u.uy))
3142 if (NODIAG(u.umonnum) && x != u.ux && y != u.uy)
3145 if ((mtmp = m_at(x, y)) != 0
3146 && mtmp->m_ap_type != M_AP_FURNITURE
3147 && mtmp->m_ap_type != M_AP_OBJECT
3148 && (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
3149 if ((context.run != 1 && !mtmp->mtame)
3150 || (x == u.ux + u.dx && y == u.uy + u.dy
3151 && !context.travel)) {
3152 if (iflags.mention_walls)
3153 pline("%s blocks your path.", upstart(a_monnam(mtmp)));
3158 if (levl[x][y].typ == STONE)
3160 if (x == u.ux - u.dx && y == u.uy - u.dy)
3163 if (IS_ROCK(levl[x][y].typ) || levl[x][y].typ == ROOM
3164 || IS_AIR(levl[x][y].typ)) {
3166 } else if (closed_door(x, y) || (mtmp && is_door_mappear(mtmp))) {
3167 if (x != u.ux && y != u.uy)
3169 if (context.run != 1) {
3170 if (iflags.mention_walls)
3171 You("stop in front of the door.");
3175 } else if (levl[x][y].typ == CORR) {
3177 if (levl[u.ux][u.uy].typ != ROOM) {
3178 if (context.run == 1 || context.run == 3
3179 || context.run == 8) {
3180 i = dist2(x, y, u.ux + u.dx, u.uy + u.dy);
3183 if (corrct == 1 && dist2(x, y, x0, y0) != 1)
3195 } else if ((trap = t_at(x, y)) && trap->tseen) {
3196 if (context.run == 1)
3197 goto bcorr; /* if you must */
3198 if (x == u.ux + u.dx && y == u.uy + u.dy) {
3199 if (iflags.mention_walls) {
3200 int tt = what_trap(trap->ttyp);
3201 You("stop in front of %s.",
3202 an(defsyms[trap_to_defsym(tt)].explanation));
3207 } else if (is_pool_or_lava(x, y)) {
3208 /* water and lava only stop you if directly in front, and stop
3209 * you even if you are running
3211 if (!Levitation && !Flying && !is_clinger(youmonst.data)
3212 && x == u.ux + u.dx && y == u.uy + u.dy) {
3213 /* No Wwalking check; otherwise they'd be able
3214 * to test boots by trying to SHIFT-direction
3215 * into a pool and seeing if the game allowed it
3217 if (iflags.mention_walls)
3218 You("stop at the edge of the %s.",
3219 hliquid(is_pool(x,y) ? "water" : "lava"));
3223 } else { /* e.g. objects or trap or stairs */
3224 if (context.run == 1)
3226 if (context.run == 8)
3230 if (((x == u.ux - u.dx) && (y != u.uy + u.dy))
3231 || ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
3237 } /* end for loops */
3239 if (corrct > 1 && context.run == 2) {
3240 if (iflags.mention_walls)
3241 pline_The("corridor widens here.");
3244 if ((context.run == 1 || context.run == 3 || context.run == 8) && !noturn
3245 && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) {
3246 /* make sure that we do not turn too far */
3248 if (u.dx == y0 - u.uy && u.dy == u.ux - x0)
3249 i = 2; /* straight turn right */
3251 i = -2; /* straight turn left */
3252 } else if (u.dx && u.dy) {
3253 if ((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
3254 i = -1; /* half turn left */
3256 i = 1; /* half turn right */
3258 if ((x0 - u.ux == y0 - u.uy && !u.dy)
3259 || (x0 - u.ux != y0 - u.uy && u.dy))
3260 i = 1; /* half turn right */
3262 i = -1; /* half turn left */
3265 i += u.last_str_turn;
3266 if (i <= 2 && i >= -2) {
3267 u.last_str_turn = i;
3274 /* check for a doorway which lacks its door (NODOOR or BROKEN) */
3279 struct rm *lev_p = &levl[x][y];
3281 if (!IS_DOOR(lev_p->typ))
3283 /* all rogue level doors are doorless but disallow diagonal access, so
3284 we treat them as if their non-existant doors were actually present */
3285 if (Is_rogue_level(&u.uz))
3287 return !(lev_p->doormask & ~(D_NODOOR | D_BROKEN));
3290 /* used by drown() to check whether hero can crawl from water to <x,y> */
3292 crawl_destination(x, y)
3295 /* is location ok in general? */
3296 if (!goodpos(x, y, &youmonst, 0))
3299 /* orthogonal movement is unrestricted when destination is ok */
3300 if (x == u.ux || y == u.uy)
3303 /* diagonal movement has some restrictions */
3304 if (NODIAG(u.umonnum))
3305 return FALSE; /* poly'd into a grid bug... */
3307 return TRUE; /* or a xorn... */
3308 /* pool could be next to a door, conceivably even inside a shop */
3309 if (IS_DOOR(levl[x][y].typ) && (!doorless_door(x, y) || block_door(x, y)))
3311 /* finally, are we trying to squeeze through a too-narrow gap? */
3312 return !(bad_rock(youmonst.data, u.ux, y)
3313 && bad_rock(youmonst.data, x, u.uy));
3316 /* something like lookaround, but we are not running */
3317 /* react only to monsters that might hit us */
3322 register struct monst *mtmp;
3324 /* Also see the similar check in dochugw() in monmove.c */
3325 for (x = u.ux - 1; x <= u.ux + 1; x++)
3326 for (y = u.uy - 1; y <= u.uy + 1; y++) {
3327 if (!isok(x, y) || (x == u.ux && y == u.uy))
3329 if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
3330 && mtmp->m_ap_type != M_AP_OBJECT
3331 && (!mtmp->mpeaceful || Hallucination)
3332 && (!is_hider(mtmp->data) || !mtmp->mundetected)
3333 && !noattacks(mtmp->data) && mtmp->mcanmove
3334 && !mtmp->msleeping /* aplvax!jcn */
3335 && !onscary(u.ux, u.uy, mtmp) && canspotmon(mtmp))
3346 return; /* This is a bug fix by ab@unido */
3347 u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
3351 multi_reason = NULL;
3352 context.travel = context.travel1 = context.mv = context.run = 0;
3355 /* called when a non-movement, multi-turn action has completed */
3358 const char *msg_override;
3360 multi = 0; /* caller will usually have done this already */
3362 nomovemsg = msg_override;
3363 else if (!nomovemsg)
3364 nomovemsg = You_can_move_again;
3369 multi_reason = NULL;
3371 int NDECL((*f)) = afternmv;
3372 /* clear afternmv before calling it (to override the
3373 encumbrance hack for levitation--see weight_cap()) */
3374 afternmv = (int NDECL((*))) 0;
3382 static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES,
3383 SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
3384 TELEPORT_CONTROL, STEALTH, FAST, INVIS };
3386 if (moves <= wailmsg + 50)
3390 if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) {
3395 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3398 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3403 pline("%s is about to die.", who);
3405 pline("%s
\82Í
\8e\80\82É
\82©
\82¯
\82Ä
\82¢
\82é
\81D", who);
3407 for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
3408 if (u.uprops[powers[i]].intrinsic & INTRINSIC)
3412 pline((powercnt >= 4) ? "%s, all your powers will be lost..."
3414 pline((powercnt >= 4) ? "%s
\81C
\82 \82È
\82½
\82Ì
\91S
\82Ä
\82Ì
\97Í
\82Í
\8e¸
\82í
\82ê
\82Â
\82Â
\82 \82é
\81D
\81D
\81D"
3416 : "%s, your life force is running out.",
3418 : "%s
\81C
\82 \82È
\82½
\82Ì
\90¶
\96½
\97Í
\82Í
\90s
\82«
\82æ
\82¤
\82Æ
\82µ
\82Ä
\82¢
\82é
\81D
\81D
\81D",
3423 You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
3425 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"
3427 : "the howling of the CwnAnnwn...");
3429 : "
\83N
\81[
\83\93\81E
\83A
\83\93\83k
\81[
\83\93\82Ì
\89\93\96i
\82ª
\95·
\82±
\82¦
\82é
\81D
\81D
\81D");
3434 losehp(n, knam, k_format)
3436 register const char *knam;
3446 else if (n > 0 && u.mh * 10 < u.mhmax && Unchanging)
3452 if (u.uhp > u.uhpmax)
3453 u.uhpmax = u.uhp; /* perhaps n was negative */
3455 context.travel = context.travel1 = context.mv = context.run = 0;
3458 killer.format = k_format;
3459 if (killer.name != knam) /* the thing that killed you */
3460 Strcpy(killer.name, knam ? knam : "");
3464 pline("
\82 \82È
\82½
\82Í
\8e\80\82É
\82Ü
\82µ
\82½
\81D
\81D
\81D");
3466 } else if (n > 0 && u.uhp * 10 < u.uhpmax) {
3474 long carrcap, save_ELev = ELevitation;
3476 /* boots take multiple turns to wear but any properties they
3477 confer are enabled at the start rather than the end; that
3478 causes message sequencing issues for boots of levitation
3479 so defer their encumbrance benefit until they're fully worn */
3480 if (afternmv == Boots_on && (ELevitation & W_ARMF) != 0L) {
3481 ELevitation &= ~W_ARMF;
3482 float_vs_flight(); /* in case Levitation is blocking Flying */
3485 carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
3487 /* consistent with can_carry() in mon.c */
3488 if (youmonst.data->mlet == S_NYMPH)
3489 carrcap = MAX_CARR_CAP;
3490 else if (!youmonst.data->cwt)
3491 carrcap = (carrcap * (long) youmonst.data->msize) / MZ_HUMAN;
3492 else if (!strongmonst(youmonst.data)
3493 || (strongmonst(youmonst.data)
3494 && (youmonst.data->cwt > WT_HUMAN)))
3495 carrcap = (carrcap * (long) youmonst.data->cwt / WT_HUMAN);
3498 if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
3499 || (u.usteed && strongmonst(u.usteed->data))) {
3500 carrcap = MAX_CARR_CAP;
3502 if (carrcap > MAX_CARR_CAP)
3503 carrcap = MAX_CARR_CAP;
3505 if (EWounded_legs & LEFT_SIDE)
3507 if (EWounded_legs & RIGHT_SIDE)
3514 if (ELevitation != save_ELev) {
3515 ELevitation = save_ELev;
3519 return (int) carrcap;
3522 static int wc; /* current weight_cap(); valid after call to inv_weight() */
3524 /* returns how far beyond the normal capacity the player is currently. */
3525 /* inv_weight() is negative if the player is below normal capacity. */
3529 register struct obj *otmp = invent;
3530 register int wt = 0;
3533 if (otmp->oclass == COIN_CLASS)
3534 wt += (int) (((long) otmp->quan + 50L) / 100L);
3535 else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
3544 * Returns 0 if below normal capacity, or the number of "capacity units"
3545 * over the normal capacity the player is loaded. Max is 5.
3548 calc_capacity(xtra_wt)
3551 int cap, wt = inv_weight() + xtra_wt;
3554 return UNENCUMBERED;
3557 cap = (wt * 2 / wc) + 1;
3558 return min(cap, OVERLOADED);
3564 return calc_capacity(0);
3570 int wt = inv_weight();
3572 return (wt - (2 * wc));
3579 if (near_capacity() >= EXT_ENCUMBER) {
3584 You_cant("do that while carrying so much stuff.");
3586 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");
3596 register struct obj *otmp = invent;
3597 register int ct = 0;
3600 if (incl_gold || otmp->invlet != GOLD_SYM)
3607 /* Counts the money in an object chain. */
3608 /* Intended use is for your or some monster's inventory, */
3609 /* now that u.gold/m.gold is gone.*/
3610 /* Counting money in a container might be possible too. */
3616 /* Must change when silver & copper is implemented: */
3617 if (otmp->oclass == COIN_CLASS)