From 810c538dd0bba69800dfb69eb8feb862ca04f01a Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Tue, 7 Apr 2009 08:21:32 +0000 Subject: [PATCH] climbing back to the Castle (trunk only) From the newsgroup: someone using '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. --- doc/fixes35.0 | 1 + include/extern.h | 3 +- src/do.c | 49 ++++++++------------------------ src/dungeon.c | 72 +++++++++++++++++++++++++++++------------------- 4 files changed, 57 insertions(+), 68 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index a15bebcdd..b613b902f 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index 089d1efae..f92e455b7 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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)); diff --git a/src/do.c b/src/do.c index 56b990be6..3132030cd 100644 --- a/src/do.c +++ b/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"); diff --git a/src/dungeon.c b/src/dungeon.c index 798a59ed1..c02e762f3 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -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 -- 2.40.0