1 /* NetHack 3.6 hack.c $NHDT-Date: 1446604111 2015/11/04 02:28:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.155 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
8 /* JNetHack may be freely redistributed. See license for details. */
12 /* #define DEBUG */ /* uncomment for debugging */
14 STATIC_DCL void NDECL(maybe_wail);
15 STATIC_DCL int NDECL(moverock);
16 STATIC_DCL int FDECL(still_chewing, (XCHAR_P, XCHAR_P));
17 STATIC_DCL void NDECL(dosinkfall);
18 STATIC_DCL boolean FDECL(findtravelpath, (BOOLEAN_P));
19 STATIC_DCL boolean FDECL(trapmove, (int, int, struct trap *));
20 STATIC_DCL void NDECL(switch_terrain);
21 STATIC_DCL struct monst *FDECL(monstinroom, (struct permonst *, int));
22 STATIC_DCL boolean FDECL(doorless_door, (int, int));
23 STATIC_DCL void FDECL(move_update, (BOOLEAN_P));
25 #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
27 static anything tmp_anything;
33 tmp_anything = zeroany;
34 tmp_anything.a_uint = ui;
42 tmp_anything = zeroany;
43 tmp_anything.a_long = lng;
51 tmp_anything = zeroany;
52 tmp_anything.a_monst = mtmp;
60 tmp_anything = zeroany;
61 tmp_anything.a_obj = obj;
66 revive_nasty(x, y, msg)
70 register struct obj *otmp, *otmp2;
73 boolean revived = FALSE;
75 for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
76 otmp2 = otmp->nexthere;
77 if (otmp->otyp == CORPSE
78 && (is_rider(&mons[otmp->corpsenm])
79 || otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
80 /* move any living monster already at that location */
81 if ((mtmp = m_at(x, y)) && enexto(&cc, x, y, mtmp->data))
82 rloc_to(mtmp, cc.x, cc.y);
85 revived = revive_corpse(otmp);
89 /* this location might not be safe, if not, move revived monster */
92 if (mtmp && !goodpos(x, y, mtmp, 0)
93 && enexto(&cc, x, y, mtmp->data)) {
94 rloc_to(mtmp, cc.x, cc.y);
96 /* else impossible? */
105 register xchar rx, ry, sx, sy;
106 register struct obj *otmp;
107 register struct trap *ttmp;
108 register struct monst *mtmp;
110 sx = u.ux + u.dx, sy = u.uy + u.dy; /* boulder starting position */
111 while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
112 /* make sure that this boulder is visible as the top object */
113 if (otmp != level.objects[sx][sy])
114 movobj(otmp, sx, sy);
116 rx = u.ux + 2 * u.dx; /* boulder destination position */
117 ry = u.uy + 2 * u.dy;
119 if (Levitation || Is_airlevel(&u.uz)) {
121 feel_location(sx, sy);
123 You("don't have enough leverage to push %s.", the(xname(otmp)));
125 You("
\91Ì
\82ª
\95\82\82¢
\82Ä
\82¢
\82é
\82Ì
\82Å%s
\82ð
\89\9f\82¹
\82È
\82¢
\81D", the(xname(otmp)));
126 /* Give them a chance to climb over it? */
129 if (verysmall(youmonst.data) && !u.usteed) {
131 feel_location(sx, sy);
133 pline("You're too small to push that %s.", xname(otmp));
135 You("
\8f¬
\82³
\82·
\82¬
\82Ä%s
\82ð
\89\9f\82¹
\82È
\82¢
\81D",xname(otmp));
138 if (isok(rx, ry) && !IS_ROCK(levl[rx][ry].typ)
139 && levl[rx][ry].typ != IRONBARS
140 && (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy)
141 || doorless_door(rx, ry)) && !sobj_at(BOULDER, rx, ry)) {
145 /* KMH -- Sokoban doesn't let you push boulders diagonally */
146 if (Sokoban && u.dx && u.dy) {
148 feel_location(sx, sy);
150 pline("%s won't roll diagonally on this %s.",
152 pline("%s
\82Ì
\8fã
\82Å
\82Í%s
\82Í
\8eÎ
\82ß
\82É
\89\9f\82¹
\82È
\82¢
\81D",
153 The(xname(otmp)), surface(sx, sy));
158 if (revive_nasty(rx, ry, "You sense movement on the other side."))
160 if (revive_nasty(rx, ry, "
\94½
\91Î
\91¤
\82É
\93®
\82«
\82ð
\8a´
\82¶
\82½
\81D"))
163 if (mtmp && !noncorporeal(mtmp->data)
165 || !(ttmp && ((ttmp->ttyp == PIT)
166 || (ttmp->ttyp == SPIKED_PIT))))) {
168 feel_location(sx, sy);
169 if (canspotmon(mtmp))
171 pline("There's %s on the other side.", a_monnam(mtmp));
173 pline("
\94½
\91Î
\91¤
\82É%s
\82ª
\82¢
\82é
\81D", a_monnam(mtmp));
176 You_hear("a monster behind %s.", the(xname(otmp)));
178 pline("%s
\82Ì
\94w
\8cã
\82É
\89ö
\95¨
\82Ì
\8bC
\94z
\82ª
\82·
\82é
\81D", the(xname(otmp)));
179 map_invisible(rx, ry);
183 pline("Perhaps that's why %s cannot move it.",
184 u.usteed ? y_monnam(u.usteed) : "you");
186 pline("
\82½
\82Ô
\82ñ
\82±
\82ê
\82ª
\81C
\8aâ
\82ð
\93®
\82©
\82¹
\82È
\82¢
\97\9d\97R
\82¾
\81D");
192 /* if a trap operates on the boulder, don't attempt
193 to move any others at this location; return -1
194 if another boulder is in hero's way, or 0 if he
195 should advance to the vacated boulder position */
196 switch (ttmp->ttyp) {
199 obj_extract_self(otmp);
200 place_object(otmp, rx, ry);
203 pline("KAABLAMM!!! %s %s land mine.",
204 Tobjnam(otmp, "trigger"),
205 ttmp->madeby_u ? "your" : "a");
207 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",
209 ttmp->madeby_u ? "
\82 \82È
\82½
\82Ì
\8ed
\8a|
\82¯
\82½" : "");
211 blow_up_landmine(ttmp);
212 /* if the boulder remains, it should fill the pit */
213 fill_pit(u.ux, u.uy);
216 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
221 obj_extract_self(otmp);
222 /* vision kludge to get messages right;
223 the pit will temporarily be seen even
224 if this is one among multiple boulders */
226 viz_array[ry][rx] |= IN_SIGHT;
228 if (!flooreffects(otmp, rx, ry, "fall")) {
230 if (!flooreffects(otmp, rx, ry, "
\97\8e\82¿
\82é")) {
231 place_object(otmp, rx, ry);
235 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
240 pline("Kerplunk! You no longer feel %s.",
242 pline("
\83h
\83T
\83b
\81I
\82 \82È
\82½
\82Í
\82à
\82¤%s
\82ð
\8a´
\82¶
\82ç
\82ê
\82È
\82¢
\81D",
246 pline("%s%s and %s a %s in the %s!",
247 Tobjnam(otmp, (ttmp->ttyp == TRAPDOOR)
250 (ttmp->ttyp == TRAPDOOR) ? "" : " into",
251 otense(otmp, "plug"),
252 (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
255 pline("%s
\82Í
\97\8e\82¿
\82Ä%s
\82Ì%s
\82ð
\96\84\82ß
\82½
\81I",
258 (ttmp->ttyp == TRAPDOOR) ? "
\97\8e\82µ
\94à" : "
\8c\8a");
263 levl[rx][ry].wall_info &= ~W_NONDIGGABLE;
264 levl[rx][ry].candig = 1;
267 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
270 int newlev = 0; /* lint suppression */
273 if (ttmp->ttyp == LEVEL_TELEP) {
274 newlev = random_teleport_level();
275 if (newlev == depth(&u.uz) || In_endgame(&u.uz))
276 /* trap didn't work; skip "disappears" message */
281 pline("%s pushes %s and suddenly it disappears!",
283 pline("%s
\82ª%s
\82ð
\89\9f\82·
\82Æ
\81C
\93Ë
\91R
\82»
\82ê
\82Í
\8fÁ
\96Å
\82µ
\82½
\81I",
284 upstart(y_monnam(u.usteed)), the(xname(otmp)));
287 You("push %s and suddenly it disappears!",
289 pline("
\82 \82È
\82½
\82ª%s
\82ð
\89\9f\82·
\82Æ
\81C
\93Ë
\91R
\82»
\82ê
\82Í
\8fÁ
\96Å
\82µ
\82½
\81I",
291 if (ttmp->ttyp == TELEP_TRAP) {
294 obj_extract_self(otmp);
295 add_to_migration(otmp);
296 get_level(&dest, newlev);
297 otmp->ox = dest.dnum;
298 otmp->oy = dest.dlevel;
299 otmp->owornmask = (long) MIGR_RANDOM;
302 return sobj_at(BOULDER, sx, sy) ? -1 : 0;
305 break; /* boulder not affected by this trap */
309 if (closed_door(rx, ry))
311 if (boulder_hits_pool(otmp, rx, ry, TRUE))
314 * Re-link at top of fobj chain so that pile order is preserved
315 * when level is restored.
319 place_object(otmp, otmp->ox, otmp->oy);
323 #ifdef LINT /* static long lastmovetime; */
327 /* note: reset to zero after save/restore cycle */
328 static NEARDATA long lastmovetime;
332 if (moves > lastmovetime + 2 || moves < lastmovetime)
334 pline("With %s effort you move %s.",
335 throws_rocks(youmonst.data) ? "little"
339 pline("%s
\97Í
\82ð
\82±
\82ß
\82Ä%s
\82ð
\89\9f\82µ
\82½
\81D",
340 throws_rocks(youmonst.data) ? "
\8f
\82µ" : "
\82©
\82È
\82è",
343 exercise(A_STR, TRUE);
346 pline("%s moves %s.", upstart(y_monnam(u.usteed)),
349 pline("%s
\82Í%s
\82ð
\93®
\82©
\82µ
\82½
\81D", upstart(y_monnam(u.usteed)),
352 lastmovetime = moves;
355 /* Move the boulder *after* the message. */
356 if (glyph_is_invisible(levl[rx][ry].glyph))
357 unmap_object(rx, ry);
358 movobj(otmp, rx, ry); /* does newsym(rx,ry) */
360 feel_location(rx, ry);
361 feel_location(sx, sy);
369 pline("%s tries to move %s, but cannot.",
370 upstart(y_monnam(u.usteed)), the(xname(otmp)));
372 pline("%s
\82Í%s
\82ð
\93®
\82©
\82»
\82¤
\82Æ
\82µ
\82½
\82ª
\8fo
\97\88\82È
\82©
\82Á
\82½
\81D",
373 upstart(y_monnam(u.usteed)), the(xname(otmp)));
377 You("try to move %s, but in vain.", the(xname(otmp)));
379 You("%s
\82ð
\93®
\82©
\82»
\82¤
\82Æ
\82µ
\82½
\82ª
\81C
\82¾
\82ß
\82¾
\82Á
\82½
\81D", the(xname(otmp)));
381 feel_location(sx, sy);
383 if (throws_rocks(youmonst.data)) {
384 if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
386 You("aren't skilled enough to %s %s from %s.",
387 (flags.pickup && !Sokoban) ? "pick up" : "push aside",
388 the(xname(otmp)), y_monnam(u.usteed));
390 You("%s
\82É%s
\82ð%s
\82é
\82Ù
\82Ç
\8bZ
\97Ê
\82ª
\82È
\82¢
\81D",
393 (flags.pickup && !Sokoban) ? "
\8fE
\82í
\82¹" : "
\89\9f\82³
\82¹");
397 pline("However, you can easily %s.",
398 (flags.pickup && !Sokoban) ? "pick it up"
401 pline("
\82µ
\82©
\82µ
\81C
\82 \82È
\82½
\82Í
\8aÈ
\92P
\82É
\82»
\82ê
\82ð%s
\81D",
402 (flags.pickup && !Sokoban)
403 ? "
\8fE
\82¦
\82½" : "
\95Ê
\82Ì
\95û
\82É
\89\9f\82¹
\82½");
412 && (((!invent || inv_weight() <= -850)
413 && (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ)
414 && IS_ROCK(levl[sx][u.uy].typ))))
415 || verysmall(youmonst.data))) {
418 "However, you can squeeze yourself into a small opening.");
420 "
\82µ
\82©
\82µ
\81C
\82 \82È
\82½
\82Í
\8f¬
\82³
\82¢
\8c\84\8aÔ
\82É
\82±
\82¶
\93ü
\82Á
\82½
\81D");
433 * Chew on a wall, door, or boulder. Returns TRUE if still eating, FALSE
440 struct rm *lev = &levl[x][y];
441 struct obj *boulder = sobj_at(BOULDER, x, y);
442 const char *digtxt = (char *) 0, *dmgtxt = (char *) 0;
444 if (context.digging.down) /* not continuing previous dig (w/ pick-axe) */
445 (void) memset((genericptr_t) &context.digging, 0,
446 sizeof(struct dig_info));
448 if (!boulder && IS_ROCK(lev->typ) && !may_dig(x, y)) {
450 You("hurt your teeth on the %s.",
451 (lev->typ == IRONBARS)
457 You("%s
\82Å
\8e\95\82ð
\92É
\82ß
\82½
\81D",
458 (lev->typ == IRONBARS)
466 } else if (context.digging.pos.x != x || context.digging.pos.y != y
467 || !on_level(&context.digging.level, &u.uz)) {
468 context.digging.down = FALSE;
469 context.digging.chew = TRUE;
470 context.digging.warned = FALSE;
471 context.digging.pos.x = x;
472 context.digging.pos.y = y;
473 assign_level(&context.digging.level, &u.uz);
474 /* solid rock takes more work & time to dig through */
475 context.digging.effort =
476 (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc;
478 You("start chewing %s %s.",
479 (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
488 : lev->typ == IRONBARS
492 You("%s%s
\82Í
\82¶
\82ß
\82½
\81D",
499 : lev->typ == IRONBARS
502 (boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
504 : "
\82É
\8c\8a\82ð
\82 \82¯");
506 watch_dig((struct monst *) 0, x, y, FALSE);
508 } else if ((context.digging.effort += (30 + u.udaminc)) <= 100) {
511 You("%s chewing on the %s.",
512 context.digging.chew ? "continue" : "begin",
519 : (lev->typ == IRONBARS)
523 You("%s
\82ð
\8a\9a\82Ý%s
\81D",
530 : lev->typ == IRONBARS
533 context.digging.chew ? "
\91±
\82¯
\82½" : "
\82Í
\82¶
\82ß
\82½");
535 context.digging.chew = TRUE;
536 watch_dig((struct monst *) 0, x, y, FALSE);
540 /* Okay, you've chewed through something */
542 u.uhunger += rnd(20);
545 delobj(boulder); /* boulder goes bye-bye */
547 You("eat the boulder."); /* yum */
549 You("
\8aâ
\82ð
\90H
\82×
\82½
\81D"); /* yum */
553 * The location could still block because of
554 * 1. More than one boulder
555 * 2. Boulder stuck in a wall/stone/door.
557 * [perhaps use does_block() below (from vision.c)]
559 if (IS_ROCK(lev->typ) || closed_door(x, y)
560 || sobj_at(BOULDER, x, y)) {
561 block_point(x, y); /* delobj will unblock the point */
562 /* reset dig state */
563 (void) memset((genericptr_t) &context.digging, 0,
564 sizeof(struct dig_info));
568 } else if (IS_WALL(lev->typ)) {
569 if (*in_rooms(x, y, SHOPBASE)) {
570 add_damage(x, y, 10L * ACURRSTR);
574 dmgtxt = "
\8f\9d\82Â
\82¯
\82é";
577 digtxt = "chew a hole in the wall.";
579 digtxt = "
\95Ç
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
580 if (level.flags.is_maze_lev) {
582 } else if (level.flags.is_cavernous_lev && !in_town(x, y)) {
586 lev->doormask = D_NODOOR;
588 } else if (IS_TREE(lev->typ)) {
590 digtxt = "chew through the tree.";
592 digtxt = "
\96Ø
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
594 } else if (lev->typ == IRONBARS) {
596 digtxt = "eat through the bars.";
598 digtxt = "
\93S
\82Ì
\96_
\82É
\8c\8a\82ð
\8aJ
\82¯
\82½
\81D";
600 } else if (lev->typ == SDOOR) {
601 if (lev->doormask & D_TRAPPED) {
602 lev->doormask = D_NODOOR;
604 b_trapped("secret door", 0);
606 b_trapped("
\94é
\96§
\82Ì
\94à", 0);
609 digtxt = "chew through the secret door.";
611 digtxt = "
\94é
\96§
\82Ì
\94à
\82ð
\8a\9a\82Ý
\8dÓ
\82¢
\82½
\81D";
612 lev->doormask = D_BROKEN;
616 } else if (IS_DOOR(lev->typ)) {
617 if (*in_rooms(x, y, SHOPBASE)) {
618 add_damage(x, y, 400L);
624 if (lev->doormask & D_TRAPPED) {
625 lev->doormask = D_NODOOR;
627 b_trapped("door", 0);
629 b_trapped("
\94à", 0);
632 digtxt = "chew through the door.";
634 digtxt = "
\94à
\82ð
\8dÓ
\82¢
\82½
\81D";
635 lev->doormask = D_BROKEN;
638 } else { /* STONE or SCORR */
640 digtxt = "chew a passage through the rock.";
642 digtxt = "
\8aâ
\82ð
\8a\9a\82Ý
\8dÓ
\82¢
\82Ä
\92Ê
\82è
\94²
\82¯
\82½
\81D";
646 unblock_point(x, y); /* vision */
649 You1(digtxt); /* after newsym */
651 pay_for_damage(dmgtxt, FALSE);
652 (void) memset((genericptr_t) &context.digging, 0,
653 sizeof(struct dig_info));
659 register struct obj *obj;
660 register xchar ox, oy;
662 /* optimize by leaving on the fobj chain? */
664 newsym(obj->ox, obj->oy);
665 place_object(obj, ox, oy);
670 static NEARDATA const char fell_on_sink[] = "fell onto a sink";
672 static NEARDATA const char fell_on_sink[] = "
\97¬
\82µ
\91ä
\82É
\97\8e\82¿
\82Ä";
677 register struct obj *obj;
679 boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
680 innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L),
681 ufall = (!innate_lev && !(HFlying || EFlying)); /* BFlying */
685 You(innate_lev ? "wobble unsteadily for a moment."
687 You(innate_lev ? "
\82¿
\82å
\82Á
\82Æ
\82Ó
\82ç
\82Â
\82¢
\82½
\81D"
689 : "gain control of your flight.");
691 : "
\94ò
\8ds
\92\86\82Ì
\90§
\8cä
\82ð
\8eæ
\82è
\82à
\82Ç
\82µ
\82½
\81D");
693 long save_ELev = ELevitation, save_HLev = HLevitation;
695 /* fake removal of levitation in advance so that final
696 disclosure will be right in case this turns out to
697 be fatal; fortunately the fact that rings and boots
698 are really still worn has no effect on bones data */
699 ELevitation = HLevitation = 0L;
701 You("crash to the floor!");
703 You("
\8f°
\82É
\92@
\82«
\82Â
\82¯
\82ç
\82ê
\82½
\81I");
704 dmg = rn1(8, 25 - (int) ACURR(A_CON));
706 losehp(Maybe_Half_Phys(dmg), fell_on_sink, NO_KILLER_PREFIX);
708 losehp(Maybe_Half_Phys(dmg), fell_on_sink, KILLED_BY);
710 exercise(A_DEX, FALSE);
712 selftouch("Falling, you");
714 selftouch("
\97\8e\82¿
\82È
\82ª
\82ç
\81C
\82 \82È
\82½
\82Í");
715 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
716 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) {
718 You("fell on %s.", doname(obj));
720 You("%s
\82Ì
\8fã
\82É
\97\8e\82¿
\82½
\81D",doname(obj));
722 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
725 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
728 exercise(A_CON, FALSE);
730 ELevitation = save_ELev;
731 HLevitation = save_HLev;
735 * Interrupt multi-turn putting on/taking off of armor (in which
736 * case we reached the sink due to being teleported while busy;
737 * in 3.4.3, Boots_on()/Boots_off() [called via (*aftermv)() when
738 * 'multi' reaches 0] triggered a crash if we were donning/doffing
739 * levitation boots [because the Boots_off() below causes 'uarmf'
740 * to be null by the time 'aftermv' gets called]).
742 * Interrupt donning/doffing if we fall onto the sink, or if the
743 * code below is going to remove levitation boots even when we
744 * haven't fallen (innate floating or flying becoming unblocked).
746 if (ufall || lev_boots) {
747 (void) stop_donning(lev_boots ? uarmf : (struct obj *) 0);
748 /* recalculate in case uarmf just got set to null */
749 lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS);
752 /* remove worn levitation items */
753 ELevitation &= ~W_ARTI;
754 HLevitation &= ~(I_SPECIAL | TIMEOUT);
756 if (uleft && uleft->otyp == RIN_LEVITATION) {
761 if (uright && uright->otyp == RIN_LEVITATION) {
772 /* probably moot; we're either still levitating or went
773 through float_down(), but make sure BFlying is up to date */
777 /* intended to be called only on ROCKs or TREEs */
782 struct rm *lev = &levl[x][y];
784 return (boolean) !((IS_STWALL(lev->typ) || IS_TREE(lev->typ))
785 && (lev->wall_info & W_NONDIGGABLE));
792 return (boolean) !(IS_STWALL(levl[x][y].typ)
793 && (levl[x][y].wall_info & W_NONPASSWALL));
798 struct permonst *mdat;
801 return (boolean) ((Sokoban && sobj_at(BOULDER, x, y))
802 || (IS_ROCK(levl[x][y].typ)
803 && (!tunnels(mdat) || needspick(mdat)
805 && !(passes_walls(mdat) && may_passwall(x, y))));
808 /* caller has already decided that it's a tight diagonal; check whether a
809 monster--who might be the hero--can fit through, and if not then return
810 the reason why: 1: can't fit, 2: possessions won't fit, 3: sokoban */
811 int /* returns 0 if we can squeeze through */
812 cant_squeeze_thru(mon)
816 struct permonst *ptr = mon->data;
820 && !(amorphous(ptr) || is_whirly(ptr) || noncorporeal(ptr)
821 || slithy(ptr) || can_fog(mon)))
824 /* lugging too much junk? */
826 (mon == &youmonst) ? inv_weight() + weight_cap() : curr_mon_load(mon);
830 /* Sokoban restriction applies to hero only */
831 if (mon == &youmonst && Sokoban)
834 /* can squeeze through */
842 return (boolean) (Invocation_lev(&u.uz)
843 && x == inv_pos.x && y == inv_pos.y);
846 /* return TRUE if (dx,dy) is an OK place to move
847 * mode is one of DO_MOVE, TEST_MOVE or TEST_TRAV
850 test_move(ux, uy, dx, dy, mode)
856 register struct rm *tmpr = &levl[x][y];
857 register struct rm *ust;
859 context.door_opened = FALSE;
861 * Check for physical obstacles. First, the place we are going.
863 if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) {
864 if (Blind && mode == DO_MOVE)
866 if (Passes_walls && may_passwall(x, y)) {
868 } else if (tmpr->typ == IRONBARS) {
869 if ((dmgtype(youmonst.data, AD_RUST)
870 || dmgtype(youmonst.data, AD_CORR)) && mode == DO_MOVE
871 && still_chewing(x, y)) {
874 if (!(Passes_walls || passes_bars(youmonst.data))) {
875 if (iflags.mention_walls)
877 You("cannot pass through the bars.");
879 You("
\93S
\82Ì
\96_
\82ð
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
882 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
884 if (mode == DO_MOVE && still_chewing(x, y))
886 } else if (flags.autodig && !context.run && !context.nopick && uwep
888 /* MRKR: Automatic digging when wielding the appropriate tool */
890 (void) use_pick_axe2(uwep);
893 if (mode == DO_MOVE) {
894 if (Is_stronghold(&u.uz) && is_db_wall(x, y))
896 pline_The("drawbridge is up!");
898 pline("
\92µ
\82Ë
\8b´
\82Í
\8fã
\82Á
\82Ä
\82¢
\82é
\81I");
899 /* sokoban restriction stays even after puzzle is solved */
900 else if (Passes_walls && !may_passwall(x, y)
901 && In_sokoban(&u.uz))
903 pline_The("Sokoban walls resist your ability.");
905 pline_The("
\91q
\8cÉ
\94Ô
\82Ì
\95Ç
\82Í
\82 \82È
\82½
\82Ì
\94\
\97Í
\82É
\92ï
\8dR
\82µ
\82½
\81D");
906 else if (iflags.mention_walls)
908 pline("It's a wall.");
910 pline("
\82±
\82ê
\82Í
\95Ç
\82¾
\81D");
914 } else if (IS_DOOR(tmpr->typ)) {
915 if (closed_door(x, y)) {
916 if (Blind && mode == DO_MOVE)
920 else if (can_ooze(&youmonst)) {
923 You("ooze under the door.");
925 You("
\83h
\83A
\82Ì
\89º
\82©
\82ç
\82É
\82¶
\82Ý
\8fo
\82½
\81D");
926 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
928 if (mode == DO_MOVE && still_chewing(x, y))
931 if (mode == DO_MOVE) {
932 if (amorphous(youmonst.data))
935 "try to ooze under the door, but can't squeeze your possessions through.");
937 "
\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");
938 if (flags.autoopen && !context.run && !Confusion
939 && !Stunned && !Fumbling) {
940 context.door_opened = context.move =
942 } else if (x == ux || y == uy) {
943 if (Blind || Stunned || ACURR(A_DEX) < 10
947 You_cant("lead %s through that closed door.",
949 You_cant("%s
\82É
\95Â
\82Ü
\82Á
\82½
\94à
\82ð
\92Ê
\89ß
\82³
\82¹
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
953 pline("Ouch! You bump into a door.");
955 pline("
\82¢
\82Ä
\82Á
\81I
\93ª
\82ð
\94à
\82É
\82Ô
\82Â
\82¯
\82½
\81D");
956 exercise(A_DEX, FALSE);
960 pline("That door is closed.");
962 pline("
\94à
\82Í
\95Â
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D");
964 } else if (mode == TEST_TRAV)
970 if (dx && dy && !Passes_walls
971 && (!doorless_door(x, y) || block_door(x, y))) {
972 /* Diagonal moves into a door are not allowed. */
973 if (Blind && mode == DO_MOVE)
979 if (dx && dy && bad_rock(youmonst.data, ux, y)
980 && bad_rock(youmonst.data, x, uy)) {
981 /* Move at a diagonal. */
982 switch (cant_squeeze_thru(&youmonst)) {
986 You("cannot pass that way.");
988 You("
\92Ê
\82è
\82Ê
\82¯
\82Å
\82«
\82È
\82¢
\81D");
993 You("are carrying too much to get through.");
995 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1000 Your("body is too large to fit through.");
1002 Your("
\91Ì
\82ª
\91å
\82«
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1005 break; /* can squeeze through */
1007 } else if (dx && dy && worm_cross(ux, uy, x, y)) {
1008 /* consecutive long worm segments are at <ux,y> and <x,uy> */
1009 if (mode == DO_MOVE)
1011 pline("%s is in your way.", Monnam(m_at(ux, y)));
1013 pline("
\93¹
\82Ì
\93r
\92\86\82É%s
\82ª
\82¢
\82é
\81D", Monnam(m_at(ux, y)));
1016 /* Pick travel path that does not require crossing a trap.
1017 * Avoid water and lava using the usual running rules.
1018 * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
1019 if (context.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
1020 struct trap *t = t_at(x, y);
1023 || (!Levitation && !Flying && !is_clinger(youmonst.data)
1024 && is_pool_or_lava(x, y) && levl[x][y].seenv))
1028 ust = &levl[ux][uy];
1030 /* Now see if other things block our way . . */
1031 if (dx && dy && !Passes_walls && IS_DOOR(ust->typ)
1032 && (!doorless_door(ux, uy) || block_entry(x, y))) {
1033 /* Can't move at a diagonal out of a doorway with door. */
1037 if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
1038 if (!(Blind || Hallucination) && (context.run >= 2)
1039 && mode != TEST_TRAV)
1041 if (mode == DO_MOVE) {
1042 /* tunneling monsters will chew before pushing */
1043 if (tunnels(youmonst.data) && !needspick(youmonst.data)
1045 if (still_chewing(x, y))
1047 } else if (moverock() < 0)
1049 } else if (mode == TEST_TRAV) {
1052 /* don't pick two boulders in a row, unless there's a way thru */
1053 if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
1055 && !(tunnels(youmonst.data) && !needspick(youmonst.data))
1056 && !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK)
1057 && !((obj = carrying(WAN_DIGGING))
1058 && !objects[obj->otyp].oc_name_known))
1062 /* assume you'll be able to push it when you get there... */
1065 /* OK, it is a legal place to move. */
1070 static boolean trav_debug = FALSE;
1072 /* in this case, toggle display of travel debug info */
1073 int wiz_debug_cmd_traveldisplay()
1075 trav_debug = !trav_debug;
1081 * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
1082 * A shortest path is returned. If guess is TRUE, consider various
1083 * inaccessible locations as valid intermediate path points.
1084 * Returns TRUE if a path was found.
1087 findtravelpath(guess)
1090 /* if travel to adjacent, reachable location, use normal movement rules */
1091 if (!guess && context.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1
1092 && !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
1094 if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
1098 iflags.travelcc.x = iflags.travelcc.y = -1;
1103 if (u.tx != u.ux || u.ty != u.uy) {
1104 xchar travel[COLNO][ROWNO];
1105 xchar travelstepx[2][COLNO * ROWNO];
1106 xchar travelstepy[2][COLNO * ROWNO];
1107 xchar tx, ty, ux, uy;
1108 int n = 1; /* max offset in travelsteps */
1109 int set = 0; /* two sets current and previous */
1110 int radius = 1; /* search radius */
1113 /* If guessing, first find an "obvious" goal location. The obvious
1114 * goal is the position the player knows of, or might figure out
1115 * (couldsee) that is closest to the target on a straight path.
1130 (void) memset((genericptr_t) travel, 0, sizeof(travel));
1131 travelstepx[0][0] = tx;
1132 travelstepy[0][0] = ty;
1137 for (i = 0; i < n; i++) {
1139 int x = travelstepx[set][i];
1140 int y = travelstepy[set][i];
1141 static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
1142 /* no diagonal movement for grid bugs */
1143 int dirmax = NODIAG(u.umonnum) ? 4 : 8;
1145 for (dir = 0; dir < dirmax; ++dir) {
1146 int nx = x + xdir[ordered[dir]];
1147 int ny = y + ydir[ordered[dir]];
1151 if ((!Passes_walls && !can_ooze(&youmonst)
1152 && closed_door(x, y)) || sobj_at(BOULDER, x, y)) {
1153 /* closed doors and boulders usually
1154 * cause a delay, so prefer another path */
1155 if (travel[x][y] > radius - 3) {
1156 travelstepx[1 - set][nn] = x;
1157 travelstepy[1 - set][nn] = y;
1158 /* don't change travel matrix! */
1163 if (test_move(x, y, nx - x, ny - y, TEST_TRAV)
1164 && (levl[nx][ny].seenv
1165 || (!Blind && couldsee(nx, ny)))) {
1166 if (nx == ux && ny == uy) {
1170 if (x == u.tx && y == u.ty) {
1172 /* reset run so domove run checks work */
1174 iflags.travelcc.x = iflags.travelcc.y =
1179 } else if (!travel[nx][ny]) {
1180 travelstepx[1 - set][nn] = nx;
1181 travelstepy[1 - set][nn] = ny;
1182 travel[nx][ny] = radius;
1191 /* Use of warning glyph is arbitrary. It stands out. */
1192 tmp_at(DISP_ALL, warning_to_glyph(1));
1193 for (i = 0; i < nn; ++i) {
1194 tmp_at(travelstepx[1 - set][i], travelstepy[1 - set][i]);
1197 if (flags.runmode == RUN_CRAWL) {
1201 tmp_at(DISP_END, 0);
1210 /* if guessing, find best location in travel matrix and go there */
1212 int px = tx, py = ty; /* pick location */
1213 int dist, nxtdist, d2, nd2;
1215 dist = distmin(ux, uy, tx, ty);
1216 d2 = dist2(ux, uy, tx, ty);
1217 for (tx = 1; tx < COLNO; ++tx)
1218 for (ty = 0; ty < ROWNO; ++ty)
1219 if (travel[tx][ty]) {
1220 nxtdist = distmin(ux, uy, tx, ty);
1221 if (nxtdist == dist && couldsee(tx, ty)) {
1222 nd2 = dist2(ux, uy, tx, ty);
1224 /* prefer non-zigzag path */
1229 } else if (nxtdist < dist && couldsee(tx, ty)) {
1233 d2 = dist2(ux, uy, tx, ty);
1237 if (px == u.ux && py == u.uy) {
1238 /* no guesses, just go in the general direction */
1239 u.dx = sgn(u.tx - u.ux);
1240 u.dy = sgn(u.ty - u.uy);
1241 if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
1247 /* Use of warning glyph is arbitrary. It stands out. */
1248 tmp_at(DISP_ALL, warning_to_glyph(2));
1251 if (flags.runmode == RUN_CRAWL) {
1257 tmp_at(DISP_END, 0);
1279 /* try to escape being stuck in a trapped state by walking out of it;
1280 return true iff moving should continue to intended destination
1281 (all failures and most successful escapes leave hero at original spot) */
1283 trapmove(x, y, desttrap)
1284 int x, y; /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
1285 struct trap *desttrap; /* nonnull if another trap at <x,y> */
1288 const char *predicament, *culprit;
1289 char *steedname = !u.usteed ? (char *) 0 : y_monnam(u.usteed);
1292 return TRUE; /* sanity check */
1294 switch (u.utraptype) {
1296 if (flags.verbose) {
1298 predicament = "caught in a bear trap";
1300 predicament = "
\8cF
\82Ìã©
\82É
\82Â
\82©
\82Ü
\82Á
\82½";
1303 Norep("%s is %s.", upstart(steedname), predicament);
1305 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1308 Norep("You are %s.", predicament);
1310 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1312 /* [why does diagonal movement give quickest escape?] */
1313 if ((u.dx && u.dy) || !rn2(5))
1317 if (desttrap && desttrap->tseen
1318 && (desttrap->ttyp == PIT || desttrap->ttyp == SPIKED_PIT))
1319 return TRUE; /* move into adjacent pit */
1320 /* try to escape; position stays same regardless of success */
1324 if (uwep && uwep->oartifact == ART_STING) {
1327 pline("Sting cuts through the web!");
1329 pline("
\83X
\83e
\83B
\83\93\83O
\82Í
\82
\82à
\82Ì
\91\83\82ð
\90Ø
\82è
\82³
\82¢
\82½
\81I");
1330 break; /* escape trap but don't move */
1333 if (flags.verbose) {
1335 predicament = "stuck to the web";
1337 predicament = "
\82
\82à
\82Ì
\91\83\82É
\82Ð
\82Á
\82©
\82©
\82Á
\82½";
1340 Norep("%s is %s.", upstart(steedname), predicament);
1342 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1345 Norep("You are %s.", predicament);
1347 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1352 pline("%s breaks out of the web.", upstart(steedname));
1354 pline("%s
\82Í
\82
\82à
\82Ì
\91\83\82ð
\89ó
\82µ
\82½
\81D", upstart(steedname));
1357 You("disentangle yourself.");
1359 You("
\8e©
\95ª
\82Å
\82Ù
\82Ç
\82¢
\82½
\81D");
1363 if (flags.verbose) {
1365 predicament = "stuck in the lava";
1367 predicament = "
\97n
\8aâ
\82É
\82Í
\82Ü
\82Á
\82½";
1370 Norep("%s is %s.", upstart(steedname), predicament);
1372 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1375 Norep("You are %s.", predicament);
1377 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1379 if (!is_lava(x, y)) {
1381 if ((u.utrap & 0xff) == 0) {
1385 You("lead %s to the edge of the lava.", steedname);
1387 You("%s
\82ð
\97n
\8aâ
\82Ì
\92[
\82Ü
\82Å
\93±
\82¢
\82½
\81D", steedname);
1390 You("pull yourself to the edge of the lava.");
1392 You("
\97n
\8aâ
\82Ì
\92[
\82Ü
\82Å
\82©
\82ë
\82¤
\82¶
\82Ä
\81C
\82½
\82Ç
\82è
\82Â
\82¢
\82½
\81D");
1399 anchored = (u.utraptype == TT_BURIEDBALL);
1403 cc.x = u.ux, cc.y = u.uy;
1404 /* can move normally within radius 1 of buried ball */
1405 if (buried_ball(&cc) && dist2(x, y, cc.x, cc.y) <= 2) {
1406 /* ugly hack: we need to issue some message here
1407 in case "you are chained to the buried ball"
1408 was the most recent message given, otherwise
1409 our next attempt to move out of tether range
1410 after this successful move would have its
1411 can't-do-that message suppressed by Norep */
1414 Norep("You move within the chain's reach.");
1416 Norep("
\8d½
\82ª
\93Í
\82
\94Í
\88Í
\82É
\88Ú
\93®
\82Å
\82«
\82é
\81D");
1421 if (flags.verbose) {
1424 predicament = "chained to the";
1425 culprit = "buried ball";
1427 predicament = "
\82Æ
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é";
1428 culprit = "
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é
\8b\85";
1432 predicament = "stuck in the";
1433 culprit = surface(u.ux, u.uy);
1435 predicament = "
\82É
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é";
1436 culprit = surface(u.ux, u.uy);
1442 Norep("You and %s are %s %s.", steedname, predicament,
1445 Norep("
\82 \82È
\82½
\82Æ%s
\82Í%s%s
\81D", steedname, culprit,
1450 Norep("%s is %s %s.", upstart(steedname), predicament,
1453 Norep("%s
\82Í%s%s
\81D", steedname, culprit,
1458 Norep("You are %s %s.", predicament, culprit);
1460 Norep("
\82 \82È
\82½
\82Í%s
\82É%s
\81D", culprit, predicament);
1465 pline("%s finally %s free.", upstart(steedname),
1466 !anchored ? "lurches" : "wrenches the ball");
1468 pline("%s
\82Í%s
\82â
\82Á
\82Æ
\8e©
\97R
\82É
\82È
\82Á
\82½
\81D", upstart(steedname),
1469 !anchored ? "
\82à
\82ª
\82¢
\82Ä" : "
\93S
\8b\85\82ð
\82à
\82¬
\8eæ
\82Á
\82Ä");
1473 You("finally %s free.",
1474 !anchored ? "wriggle" : "wrench the ball");
1476 You("%s
\82â
\82Á
\82Æ
\8e©
\97R
\82É
\82È
\82Á
\82½
\81D",
1477 !anchored ? "
\82à
\82ª
\82¢
\82Ä" : "
\93S
\8b\85\82ð
\82à
\82¬
\8eæ
\82Á
\82Ä");
1480 buried_ball_to_punishment();
1484 impossible("trapmove: stuck in unknown trap? (%d)",
1494 if (!youmonst.data->mmove) {
1496 You("are rooted %s.",
1497 Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
1501 You("
\82»
\82Ì
\8fê
\82É
\97§
\82¿
\82·
\82
\82ñ
\82¾
\81D");
1512 register struct monst *mtmp;
1513 register struct rm *tmpr;
1514 register xchar x, y;
1515 struct trap *trap = NULL;
1518 xchar chainx = 0, chainy = 0,
1519 ballx = 0, bally = 0; /* ball&chain new positions */
1520 int bc_control = 0; /* control for ball&chain */
1521 boolean cause_delay = FALSE; /* dragging ball will skip a move */
1523 u_wipe_engr(rnd(5));
1525 if (context.travel) {
1526 if (!findtravelpath(FALSE))
1527 (void) findtravelpath(TRUE);
1528 context.travel1 = 0;
1531 if (((wtcap = near_capacity()) >= OVERLOADED
1532 || (wtcap > SLT_ENCUMBER
1533 && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1534 : (u.uhp < 10 && u.uhp != u.uhpmax))))
1535 && !Is_airlevel(&u.uz)) {
1536 if (wtcap < OVERLOADED) {
1538 You("don't have enough stamina to move.");
1540 You("
\82Ö
\82Æ
\82Ö
\82Æ
\82Å
\93®
\82¯
\82È
\82¢
\81D");
1541 exercise(A_CON, FALSE);
1544 You("collapse under your load.");
1546 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\93|
\82ê
\82½
\81D");
1552 u.ux = x = u.ustuck->mx;
1553 u.uy = y = u.ustuck->my;
1556 if (Is_airlevel(&u.uz) && rn2(4) && !Levitation && !Flying) {
1560 You("tumble in place.");
1562 You("
\82»
\82Ì
\8fê
\82Å
\93|
\82ê
\82½
\81D");
1563 exercise(A_DEX, FALSE);
1567 You_cant("control your movements very well.");
1569 You("
\82¤
\82Ü
\82
\95à
\82¯
\82È
\82¢
\81D");
1573 pline("It's hard to walk in thin air.");
1575 pline("
\8bó
\92\86\82ð
\95à
\82
\82Ì
\82Í
\93ï
\82µ
\82¢
\81D");
1576 exercise(A_DEX, TRUE);
1582 /* check slippery ice */
1583 on_ice = !Levitation && is_ice(u.ux, u.uy);
1585 static int skates = 0;
1587 skates = find_skates();
1588 if ((uarmf && uarmf->otyp == skates) || resists_cold(&youmonst)
1589 || Flying || is_floater(youmonst.data)
1590 || is_clinger(youmonst.data) || is_whirly(youmonst.data))
1592 else if (!rn2(Cold_resistance ? 3 : 2)) {
1593 HFumbling |= FROMOUTSIDE;
1594 HFumbling &= ~TIMEOUT;
1595 HFumbling += 1; /* slip on next move */
1598 if (!on_ice && (HFumbling & FROMOUTSIDE))
1599 HFumbling &= ~FROMOUTSIDE;
1603 if (Stunned || (Confusion && !rn2(5))) {
1604 register int tries = 0;
1614 } while (!isok(x, y) || bad_rock(youmonst.data, x, y));
1616 /* turbulence might alter your actual destination */
1619 if (!u.dx && !u.dy) {
1630 if (((trap = t_at(x, y)) && trap->tseen)
1631 || (Blind && !Levitation && !Flying && !is_clinger(youmonst.data)
1632 && is_pool_or_lava(x, y) && levl[x][y].seenv)) {
1633 if (context.run >= 2) {
1641 if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
1642 if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
1643 /* perhaps it fled (or was teleported or ... ) */
1645 } else if (sticks(youmonst.data)) {
1646 /* When polymorphed into a sticking monster,
1647 * u.ustuck means it's stuck to you, not you to it.
1650 You("release %s.", mon_nam(u.ustuck));
1652 You("%s
\82ð
\95ú
\82µ
\82½
\81D", mon_nam(u.ustuck));
1655 /* If holder is asleep or paralyzed:
1656 * 37.5% chance of getting away,
1657 * 12.5% chance of waking/releasing it;
1659 * 7.5% chance of getting away.
1660 * [strength ought to be a factor]
1661 * If holder is tame and there is no conflict,
1662 * guaranteed escape.
1664 switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
1670 You("pull free from %s.", mon_nam(u.ustuck));
1672 You("%s
\82ð
\82Ð
\82«
\82Í
\82È
\82µ
\82½
\81D", mon_nam(u.ustuck));
1676 if (!u.ustuck->mcanmove) {
1677 /* it's free to move on next turn */
1678 u.ustuck->mfrozen = 1;
1679 u.ustuck->msleeping = 0;
1683 if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf)
1686 You("cannot escape from %s!", mon_nam(u.ustuck));
1688 You("%s
\82©
\82ç
\93¦
\82°
\82ç
\82ê
\82È
\82¢
\81I", mon_nam(u.ustuck));
1697 /* Don't attack if you're running, and can see it */
1698 /* We should never get here if forcefight */
1699 if (context.run && ((!Blind && mon_visible(mtmp)
1700 && ((mtmp->m_ap_type != M_AP_FURNITURE
1701 && mtmp->m_ap_type != M_AP_OBJECT)
1702 || Protection_from_shape_changers))
1703 || sensemon(mtmp))) {
1717 /* attack monster */
1720 /* only attack if we know it's there */
1721 /* or if we used the 'F' command to fight blindly */
1722 /* or if it hides_under, in which case we call attack() to print
1723 * the Wait! message.
1724 * This is different from ceiling hiders, who aren't handled in
1728 /* If they used a 'm' command, trying to move onto a monster
1729 * prints the below message and wastes a turn. The exception is
1730 * if the monster is unseen and the player doesn't remember an
1731 * invisible monster--then, we fall through to attack() and
1732 * attack_check(), which still wastes a turn, but prints a
1733 * different message and makes the player remember the monster.
1736 && (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))) {
1737 if (mtmp->m_ap_type && !Protection_from_shape_changers
1739 stumble_onto_mimic(mtmp);
1740 else if (mtmp->mpeaceful && !Hallucination)
1742 pline("Pardon me, %s.", m_monnam(mtmp));
1744 pline("
\82¿
\82å
\82Á
\82Æ
\82²
\82ß
\82ñ
\82È
\82³
\82¢
\82æ
\81C%s
\82³
\82ñ
\81D", m_monnam(mtmp));
1747 You("move right into %s.", mon_nam(mtmp));
1749 You("%s
\82Ì
\82»
\82Î
\82É
\88Ú
\93®
\82µ
\82½
\81D", mon_nam(mtmp));
1752 if (context.forcefight || !mtmp->mundetected || sensemon(mtmp)
1753 || ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)
1754 && !is_safepet(mtmp))) {
1755 /* try to attack; note that it might evade */
1756 /* also, we don't attack tame when _safepet_ */
1762 /* specifying 'F' with no monster wastes a turn */
1763 if (context.forcefight
1764 /* remembered an 'I' && didn't use a move command */
1765 || (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
1766 struct obj *boulder = 0;
1767 boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
1768 solid = !accessible(x, y);
1769 int glyph = glyph_at(x, y); /* might be monster */
1773 boulder = sobj_at(BOULDER, x, y);
1774 /* if a statue is displayed at the target location,
1775 player is attempting to attack it [and boulder
1776 handling below is suitable for handling that] */
1777 if (glyph_is_statue(glyph)
1778 || (Hallucination && glyph_is_monster(glyph)))
1779 boulder = sobj_at(STATUE, x, y);
1781 /* force fight at boulder/statue or wall/door while wielding
1782 pick: start digging to break the boulder or wall */
1783 if (context.forcefight
1785 && uwep && dig_typ(uwep, x, y)
1786 /* should we dig? */
1787 && !glyph_is_invisible(glyph) && !glyph_is_monster(glyph)) {
1788 (void) use_pick_axe2(uwep);
1793 /* about to become known empty -- remove 'I' if present */
1796 map_object(boulder, TRUE);
1798 glyph = glyph_at(x, y); /* might have just changed */
1801 Strcpy(buf, ansimpleoname(boulder));
1802 else if (Underwater && !is_pool(x, y))
1803 /* Underwater, targetting non-water; the map just shows blank
1804 because you don't see remembered terrain while underwater;
1805 although the hero can attack an adjacent monster this way,
1806 assume he can't reach out far enough to distinguish terrain */
1808 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
1812 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
1813 ? "
\8bó
\8bC
\82Ì
\96A"
1814 : "
\89½
\82à
\82È
\82¢
\82Æ
\82±
\82ë");
1817 /* glyph might indicate unseen terrain if hero is blind;
1818 unlike searching, this won't reveal what that terrain is
1819 (except for solid rock, where the glyph would otherwise
1820 yield ludicrous "dark part of a room") */
1823 (levl[x][y].typ == STONE)
1825 : glyph_is_cmap(glyph)
1826 ? the(defsyms[glyph_to_cmap(glyph)].explanation)
1827 : (const char *) "an unknown obstacle");
1830 (levl[x][y].typ == STONE)
1832 : glyph_is_cmap(glyph)
1833 ? the(defsyms[glyph_to_cmap(glyph)].explanation)
1834 : (const char *) "
\95s
\96¾
\82È
\8fá
\8aQ
\95¨");
1836 /* note: 'solid' is misleadingly named and catches pools
1837 of water and lava as well as rock and walls */
1840 Strcpy(buf, "thin air");
1842 Strcpy(buf, "
\89½
\82à
\82È
\82¢
\8bó
\92\86");
1845 !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
1846 explo ? "explode at" : "attack", buf);
1849 !(boulder || solid) ? "" : !explo ? "
\8cø
\89Ê
\82È
\82" : "
\82Þ
\82¾
\82É",
1850 buf, explo ? "
\82Å
\94\9a\94
\82µ
\82½" : "
\82ð
\8dU
\8c\82\82µ
\82½");
1856 u.mh = -1; /* dead in the current form */
1861 if (glyph_is_invisible(levl[x][y].glyph)) {
1865 /* not attacking an animal, so we try to move */
1866 if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
1875 if (!trapmove(x, y, trap))
1879 if (!test_move(u.ux, u.uy, x - u.ux, y - u.uy, DO_MOVE)) {
1880 if (!context.door_opened) {
1887 /* Move ball and chain. */
1889 if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy,
1890 &cause_delay, TRUE))
1893 /* Check regions entering/leaving */
1894 if (!in_out_region(x, y))
1897 /* now move the hero */
1901 /* Move your steed, too */
1903 u.usteed->mx = u.ux;
1904 u.usteed->my = u.uy;
1909 * If safepet at destination then move the pet to the hero's
1910 * previous location using the same conditions as in attack().
1911 * there are special extenuating circumstances:
1912 * (1) if the pet dies then your god angers,
1913 * (2) if the pet gets trapped then your god may disapprove,
1914 * (3) if the pet was already trapped and you attempt to free it
1915 * not only do you encounter the trap but you may frighten your
1916 * pet causing it to go wild! moral: don't abuse this privilege.
1918 * Ceiling-hiding pets are skipped by this section of code, to
1919 * be caught by the normal falling-monster code.
1921 if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
1922 /* if trapped, there's a chance the pet goes wild */
1923 if (mtmp->mtrapped) {
1924 if (!rn2(mtmp->mtame)) {
1925 mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
1927 m_unleash(mtmp, TRUE);
1933 mtmp->mundetected = 0;
1934 if (mtmp->m_ap_type)
1936 else if (!mtmp->mtame)
1937 newsym(mtmp->mx, mtmp->my);
1939 if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
1940 && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
1941 && sobj_at(BOULDER, trap->tx, trap->ty)) {
1942 /* can't swap places with pet pinned in a pit by a boulder */
1943 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
1944 } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
1945 /* can't swap places when pet can't move to your spot */
1946 u.ux = u.ux0, u.uy = u.uy0;
1948 You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp)));
1950 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\8eÎ
\82ß
\82É
\93®
\82¯
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
1951 } else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0)
1952 && bad_rock(mtmp->data, u.ux0, y)
1953 && (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
1954 /* can't swap places when pet won't fit thru the opening */
1955 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
1957 You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
1959 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
1961 char pnambuf[BUFSZ];
1963 /* save its current description in case of polymorph */
1964 Strcpy(pnambuf, y_monnam(mtmp));
1966 remove_monster(x, y);
1967 place_monster(mtmp, u.ux0, u.uy0);
1969 newsym(u.ux0, u.uy0);
1972 You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
1977 mtmp->mtame ? "
\82Æ
\8fê
\8f\8a\82ð
\93ü
\82ê
\8a·
\82í
\82Á" : "
\82ð
\95|
\82ª
\82ç
\82¹");
1980 /* check for displacing it into pools and traps */
1981 switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
1984 case 1: /* trapped */
1985 case 3: /* changed levels */
1986 /* there's already been a trap message, reinforce it */
1991 /* drowned or died...
1992 * you killed your pet by direct action, so get experience
1993 * and possibly penalties;
1994 * we want the level gain message, if it happens, to occur
1995 * before the guilt message below
1998 /* minliquid() and mintrap() call mondead() rather than
1999 killed() so we duplicate some of the latter here */
2002 u.uconduct.killer++;
2003 mndx = monsndx(mtmp->data);
2004 tmp = experience(mtmp, (int) mvitals[mndx].died);
2005 more_experienced(tmp, 0);
2006 newexplevel(); /* will decide if you go up */
2008 /* That's no way to treat a pet! Your god gets angry.
2010 * [This has always been pretty iffy. Why does your
2011 * patron deity care at all, let alone enough to get mad?]
2015 You_feel("guilty about losing your pet like this.");
2017 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");
2023 pline("that's strange, unknown mintrap result!");
2029 reset_occupations();
2031 if (context.run < 8)
2032 if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ)
2033 || IS_FURNITURE(tmpr->typ))
2037 if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) || u.dx
2039 (void) hideunder(&youmonst);
2042 * Mimics (or whatever) become noticeable if they move and are
2043 * imitating something that doesn't move. We could extend this
2044 * to non-moving monsters...
2046 if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
2047 || youmonst.m_ap_type == M_AP_FURNITURE))
2048 youmonst.m_ap_type = M_AP_NOTHING;
2050 check_leash(u.ux0, u.uy0);
2052 if (u.ux0 != u.ux || u.uy0 != u.uy) {
2054 /* Clean old position -- vision_recalc() will print our new one. */
2055 newsym(u.ux0, u.uy0);
2056 /* Since the hero has moved, adjust what can be seen/unseen. */
2057 vision_recalc(1); /* Do the work now in the recover time. */
2058 invocation_message();
2061 if (Punished) /* put back ball and chain */
2062 move_bc(0, bc_control, ballx, bally, chainx, chainy);
2066 /* delay next move because of ball dragging */
2067 /* must come after we finished picking up, in spoteffects() */
2070 multi_reason = "dragging an iron ball";
2074 if (context.run && flags.runmode != RUN_TPORT) {
2075 /* display every step or every 7th step depending upon mode */
2076 if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
2081 if (flags.runmode == RUN_CRAWL) {
2091 /* combat increases metabolism */
2095 /* this used to be part of domove() when moving to a monster's
2096 position, but is now called by attack() so that it doesn't
2097 execute if you decline to attack a peaceful monster */
2099 if ((moves % 3L) != 0L && near_capacity() >= HVY_ENCUMBER) {
2100 int *hp = (!Upolyd ? &u.uhp : &u.mh);
2106 You("pass out from exertion!");
2108 You("
\8bC
\90â
\82µ
\82½
\81D");
2109 exercise(A_CON, FALSE);
2110 fall_asleep(-10, FALSE);
2113 return (boolean) (multi < 0); /* might have fainted (forced to sleep) */
2117 invocation_message()
2119 /* a special clue-msg when on the Invocation position */
2120 if (invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
2122 struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
2124 nomul(0); /* stop running or travelling */
2127 Sprintf(buf, "beneath %s", y_monnam(u.usteed));
2129 Sprintf(buf, "%s
\82Ì
\89º
\82É", y_monnam(u.usteed));
2130 else if (Levitation || Flying)
2132 Strcpy(buf, "beneath you");
2134 Strcpy(buf, "
\89º
\95û
\82É");
2137 Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
2139 Strcpy(buf, "
\91«
\8c³
\82É");
2142 You_feel("a strange vibration %s.", buf);
2144 You("%s
\8aï
\96
\82È
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D", buf);
2145 u.uevent.uvibrated = 1;
2146 if (otmp && otmp->spe == 7 && otmp->lamplit)
2148 pline("%s %s!", The(xname(otmp)),
2149 Blind ? "throbs palpably" : "glows with a strange light");
2151 pline("%s
\82Í%s
\82µ
\82½
\81I", The(xname(otmp)),
2152 Blind ? "
\82©
\82·
\82©
\82É
\90U
\93®" : "
\8aï
\96
\82È
\8cõ
\82ð
\94");
2157 /* moving onto different terrain;
2158 might be going into solid rock, inhibiting levitation or flight,
2159 or coming back out of such, reinstating levitation/flying */
2163 struct rm *lev = &levl[u.ux][u.uy];
2164 boolean blocklev = (IS_ROCK(lev->typ) || closed_door(u.ux, u.uy)
2165 || (Is_waterlevel(&u.uz) && lev->typ == WATER));
2168 /* called from spoteffects(), skip float_down() */
2171 You_cant("levitate in here.");
2173 You_cant("
\82±
\82±
\82Å
\82Í
\95\82\97V
\82Å
\82«
\82È
\82¢
\81D");
2174 BLevitation |= FROMOUTSIDE;
2175 } else if (BLevitation) {
2176 BLevitation &= ~FROMOUTSIDE;
2180 /* the same terrain that blocks levitation also blocks flight */
2184 You_cant("fly in here.");
2186 You_cant("
\82±
\82±
\82Å
\82Í
\94ò
\82×
\82È
\82¢
\81D");
2187 BFlying |= FROMOUTSIDE;
2188 } else if (BFlying) {
2189 BFlying &= ~FROMOUTSIDE;
2190 float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
2191 /* [minor bug: we don't know whether this is beginning flight or
2192 resuming it; that could be tracked so that this message could
2193 be adjusted to "resume flying", but isn't worth the effort...] */
2196 You("start flying.");
2198 You("
\94ò
\82Ñ
\82Í
\82¶
\82ß
\82½
\81D");
2202 /* extracted from spoteffects; called by spoteffects to check for entering or
2203 leaving a pool of water/lava, and by moveloop to check for staying on one
2205 returns true to skip rest of spoteffects */
2207 pooleffects(newspot)
2208 boolean newspot; /* true if called by spoteffects */
2210 /* check for leaving water */
2212 boolean still_inwater = FALSE; /* assume we're getting out */
2214 if (!is_pool(u.ux, u.uy)) {
2215 if (Is_waterlevel(&u.uz))
2217 You("pop into an air bubble.");
2219 You("
\82Ð
\82å
\82¢
\82Æ
\8bó
\8bC
\82Ì
\96A
\82É
\93ü
\82Á
\82½
\81D");
2220 else if (is_lava(u.ux, u.uy))
2222 You("leave the water..."); /* oops! */
2224 You("
\90\85\82©
\82ç
\94²
\82¯
\82¾
\82µ
\82½
\81D
\81D
\81D"); /* oops! */
2228 You("are on solid %s again.",
2229 is_ice(u.ux, u.uy) ? "ice" : "land");
2231 You("
\8cÅ
\82¢%s
\82Ì
\8fã
\82É
\82Ü
\82½
\96ß
\82Á
\82½
\81D",
2232 is_ice(u.ux, u.uy) ? "
\95X" : "
\92n
\96Ê");
2234 } else if (Is_waterlevel(&u.uz)) {
2235 still_inwater = TRUE;
2236 } else if (Levitation) {
2238 You("pop out of the water like a cork!");
2240 You("
\83R
\83\8b\83N
\82Ì
\82æ
\82¤
\82É
\94ò
\82Ñ
\82¾
\82µ
\82½
\81I");
2241 } else if (Flying) {
2243 You("fly out of the water.");
2245 You("
\90\85\82©
\82ç
\94ò
\82Ñ
\82¾
\82µ
\82½
\81D");
2246 } else if (Wwalking) {
2248 You("slowly rise above the surface.");
2250 You("
\82ä
\82Á
\82
\82è
\90\85\96Ê
\82Ü
\82Å
\8fã
\82ª
\82Á
\82½
\81D");
2252 still_inwater = TRUE;
2254 if (!still_inwater) {
2255 boolean was_underwater = (Underwater && !Is_waterlevel(&u.uz));
2257 u.uinwater = 0; /* leave the water */
2258 if (was_underwater) { /* restore vision */
2260 vision_full_recalc = 1;
2265 /* check for entering water or lava */
2266 if (!u.ustuck && !Levitation && !Flying && is_pool_or_lava(u.ux, u.uy)) {
2268 && (is_flyer(u.usteed->data) || is_floater(u.usteed->data)
2269 || is_clinger(u.usteed->data))) {
2270 /* floating or clinging steed keeps hero safe (is_flyer() test
2271 is redundant; it can't be true since Flying yielded false) */
2273 } else if (u.usteed) {
2274 /* steed enters pool */
2275 dismount_steed(Underwater ? DISMOUNT_FELL : DISMOUNT_GENERIC);
2276 /* dismount_steed() -> float_down() -> pickup()
2277 (float_down doesn't do autopickup on Air or Water) */
2278 if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
2280 /* even if we actually end up at same location, float_down()
2281 has already done spoteffect()'s trap and pickup actions */
2283 check_special_room(FALSE); /* spoteffects */
2288 /* drown(),lava_effects() return true if hero changes
2289 location while surviving the problem */
2290 if (is_lava(u.ux, u.uy)) {
2293 } else if (!Wwalking
2294 && (newspot || !u.uinwater || !(Swimming || Amphibious))) {
2306 static int inspoteffects = 0;
2307 static coord spotloc;
2308 static int spotterrain;
2309 static struct trap *spottrap = (struct trap *) 0;
2310 static unsigned spottraptyp = NO_TRAP;
2311 struct trap *trap = t_at(u.ux, u.uy);
2312 register struct monst *mtmp;
2314 /* prevent recursion from affecting the hero all over again
2315 [hero poly'd to iron golem enters water here, drown() inflicts
2316 damage that triggers rehumanize() which calls spoteffects()...] */
2317 if (inspoteffects && u.ux == spotloc.x && u.uy == spotloc.y
2318 /* except when reason is transformed terrain (ice -> water) */
2319 && spotterrain == levl[u.ux][u.uy].typ
2320 /* or transformed trap (land mine -> pit) */
2321 && (!spottrap || !trap || trap->ttyp == spottraptyp))
2325 spotterrain = levl[u.ux][u.uy].typ;
2326 spotloc.x = u.ux, spotloc.y = u.uy;
2328 /* moving onto different terrain might cause Levitation to toggle */
2329 if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
2332 if (pooleffects(TRUE))
2335 check_special_room(FALSE);
2336 if (IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
2338 if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
2341 /* if levitation is due to time out at the end of this
2342 turn, allowing it to do so could give the perception
2343 that a trap here is being triggered twice, so adjust
2344 the timeout to prevent that */
2345 if (trap && (HLevitation & TIMEOUT) == 1L && !ELevitation
2346 && !(HLevitation & ~TIMEOUT)) {
2347 if (rn2(2)) { /* defer timeout */
2348 incr_itimeout(&HLevitation, 1L);
2349 } else { /* timeout early */
2350 if (float_down(I_SPECIAL | TIMEOUT, 0L)) {
2351 /* levitation has ended; we've already triggered
2352 any trap and [usually] performed autopickup */
2359 * If not a pit, pickup before triggering trap.
2360 * If pit, trigger trap before pickup.
2362 pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
2368 * dotrap on a fire trap calls melt_ice() which triggers
2369 * spoteffects() (again) which can trigger the same fire
2370 * trap (again). Use static spottrap to prevent that.
2371 * We track spottraptyp because some traps morph
2372 * (landmine to pit) and any new trap type
2373 * should get triggered.
2375 if (!spottrap || spottraptyp != trap->ttyp) {
2377 spottraptyp = trap->ttyp;
2378 dotrap(trap, 0); /* fall into arrow trap, etc. */
2379 spottrap = (struct trap *) 0;
2380 spottraptyp = NO_TRAP;
2386 /* Warning alerts you to ice danger */
2387 if (Warning && is_ice(u.ux, u.uy)) {
2388 static const char *const icewarnings[] = {
2390 "The ice seems very soft and slushy.",
2391 "You feel the ice shift beneath you!",
2392 "The ice, is gonna BREAK!", /* The Dead Zone */
2394 "
\95X
\82Í
\82Æ
\82Ä
\82à
\93î
\82ç
\82©
\82
\82Ä
\97n
\82¯
\82»
\82¤
\82¾
\81D",
2395 "
\82 \82È
\82½
\82Ì
\89º
\82Ì
\95X
\82ª
\93®
\82¢
\82½
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81I",
2396 "
\95X
\82ª
\89ó
\82ê
\82é
\82¼
\81I", /* The Dead Zone */
2399 long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
2400 if (time_left && time_left < 15L)
2401 pline1((time_left < 5L) ? icewarnings[2] : (time_left < 10L)
2405 if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
2406 mtmp->mundetected = mtmp->msleeping = 0;
2407 switch (mtmp->data->mlet) {
2410 pline("%s suddenly drops from the %s!", Amonnam(mtmp),
2411 ceiling(u.ux, u.uy));
2413 pline("%s
\82ª
\93Ë
\91R%s
\82©
\82ç
\97\8e\82¿
\82Ä
\82«
\82½
\81I",
2414 Amonnam(mtmp), ceiling(u.ux,u.uy));
2416 if (mtmp->mtame) /* jumps to greet you, not attack */
2418 else if (uarmh && is_metallic(uarmh))
2420 pline("Its blow glances off your %s.",
2422 pline("
\8dU
\8c\82\82Í
\82 \82È
\82½
\82Ì%s
\82ð
\82©
\82·
\82ß
\82½
\82¾
\82¯
\82¾
\82Á
\82½
\81D",
2423 helm_simple_name(uarmh));
2424 else if (u.uac + 3 <= rnd(20))
2426 You("are almost hit by %s!",
2427 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2429 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",
2430 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2435 You("are hit by %s!",
2436 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2438 You("
\97\8e\82¿
\82Ä
\82«
\82½%s
\82É
\93\96\82½
\82Á
\82½
\81I",
2439 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2442 if (Half_physical_damage)
2443 dmg = (dmg + 1) / 2;
2444 mdamageu(mtmp, dmg);
2447 default: /* monster surprises you. */
2450 pline("%s jumps near you from the %s.", Amonnam(mtmp),
2451 ceiling(u.ux, u.uy));
2453 pline("%s
\82ª%s
\82©
\82ç
\82 \82È
\82½
\82Ì
\8bß
\82
\82É
\94ò
\82ñ
\82Å
\82«
\82½
\81D", Amonnam(mtmp),
2454 ceiling(u.ux,u.uy));
2456 else if (mtmp->mpeaceful) {
2460 You("%s
\82ð
\8bÁ
\82©
\82µ
\82½
\81I",
2461 Blind && !sensemon(mtmp) ? something : a_monnam(mtmp));
2462 mtmp->mpeaceful = 0;
2465 pline("%s attacks you by surprise!", Amonnam(mtmp));
2467 pline("%s
\82Í
\8bÁ
\82¢
\82Ä
\82 \82È
\82½
\82ð
\8dU
\8c\82\82µ
\82½
\81I", Amonnam(mtmp));
2470 mnexto(mtmp); /* have to move the monster */
2473 if (!--inspoteffects) {
2474 spotterrain = STONE; /* 0 */
2475 spotloc.x = spotloc.y = 0;
2480 /* returns first matching monster */
2481 STATIC_OVL struct monst *
2482 monstinroom(mdat, roomno)
2483 struct permonst *mdat;
2486 register struct monst *mtmp;
2488 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2489 if (DEADMONSTER(mtmp))
2491 if (mtmp->data == mdat
2492 && index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
2495 return (struct monst *) 0;
2499 in_rooms(x, y, typewanted)
2500 register xchar x, y;
2501 register int typewanted;
2504 char rno, *ptr = &buf[4];
2505 int typefound, min_x, min_y, max_x, max_y_offset, step;
2506 register struct rm *lev;
2508 #define goodtype(rno) \
2510 || ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) \
2511 || ((typewanted == SHOPBASE) && (typefound > SHOPBASE)))
2513 switch (rno = levl[x][y].roomno) {
2522 default: /* i.e. a regular room # */
2532 else if (x >= COLNO)
2539 max_y_offset -= step;
2540 } else if ((min_y + max_y_offset) >= ROWNO)
2541 max_y_offset -= step;
2543 for (x = min_x; x <= max_x; x += step) {
2544 lev = &levl[x][min_y];
2546 if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
2550 if (y > max_y_offset)
2552 if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
2556 if (y > max_y_offset)
2558 if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
2565 /* is (x,y) in a town? */
2570 s_level *slev = Is_special(&u.uz);
2571 register struct mkroom *sroom;
2572 boolean has_subrooms = FALSE;
2574 if (!slev || !slev->flags.town)
2578 * See if (x,y) is in a room with subrooms, if so, assume it's the
2579 * town. If there are no subrooms, the whole level is in town.
2581 for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
2582 if (sroom->nsubrooms > 0) {
2583 has_subrooms = TRUE;
2584 if (inside_room(sroom, x, y))
2589 return !has_subrooms;
2594 register boolean newlev;
2596 char *ptr1, *ptr2, *ptr3, *ptr4;
2598 Strcpy(u.urooms0, u.urooms);
2599 Strcpy(u.ushops0, u.ushops);
2602 u.uentered[0] = '\0';
2604 u.ushops_entered[0] = '\0';
2605 Strcpy(u.ushops_left, u.ushops0);
2608 Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
2610 for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
2611 ptr4 = &u.ushops_entered[0];
2613 if (!index(u.urooms0, *ptr1))
2615 if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
2617 if (!index(u.ushops0, *ptr1))
2625 /* filter u.ushops0 -> u.ushops_left */
2626 for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
2627 if (!index(u.ushops, *ptr1))
2633 check_special_room(newlev)
2634 register boolean newlev;
2636 register struct monst *mtmp;
2639 move_update(newlev);
2642 u_left_shop(u.ushops_left, newlev);
2644 if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
2645 return; /* no entrance messages necessary */
2647 /* Did we just enter a shop? */
2648 if (*u.ushops_entered)
2649 u_entered_shop(u.ushops_entered);
2651 for (ptr = &u.uentered[0]; *ptr; ptr++) {
2652 int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
2653 boolean msg_given = TRUE;
2655 /* Did we just enter some other special room? */
2656 /* vault.c insists that a vault remain a VAULT,
2657 * and temples should remain TEMPLEs,
2658 * but everything else gives a message only the first time */
2662 pline("Welcome to David's treasure zoo!");
2664 pline("
\83f
\83r
\83b
\83g
\95ó
\94 \93®
\95¨
\89\80\82É
\82æ
\82¤
\82±
\82»
\81I");
2668 pline("It %s rather %s down here.", Blind ? "feels" : "looks",
2669 Blind ? "humid" : "muddy");
2671 pline("
\82©
\82È
\82è%s
\81D",
2672 Blind ? "
\8e¼
\8bC
\82ª
\82 \82é
\8fê
\8f\8a\82Ì
\82æ
\82¤
\82¾"
2673 : "
\82Ç
\82ë
\82Ç
\82ë
\82µ
\82Ä
\82¢
\82é
\8fê
\8f\8a\82¾");
2678 You("enter an opulent throne room!");
2680 You("
\89Ø
\82â
\82©
\82È
\8bÊ
\8dÀ
\82Ì
\8aÔ
\82É
\93ü
\82Á
\82½
\81I");
2684 You("enter a leprechaun hall!");
2686 You("
\83\8c\83v
\83\89\83R
\81[
\83\93\83z
\81[
\83\8b\82É
\93ü
\82Á
\82½
\81I");
2691 const char *run = locomotion(youmonst.data, "Run");
2692 pline("%s away! %s away!", run, run);
2694 pline("
\93¦
\82°
\82ë
\81I
\93¦
\82°
\82ë
\81I");
2698 You("have an uncanny feeling...");
2700 You("
\95s
\8bC
\96¡
\82È
\8a´
\82¶
\82ª
\82µ
\82½
\81D
\81D
\81D");
2704 You("enter a giant beehive!");
2706 You("
\8b\90\91å
\82È
\96I
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2710 You("enter a disgusting nest!");
2712 You("
\82Þ
\82Á
\82Æ
\82·
\82é
\8fL
\82¢
\82Ì
\82·
\82é
\92¹
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2716 You("enter an anthole!");
2718 You("
\83A
\83\8a\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2721 if (monstinroom(&mons[PM_SOLDIER], roomno)
2722 || monstinroom(&mons[PM_SERGEANT], roomno)
2723 || monstinroom(&mons[PM_LIEUTENANT], roomno)
2724 || monstinroom(&mons[PM_CAPTAIN], roomno))
2726 You("enter a military barracks!");
2728 You("
\8cR
\91à
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81I");
2731 You("enter an abandoned barracks.");
2733 You("
\95ú
\92u
\82³
\82ê
\82½
\82Ü
\82Ü
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81D");
2736 struct monst *oracle = monstinroom(&mons[PM_ORACLE], roomno);
2738 if (!oracle->mpeaceful)
2740 verbalize("You're in Delphi, %s.", plname);
2742 verbalize("
\82¨
\82Ü
\82¦
\82Í
\83f
\83\8b\83t
\83@
\83C
\82Ì
\90_
\91õ
\8f\8a\82É
\82¢
\82é
\81D");
2745 verbalize("%s, %s, welcome to Delphi!",
2746 Hello((struct monst *) 0), plname);
2748 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",
2756 intemple(roomno + ROOMOFFSET);
2759 msg_given = (rt == TEMPLE);
2764 room_discovered(roomno);
2767 rooms[roomno].rtype = OROOM;
2768 if (!search_special(rt)) {
2769 /* No more room of that type */
2772 level.flags.has_court = 0;
2775 level.flags.has_swamp = 0;
2778 level.flags.has_morgue = 0;
2781 level.flags.has_zoo = 0;
2784 level.flags.has_barracks = 0;
2787 level.flags.has_temple = 0;
2790 level.flags.has_beehive = 0;
2794 if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
2795 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2796 if (DEADMONSTER(mtmp))
2798 if (!Stealth && !rn2(3))
2799 mtmp->msleeping = 0;
2811 struct trap *traphere = t_at(u.ux, u.uy);
2812 /* awful kludge to work around parse()'s pre-decrement */
2813 count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
2814 multi = 0; /* always reset */
2815 /* uswallow case added by GAN 01/29/87 */
2817 if (!u.ustuck->minvent) {
2818 if (is_animal(u.ustuck->data)) {
2820 You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
2822 You("%s
\82Ì
\90ã
\82ð
\8fE
\82Á
\82½
\81D", mon_nam(u.ustuck));
2824 pline("But it's kind of slimy, so you drop it.");
2826 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");
2829 You("don't %s anything in here to pick up.",
2830 Blind ? "feel" : "see");
2832 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82ª
\82È
\82¢%s
\81D",
2833 Blind ? "
\82æ
\82¤
\82¾" : "");
2837 int tmpcount = -count;
2838 return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
2841 if (is_pool(u.ux, u.uy)) {
2842 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
2843 || (Flying && !Breathless)) {
2845 You("cannot dive into the water to pick things up.");
2847 You("
\95¨
\82ð
\8fE
\82¢
\82 \82°
\82é
\82½
\82ß
\82É
\90\85\82É
\94ò
\82Ñ
\82±
\82ß
\82È
\82¢
\81D");
2849 } else if (!Underwater) {
2851 You_cant("even see the bottom, let alone pick up %s.", something);
2853 pline("
\92ê
\82³
\82¦
\8c©
\82¦
\82È
\82¢
\81C
\8fE
\82¤
\82Ì
\82Í
\82â
\82ß
\82æ
\82¤
\81D");
2857 if (is_lava(u.ux, u.uy)) {
2858 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
2859 || (Flying && !Breathless)) {
2861 You_cant("reach the bottom to pick things up.");
2863 You_cant("
\95¨
\82ð
\8fE
\82¢
\8fã
\82°
\82é
\82½
\82ß
\82É
\92ê
\82Ü
\82Å
\82¢
\82¯
\82È
\82¢
\81D");
2865 } else if (!likes_lava(youmonst.data)) {
2867 You("would burn to a crisp trying to pick things up.");
2869 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");
2873 if (!OBJ_AT(u.ux, u.uy)) {
2874 register struct rm *lev = &levl[u.ux][u.uy];
2875 if (IS_THRONE(lev->typ))
2877 pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
2879 pline("
\82±
\82ê
\82Í%s
\8fd
\82¢
\81I", lev->looted ? "
\82©
\82È
\82è" : "
\82·
\82²
\82");
2880 else if (IS_SINK(lev->typ))
2882 pline_The("plumbing connects it to the floor.");
2884 pline_The("
\94z
\8aÇ
\82Í
\8f°
\82É
\82Â
\82È
\82ª
\82Á
\82Ä
\82¢
\82é
\81D");
2885 else if (IS_GRAVE(lev->typ))
2887 You("don't need a gravestone. Yet.");
2889 pline("
\82 \82È
\82½
\82É
\82Í
\95æ
\90Î
\82Í
\95s
\97v
\82¾
\81D
\81D
\81D
\8d¡
\82Ì
\82Æ
\82±
\82ë
\81D");
2890 else if (IS_FOUNTAIN(lev->typ))
2892 You("could drink the water...");
2894 You("
\90\85\82ð
\88ù
\82ß
\82È
\82¢
\81D
\81D
\81D");
2895 else if (IS_DOOR(lev->typ) && (lev->doormask & D_ISOPEN))
2897 pline("It won't come off the hinges.");
2899 pline("
\83q
\83\93\83W
\82ð
\8aO
\82¹
\82È
\82¢
\81D");
2902 There("is nothing here to pick up.");
2904 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82Í
\82È
\82¢
\81D");
2907 if (!can_reach_floor(TRUE)) {
2908 if (traphere && uteetering_at_seen_pit(traphere))
2910 You("cannot reach the bottom of the pit.");
2912 You("
\97\8e\82µ
\8c\8a\82Ì
\92ê
\82É%s
\82ª
\93Í
\82©
\82È
\82©
\82Á
\82½
\81D", body_part(HAND));
2913 else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
2915 else if (Blind && !can_reach_floor(TRUE))
2917 You("cannot reach anything here.");
2919 You("
\89½
\82É
\82à
\93Í
\82©
\82È
\82¢
\81D");
2922 You("cannot reach the %s.", surface(u.ux, u.uy));
2924 You("%s
\82É
\82½
\82Ç
\82è
\82Â
\82
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D", surface(u.ux, u.uy));
2928 return pickup(-count);
2931 /* stop running if we see something interesting */
2932 /* turn around a corner if that is the only way we can proceed */
2933 /* do not turn left or right twice */
2937 register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
2938 register int corrct = 0, noturn = 0;
2939 register struct monst *mtmp;
2940 register struct trap *trap;
2942 /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
2943 /* they polymorphed while in the middle of a long move. */
2944 if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
2949 if (Blind || context.run == 0)
2951 for (x = u.ux - 1; x <= u.ux + 1; x++)
2952 for (y = u.uy - 1; y <= u.uy + 1; y++) {
2956 if (u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy)
2959 if (x == u.ux && y == u.uy)
2962 if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
2963 && mtmp->m_ap_type != M_AP_OBJECT
2964 && (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
2965 if ((context.run != 1 && !mtmp->mtame)
2966 || (x == u.ux + u.dx && y == u.uy + u.dy))
2970 if (levl[x][y].typ == STONE)
2972 if (x == u.ux - u.dx && y == u.uy - u.dy)
2975 if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM)
2976 || IS_AIR(levl[x][y].typ))
2978 else if (closed_door(x, y)
2979 || (mtmp && is_door_mappear(mtmp))) {
2980 if (x != u.ux && y != u.uy)
2982 if (context.run != 1)
2985 } else if (levl[x][y].typ == CORR) {
2987 if (levl[u.ux][u.uy].typ != ROOM) {
2988 if (context.run == 1 || context.run == 3
2989 || context.run == 8) {
2990 i = dist2(x, y, u.ux + u.dx, u.uy + u.dy);
2993 if (corrct == 1 && dist2(x, y, x0, y0) != 1)
3005 } else if ((trap = t_at(x, y)) && trap->tseen) {
3006 if (context.run == 1)
3007 goto bcorr; /* if you must */
3008 if (x == u.ux + u.dx && y == u.uy + u.dy)
3011 } else if (is_pool_or_lava(x, y)) {
3012 /* water and lava only stop you if directly in front, and stop
3013 * you even if you are running
3015 if (!Levitation && !Flying && !is_clinger(youmonst.data)
3016 && x == u.ux + u.dx && y == u.uy + u.dy)
3017 /* No Wwalking check; otherwise they'd be able
3018 * to test boots by trying to SHIFT-direction
3019 * into a pool and seeing if the game allowed it
3023 } else { /* e.g. objects or trap or stairs */
3024 if (context.run == 1)
3026 if (context.run == 8)
3030 if (((x == u.ux - u.dx) && (y != u.uy + u.dy))
3031 || ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
3037 } /* end for loops */
3039 if (corrct > 1 && context.run == 2)
3041 if ((context.run == 1 || context.run == 3 || context.run == 8) && !noturn
3042 && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) {
3043 /* make sure that we do not turn too far */
3045 if (u.dx == y0 - u.uy && u.dy == u.ux - x0)
3046 i = 2; /* straight turn right */
3048 i = -2; /* straight turn left */
3049 } else if (u.dx && u.dy) {
3050 if ((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
3051 i = -1; /* half turn left */
3053 i = 1; /* half turn right */
3055 if ((x0 - u.ux == y0 - u.uy && !u.dy)
3056 || (x0 - u.ux != y0 - u.uy && u.dy))
3057 i = 1; /* half turn right */
3059 i = -1; /* half turn left */
3062 i += u.last_str_turn;
3063 if (i <= 2 && i >= -2) {
3064 u.last_str_turn = i;
3071 /* check for a doorway which lacks its door (NODOOR or BROKEN) */
3076 struct rm *lev_p = &levl[x][y];
3078 if (!IS_DOOR(lev_p->typ))
3080 /* all rogue level doors are doorless but disallow diagonal access, so
3081 we treat them as if their non-existant doors were actually present */
3082 if (Is_rogue_level(&u.uz))
3084 return !(lev_p->doormask & ~(D_NODOOR | D_BROKEN));
3087 /* used by drown() to check whether hero can crawl from water to <x,y> */
3089 crawl_destination(x, y)
3092 /* is location ok in general? */
3093 if (!goodpos(x, y, &youmonst, 0))
3096 /* orthogonal movement is unrestricted when destination is ok */
3097 if (x == u.ux || y == u.uy)
3100 /* diagonal movement has some restrictions */
3101 if (NODIAG(u.umonnum))
3102 return FALSE; /* poly'd into a grid bug... */
3104 return TRUE; /* or a xorn... */
3105 /* pool could be next to a door, conceivably even inside a shop */
3106 if (IS_DOOR(levl[x][y].typ) && (!doorless_door(x, y) || block_door(x, y)))
3108 /* finally, are we trying to squeeze through a too-narrow gap? */
3109 return !(bad_rock(youmonst.data, u.ux, y)
3110 && bad_rock(youmonst.data, x, u.uy));
3113 /* something like lookaround, but we are not running */
3114 /* react only to monsters that might hit us */
3119 register struct monst *mtmp;
3121 /* Also see the similar check in dochugw() in monmove.c */
3122 for (x = u.ux - 1; x <= u.ux + 1; x++)
3123 for (y = u.uy - 1; y <= u.uy + 1; y++) {
3126 if (x == u.ux && y == u.uy)
3128 if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
3129 && mtmp->m_ap_type != M_AP_OBJECT
3130 && (!mtmp->mpeaceful || Hallucination)
3131 && (!is_hider(mtmp->data) || !mtmp->mundetected)
3132 && !noattacks(mtmp->data) && mtmp->mcanmove
3133 && !mtmp->msleeping /* aplvax!jcn */
3134 && !onscary(u.ux, u.uy, mtmp) && canspotmon(mtmp))
3145 return; /* This is a bug fix by ab@unido */
3146 u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
3150 multi_reason = NULL;
3151 context.travel = context.travel1 = context.mv = context.run = 0;
3154 /* called when a non-movement, multi-turn action has completed */
3157 const char *msg_override;
3159 multi = 0; /* caller will usually have done this already */
3161 nomovemsg = msg_override;
3162 else if (!nomovemsg)
3163 nomovemsg = You_can_move_again;
3168 multi_reason = NULL;
3177 static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES,
3178 SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
3179 TELEPORT_CONTROL, STEALTH, FAST, INVIS };
3181 if (moves <= wailmsg + 50)
3185 if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) {
3190 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3193 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3198 pline("%s is about to die.", who);
3200 pline("%s
\82Í
\8e\80\82É
\82©
\82¯
\82Ä
\82¢
\82é
\81D", who);
3202 for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
3203 if (u.uprops[powers[i]].intrinsic & INTRINSIC)
3207 pline(powercnt >= 4 ? "%s, all your powers will be lost..."
3209 pline(powercnt >= 4 ? "%s
\81C
\82 \82È
\82½
\82Ì
\91S
\82Ä
\82Ì
\97Í
\82Í
\8e¸
\82í
\82ê
\82Â
\82Â
\82 \82é
\81D
\81D
\81D"
3211 : "%s, your life force is running out.",
3213 : "%s
\81C
\82 \82È
\82½
\82Ì
\90¶
\96½
\97Í
\82Í
\90s
\82«
\82æ
\82¤
\82Æ
\82µ
\82Ä
\82¢
\82é
\81D
\81D
\81D",
3218 You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
3220 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"
3222 : "the howling of the CwnAnnwn...");
3224 : "
\83N
\81[
\83\93\81E
\83A
\83\93\83k
\81[
\83\93\82Ì
\89\93\96i
\82ª
\95·
\82±
\82¦
\82é
\81D
\81D
\81D");
3229 losehp(n, knam, k_format)
3231 register const char *knam;
3241 else if (n > 0 && u.mh * 10 < u.mhmax && Unchanging)
3247 if (u.uhp > u.uhpmax)
3248 u.uhpmax = u.uhp; /* perhaps n was negative */
3251 killer.format = k_format;
3252 if (killer.name != knam) /* the thing that killed you */
3253 Strcpy(killer.name, knam ? knam : "");
3257 pline("
\82 \82È
\82½
\82Í
\8e\80\82É
\82Ü
\82µ
\82½
\81D
\81D
\81D");
3259 } else if (n > 0 && u.uhp * 10 < u.uhpmax) {
3267 register long carrcap;
3269 carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
3271 /* consistent with can_carry() in mon.c */
3272 if (youmonst.data->mlet == S_NYMPH)
3273 carrcap = MAX_CARR_CAP;
3274 else if (!youmonst.data->cwt)
3275 carrcap = (carrcap * (long) youmonst.data->msize) / MZ_HUMAN;
3276 else if (!strongmonst(youmonst.data)
3277 || (strongmonst(youmonst.data)
3278 && (youmonst.data->cwt > WT_HUMAN)))
3279 carrcap = (carrcap * (long) youmonst.data->cwt / WT_HUMAN);
3282 if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
3283 || (u.usteed && strongmonst(u.usteed->data)))
3284 carrcap = MAX_CARR_CAP;
3286 if (carrcap > MAX_CARR_CAP)
3287 carrcap = MAX_CARR_CAP;
3289 if (EWounded_legs & LEFT_SIDE)
3291 if (EWounded_legs & RIGHT_SIDE)
3297 return (int) carrcap;
3300 static int wc; /* current weight_cap(); valid after call to inv_weight() */
3302 /* returns how far beyond the normal capacity the player is currently. */
3303 /* inv_weight() is negative if the player is below normal capacity. */
3307 register struct obj *otmp = invent;
3308 register int wt = 0;
3311 if (otmp->oclass == COIN_CLASS)
3312 wt += (int) (((long) otmp->quan + 50L) / 100L);
3313 else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
3322 * Returns 0 if below normal capacity, or the number of "capacity units"
3323 * over the normal capacity the player is loaded. Max is 5.
3326 calc_capacity(xtra_wt)
3329 int cap, wt = inv_weight() + xtra_wt;
3332 return UNENCUMBERED;
3335 cap = (wt * 2 / wc) + 1;
3336 return min(cap, OVERLOADED);
3342 return calc_capacity(0);
3348 int wt = inv_weight();
3350 return (wt - (2 * wc));
3357 if (near_capacity() >= EXT_ENCUMBER) {
3362 You_cant("do that while carrying so much stuff.");
3364 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");
3374 register struct obj *otmp = invent;
3375 register int ct = 0;
3378 if (incl_gold || otmp->invlet != GOLD_SYM)
3385 /* Counts the money in an object chain. */
3386 /* Intended use is for your or some monsters inventory, */
3387 /* now that u.gold/m.gold is gone.*/
3388 /* Counting money in a container might be possible too. */
3394 /* Must change when silver & copper is implemented: */
3395 if (otmp->oclass == COIN_CLASS)