From 31c824dbf364fa6591a78ceb24bd892b7ef96f9e Mon Sep 17 00:00:00 2001 From: kmhugo Date: Tue, 16 Apr 2002 01:37:57 +0000 Subject: [PATCH] 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. --- src/apply.c | 2 +- src/dig.c | 136 ++++++++++++++++++++++++++++++++------------------- src/invent.c | 2 +- 3 files changed, 88 insertions(+), 52 deletions(-) diff --git a/src/apply.c b/src/apply.c index 7e41f1e11..cd5ab73a8 100644 --- a/src/apply.c +++ b/src/apply.c @@ -2827,7 +2827,7 @@ doapply() if (is_pole(obj)) { res = use_pole(obj); break; - } else if (is_pick(obj) /* || is_axe(obj) */) { + } else if (is_pick(obj) || is_axe(obj)) { res = use_pick_axe(obj); break; } diff --git a/src/dig.c b/src/dig.c index b9ea46f7c..9bd70d60e 100644 --- a/src/dig.c +++ b/src/dig.c @@ -13,11 +13,19 @@ static NEARDATA boolean did_dig_msg; STATIC_DCL boolean NDECL(rm_waslit); STATIC_DCL void FDECL(mkcavepos, (XCHAR_P,XCHAR_P,int,BOOLEAN_P,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 schar FDECL(fillholetyp, (int, int)); 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 rm_waslit() @@ -122,16 +130,20 @@ register boolean rockit; } /* When digging into location , 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 -dig_typ(x, y) +dig_typ(otmp, x, y) +struct obj *otmp; xchar x, y; { - return (sobj_at(STATUE, x, y) ? 1 : - sobj_at(BOULDER, x, y) ? 2 : - closed_door(x, y) ? 3 : - IS_TREE(levl[x][y].typ) ? 4: 0); + boolean ispick = is_pick(otmp); + + return (ispick && sobj_at(STATUE, x, y) ? DIGTYP_STATUE : + 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 @@ -153,11 +165,12 @@ dig_check(madeby, verbose, x, y) int 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 (x == xdnladder || x == xupladder) { 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); } else if (IS_THRONE(levl[x][y].typ) && madeby != BY_OBJECT) { 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."); return(FALSE); } else if (Is_airlevel(&u.uz)) { - if(verbose) You("cannot dig in thin air."); + if(verbose) You("cannot %s thin air.", verb); return(FALSE); } else if (Is_waterlevel(&u.uz)) { 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) || (ttmp && (ttmp->ttyp == MAGIC_PORTAL || !Can_dig_down(&u.uz)))) { - if(verbose) pline_The("%s here is too hard to dig in.", - surface(x,y)); + if(verbose) pline_The("%s here is too hard to %s.", + surface(x,y), verb); return(FALSE); } 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); } else if (madeby == BY_OBJECT && /* the block against existing traps is mainly to @@ -197,11 +210,13 @@ dig() { register struct rm *lev; 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]; /* perhaps a nymph stole your pick-axe while you were busy digging */ /* 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) || ((digging.down ? (dpx != u.ux || dpy != u.uy) : (distu(dpx,dpy) > 2)))) @@ -210,12 +225,14 @@ dig() if (digging.down) { if(!dig_check(BY_YOU, TRUE, u.ux, u.uy)) return(0); } else { /* !digging.down */ - if (IS_ROCK(lev->typ) && !may_dig(dpx,dpy) && !dig_typ(dpx, dpy)) { - pline("This wall is too hard to dig into."); + if (IS_TREE(lev->typ) && !may_dig(dpx,dpy) && + dig_typ(uwep, dpx, dpy) == DIGTYP_TREE) { + pline("This tree seems to be petrified."); return(0); } - if (IS_TREE(lev->typ) && !may_dig(dpx,dpy) && dig_typ(dpx, dpy) == 4) { - pline("This tree seems to be petrified."); + if (IS_ROCK(lev->typ) && !may_dig(dpx,dpy) && + dig_typ(uwep, dpx, dpy) == DIGTYP_ROCK) { + pline("This wall is too hard to %s.", verb); return(0); } } @@ -319,6 +336,7 @@ dig() if (IS_TREE(lev->typ)) { digtxt = "You cut down the tree."; lev->typ = ROOM; + if (!rn2(5)) (void) rnd_treefruit_at(dpx, dpy); } else { digtxt = "You succeed in cutting away some rock."; lev->typ = CORR; @@ -389,15 +407,15 @@ cleanup: digging.level.dlevel = -1; return(0); } else { /* not enough effort has been spent yet */ - static const char *d_target[5] = { - "rock", "statue", "boulder", "door", "tree" + static const char *d_target[6] = { + "", "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(*in_rooms(dpx, dpy, SHOPBASE)) { - pline("This %s seems too hard to dig into.", - IS_DOOR(lev->typ) ? "door" : "wall"); + pline("This %s seems too hard to %s.", + IS_DOOR(lev->typ) ? "door" : "wall", verb); return(0); } } else if (!IS_ROCK(lev->typ) && !dig_target) @@ -777,23 +795,29 @@ int use_pick_axe(obj) struct obj *obj; { + boolean ispick; char dirsyms[12]; char qbuf[QBUFSZ]; register char *dsp = dirsyms; register int rx, ry; int res = 0; - register const char *sdp; + register const char *sdp, *verb; + if(iflags.num_pad) sdp = ndir; else sdp = sdir; /* DICE workaround */ + /* Check tool */ if (obj != uwep) { if (!wield_tool(obj)) return(0); else res = 1; } + ispick = is_pick(obj); + verb = ispick ? "dig" : "chop"; + 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==1 => just got "You now wield a pick-axe." message */ - !res ? "Unfortunately," : "But"); + !res ? "Unfortunately," : "But", verb); return res; } @@ -801,13 +825,14 @@ struct obj *obj; (void) movecmd(*sdp); /* sets u.dx and u.dy and u.dz */ rx = u.ux + u.dx; ry = u.uy + u.dy; - if(u.dz > 0 || (u.dz == 0 && isok(rx, ry) && - (IS_ROCK(levl[rx][ry].typ) || dig_typ(rx, ry)))) + /* Include down even with axe, so we have at least one direction */ + if (u.dz > 0 || + (u.dz == 0 && isok(rx, ry) && dig_typ(obj, rx, ry))) *dsp++ = *sdp; sdp++; } *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)) return(res); @@ -825,11 +850,14 @@ struct obj *obj; register int rx, ry; register struct rm *lev; 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)) { ; /* return(1) */ } else if (Underwater) { - pline("Turbulence torpedoes your digging attempts."); + pline("Turbulence torpedoes your %s attempts.", verbing); } else if(u.dz < 0) { if(Levitation) You("don't have enough leverage."); @@ -858,8 +886,8 @@ struct obj *obj; lev = &levl[rx][ry]; if(MON_AT(rx, ry) && attack(m_at(rx, ry))) return(1); - dig_target = dig_typ(rx, ry); - if (!IS_ROCK(lev->typ) && !dig_target) { + dig_target = dig_typ(obj, rx, ry); + if (dig_target == DIGTYP_UNDIGGABLE) { /* ACCESSIBLE or POOL */ struct trap *trap = t_at(rx, ry); @@ -877,11 +905,16 @@ struct obj *obj; } else if (lev->typ == IRONBARS) { pline("Clang!"); 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.", aobjnam(obj, (char *)0)); } else { - static const char *d_action[5] = { + static const char *d_action[6] = { + "swinging", "digging", "chipping the statue", "hitting the boulder", @@ -914,7 +947,7 @@ struct obj *obj; d_action[dig_target]); digging.chew = FALSE; } - set_occupation(dig, "digging", 0); + set_occupation(dig, verbing, 0); } } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) { /* 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 */ You("cannot stay under%s long enough.", 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 { if (digging.pos.x != u.ux || digging.pos.y != u.uy || !on_level(&digging.level, &u.uz) || !digging.down) { @@ -935,12 +972,12 @@ struct obj *obj; digging.pos.y = u.uy; assign_level(&digging.level, &u.uz); digging.effort = 0; - You("start digging downward."); + You("start %s downward.", verbing); if (*u.ushops) shopdig(0); } else - You("continue digging downward."); + You("continue %s downward.", verbing); did_dig_msg = FALSE; - set_occupation(dig, "digging", 0); + set_occupation(dig, verbing, 0); } return(1); } @@ -1009,9 +1046,6 @@ register struct monst *mtmp; here = &levl[mtmp->mx][mtmp->my]; if (here->typ == SDOOR) 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 */ if (closed_door(mtmp->mx, mtmp->my)) { @@ -1031,11 +1065,10 @@ register struct monst *mtmp; } newsym(mtmp->mx, mtmp->my); return FALSE; - } else - if (!IS_ROCK(here->typ)) /* no dig */ + } else if (!IS_ROCK(here->typ) && !IS_TREE(here->typ)) /* no dig */ 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) { impossible("mdig_tunnel: %s at (%d,%d) is undiggable", (IS_WALL(here->typ) ? "wall" : "stone"), @@ -1057,13 +1090,16 @@ register struct monst *mtmp; here->typ = DOOR; here->doormask = D_NODOOR; } - } else - /* KMH -- Added support for trees */ - here->typ = level.flags.arboreal ? ROOM : CORR; - - if (pile && pile < 5) /* leave behind some rocks? */ - (void) mksobj_at((pile == 1) ? BOULDER : ROCK, + } else if (IS_TREE(here->typ)) { + here->typ = ROOM; + if (pile && pile < 5) + (void) rnd_treefruit_at(mtmp->mx, mtmp->my); + } else { + here->typ = CORR; + if (pile && pile < 5) + (void) mksobj_at((pile == 1) ? BOULDER : ROCK, mtmp->mx, mtmp->my, TRUE, FALSE); + } newsym(mtmp->mx, mtmp->my); if (!sobj_at(BOULDER, mtmp->mx, mtmp->my)) unblock_point(mtmp->mx, mtmp->my); /* vision */ diff --git a/src/invent.c b/src/invent.c index 40a1147a7..d4006c446 100644 --- a/src/invent.c +++ b/src/invent.c @@ -855,7 +855,7 @@ register const char *let,*word; !strcmp(word, "untrap with")) && /* Picks, axes, pole-weapons, bullwhips */ ((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) && - !is_pole(otmp) && otyp != BULLWHIP) + !is_axe(otmp) && !is_pole(otmp) && otyp != BULLWHIP) || (otmp->oclass == POTION_CLASS && /* only applicable potion is oil, and it will only be offered as a choice when already discovered */