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:
nethack.rankin
2009-04-07 08:21:32 +00:00
parent e205569714
commit 810c538dd0
4 changed files with 57 additions and 68 deletions

View File

@@ -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

View File

@@ -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));

View File

@@ -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");

View File

@@ -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