climbing back to the Castle (trunk only)
From the newsgroup: someone using <Someone>'s level-flip patch
(to transpose special levels left-to-right or top-to-bottom or both in
order to get more variety from them) ended up in solid rock. When
climbing the stairs up from the Valley to the Castle, goto_level() was
hardcoded to find a spot in the extreme lower right corner. If the level
is turned upside down, solid rock from an unused row at the top edge of
the map ends up at the bottom, and the placement code could put the hero
there. That code only checked for walls and monsters being in the way,
not rock. Also, if the level is flipped side-to-side than hero ends up
in same area as the upstairs rather than on opposite side of the Castle.
This switches to the same teleport-region code used for other level
changes which don't arrive on stairs; such regions get flipped along with
map by that patch (I hope). Even though no such fix is currently needed
for unmodified nethack, this change gets rid of the special case Castle
placement code entirely, simplifying both goto_level() and u_on_sstairs()
in the process.
The Castle's existing from-below region covers the rightmost half-
dozen or so columns across all rows, so offers a bigger landing zone than
just the bottom corner. That could be tweaked within castle.des but I
don't think it needs to be.
This commit is contained in:
@@ -319,6 +319,7 @@ prevent temple priests and minions from wearing helms of opposite alignment
|
||||
were inside containers
|
||||
pearl rings shouldn't rust
|
||||
shouldn't be able to read a worn T-shirt when it's covered by a worn suit
|
||||
simplify hero placement on Castle level when climbing up stairs from Valley
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific Fixes
|
||||
|
||||
@@ -547,7 +547,8 @@ E boolean FDECL(on_level, (d_level *,d_level *));
|
||||
E void FDECL(next_level, (BOOLEAN_P));
|
||||
E void FDECL(prev_level, (BOOLEAN_P));
|
||||
E void FDECL(u_on_newpos, (int,int));
|
||||
E void NDECL(u_on_sstairs);
|
||||
E void FDECL(u_on_rndspot, (int));
|
||||
E void FDECL(u_on_sstairs, (int));
|
||||
E void NDECL(u_on_upstairs);
|
||||
E void NDECL(u_on_dnstairs);
|
||||
E boolean FDECL(On_stairs, (XCHAR_P,XCHAR_P));
|
||||
|
||||
49
src/do.c
49
src/do.c
@@ -1162,22 +1162,12 @@ boolean at_stairs, falling, portal;
|
||||
u_on_newpos(ttrap->tx, ttrap->ty);
|
||||
} else if (at_stairs && !In_endgame(&u.uz)) {
|
||||
if (up) {
|
||||
if (at_ladder) {
|
||||
if (at_ladder)
|
||||
u_on_newpos(xdnladder, ydnladder);
|
||||
} else {
|
||||
if (newdungeon) {
|
||||
if (Is_stronghold(&u.uz)) {
|
||||
register xchar x, y;
|
||||
|
||||
do {
|
||||
x = (COLNO - 2 - rnd(5));
|
||||
y = rn1(ROWNO - 4, 3);
|
||||
} while(occupied(x, y) ||
|
||||
IS_WALL(levl[x][y].typ));
|
||||
u_on_newpos(x, y);
|
||||
} else u_on_sstairs();
|
||||
} else u_on_dnstairs();
|
||||
}
|
||||
else if (newdungeon)
|
||||
u_on_sstairs(1);
|
||||
else
|
||||
u_on_dnstairs();
|
||||
/* you climb up the {stairs|ladder};
|
||||
fly up the stairs; fly up along the ladder */
|
||||
pline("%s %s up%s the %s.",
|
||||
@@ -1187,12 +1177,12 @@ boolean at_stairs, falling, portal;
|
||||
(Flying && at_ladder) ? " along" : "",
|
||||
at_ladder ? "ladder" : "stairs");
|
||||
} else { /* down */
|
||||
if (at_ladder) {
|
||||
if (at_ladder)
|
||||
u_on_newpos(xupladder, yupladder);
|
||||
} else {
|
||||
if (newdungeon) u_on_sstairs();
|
||||
else u_on_upstairs();
|
||||
}
|
||||
else if (newdungeon)
|
||||
u_on_sstairs(0);
|
||||
else
|
||||
u_on_upstairs();
|
||||
if (!u.dz) {
|
||||
; /* stayed on same level? (no transit effects) */
|
||||
} else if (Flying) {
|
||||
@@ -1232,24 +1222,7 @@ boolean at_stairs, falling, portal;
|
||||
}
|
||||
}
|
||||
} else { /* trap door or level_tele or In_endgame */
|
||||
if (was_in_W_tower && On_W_tower_level(&u.uz))
|
||||
/* Stay inside the Wizard's tower when feasible. */
|
||||
/* Note: up vs down doesn't really matter in this case. */
|
||||
place_lregion(dndest.nlx, dndest.nly,
|
||||
dndest.nhx, dndest.nhy,
|
||||
0,0, 0,0, LR_DOWNTELE, (d_level *) 0);
|
||||
else if (up)
|
||||
place_lregion(updest.lx, updest.ly,
|
||||
updest.hx, updest.hy,
|
||||
updest.nlx, updest.nly,
|
||||
updest.nhx, updest.nhy,
|
||||
LR_UPTELE, (d_level *) 0);
|
||||
else
|
||||
place_lregion(dndest.lx, dndest.ly,
|
||||
dndest.hx, dndest.hy,
|
||||
dndest.nlx, dndest.nly,
|
||||
dndest.nhx, dndest.nhy,
|
||||
LR_DOWNTELE, (d_level *) 0);
|
||||
u_on_rndspot((up ? 1 : 0) | (was_in_W_tower ? 2 : 0));
|
||||
if (falling) {
|
||||
if (Punished) ballfall();
|
||||
selftouch("Falling, you");
|
||||
|
||||
@@ -1155,47 +1155,61 @@ int x, y;
|
||||
}
|
||||
|
||||
void
|
||||
u_on_sstairs() /* place you on the special staircase */
|
||||
u_on_rndspot(upflag) /* place you on a random location */
|
||||
int upflag;
|
||||
{
|
||||
if (sstairs.sx) {
|
||||
int up = (upflag & 1),
|
||||
was_in_W_tower = (upflag & 2);
|
||||
|
||||
/*
|
||||
* Place the hero at a random location within the relevant region.
|
||||
* place_lregion(xTELE) -> put_lregion_here(xTELE) -> u_on_newpos()
|
||||
* Unspecified region (.lx == 0) defaults to entire level.
|
||||
*/
|
||||
if (was_in_W_tower && On_W_tower_level(&u.uz))
|
||||
/* Stay inside the Wizard's tower when feasible.
|
||||
We use the W Tower's exclusion region for the
|
||||
destination instead of its enclosing region.
|
||||
Note: up vs down doesn't matter in this case
|
||||
because both specify the same exclusion area. */
|
||||
place_lregion(dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy,
|
||||
0, 0, 0, 0, LR_DOWNTELE, (d_level *) 0);
|
||||
else if (up)
|
||||
place_lregion(updest.lx, updest.ly, updest.hx, updest.hy,
|
||||
updest.nlx, updest.nly, updest.nhx, updest.nhy,
|
||||
LR_UPTELE, (d_level *)0);
|
||||
else
|
||||
place_lregion(dndest.lx, dndest.ly, dndest.hx, dndest.hy,
|
||||
dndest.nlx, dndest.nly, dndest.nhx, dndest.nhy,
|
||||
LR_DOWNTELE, (d_level *)0);
|
||||
}
|
||||
|
||||
void
|
||||
u_on_sstairs(upflag) /* place you on the special staircase */
|
||||
int upflag;
|
||||
{
|
||||
if (sstairs.sx)
|
||||
u_on_newpos(sstairs.sx, sstairs.sy);
|
||||
} else {
|
||||
/* code stolen from goto_level */
|
||||
int trycnt = 0;
|
||||
xchar x, y;
|
||||
#ifdef DEBUG
|
||||
pline("u_on_sstairs: picking random spot");
|
||||
#endif
|
||||
#define badspot(x,y) ((levl[x][y].typ != ROOM && levl[x][y].typ != CORR) || MON_AT(x, y))
|
||||
do {
|
||||
x = rnd(COLNO-1);
|
||||
y = rn2(ROWNO);
|
||||
if (!badspot(x, y)) {
|
||||
u_on_newpos(x, y);
|
||||
return;
|
||||
}
|
||||
} while (++trycnt <= 500);
|
||||
panic("u_on_sstairs: could not relocate player!");
|
||||
#undef badspot
|
||||
}
|
||||
else
|
||||
u_on_rndspot(upflag);
|
||||
}
|
||||
|
||||
void
|
||||
u_on_upstairs() /* place you on upstairs (or special equivalent) */
|
||||
{
|
||||
if (xupstair) {
|
||||
u_on_newpos(xupstair, yupstair);
|
||||
} else
|
||||
u_on_sstairs();
|
||||
if (xupstair)
|
||||
u_on_newpos(xupstair, yupstair);
|
||||
else
|
||||
u_on_sstairs(0); /* destination upstairs implies moving down */
|
||||
}
|
||||
|
||||
void
|
||||
u_on_dnstairs() /* place you on dnstairs (or special equivalent) */
|
||||
{
|
||||
if (xdnstair) {
|
||||
u_on_newpos(xdnstair, ydnstair);
|
||||
} else
|
||||
u_on_sstairs();
|
||||
if (xdnstair)
|
||||
u_on_newpos(xdnstair, ydnstair);
|
||||
else
|
||||
u_on_sstairs(1); /* destination dnstairs implies moving up */
|
||||
}
|
||||
|
||||
boolean
|
||||
|
||||
Reference in New Issue
Block a user