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));
705 losehp(Maybe_Half_Phys(dmg), fell_on_sink, NO_KILLER_PREFIX);
706 exercise(A_DEX, FALSE);
708 selftouch("Falling, you");
710 selftouch("
\97\8e\82¿
\82È
\82ª
\82ç
\81C
\82 \82È
\82½
\82Í");
711 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
712 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) {
714 You("fell on %s.", doname(obj));
716 You("%s
\82Ì
\8fã
\82É
\97\8e\82¿
\82½
\81D",doname(obj));
718 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
721 losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink,
724 exercise(A_CON, FALSE);
726 ELevitation = save_ELev;
727 HLevitation = save_HLev;
731 * Interrupt multi-turn putting on/taking off of armor (in which
732 * case we reached the sink due to being teleported while busy;
733 * in 3.4.3, Boots_on()/Boots_off() [called via (*aftermv)() when
734 * 'multi' reaches 0] triggered a crash if we were donning/doffing
735 * levitation boots [because the Boots_off() below causes 'uarmf'
736 * to be null by the time 'aftermv' gets called]).
738 * Interrupt donning/doffing if we fall onto the sink, or if the
739 * code below is going to remove levitation boots even when we
740 * haven't fallen (innate floating or flying becoming unblocked).
742 if (ufall || lev_boots) {
743 (void) stop_donning(lev_boots ? uarmf : (struct obj *) 0);
744 /* recalculate in case uarmf just got set to null */
745 lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS);
748 /* remove worn levitation items */
749 ELevitation &= ~W_ARTI;
750 HLevitation &= ~(I_SPECIAL | TIMEOUT);
752 if (uleft && uleft->otyp == RIN_LEVITATION) {
757 if (uright && uright->otyp == RIN_LEVITATION) {
768 /* probably moot; we're either still levitating or went
769 through float_down(), but make sure BFlying is up to date */
773 /* intended to be called only on ROCKs or TREEs */
778 struct rm *lev = &levl[x][y];
780 return (boolean) !((IS_STWALL(lev->typ) || IS_TREE(lev->typ))
781 && (lev->wall_info & W_NONDIGGABLE));
788 return (boolean) !(IS_STWALL(levl[x][y].typ)
789 && (levl[x][y].wall_info & W_NONPASSWALL));
794 struct permonst *mdat;
797 return (boolean) ((Sokoban && sobj_at(BOULDER, x, y))
798 || (IS_ROCK(levl[x][y].typ)
799 && (!tunnels(mdat) || needspick(mdat)
801 && !(passes_walls(mdat) && may_passwall(x, y))));
804 /* caller has already decided that it's a tight diagonal; check whether a
805 monster--who might be the hero--can fit through, and if not then return
806 the reason why: 1: can't fit, 2: possessions won't fit, 3: sokoban */
807 int /* returns 0 if we can squeeze through */
808 cant_squeeze_thru(mon)
812 struct permonst *ptr = mon->data;
816 && !(amorphous(ptr) || is_whirly(ptr) || noncorporeal(ptr)
817 || slithy(ptr) || can_fog(mon)))
820 /* lugging too much junk? */
822 (mon == &youmonst) ? inv_weight() + weight_cap() : curr_mon_load(mon);
826 /* Sokoban restriction applies to hero only */
827 if (mon == &youmonst && Sokoban)
830 /* can squeeze through */
838 return (boolean) (Invocation_lev(&u.uz)
839 && x == inv_pos.x && y == inv_pos.y);
842 /* return TRUE if (dx,dy) is an OK place to move
843 * mode is one of DO_MOVE, TEST_MOVE or TEST_TRAV
846 test_move(ux, uy, dx, dy, mode)
852 register struct rm *tmpr = &levl[x][y];
853 register struct rm *ust;
855 context.door_opened = FALSE;
857 * Check for physical obstacles. First, the place we are going.
859 if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) {
860 if (Blind && mode == DO_MOVE)
862 if (Passes_walls && may_passwall(x, y)) {
864 } else if (tmpr->typ == IRONBARS) {
865 if ((dmgtype(youmonst.data, AD_RUST)
866 || dmgtype(youmonst.data, AD_CORR)) && mode == DO_MOVE
867 && still_chewing(x, y)) {
870 if (!(Passes_walls || passes_bars(youmonst.data))) {
871 if (iflags.mention_walls)
873 You("cannot pass through the bars.");
875 You("
\93S
\82Ì
\96_
\82ð
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
878 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
880 if (mode == DO_MOVE && still_chewing(x, y))
882 } else if (flags.autodig && !context.run && !context.nopick && uwep
884 /* MRKR: Automatic digging when wielding the appropriate tool */
886 (void) use_pick_axe2(uwep);
889 if (mode == DO_MOVE) {
890 if (Is_stronghold(&u.uz) && is_db_wall(x, y))
892 pline_The("drawbridge is up!");
894 pline("
\92µ
\82Ë
\8b´
\82Í
\8fã
\82Á
\82Ä
\82¢
\82é
\81I");
895 /* sokoban restriction stays even after puzzle is solved */
896 else if (Passes_walls && !may_passwall(x, y)
897 && In_sokoban(&u.uz))
899 pline_The("Sokoban walls resist your ability.");
901 pline_The("
\91q
\8cÉ
\94Ô
\82Ì
\95Ç
\82Í
\82 \82È
\82½
\82Ì
\94\
\97Í
\82É
\92ï
\8dR
\82µ
\82½
\81D");
902 else if (iflags.mention_walls)
904 pline("It's a wall.");
906 pline("
\82±
\82ê
\82Í
\95Ç
\82¾
\81D");
910 } else if (IS_DOOR(tmpr->typ)) {
911 if (closed_door(x, y)) {
912 if (Blind && mode == DO_MOVE)
916 else if (can_ooze(&youmonst)) {
919 You("ooze under the door.");
921 You("
\83h
\83A
\82Ì
\89º
\82©
\82ç
\82É
\82¶
\82Ý
\8fo
\82½
\81D");
922 } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
924 if (mode == DO_MOVE && still_chewing(x, y))
927 if (mode == DO_MOVE) {
928 if (amorphous(youmonst.data))
931 "try to ooze under the door, but can't squeeze your possessions through.");
933 "
\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");
934 if (flags.autoopen && !context.run && !Confusion
935 && !Stunned && !Fumbling) {
936 context.door_opened = context.move =
938 } else if (x == ux || y == uy) {
939 if (Blind || Stunned || ACURR(A_DEX) < 10
943 You_cant("lead %s through that closed door.",
945 You_cant("%s
\82É
\95Â
\82Ü
\82Á
\82½
\94à
\82ð
\92Ê
\89ß
\82³
\82¹
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D",
949 pline("Ouch! You bump into a door.");
951 pline("
\82¢
\82Ä
\82Á
\81I
\93ª
\82ð
\94à
\82É
\82Ô
\82Â
\82¯
\82½
\81D");
952 exercise(A_DEX, FALSE);
956 pline("That door is closed.");
958 pline("
\94à
\82Í
\95Â
\82Ü
\82Á
\82Ä
\82¢
\82é
\81D");
960 } else if (mode == TEST_TRAV)
966 if (dx && dy && !Passes_walls
967 && (!doorless_door(x, y) || block_door(x, y))) {
968 /* Diagonal moves into a door are not allowed. */
969 if (Blind && mode == DO_MOVE)
975 if (dx && dy && bad_rock(youmonst.data, ux, y)
976 && bad_rock(youmonst.data, x, uy)) {
977 /* Move at a diagonal. */
978 switch (cant_squeeze_thru(&youmonst)) {
982 You("cannot pass that way.");
984 You("
\92Ê
\82è
\82Ê
\82¯
\82Å
\82«
\82È
\82¢
\81D");
989 You("are carrying too much to get through.");
991 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
996 Your("body is too large to fit through.");
998 Your("
\91Ì
\82ª
\91å
\82«
\82·
\82¬
\82Ä
\92Ê
\82è
\82Ê
\82¯
\82ç
\82ê
\82È
\82¢
\81D");
1001 break; /* can squeeze through */
1003 } else if (dx && dy && worm_cross(ux, uy, x, y)) {
1004 /* consecutive long worm segments are at <ux,y> and <x,uy> */
1005 if (mode == DO_MOVE)
1006 pline("%s is in your way.", Monnam(m_at(ux, y)));
1009 /* Pick travel path that does not require crossing a trap.
1010 * Avoid water and lava using the usual running rules.
1011 * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
1012 if (context.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
1013 struct trap *t = t_at(x, y);
1016 || (!Levitation && !Flying && !is_clinger(youmonst.data)
1017 && is_pool_or_lava(x, y) && levl[x][y].seenv))
1021 ust = &levl[ux][uy];
1023 /* Now see if other things block our way . . */
1024 if (dx && dy && !Passes_walls && IS_DOOR(ust->typ)
1025 && (!doorless_door(ux, uy) || block_entry(x, y))) {
1026 /* Can't move at a diagonal out of a doorway with door. */
1030 if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
1031 if (!(Blind || Hallucination) && (context.run >= 2)
1032 && mode != TEST_TRAV)
1034 if (mode == DO_MOVE) {
1035 /* tunneling monsters will chew before pushing */
1036 if (tunnels(youmonst.data) && !needspick(youmonst.data)
1038 if (still_chewing(x, y))
1040 } else if (moverock() < 0)
1042 } else if (mode == TEST_TRAV) {
1045 /* don't pick two boulders in a row, unless there's a way thru */
1046 if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
1048 && !(tunnels(youmonst.data) && !needspick(youmonst.data))
1049 && !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK)
1050 && !((obj = carrying(WAN_DIGGING))
1051 && !objects[obj->otyp].oc_name_known))
1055 /* assume you'll be able to push it when you get there... */
1058 /* OK, it is a legal place to move. */
1063 static boolean trav_debug = FALSE;
1065 /* in this case, toggle display of travel debug info */
1066 int wiz_debug_cmd_traveldisplay()
1068 trav_debug = !trav_debug;
1074 * Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
1075 * A shortest path is returned. If guess is TRUE, consider various
1076 * inaccessible locations as valid intermediate path points.
1077 * Returns TRUE if a path was found.
1080 findtravelpath(guess)
1083 /* if travel to adjacent, reachable location, use normal movement rules */
1084 if (!guess && context.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1
1085 && !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
1087 if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
1091 iflags.travelcc.x = iflags.travelcc.y = -1;
1096 if (u.tx != u.ux || u.ty != u.uy) {
1097 xchar travel[COLNO][ROWNO];
1098 xchar travelstepx[2][COLNO * ROWNO];
1099 xchar travelstepy[2][COLNO * ROWNO];
1100 xchar tx, ty, ux, uy;
1101 int n = 1; /* max offset in travelsteps */
1102 int set = 0; /* two sets current and previous */
1103 int radius = 1; /* search radius */
1106 /* If guessing, first find an "obvious" goal location. The obvious
1107 * goal is the position the player knows of, or might figure out
1108 * (couldsee) that is closest to the target on a straight path.
1123 (void) memset((genericptr_t) travel, 0, sizeof(travel));
1124 travelstepx[0][0] = tx;
1125 travelstepy[0][0] = ty;
1130 for (i = 0; i < n; i++) {
1132 int x = travelstepx[set][i];
1133 int y = travelstepy[set][i];
1134 static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
1135 /* no diagonal movement for grid bugs */
1136 int dirmax = NODIAG(u.umonnum) ? 4 : 8;
1138 for (dir = 0; dir < dirmax; ++dir) {
1139 int nx = x + xdir[ordered[dir]];
1140 int ny = y + ydir[ordered[dir]];
1144 if ((!Passes_walls && !can_ooze(&youmonst)
1145 && closed_door(x, y)) || sobj_at(BOULDER, x, y)) {
1146 /* closed doors and boulders usually
1147 * cause a delay, so prefer another path */
1148 if (travel[x][y] > radius - 3) {
1149 travelstepx[1 - set][nn] = x;
1150 travelstepy[1 - set][nn] = y;
1151 /* don't change travel matrix! */
1156 if (test_move(x, y, nx - x, ny - y, TEST_TRAV)
1157 && (levl[nx][ny].seenv
1158 || (!Blind && couldsee(nx, ny)))) {
1159 if (nx == ux && ny == uy) {
1163 if (x == u.tx && y == u.ty) {
1165 /* reset run so domove run checks work */
1167 iflags.travelcc.x = iflags.travelcc.y =
1172 } else if (!travel[nx][ny]) {
1173 travelstepx[1 - set][nn] = nx;
1174 travelstepy[1 - set][nn] = ny;
1175 travel[nx][ny] = radius;
1184 /* Use of warning glyph is arbitrary. It stands out. */
1185 tmp_at(DISP_ALL, warning_to_glyph(1));
1186 for (i = 0; i < nn; ++i) {
1187 tmp_at(travelstepx[1 - set][i], travelstepy[1 - set][i]);
1190 if (flags.runmode == RUN_CRAWL) {
1194 tmp_at(DISP_END, 0);
1203 /* if guessing, find best location in travel matrix and go there */
1205 int px = tx, py = ty; /* pick location */
1206 int dist, nxtdist, d2, nd2;
1208 dist = distmin(ux, uy, tx, ty);
1209 d2 = dist2(ux, uy, tx, ty);
1210 for (tx = 1; tx < COLNO; ++tx)
1211 for (ty = 0; ty < ROWNO; ++ty)
1212 if (travel[tx][ty]) {
1213 nxtdist = distmin(ux, uy, tx, ty);
1214 if (nxtdist == dist && couldsee(tx, ty)) {
1215 nd2 = dist2(ux, uy, tx, ty);
1217 /* prefer non-zigzag path */
1222 } else if (nxtdist < dist && couldsee(tx, ty)) {
1226 d2 = dist2(ux, uy, tx, ty);
1230 if (px == u.ux && py == u.uy) {
1231 /* no guesses, just go in the general direction */
1232 u.dx = sgn(u.tx - u.ux);
1233 u.dy = sgn(u.ty - u.uy);
1234 if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
1240 /* Use of warning glyph is arbitrary. It stands out. */
1241 tmp_at(DISP_ALL, warning_to_glyph(2));
1244 if (flags.runmode == RUN_CRAWL) {
1250 tmp_at(DISP_END, 0);
1272 /* try to escape being stuck in a trapped state by walking out of it;
1273 return true iff moving should continue to intended destination
1274 (all failures and most successful escapes leave hero at original spot) */
1276 trapmove(x, y, desttrap)
1277 int x, y; /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
1278 struct trap *desttrap; /* nonnull if another trap at <x,y> */
1281 const char *predicament, *culprit;
1282 char *steedname = !u.usteed ? (char *) 0 : y_monnam(u.usteed);
1285 return TRUE; /* sanity check */
1287 switch (u.utraptype) {
1289 if (flags.verbose) {
1291 predicament = "caught in a bear trap";
1293 predicament = "
\8cF
\82Ìã©
\82É
\82Â
\82©
\82Ü
\82Á
\82½";
1296 Norep("%s is %s.", upstart(steedname), predicament);
1298 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1301 Norep("You are %s.", predicament);
1303 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1305 /* [why does diagonal movement give quickest escape?] */
1306 if ((u.dx && u.dy) || !rn2(5))
1310 if (desttrap && desttrap->tseen
1311 && (desttrap->ttyp == PIT || desttrap->ttyp == SPIKED_PIT))
1312 return TRUE; /* move into adjacent pit */
1313 /* try to escape; position stays same regardless of success */
1317 if (uwep && uwep->oartifact == ART_STING) {
1320 pline("Sting cuts through the web!");
1322 pline("
\83X
\83e
\83B
\83\93\83O
\82Í
\82
\82à
\82Ì
\91\83\82ð
\90Ø
\82è
\82³
\82¢
\82½
\81I");
1323 break; /* escape trap but don't move */
1326 if (flags.verbose) {
1328 predicament = "stuck to the web";
1330 predicament = "
\82
\82à
\82Ì
\91\83\82É
\82Ð
\82Á
\82©
\82©
\82Á
\82½";
1333 Norep("%s is %s.", upstart(steedname), predicament);
1335 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1338 Norep("You are %s.", predicament);
1340 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1345 pline("%s breaks out of the web.", upstart(steedname));
1347 pline("%s
\82Í
\82
\82à
\82Ì
\91\83\82ð
\89ó
\82µ
\82½
\81D", upstart(steedname));
1350 You("disentangle yourself.");
1352 You("
\8e©
\95ª
\82Å
\82Ù
\82Ç
\82¢
\82½
\81D");
1356 if (flags.verbose) {
1358 predicament = "stuck in the lava";
1360 predicament = "
\97n
\8aâ
\82É
\82Í
\82Ü
\82Á
\82½";
1363 Norep("%s is %s.", upstart(steedname), predicament);
1365 Norep("%s
\82Í%s
\81D", upstart(steedname), predicament);
1368 Norep("You are %s.", predicament);
1370 Norep("
\82 \82È
\82½
\82Í%s
\81D", predicament);
1372 if (!is_lava(x, y)) {
1374 if ((u.utrap & 0xff) == 0) {
1378 You("lead %s to the edge of the lava.", steedname);
1380 You("%s
\82ð
\97n
\8aâ
\82Ì
\92[
\82Ü
\82Å
\93±
\82¢
\82½
\81D", steedname);
1383 You("pull yourself to the edge of the lava.");
1385 You("
\97n
\8aâ
\82Ì
\92[
\82Ü
\82Å
\82©
\82ë
\82¤
\82¶
\82Ä
\81C
\82½
\82Ç
\82è
\82Â
\82¢
\82½
\81D");
1392 anchored = (u.utraptype == TT_BURIEDBALL);
1396 cc.x = u.ux, cc.y = u.uy;
1397 /* can move normally within radius 1 of buried ball */
1398 if (buried_ball(&cc) && dist2(x, y, cc.x, cc.y) <= 2) {
1399 /* ugly hack: we need to issue some message here
1400 in case "you are chained to the buried ball"
1401 was the most recent message given, otherwise
1402 our next attempt to move out of tether range
1403 after this successful move would have its
1404 can't-do-that message suppressed by Norep */
1406 Norep("You move within the chain's reach.");
1411 if (flags.verbose) {
1413 predicament = "chained to the";
1414 culprit = "buried ball";
1416 predicament = "stuck in the";
1417 culprit = surface(u.ux, u.uy);
1421 Norep("You and %s are %s %s.", steedname, predicament,
1424 Norep("%s is %s %s.", upstart(steedname), predicament,
1427 Norep("You are %s %s.", predicament, culprit);
1431 pline("%s finally %s free.", upstart(steedname),
1432 !anchored ? "lurches" : "wrenches the ball");
1434 You("finally %s free.",
1435 !anchored ? "wriggle" : "wrench the ball");
1437 buried_ball_to_punishment();
1441 impossible("trapmove: stuck in unknown trap? (%d)",
1451 if (!youmonst.data->mmove) {
1453 You("are rooted %s.",
1454 Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
1458 You("
\82»
\82Ì
\8fê
\82É
\97§
\82¿
\82·
\82
\82ñ
\82¾
\81D");
1469 register struct monst *mtmp;
1470 register struct rm *tmpr;
1471 register xchar x, y;
1472 struct trap *trap = NULL;
1475 xchar chainx = 0, chainy = 0,
1476 ballx = 0, bally = 0; /* ball&chain new positions */
1477 int bc_control = 0; /* control for ball&chain */
1478 boolean cause_delay = FALSE; /* dragging ball will skip a move */
1480 u_wipe_engr(rnd(5));
1482 if (context.travel) {
1483 if (!findtravelpath(FALSE))
1484 (void) findtravelpath(TRUE);
1485 context.travel1 = 0;
1488 if (((wtcap = near_capacity()) >= OVERLOADED
1489 || (wtcap > SLT_ENCUMBER
1490 && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1491 : (u.uhp < 10 && u.uhp != u.uhpmax))))
1492 && !Is_airlevel(&u.uz)) {
1493 if (wtcap < OVERLOADED) {
1495 You("don't have enough stamina to move.");
1497 You("
\82Ö
\82Æ
\82Ö
\82Æ
\82Å
\93®
\82¯
\82È
\82¢
\81D");
1498 exercise(A_CON, FALSE);
1501 You("collapse under your load.");
1503 pline("
\95¨
\82ð
\8e\9d\82¿
\82·
\82¬
\82Ä
\93|
\82ê
\82½
\81D");
1509 u.ux = x = u.ustuck->mx;
1510 u.uy = y = u.ustuck->my;
1513 if (Is_airlevel(&u.uz) && rn2(4) && !Levitation && !Flying) {
1517 You("tumble in place.");
1519 You("
\82»
\82Ì
\8fê
\82Å
\93|
\82ê
\82½
\81D");
1520 exercise(A_DEX, FALSE);
1524 You_cant("control your movements very well.");
1526 You("
\82¤
\82Ü
\82
\95à
\82¯
\82È
\82¢
\81D");
1530 pline("It's hard to walk in thin air.");
1532 pline("
\8bó
\92\86\82ð
\95à
\82
\82Ì
\82Í
\93ï
\82µ
\82¢
\81D");
1533 exercise(A_DEX, TRUE);
1539 /* check slippery ice */
1540 on_ice = !Levitation && is_ice(u.ux, u.uy);
1542 static int skates = 0;
1544 skates = find_skates();
1545 if ((uarmf && uarmf->otyp == skates) || resists_cold(&youmonst)
1546 || Flying || is_floater(youmonst.data)
1547 || is_clinger(youmonst.data) || is_whirly(youmonst.data))
1549 else if (!rn2(Cold_resistance ? 3 : 2)) {
1550 HFumbling |= FROMOUTSIDE;
1551 HFumbling &= ~TIMEOUT;
1552 HFumbling += 1; /* slip on next move */
1555 if (!on_ice && (HFumbling & FROMOUTSIDE))
1556 HFumbling &= ~FROMOUTSIDE;
1560 if (Stunned || (Confusion && !rn2(5))) {
1561 register int tries = 0;
1571 } while (!isok(x, y) || bad_rock(youmonst.data, x, y));
1573 /* turbulence might alter your actual destination */
1576 if (!u.dx && !u.dy) {
1587 if (((trap = t_at(x, y)) && trap->tseen)
1588 || (Blind && !Levitation && !Flying && !is_clinger(youmonst.data)
1589 && is_pool_or_lava(x, y) && levl[x][y].seenv)) {
1590 if (context.run >= 2) {
1598 if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
1599 if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
1600 /* perhaps it fled (or was teleported or ... ) */
1602 } else if (sticks(youmonst.data)) {
1603 /* When polymorphed into a sticking monster,
1604 * u.ustuck means it's stuck to you, not you to it.
1607 You("release %s.", mon_nam(u.ustuck));
1609 You("%s
\82ð
\95ú
\82µ
\82½
\81D", mon_nam(u.ustuck));
1612 /* If holder is asleep or paralyzed:
1613 * 37.5% chance of getting away,
1614 * 12.5% chance of waking/releasing it;
1616 * 7.5% chance of getting away.
1617 * [strength ought to be a factor]
1618 * If holder is tame and there is no conflict,
1619 * guaranteed escape.
1621 switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
1627 You("pull free from %s.", mon_nam(u.ustuck));
1629 You("%s
\82ð
\82Ð
\82«
\82Í
\82È
\82µ
\82½
\81D", mon_nam(u.ustuck));
1633 if (!u.ustuck->mcanmove) {
1634 /* it's free to move on next turn */
1635 u.ustuck->mfrozen = 1;
1636 u.ustuck->msleeping = 0;
1640 if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf)
1643 You("cannot escape from %s!", mon_nam(u.ustuck));
1645 You("%s
\82©
\82ç
\93¦
\82°
\82ç
\82ê
\82È
\82¢
\81I", mon_nam(u.ustuck));
1654 /* Don't attack if you're running, and can see it */
1655 /* We should never get here if forcefight */
1656 if (context.run && ((!Blind && mon_visible(mtmp)
1657 && ((mtmp->m_ap_type != M_AP_FURNITURE
1658 && mtmp->m_ap_type != M_AP_OBJECT)
1659 || Protection_from_shape_changers))
1660 || sensemon(mtmp))) {
1674 /* attack monster */
1677 /* only attack if we know it's there */
1678 /* or if we used the 'F' command to fight blindly */
1679 /* or if it hides_under, in which case we call attack() to print
1680 * the Wait! message.
1681 * This is different from ceiling hiders, who aren't handled in
1685 /* If they used a 'm' command, trying to move onto a monster
1686 * prints the below message and wastes a turn. The exception is
1687 * if the monster is unseen and the player doesn't remember an
1688 * invisible monster--then, we fall through to attack() and
1689 * attack_check(), which still wastes a turn, but prints a
1690 * different message and makes the player remember the monster.
1693 && (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))) {
1694 if (mtmp->m_ap_type && !Protection_from_shape_changers
1696 stumble_onto_mimic(mtmp);
1697 else if (mtmp->mpeaceful && !Hallucination)
1699 pline("Pardon me, %s.", m_monnam(mtmp));
1701 pline("
\82¿
\82å
\82Á
\82Æ
\82²
\82ß
\82ñ
\82È
\82³
\82¢
\82æ
\81C%s
\82³
\82ñ
\81D", m_monnam(mtmp));
1704 You("move right into %s.", mon_nam(mtmp));
1706 You("%s
\82Ì
\82»
\82Î
\82É
\88Ú
\93®
\82µ
\82½
\81D", mon_nam(mtmp));
1709 if (context.forcefight || !mtmp->mundetected || sensemon(mtmp)
1710 || ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)
1711 && !is_safepet(mtmp))) {
1712 /* try to attack; note that it might evade */
1713 /* also, we don't attack tame when _safepet_ */
1719 /* specifying 'F' with no monster wastes a turn */
1720 if (context.forcefight
1721 /* remembered an 'I' && didn't use a move command */
1722 || (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
1723 struct obj *boulder = 0;
1724 boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
1725 solid = !accessible(x, y);
1726 int glyph = glyph_at(x, y); /* might be monster */
1730 boulder = sobj_at(BOULDER, x, y);
1731 /* if a statue is displayed at the target location,
1732 player is attempting to attack it [and boulder
1733 handling below is suitable for handling that] */
1734 if (glyph_is_statue(glyph)
1735 || (Hallucination && glyph_is_monster(glyph)))
1736 boulder = sobj_at(STATUE, x, y);
1738 /* force fight at boulder/statue or wall/door while wielding
1739 pick: start digging to break the boulder or wall */
1740 if (context.forcefight
1742 && uwep && dig_typ(uwep, x, y)
1743 /* should we dig? */
1744 && !glyph_is_invisible(glyph) && !glyph_is_monster(glyph)) {
1745 (void) use_pick_axe2(uwep);
1750 /* about to become known empty -- remove 'I' if present */
1753 map_object(boulder, TRUE);
1755 glyph = glyph_at(x, y); /* might have just changed */
1758 Strcpy(buf, ansimpleoname(boulder));
1759 else if (Underwater && !is_pool(x, y))
1760 /* Underwater, targetting non-water; the map just shows blank
1761 because you don't see remembered terrain while underwater;
1762 although the hero can attack an adjacent monster this way,
1763 assume he can't reach out far enough to distinguish terrain */
1764 Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
1768 /* glyph might indicate unseen terrain if hero is blind;
1769 unlike searching, this won't reveal what that terrain is
1770 (except for solid rock, where the glyph would otherwise
1771 yield ludicrous "dark part of a room") */
1773 (levl[x][y].typ == STONE)
1775 : glyph_is_cmap(glyph)
1776 ? the(defsyms[glyph_to_cmap(glyph)].explanation)
1777 : (const char *) "an unknown obstacle");
1778 /* note: 'solid' is misleadingly named and catches pools
1779 of water and lava as well as rock and walls */
1781 Strcpy(buf, "thin air");
1783 !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
1784 explo ? "explode at" : "attack", buf);
1789 u.mh = -1; /* dead in the current form */
1794 if (glyph_is_invisible(levl[x][y].glyph)) {
1798 /* not attacking an animal, so we try to move */
1799 if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
1808 if (!trapmove(x, y, trap))
1812 if (!test_move(u.ux, u.uy, x - u.ux, y - u.uy, DO_MOVE)) {
1813 if (!context.door_opened) {
1820 /* Move ball and chain. */
1822 if (!drag_ball(x, y, &bc_control, &ballx, &bally, &chainx, &chainy,
1823 &cause_delay, TRUE))
1826 /* Check regions entering/leaving */
1827 if (!in_out_region(x, y))
1830 /* now move the hero */
1834 /* Move your steed, too */
1836 u.usteed->mx = u.ux;
1837 u.usteed->my = u.uy;
1842 * If safepet at destination then move the pet to the hero's
1843 * previous location using the same conditions as in attack().
1844 * there are special extenuating circumstances:
1845 * (1) if the pet dies then your god angers,
1846 * (2) if the pet gets trapped then your god may disapprove,
1847 * (3) if the pet was already trapped and you attempt to free it
1848 * not only do you encounter the trap but you may frighten your
1849 * pet causing it to go wild! moral: don't abuse this privilege.
1851 * Ceiling-hiding pets are skipped by this section of code, to
1852 * be caught by the normal falling-monster code.
1854 if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
1855 /* if trapped, there's a chance the pet goes wild */
1856 if (mtmp->mtrapped) {
1857 if (!rn2(mtmp->mtame)) {
1858 mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
1860 m_unleash(mtmp, TRUE);
1866 mtmp->mundetected = 0;
1867 if (mtmp->m_ap_type)
1869 else if (!mtmp->mtame)
1870 newsym(mtmp->mx, mtmp->my);
1872 if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
1873 && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
1874 && sobj_at(BOULDER, trap->tx, trap->ty)) {
1875 /* can't swap places with pet pinned in a pit by a boulder */
1876 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
1877 } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
1878 /* can't swap places when pet can't move to your spot */
1879 u.ux = u.ux0, u.uy = u.uy0;
1880 You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp)));
1881 } else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0)
1882 && bad_rock(mtmp->data, u.ux0, y)
1883 && (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
1884 /* can't swap places when pet won't fit thru the opening */
1885 u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
1887 You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
1889 You("
\8e~
\82Ü
\82Á
\82½
\81D%s
\82Í
\92Ê
\82è
\94²
\82¯
\82ç
\82ê
\82È
\82¢
\81D", upstart(y_monnam(mtmp)));
1891 char pnambuf[BUFSZ];
1893 /* save its current description in case of polymorph */
1894 Strcpy(pnambuf, y_monnam(mtmp));
1896 remove_monster(x, y);
1897 place_monster(mtmp, u.ux0, u.uy0);
1899 newsym(u.ux0, u.uy0);
1902 You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
1907 mtmp->mtame ? "
\82Æ
\8fê
\8f\8a\82ð
\93ü
\82ê
\8a·
\82í
\82Á" : "
\82ð
\95|
\82ª
\82ç
\82¹");
1910 /* check for displacing it into pools and traps */
1911 switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
1914 case 1: /* trapped */
1915 case 3: /* changed levels */
1916 /* there's already been a trap message, reinforce it */
1921 /* drowned or died...
1922 * you killed your pet by direct action, so get experience
1923 * and possibly penalties;
1924 * we want the level gain message, if it happens, to occur
1925 * before the guilt message below
1928 /* minliquid() and mintrap() call mondead() rather than
1929 killed() so we duplicate some of the latter here */
1932 u.uconduct.killer++;
1933 mndx = monsndx(mtmp->data);
1934 tmp = experience(mtmp, (int) mvitals[mndx].died);
1935 more_experienced(tmp, 0);
1936 newexplevel(); /* will decide if you go up */
1938 /* That's no way to treat a pet! Your god gets angry.
1940 * [This has always been pretty iffy. Why does your
1941 * patron deity care at all, let alone enough to get mad?]
1945 You_feel("guilty about losing your pet like this.");
1947 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");
1953 pline("that's strange, unknown mintrap result!");
1959 reset_occupations();
1961 if (context.run < 8)
1962 if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ)
1963 || IS_FURNITURE(tmpr->typ))
1967 if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) || u.dx
1969 (void) hideunder(&youmonst);
1972 * Mimics (or whatever) become noticeable if they move and are
1973 * imitating something that doesn't move. We could extend this
1974 * to non-moving monsters...
1976 if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
1977 || youmonst.m_ap_type == M_AP_FURNITURE))
1978 youmonst.m_ap_type = M_AP_NOTHING;
1980 check_leash(u.ux0, u.uy0);
1982 if (u.ux0 != u.ux || u.uy0 != u.uy) {
1984 /* Clean old position -- vision_recalc() will print our new one. */
1985 newsym(u.ux0, u.uy0);
1986 /* Since the hero has moved, adjust what can be seen/unseen. */
1987 vision_recalc(1); /* Do the work now in the recover time. */
1988 invocation_message();
1991 if (Punished) /* put back ball and chain */
1992 move_bc(0, bc_control, ballx, bally, chainx, chainy);
1996 /* delay next move because of ball dragging */
1997 /* must come after we finished picking up, in spoteffects() */
2000 multi_reason = "dragging an iron ball";
2004 if (context.run && flags.runmode != RUN_TPORT) {
2005 /* display every step or every 7th step depending upon mode */
2006 if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
2011 if (flags.runmode == RUN_CRAWL) {
2021 /* combat increases metabolism */
2025 /* this used to be part of domove() when moving to a monster's
2026 position, but is now called by attack() so that it doesn't
2027 execute if you decline to attack a peaceful monster */
2029 if ((moves % 3L) != 0L && near_capacity() >= HVY_ENCUMBER) {
2030 int *hp = (!Upolyd ? &u.uhp : &u.mh);
2036 You("pass out from exertion!");
2038 You("
\8bC
\90â
\82µ
\82½
\81D");
2039 exercise(A_CON, FALSE);
2040 fall_asleep(-10, FALSE);
2043 return (boolean) (multi < 0); /* might have fainted (forced to sleep) */
2047 invocation_message()
2049 /* a special clue-msg when on the Invocation position */
2050 if (invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
2052 struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
2054 nomul(0); /* stop running or travelling */
2057 Sprintf(buf, "beneath %s", y_monnam(u.usteed));
2059 Sprintf(buf, "%s
\82Ì
\89º
\82É", y_monnam(u.usteed));
2060 else if (Levitation || Flying)
2062 Strcpy(buf, "beneath you");
2064 Strcpy(buf, "
\89º
\95û
\82É");
2067 Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
2069 Strcpy(buf, "
\91«
\8c³
\82É");
2072 You_feel("a strange vibration %s.", buf);
2074 You("%s
\8aï
\96
\82È
\90U
\93®
\82ð
\8a´
\82¶
\82½
\81D", buf);
2075 u.uevent.uvibrated = 1;
2076 if (otmp && otmp->spe == 7 && otmp->lamplit)
2078 pline("%s %s!", The(xname(otmp)),
2079 Blind ? "throbs palpably" : "glows with a strange light");
2081 pline("%s
\82Í%s
\82µ
\82½
\81I", The(xname(otmp)),
2082 Blind ? "
\82©
\82·
\82©
\82É
\90U
\93®" : "
\8aï
\96
\82È
\8cõ
\82ð
\94");
2087 /* moving onto different terrain;
2088 might be going into solid rock, inhibiting levitation or flight,
2089 or coming back out of such, reinstating levitation/flying */
2093 struct rm *lev = &levl[u.ux][u.uy];
2094 boolean blocklev = (IS_ROCK(lev->typ) || closed_door(u.ux, u.uy)
2095 || (Is_waterlevel(&u.uz) && lev->typ == WATER));
2098 /* called from spoteffects(), skip float_down() */
2100 You_cant("levitate in here.");
2101 BLevitation |= FROMOUTSIDE;
2102 } else if (BLevitation) {
2103 BLevitation &= ~FROMOUTSIDE;
2107 /* the same terrain that blocks levitation also blocks flight */
2110 You_cant("fly in here.");
2111 BFlying |= FROMOUTSIDE;
2112 } else if (BFlying) {
2113 BFlying &= ~FROMOUTSIDE;
2114 float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
2115 /* [minor bug: we don't know whether this is beginning flight or
2116 resuming it; that could be tracked so that this message could
2117 be adjusted to "resume flying", but isn't worth the effort...] */
2119 You("start flying.");
2123 /* extracted from spoteffects; called by spoteffects to check for entering or
2124 leaving a pool of water/lava, and by moveloop to check for staying on one
2126 returns true to skip rest of spoteffects */
2128 pooleffects(newspot)
2129 boolean newspot; /* true if called by spoteffects */
2131 /* check for leaving water */
2133 boolean still_inwater = FALSE; /* assume we're getting out */
2135 if (!is_pool(u.ux, u.uy)) {
2136 if (Is_waterlevel(&u.uz))
2138 You("pop into an air bubble.");
2140 You("
\82Ð
\82å
\82¢
\82Æ
\8bó
\8bC
\82Ì
\96A
\82É
\93ü
\82Á
\82½
\81D");
2141 else if (is_lava(u.ux, u.uy))
2143 You("leave the water..."); /* oops! */
2145 You("
\90\85\82©
\82ç
\94²
\82¯
\82¾
\82µ
\82½
\81D
\81D
\81D"); /* oops! */
2149 You("are on solid %s again.",
2150 is_ice(u.ux, u.uy) ? "ice" : "land");
2152 You("
\8cÅ
\82¢%s
\82Ì
\8fã
\82É
\82Ü
\82½
\96ß
\82Á
\82½
\81D",
2153 is_ice(u.ux, u.uy) ? "
\95X" : "
\92n
\96Ê");
2155 } else if (Is_waterlevel(&u.uz)) {
2156 still_inwater = TRUE;
2157 } else if (Levitation) {
2159 You("pop out of the water like a cork!");
2161 You("
\83R
\83\8b\83N
\82Ì
\82æ
\82¤
\82É
\94ò
\82Ñ
\82¾
\82µ
\82½
\81I");
2162 } else if (Flying) {
2164 You("fly out of the water.");
2166 You("
\90\85\82©
\82ç
\94ò
\82Ñ
\82¾
\82µ
\82½
\81D");
2167 } else if (Wwalking) {
2169 You("slowly rise above the surface.");
2171 You("
\82ä
\82Á
\82
\82è
\90\85\96Ê
\82Ü
\82Å
\8fã
\82ª
\82Á
\82½
\81D");
2173 still_inwater = TRUE;
2175 if (!still_inwater) {
2176 boolean was_underwater = (Underwater && !Is_waterlevel(&u.uz));
2178 u.uinwater = 0; /* leave the water */
2179 if (was_underwater) { /* restore vision */
2181 vision_full_recalc = 1;
2186 /* check for entering water or lava */
2187 if (!u.ustuck && !Levitation && !Flying && is_pool_or_lava(u.ux, u.uy)) {
2189 && (is_flyer(u.usteed->data) || is_floater(u.usteed->data)
2190 || is_clinger(u.usteed->data))) {
2191 /* floating or clinging steed keeps hero safe (is_flyer() test
2192 is redundant; it can't be true since Flying yielded false) */
2194 } else if (u.usteed) {
2195 /* steed enters pool */
2196 dismount_steed(Underwater ? DISMOUNT_FELL : DISMOUNT_GENERIC);
2197 /* dismount_steed() -> float_down() -> pickup()
2198 (float_down doesn't do autopickup on Air or Water) */
2199 if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
2201 /* even if we actually end up at same location, float_down()
2202 has already done spoteffect()'s trap and pickup actions */
2204 check_special_room(FALSE); /* spoteffects */
2209 /* drown(),lava_effects() return true if hero changes
2210 location while surviving the problem */
2211 if (is_lava(u.ux, u.uy)) {
2214 } else if (!Wwalking
2215 && (newspot || !u.uinwater || !(Swimming || Amphibious))) {
2227 static int inspoteffects = 0;
2228 static coord spotloc;
2229 static int spotterrain;
2230 static struct trap *spottrap = (struct trap *) 0;
2231 static unsigned spottraptyp = NO_TRAP;
2232 struct trap *trap = t_at(u.ux, u.uy);
2233 register struct monst *mtmp;
2235 /* prevent recursion from affecting the hero all over again
2236 [hero poly'd to iron golem enters water here, drown() inflicts
2237 damage that triggers rehumanize() which calls spoteffects()...] */
2238 if (inspoteffects && u.ux == spotloc.x && u.uy == spotloc.y
2239 /* except when reason is transformed terrain (ice -> water) */
2240 && spotterrain == levl[u.ux][u.uy].typ
2241 /* or transformed trap (land mine -> pit) */
2242 && (!spottrap || !trap || trap->ttyp == spottraptyp))
2246 spotterrain = levl[u.ux][u.uy].typ;
2247 spotloc.x = u.ux, spotloc.y = u.uy;
2249 /* moving onto different terrain might cause Levitation to toggle */
2250 if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
2253 if (pooleffects(TRUE))
2256 check_special_room(FALSE);
2257 if (IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
2259 if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
2262 /* if levitation is due to time out at the end of this
2263 turn, allowing it to do so could give the perception
2264 that a trap here is being triggered twice, so adjust
2265 the timeout to prevent that */
2266 if (trap && (HLevitation & TIMEOUT) == 1L && !ELevitation
2267 && !(HLevitation & ~TIMEOUT)) {
2268 if (rn2(2)) { /* defer timeout */
2269 incr_itimeout(&HLevitation, 1L);
2270 } else { /* timeout early */
2271 if (float_down(I_SPECIAL | TIMEOUT, 0L)) {
2272 /* levitation has ended; we've already triggered
2273 any trap and [usually] performed autopickup */
2280 * If not a pit, pickup before triggering trap.
2281 * If pit, trigger trap before pickup.
2283 pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
2289 * dotrap on a fire trap calls melt_ice() which triggers
2290 * spoteffects() (again) which can trigger the same fire
2291 * trap (again). Use static spottrap to prevent that.
2292 * We track spottraptyp because some traps morph
2293 * (landmine to pit) and any new trap type
2294 * should get triggered.
2296 if (!spottrap || spottraptyp != trap->ttyp) {
2298 spottraptyp = trap->ttyp;
2299 dotrap(trap, 0); /* fall into arrow trap, etc. */
2300 spottrap = (struct trap *) 0;
2301 spottraptyp = NO_TRAP;
2307 /* Warning alerts you to ice danger */
2308 if (Warning && is_ice(u.ux, u.uy)) {
2309 static const char *const icewarnings[] = {
2310 "The ice seems very soft and slushy.",
2311 "You feel the ice shift beneath you!",
2312 "The ice, is gonna BREAK!", /* The Dead Zone */
2314 long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
2315 if (time_left && time_left < 15L)
2316 pline1((time_left < 5L) ? icewarnings[2] : (time_left < 10L)
2320 if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
2321 mtmp->mundetected = mtmp->msleeping = 0;
2322 switch (mtmp->data->mlet) {
2325 pline("%s suddenly drops from the %s!", Amonnam(mtmp),
2326 ceiling(u.ux, u.uy));
2328 pline("%s
\82ª
\93Ë
\91R%s
\82©
\82ç
\97\8e\82¿
\82Ä
\82«
\82½
\81I",
2329 Amonnam(mtmp), ceiling(u.ux,u.uy));
2331 if (mtmp->mtame) /* jumps to greet you, not attack */
2333 else if (uarmh && is_metallic(uarmh))
2335 pline("Its blow glances off your %s.",
2337 pline("
\8dU
\8c\82\82Í
\82 \82È
\82½
\82Ì%s
\82ð
\82©
\82·
\82ß
\82½
\82¾
\82¯
\82¾
\82Á
\82½
\81D",
2338 helm_simple_name(uarmh));
2339 else if (u.uac + 3 <= rnd(20))
2341 You("are almost hit by %s!",
2342 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2344 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",
2345 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2350 You("are hit by %s!",
2351 x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
2353 You("
\97\8e\82¿
\82Ä
\82«
\82½%s
\82É
\93\96\82½
\82Á
\82½
\81I",
2354 x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
2357 if (Half_physical_damage)
2358 dmg = (dmg + 1) / 2;
2359 mdamageu(mtmp, dmg);
2362 default: /* monster surprises you. */
2365 pline("%s jumps near you from the %s.", Amonnam(mtmp),
2366 ceiling(u.ux, u.uy));
2368 pline("%s
\82ª%s
\82©
\82ç
\82 \82È
\82½
\82Ì
\8bß
\82
\82É
\94ò
\82ñ
\82Å
\82«
\82½
\81D", Amonnam(mtmp),
2369 ceiling(u.ux,u.uy));
2371 else if (mtmp->mpeaceful) {
2375 You("%s
\82ð
\8bÁ
\82©
\82µ
\82½
\81I",
2376 Blind && !sensemon(mtmp) ? something : a_monnam(mtmp));
2377 mtmp->mpeaceful = 0;
2380 pline("%s attacks you by surprise!", Amonnam(mtmp));
2382 pline("%s
\82Í
\8bÁ
\82¢
\82Ä
\82 \82È
\82½
\82ð
\8dU
\8c\82\82µ
\82½
\81I", Amonnam(mtmp));
2385 mnexto(mtmp); /* have to move the monster */
2388 if (!--inspoteffects) {
2389 spotterrain = STONE; /* 0 */
2390 spotloc.x = spotloc.y = 0;
2395 /* returns first matching monster */
2396 STATIC_OVL struct monst *
2397 monstinroom(mdat, roomno)
2398 struct permonst *mdat;
2401 register struct monst *mtmp;
2403 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2404 if (DEADMONSTER(mtmp))
2406 if (mtmp->data == mdat
2407 && index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
2410 return (struct monst *) 0;
2414 in_rooms(x, y, typewanted)
2415 register xchar x, y;
2416 register int typewanted;
2419 char rno, *ptr = &buf[4];
2420 int typefound, min_x, min_y, max_x, max_y_offset, step;
2421 register struct rm *lev;
2423 #define goodtype(rno) \
2425 || ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) \
2426 || ((typewanted == SHOPBASE) && (typefound > SHOPBASE)))
2428 switch (rno = levl[x][y].roomno) {
2437 default: /* i.e. a regular room # */
2447 else if (x >= COLNO)
2454 max_y_offset -= step;
2455 } else if ((min_y + max_y_offset) >= ROWNO)
2456 max_y_offset -= step;
2458 for (x = min_x; x <= max_x; x += step) {
2459 lev = &levl[x][min_y];
2461 if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
2465 if (y > max_y_offset)
2467 if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
2471 if (y > max_y_offset)
2473 if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
2480 /* is (x,y) in a town? */
2485 s_level *slev = Is_special(&u.uz);
2486 register struct mkroom *sroom;
2487 boolean has_subrooms = FALSE;
2489 if (!slev || !slev->flags.town)
2493 * See if (x,y) is in a room with subrooms, if so, assume it's the
2494 * town. If there are no subrooms, the whole level is in town.
2496 for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
2497 if (sroom->nsubrooms > 0) {
2498 has_subrooms = TRUE;
2499 if (inside_room(sroom, x, y))
2504 return !has_subrooms;
2509 register boolean newlev;
2511 char *ptr1, *ptr2, *ptr3, *ptr4;
2513 Strcpy(u.urooms0, u.urooms);
2514 Strcpy(u.ushops0, u.ushops);
2517 u.uentered[0] = '\0';
2519 u.ushops_entered[0] = '\0';
2520 Strcpy(u.ushops_left, u.ushops0);
2523 Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
2525 for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
2526 ptr4 = &u.ushops_entered[0];
2528 if (!index(u.urooms0, *ptr1))
2530 if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
2532 if (!index(u.ushops0, *ptr1))
2540 /* filter u.ushops0 -> u.ushops_left */
2541 for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
2542 if (!index(u.ushops, *ptr1))
2548 check_special_room(newlev)
2549 register boolean newlev;
2551 register struct monst *mtmp;
2554 move_update(newlev);
2557 u_left_shop(u.ushops_left, newlev);
2559 if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
2560 return; /* no entrance messages necessary */
2562 /* Did we just enter a shop? */
2563 if (*u.ushops_entered)
2564 u_entered_shop(u.ushops_entered);
2566 for (ptr = &u.uentered[0]; *ptr; ptr++) {
2567 int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
2568 boolean msg_given = TRUE;
2570 /* Did we just enter some other special room? */
2571 /* vault.c insists that a vault remain a VAULT,
2572 * and temples should remain TEMPLEs,
2573 * but everything else gives a message only the first time */
2577 pline("Welcome to David's treasure zoo!");
2579 pline("
\83f
\83r
\83b
\83g
\95ó
\94 \93®
\95¨
\89\80\82É
\82æ
\82¤
\82±
\82»
\81I");
2583 pline("It %s rather %s down here.", Blind ? "feels" : "looks",
2584 Blind ? "humid" : "muddy");
2586 pline("
\82©
\82È
\82è%s
\81D",
2587 Blind ? "
\8e¼
\8bC
\82ª
\82 \82é
\8fê
\8f\8a\82Ì
\82æ
\82¤
\82¾"
2588 : "
\82Ç
\82ë
\82Ç
\82ë
\82µ
\82Ä
\82¢
\82é
\8fê
\8f\8a\82¾");
2593 You("enter an opulent throne room!");
2595 You("
\89Ø
\82â
\82©
\82È
\8bÊ
\8dÀ
\82Ì
\8aÔ
\82É
\93ü
\82Á
\82½
\81I");
2599 You("enter a leprechaun hall!");
2601 You("
\83\8c\83v
\83\89\83R
\81[
\83\93\83z
\81[
\83\8b\82É
\93ü
\82Á
\82½
\81I");
2606 const char *run = locomotion(youmonst.data, "Run");
2607 pline("%s away! %s away!", run, run);
2609 pline("
\93¦
\82°
\82ë
\81I
\93¦
\82°
\82ë
\81I");
2613 You("have an uncanny feeling...");
2615 You("
\95s
\8bC
\96¡
\82È
\8a´
\82¶
\82ª
\82µ
\82½
\81D
\81D
\81D");
2619 You("enter a giant beehive!");
2621 You("
\8b\90\91å
\82È
\96I
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2625 You("enter a disgusting nest!");
2627 You("
\82Þ
\82Á
\82Æ
\82·
\82é
\8fL
\82¢
\82Ì
\82·
\82é
\92¹
\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2631 You("enter an anthole!");
2633 You("
\83A
\83\8a\82Ì
\91\83\82É
\93ü
\82Á
\82½
\81I");
2636 if (monstinroom(&mons[PM_SOLDIER], roomno)
2637 || monstinroom(&mons[PM_SERGEANT], roomno)
2638 || monstinroom(&mons[PM_LIEUTENANT], roomno)
2639 || monstinroom(&mons[PM_CAPTAIN], roomno))
2641 You("enter a military barracks!");
2643 You("
\8cR
\91à
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81I");
2646 You("enter an abandoned barracks.");
2648 You("
\95ú
\92u
\82³
\82ê
\82½
\82Ü
\82Ü
\82Ì
\95ºäq
\82É
\93ü
\82Á
\82½
\81D");
2651 struct monst *oracle = monstinroom(&mons[PM_ORACLE], roomno);
2653 if (!oracle->mpeaceful)
2655 verbalize("You're in Delphi, %s.", plname);
2657 verbalize("
\82¨
\82Ü
\82¦
\82Í
\83f
\83\8b\83t
\83@
\83C
\82Ì
\90_
\91õ
\8f\8a\82É
\82¢
\82é
\81D");
2660 verbalize("%s, %s, welcome to Delphi!",
2661 Hello((struct monst *) 0), plname);
2663 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",
2671 intemple(roomno + ROOMOFFSET);
2674 msg_given = (rt == TEMPLE);
2679 room_discovered(roomno);
2682 rooms[roomno].rtype = OROOM;
2683 if (!search_special(rt)) {
2684 /* No more room of that type */
2687 level.flags.has_court = 0;
2690 level.flags.has_swamp = 0;
2693 level.flags.has_morgue = 0;
2696 level.flags.has_zoo = 0;
2699 level.flags.has_barracks = 0;
2702 level.flags.has_temple = 0;
2705 level.flags.has_beehive = 0;
2709 if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
2710 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2711 if (DEADMONSTER(mtmp))
2713 if (!Stealth && !rn2(3))
2714 mtmp->msleeping = 0;
2726 struct trap *traphere = t_at(u.ux, u.uy);
2727 /* awful kludge to work around parse()'s pre-decrement */
2728 count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
2729 multi = 0; /* always reset */
2730 /* uswallow case added by GAN 01/29/87 */
2732 if (!u.ustuck->minvent) {
2733 if (is_animal(u.ustuck->data)) {
2735 You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
2737 You("%s
\82Ì
\90ã
\82ð
\8fE
\82Á
\82½
\81D", mon_nam(u.ustuck));
2739 pline("But it's kind of slimy, so you drop it.");
2741 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");
2744 You("don't %s anything in here to pick up.",
2745 Blind ? "feel" : "see");
2747 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82ª
\82È
\82¢%s
\81D",
2748 Blind ? "
\82æ
\82¤
\82¾" : "");
2752 int tmpcount = -count;
2753 return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
2756 if (is_pool(u.ux, u.uy)) {
2757 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
2758 || (Flying && !Breathless)) {
2760 You("cannot dive into the water to pick things up.");
2762 You("
\95¨
\82ð
\8fE
\82¢
\82 \82°
\82é
\82½
\82ß
\82É
\90\85\82É
\94ò
\82Ñ
\82±
\82ß
\82È
\82¢
\81D");
2764 } else if (!Underwater) {
2766 You_cant("even see the bottom, let alone pick up %s.", something);
2768 pline("
\92ê
\82³
\82¦
\8c©
\82¦
\82È
\82¢
\81C
\8fE
\82¤
\82Ì
\82Í
\82â
\82ß
\82æ
\82¤
\81D");
2772 if (is_lava(u.ux, u.uy)) {
2773 if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
2774 || (Flying && !Breathless)) {
2776 You_cant("reach the bottom to pick things up.");
2778 You_cant("
\95¨
\82ð
\8fE
\82¢
\8fã
\82°
\82é
\82½
\82ß
\82É
\92ê
\82Ü
\82Å
\82¢
\82¯
\82È
\82¢
\81D");
2780 } else if (!likes_lava(youmonst.data)) {
2782 You("would burn to a crisp trying to pick things up.");
2784 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");
2788 if (!OBJ_AT(u.ux, u.uy)) {
2789 register struct rm *lev = &levl[u.ux][u.uy];
2790 if (IS_THRONE(lev->typ))
2791 pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
2792 else if (IS_SINK(lev->typ))
2793 pline_The("plumbing connects it to the floor.");
2794 else if (IS_GRAVE(lev->typ))
2795 You("don't need a gravestone. Yet.");
2796 else if (IS_FOUNTAIN(lev->typ))
2797 You("could drink the water...");
2798 else if (IS_DOOR(lev->typ) && (lev->doormask & D_ISOPEN))
2799 pline("It won't come off the hinges.");
2802 There("is nothing here to pick up.");
2804 pline("
\82±
\82±
\82É
\82Í
\8fE
\82¦
\82é
\82à
\82Ì
\82Í
\82È
\82¢
\81D");
2807 if (!can_reach_floor(TRUE)) {
2808 if (traphere && uteetering_at_seen_pit(traphere))
2810 You("cannot reach the bottom of the pit.");
2812 You("
\97\8e\82µ
\8c\8a\82Ì
\92ê
\82É%s
\82ª
\93Í
\82©
\82È
\82©
\82Á
\82½
\81D", body_part(HAND));
2813 else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
2815 else if (Blind && !can_reach_floor(TRUE))
2816 You("cannot reach anything here.");
2819 You("cannot reach the %s.", surface(u.ux, u.uy));
2821 You("%s
\82É
\82½
\82Ç
\82è
\82Â
\82
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D", surface(u.ux, u.uy));
2825 return pickup(-count);
2828 /* stop running if we see something interesting */
2829 /* turn around a corner if that is the only way we can proceed */
2830 /* do not turn left or right twice */
2834 register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
2835 register int corrct = 0, noturn = 0;
2836 register struct monst *mtmp;
2837 register struct trap *trap;
2839 /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
2840 /* they polymorphed while in the middle of a long move. */
2841 if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
2846 if (Blind || context.run == 0)
2848 for (x = u.ux - 1; x <= u.ux + 1; x++)
2849 for (y = u.uy - 1; y <= u.uy + 1; y++) {
2853 if (u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy)
2856 if (x == u.ux && y == u.uy)
2859 if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
2860 && mtmp->m_ap_type != M_AP_OBJECT
2861 && (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
2862 if ((context.run != 1 && !mtmp->mtame)
2863 || (x == u.ux + u.dx && y == u.uy + u.dy))
2867 if (levl[x][y].typ == STONE)
2869 if (x == u.ux - u.dx && y == u.uy - u.dy)
2872 if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM)
2873 || IS_AIR(levl[x][y].typ))
2875 else if (closed_door(x, y)
2876 || (mtmp && is_door_mappear(mtmp))) {
2877 if (x != u.ux && y != u.uy)
2879 if (context.run != 1)
2882 } else if (levl[x][y].typ == CORR) {
2884 if (levl[u.ux][u.uy].typ != ROOM) {
2885 if (context.run == 1 || context.run == 3
2886 || context.run == 8) {
2887 i = dist2(x, y, u.ux + u.dx, u.uy + u.dy);
2890 if (corrct == 1 && dist2(x, y, x0, y0) != 1)
2902 } else if ((trap = t_at(x, y)) && trap->tseen) {
2903 if (context.run == 1)
2904 goto bcorr; /* if you must */
2905 if (x == u.ux + u.dx && y == u.uy + u.dy)
2908 } else if (is_pool_or_lava(x, y)) {
2909 /* water and lava only stop you if directly in front, and stop
2910 * you even if you are running
2912 if (!Levitation && !Flying && !is_clinger(youmonst.data)
2913 && x == u.ux + u.dx && y == u.uy + u.dy)
2914 /* No Wwalking check; otherwise they'd be able
2915 * to test boots by trying to SHIFT-direction
2916 * into a pool and seeing if the game allowed it
2920 } else { /* e.g. objects or trap or stairs */
2921 if (context.run == 1)
2923 if (context.run == 8)
2927 if (((x == u.ux - u.dx) && (y != u.uy + u.dy))
2928 || ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
2934 } /* end for loops */
2936 if (corrct > 1 && context.run == 2)
2938 if ((context.run == 1 || context.run == 3 || context.run == 8) && !noturn
2939 && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) {
2940 /* make sure that we do not turn too far */
2942 if (u.dx == y0 - u.uy && u.dy == u.ux - x0)
2943 i = 2; /* straight turn right */
2945 i = -2; /* straight turn left */
2946 } else if (u.dx && u.dy) {
2947 if ((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
2948 i = -1; /* half turn left */
2950 i = 1; /* half turn right */
2952 if ((x0 - u.ux == y0 - u.uy && !u.dy)
2953 || (x0 - u.ux != y0 - u.uy && u.dy))
2954 i = 1; /* half turn right */
2956 i = -1; /* half turn left */
2959 i += u.last_str_turn;
2960 if (i <= 2 && i >= -2) {
2961 u.last_str_turn = i;
2968 /* check for a doorway which lacks its door (NODOOR or BROKEN) */
2973 struct rm *lev_p = &levl[x][y];
2975 if (!IS_DOOR(lev_p->typ))
2977 /* all rogue level doors are doorless but disallow diagonal access, so
2978 we treat them as if their non-existant doors were actually present */
2979 if (Is_rogue_level(&u.uz))
2981 return !(lev_p->doormask & ~(D_NODOOR | D_BROKEN));
2984 /* used by drown() to check whether hero can crawl from water to <x,y> */
2986 crawl_destination(x, y)
2989 /* is location ok in general? */
2990 if (!goodpos(x, y, &youmonst, 0))
2993 /* orthogonal movement is unrestricted when destination is ok */
2994 if (x == u.ux || y == u.uy)
2997 /* diagonal movement has some restrictions */
2998 if (NODIAG(u.umonnum))
2999 return FALSE; /* poly'd into a grid bug... */
3001 return TRUE; /* or a xorn... */
3002 /* pool could be next to a door, conceivably even inside a shop */
3003 if (IS_DOOR(levl[x][y].typ) && (!doorless_door(x, y) || block_door(x, y)))
3005 /* finally, are we trying to squeeze through a too-narrow gap? */
3006 return !(bad_rock(youmonst.data, u.ux, y)
3007 && bad_rock(youmonst.data, x, u.uy));
3010 /* something like lookaround, but we are not running */
3011 /* react only to monsters that might hit us */
3016 register struct monst *mtmp;
3018 /* Also see the similar check in dochugw() in monmove.c */
3019 for (x = u.ux - 1; x <= u.ux + 1; x++)
3020 for (y = u.uy - 1; y <= u.uy + 1; y++) {
3023 if (x == u.ux && y == u.uy)
3025 if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
3026 && mtmp->m_ap_type != M_AP_OBJECT
3027 && (!mtmp->mpeaceful || Hallucination)
3028 && (!is_hider(mtmp->data) || !mtmp->mundetected)
3029 && !noattacks(mtmp->data) && mtmp->mcanmove
3030 && !mtmp->msleeping /* aplvax!jcn */
3031 && !onscary(u.ux, u.uy, mtmp) && canspotmon(mtmp))
3042 return; /* This is a bug fix by ab@unido */
3043 u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
3047 multi_reason = NULL;
3048 context.travel = context.travel1 = context.mv = context.run = 0;
3051 /* called when a non-movement, multi-turn action has completed */
3054 const char *msg_override;
3056 multi = 0; /* caller will usually have done this already */
3058 nomovemsg = msg_override;
3059 else if (!nomovemsg)
3060 nomovemsg = You_can_move_again;
3065 multi_reason = NULL;
3074 static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES,
3075 SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
3076 TELEPORT_CONTROL, STEALTH, FAST, INVIS };
3078 if (moves <= wailmsg + 50)
3082 if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) {
3087 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3090 who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
3095 pline("%s is about to die.", who);
3097 pline("%s
\82Í
\8e\80\82É
\82©
\82¯
\82Ä
\82¢
\82é
\81D", who);
3099 for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
3100 if (u.uprops[powers[i]].intrinsic & INTRINSIC)
3104 pline(powercnt >= 4 ? "%s, all your powers will be lost..."
3106 pline(powercnt >= 4 ? "%s
\81C
\82 \82È
\82½
\82Ì
\91S
\82Ä
\82Ì
\97Í
\82Í
\8e¸
\82í
\82ê
\82Â
\82Â
\82 \82é
\81D
\81D
\81D"
3108 : "%s, your life force is running out.",
3110 : "%s
\81C
\82 \82È
\82½
\82Ì
\90¶
\96½
\97Í
\82Í
\90s
\82«
\82æ
\82¤
\82Æ
\82µ
\82Ä
\82¢
\82é
\81D
\81D
\81D",
3115 You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
3117 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"
3119 : "the howling of the CwnAnnwn...");
3121 : "
\83N
\81[
\83\93\81E
\83A
\83\93\83k
\81[
\83\93\82Ì
\89\93\96i
\82ª
\95·
\82±
\82¦
\82é
\81D
\81D
\81D");
3126 losehp(n, knam, k_format)
3128 register const char *knam;
3138 else if (n > 0 && u.mh * 10 < u.mhmax && Unchanging)
3144 if (u.uhp > u.uhpmax)
3145 u.uhpmax = u.uhp; /* perhaps n was negative */
3148 killer.format = k_format;
3149 if (killer.name != knam) /* the thing that killed you */
3150 Strcpy(killer.name, knam ? knam : "");
3154 pline("
\82 \82È
\82½
\82Í
\8e\80\82É
\82Ü
\82µ
\82½
\81D
\81D
\81D");
3156 } else if (n > 0 && u.uhp * 10 < u.uhpmax) {
3164 register long carrcap;
3166 carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
3168 /* consistent with can_carry() in mon.c */
3169 if (youmonst.data->mlet == S_NYMPH)
3170 carrcap = MAX_CARR_CAP;
3171 else if (!youmonst.data->cwt)
3172 carrcap = (carrcap * (long) youmonst.data->msize) / MZ_HUMAN;
3173 else if (!strongmonst(youmonst.data)
3174 || (strongmonst(youmonst.data)
3175 && (youmonst.data->cwt > WT_HUMAN)))
3176 carrcap = (carrcap * (long) youmonst.data->cwt / WT_HUMAN);
3179 if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
3180 || (u.usteed && strongmonst(u.usteed->data)))
3181 carrcap = MAX_CARR_CAP;
3183 if (carrcap > MAX_CARR_CAP)
3184 carrcap = MAX_CARR_CAP;
3186 if (EWounded_legs & LEFT_SIDE)
3188 if (EWounded_legs & RIGHT_SIDE)
3194 return (int) carrcap;
3197 static int wc; /* current weight_cap(); valid after call to inv_weight() */
3199 /* returns how far beyond the normal capacity the player is currently. */
3200 /* inv_weight() is negative if the player is below normal capacity. */
3204 register struct obj *otmp = invent;
3205 register int wt = 0;
3208 if (otmp->oclass == COIN_CLASS)
3209 wt += (int) (((long) otmp->quan + 50L) / 100L);
3210 else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
3219 * Returns 0 if below normal capacity, or the number of "capacity units"
3220 * over the normal capacity the player is loaded. Max is 5.
3223 calc_capacity(xtra_wt)
3226 int cap, wt = inv_weight() + xtra_wt;
3229 return UNENCUMBERED;
3232 cap = (wt * 2 / wc) + 1;
3233 return min(cap, OVERLOADED);
3239 return calc_capacity(0);
3245 int wt = inv_weight();
3247 return (wt - (2 * wc));
3254 if (near_capacity() >= EXT_ENCUMBER) {
3259 You_cant("do that while carrying so much stuff.");
3261 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");
3271 register struct obj *otmp = invent;
3272 register int ct = 0;
3275 if (incl_gold || otmp->invlet != GOLD_SYM)
3282 /* Counts the money in an object chain. */
3283 /* Intended use is for your or some monsters inventory, */
3284 /* now that u.gold/m.gold is gone.*/
3285 /* Counting money in a container might be possible too. */
3291 /* Must change when silver & copper is implemented: */
3292 if (otmp->oclass == COIN_CLASS)