Holes and trapdoors have predetermined exit level

Same hole/trapdoor will always take you to the same level.
This commit is contained in:
Pasi Kallinen
2022-07-27 22:51:13 +03:00
parent 543a3c1b9a
commit 05761bada6
4 changed files with 49 additions and 17 deletions

View File

@@ -978,6 +978,7 @@ wielding Giantslayer prevents knockback from larger monsters
scared hostile monster which cannot move away will attack
prevent a fog cloud that has engulfed the hero from moving under closed doors
allow cutting a known spider web with wielded weapon by force-fighting the web
holes and trapdoors have a fixed exit level
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -18,7 +18,7 @@ union vlaunchinfo {
struct trap {
struct trap *ntrap;
coordxy tx, ty;
d_level dst; /* destination for portals */
d_level dst; /* destination for portals/holes/trapdoors */
coord launch;
Bitfield(ttyp, 5);
Bitfield(tseen, 1);

View File

@@ -1133,6 +1133,8 @@ dodown(void)
}
if (trap && Is_stronghold(&u.uz)) {
goto_hell(FALSE, TRUE);
} else if (trap) {
goto_level(&(trap->dst), FALSE, FALSE, FALSE);
} else {
g.at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
next_level(!trap);

View File

@@ -8,6 +8,8 @@
extern const char *const destroy_strings[][3]; /* from zap.c */
static void mk_trap_statue(coordxy, coordxy);
static int dng_bottom(void);
static void hole_destination(d_level *);
static boolean keep_saddle_with_steedcorpse(unsigned, struct obj *,
struct obj *);
static boolean mu_maybe_destroy_web(struct monst *, boolean, struct trap *);
@@ -373,6 +375,37 @@ mk_trap_statue(coordxy x, coordxy y)
mongone(mtmp);
}
/* find "bottom" level of current dungeon, stopping at quest locate */
static int
dng_bottom(void)
{
int bottom = dunlevs_in_dungeon(&u.uz);
/* when in the upper half of the quest, don't fall past the
middle "quest locate" level if hero hasn't been there yet */
if (In_quest(&u.uz)) {
int qlocate_depth = qlocate_level.dlevel;
/* deepest reached < qlocate implies current < qlocate */
if (dunlev_reached(&u.uz) < qlocate_depth)
bottom = qlocate_depth; /* early cut-off */
}
return bottom;
}
/* destination dlevel for holes or trapdoors */
static void
hole_destination(d_level *dst)
{
int bottom = dng_bottom();
dst->dnum = u.uz.dnum;
dst->dlevel = dunlev(&u.uz);
do {
dst->dlevel++;
} while (!rn2(4) && dst->dlevel < bottom);
}
struct trap *
maketrap(coordxy x, coordxy y, int typ)
{
@@ -435,6 +468,8 @@ maketrap(coordxy x, coordxy y, int typ)
/*FALLTHRU*/
case HOLE:
case TRAPDOOR:
if (is_hole(typ))
hole_destination(&(ttmp->dst));
if (*in_rooms(x, y, SHOPBASE)
&& (is_hole(typ) || IS_DOOR(lev->typ) || IS_WALL(lev->typ)))
add_damage(x, y, /* schedule repair */
@@ -481,7 +516,7 @@ fall_through(
d_level dtmp;
char msgbuf[BUFSZ];
const char *dont_fall = 0;
int newlevel, bottom;
int newlevel, bottom = dng_bottom();
struct trap *t = (struct trap *) 0;
/* we'll fall even while levitating in Sokoban; otherwise, if we
@@ -489,20 +524,8 @@ fall_through(
if (Blind && Levitation && !Sokoban)
return;
bottom = dunlevs_in_dungeon(&u.uz);
/* when in the upper half of the quest, don't fall past the
middle "quest locate" level if hero hasn't been there yet */
if (In_quest(&u.uz)) {
int qlocate_depth = qlocate_level.dlevel;
/* deepest reached < qlocate implies current < qlocate */
if (dunlev_reached(&u.uz) < qlocate_depth)
bottom = qlocate_depth; /* early cut-off */
}
newlevel = dunlev(&u.uz); /* current level */
do {
newlevel++;
} while (!rn2(4) && newlevel < bottom);
newlevel++;
if (td) {
t = t_at(u.ux, u.uy);
@@ -555,8 +578,14 @@ fall_through(
} else {
int dist = newlevel - dunlev(&u.uz);
dtmp.dnum = u.uz.dnum;
dtmp.dlevel = newlevel;
if (t) {
dtmp.dnum = t->dst.dnum;
dtmp.dlevel = t->dst.dlevel;
dist = dtmp.dlevel - dunlev(&u.uz);
} else {
dtmp.dnum = u.uz.dnum;
dtmp.dlevel = newlevel;
}
if (dist > 1)
You("fall down a %s%sshaft!", dist > 3 ? "very " : "",
dist > 2 ? "deep " : "");