-/* NetHack 3.6 hack.c $NHDT-Date: 1446604111 2015/11/04 02:28:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.155 $ */
+/* NetHack 3.6 hack.c $NHDT-Date: 1576638500 2019/12/18 03:08:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.220 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2022 */
/* JNetHack may be freely redistributed. See license for details. */
#include "hack.h"
STATIC_DCL int NDECL(moverock);
STATIC_DCL int FDECL(still_chewing, (XCHAR_P, XCHAR_P));
STATIC_DCL void NDECL(dosinkfall);
-STATIC_DCL boolean FDECL(findtravelpath, (BOOLEAN_P));
+STATIC_DCL boolean FDECL(findtravelpath, (int));
STATIC_DCL boolean FDECL(trapmove, (int, int, struct trap *));
-STATIC_DCL void NDECL(switch_terrain);
STATIC_DCL struct monst *FDECL(monstinroom, (struct permonst *, int));
STATIC_DCL boolean FDECL(doorless_door, (int, int));
STATIC_DCL void FDECL(move_update, (BOOLEAN_P));
+STATIC_DCL void FDECL(maybe_smudge_engr, (int, int, int, int));
+STATIC_DCL void NDECL(domove_core);
#define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
+/* mode values for findtravelpath() */
+#define TRAVP_TRAVEL 0
+#define TRAVP_GUESS 1
+#define TRAVP_VALID 2
+
static anything tmp_anything;
anything *
if (mtmp && !noncorporeal(mtmp->data)
&& (!mtmp->mtrapped
- || !(ttmp && ((ttmp->ttyp == PIT)
- || (ttmp->ttyp == SPIKED_PIT))))) {
+ || !(ttmp && is_pit(ttmp->ttyp)))) {
+ boolean deliver_part1 = FALSE;
+
if (Blind)
feel_location(sx, sy);
- if (canspotmon(mtmp))
+ if (canspotmon(mtmp)) {
/*JP
pline("There's %s on the other side.", a_monnam(mtmp));
*/
pline("\94½\91Î\91¤\82É%s\82ª\82¢\82é\81D", a_monnam(mtmp));
- else {
+ deliver_part1 = TRUE;
+ } else {
/*JP
You_hear("a monster behind %s.", the(xname(otmp)));
*/
pline("%s\82Ì\94w\8cã\82É\89ö\95¨\82Ì\8bC\94z\82ª\82·\82é\81D", the(xname(otmp)));
+ if (!Deaf)
+ deliver_part1 = TRUE;
map_invisible(rx, ry);
}
- if (flags.verbose)
-#if 0 /*JP*/
- pline("Perhaps that's why %s cannot move it.",
- u.usteed ? y_monnam(u.usteed) : "you");
+ if (flags.verbose) {
+ char you_or_steed[BUFSZ];
+
+#if 0 /*JP:T*/
+ Strcpy(you_or_steed,
+ u.usteed ? y_monnam(u.usteed) : "you");
+#else
+ Strcpy(you_or_steed,
+ u.usteed ? y_monnam(u.usteed) : "\82 \82È\82½");
+#endif
+#if 0 /*JP:T*/
+ pline("%s%s cannot move %s.",
+ deliver_part1
+ ? "Perhaps that's why "
+ : "",
+ deliver_part1
+ ? you_or_steed
+ : upstart(you_or_steed),
+ deliver_part1
+ ? "it"
+ : the(xname(otmp)));
#else
- pline("\82½\82Ô\82ñ\82±\82ê\82ª\81C\8aâ\82ð\93®\82©\82¹\82È\82¢\97\9d\97R\82¾\81D");
+ /* "Perhaps that's why (you_or_steed) cannot move it."*/
+ /* "(You_or_steed) cannot move (otmp)."*/
+ if (deliver_part1) {
+ pline("\82½\82Ô\82ñ\82±\82ê\82ª\81C%s\82ª\82»\82ê\82ð\93®\82©\82¹\82È\82¢\97\9d\97R\82¾\81D",
+ you_or_steed);
+ } else {
+ pline("%s\82Í%s\82ð\93®\82©\82¹\82È\82¢\81D",
+ you_or_steed, xname(otmp));
+ }
#endif
+ }
goto cannot_push;
}
obj_extract_self(otmp);
place_object(otmp, rx, ry);
newsym(sx, sy);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("KAABLAMM!!! %s %s land mine.",
Tobjnam(otmp, "trigger"),
ttmp->madeby_u ? "your" : "a");
pline("\83h\83T\83b\81I\82 \82È\82½\82Í\82à\82¤%s\82ð\8a´\82¶\82ç\82ê\82È\82¢\81D",
the(xname(otmp)));
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s%s and %s a %s in the %s!",
Tobjnam(otmp, (ttmp->ttyp == TRAPDOOR)
? "trigger"
/* note: reset to zero after save/restore cycle */
static NEARDATA long lastmovetime;
#endif
- dopush:
+ dopush:
if (!u.usteed) {
if (moves > lastmovetime + 2 || moves < lastmovetime)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("With %s effort you move %s.",
throws_rocks(youmonst.data) ? "little"
: "great",
#endif
exercise(A_STR, TRUE);
} else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s moves %s.", upstart(y_monnam(u.usteed)),
the(xname(otmp)));
#else
newsym(sx, sy);
}
} else {
- nopushmsg:
+ nopushmsg:
if (u.usteed)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s tries to move %s, but cannot.",
upstart(y_monnam(u.usteed)), the(xname(otmp)));
#else
You("%s\82ð\93®\82©\82»\82¤\82Æ\82µ\82½\82ª\81C\82¾\82ß\82¾\82Á\82½\81D", the(xname(otmp)));
if (Blind)
feel_location(sx, sy);
- cannot_push:
+ cannot_push:
if (throws_rocks(youmonst.data)) {
+ boolean
+ canpickup = (!Sokoban
+ /* similar exception as in can_lift():
+ when poly'd into a giant, you can
+ pick up a boulder if you have a free
+ slot or into the overflow ('#') slot
+ unless already carrying at least one */
+ && (inv_cnt(FALSE) < 52 || !carrying(BOULDER))),
+ willpickup = (canpickup && autopick_testobj(otmp, TRUE));
+
if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("aren't skilled enough to %s %s from %s.",
- (flags.pickup && !Sokoban) ? "pick up" : "push aside",
+ willpickup ? "pick up" : "push aside",
the(xname(otmp)), y_monnam(u.usteed));
#else
You("%s\82É%s\82ð%s\82é\82Ù\82Ç\8bZ\97Ê\82ª\82È\82¢\81D",
- y_monnam(u.usteed),
- the(xname(otmp)),
- (flags.pickup && !Sokoban) ? "\8fE\82í\82¹" : "\89\9f\82³\82¹");
+ y_monnam(u.usteed), the(xname(otmp)),
+ willpickup ? "\8fE\82í\82¹" : "\89\9f\82³\82¹");
#endif
} else {
-#if 0 /*JP*/
- pline("However, you can easily %s.",
- (flags.pickup && !Sokoban) ? "pick it up"
- : "push it aside");
+ /*
+ * willpickup: you easily pick it up
+ * canpickup: you could easily pick it up
+ * otherwise: you easily push it aside
+ */
+#if 0 /*JP:T*/
+ pline("However, you %seasily %s.",
+ (willpickup || !canpickup) ? "" : "could ",
+ (willpickup || canpickup) ? "pick it up"
+ : "push it aside");
#else
pline("\82µ\82©\82µ\81C\82 \82È\82½\82Í\8aÈ\92P\82É\82»\82ê\82ð%s\81D",
- (flags.pickup && !Sokoban)
- ? "\8fE\82¦\82½" : "\95Ê\82Ì\95û\82É\89\9f\82¹\82½");
+ (willpickup || canpickup) ?
+ "\8fE\82¦\82½" : "\95Ê\82Ì\95û\82É\89\9f\82¹\82½");
#endif
sokoban_guilt();
break;
/*JP
"However, you can squeeze yourself into a small opening.");
*/
- "\82µ\82©\82µ\81C\82 \82È\82½\82Í\8f¬\82³\82¢\8c\84\8aÔ\82É\82±\82¶\93ü\82Á\82½\81D");
+ "\82µ\82©\82µ\81C\82 \82È\82½\82Í\8f¬\82³\82¢\8c\84\8aÔ\82É\82±\82¶\93ü\82Á\82½\81D");
sokoban_guilt();
break;
} else
/*
* still_chewing()
*
- * Chew on a wall, door, or boulder. Returns TRUE if still eating, FALSE
- * when done.
+ * Chew on a wall, door, or boulder. [What about statues?]
+ * Returns TRUE if still eating, FALSE when done.
*/
STATIC_OVL int
still_chewing(x, y)
if (context.digging.down) /* not continuing previous dig (w/ pick-axe) */
(void) memset((genericptr_t) &context.digging, 0,
- sizeof(struct dig_info));
+ sizeof (struct dig_info));
- if (!boulder && IS_ROCK(lev->typ) && !may_dig(x, y)) {
-#if 0 /*JP*/
+ if (!boulder
+ && ((IS_ROCK(lev->typ) && !may_dig(x, y))
+ /* may_dig() checks W_NONDIGGABLE but doesn't handle iron bars */
+ || (lev->typ == IRONBARS && (lev->wall_info & W_NONDIGGABLE)))) {
+#if 0 /*JP:T*/
You("hurt your teeth on the %s.",
(lev->typ == IRONBARS)
? "bars"
#else
You("%s\82Å\8e\95\82ð\92É\82ß\82½\81D",
(lev->typ == IRONBARS)
- ? "\93S\82Ì\96_"
- : IS_TREE(lev->typ)
- ? "\96Ø"
- : "\8cÅ\82¢\8aâ");
+ ? "\93S\82Ì\96_"
+ : IS_TREE(lev->typ)
+ ? "\96Ø"
+ : "\8cÅ\82¢\8aâ");
#endif
nomul(0);
return 1;
/* solid rock takes more work & time to dig through */
context.digging.effort =
(IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("start chewing %s %s.",
(boulder || IS_TREE(lev->typ) || lev->typ == IRONBARS)
? "on a"
? "tree"
: IS_ROCK(lev->typ)
? "rock"
- : lev->typ == IRONBARS
+ : (lev->typ == IRONBARS)
? "bar"
: "door");
#else
return 1;
} else if ((context.digging.effort += (30 + u.udaminc)) <= 100) {
if (flags.verbose)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("%s chewing on the %s.",
context.digging.chew ? "continue" : "begin",
boulder
if (boulder) {
delobj(boulder); /* boulder goes bye-bye */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("eat the boulder."); /* yum */
#else
You("\8aâ\82ð\90H\82×\82½\81D"); /* yum */
block_point(x, y); /* delobj will unblock the point */
/* reset dig state */
(void) memset((genericptr_t) &context.digging, 0,
- sizeof(struct dig_info));
+ sizeof (struct dig_info));
return 1;
}
} else if (IS_WALL(lev->typ)) {
if (*in_rooms(x, y, SHOPBASE)) {
- add_damage(x, y, 10L * ACURRSTR);
+ add_damage(x, y, SHOP_WALL_DMG);
/*JP
dmgtxt = "damage";
*/
} else if (IS_DOOR(lev->typ)) {
if (*in_rooms(x, y, SHOPBASE)) {
- add_damage(x, y, 400L);
+ add_damage(x, y, SHOP_DOOR_COST);
/*JP
dmgtxt = "break";
*/
if (dmgtxt)
pay_for_damage(dmgtxt, FALSE);
(void) memset((genericptr_t) &context.digging, 0,
- sizeof(struct dig_info));
+ sizeof (struct dig_info));
return 0;
}
int dmg;
boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L),
- ufall = (!innate_lev && !(HFlying || EFlying)); /* BFlying */
+ /* to handle being chained to buried iron ball, trying to
+ levitate but being blocked, then moving onto adjacent sink;
+ no need to worry about being blocked by terrain because we
+ couldn't be over a sink at the same time */
+ blockd_lev = (BLevitation == I_SPECIAL),
+ ufall = (!innate_lev && !blockd_lev
+ && !(HFlying || EFlying)); /* BFlying */
if (!ufall) {
/*JP
- You(innate_lev ? "wobble unsteadily for a moment."
+ You((innate_lev || blockd_lev) ? "wobble unsteadily for a moment."
*/
- You(innate_lev ? "\82¿\82å\82Á\82Æ\82Ó\82ç\82Â\82¢\82½\81D"
+ You((innate_lev || blockd_lev) ? "\82¿\82å\82Á\82Æ\82Ó\82ç\82Â\82¢\82½\81D"
/*JP
- : "gain control of your flight.");
+ : "gain control of your flight.");
*/
- : "\94ò\8ds\92\86\82Ì\90§\8cä\82ð\8eæ\82è\82à\82Ç\82µ\82½\81D");
+ : "\94ò\8ds\92\86\82Ì\90§\8cä\82ð\8eæ\82è\82à\82Ç\82µ\82½\81D");
} else {
long save_ELev = ELevitation, save_HLev = HLevitation;
*/
You("\8f°\82É\92@\82«\82Â\82¯\82ç\82ê\82½\81I");
dmg = rn1(8, 25 - (int) ACURR(A_CON));
+#if 0 /*JP*/
losehp(Maybe_Half_Phys(dmg), fell_on_sink, NO_KILLER_PREFIX);
+#else
+ losehp(Maybe_Half_Phys(dmg), fell_on_sink, KILLED_BY);
+#endif
exercise(A_DEX, FALSE);
/*JP
selftouch("Falling, you");
/*
* Interrupt multi-turn putting on/taking off of armor (in which
* case we reached the sink due to being teleported while busy;
- * in 3.4.3, Boots_on()/Boots_off() [called via (*aftermv)() when
+ * in 3.4.3, Boots_on()/Boots_off() [called via (*afternmv)() when
* 'multi' reaches 0] triggered a crash if we were donning/doffing
* levitation boots [because the Boots_off() below causes 'uarmf'
- * to be null by the time 'aftermv' gets called]).
+ * to be null by the time 'afternmv' gets called]).
*
* Interrupt donning/doffing if we fall onto the sink, or if the
* code below is going to remove levitation boots even when we
/* caller has already decided that it's a tight diagonal; check whether a
monster--who might be the hero--can fit through, and if not then return
- the reason why: 1: can't fit, 2: possessions won't fit, 3: sokoban */
-int /* returns 0 if we can squeeze through */
- cant_squeeze_thru(mon)
+ the reason why: 1: can't fit, 2: possessions won't fit, 3: sokoban
+ returns 0 if we can squeeze through */
+int
+cant_squeeze_thru(mon)
struct monst *mon;
{
int amt;
return 1;
/* lugging too much junk? */
- amt =
- (mon == &youmonst) ? inv_weight() + weight_cap() : curr_mon_load(mon);
+ amt = (mon == &youmonst) ? inv_weight() + weight_cap()
+ : curr_mon_load(mon);
if (amt > 600)
return 2;
}
/* return TRUE if (dx,dy) is an OK place to move
- * mode is one of DO_MOVE, TEST_MOVE or TEST_TRAV
+ * mode is one of DO_MOVE, TEST_MOVE, TEST_TRAV, or TEST_TRAP
*/
boolean
test_move(ux, uy, dx, dy, mode)
feel_location(x, y);
if (Passes_walls && may_passwall(x, y)) {
; /* do nothing */
+ } else if (Underwater) {
+ /* note: if water_friction() changes direction due to
+ turbulence, new target destination will always be water,
+ so we won't get here, hence don't need to worry about
+ "there" being somewhere the player isn't sure of */
+ if (mode == DO_MOVE)
+/*JP
+ pline("There is an obstacle there.");
+*/
+ pline("\8fá\8aQ\95¨\82ª\82 \82é\81D");
+ return FALSE;
} else if (tmpr->typ == IRONBARS) {
if ((dmgtype(youmonst.data, AD_RUST)
|| dmgtype(youmonst.data, AD_CORR)) && mode == DO_MOVE
return FALSE;
}
if (!(Passes_walls || passes_bars(youmonst.data))) {
- if (iflags.mention_walls)
+ if (mode == DO_MOVE && iflags.mention_walls)
/*JP
You("cannot pass through the bars.");
*/
return FALSE;
} else {
if (mode == DO_MOVE) {
- if (Is_stronghold(&u.uz) && is_db_wall(x, y))
+ if (is_db_wall(x, y))
/*JP
- pline_The("drawbridge is up!");
+ pline("That drawbridge is up!");
*/
pline("\92µ\82Ë\8b´\82Í\8fã\82Á\82Ä\82¢\82é\81I");
/* sokoban restriction stays even after puzzle is solved */
*/
pline_The("\91q\8cÉ\94Ô\82Ì\95Ç\82Í\82 \82È\82½\82Ì\94\\97Í\82É\92ï\8dR\82µ\82½\81D");
else if (iflags.mention_walls)
-/*JP
- pline("It's a wall.");
-*/
- pline("\82±\82ê\82Í\95Ç\82¾\81D");
+#if 0 /*JP:T*/
+ pline("It's %s.",
+ (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "a wall"
+ : IS_TREE(tmpr->typ) ? "a tree"
+ : "solid stone");
+#else
+ pline("\82±\82ê\82Í%s\82¾\81D",
+ (IS_WALL(tmpr->typ) || tmpr->typ == SDOOR) ? "\95Ç"
+ : IS_TREE(tmpr->typ) ? "\96Ø"
+ : "\90Î");
+#endif
}
return FALSE;
}
if (closed_door(x, y)) {
if (Blind && mode == DO_MOVE)
feel_location(x, y);
- if (Passes_walls)
+ if (Passes_walls) {
; /* do nothing */
- else if (can_ooze(&youmonst)) {
+ } else if (can_ooze(&youmonst)) {
if (mode == DO_MOVE)
/*JP
You("ooze under the door.");
*/
You("\83h\83A\82Ì\89º\82©\82ç\82É\82¶\82Ý\8fo\82½\81D");
+ } else if (Underwater) {
+ if (mode == DO_MOVE)
+/*JP
+ pline("There is an obstacle there.");
+*/
+ pline("\8fá\8aQ\95¨\82ª\82 \82é\81D");
+ return FALSE;
} else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
/* Eat the door. */
if (mode == DO_MOVE && still_chewing(x, y))
*/
pline("\94à\82Í\95Â\82Ü\82Á\82Ä\82¢\82é\81D");
}
- } else if (mode == TEST_TRAV)
+ } else if (mode == TEST_TRAV || mode == TEST_TRAP)
goto testdiag;
return FALSE;
}
} else {
- testdiag:
+ testdiag:
if (dx && dy && !Passes_walls
&& (!doorless_door(x, y) || block_door(x, y))) {
/* Diagonal moves into a door are not allowed. */
- if (Blind && mode == DO_MOVE)
- feel_location(x, y);
+ if (mode == DO_MOVE) {
+ if (Blind)
+ feel_location(x, y);
+ if (Underwater || iflags.mention_walls)
+/*JP
+ You_cant("move diagonally into an intact doorway.");
+*/
+ You_cant("\89ó\82ê\82Ä\82¢\82È\82¢\94à\82É\8eÎ\82ß\82É\88Ú\93®\82·\82é\82±\82Æ\82Í\82Å\82«\82È\82¢\81D");
+ }
return FALSE;
}
}
/* Pick travel path that does not require crossing a trap.
* Avoid water and lava using the usual running rules.
* (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
- if (context.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
+ if (context.run == 8 && (mode != DO_MOVE)
+ && (x != u.ux || y != u.uy)) {
struct trap *t = t_at(x, y);
if ((t && t->tseen)
|| (!Levitation && !Flying && !is_clinger(youmonst.data)
&& is_pool_or_lava(x, y) && levl[x][y].seenv))
- return FALSE;
+ return (mode == TEST_TRAP);
}
+ if (mode == TEST_TRAP)
+ return FALSE; /* do not move through traps */
+
ust = &levl[ux][uy];
/* Now see if other things block our way . . */
if (dx && dy && !Passes_walls && IS_DOOR(ust->typ)
&& (!doorless_door(ux, uy) || block_entry(x, y))) {
/* Can't move at a diagonal out of a doorway with door. */
+ if (mode == DO_MOVE && iflags.mention_walls)
+/*JP
+ You_cant("move diagonally out of an intact doorway.");
+*/
+ You_cant("\89ó\82ê\82Ä\82¢\82È\82¢\94à\82©\82ç\8eÎ\82ß\82É\88Ú\93®\82·\82é\82±\82Æ\82Í\82Å\82«\82È\82¢\81D");
return FALSE;
}
if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
if (!(Blind || Hallucination) && (context.run >= 2)
- && mode != TEST_TRAV)
+ && mode != TEST_TRAV) {
+ if (mode == DO_MOVE && iflags.mention_walls)
+/*JP
+ pline("A boulder blocks your path.");
+*/
+ pline("\8b\90\8aâ\82ª\93¹\82ð\82Ó\82³\82¢\82Å\82¢\82é\81D");
return FALSE;
+ }
if (mode == DO_MOVE) {
/* tunneling monsters will chew before pushing */
if (tunnels(youmonst.data) && !needspick(youmonst.data)
} else if (mode == TEST_TRAV) {
struct obj *obj;
+ /* never travel through boulders in Sokoban */
+ if (Sokoban)
+ return FALSE;
+
/* don't pick two boulders in a row, unless there's a way thru */
if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
if (!Passes_walls
return TRUE;
}
-#ifdef DEBUG
-static boolean trav_debug = FALSE;
-
-/* in this case, toggle display of travel debug info */
-int wiz_debug_cmd_traveldisplay()
-{
- trav_debug = !trav_debug;
- return 0;
-}
-#endif /* DEBUG */
-
/*
* Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
* A shortest path is returned. If guess is TRUE, consider various
* Returns TRUE if a path was found.
*/
STATIC_OVL boolean
-findtravelpath(guess)
-boolean guess;
+findtravelpath(mode)
+int mode;
{
/* if travel to adjacent, reachable location, use normal movement rules */
- if (!guess && context.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1
+ if ((mode == TRAVP_TRAVEL || mode == TRAVP_VALID) && context.travel1
+ && distmin(u.ux, u.uy, u.tx, u.ty) == 1
&& !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
context.run = 0;
if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
- u.dx = u.tx - u.ux;
- u.dy = u.ty - u.uy;
- nomul(0);
- iflags.travelcc.x = iflags.travelcc.y = -1;
+ if (mode == TRAVP_TRAVEL) {
+ u.dx = u.tx - u.ux;
+ u.dy = u.ty - u.uy;
+ nomul(0);
+ iflags.travelcc.x = iflags.travelcc.y = 0;
+ }
return TRUE;
}
- context.run = 8;
+ if (mode == TRAVP_TRAVEL)
+ context.run = 8;
}
if (u.tx != u.ux || u.ty != u.uy) {
xchar travel[COLNO][ROWNO];
* goal is the position the player knows of, or might figure out
* (couldsee) that is closest to the target on a straight path.
*/
- if (guess) {
+ if (mode == TRAVP_GUESS || mode == TRAVP_VALID) {
tx = u.ux;
ty = u.uy;
ux = u.tx;
uy = u.uy;
}
- noguess:
- (void) memset((genericptr_t) travel, 0, sizeof(travel));
+ noguess:
+ (void) memset((genericptr_t) travel, 0, sizeof travel);
travelstepx[0][0] = tx;
travelstepy[0][0] = ty;
static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
/* no diagonal movement for grid bugs */
int dirmax = NODIAG(u.umonnum) ? 4 : 8;
+ boolean alreadyrepeated = FALSE;
for (dir = 0; dir < dirmax; ++dir) {
int nx = x + xdir[ordered[dir]];
int ny = y + ydir[ordered[dir]];
- if (!isok(nx, ny))
+ /*
+ * When guessing and trying to travel as close as possible
+ * to an unreachable target space, don't include spaces
+ * that would never be picked as a guessed target in the
+ * travel matrix describing hero-reachable spaces.
+ * This stops travel from getting confused and moving
+ * the hero back and forth in certain degenerate
+ * configurations of sight-blocking obstacles, e.g.
+ *
+ * T 1. Dig this out and carry enough to not be
+ * #### able to squeeze through diagonal gaps.
+ * #--.--- Stand at @ and target travel at space T.
+ * @.....
+ * |.....
+ *
+ * T 2. couldsee() marks spaces marked a and x
+ * #### as eligible guess spaces to move the hero
+ * a--.--- towards. Space a is closest to T, so it
+ * @xxxxx gets chosen. Travel system moves @ right
+ * |xxxxx to travel to space a.
+ *
+ * T 3. couldsee() marks spaces marked b, c and x
+ * #### as eligible guess spaces to move the hero
+ * a--c--- towards. Since findtravelpath() is called
+ * b@xxxx repeatedly during travel, it doesn't
+ * |xxxxx remember that it wanted to go to space a,
+ * so in comparing spaces b and c, b is
+ * chosen, since it seems like the closest
+ * eligible space to T. Travel system moves @
+ * left to go to space b.
+ *
+ * 4. Go to 2.
+ *
+ * By limiting the travel matrix here, space a in the
+ * example above is never included in it, preventing
+ * the cycle.
+ */
+ if (!isok(nx, ny)
+ || ((mode == TRAVP_GUESS) && !couldsee(nx, ny)))
continue;
if ((!Passes_walls && !can_ooze(&youmonst)
- && closed_door(x, y)) || sobj_at(BOULDER, x, y)) {
+ && closed_door(x, y)) || sobj_at(BOULDER, x, y)
+ || test_move(x, y, nx-x, ny-y, TEST_TRAP)) {
/* closed doors and boulders usually
* cause a delay, so prefer another path */
if (travel[x][y] > radius - 3) {
- travelstepx[1 - set][nn] = x;
- travelstepy[1 - set][nn] = y;
- /* don't change travel matrix! */
- nn++;
+ if (!alreadyrepeated) {
+ travelstepx[1 - set][nn] = x;
+ travelstepy[1 - set][nn] = y;
+ /* don't change travel matrix! */
+ nn++;
+ alreadyrepeated = TRUE;
+ }
continue;
}
}
&& (levl[nx][ny].seenv
|| (!Blind && couldsee(nx, ny)))) {
if (nx == ux && ny == uy) {
- if (!guess) {
+ if (mode == TRAVP_TRAVEL || mode == TRAVP_VALID) {
u.dx = x - ux;
u.dy = y - uy;
- if (x == u.tx && y == u.ty) {
+ if (mode == TRAVP_TRAVEL
+ && x == u.tx && y == u.ty) {
nomul(0);
/* reset run so domove run checks work */
context.run = 8;
- iflags.travelcc.x = iflags.travelcc.y =
- -1;
+ iflags.travelcc.x = iflags.travelcc.y = 0;
}
return TRUE;
}
}
#ifdef DEBUG
- if (trav_debug) {
+ if (iflags.trav_debug) {
/* Use of warning glyph is arbitrary. It stands out. */
tmp_at(DISP_ALL, warning_to_glyph(1));
for (i = 0; i < nn; ++i) {
}
/* if guessing, find best location in travel matrix and go there */
- if (guess) {
+ if (mode == TRAVP_GUESS) {
int px = tx, py = ty; /* pick location */
int dist, nxtdist, d2, nd2;
goto found;
}
#ifdef DEBUG
- if (trav_debug) {
+ if (iflags.trav_debug) {
/* Use of warning glyph is arbitrary. It stands out. */
tmp_at(DISP_ALL, warning_to_glyph(2));
tmp_at(px, py);
uy = u.uy;
set = 0;
n = radius = 1;
- guess = FALSE;
+ mode = TRAVP_TRAVEL;
goto noguess;
}
return FALSE;
}
-found:
+ found:
u.dx = 0;
u.dy = 0;
nomul(0);
return FALSE;
}
+boolean
+is_valid_travelpt(x,y)
+int x,y;
+{
+ int tx = u.tx;
+ int ty = u.ty;
+ boolean ret;
+ int g = glyph_at(x,y);
+
+ if (x == u.ux && y == u.uy)
+ return TRUE;
+ if (isok(x,y) && glyph_is_cmap(g) && S_stone == glyph_to_cmap(g)
+ && !levl[x][y].seenv)
+ return FALSE;
+ u.tx = x;
+ u.ty = y;
+ ret = findtravelpath(TRAVP_VALID);
+ u.tx = tx;
+ u.ty = ty;
+ return ret;
+}
+
/* try to escape being stuck in a trapped state by walking out of it;
return true iff moving should continue to intended destination
(all failures and most successful escapes leave hero at original spot) */
int x, y; /* targetted destination, <u.ux+u.dx,u.uy+u.dy> */
struct trap *desttrap; /* nonnull if another trap at <x,y> */
{
- boolean anchored;
+ boolean anchored = FALSE;
const char *predicament, *culprit;
char *steedname = !u.usteed ? (char *) 0 : y_monnam(u.usteed);
if (!u.utrap)
return TRUE; /* sanity check */
+ /*
+ * Note: caller should call reset_utrap() when we set u.utrap to 0.
+ */
+
switch (u.utraptype) {
case TT_BEARTRAP:
if (flags.verbose) {
/* [why does diagonal movement give quickest escape?] */
if ((u.dx && u.dy) || !rn2(5))
u.utrap--;
+ if (!u.utrap)
+ goto wriggle_free;
break;
case TT_PIT:
if (desttrap && desttrap->tseen
- && (desttrap->ttyp == PIT || desttrap->ttyp == SPIKED_PIT))
+ && is_pit(desttrap->ttyp))
return TRUE; /* move into adjacent pit */
/* try to escape; position stays same regardless of success */
climb_pit();
break;
case TT_WEB:
if (uwep && uwep->oartifact == ART_STING) {
- u.utrap = 0;
+ /* escape trap but don't move and don't destroy it */
+ u.utrap = 0; /* caller will call reset_utrap() */
/*JP
pline("Sting cuts through the web!");
*/
pline("\83X\83e\83B\83\93\83O\82Í\82\82à\82Ì\91\83\82ð\90Ø\82è\82³\82¢\82½\81I");
- break; /* escape trap but don't move */
+ break;
}
if (--u.utrap) {
if (flags.verbose) {
if ((u.utrap & 0xff) == 0) {
u.utrap = 0;
if (u.usteed)
-/*JP
- You("lead %s to the edge of the lava.", steedname);
-*/
- You("%s\82ð\97n\8aâ\82Ì\92[\82Ü\82Å\93±\82¢\82½\81D", steedname);
+#if 0 /*JP:T*/
+ You("lead %s to the edge of the %s.", steedname,
+ hliquid("lava"));
+#else
+ You("%s\82ð%s\82Ì\92[\82Ü\82Å\93±\82¢\82½\81D", steedname,
+ hliquid("\97n\8aâ"));
+#endif
else
-/*JP
- You("pull yourself to the edge of the lava.");
-*/
- You("\97n\8aâ\82Ì\92[\82Ü\82Å\82©\82ë\82¤\82¶\82Ä\81C\82½\82Ç\82è\82Â\82¢\82½\81D");
+#if 0 /*JP:T*/
+ You("pull yourself to the edge of the %s.",
+ hliquid("lava"));
+#else
+ You("%s\82Ì\92[\82Ü\82Å\82©\82ë\82¤\82¶\82Ä\81C\82½\82Ç\82è\82Â\82¢\82½\81D",
+ hliquid("\97n\8aâ"));
+#endif
}
}
u.umoved = TRUE;
if (--u.utrap) {
if (flags.verbose) {
if (anchored) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
predicament = "chained to the";
culprit = "buried ball";
#else
culprit = "\96\84\82Ü\82Á\82Ä\82¢\82é\8b\85";
#endif
} else {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
predicament = "stuck in the";
culprit = surface(u.ux, u.uy);
#else
}
if (u.usteed) {
if (anchored)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Norep("You and %s are %s %s.", steedname, predicament,
culprit);
#else
predicament);
#endif
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Norep("%s is %s %s.", upstart(steedname), predicament,
culprit);
#else
Norep("\82 \82È\82½\82Í%s\82É%s\81D", culprit, predicament);
}
} else {
+ wriggle_free:
if (u.usteed)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s finally %s free.", upstart(steedname),
!anchored ? "lurches" : "wrenches the ball");
#else
!anchored ? "\82à\82ª\82¢\82Ä" : "\93S\8b\85\82ð\82à\82¬\8eæ\82Á\82Ä");
#endif
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("finally %s free.",
!anchored ? "wriggle" : "wrench the ball");
#else
u_rooted()
{
if (!youmonst.data->mmove) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("are rooted %s.",
Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
? "in place"
void
domove()
{
+ int ux1 = u.ux, uy1 = u.uy;
+
+ domove_succeeded = 0L;
+ domove_core();
+ /* domove_succeeded is available for making assessments now */
+ if ((domove_succeeded & (DOMOVE_RUSH | DOMOVE_WALK)) != 0)
+ maybe_smudge_engr(ux1, uy1, u.ux, u.uy);
+ domove_attempting = 0L;
+}
+
+STATIC_OVL void
+domove_core()
+{
register struct monst *mtmp;
register struct rm *tmpr;
register xchar x, y;
xchar chainx = 0, chainy = 0,
ballx = 0, bally = 0; /* ball&chain new positions */
int bc_control = 0; /* control for ball&chain */
- boolean cause_delay = FALSE; /* dragging ball will skip a move */
-
- u_wipe_engr(rnd(5));
+ boolean cause_delay = FALSE, /* dragging ball will skip a move */
+ u_with_boulder = (sobj_at(BOULDER, u.ux, u.uy) != 0);
if (context.travel) {
if (!findtravelpath(FALSE))
on_ice = !Levitation && is_ice(u.ux, u.uy);
if (on_ice) {
static int skates = 0;
+
if (!skates)
skates = find_skates();
if ((uarmf && uarmf->otyp == skates) || resists_cold(&youmonst)
|| Flying || is_floater(youmonst.data)
- || is_clinger(youmonst.data) || is_whirly(youmonst.data))
+ || is_clinger(youmonst.data) || is_whirly(youmonst.data)) {
on_ice = FALSE;
- else if (!rn2(Cold_resistance ? 3 : 2)) {
+ } else if (!rn2(Cold_resistance ? 3 : 2)) {
HFumbling |= FROMOUTSIDE;
HFumbling &= ~TIMEOUT;
HFumbling += 1; /* slip on next move */
}
x = u.ux + u.dx;
y = u.uy + u.dy;
+
+ /* are we trying to move out of water while carrying too much? */
+ if (isok(x, y) && !is_pool(x, y) && !Is_waterlevel(&u.uz)
+ && wtcap > (Swimming ? MOD_ENCUMBER : SLT_ENCUMBER)) {
+ /* when escaping from drowning you need to be unencumbered
+ in order to crawl out of water, but when not drowning,
+ doing so while encumbered is feasible; if in an aquatic
+ form, stressed or less is allowed; otherwise (magical
+ breathing), only burdened is allowed */
+/*JP
+ You("are carrying too much to climb out of the water.");
+*/
+ You("\90\85\82©\82ç\8fã\82ª\82é\82É\82Í\89×\95¨\82ð\8e\9d\82¿\82·\82¬\82Ä\82¢\82é\81D");
+ nomul(0);
+ return;
+ }
}
if (!isok(x, y)) {
+ if (iflags.mention_walls) {
+ int dx = u.dx, dy = u.dy;
+
+ if (dx && dy) { /* diagonal */
+ /* only as far as possible diagonally if in very
+ corner; otherwise just report whichever of the
+ cardinal directions has reached its limit */
+ if (isok(x, u.uy))
+ dx = 0;
+ else if (isok(u.ux, y))
+ dy = 0;
+ }
+#if 0 /*JP*/
+ You("have already gone as far %s as possible.",
+ directionname(xytod(dx, dy)));
+#else
+ You("\82·\82Å\82É\82Å\82«\82é\82¾\82¯%s\82É\93®\82¢\82Ä\82¢\82é\81D",
+ directionname(xytod(dx, dy)));
+#endif
+ }
nomul(0);
return;
}
|| (Blind && !Levitation && !Flying && !is_clinger(youmonst.data)
&& is_pool_or_lava(x, y) && levl[x][y].seenv)) {
if (context.run >= 2) {
+ if (iflags.mention_walls) {
+ if (trap && trap->tseen) {
+ int tt = what_trap(trap->ttyp, rn2_on_display_rng);
+
+/*JP
+ You("stop in front of %s.",
+*/
+ You("%s\82Ì\8eè\91O\82Å\8e~\82Ü\82Á\82½\81D",
+ an(defsyms[trap_to_defsym(tt)].explanation));
+ } else if (is_pool_or_lava(x,y) && levl[x][y].seenv) {
+#if 0 /*JP:T*/
+ You("stop at the edge of the %s.",
+ hliquid(is_pool(x,y) ? "water" : "lava"));
+#else
+ You("%s\82Ì\92[\82Å\8e~\82Ü\82Á\82½\81D.",
+ hliquid(is_pool(x,y) ? "\90\85" : "\97n\8aâ"));
+#endif
+ }
+ }
nomul(0);
context.move = 0;
return;
case 0:
case 1:
case 2:
- pull_free:
+ pull_free:
/*JP
You("pull free from %s.", mon_nam(u.ustuck));
*/
}
mtmp = m_at(x, y);
- if (mtmp) {
+ if (mtmp && !is_safepet(mtmp)) {
/* Don't attack if you're running, and can see it */
+ /* It's fine to displace pets, though */
/* We should never get here if forcefight */
if (context.run && ((!Blind && mon_visible(mtmp)
- && ((mtmp->m_ap_type != M_AP_FURNITURE
- && mtmp->m_ap_type != M_AP_OBJECT)
+ && ((M_AP_TYPE(mtmp) != M_AP_FURNITURE
+ && M_AP_TYPE(mtmp) != M_AP_OBJECT)
|| Protection_from_shape_changers))
|| sensemon(mtmp))) {
nomul(0);
/* attack monster */
if (mtmp) {
- nomul(0);
+ /* don't stop travel when displacing pets; if the
+ displace fails for some reason, attack() in uhitm.c
+ will stop travel rather than domove */
+ if (!is_safepet(mtmp) || context.forcefight)
+ nomul(0);
/* only attack if we know it's there */
/* or if we used the 'F' command to fight blindly */
/* or if it hides_under, in which case we call attack() to print
* attack_check(), which still wastes a turn, but prints a
* different message and makes the player remember the monster.
*/
- if (context.nopick
+ if (context.nopick && !context.travel
&& (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))) {
- if (mtmp->m_ap_type && !Protection_from_shape_changers
+ if (M_AP_TYPE(mtmp) && !Protection_from_shape_changers
&& !sensemon(mtmp))
stumble_onto_mimic(mtmp);
else if (mtmp->mpeaceful && !Hallucination)
+ /* m_monnam(): "dog" or "Fido", no "invisible dog" or "it" */
/*JP
pline("Pardon me, %s.", m_monnam(mtmp));
*/
}
}
+ if (context.forcefight && levl[x][y].typ == IRONBARS && uwep) {
+ struct obj *obj = uwep;
+
+ if (breaktest(obj)) {
+ if (obj->quan > 1L)
+ obj = splitobj(obj, 1L);
+ else
+ setuwep((struct obj *)0);
+ freeinv(obj);
+ }
+ hit_bars(&obj, u.ux, u.uy, x, y, TRUE, TRUE);
+ return;
+ }
+
/* specifying 'F' with no monster wastes a turn */
if (context.forcefight
/* remembered an 'I' && didn't use a move command */
newsym(x, y);
glyph = glyph_at(x, y); /* might have just changed */
- if (boulder)
+ if (boulder) {
Strcpy(buf, ansimpleoname(boulder));
- else if (Underwater && !is_pool(x, y))
+ } else if (Underwater && !is_pool(x, y)) {
/* Underwater, targetting non-water; the map just shows blank
because you don't see remembered terrain while underwater;
although the hero can attack an adjacent monster this way,
assume he can't reach out far enough to distinguish terrain */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR)
? "an air bubble"
: "nothing");
? "\8bó\8bC\82Ì\96A"
: "\89½\82à\82È\82¢\82Æ\82±\82ë");
#endif
- else if (solid)
+ } else if (solid) {
/* glyph might indicate unseen terrain if hero is blind;
unlike searching, this won't reveal what that terrain is
(except for solid rock, where the glyph would otherwise
yield ludicrous "dark part of a room") */
-#if 0 /*JP*/
- Strcpy(buf,
- (levl[x][y].typ == STONE)
- ? "solid rock"
- : glyph_is_cmap(glyph)
+#if 0 /*JP:T*/
+ Strcpy(buf, (levl[x][y].typ == STONE) ? "solid rock"
+ : glyph_is_cmap(glyph)
? the(defsyms[glyph_to_cmap(glyph)].explanation)
: (const char *) "an unknown obstacle");
#else
- Strcpy(buf,
- (levl[x][y].typ == STONE)
- ? "\90Î"
- : glyph_is_cmap(glyph)
+ Strcpy(buf, (levl[x][y].typ == STONE) ? "\90Î"
+ : glyph_is_cmap(glyph)
? the(defsyms[glyph_to_cmap(glyph)].explanation)
: (const char *) "\95s\96¾\82È\8fá\8aQ\95¨");
#endif
- /* note: 'solid' is misleadingly named and catches pools
- of water and lava as well as rock and walls */
- else
+ /* note: 'solid' is misleadingly named and catches pools
+ of water and lava as well as rock and walls */
+ } else {
/*JP
Strcpy(buf, "thin air");
*/
Strcpy(buf, "\89½\82à\82È\82¢\8bó\92\86");
-#if 0 /*JP*/
+ }
+#if 0 /*JP:T*/
You("%s%s %s.",
!(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
explo ? "explode at" : "attack", buf);
#else
- You("%s%s%s.",
+ You("%s%s%s\81D",
!(boulder || solid) ? "" : !explo ? "\8cø\89Ê\82È\82" : "\82Þ\82¾\82É",
buf, explo ? "\82Å\94\9a\94\82µ\82½" : "\82ð\8dU\8c\82\82µ\82½");
#endif
}
return;
}
- if (glyph_is_invisible(levl[x][y].glyph)) {
- unmap_object(x, y);
- newsym(x, y);
- }
+ (void) unmap_invisible(x, y);
/* not attacking an animal, so we try to move */
if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
nomul(0);
return;
if (u.utrap) {
- if (!trapmove(x, y, trap))
+ boolean moved = trapmove(x, y, trap);
+
+ if (!u.utrap)
+ reset_utrap(TRUE); /* might resume levitation or flight */
+ /* might not have escaped, or did escape but remain in same spot */
+ if (!moved)
return;
}
yelp(mtmp);
}
}
+
+ /* seemimic/newsym should be done before moving hero, otherwise
+ the display code will draw the hero here before we possibly
+ cancel the swap below (we can ignore steed mx,my here) */
+ u.ux = u.ux0, u.uy = u.uy0;
mtmp->mundetected = 0;
- if (mtmp->m_ap_type)
+ if (M_AP_TYPE(mtmp))
seemimic(mtmp);
else if (!mtmp->mtame)
newsym(mtmp->mx, mtmp->my);
+ u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
- && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
+ && is_pit(trap->ttyp)
&& sobj_at(BOULDER, trap->tx, trap->ty)) {
/* can't swap places with pet pinned in a pit by a boulder */
u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+ if (u.usteed)
+ u.usteed->mx = u.ux, u.usteed->my = u.uy;
} else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
/* can't swap places when pet can't move to your spot */
u.ux = u.ux0, u.uy = u.uy0;
+ if (u.usteed)
+ u.usteed->mx = u.ux, u.usteed->my = u.uy;
/*JP
You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp)));
*/
You("\8e~\82Ü\82Á\82½\81D%s\82Í\8eÎ\82ß\82É\93®\82¯\82È\82¢\81D", upstart(y_monnam(mtmp)));
+ } else if (u_with_boulder
+ && !(verysmall(mtmp->data)
+ && (!mtmp->minvent || (curr_mon_load(mtmp) <= 600)))) {
+ /* can't swap places when pet won't fit there with the boulder */
+ u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+ if (u.usteed)
+ u.usteed->mx = u.ux, u.usteed->my = u.uy;
+#if 0 /*JP:T*/
+ You("stop. %s won't fit into the same spot that you're at.",
+ upstart(y_monnam(mtmp)));
+#else
+ You("\8e~\82Ü\82Á\82½\81D%s\82Í\82 \82È\82½\82Ì\82¢\82é\82Ì\82Æ\93¯\82¶\8fê\8f\8a\82É\82Í\8eû\82Ü\82ç\82È\82¢\81D",
+ y_monnam(mtmp));
+#endif
} else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0)
&& bad_rock(mtmp->data, u.ux0, y)
&& (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
/* can't swap places when pet won't fit thru the opening */
u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+ if (u.usteed)
+ u.usteed->mx = u.ux, u.usteed->my = u.uy;
/*JP
You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
*/
newsym(x, y);
newsym(u.ux0, u.uy0);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
pnambuf);
#else
nomul(0);
}
- if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) || u.dx
- || u.dy)
+ if (hides_under(youmonst.data) || youmonst.data->mlet == S_EEL
+ || u.dx || u.dy)
(void) hideunder(&youmonst);
/*
* imitating something that doesn't move. We could extend this
* to non-moving monsters...
*/
- if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
- || youmonst.m_ap_type == M_AP_FURNITURE))
+ if ((u.dx || u.dy) && (U_AP_TYPE == M_AP_OBJECT
+ || U_AP_TYPE == M_AP_FURNITURE))
youmonst.m_ap_type = M_AP_NOTHING;
check_leash(u.ux0, u.uy0);
if (u.ux0 != u.ux || u.uy0 != u.uy) {
+ /* let caller know so that an evaluation may take place */
+ domove_succeeded |= (domove_attempting & (DOMOVE_RUSH | DOMOVE_WALK));
u.umoved = TRUE;
/* Clean old position -- vision_recalc() will print our new one. */
newsym(u.ux0, u.uy0);
if (Punished) /* put back ball and chain */
move_bc(0, bc_control, ballx, bally, chainx, chainy);
- spoteffects(TRUE);
+ if (u.umoved)
+ spoteffects(TRUE);
/* delay next move because of ball dragging */
/* must come after we finished picking up, in spoteffects() */
if (cause_delay) {
nomul(-2);
+/*JP
multi_reason = "dragging an iron ball";
+*/
+ multi_reason = "\93S\8b\85\82É\88ø\82«\82¸\82ç\82ê\82Ä\82¢\82é\8e\9e\82É";
nomovemsg = "";
}
}
}
+STATIC_OVL void
+maybe_smudge_engr(x1,y1,x2,y2)
+int x1, y1, x2, y2;
+{
+ struct engr *ep;
+
+ if (can_reach_floor(TRUE)) {
+ if ((ep = engr_at(x1, y1)) && ep->engr_type != HEADSTONE)
+ wipe_engr_at(x1, y1, rnd(5), FALSE);
+ if ((x2 != x1 || y2 != y1)
+ && (ep = engr_at(x2, y2)) && ep->engr_type != HEADSTONE)
+ wipe_engr_at(x2, y2, rnd(5), FALSE);
+ }
+}
+
/* combat increases metabolism */
boolean
overexertion()
You("%s\8aï\96\82È\90U\93®\82ð\8a´\82¶\82½\81D", buf);
u.uevent.uvibrated = 1;
if (otmp && otmp->spe == 7 && otmp->lamplit)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s %s!", The(xname(otmp)),
Blind ? "throbs palpably" : "glows with a strange light");
#else
/* moving onto different terrain;
might be going into solid rock, inhibiting levitation or flight,
or coming back out of such, reinstating levitation/flying */
-STATIC_OVL void
+void
switch_terrain()
{
struct rm *lev = &levl[u.ux][u.uy];
boolean blocklev = (IS_ROCK(lev->typ) || closed_door(u.ux, u.uy)
- || (Is_waterlevel(&u.uz) && lev->typ == WATER));
+ || (Is_waterlevel(&u.uz) && lev->typ == WATER)),
+ was_levitating = !!Levitation, was_flying = !!Flying;
if (blocklev) {
- /* called from spoteffects(), skip float_down() */
+ /* called from spoteffects(), stop levitating but skip float_down() */
if (Levitation)
/*JP
You_cant("levitate in here.");
BLevitation |= FROMOUTSIDE;
} else if (BLevitation) {
BLevitation &= ~FROMOUTSIDE;
- if (Levitation)
+ /* we're probably levitating now; if not, we must be chained
+ to a buried iron ball so get float_up() feedback for that */
+ if (Levitation || BLevitation)
float_up();
}
/* the same terrain that blocks levitation also blocks flight */
*/
You("\94ò\82Ñ\82Í\82¶\82ß\82½\81D");
}
+ if ((!Levitation ^ was_levitating) || (!Flying ^ was_flying))
+ context.botl = TRUE; /* update Lev/Fly status condition */
}
/* extracted from spoteffects; called by spoteffects to check for entering or
- leaving a pool of water/lava, and by moveloop to check for staying on one
-
+ leaving a pool of water/lava, and by moveloop to check for staying on one;
returns true to skip rest of spoteffects */
boolean
pooleffects(newspot)
*/
You("\82Ð\82å\82¢\82Æ\8bó\8bC\82Ì\96A\82É\93ü\82Á\82½\81D");
else if (is_lava(u.ux, u.uy))
-#if 0 /*JP*/
- You("leave the water..."); /* oops! */
+#if 0 /*JP:T*/
+ You("leave the %s...", hliquid("water")); /* oops! */
#else
- You("\90\85\82©\82ç\94²\82¯\82¾\82µ\82½\81D\81D\81D"); /* oops! */
+ You("%s\90\85\82©\82ç\94²\82¯\82¾\82µ\82½\81D\81D\81D", hliquid("\90\85")); /* oops! */
#endif
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("are on solid %s again.",
is_ice(u.ux, u.uy) ? "ice" : "land");
#else
still_inwater = TRUE;
} else if (Levitation) {
/*JP
- You("pop out of the water like a cork!");
+ You("pop out of the %s like a cork!", hliquid("water"));
*/
- You("\83R\83\8b\83N\82Ì\82æ\82¤\82É\94ò\82Ñ\82¾\82µ\82½\81I");
+ You("\83R\83\8b\83N\82Ì\82æ\82¤\82É%s\82©\82ç\94ò\82Ñ\82¾\82µ\82½\81I", hliquid("\90\85"));
} else if (Flying) {
/*JP
- You("fly out of the water.");
+ You("fly out of the %s.", hliquid("water"));
*/
- You("\90\85\82©\82ç\94ò\82Ñ\82¾\82µ\82½\81D");
+ You("%s\82©\82ç\94ò\82Ñ\82¾\82µ\82½\81D", hliquid("\90\85"));
} else if (Wwalking) {
/*JP
You("slowly rise above the surface.");
}
/* not mounted */
+ /* if hiding on ceiling then don't automatically enter pool */
+ if (Upolyd && ceiling_hider(&mons[u.umonnum]) && u.uundetected)
+ return FALSE;
+
/* drown(),lava_effects() return true if hero changes
location while surviving the problem */
if (is_lava(u.ux, u.uy)) {
static int spotterrain;
static struct trap *spottrap = (struct trap *) 0;
static unsigned spottraptyp = NO_TRAP;
+
+ struct monst *mtmp;
struct trap *trap = t_at(u.ux, u.uy);
- register struct monst *mtmp;
+ int trapflag = iflags.failing_untrap ? FAILEDUNTRAP : 0;
/* prevent recursion from affecting the hero all over again
[hero poly'd to iron golem enters water here, drown() inflicts
spotterrain = levl[u.ux][u.uy].typ;
spotloc.x = u.ux, spotloc.y = u.uy;
- /* moving onto different terrain might cause Levitation to toggle */
+ /* moving onto different terrain might cause Lev or Fly to toggle */
if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
switch_terrain();
turn, allowing it to do so could give the perception
that a trap here is being triggered twice, so adjust
the timeout to prevent that */
- if (trap && (HLevitation & TIMEOUT) == 1L && !ELevitation
- && !(HLevitation & ~TIMEOUT)) {
+ if (trap && (HLevitation & TIMEOUT) == 1L
+ && !(ELevitation || (HLevitation & ~(I_SPECIAL | TIMEOUT)))) {
if (rn2(2)) { /* defer timeout */
incr_itimeout(&HLevitation, 1L);
} else { /* timeout early */
}
}
/*
- * If not a pit, pickup before triggering trap.
- * If pit, trigger trap before pickup.
- */
- pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
+ * If not a pit, pickup before triggering trap.
+ * If pit, trigger trap before pickup.
+ */
+ pit = (trap && is_pit(trap->ttyp));
if (pick && !pit)
(void) pickup(1);
if (trap) {
/*
- * dotrap on a fire trap calls melt_ice() which triggers
- * spoteffects() (again) which can trigger the same fire
- * trap (again). Use static spottrap to prevent that.
- * We track spottraptyp because some traps morph
- * (landmine to pit) and any new trap type
- * should get triggered.
- */
+ * dotrap on a fire trap calls melt_ice() which triggers
+ * spoteffects() (again) which can trigger the same fire
+ * trap (again). Use static spottrap to prevent that.
+ * We track spottraptyp because some traps morph
+ * (landmine to pit) and any new trap type
+ * should get triggered.
+ */
if (!spottrap || spottraptyp != trap->ttyp) {
spottrap = trap;
spottraptyp = trap->ttyp;
- dotrap(trap, 0); /* fall into arrow trap, etc. */
+ dotrap(trap, trapflag); /* fall into arrow trap, etc. */
spottrap = (struct trap *) 0;
spottraptyp = NO_TRAP;
}
/* Warning alerts you to ice danger */
if (Warning && is_ice(u.ux, u.uy)) {
static const char *const icewarnings[] = {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
"The ice seems very soft and slushy.",
"You feel the ice shift beneath you!",
"The ice, is gonna BREAK!", /* The Dead Zone */
#endif
};
long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
+
if (time_left && time_left < 15L)
- pline1((time_left < 5L) ? icewarnings[2] : (time_left < 10L)
- ? icewarnings[1]
- : icewarnings[0]);
+ pline("%s", icewarnings[(time_left < 5L) ? 2
+ : (time_left < 10L) ? 1
+ : 0]);
}
if ((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
mtmp->mundetected = mtmp->msleeping = 0;
switch (mtmp->data->mlet) {
case S_PIERCER:
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s suddenly drops from the %s!", Amonnam(mtmp),
ceiling(u.ux, u.uy));
#else
- pline("%s\82ª\93Ë\91R%s\82©\82ç\97\8e\82¿\82Ä\82«\82½\81I",
- Amonnam(mtmp), ceiling(u.ux,u.uy));
+ pline("%s\82ª\93Ë\91R%s\82©\82ç\97\8e\82¿\82Ä\82«\82½\81I", Amonnam(mtmp),
+ ceiling(u.ux,u.uy));
#endif
- if (mtmp->mtame) /* jumps to greet you, not attack */
+ if (mtmp->mtame) { /* jumps to greet you, not attack */
;
- else if (uarmh && is_metallic(uarmh))
+ } else if (uarmh && is_metallic(uarmh)) {
/*JP
pline("Its blow glances off your %s.",
*/
pline("\8dU\8c\82\82Í\82 \82È\82½\82Ì%s\82ð\82©\82·\82ß\82½\82¾\82¯\82¾\82Á\82½\81D",
helm_simple_name(uarmh));
- else if (u.uac + 3 <= rnd(20))
-#if 0 /*JP*/
+ } else if (u.uac + 3 <= rnd(20)) {
+#if 0 /*JP:T*/
You("are almost hit by %s!",
x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
#else
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",
x_monnam(mtmp, ARTICLE_A, "", 0, TRUE));
#endif
- else {
+ } else {
int dmg;
-#if 0 /*JP*/
+
+#if 0 /*JP:T*/
You("are hit by %s!",
x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
#else
break;
default: /* monster surprises you. */
if (mtmp->mtame)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s jumps near you from the %s.", Amonnam(mtmp),
ceiling(u.ux, u.uy));
#else
}
mnexto(mtmp); /* have to move the monster */
}
-spotdone:
+ spotdone:
if (!--inspoteffects) {
spotterrain = STONE; /* 0 */
spotloc.x = spotloc.y = 0;
int typefound, min_x, min_y, max_x, max_y_offset, step;
register struct rm *lev;
-#define goodtype(rno) \
- (!typewanted \
- || ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) \
- || ((typewanted == SHOPBASE) && (typefound > SHOPBASE)))
+#define goodtype(rno) \
+ (!typewanted \
+ || (typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted \
+ || (typewanted == SHOPBASE && typefound > SHOPBASE))
switch (rno = levl[x][y].roomno) {
case NO_ROOM:
for (x = min_x; x <= max_x; x += step) {
lev = &levl[x][min_y];
y = 0;
- if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
+ if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
&& goodtype(rno))
*(--ptr) = rno;
y += step;
if (y > max_y_offset)
continue;
- if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
+ if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
&& goodtype(rno))
*(--ptr) = rno;
y += step;
if (y > max_y_offset)
continue;
- if (((rno = lev[y].roomno) >= ROOMOFFSET) && !index(ptr, rno)
+ if ((rno = lev[y].roomno) >= ROOMOFFSET && !index(ptr, rno)
&& goodtype(rno))
*(--ptr) = rno;
}
Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
for (ptr1 = &u.urooms[0], ptr2 = &u.uentered[0], ptr3 = &u.ushops[0],
- ptr4 = &u.ushops_entered[0];
+ ptr4 = &u.ushops_entered[0];
*ptr1; ptr1++) {
if (!index(u.urooms0, *ptr1))
*(ptr2++) = *ptr1;
*ptr2 = '\0';
}
+/* possibly deliver a one-time room entry message */
void
check_special_room(newlev)
register boolean newlev;
pline("\83f\83r\83b\83g\95ó\94 \93®\95¨\89\80\82É\82æ\82¤\82±\82»\81I");
break;
case SWAMP:
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("It %s rather %s down here.", Blind ? "feels" : "looks",
Blind ? "humid" : "muddy");
#else
break;
case MORGUE:
if (midnight()) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
const char *run = locomotion(youmonst.data, "Run");
pline("%s away! %s away!", run, run);
#else
*/
verbalize("\82¨\82Ü\82¦\82Í\83f\83\8b\83t\83@\83C\82Ì\90_\91õ\8f\8a\82É\82¢\82é\81D");
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
verbalize("%s, %s, welcome to Delphi!",
Hello((struct monst *) 0), plname);
#else
return;
}
+/* returns
+ 1 = cannot pickup, time taken
+ 0 = cannot pickup, no time taken
+ -1 = do normal pickup
+ -2 = loot the monster */
int
-dopickup()
+pickup_checks()
{
- int count;
- struct trap *traphere = t_at(u.ux, u.uy);
- /* awful kludge to work around parse()'s pre-decrement */
- count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
- multi = 0; /* always reset */
/* uswallow case added by GAN 01/29/87 */
if (u.uswallow) {
if (!u.ustuck->minvent) {
*/
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");
} else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("don't %s anything in here to pick up.",
Blind ? "feel" : "see");
#else
#endif
return 1;
} else {
- int tmpcount = -count;
- return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
+ return -2; /* loot the monster inventory */
}
}
if (is_pool(u.ux, u.uy)) {
if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
|| (Flying && !Breathless)) {
-/*JP
- You("cannot dive into the water to pick things up.");
-*/
- You("\95¨\82ð\8fE\82¢\82 \82°\82é\82½\82ß\82É\90\85\82É\94ò\82Ñ\82±\82ß\82È\82¢\81D");
+#if 0 /*JP:T*/
+ You("cannot dive into the %s to pick things up.",
+ hliquid("water"));
+#else
+ You("\95¨\82ð\8fE\82¢\82 \82°\82é\82½\82ß\82É%s\82É\94ò\82Ñ\82±\82ß\82È\82¢\81D",
+ hliquid("\90\85"));
+#endif
return 0;
} else if (!Underwater) {
/*JP
}
if (!OBJ_AT(u.ux, u.uy)) {
register struct rm *lev = &levl[u.ux][u.uy];
+
if (IS_THRONE(lev->typ))
/*JP
pline("It must weigh%s a ton!", lev->looted ? " almost" : "");
pline("\82 \82È\82½\82É\82Í\95æ\90Î\82Í\95s\97v\82¾\81D\81D\81D\8d¡\82Ì\82Æ\82±\82ë\81D");
else if (IS_FOUNTAIN(lev->typ))
/*JP
- You("could drink the water...");
+ You("could drink the %s...", hliquid("water"));
*/
- You("\90\85\82ð\88ù\82ß\82È\82¢\81D\81D\81D");
+ You("%s\82ð\88ù\82ß\82È\82¢\81D\81D\81D", hliquid("\90\85"));
else if (IS_DOOR(lev->typ) && (lev->doormask & D_ISOPEN))
/*JP
pline("It won't come off the hinges.");
*/
pline("\83q\83\93\83W\82ð\8aO\82¹\82È\82¢\81D");
+ else if (IS_ALTAR(lev->typ))
+/*JP
+ pline("Moving the altar would be a very bad idea.");
+*/
+ pline("\8dÕ\92d\82ð\93®\82©\82·\82Ì\82Í\82Æ\82Ä\82à\88«\82¢\8dl\82¦\82¾\81D");
+ else if (lev->typ == STAIRS)
+#if 0 /*JP:T*/
+ pline_The("stairs are solidly fixed to the %s.",
+ surface(u.ux, u.uy));
+#else
+ pline_The("\8aK\92i\82Í%s\82É\82µ\82Á\82©\82è\82Æ\8cÅ\92è\82³\82ê\82Ä\82¢\82é\81D",
+ surface(u.ux, u.uy));
+#endif
else
/*JP
There("is nothing here to pick up.");
return 0;
}
if (!can_reach_floor(TRUE)) {
- if (traphere && uteetering_at_seen_pit(traphere))
-/*JP
- You("cannot reach the bottom of the pit.");
-*/
- You("\97\8e\82µ\8c\8a\82Ì\92ê\82É%s\82ª\93Í\82©\82È\82©\82Á\82½\81D", body_part(HAND));
+ struct trap *traphere = t_at(u.ux, u.uy);
+ if (traphere
+ && (uteetering_at_seen_pit(traphere) || uescaped_shaft(traphere)))
+#if 0 /*JP*/
+ You("cannot reach the bottom of the %s.",
+ is_pit(traphere->ttyp) ? "pit" : "abyss");
+#else
+ You("%s\82Ì\92ê\82É\93Í\82©\82È\82©\82Á\82½\81D",
+ is_pit(traphere->ttyp) ? "\97\8e\82µ\8c\8a" : "\93Þ\97\8e");
+#endif
else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
rider_cant_reach();
else if (Blind && !can_reach_floor(TRUE))
You("%s\82É\82½\82Ç\82è\82Â\82\82±\82Æ\82ª\82Å\82«\82È\82¢\81D", surface(u.ux, u.uy));
return 0;
}
+ return -1; /* can do normal pickup */
+}
+
+/* the ',' command */
+int
+dopickup(VOID_ARGS)
+{
+ int count, tmpcount, ret;
+
+ /* awful kludge to work around parse()'s pre-decrement */
+ count = (multi || (save_cm && *save_cm == cmd_from_func(dopickup)))
+ ? multi + 1 : 0;
+ multi = 0; /* always reset */
+
+ if ((ret = pickup_checks()) >= 0) {
+ return ret;
+ } else if (ret == -2) {
+ tmpcount = -count;
+ return loot_mon(u.ustuck, &tmpcount, (boolean *) 0);
+ } /* else ret == -1 */
return pickup(-count);
}
void
lookaround()
{
- register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
- register int corrct = 0, noturn = 0;
- register struct monst *mtmp;
- register struct trap *trap;
+ register int x, y;
+ int i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
+ int corrct = 0, noturn = 0;
+ struct monst *mtmp;
+ struct trap *trap;
/* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
/* they polymorphed while in the middle of a long move. */
- if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
+ if (NODIAG(u.umonnum) && u.dx && u.dy) {
+/*JP
+ You("cannot move diagonally.");
+*/
+ You("\8eÎ\82ß\82É\88Ú\93®\82Å\82«\82È\82¢\81D");
nomul(0);
return;
}
return;
for (x = u.ux - 1; x <= u.ux + 1; x++)
for (y = u.uy - 1; y <= u.uy + 1; y++) {
- if (!isok(x, y))
+ if (!isok(x, y) || (x == u.ux && y == u.uy))
continue;
-
- if (u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy)
+ if (NODIAG(u.umonnum) && x != u.ux && y != u.uy)
continue;
- if (x == u.ux && y == u.uy)
- continue;
-
- if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
- && mtmp->m_ap_type != M_AP_OBJECT
+ if ((mtmp = m_at(x, y)) != 0
+ && M_AP_TYPE(mtmp) != M_AP_FURNITURE
+ && M_AP_TYPE(mtmp) != M_AP_OBJECT
&& (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
if ((context.run != 1 && !mtmp->mtame)
- || (x == u.ux + u.dx && y == u.uy + u.dy))
+ || (x == u.ux + u.dx && y == u.uy + u.dy
+ && !context.travel)) {
+ if (iflags.mention_walls)
+/*JP
+ pline("%s blocks your path.", upstart(a_monnam(mtmp)));
+*/
+ pline("%s\82ª\93¹\82ð\82Ó\82³\82¢\82Å\82¢\82é\81D", a_monnam(mtmp));
goto stop;
+ }
}
if (levl[x][y].typ == STONE)
if (x == u.ux - u.dx && y == u.uy - u.dy)
continue;
- if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM)
- || IS_AIR(levl[x][y].typ))
+ if (IS_ROCK(levl[x][y].typ) || levl[x][y].typ == ROOM
+ || IS_AIR(levl[x][y].typ)) {
continue;
- else if (closed_door(x, y)
- || (mtmp && is_door_mappear(mtmp))) {
+ } else if (closed_door(x, y) || (mtmp && is_door_mappear(mtmp))) {
if (x != u.ux && y != u.uy)
continue;
- if (context.run != 1)
+ if (context.run != 1) {
+ if (iflags.mention_walls)
+/*JP
+ You("stop in front of the door.");
+*/
+ You("\94à\82Ì\8eè\91O\82Å\8e~\82Ü\82Á\82½\81D");
goto stop;
+ }
goto bcorr;
} else if (levl[x][y].typ == CORR) {
- bcorr:
+ bcorr:
if (levl[u.ux][u.uy].typ != ROOM) {
if (context.run == 1 || context.run == 3
|| context.run == 8) {
} else if ((trap = t_at(x, y)) && trap->tseen) {
if (context.run == 1)
goto bcorr; /* if you must */
- if (x == u.ux + u.dx && y == u.uy + u.dy)
+ if (x == u.ux + u.dx && y == u.uy + u.dy) {
+ if (iflags.mention_walls) {
+ int tt = what_trap(trap->ttyp, rn2_on_display_rng);
+
+/*JP
+ You("stop in front of %s.",
+*/
+ You("%s\82Ì\8eè\91O\82Å\8e~\82Ü\82Á\82½\81D",
+ an(defsyms[trap_to_defsym(tt)].explanation));
+ }
goto stop;
+ }
continue;
} else if (is_pool_or_lava(x, y)) {
/* water and lava only stop you if directly in front, and stop
* you even if you are running
*/
if (!Levitation && !Flying && !is_clinger(youmonst.data)
- && x == u.ux + u.dx && y == u.uy + u.dy)
+ && x == u.ux + u.dx && y == u.uy + u.dy) {
/* No Wwalking check; otherwise they'd be able
* to test boots by trying to SHIFT-direction
* into a pool and seeing if the game allowed it
*/
+ if (iflags.mention_walls)
+#if 0 /*JP:T*/
+ You("stop at the edge of the %s.",
+ hliquid(is_pool(x,y) ? "water" : "lava"));
+#else
+ You("%s\82Ì\92[\82Å\8e~\82Ü\82Á\82½\81D",
+ hliquid(is_pool(x,y) ? "\90\85" : "\97n\8aâ"));
+#endif
goto stop;
+ }
continue;
} else { /* e.g. objects or trap or stairs */
if (context.run == 1)
|| ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
continue;
}
- stop:
+ stop:
nomul(0);
return;
} /* end for loops */
- if (corrct > 1 && context.run == 2)
+ if (corrct > 1 && context.run == 2) {
+ if (iflags.mention_walls)
+/*JP
+ pline_The("corridor widens here.");
+*/
+ pline("\92Ê\98H\82Í\82±\82±\82Å\8dL\82\82È\82Á\82Ä\82¢\82é\81D");
goto stop;
+ }
if ((context.run == 1 || context.run == 3 || context.run == 8) && !noturn
&& !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) {
/* make sure that we do not turn too far */
if (!IS_DOOR(lev_p->typ))
return FALSE;
/* all rogue level doors are doorless but disallow diagonal access, so
- we treat them as if their non-existant doors were actually present */
+ we treat them as if their non-existent doors were actually present */
if (Is_rogue_level(&u.uz))
return FALSE;
return !(lev_p->doormask & ~(D_NODOOR | D_BROKEN));
/* Also see the similar check in dochugw() in monmove.c */
for (x = u.ux - 1; x <= u.ux + 1; x++)
for (y = u.uy - 1; y <= u.uy + 1; y++) {
- if (!isok(x, y))
- continue;
- if (x == u.ux && y == u.uy)
+ if (!isok(x, y) || (x == u.ux && y == u.uy))
continue;
- if ((mtmp = m_at(x, y)) && mtmp->m_ap_type != M_AP_FURNITURE
- && mtmp->m_ap_type != M_AP_OBJECT
+ if ((mtmp = m_at(x, y)) && M_AP_TYPE(mtmp) != M_AP_FURNITURE
+ && M_AP_TYPE(mtmp) != M_AP_OBJECT
&& (!mtmp->mpeaceful || Hallucination)
&& (!is_hider(mtmp->data) || !mtmp->mundetected)
&& !noattacks(mtmp->data) && mtmp->mcanmove
nomovemsg = msg_override;
else if (!nomovemsg)
nomovemsg = You_can_move_again;
- if (*nomovemsg)
- pline1(nomovemsg);
+ if (*nomovemsg) {
+ pline("%s", nomovemsg);
+ /* follow "you survived that attempt on your life" with a message
+ about current form if it's not the default; primarily for
+ life-saving while turning into green slime but is also a reminder
+ if life-saved while poly'd and Unchanging (explore or wizard mode
+ declining to die since can't be both Unchanging and Lifesaved) */
+#if 0 /*JP:T*/
+ if (Upolyd && !strncmpi(nomovemsg, "You survived that ", 18))
+ You("are %s.", an(mons[u.umonnum].mname)); /* (ignore Hallu) */
+#else
+ if (Upolyd && !STRNCMP2(nomovemsg, "\82 \82È\82½\82Í\90¶\82«\82È\82ª\82ç"))
+ You("%s\82¾\81D", mons[u.umonnum].mname); /* (ignore Hallu) */
+#endif
+ }
nomovemsg = 0;
u.usleep = 0;
multi_reason = NULL;
- if (afternmv)
- (*afternmv)();
- afternmv = 0;
+ if (afternmv) {
+ int NDECL((*f)) = afternmv;
+
+ /* clear afternmv before calling it (to override the
+ encumbrance hack for levitation--see weight_cap()) */
+ afternmv = (int NDECL((*))) 0;
+ (void) (*f)();
+ /* for finishing Armor/Boots/&c_on() */
+ update_inventory();
+ }
}
STATIC_OVL void
const char *who;
int i, powercnt;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? urole.name.m
: "Elf";
#else
++powercnt;
/*JP
- pline(powercnt >= 4 ? "%s, all your powers will be lost..."
+ pline((powercnt >= 4) ? "%s, all your powers will be lost..."
*/
- pline(powercnt >= 4 ? "%s\81C\82 \82È\82½\82Ì\91S\82Ä\82Ì\97Í\82Í\8e¸\82í\82ê\82Â\82Â\82 \82é\81D\81D\81D"
+ pline((powercnt >= 4) ? "%s\81C\82 \82È\82½\82Ì\91S\82Ä\82Ì\97Í\82Í\8e¸\82í\82ê\82Â\82Â\82 \82é\81D\81D\81D"
/*JP
- : "%s, your life force is running out.",
+ : "%s, your life force is running out.",
*/
- : "%s\81C\82 \82È\82½\82Ì\90¶\96½\97Í\82Í\90s\82«\82æ\82¤\82Æ\82µ\82Ä\82¢\82é\81D\81D\81D",
+ : "%s\81C\82 \82È\82½\82Ì\90¶\96½\97Í\82Í\90s\82«\82æ\82¤\82Æ\82µ\82Ä\82¢\82é\81D\81D\81D",
who);
}
} else {
u.uhp -= n;
if (u.uhp > u.uhpmax)
u.uhpmax = u.uhp; /* perhaps n was negative */
+ else
+ context.travel = context.travel1 = context.mv = context.run = 0;
context.botl = 1;
if (u.uhp < 1) {
killer.format = k_format;
int
weight_cap()
{
- register long carrcap;
+ long carrcap, save_ELev = ELevitation, save_BLev = BLevitation;
+
+ /* boots take multiple turns to wear but any properties they
+ confer are enabled at the start rather than the end; that
+ causes message sequencing issues for boots of levitation
+ so defer their encumbrance benefit until they're fully worn */
+ if (afternmv == Boots_on && (ELevitation & W_ARMF) != 0L) {
+ ELevitation &= ~W_ARMF;
+ float_vs_flight(); /* in case Levitation is blocking Flying */
+ }
+ /* levitation is blocked by being trapped in the floor, but it still
+ functions enough in that situation to enhance carrying capacity */
+ BLevitation &= ~I_SPECIAL;
carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
if (Upolyd) {
}
if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
- || (u.usteed && strongmonst(u.usteed->data)))
+ || (u.usteed && strongmonst(u.usteed->data))) {
carrcap = MAX_CARR_CAP;
- else {
+ } else {
if (carrcap > MAX_CARR_CAP)
carrcap = MAX_CARR_CAP;
if (!Flying) {
if (carrcap < 0)
carrcap = 0;
}
+
+ if (ELevitation != save_ELev || BLevitation != save_BLev) {
+ ELevitation = save_ELev;
+ BLevitation = save_BLev;
+ float_vs_flight();
+ }
+
return (int) carrcap;
}
}
/* Counts the money in an object chain. */
-/* Intended use is for your or some monsters inventory, */
+/* Intended use is for your or some monster's inventory, */
/* now that u.gold/m.gold is gone.*/
/* Counting money in a container might be possible too. */
long