digging land mines & bear traps (trunk only)
<Someone> suggested that digging down on a land mine with a pick-axe ought
to set if off. I agree; this implements that and also for bear traps. In
the bear trap case, if you dig down once trapped, you will destroy that
trap explicitly rather than replace it with a pit, so it's now possible to
escape from one without leaving another trap in your wake. Once the bear
trap is gone, further digging there will make a pit as usual. While stuck
in one, digging down poses a modest risk of harming yourself.
|You now wield a pick-axe.
|You start digging downward. A bear trap closes on your foot!
|You start digging downward. You destroy the bear trap with your pick-axe.
|You continue digging downward. You dig a pit in the floor.
|You start digging downward. You dig a hole through the floor.
|You fall through...
[It seems a bit strange that finishing a pit discards all digging context,
so that resuming within the pit in order to make a hole "starts" digging
rather than "continues" it.]
Digging down with a wand or spell will disarm these two types of traps
and then leave the corresponding object (which may or may not fall through
the resulting hole, like any other object there). Digging to the side via
magic while trapped in a pit will also disarm such traps when it encounters
them. (When not in a pit, a digging beam which simply passes over an armed
bear trap or land mine won't have any effect on the trap.) Digging to the
side via tool behaves somewhat oddly ("no room for the rubble"?) and will
probably need some tweaking before eventual release; at present it doesn't
reach adjacent traps so didn't need any land mine or bear trap handling.
I put the fixes entry in the new features section.
This commit is contained in:
68
src/dig.c
68
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 <u.ux,u.uy> */
|
||||
/* make pit at <u.ux,u.uy> */
|
||||
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();
|
||||
}
|
||||
|
||||
46
src/trap.c
46
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user