digging rock vs. chopping wood

Refinement of the digging code:
* Picks should not chop down trees, but axes should.
* Picks should break walls, rock, statues, and boulders; axes shouldn't.
* Either picks or axes should chop down doors.
This commit is contained in:
kmhugo
2002-04-16 01:37:57 +00:00
parent a15813a3cb
commit 31c824dbf3
3 changed files with 88 additions and 52 deletions

View File

@@ -2827,7 +2827,7 @@ doapply()
if (is_pole(obj)) { if (is_pole(obj)) {
res = use_pole(obj); res = use_pole(obj);
break; break;
} else if (is_pick(obj) /* || is_axe(obj) */) { } else if (is_pick(obj) || is_axe(obj)) {
res = use_pick_axe(obj); res = use_pick_axe(obj);
break; break;
} }

136
src/dig.c
View File

@@ -13,11 +13,19 @@ static NEARDATA boolean did_dig_msg;
STATIC_DCL boolean NDECL(rm_waslit); STATIC_DCL boolean NDECL(rm_waslit);
STATIC_DCL void FDECL(mkcavepos, (XCHAR_P,XCHAR_P,int,BOOLEAN_P,BOOLEAN_P)); STATIC_DCL void FDECL(mkcavepos, (XCHAR_P,XCHAR_P,int,BOOLEAN_P,BOOLEAN_P));
STATIC_DCL void FDECL(mkcavearea, (BOOLEAN_P)); STATIC_DCL void FDECL(mkcavearea, (BOOLEAN_P));
STATIC_DCL int FDECL(dig_typ, (XCHAR_P,XCHAR_P)); STATIC_DCL int FDECL(dig_typ, (struct obj *,XCHAR_P,XCHAR_P));
STATIC_DCL int NDECL(dig); STATIC_DCL int NDECL(dig);
STATIC_DCL schar FDECL(fillholetyp, (int, int)); STATIC_DCL schar FDECL(fillholetyp, (int, int));
STATIC_DCL void NDECL(dig_up_grave); STATIC_DCL void NDECL(dig_up_grave);
/* Indicies returned by dig_typ() */
#define DIGTYP_UNDIGGABLE 0
#define DIGTYP_ROCK 1
#define DIGTYP_STATUE 2
#define DIGTYP_BOULDER 3
#define DIGTYP_DOOR 4
#define DIGTYP_TREE 5
STATIC_OVL boolean STATIC_OVL boolean
rm_waslit() rm_waslit()
@@ -122,16 +130,20 @@ register boolean rockit;
} }
/* When digging into location <x,y>, what are you actually digging into? */ /* When digging into location <x,y>, what are you actually digging into? */
/* result: 1=>statue, 2=>boulder, 3=>door, 0=>other; used as array index */
/* KMH -- Added 4=>tree */
STATIC_OVL int STATIC_OVL int
dig_typ(x, y) dig_typ(otmp, x, y)
struct obj *otmp;
xchar x, y; xchar x, y;
{ {
return (sobj_at(STATUE, x, y) ? 1 : boolean ispick = is_pick(otmp);
sobj_at(BOULDER, x, y) ? 2 :
closed_door(x, y) ? 3 : return (ispick && sobj_at(STATUE, x, y) ? DIGTYP_STATUE :
IS_TREE(levl[x][y].typ) ? 4: 0); ispick && sobj_at(BOULDER, x, y) ? DIGTYP_BOULDER :
closed_door(x, y) ? DIGTYP_DOOR :
IS_TREE(levl[x][y].typ) ? (ispick ? DIGTYP_UNDIGGABLE : DIGTYP_TREE) :
ispick && IS_ROCK(levl[x][y].typ) &&
(!level.flags.arboreal || IS_WALL(levl[x][y].typ)) ?
DIGTYP_ROCK : DIGTYP_UNDIGGABLE);
} }
boolean boolean
@@ -153,11 +165,12 @@ dig_check(madeby, verbose, x, y)
int x, y; int x, y;
{ {
struct trap *ttmp = t_at(x, 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)) { if (On_stairs(x, y)) {
if (x == xdnladder || x == xupladder) { if (x == xdnladder || x == xupladder) {
if(verbose) pline_The("ladder resists your effort."); if(verbose) pline_The("ladder resists your effort.");
} else if(verbose) pline_The("stairs are too hard to dig in."); } else if(verbose) pline_The("stairs are too hard to %s.", verb);
return(FALSE); return(FALSE);
} else if (IS_THRONE(levl[x][y].typ) && madeby != BY_OBJECT) { } else if (IS_THRONE(levl[x][y].typ) && madeby != BY_OBJECT) {
if(verbose) pline_The("throne is too hard to break apart."); if(verbose) pline_The("throne is too hard to break apart.");
@@ -167,7 +180,7 @@ dig_check(madeby, verbose, x, y)
if(verbose) pline_The("altar is too hard to break apart."); if(verbose) pline_The("altar is too hard to break apart.");
return(FALSE); return(FALSE);
} else if (Is_airlevel(&u.uz)) { } else if (Is_airlevel(&u.uz)) {
if(verbose) You("cannot dig in thin air."); if(verbose) You("cannot %s thin air.", verb);
return(FALSE); return(FALSE);
} else if (Is_waterlevel(&u.uz)) { } else if (Is_waterlevel(&u.uz)) {
if(verbose) pline_The("water splashes and subsides."); if(verbose) pline_The("water splashes and subsides.");
@@ -176,11 +189,11 @@ dig_check(madeby, verbose, x, y)
(levl[x][y].wall_info & W_NONDIGGABLE) != 0) (levl[x][y].wall_info & W_NONDIGGABLE) != 0)
|| (ttmp && || (ttmp &&
(ttmp->ttyp == MAGIC_PORTAL || !Can_dig_down(&u.uz)))) { (ttmp->ttyp == MAGIC_PORTAL || !Can_dig_down(&u.uz)))) {
if(verbose) pline_The("%s here is too hard to dig in.", if(verbose) pline_The("%s here is too hard to %s.",
surface(x,y)); surface(x,y), verb);
return(FALSE); return(FALSE);
} else if (sobj_at(BOULDER, x, y)) { } else if (sobj_at(BOULDER, x, y)) {
if(verbose) There("isn't enough room to dig here."); if(verbose) There("isn't enough room to %s here.", verb);
return(FALSE); return(FALSE);
} else if (madeby == BY_OBJECT && } else if (madeby == BY_OBJECT &&
/* the block against existing traps is mainly to /* the block against existing traps is mainly to
@@ -197,11 +210,13 @@ dig()
{ {
register struct rm *lev; register struct rm *lev;
register xchar dpx = digging.pos.x, dpy = digging.pos.y; register xchar dpx = digging.pos.x, dpy = digging.pos.y;
register boolean ispick = uwep && is_pick(uwep);
const char *verb = (!uwep || is_pick(uwep)) ? "dig into" : "chop";
lev = &levl[dpx][dpy]; lev = &levl[dpx][dpy];
/* perhaps a nymph stole your pick-axe while you were busy digging */ /* perhaps a nymph stole your pick-axe while you were busy digging */
/* or perhaps you teleported away */ /* or perhaps you teleported away */
if (u.uswallow || !uwep || !is_pick(uwep) || if (u.uswallow || !uwep || (!ispick && !is_axe(uwep)) ||
!on_level(&digging.level, &u.uz) || !on_level(&digging.level, &u.uz) ||
((digging.down ? (dpx != u.ux || dpy != u.uy) ((digging.down ? (dpx != u.ux || dpy != u.uy)
: (distu(dpx,dpy) > 2)))) : (distu(dpx,dpy) > 2))))
@@ -210,12 +225,14 @@ dig()
if (digging.down) { if (digging.down) {
if(!dig_check(BY_YOU, TRUE, u.ux, u.uy)) return(0); if(!dig_check(BY_YOU, TRUE, u.ux, u.uy)) return(0);
} else { /* !digging.down */ } else { /* !digging.down */
if (IS_ROCK(lev->typ) && !may_dig(dpx,dpy) && !dig_typ(dpx, dpy)) { if (IS_TREE(lev->typ) && !may_dig(dpx,dpy) &&
pline("This wall is too hard to dig into."); dig_typ(uwep, dpx, dpy) == DIGTYP_TREE) {
pline("This tree seems to be petrified.");
return(0); return(0);
} }
if (IS_TREE(lev->typ) && !may_dig(dpx,dpy) && dig_typ(dpx, dpy) == 4) { if (IS_ROCK(lev->typ) && !may_dig(dpx,dpy) &&
pline("This tree seems to be petrified."); dig_typ(uwep, dpx, dpy) == DIGTYP_ROCK) {
pline("This wall is too hard to %s.", verb);
return(0); return(0);
} }
} }
@@ -319,6 +336,7 @@ dig()
if (IS_TREE(lev->typ)) { if (IS_TREE(lev->typ)) {
digtxt = "You cut down the tree."; digtxt = "You cut down the tree.";
lev->typ = ROOM; lev->typ = ROOM;
if (!rn2(5)) (void) rnd_treefruit_at(dpx, dpy);
} else { } else {
digtxt = "You succeed in cutting away some rock."; digtxt = "You succeed in cutting away some rock.";
lev->typ = CORR; lev->typ = CORR;
@@ -389,15 +407,15 @@ cleanup:
digging.level.dlevel = -1; digging.level.dlevel = -1;
return(0); return(0);
} else { /* not enough effort has been spent yet */ } else { /* not enough effort has been spent yet */
static const char *d_target[5] = { static const char *d_target[6] = {
"rock", "statue", "boulder", "door", "tree" "", "rock", "statue", "boulder", "door", "tree"
}; };
int dig_target = dig_typ(dpx, dpy); int dig_target = dig_typ(uwep, dpx, dpy);
if (IS_WALL(lev->typ) || dig_target == 3) { if (IS_WALL(lev->typ) || dig_target == 3) {
if(*in_rooms(dpx, dpy, SHOPBASE)) { if(*in_rooms(dpx, dpy, SHOPBASE)) {
pline("This %s seems too hard to dig into.", pline("This %s seems too hard to %s.",
IS_DOOR(lev->typ) ? "door" : "wall"); IS_DOOR(lev->typ) ? "door" : "wall", verb);
return(0); return(0);
} }
} else if (!IS_ROCK(lev->typ) && !dig_target) } else if (!IS_ROCK(lev->typ) && !dig_target)
@@ -777,23 +795,29 @@ int
use_pick_axe(obj) use_pick_axe(obj)
struct obj *obj; struct obj *obj;
{ {
boolean ispick;
char dirsyms[12]; char dirsyms[12];
char qbuf[QBUFSZ]; char qbuf[QBUFSZ];
register char *dsp = dirsyms; register char *dsp = dirsyms;
register int rx, ry; register int rx, ry;
int res = 0; int res = 0;
register const char *sdp; register const char *sdp, *verb;
if(iflags.num_pad) sdp = ndir; else sdp = sdir; /* DICE workaround */ if(iflags.num_pad) sdp = ndir; else sdp = sdir; /* DICE workaround */
/* Check tool */
if (obj != uwep) { if (obj != uwep) {
if (!wield_tool(obj)) return(0); if (!wield_tool(obj)) return(0);
else res = 1; else res = 1;
} }
ispick = is_pick(obj);
verb = ispick ? "dig" : "chop";
if (u.utrap && u.utraptype == TT_WEB) { if (u.utrap && u.utraptype == TT_WEB) {
pline("%s you can't dig while entangled in a web.", pline("%s you can't %s while entangled in a web.",
/* res==0 => no prior message; /* res==0 => no prior message;
res==1 => just got "You now wield a pick-axe." message */ res==1 => just got "You now wield a pick-axe." message */
!res ? "Unfortunately," : "But"); !res ? "Unfortunately," : "But", verb);
return res; return res;
} }
@@ -801,13 +825,14 @@ struct obj *obj;
(void) movecmd(*sdp); /* sets u.dx and u.dy and u.dz */ (void) movecmd(*sdp); /* sets u.dx and u.dy and u.dz */
rx = u.ux + u.dx; rx = u.ux + u.dx;
ry = u.uy + u.dy; ry = u.uy + u.dy;
if(u.dz > 0 || (u.dz == 0 && isok(rx, ry) && /* Include down even with axe, so we have at least one direction */
(IS_ROCK(levl[rx][ry].typ) || dig_typ(rx, ry)))) if (u.dz > 0 ||
(u.dz == 0 && isok(rx, ry) && dig_typ(obj, rx, ry)))
*dsp++ = *sdp; *dsp++ = *sdp;
sdp++; sdp++;
} }
*dsp = 0; *dsp = 0;
Sprintf(qbuf, "In what direction do you want to dig? [%s]", dirsyms); Sprintf(qbuf, "In what direction do you want to %s? [%s]", verb, dirsyms);
if(!getdir(qbuf)) if(!getdir(qbuf))
return(res); return(res);
@@ -825,11 +850,14 @@ struct obj *obj;
register int rx, ry; register int rx, ry;
register struct rm *lev; register struct rm *lev;
int dig_target; int dig_target;
boolean ispick = is_pick(obj);
const char *verb = ispick ? "dig" : "chop";
const char *verbing = ispick ? "digging" : "chopping";
if (u.uswallow && attack(u.ustuck)) { if (u.uswallow && attack(u.ustuck)) {
; /* return(1) */ ; /* return(1) */
} else if (Underwater) { } else if (Underwater) {
pline("Turbulence torpedoes your digging attempts."); pline("Turbulence torpedoes your %s attempts.", verbing);
} else if(u.dz < 0) { } else if(u.dz < 0) {
if(Levitation) if(Levitation)
You("don't have enough leverage."); You("don't have enough leverage.");
@@ -858,8 +886,8 @@ struct obj *obj;
lev = &levl[rx][ry]; lev = &levl[rx][ry];
if(MON_AT(rx, ry) && attack(m_at(rx, ry))) if(MON_AT(rx, ry) && attack(m_at(rx, ry)))
return(1); return(1);
dig_target = dig_typ(rx, ry); dig_target = dig_typ(obj, rx, ry);
if (!IS_ROCK(lev->typ) && !dig_target) { if (dig_target == DIGTYP_UNDIGGABLE) {
/* ACCESSIBLE or POOL */ /* ACCESSIBLE or POOL */
struct trap *trap = t_at(rx, ry); struct trap *trap = t_at(rx, ry);
@@ -877,11 +905,16 @@ struct obj *obj;
} else if (lev->typ == IRONBARS) { } else if (lev->typ == IRONBARS) {
pline("Clang!"); pline("Clang!");
wake_nearby(); wake_nearby();
} else } else if (IS_TREE(lev->typ))
You("need an axe to cut down a tree.");
else if (IS_ROCK(lev->typ))
You("need a pick to dig rock.");
else
You("swing your %s through thin air.", You("swing your %s through thin air.",
aobjnam(obj, (char *)0)); aobjnam(obj, (char *)0));
} else { } else {
static const char *d_action[5] = { static const char *d_action[6] = {
"swinging",
"digging", "digging",
"chipping the statue", "chipping the statue",
"hitting the boulder", "hitting the boulder",
@@ -914,7 +947,7 @@ struct obj *obj;
d_action[dig_target]); d_action[dig_target]);
digging.chew = FALSE; digging.chew = FALSE;
} }
set_occupation(dig, "digging", 0); set_occupation(dig, verbing, 0);
} }
} else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) { } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
/* it must be air -- water checked above */ /* it must be air -- water checked above */
@@ -925,6 +958,10 @@ struct obj *obj;
/* Monsters which swim also happen not to be able to dig */ /* Monsters which swim also happen not to be able to dig */
You("cannot stay under%s long enough.", You("cannot stay under%s long enough.",
is_pool(u.ux, u.uy) ? "water" : " the lava"); is_pool(u.ux, u.uy) ? "water" : " the lava");
} else if (!ispick) {
Your("%s merely scratches the %s.",
aobjnam(obj, (char *)0), surface(u.ux,u.uy));
u_wipe_engr(3);
} else { } else {
if (digging.pos.x != u.ux || digging.pos.y != u.uy || if (digging.pos.x != u.ux || digging.pos.y != u.uy ||
!on_level(&digging.level, &u.uz) || !digging.down) { !on_level(&digging.level, &u.uz) || !digging.down) {
@@ -935,12 +972,12 @@ struct obj *obj;
digging.pos.y = u.uy; digging.pos.y = u.uy;
assign_level(&digging.level, &u.uz); assign_level(&digging.level, &u.uz);
digging.effort = 0; digging.effort = 0;
You("start digging downward."); You("start %s downward.", verbing);
if (*u.ushops) shopdig(0); if (*u.ushops) shopdig(0);
} else } else
You("continue digging downward."); You("continue %s downward.", verbing);
did_dig_msg = FALSE; did_dig_msg = FALSE;
set_occupation(dig, "digging", 0); set_occupation(dig, verbing, 0);
} }
return(1); return(1);
} }
@@ -1009,9 +1046,6 @@ register struct monst *mtmp;
here = &levl[mtmp->mx][mtmp->my]; here = &levl[mtmp->mx][mtmp->my];
if (here->typ == SDOOR) if (here->typ == SDOOR)
cvt_sdoor_to_door(here); /* ->typ = DOOR */ cvt_sdoor_to_door(here); /* ->typ = DOOR */
if (IS_TREE(here->typ))
/* KMH -- Trees shouldn't create piles */
pile = 0;
/* Eats away door if present & closed or locked */ /* Eats away door if present & closed or locked */
if (closed_door(mtmp->mx, mtmp->my)) { if (closed_door(mtmp->mx, mtmp->my)) {
@@ -1031,11 +1065,10 @@ register struct monst *mtmp;
} }
newsym(mtmp->mx, mtmp->my); newsym(mtmp->mx, mtmp->my);
return FALSE; return FALSE;
} else } else if (!IS_ROCK(here->typ) && !IS_TREE(here->typ)) /* no dig */
if (!IS_ROCK(here->typ)) /* no dig */
return FALSE; return FALSE;
/* Only rock and walls fall through to this point. */ /* Only rock, trees, and walls fall through to this point. */
if ((here->wall_info & W_NONDIGGABLE) != 0) { if ((here->wall_info & W_NONDIGGABLE) != 0) {
impossible("mdig_tunnel: %s at (%d,%d) is undiggable", impossible("mdig_tunnel: %s at (%d,%d) is undiggable",
(IS_WALL(here->typ) ? "wall" : "stone"), (IS_WALL(here->typ) ? "wall" : "stone"),
@@ -1057,13 +1090,16 @@ register struct monst *mtmp;
here->typ = DOOR; here->typ = DOOR;
here->doormask = D_NODOOR; here->doormask = D_NODOOR;
} }
} else } else if (IS_TREE(here->typ)) {
/* KMH -- Added support for trees */ here->typ = ROOM;
here->typ = level.flags.arboreal ? ROOM : CORR; if (pile && pile < 5)
(void) rnd_treefruit_at(mtmp->mx, mtmp->my);
if (pile && pile < 5) /* leave behind some rocks? */ } else {
(void) mksobj_at((pile == 1) ? BOULDER : ROCK, here->typ = CORR;
if (pile && pile < 5)
(void) mksobj_at((pile == 1) ? BOULDER : ROCK,
mtmp->mx, mtmp->my, TRUE, FALSE); mtmp->mx, mtmp->my, TRUE, FALSE);
}
newsym(mtmp->mx, mtmp->my); newsym(mtmp->mx, mtmp->my);
if (!sobj_at(BOULDER, mtmp->mx, mtmp->my)) if (!sobj_at(BOULDER, mtmp->mx, mtmp->my))
unblock_point(mtmp->mx, mtmp->my); /* vision */ unblock_point(mtmp->mx, mtmp->my); /* vision */

View File

@@ -855,7 +855,7 @@ register const char *let,*word;
!strcmp(word, "untrap with")) && !strcmp(word, "untrap with")) &&
/* Picks, axes, pole-weapons, bullwhips */ /* Picks, axes, pole-weapons, bullwhips */
((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) && ((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) &&
!is_pole(otmp) && otyp != BULLWHIP) !is_axe(otmp) && !is_pole(otmp) && otyp != BULLWHIP)
|| (otmp->oclass == POTION_CLASS && || (otmp->oclass == POTION_CLASS &&
/* only applicable potion is oil, and it will only /* only applicable potion is oil, and it will only
be offered as a choice when already discovered */ be offered as a choice when already discovered */