diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 91f5fbd35..6262b4e2c 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -197,6 +197,7 @@ tame ghouls can eat old eggs new effect for reading a scroll of light while confused allow digging an adjacent pit with wand of digging while trapped in a pit #terrain command for debug mode +digging can activate or disarm some types of traps Platform- and/or Interface-Specific New Features diff --git a/include/extern.h b/include/extern.h index 47f8962d7..4c7292b97 100644 --- a/include/extern.h +++ b/include/extern.h @@ -254,7 +254,7 @@ E int NDECL(dig); E int NDECL(holetime); E boolean FDECL(dig_check, (struct monst *, BOOLEAN_P, int, int)); E void FDECL(digactualhole, (int,int,struct monst *,int)); -E boolean FDECL(dighole, (BOOLEAN_P, coord *)); +E boolean FDECL(dighole, (BOOLEAN_P,BOOLEAN_P,coord *)); E int FDECL(use_pick_axe, (struct obj *)); E int FDECL(use_pick_axe2, (struct obj *)); E boolean FDECL(mdig_tunnel, (struct monst *)); @@ -2149,6 +2149,7 @@ E void FDECL(water_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P)); E boolean NDECL(drown); E void FDECL(drain_en, (int)); E int NDECL(dountrap); +E void FDECL(cnv_trap_obj, (int,int,struct trap *,BOOLEAN_P)); E int FDECL(untrap, (BOOLEAN_P)); E boolean FDECL(chest_trap, (struct obj *,int,BOOLEAN_P)); E void FDECL(deltrap, (struct trap *)); diff --git a/include/hack.h b/include/hack.h index cd37508bf..1e3b31e34 100644 --- a/include/hack.h +++ b/include/hack.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)hack.h 3.5 2006/02/03 */ +/* SCCS Id: @(#)hack.h 3.5 2006/04/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -231,10 +231,11 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ #define PICK_RIGID 1 /* Flags to control dotrap() in trap.c */ -#define NOWEBMSG 0x01 /* suppress stumble into web message */ -#define FORCEBUNGLE 0x02 /* adjustments appropriate for bungling */ -#define RECURSIVETRAP 0x04 /* trap changed into another type this same turn */ -#define TOOKPLUNGE 0x08 /* used '>' to enter pit below you */ +#define FORCETRAP 0x01 /* triggering not left to chance */ +#define NOWEBMSG 0x02 /* suppress stumble into web message */ +#define FORCEBUNGLE 0x04 /* adjustments appropriate for bungling */ +#define RECURSIVETRAP 0x08 /* trap changed into another type this same turn */ +#define TOOKPLUNGE 0x10 /* used '>' to enter pit below you */ /* Flags to control test_move in hack.c */ #define DO_MOVE 0 /* really doing the move */ diff --git a/src/dig.c b/src/dig.c index 022918d39..2f949923e 100644 --- a/src/dig.c +++ b/src/dig.c @@ -276,23 +276,54 @@ dig() if (context.digging.effort > 250 || (ttmp && ttmp->ttyp == HOLE)) { - (void) dighole(FALSE, (coord *)0); + (void) dighole(FALSE, FALSE, (coord *)0); (void) memset((genericptr_t)&context.digging, 0, - sizeof (struct dig_info)); + sizeof context.digging); return(0); /* done with digging */ } if (context.digging.effort <= 50 || (ttmp && (ttmp->ttyp == TRAPDOOR || - ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT))) + ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT))) { return(1); + } else if (ttmp && (ttmp->ttyp == LANDMINE || + (ttmp->ttyp == BEAR_TRAP && !u.utrap))) { + /* digging onto a set object trap triggers it; + hero should have used #untrap first */ + dotrap(ttmp, FORCETRAP); + /* restart completely from scratch if we resume digging */ + (void) memset((genericptr_t)&context.digging, 0, + sizeof context.digging); + return 0; + } else if (ttmp && ttmp->ttyp == BEAR_TRAP && u.utrap) { + if (rnl(7) > (Fumbling ? 1 : 4)) { + char kbuf[BUFSZ]; + int dmg = dmgval(uwep, &youmonst) + dbon(); + + if (dmg < 1) dmg = 1; + else if (uarmf) dmg = (dmg + 1) / 2; + You("hit yourself in the %s.", body_part(FOOT)); + Sprintf(kbuf, "chopping off %s own %s", + uhis(), body_part(FOOT)); + losehp(Maybe_Half_Phys(dmg), kbuf, KILLED_BY); + } else { + You("destroy the bear trap with %s.", + yobjnam(uwep, (const char *)0)); + u.utrap = 0; /* release from trap */ + deltrap(ttmp); + } + /* we haven't made any progress toward a pit yet */ + context.digging.effort = 0; + return 0; + } if (IS_ALTAR(lev->typ)) { altar_wrath(dpx, dpy); angry_priest(); } - if (dighole(TRUE, (coord *)0)) { /* make pit at */ + /* make pit at */ + if (dighole(TRUE, FALSE, (coord *)0)) { context.digging.level.dnum = 0; context.digging.level.dlevel = -1; } @@ -679,8 +710,8 @@ const char *fillmsg; /* return TRUE if digging succeeded, FALSE otherwise */ boolean -dighole(pit_only, cc) -boolean pit_only; +dighole(pit_only, by_magic, cc) +boolean pit_only, by_magic; coord *cc; { register struct trap *ttmp; @@ -792,6 +823,15 @@ coord *cc; return TRUE; } + /* magical digging disarms settable traps */ + if (by_magic && ttmp && + (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP)) { + int otyp = (ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP; + + /* convert trap into buried object (deletes trap) */ + cnv_trap_obj(otyp, 1, ttmp, TRUE); + } + /* finally we get to make a hole */ if (nohole || pit_only) digactualhole(dig_x, dig_y, BY_YOU, PIT); @@ -1067,13 +1107,17 @@ struct obj *obj; dotrap(trap, FORCEBUNGLE); /* might escape trap and still be teetering at brink */ if (!u.utrap) cant_reach_floor(u.ux, u.uy, FALSE, TRUE); - } else if (!ispick) { + } else if (!ispick && + /* can only dig down with an axe if stuck in a bear trap */ + (!trap || !u.utrap || u.utraptype != TT_BEARTRAP)) { pline("%s merely scratches the %s.", Yobjnam2(obj, (char *)0), surface(u.ux,u.uy)); u_wipe_engr(3); } else { - if (context.digging.pos.x != u.ux || context.digging.pos.y != u.uy || - !on_level(&context.digging.level, &u.uz) || !context.digging.down) { + if (context.digging.pos.x != u.ux || + context.digging.pos.y != u.uy || + !on_level(&context.digging.level, &u.uz) || + !context.digging.down) { context.digging.chew = FALSE; context.digging.down = TRUE; context.digging.warned = FALSE; @@ -1271,7 +1315,7 @@ zap_dig() newsym(u.ux, u.uy); } else { watch_dig((struct monst *)0, u.ux, u.uy, TRUE); - (void) dighole(FALSE, (coord *)0); + (void) dighole(FALSE, TRUE, (coord *)0); } } return; @@ -1312,7 +1356,7 @@ zap_dig() if (buf[0]) pline("%s", buf); } else { /* this can also result in a pool at zx,zy */ - dighole(TRUE, &cc); + dighole(TRUE, TRUE, &cc); adjpit = t_at(zx,zy); } } @@ -1900,7 +1944,7 @@ escape_tomb() "ooze" : "phase", surface(u.ux, u.uy)); if(tunnels(youmonst.data) && !needspick(youmonst.data)) - good = dighole(TRUE, (coord *)0); + good = dighole(TRUE, FALSE, (coord *)0); else good = TRUE; if(good) unearth_you(); } diff --git a/src/trap.c b/src/trap.c index ea7e5f659..dc4d913f6 100644 --- a/src/trap.c +++ b/src/trap.c @@ -10,7 +10,6 @@ STATIC_DCL void FDECL(dofiretrap, (struct obj *)); STATIC_DCL void NDECL(domagictrap); STATIC_DCL boolean FDECL(emergency_disrobe,(boolean *)); STATIC_DCL int FDECL(untrap_prob, (struct trap *ttmp)); -STATIC_DCL void FDECL(cnv_trap_obj, (int, int, struct trap *)); STATIC_DCL void FDECL(move_into_trap, (struct trap *)); STATIC_DCL int FDECL(try_disarm, (struct trap *,BOOLEAN_P)); STATIC_DCL void FDECL(reward_untrap, (struct trap *, struct monst *)); @@ -631,11 +630,12 @@ unsigned trflags; { register int ttype = trap->ttyp; register struct obj *otmp; - boolean already_seen = trap->tseen; - boolean webmsgok = (!(trflags & NOWEBMSG)); - boolean forcebungle = (trflags & FORCEBUNGLE); - boolean plunged = (trflags & TOOKPLUNGE); - boolean adj_pit = conjoined_pits(trap, t_at(u.ux0,u.uy0), TRUE); + boolean already_seen = trap->tseen, + forcetrap = (trflags & FORCETRAP) != 0, + webmsgok = (trflags & NOWEBMSG) == 0, + forcebungle = (trflags & FORCEBUNGLE) != 0, + plunged = (trflags & TOOKPLUNGE) != 0, + adj_pit = conjoined_pits(trap, t_at(u.ux0,u.uy0), TRUE); #ifdef STEED int steed_article = ARTICLE_THE; #endif @@ -655,7 +655,7 @@ unsigned trflags; a_your[trap->madeby_u], defsyms[trap_to_defsym(ttype)].explanation); /* then proceed to normal trap effect */ - } else if (already_seen) { + } else if (already_seen && !forcetrap) { if ((Levitation || Flying) && (ttype == PIT || ttype == SPIKED_PIT || ttype == HOLE || ttype == BEAR_TRAP)) { @@ -783,7 +783,7 @@ unsigned trflags; break; case SQKY_BOARD: /* stepped on a squeaky board */ - if (Levitation || Flying) { + if ((Levitation || Flying) && !forcetrap) { if (!Blind) { seetrap(trap); if (Hallucination) @@ -799,7 +799,7 @@ unsigned trflags; break; case BEAR_TRAP: - if(Levitation || Flying) break; + if ((Levitation || Flying) && !forcetrap) break; feeltrap(trap); if(amorphous(youmonst.data) || is_whirly(youmonst.data) || unsolid(youmonst.data)) { @@ -1179,7 +1179,7 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); unsigned steed_mid = 0; struct obj *saddle = 0; #endif - if (Levitation || Flying) { + if ((Levitation || Flying) && !forcetrap) { if (!already_seen && rn2(3)) break; feeltrap(trap); pline("%s %s in a pile of soil below you.", @@ -3205,23 +3205,31 @@ struct trap *ttmp; } /* Replace trap with object(s). Helge Hafting */ -STATIC_OVL void -cnv_trap_obj(otyp, cnt, ttmp) +void +cnv_trap_obj(otyp, cnt, ttmp, bury_it) int otyp; int cnt; struct trap *ttmp; +boolean bury_it; { struct obj *otmp = mksobj(otyp, TRUE, FALSE); - otmp->quan=cnt; + + otmp->quan = cnt; otmp->owt = weight(otmp); /* Only dart traps are capable of being poisonous */ if (otyp != DART) otmp->opoisoned = 0; place_object(otmp, ttmp->tx, ttmp->ty); - /* Sell your own traps only... */ - if (ttmp->madeby_u) sellobj(otmp, ttmp->tx, ttmp->ty); - stackobj(otmp); + if (bury_it) { + /* magical digging first disarms this trap, then will unearth it */ + (void) bury_an_obj(otmp); + } else { + /* Sell your own traps only... */ + if (ttmp->madeby_u) sellobj(otmp, ttmp->tx, ttmp->ty); + stackobj(otmp); + } newsym(ttmp->tx, ttmp->ty); + if (u.utrap && ttmp->tx == u.ux && ttmp->ty == u.uy) u.utrap = 0; deltrap(ttmp); } @@ -3389,7 +3397,7 @@ struct trap *ttmp; } else { if (ttmp->ttyp == BEAR_TRAP) { You("disarm %s bear trap.", the_your[ttmp->madeby_u]); - cnv_trap_obj(BEARTRAP, 1, ttmp); + cnv_trap_obj(BEARTRAP, 1, ttmp, FALSE); } else /* if (ttmp->ttyp == WEB) */ { You("succeed in removing %s web.", the_your[ttmp->madeby_u]); deltrap(ttmp); @@ -3407,7 +3415,7 @@ struct trap *ttmp; if (fails < 2) return fails; You("disarm %s land mine.", the_your[ttmp->madeby_u]); - cnv_trap_obj(LAND_MINE, 1, ttmp); + cnv_trap_obj(LAND_MINE, 1, ttmp, FALSE); return 1; } @@ -3458,7 +3466,7 @@ int otyp; if (fails < 2) return fails; You("disarm %s trap.", the_your[ttmp->madeby_u]); - cnv_trap_obj(otyp, 50-rnl(50), ttmp); + cnv_trap_obj(otyp, 50-rnl(50), ttmp, FALSE); return 1; }