digging conjoined pits (trunk only)
This one turned out to be more effort than I had originally anticipated. We had a bug report requesting that zapping a wand of digging laterally while in a pit should dig beside you. That seemed like a reasonable enough request, but this ended up with the following results: - needed to check where this should not be permitted, or at least where there should be special-case code because there is something such as furniture on the surface above the dig point. - now tracks conjoined pits through new fields in the trap structure, hence the pathlevel increment. The array of 8 boolean values represents each of the 8 directions around a pit. - Previously, pits could be adjacent to each other as two individual pits, in which case moving between them results in a fall as you went into the next pit. That behavior is preserved. - Pits created either by zapping a wand of digging laterally while in a pit, or by "clearing debris" between two adjacent pits via a pick-axe, sets the conjoined fields for those two pits. You cannot create a brand new adjacent pit via pick-axe, only with the wand. - The hero can pass between conjoined pits without falling. - dighole() was hijacked for adjacent pit digging, so the ability to pass coordinates to it and its downstream functions was added (dig_up_grave() for example). dighole() does pretty much everything appropriately for this adjacent digging, more so than calling digactualhole() directly. - moving into a conjoined pit that has spikes still does damage, but less so that "falling" into the spiked pit, and you "step on" the spikes rather than falling into them. - Not done: should pits with the conjoined fields set be referred to as 'trenches' rather than pits in messages and identifications?
This commit is contained in:
122
src/trap.c
122
src/trap.c
@@ -25,6 +25,10 @@ STATIC_DCL void FDECL(launch_drop_spot, (struct obj *, XCHAR_P, XCHAR_P));
|
||||
STATIC_DCL int FDECL(mkroll_launch,
|
||||
(struct trap *,XCHAR_P,XCHAR_P,SHORT_P,long));
|
||||
STATIC_DCL boolean FDECL(isclearpath,(coord *, int, SCHAR_P, SCHAR_P));
|
||||
#if 0
|
||||
STATIC_DCL void FDECL(join_adjacent_pits, (struct trap *));
|
||||
#endif
|
||||
STATIC_DCL void FDECL(clear_conjoined_pits, (struct trap *));
|
||||
#ifdef STEED
|
||||
STATIC_OVL int FDECL(steedintrap, (struct trap *, struct obj *));
|
||||
STATIC_OVL boolean FDECL(keep_saddle_with_steedcorpse,
|
||||
@@ -223,6 +227,7 @@ register int x, y, typ;
|
||||
register struct trap *ttmp;
|
||||
register struct rm *lev;
|
||||
register boolean oldplace;
|
||||
int idx;
|
||||
|
||||
if ((ttmp = t_at(x,y)) != 0) {
|
||||
if (ttmp->ttyp == MAGIC_PORTAL) return (struct trap *)0;
|
||||
@@ -267,6 +272,8 @@ register int x, y, typ;
|
||||
case PIT:
|
||||
case SPIKED_PIT:
|
||||
case TRAPDOOR:
|
||||
for (idx = 0; idx < 8; ++idx)
|
||||
ttmp->conjoined[idx] = FALSE;
|
||||
lev = &levl[x][y];
|
||||
if (*in_rooms(x, y, SHOPBASE) &&
|
||||
((typ == HOLE || typ == TRAPDOOR) ||
|
||||
@@ -629,6 +636,7 @@ unsigned trflags;
|
||||
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);
|
||||
#ifdef STEED
|
||||
int steed_article = ARTICLE_THE;
|
||||
#endif
|
||||
@@ -659,9 +667,9 @@ unsigned trflags;
|
||||
return;
|
||||
}
|
||||
if(!Fumbling && ttype != MAGIC_PORTAL &&
|
||||
ttype != ANTI_MAGIC && !forcebungle && !plunged &&
|
||||
ttype != ANTI_MAGIC && !forcebungle && !plunged && !adj_pit &&
|
||||
(!rn2(5) ||
|
||||
((ttype == PIT || ttype == SPIKED_PIT) && is_clinger(youmonst.data)))) {
|
||||
((ttype == PIT || ttype == SPIKED_PIT) && is_clinger(youmonst.data)))) {
|
||||
You("escape %s %s.",
|
||||
(ttype == ARROW_TRAP && !trap->madeby_u) ? "an" :
|
||||
a_your[trap->madeby_u],
|
||||
@@ -938,8 +946,12 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
|
||||
"poor", SUPPRESS_SADDLE, FALSE));
|
||||
} else
|
||||
#endif
|
||||
Strcpy(verbbuf, plunged ? "plunge" : "fall");
|
||||
You("%s into %s pit!", verbbuf, a_your[trap->madeby_u]);
|
||||
if (adj_pit) {
|
||||
You("move into an adjacent pit.");
|
||||
} else {
|
||||
Strcpy(verbbuf, plunged ? "plunge" : "fall");
|
||||
You("%s into %s pit!", verbbuf, a_your[trap->madeby_u]);
|
||||
}
|
||||
}
|
||||
/* wumpus reference */
|
||||
if (Role_if(PM_RANGER) && !trap->madeby_u && !trap->once &&
|
||||
@@ -953,13 +965,14 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
|
||||
const char *predicament = "on a set of sharp iron spikes";
|
||||
#ifdef STEED
|
||||
if (u.usteed) {
|
||||
pline("%s lands %s!",
|
||||
pline("%s %s %s!",
|
||||
upstart(x_monnam(u.usteed, steed_article,
|
||||
"poor", SUPPRESS_SADDLE, FALSE)),
|
||||
adj_pit ? "steps" : "lands",
|
||||
predicament);
|
||||
} else
|
||||
#endif
|
||||
You("land %s!", predicament);
|
||||
You("%s %s!", adj_pit ? "step" : "land", predicament);
|
||||
}
|
||||
u.utrap = rn1(6,2);
|
||||
u.utraptype = TT_PIT;
|
||||
@@ -967,24 +980,29 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
|
||||
if (!steedintrap(trap, (struct obj *)0)) {
|
||||
#endif
|
||||
if (ttype == SPIKED_PIT) {
|
||||
losehp(Maybe_Half_Phys(rnd(10)),
|
||||
losehp(Maybe_Half_Phys(rnd(adj_pit ? 6 : 10)),
|
||||
plunged ? "deliberately plunged into a pit of iron spikes" :
|
||||
adj_pit ? "stepped into a pit of iron spikes" :
|
||||
"fell into a pit of iron spikes",
|
||||
NO_KILLER_PREFIX);
|
||||
if (!rn2(6))
|
||||
poisoned("spikes", A_STR, "fall onto poison spikes",
|
||||
poisoned("spikes", A_STR,
|
||||
adj_pit ? "stepping on poison spikes" :
|
||||
"fall onto poison spikes",
|
||||
8, FALSE);
|
||||
} else
|
||||
losehp(Maybe_Half_Phys(rnd(6)),
|
||||
plunged ? "deliberately plunged into a pit" :
|
||||
"fell into a pit",
|
||||
NO_KILLER_PREFIX);
|
||||
} else {
|
||||
if (!adj_pit)
|
||||
losehp(Maybe_Half_Phys(rnd(6)),
|
||||
plunged ? "deliberately plunged into a pit" :
|
||||
"fell into a pit",
|
||||
NO_KILLER_PREFIX);
|
||||
}
|
||||
if (Punished && !carried(uball)) {
|
||||
unplacebc();
|
||||
ballfall();
|
||||
placebc();
|
||||
}
|
||||
selftouch("Falling, you");
|
||||
if (!adj_pit) selftouch("Falling, you");
|
||||
vision_full_recalc = 1; /* vision limits change */
|
||||
exercise(A_STR, FALSE);
|
||||
exercise(A_DEX, FALSE);
|
||||
@@ -3956,6 +3974,7 @@ register struct trap *trap;
|
||||
{
|
||||
register struct trap *ttmp;
|
||||
|
||||
clear_conjoined_pits(trap);
|
||||
if(trap == ftrap)
|
||||
ftrap = ftrap->ntrap;
|
||||
else {
|
||||
@@ -3965,6 +3984,81 @@ register struct trap *trap;
|
||||
dealloc_trap(trap);
|
||||
}
|
||||
|
||||
boolean
|
||||
conjoined_pits(trap2, trap1, u_entering_trap2)
|
||||
struct trap *trap2, *trap1;
|
||||
boolean u_entering_trap2;
|
||||
{
|
||||
int dx, dy, diridx, adjidx;
|
||||
if (!trap1 || !trap2) return FALSE;
|
||||
if (!isok(trap2->tx,trap2->ty) || !isok(trap1->tx,trap1->ty) ||
|
||||
!(trap2->ttyp == PIT || trap2->ttyp == SPIKED_PIT) ||
|
||||
!(trap1->ttyp == PIT || trap1->ttyp == SPIKED_PIT) ||
|
||||
(u_entering_trap2 && !(u.utrap && u.utraptype == TT_PIT)))
|
||||
return FALSE;
|
||||
dx = sgn(trap2->tx - trap1->tx);
|
||||
dy = sgn(trap2->ty - trap1->ty);
|
||||
for (diridx = 0; diridx < 8; diridx++)
|
||||
if (xdir[diridx] == dx && ydir[diridx] == dy)
|
||||
break;
|
||||
/* diridx is valid if < 8 */
|
||||
if (diridx < 8) {
|
||||
adjidx = (diridx + 4) % 8;
|
||||
if (trap1->conjoined[diridx] && trap2->conjoined[adjidx])
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
clear_conjoined_pits(trap)
|
||||
struct trap *trap;
|
||||
{
|
||||
int tmp, adj, x, y;
|
||||
struct trap *t;
|
||||
if (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) {
|
||||
for(tmp = 0; tmp < 8; ++tmp) {
|
||||
if (trap->conjoined[tmp]) {
|
||||
x = trap->tx + xdir[tmp];
|
||||
y = trap->ty + ydir[tmp];
|
||||
t = t_at(x,y);
|
||||
if (isok(x,y) && t &&
|
||||
(t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
|
||||
adj = (tmp + 4) % 8;
|
||||
t->conjoined[adj] = FALSE;
|
||||
}
|
||||
trap->conjoined[tmp] = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Mark all neighboring pits as conjoined pits.
|
||||
* (currently not called from anywhere)
|
||||
*/
|
||||
STATIC_OVL void
|
||||
join_adjacent_pits(trap)
|
||||
struct trap *trap;
|
||||
{
|
||||
struct trap *t;
|
||||
int tmp, x, y;
|
||||
if (!trap) return;
|
||||
for(tmp = 0; tmp < 8; ++tmp) {
|
||||
x = trap->tx + xdir[tmp];
|
||||
y = trap->ty + ydir[tmp];
|
||||
if (isok(x,y)) {
|
||||
if (((t = t_at(x,y)) != 0) &&
|
||||
(t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
|
||||
trap->conjoined[tmp] = TRUE;
|
||||
join_adjacent_pits(t);
|
||||
} else trap->conjoined[tmp] = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns TRUE if you escaped a pit and are standing on the precipice.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user