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 scared hostile monster which cannot move away will attack
prevent a fog cloud that has engulfed the hero from moving under closed doors 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 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 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 {
struct trap *ntrap; struct trap *ntrap;
coordxy tx, ty; coordxy tx, ty;
d_level dst; /* destination for portals */ d_level dst; /* destination for portals/holes/trapdoors */
coord launch; coord launch;
Bitfield(ttyp, 5); Bitfield(ttyp, 5);
Bitfield(tseen, 1); Bitfield(tseen, 1);

View File

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

View File

@@ -8,6 +8,8 @@
extern const char *const destroy_strings[][3]; /* from zap.c */ extern const char *const destroy_strings[][3]; /* from zap.c */
static void mk_trap_statue(coordxy, coordxy); 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 *, static boolean keep_saddle_with_steedcorpse(unsigned, struct obj *,
struct obj *); struct obj *);
static boolean mu_maybe_destroy_web(struct monst *, boolean, struct trap *); static boolean mu_maybe_destroy_web(struct monst *, boolean, struct trap *);
@@ -373,6 +375,37 @@ mk_trap_statue(coordxy x, coordxy y)
mongone(mtmp); 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 * struct trap *
maketrap(coordxy x, coordxy y, int typ) maketrap(coordxy x, coordxy y, int typ)
{ {
@@ -435,6 +468,8 @@ maketrap(coordxy x, coordxy y, int typ)
/*FALLTHRU*/ /*FALLTHRU*/
case HOLE: case HOLE:
case TRAPDOOR: case TRAPDOOR:
if (is_hole(typ))
hole_destination(&(ttmp->dst));
if (*in_rooms(x, y, SHOPBASE) if (*in_rooms(x, y, SHOPBASE)
&& (is_hole(typ) || IS_DOOR(lev->typ) || IS_WALL(lev->typ))) && (is_hole(typ) || IS_DOOR(lev->typ) || IS_WALL(lev->typ)))
add_damage(x, y, /* schedule repair */ add_damage(x, y, /* schedule repair */
@@ -481,7 +516,7 @@ fall_through(
d_level dtmp; d_level dtmp;
char msgbuf[BUFSZ]; char msgbuf[BUFSZ];
const char *dont_fall = 0; const char *dont_fall = 0;
int newlevel, bottom; int newlevel, bottom = dng_bottom();
struct trap *t = (struct trap *) 0; struct trap *t = (struct trap *) 0;
/* we'll fall even while levitating in Sokoban; otherwise, if we /* we'll fall even while levitating in Sokoban; otherwise, if we
@@ -489,20 +524,8 @@ fall_through(
if (Blind && Levitation && !Sokoban) if (Blind && Levitation && !Sokoban)
return; 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 */ newlevel = dunlev(&u.uz); /* current level */
do { newlevel++;
newlevel++;
} while (!rn2(4) && newlevel < bottom);
if (td) { if (td) {
t = t_at(u.ux, u.uy); t = t_at(u.ux, u.uy);
@@ -555,8 +578,14 @@ fall_through(
} else { } else {
int dist = newlevel - dunlev(&u.uz); int dist = newlevel - dunlev(&u.uz);
dtmp.dnum = u.uz.dnum; if (t) {
dtmp.dlevel = newlevel; 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) if (dist > 1)
You("fall down a %s%sshaft!", dist > 3 ? "very " : "", You("fall down a %s%sshaft!", dist > 3 ? "very " : "",
dist > 2 ? "deep " : ""); dist > 2 ? "deep " : "");