GitHub issue #1254
> If there's a trap on a no-dig level, the floor beneath it will always be "too hard to dig into", making it impossible to remove the trap. > > As you can still dig pits in these levels (just not holes), the floor under the trap itself resisting to become a pit seems inconsistent. > > Steps to reproduce: > > Go to no-dig level like Mine's End > Make a trap > Dig a pit next to it -> works > Dig on the trap -> does not work Return more information about the dig_check() results to caller (was just a boolean). Move the messaging that was in dig_check() into a separate digcheck_fail_message() function that uses the expanded return information. Resolves #1254 .
This commit is contained in:
@@ -498,7 +498,9 @@ extern int wiz_mgender(void);
|
||||
extern int dig_typ(struct obj *, coordxy, coordxy);
|
||||
extern boolean is_digging(void);
|
||||
extern int holetime(void);
|
||||
extern boolean dig_check(struct monst *, boolean, coordxy, coordxy);
|
||||
extern enum digcheck_result dig_check(struct monst *, coordxy, coordxy);
|
||||
extern void digcheck_fail_message(enum digcheck_result, struct monst *,
|
||||
coordxy, coordxy);
|
||||
extern void digactualhole(coordxy, coordxy, struct monst *, int);
|
||||
extern boolean dighole(boolean, boolean, coord *);
|
||||
extern int use_pick_axe(struct obj *) NONNULLARG1;
|
||||
|
||||
@@ -327,6 +327,28 @@ struct _create_particular_data {
|
||||
boolean sleeping, saddled, invisible, hidden;
|
||||
};
|
||||
|
||||
/* dig_check() results */
|
||||
|
||||
enum digcheck_result {
|
||||
DIGCHECK_PASSED = 1,
|
||||
DIGCHECK_PASSED_DESTROY_TRAP = 2,
|
||||
DIGCHECK_PASSED_PITONLY = 3,
|
||||
DIGCHECK_FAILED = 4,
|
||||
DIGCHECK_FAIL_ONSTAIRS = DIGCHECK_FAILED,
|
||||
DIGCHECK_FAIL_ONLADDER,
|
||||
DIGCHECK_FAIL_THRONE,
|
||||
DIGCHECK_FAIL_ALTAR,
|
||||
DIGCHECK_FAIL_AIRLEVEL,
|
||||
DIGCHECK_FAIL_WATERLEVEL,
|
||||
DIGCHECK_FAIL_TOOHARD,
|
||||
DIGCHECK_FAIL_UNDESTROYABLETRAP,
|
||||
DIGCHECK_FAIL_CANTDIG,
|
||||
DIGCHECK_FAIL_BOULDER,
|
||||
DIGCHECK_FAIL_OBJ_POOL_OR_TRAP
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Dismount: causes for why you are no longer riding */
|
||||
enum dismount_types {
|
||||
DISMOUNT_GENERIC = 0,
|
||||
|
||||
@@ -3945,7 +3945,7 @@ do_break_wand(struct obj *obj)
|
||||
if (obj->otyp == WAN_DIGGING) {
|
||||
schar typ;
|
||||
|
||||
if (dig_check(BY_OBJECT, FALSE, x, y)) {
|
||||
if (dig_check(BY_OBJECT, x, y) < DIGCHECK_FAILED) {
|
||||
if (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)) {
|
||||
/* normally, pits and holes don't anger guards, but they
|
||||
* do if it's a wall or door that's being dug */
|
||||
|
||||
134
src/dig.c
134
src/dig.c
@@ -205,59 +205,97 @@ is_digging(void)
|
||||
#define BY_YOU (&gy.youmonst)
|
||||
#define BY_OBJECT ((struct monst *) 0)
|
||||
|
||||
boolean
|
||||
dig_check(struct monst *madeby, boolean verbose, coordxy x, coordxy y)
|
||||
enum digcheck_result
|
||||
dig_check(struct monst *madeby, coordxy x, coordxy y)
|
||||
{
|
||||
struct trap *ttmp = t_at(x, y);
|
||||
const char *verb =
|
||||
(madeby == BY_YOU && uwep && is_axe(uwep)) ? "chop" : "dig in";
|
||||
|
||||
if (On_stairs(x, y)) {
|
||||
stairway *stway = stairway_at(x, y);
|
||||
if (stway->isladder) {
|
||||
if (verbose)
|
||||
pline_The("ladder resists your effort.");
|
||||
} else if (verbose)
|
||||
pline_The("stairs are too hard to %s.", verb);
|
||||
return FALSE;
|
||||
return DIGCHECK_FAIL_ONLADDER;
|
||||
} else {
|
||||
return DIGCHECK_FAIL_ONSTAIRS;
|
||||
}
|
||||
} else if (IS_THRONE(levl[x][y].typ) && madeby != BY_OBJECT) {
|
||||
if (verbose)
|
||||
pline_The("throne is too hard to break apart.");
|
||||
return FALSE;
|
||||
return DIGCHECK_FAIL_THRONE;
|
||||
} else if (IS_ALTAR(levl[x][y].typ)
|
||||
&& (madeby != BY_OBJECT
|
||||
|| (altarmask_at(x, y) & AM_SANCTUM) != 0)) {
|
||||
if (verbose)
|
||||
pline_The("altar is too hard to break apart.");
|
||||
return FALSE;
|
||||
return DIGCHECK_FAIL_ALTAR;
|
||||
} else if (Is_airlevel(&u.uz)) {
|
||||
if (verbose)
|
||||
You("cannot %s thin air.", verb);
|
||||
return FALSE;
|
||||
return DIGCHECK_FAIL_AIRLEVEL;
|
||||
} else if (Is_waterlevel(&u.uz)) {
|
||||
if (verbose)
|
||||
pline_The("%s splashes and subsides.", hliquid("water"));
|
||||
return FALSE;
|
||||
return DIGCHECK_FAIL_WATERLEVEL;
|
||||
} else if ((IS_ROCK(levl[x][y].typ) && levl[x][y].typ != SDOOR
|
||||
&& (levl[x][y].wall_info & W_NONDIGGABLE) != 0)
|
||||
|| (ttmp
|
||||
&& (undestroyable_trap(ttmp->ttyp)
|
||||
|| (!Can_dig_down(&u.uz) && !levl[x][y].candig)))) {
|
||||
if (verbose)
|
||||
pline_The("%s here is too hard to %s.", surface(x, y), verb);
|
||||
return FALSE;
|
||||
&& (levl[x][y].wall_info & W_NONDIGGABLE) != 0)) {
|
||||
return DIGCHECK_FAIL_TOOHARD;
|
||||
} else if (ttmp && undestroyable_trap(ttmp->ttyp)) {
|
||||
return DIGCHECK_FAIL_UNDESTROYABLETRAP;
|
||||
} else if (!Can_dig_down(&u.uz) && !levl[x][y].candig) {
|
||||
if (ttmp) {
|
||||
if (ttmp->ttyp != HOLE && !is_pit(ttmp->ttyp))
|
||||
return DIGCHECK_PASSED_DESTROY_TRAP;
|
||||
else
|
||||
return DIGCHECK_FAIL_CANTDIG;
|
||||
} else {
|
||||
return DIGCHECK_PASSED_PITONLY;
|
||||
}
|
||||
} else if (sobj_at(BOULDER, x, y)) {
|
||||
if (verbose)
|
||||
There("isn't enough room to %s here.", verb);
|
||||
return FALSE;
|
||||
return DIGCHECK_FAIL_BOULDER;
|
||||
} else if (madeby == BY_OBJECT
|
||||
/* the block against existing traps is mainly to
|
||||
prevent broken wands from turning holes into pits */
|
||||
&& (ttmp || is_pool_or_lava(x, y))) {
|
||||
/* digging by player handles pools separately */
|
||||
return FALSE;
|
||||
return DIGCHECK_FAIL_OBJ_POOL_OR_TRAP;
|
||||
}
|
||||
return DIGCHECK_PASSED;
|
||||
}
|
||||
|
||||
void
|
||||
digcheck_fail_message(enum digcheck_result digresult, struct monst *madeby,
|
||||
coordxy x, coordxy y)
|
||||
{
|
||||
const char *verb =
|
||||
(madeby == BY_YOU && uwep && is_axe(uwep)) ? "chop" : "dig in";
|
||||
|
||||
if (digresult < DIGCHECK_FAILED)
|
||||
return;
|
||||
|
||||
switch (digresult) {
|
||||
case DIGCHECK_FAIL_AIRLEVEL:
|
||||
You("cannot %s thin air.", verb);
|
||||
break;
|
||||
case DIGCHECK_FAIL_ALTAR:
|
||||
pline_The("altar is too hard to break apart.");
|
||||
break;
|
||||
case DIGCHECK_FAIL_BOULDER:
|
||||
There("isn't enough room to %s here.", verb);
|
||||
break;
|
||||
case DIGCHECK_FAIL_ONLADDER:
|
||||
pline_The("ladder resists your effort.");
|
||||
break;
|
||||
case DIGCHECK_FAIL_ONSTAIRS:
|
||||
pline_The("stairs are too hard to %s.", verb);
|
||||
break;
|
||||
case DIGCHECK_FAIL_THRONE:
|
||||
pline_The("throne is too hard to break apart.");
|
||||
break;
|
||||
case DIGCHECK_FAIL_CANTDIG:
|
||||
case DIGCHECK_FAIL_TOOHARD:
|
||||
pline_The("%s here is too hard to %s.", surface(x, y), verb);
|
||||
break;
|
||||
case DIGCHECK_FAIL_UNDESTROYABLETRAP:
|
||||
case DIGCHECK_FAIL_WATERLEVEL:
|
||||
pline_The("%s splashes and subsides.", hliquid("water"));
|
||||
break;
|
||||
case DIGCHECK_FAIL_OBJ_POOL_OR_TRAP:
|
||||
case DIGCHECK_PASSED:
|
||||
case DIGCHECK_PASSED_PITONLY:
|
||||
case DIGCHECK_PASSED_DESTROY_TRAP:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
staticfn int
|
||||
@@ -267,6 +305,7 @@ dig(void)
|
||||
coordxy dpx = svc.context.digging.pos.x, dpy = svc.context.digging.pos.y;
|
||||
boolean ispick = uwep && is_pick(uwep);
|
||||
const char *verb = (!uwep || is_pick(uwep)) ? "dig into" : "chop through";
|
||||
enum digcheck_result dcresult = DIGCHECK_PASSED;
|
||||
|
||||
lev = &levl[dpx][dpy];
|
||||
/* perhaps a nymph stole your pick-axe while you were busy digging */
|
||||
@@ -278,8 +317,11 @@ dig(void)
|
||||
return 0;
|
||||
|
||||
if (svc.context.digging.down) {
|
||||
if (!dig_check(BY_YOU, TRUE, u.ux, u.uy))
|
||||
dcresult = dig_check(BY_YOU, u.ux, u.uy);
|
||||
if (dcresult >= DIGCHECK_FAILED) {
|
||||
digcheck_fail_message(dcresult, BY_YOU, u.ux, u.uy);
|
||||
return 0;
|
||||
}
|
||||
} else { /* !svc.context.digging.down */
|
||||
if (IS_TREE(lev->typ) && !may_dig(dpx, dpy)
|
||||
&& dig_typ(uwep, dpx, dpy) == DIGTYP_TREE) {
|
||||
@@ -370,6 +412,17 @@ dig(void)
|
||||
/* we haven't made any progress toward a pit yet */
|
||||
svc.context.digging.effort = 0;
|
||||
return 0;
|
||||
} else if (ttmp && dcresult == DIGCHECK_PASSED_DESTROY_TRAP) {
|
||||
const char *ttmpname = trapname(ttmp->ttyp, FALSE);
|
||||
|
||||
if (ispick)
|
||||
You("destroy %s with %s.",
|
||||
ttmp->tseen ? the(ttmpname) : an(ttmpname),
|
||||
yobjnam(uwep, (const char *) 0));
|
||||
deltrap(ttmp);
|
||||
/* we haven't made any progress toward a pit yet */
|
||||
svc.context.digging.effort = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IS_ALTAR(lev->typ)) {
|
||||
@@ -637,6 +690,7 @@ digactualhole(coordxy x, coordxy y, struct monst *madeby, int ttyp)
|
||||
}
|
||||
shopdoor = IS_DOOR(lev->typ) && *in_rooms(x, y, SHOPBASE);
|
||||
oldobjs = svl.level.objects[x][y];
|
||||
|
||||
ttmp = maketrap(x, y, ttyp);
|
||||
if (!ttmp)
|
||||
return;
|
||||
@@ -836,7 +890,8 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
|
||||
schar typ, old_typ;
|
||||
coordxy dig_x, dig_y;
|
||||
boolean nohole, retval = FALSE;
|
||||
|
||||
enum digcheck_result dig_check_result;
|
||||
|
||||
if (!cc) {
|
||||
dig_x = u.ux;
|
||||
dig_y = u.uy;
|
||||
@@ -849,7 +904,10 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
|
||||
|
||||
ttmp = t_at(dig_x, dig_y);
|
||||
lev = &levl[dig_x][dig_y];
|
||||
nohole = (!Can_dig_down(&u.uz) && !lev->candig);
|
||||
dig_check_result = dig_check(BY_YOU, dig_x, dig_y);
|
||||
/* nohole = (!Can_dig_down(&u.uz) && !lev->candig); */
|
||||
nohole = (dig_check_result == DIGCHECK_FAIL_CANTDIG
|
||||
|| dig_check_result == DIGCHECK_FAIL_TOOHARD);
|
||||
old_typ = lev->typ;
|
||||
|
||||
if ((ttmp && (undestroyable_trap(ttmp->ttyp) || nohole))
|
||||
@@ -952,7 +1010,9 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
|
||||
}
|
||||
|
||||
/* finally we get to make a hole */
|
||||
if (nohole || pit_only)
|
||||
if (nohole || pit_only
|
||||
|| dig_check_result == DIGCHECK_PASSED_DESTROY_TRAP
|
||||
|| dig_check_result == DIGCHECK_PASSED_PITONLY)
|
||||
digactualhole(dig_x, dig_y, BY_YOU, PIT);
|
||||
else
|
||||
digactualhole(dig_x, dig_y, BY_YOU, HOLE);
|
||||
|
||||
Reference in New Issue
Block a user