travelling through boulders
If the hero can move to a boulder's location via m<dir>, allow travel to do so too. You will always stop on the boulder spot rather than keep going toward the destination because of change in visibility at a boulder spot. Giants should be able to see over boulders, and doing that for poly'd hero would probably be straightforward, but when not poly'd, seeing a giant beyond a boulder and vice versa seems like it would be a can of giant-sized worms. A couple of other miscellaneous changes are mixed in with this.
This commit is contained in:
+63
-38
@@ -7,18 +7,19 @@
|
|||||||
|
|
||||||
/* #define DEBUG */ /* uncomment for debugging */
|
/* #define DEBUG */ /* uncomment for debugging */
|
||||||
|
|
||||||
static void maybe_wail(void);
|
static boolean could_move_onto_boulder(int, int);
|
||||||
static int moverock(void);
|
static int moverock(void);
|
||||||
static void dosinkfall(void);
|
static void dosinkfall(void);
|
||||||
static boolean findtravelpath(int);
|
static boolean findtravelpath(int);
|
||||||
static boolean trapmove(int, int, struct trap *);
|
static boolean trapmove(int, int, struct trap *);
|
||||||
static struct monst *monstinroom(struct permonst *, int);
|
|
||||||
static boolean doorless_door(int, int);
|
|
||||||
static void move_update(boolean);
|
|
||||||
static int pickup_checks(void);
|
|
||||||
static void maybe_smudge_engr(int, int, int, int);
|
|
||||||
static void check_buried_zombies(xchar, xchar);
|
static void check_buried_zombies(xchar, xchar);
|
||||||
static void domove_core(void);
|
static void domove_core(void);
|
||||||
|
static void maybe_smudge_engr(int, int, int, int);
|
||||||
|
static struct monst *monstinroom(struct permonst *, int);
|
||||||
|
static void move_update(boolean);
|
||||||
|
static int pickup_checks(void);
|
||||||
|
static boolean doorless_door(int, int);
|
||||||
|
static void maybe_wail(void);
|
||||||
|
|
||||||
#define IS_SHOP(x) (g.rooms[x].rtype >= SHOPBASE)
|
#define IS_SHOP(x) (g.rooms[x].rtype >= SHOPBASE)
|
||||||
|
|
||||||
@@ -96,6 +97,29 @@ revive_nasty(int x, int y, const char *msg)
|
|||||||
|
|
||||||
#define squeezeablylightinvent() (!g.invent || inv_weight() <= -850)
|
#define squeezeablylightinvent() (!g.invent || inv_weight() <= -850)
|
||||||
|
|
||||||
|
/* can hero move onto a spot containing one or more boulders?
|
||||||
|
used for m<dir> and travel and during boulder push failure */
|
||||||
|
static boolean
|
||||||
|
could_move_onto_boulder(int sx, int sy)
|
||||||
|
{
|
||||||
|
/* can if able to phaze through rock (must be poly'd, so not riding) */
|
||||||
|
if (Passes_walls)
|
||||||
|
return TRUE;
|
||||||
|
/* can't when riding */
|
||||||
|
if (u.usteed)
|
||||||
|
return FALSE;
|
||||||
|
/* can if a giant, unless doing so allows hero to pass into a
|
||||||
|
diagonal squeeze at the same time */
|
||||||
|
if (throws_rocks(g.youmonst.data))
|
||||||
|
return (!u.dx || !u.dy || !(IS_ROCK(levl[u.ux][sy].typ)
|
||||||
|
&& IS_ROCK(levl[sx][u.uy].typ)));
|
||||||
|
/* can if tiny (implies carrying very little else couldn't move at all) */
|
||||||
|
if (verysmall(g.youmonst.data))
|
||||||
|
return TRUE;
|
||||||
|
/* can squeeze to spot if carrying extremely little, otherwise can't */
|
||||||
|
return squeezeablylightinvent();
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
moverock(void)
|
moverock(void)
|
||||||
{
|
{
|
||||||
@@ -144,9 +168,9 @@ moverock(void)
|
|||||||
/* ["over" seems weird on air level but what else to say?] */
|
/* ["over" seems weird on air level but what else to say?] */
|
||||||
sokoban_guilt();
|
sokoban_guilt();
|
||||||
res = 0; /* move to <sx,sy> */
|
res = 0; /* move to <sx,sy> */
|
||||||
} else if (!u.usteed && (squeezeablylightinvent()
|
} else if (could_move_onto_boulder(sx, sy)) {
|
||||||
|| verysmall(g.youmonst.data))) {
|
You("squeeze yourself %s the boulder.",
|
||||||
You("squeeze yourself against the boulder.");
|
Flying ? "over" : "against");
|
||||||
sokoban_guilt();
|
sokoban_guilt();
|
||||||
res = 0; /* move to <sx,sy> */
|
res = 0; /* move to <sx,sy> */
|
||||||
} else {
|
} else {
|
||||||
@@ -200,8 +224,7 @@ moverock(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mtmp && !noncorporeal(mtmp->data)
|
if (mtmp && !noncorporeal(mtmp->data)
|
||||||
&& (!mtmp->mtrapped
|
&& (!mtmp->mtrapped || !(ttmp && is_pit(ttmp->ttyp)))) {
|
||||||
|| !(ttmp && is_pit(ttmp->ttyp)))) {
|
|
||||||
boolean deliver_part1 = FALSE;
|
boolean deliver_part1 = FALSE;
|
||||||
|
|
||||||
if (Blind)
|
if (Blind)
|
||||||
@@ -221,15 +244,10 @@ moverock(void)
|
|||||||
Strcpy(you_or_steed,
|
Strcpy(you_or_steed,
|
||||||
u.usteed ? y_monnam(u.usteed) : "you");
|
u.usteed ? y_monnam(u.usteed) : "you");
|
||||||
pline("%s%s cannot move %s.",
|
pline("%s%s cannot move %s.",
|
||||||
deliver_part1
|
deliver_part1 ? "Perhaps that's why " : "",
|
||||||
? "Perhaps that's why "
|
deliver_part1 ? you_or_steed
|
||||||
: "",
|
: upstart(you_or_steed),
|
||||||
deliver_part1
|
deliver_part1 ? "it" : the(xname(otmp)));
|
||||||
? you_or_steed
|
|
||||||
: upstart(you_or_steed),
|
|
||||||
deliver_part1
|
|
||||||
? "it"
|
|
||||||
: the(xname(otmp)));
|
|
||||||
}
|
}
|
||||||
goto cannot_push;
|
goto cannot_push;
|
||||||
}
|
}
|
||||||
@@ -248,7 +266,16 @@ moverock(void)
|
|||||||
obj_extract_self(otmp);
|
obj_extract_self(otmp);
|
||||||
place_object(otmp, rx, ry);
|
place_object(otmp, rx, ry);
|
||||||
newsym(sx, sy);
|
newsym(sx, sy);
|
||||||
pline("KAABLAMM!!! %s %s land mine.",
|
pline("%s! %s %s land mine.",
|
||||||
|
/* "kablam" is a variation of "ka-boom" or
|
||||||
|
"kablooey", rather cartoonish descriptions
|
||||||
|
of the sound of an explosion, but give it
|
||||||
|
even when deaf if hero sees the explosion */
|
||||||
|
(!Deaf || !Blind) ? "KAABLAMM!!"
|
||||||
|
/* use an alternate exclamation when feeling
|
||||||
|
the floor/ground/whatever shake (or maybe
|
||||||
|
a weak shockwave if levitating or flying) */
|
||||||
|
: "Gadzooks",
|
||||||
Tobjnam(otmp, "trigger"),
|
Tobjnam(otmp, "trigger"),
|
||||||
ttmp->madeby_u ? "your" : "a");
|
ttmp->madeby_u ? "your" : "a");
|
||||||
blow_up_landmine(ttmp);
|
blow_up_landmine(ttmp);
|
||||||
@@ -431,13 +458,7 @@ moverock(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* similar to m<dir> above, but that doesn't care if you're
|
if (could_move_onto_boulder(sx, sy)) {
|
||||||
moving orthogonally or toward a diagonal squeeze */
|
|
||||||
if (!u.usteed && ((squeezeablylightinvent()
|
|
||||||
&& (!u.dx || !u.dy
|
|
||||||
|| (IS_ROCK(levl[u.ux][sy].typ)
|
|
||||||
&& IS_ROCK(levl[sx][u.uy].typ))))
|
|
||||||
|| verysmall(g.youmonst.data))) {
|
|
||||||
pline(
|
pline(
|
||||||
"However, you can squeeze yourself into a small opening.");
|
"However, you can squeeze yourself into a small opening.");
|
||||||
sokoban_guilt();
|
sokoban_guilt();
|
||||||
@@ -636,7 +657,7 @@ still_chewing(xchar x, xchar y)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
movobj(register struct obj *obj, register xchar ox, register xchar oy)
|
movobj(struct obj *obj, xchar ox, xchar oy)
|
||||||
{
|
{
|
||||||
/* optimize by leaving on the fobj chain? */
|
/* optimize by leaving on the fobj chain? */
|
||||||
remove_object(obj);
|
remove_object(obj);
|
||||||
@@ -646,12 +667,11 @@ movobj(register struct obj *obj, register xchar ox, register xchar oy)
|
|||||||
newsym(ox, oy);
|
newsym(ox, oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NEARDATA const char fell_on_sink[] = "fell onto a sink";
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dosinkfall(void)
|
dosinkfall(void)
|
||||||
{
|
{
|
||||||
register struct obj *obj;
|
static const char fell_on_sink[] = "fell onto a sink";
|
||||||
|
struct obj *obj;
|
||||||
int dmg;
|
int dmg;
|
||||||
boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
|
boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
|
||||||
innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L),
|
innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L),
|
||||||
@@ -806,7 +826,7 @@ test_move(int ux, int uy, int dx, int dy, int mode)
|
|||||||
int x = ux + dx;
|
int x = ux + dx;
|
||||||
int y = uy + dy;
|
int y = uy + dy;
|
||||||
register struct rm *tmpr = &levl[x][y];
|
register struct rm *tmpr = &levl[x][y];
|
||||||
register struct rm *ust;
|
struct rm *ust;
|
||||||
|
|
||||||
g.context.door_opened = FALSE;
|
g.context.door_opened = FALSE;
|
||||||
/*
|
/*
|
||||||
@@ -985,8 +1005,8 @@ test_move(int ux, int uy, int dx, int dy, int mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
|
if (sobj_at(BOULDER, x, y) && (Sokoban || !Passes_walls)) {
|
||||||
if (!(Blind || Hallucination) && (g.context.run >= 2)
|
if (mode != TEST_TRAV && g.context.run >= 2
|
||||||
&& mode != TEST_TRAV) {
|
&& !(Blind || Hallucination) && !could_move_onto_boulder(x, y)) {
|
||||||
if (mode == DO_MOVE && flags.mention_walls)
|
if (mode == DO_MOVE && flags.mention_walls)
|
||||||
pline("A boulder blocks your path.");
|
pline("A boulder blocks your path.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -1009,6 +1029,7 @@ test_move(int ux, int uy, int dx, int dy, int mode)
|
|||||||
/* don't pick two boulders in a row, unless there's a way thru */
|
/* don't pick two boulders in a row, unless there's a way thru */
|
||||||
if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
|
if (sobj_at(BOULDER, ux, uy) && !Sokoban) {
|
||||||
if (!Passes_walls
|
if (!Passes_walls
|
||||||
|
&& !could_move_onto_boulder(ux, uy)
|
||||||
&& !(tunnels(g.youmonst.data)
|
&& !(tunnels(g.youmonst.data)
|
||||||
&& !needspick(g.youmonst.data))
|
&& !needspick(g.youmonst.data))
|
||||||
&& !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK)
|
&& !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK)
|
||||||
@@ -1139,10 +1160,14 @@ findtravelpath(int mode)
|
|||||||
|| ((mode == TRAVP_GUESS) && !couldsee(nx, ny)))
|
|| ((mode == TRAVP_GUESS) && !couldsee(nx, ny)))
|
||||||
continue;
|
continue;
|
||||||
if ((!Passes_walls && !can_ooze(&g.youmonst)
|
if ((!Passes_walls && !can_ooze(&g.youmonst)
|
||||||
&& closed_door(x, y)) || sobj_at(BOULDER, x, y)
|
&& closed_door(x, y))
|
||||||
|
|| (sobj_at(BOULDER, x, y)
|
||||||
|
&& !could_move_onto_boulder(x, y))
|
||||||
|| test_move(x, y, nx - x, ny - y, TEST_TRAP)) {
|
|| test_move(x, y, nx - x, ny - y, TEST_TRAP)) {
|
||||||
/* closed doors and boulders usually
|
/* closed doors and boulders usually cause a delay,
|
||||||
* cause a delay, so prefer another path */
|
so prefer another path; however, giants and tiny
|
||||||
|
creatures can use m<dir> to move onto a boulder's
|
||||||
|
spot without pushing, so allow boulders for them */
|
||||||
if (travel[x][y] > radius - 3) {
|
if (travel[x][y] > radius - 3) {
|
||||||
if (!alreadyrepeated) {
|
if (!alreadyrepeated) {
|
||||||
travelstepx[1 - set][nn] = x;
|
travelstepx[1 - set][nn] = x;
|
||||||
|
|||||||
Reference in New Issue
Block a user