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:
nethack.allison
2006-03-19 23:59:03 +00:00
parent 3299e318ca
commit 6ef8efcefb
9 changed files with 414 additions and 65 deletions

View File

@@ -187,6 +187,7 @@ number_pad:-1 to swap function of y and z keys; z to move NW, y to zap wands
display spell retention information in the spell menu
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
Platform- and/or Interface-Specific New Features

View File

@@ -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));
E boolean FDECL(dighole, (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 *));
@@ -268,8 +268,9 @@ E void FDECL(rot_corpse, (genericptr_t, long));
E struct obj *FDECL(buried_ball, (coord *));
E void NDECL(buried_ball_to_punishment);
E void NDECL(buried_ball_to_freedom);
E schar FDECL(fillholetyp, (int, int));
E schar FDECL(fillholetyp, (int,int,BOOLEAN_P));
E void FDECL(liquid_flow, (XCHAR_P,XCHAR_P,SCHAR_P,struct trap *, const char *));
E boolean FDECL(conjoined_pits, (struct trap *,struct trap *,BOOLEAN_P));
#if 0
E void FDECL(bury_monst, (struct monst *));
E void NDECL(bury_you);

View File

@@ -13,7 +13,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
#define EDITLEVEL 26
#define EDITLEVEL 27
#define COPYRIGHT_BANNER_A \
"NetHack, Copyright 1985-2006"

View File

@@ -10,6 +10,7 @@
union vlaunchinfo {
short v_launch_otyp; /* type of object to be triggered */
coord v_launch2; /* secondary launch point (for boulders) */
boolean v_conjoined[8]; /* conjoined pit locations */
};
struct trap {
@@ -30,6 +31,7 @@ struct trap {
union vlaunchinfo vl;
#define launch_otyp vl.v_launch_otyp
#define launch2 vl.v_launch2
#define conjoined vl.v_conjoined
};
extern struct trap *ftrap;

View File

@@ -2843,7 +2843,7 @@ do_break_wand(obj)
* Adjust corresponding code in music.c for
* drum of earthquake if you alter this sequence.
*/
typ = fillholetyp(x,y);
typ = fillholetyp(x,y,FALSE);
if (typ != ROOM) {
levl[x][y].typ = typ;
liquid_flow(x, y, typ, t_at(x,y),

334
src/dig.c
View File

@@ -13,7 +13,9 @@ 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, (struct obj *,XCHAR_P,XCHAR_P));
STATIC_DCL int NDECL(dig);
STATIC_DCL void NDECL(dig_up_grave);
STATIC_DCL void FDECL(dig_up_grave, (coord *));
STATIC_DCL int FDECL(adj_pit_checks, (coord *,char *));
STATIC_DCL void FDECL(pit_flow, (struct trap *,SCHAR_P));
/* Indices returned by dig_typ() */
#define DIGTYP_UNDIGGABLE 0
@@ -274,7 +276,7 @@ dig()
if (context.digging.effort > 250 ||
(ttmp && ttmp->ttyp == HOLE)) {
(void) dighole(FALSE);
(void) dighole(FALSE, (coord *)0);
(void) memset((genericptr_t)&context.digging, 0,
sizeof (struct dig_info));
return(0); /* done with digging */
@@ -290,7 +292,7 @@ dig()
angry_priest();
}
if (dighole(TRUE)) { /* make pit at <u.ux,u.uy> */
if (dighole(TRUE, (coord *)0)) { /* make pit at <u.ux,u.uy> */
context.digging.level.dnum = 0;
context.digging.level.dlevel = -1;
}
@@ -439,8 +441,9 @@ holetime()
/* Return typ of liquid to fill a hole with, or ROOM, if no liquid nearby */
schar
fillholetyp(x,y)
fillholetyp(x,y,fill_if_any)
int x, y;
boolean fill_if_any; /* force filling if it exists at all */
{
register int x1, y1;
int lo_x = max(1,x-1), hi_x = min(x+1,COLNO-1),
@@ -459,13 +462,16 @@ int x, y;
(levl[x1][y1].typ == DRAWBRIDGE_UP &&
(levl[x1][y1].drawbridgemask & DB_UNDER) == DB_LAVA))
lava_cnt++;
pool_cnt /= 3; /* not as much liquid as the others */
if (!fill_if_any) pool_cnt /= 3; /* not as much liquid as the others */
if (lava_cnt > moat_cnt + pool_cnt && rn2(lava_cnt + 1))
if ((lava_cnt > moat_cnt + pool_cnt && rn2(lava_cnt + 1)) ||
(lava_cnt && fill_if_any))
return LAVAPOOL;
else if (moat_cnt > 0 && rn2(moat_cnt + 1))
else if ((moat_cnt > 0 && rn2(moat_cnt + 1)) ||
(moat_cnt && fill_if_any))
return MOAT;
else if (pool_cnt > 0 && rn2(pool_cnt + 1))
else if ((pool_cnt > 0 && rn2(pool_cnt + 1)) ||
(pool_cnt && fill_if_any))
return POOL;
else
return ROOM;
@@ -538,7 +544,10 @@ int ttyp;
if (ttyp == PIT) {
if(madeby_u) {
You("dig a pit in the %s.", surface_type);
if (x != u.ux || y != u.uy)
You("dig an adjacent pit.");
else
You("dig a pit in the %s.", surface_type);
if (shopdoor) pay_for_damage("ruin", FALSE);
} else if (!madeby_obj && canseemon(madeby))
pline("%s digs a pit in the %s.", Monnam(madeby), surface_type);
@@ -670,27 +679,44 @@ const char *fillmsg;
/* return TRUE if digging succeeded, FALSE otherwise */
boolean
dighole(pit_only)
dighole(pit_only, cc)
boolean pit_only;
coord *cc;
{
register struct trap *ttmp = t_at(u.ux, u.uy);
struct rm *lev = &levl[u.ux][u.uy];
register struct trap *ttmp;
struct rm *lev;
struct obj *boulder_here;
schar typ;
boolean nohole = (!Can_dig_down(&u.uz) && !lev->candig);
xchar dig_x,dig_y;
boolean nohole;
if (!cc) {
dig_x = u.ux;
dig_y = u.uy;
} else {
dig_x = cc->x;
dig_y = cc->y;
if (!isok(dig_x,dig_y)) return FALSE;
}
ttmp = t_at(dig_x, dig_y);
lev = &levl[dig_x][dig_y];
nohole = (!Can_dig_down(&u.uz) && !lev->candig);
if ((ttmp && (ttmp->ttyp == MAGIC_PORTAL || nohole)) ||
(IS_ROCK(lev->typ) && lev->typ != SDOOR &&
(lev->wall_info & W_NONDIGGABLE) != 0)) {
pline_The("%s here is too hard to dig in.", surface(u.ux,u.uy));
pline_The("%s %shere is too hard to dig in.",
surface(dig_x,dig_y),
(dig_x != u.ux || dig_y != u.uy) ? "t" : "");
} else if (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) {
} else if (is_pool(dig_x, dig_y) || is_lava(dig_x, dig_y)) {
pline_The("%s sloshes furiously for a moment, then subsides.",
is_lava(u.ux, u.uy) ? "lava" : "water");
is_lava(dig_x, dig_y) ? "lava" : "water");
wake_nearby(); /* splashing */
} else if (lev->typ == DRAWBRIDGE_DOWN ||
(is_drawbridge_wall(u.ux, u.uy) >= 0)) {
(is_drawbridge_wall(dig_x, dig_y) >= 0)) {
/* drawbridge_down is the platform crossing the moat when the
bridge is extended; drawbridge_wall is the open "doorway" or
closed "door" where the portcullis/mechanism is located */
@@ -698,17 +724,19 @@ boolean pit_only;
pline_The("drawbridge seems too hard to dig through.");
return FALSE;
} else {
int x = u.ux, y = u.uy;
int x = dig_x, y = dig_y;
/* if under the portcullis, the bridge is adjacent */
(void) find_drawbridge(&x, &y);
destroy_drawbridge(x, y);
return TRUE;
}
} else if ((boulder_here = sobj_at(BOULDER, u.ux, u.uy)) != 0) {
} else if ((boulder_here = sobj_at(BOULDER, dig_x, dig_y)) != 0) {
if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT) &&
rn2(2)) {
pline_The("boulder settles into the pit.");
pline_The("boulder settles into the %spit.",
(dig_x != u.ux || dig_y != u.uy) ?
"adjacent " : "");
ttmp->ttyp = PIT; /* crush spikes */
} else {
/*
@@ -722,27 +750,28 @@ boolean pit_only;
return TRUE;
} else if (IS_GRAVE(lev->typ)) {
digactualhole(u.ux, u.uy, BY_YOU, PIT);
dig_up_grave();
digactualhole(dig_x, dig_y, BY_YOU, PIT);
dig_up_grave(cc);
return TRUE;
} else if (lev->typ == DRAWBRIDGE_UP) {
/* must be floor or ice, other cases handled above */
/* dig "pit" and let fluid flow in (if possible) */
typ = fillholetyp(u.ux,u.uy);
typ = fillholetyp(dig_x,dig_y,FALSE);
if (typ == ROOM) {
/*
* We can't dig a hole here since that will destroy
* the drawbridge. The following is a cop-out. --dlc
*/
pline_The("%s here is too hard to dig in.",
surface(u.ux, u.uy));
pline_The("%s %shere is too hard to dig in.",
surface(dig_x, dig_y),
(dig_x != u.ux || dig_y != u.uy) ? "t" : "");
return FALSE;
}
lev->drawbridgemask &= ~DB_UNDER;
lev->drawbridgemask |= (typ == LAVAPOOL) ? DB_LAVA : DB_MOAT;
liquid_flow(u.ux, u.uy, typ, ttmp,
liquid_flow(dig_x, dig_y, typ, ttmp,
"As you dig, the hole fills with %s!");
return TRUE;
@@ -754,20 +783,20 @@ boolean pit_only;
pline_The("altar is too hard to break apart.");
} else {
typ = fillholetyp(u.ux,u.uy);
typ = fillholetyp(dig_x,dig_y,FALSE);
if (typ != ROOM) {
lev->typ = typ;
liquid_flow(u.ux, u.uy, typ, ttmp,
liquid_flow(dig_x, dig_y, typ, ttmp,
"As you dig, the hole fills with %s!");
return TRUE;
}
/* finally we get to make a hole */
if (nohole || pit_only)
digactualhole(u.ux, u.uy, BY_YOU, PIT);
digactualhole(dig_x, dig_y, BY_YOU, PIT);
else
digactualhole(u.ux, u.uy, BY_YOU, HOLE);
digactualhole(dig_x, dig_y, BY_YOU, HOLE);
return TRUE;
}
@@ -776,9 +805,21 @@ boolean pit_only;
}
STATIC_OVL void
dig_up_grave()
dig_up_grave(cc)
coord *cc;
{
struct obj *otmp;
xchar dig_x, dig_y;
if (!cc) {
dig_x = u.ux;
dig_y = u.uy;
} else {
dig_x = cc->x;
dig_y = cc->y;
if (!isok(dig_x,dig_y)) return ;
}
/* Grave-robbing is frowned upon... */
exercise(A_WIS, FALSE);
@@ -797,27 +838,27 @@ dig_up_grave()
case 0:
case 1:
You("unearth a corpse.");
if (!!(otmp = mk_tt_object(CORPSE, u.ux, u.uy)))
if (!!(otmp = mk_tt_object(CORPSE, dig_x, dig_y)))
otmp->age -= 100; /* this is an *OLD* corpse */;
break;
case 2:
if (!Blind) pline(Hallucination ? "Dude! The living dead!" :
"The grave's owner is very upset!");
(void) makemon(mkclass(S_ZOMBIE,0), u.ux, u.uy, NO_MM_FLAGS);
(void) makemon(mkclass(S_ZOMBIE,0), dig_x, dig_y, NO_MM_FLAGS);
break;
case 3:
if (!Blind) pline(Hallucination ? "I want my mummy!" :
"You've disturbed a tomb!");
(void) makemon(mkclass(S_MUMMY,0), u.ux, u.uy, NO_MM_FLAGS);
(void) makemon(mkclass(S_MUMMY,0), dig_x, dig_y, NO_MM_FLAGS);
break;
default:
/* No corpse */
pline_The("grave seems unused. Strange....");
break;
}
levl[u.ux][u.uy].typ = ROOM;
del_engr_at(u.ux, u.uy);
newsym(u.ux,u.uy);
levl[dig_x][dig_y].typ = ROOM;
del_engr_at(dig_x, dig_y);
newsym(dig_x,dig_y);
return;
}
@@ -878,7 +919,7 @@ struct obj *obj;
{
register int rx, ry;
register struct rm *lev;
struct trap *trap;
struct trap *trap, *trap_with_u;
int dig_target;
boolean ispick = is_pick(obj);
const char *verbing = ispick ? "digging" : "chopping";
@@ -946,6 +987,29 @@ struct obj *obj;
if (vibrate) losehp(Maybe_Half_Phys(2),
"axing a hard object", KILLED_BY);
}
else if (u.utrap && u.utraptype == TT_PIT && trap &&
(trap_with_u = t_at(u.ux, u.uy)) &&
(trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) &&
!conjoined_pits(trap, trap_with_u, FALSE)) {
int idx;
for (idx = 0; idx < 8; idx++) {
if (xdir[idx] == u.dx && ydir[idx] == u.dy)
break;
}
/* idx is valid if < 8 */
if (idx < 8) {
int adjidx = (idx + 4) % 8;
trap_with_u->conjoined[idx] = TRUE;
trap->conjoined[adjidx] = TRUE;
pline(
"You clear some debris from between the pits.");
}
}
else if (u.utrap && u.utraptype == TT_PIT &&
(trap_with_u = t_at(u.ux, u.uy))) {
You("swing %s, but the rubble has no place to go.",
yobjnam(obj, (char *)0));
}
else
You("swing %s through thin air.",
yobjnam(obj, (char *)0));
@@ -1159,8 +1223,10 @@ zap_dig()
struct rm *room;
struct monst *mtmp;
struct obj *otmp;
int zx, zy, digdepth;
boolean shopdoor, shopwall, maze_dig;
struct trap *trap_with_u = (struct trap *)0;
int zx, zy, diridx, digdepth, flow_x, flow_y;
boolean shopdoor, shopwall, maze_dig, pitdig = FALSE, pitflow = FALSE;
/*
* Original effect (approximately):
* from CORR: dig until we pierce a wall
@@ -1168,6 +1234,7 @@ zap_dig()
* an ACCESSIBLE place.
* Currently: dig for digdepth positions;
* also down on request of Lennart Augustsson.
* 3.5.0: from a PIT: dig one adjacent pit.
*/
if (u.uswallow) {
@@ -1204,7 +1271,7 @@ zap_dig()
newsym(u.ux, u.uy);
} else {
watch_dig((struct monst *)0, u.ux, u.uy, TRUE);
(void) dighole(FALSE);
(void) dighole(FALSE, (coord *)0);
}
}
return;
@@ -1215,6 +1282,14 @@ zap_dig()
maze_dig = level.flags.is_maze_lev && !Is_earthlevel(&u.uz);
zx = u.ux + u.dx;
zy = u.uy + u.dy;
if(u.utrap && u.utraptype == TT_PIT && (trap_with_u = t_at(u.ux, u.uy))) {
pitdig = TRUE;
for (diridx = 0; diridx < 8; diridx++) {
if (xdir[diridx] == u.dx && ydir[diridx] == u.dy)
break;
/* diridx is valid if < 8 */
}
}
digdepth = rn1(18, 8);
tmp_at(DISP_BEAM, cmap_to_glyph(S_digbeam));
while (--digdepth >= 0) {
@@ -1222,7 +1297,42 @@ zap_dig()
room = &levl[zx][zy];
tmp_at(zx,zy);
delay_output(); /* wait a little bit */
if (closed_door(zx, zy) || room->typ == SDOOR) {
if (pitdig) { /* we are already in a pit if this is true */
coord cc;
struct trap *adjpit = t_at(zx,zy);
if ((diridx < 8) &&
!conjoined_pits(adjpit, trap_with_u, FALSE)) {
digdepth = 0; /* limited to the adjacent location only */
if (!(adjpit && (adjpit->ttyp == PIT ||
adjpit->ttyp == SPIKED_PIT))) {
char buf[BUFSZ];
cc.x = zx; cc.y = zy;
if (!adj_pit_checks(&cc, buf)) {
if (buf[0]) pline("%s", buf);
} else {
/* this can also result in a pool at zx,zy */
dighole(TRUE, &cc);
adjpit = t_at(zx,zy);
}
}
if (adjpit && (adjpit->ttyp == PIT ||
adjpit->ttyp == SPIKED_PIT)) {
int adjidx = (diridx + 4) % 8;
trap_with_u->conjoined[diridx] = TRUE;
adjpit->conjoined[adjidx] = TRUE;
flow_x = zx;
flow_y = zy;
pitflow = TRUE;
}
if (is_pool(zx,zy) || is_lava(zx,zy)) {
flow_x = zx - u.dx;
flow_y = zy - u.dy;
pitflow = TRUE;
}
break;
}
} else if (closed_door(zx, zy) || room->typ == SDOOR) {
if (*in_rooms(zx,zy,SHOPBASE)) {
add_damage(zx, zy, 400L);
shopdoor = TRUE;
@@ -1291,11 +1401,149 @@ zap_dig()
zy += u.dy;
} /* while */
tmp_at(DISP_END,0); /* closing call */
if (pitflow) {
struct trap *ttmp = t_at(flow_x, flow_y);
if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT)) {
schar filltyp = fillholetyp(ttmp->tx, ttmp->ty, TRUE);
if (filltyp != ROOM)
pit_flow(ttmp, filltyp);
}
}
if (shopdoor || shopwall)
pay_for_damage(shopdoor ? "destroy" : "dig into", FALSE);
return;
}
/*
* This checks what is on the surface above the
* location where an adjacent pit might be created if
* you're zapping a wand of digging laterally while
* down in the pit.
*/
STATIC_OVL int
adj_pit_checks(cc, msg)
coord *cc;
char *msg;
{
int ltyp;
struct rm *room;
const char *foundation_msg =
"The foundation is too hard to dig through from this angle.";
if (!cc) return FALSE;
if (!isok(cc->x,cc->y)) return FALSE;
if (msg) *msg = '\0';
room = &levl[cc->x][cc->y];
ltyp = room->typ;
if (is_pool(cc->x, cc->y) || is_lava(cc->x, cc->y)) {
/* this is handled by the caller after we return FALSE */
return FALSE;
} else if (closed_door(cc->x, cc->y) || room->typ == SDOOR) {
/* We reject this here because dighole() isn't
prepared to deal with this case */
Strcpy(msg, foundation_msg);
return FALSE;
} else if (IS_WALL(ltyp)) {
/* if (room->wall_info & W_NONDIGGABLE) */
Strcpy(msg, foundation_msg);
return FALSE;
} else if (IS_TREE(ltyp)) { /* check trees before stone */
/* if (room->wall_info & W_NONDIGGABLE) */
Strcpy(msg, "The tree's roots glow then fade.");
return FALSE;
} else if (ltyp == STONE || ltyp == SCORR) {
if (room->wall_info & W_NONDIGGABLE) {
Strcpy(msg, "The rock glows then fades.");
return FALSE;
}
} else if (ltyp == IRONBARS) {
/* "set of iron bars" */
Strcpy(msg, "The bars go much deeper than your pit.");
#if 0
} else if (is_lava(cc->x,cc->y)) {
} else if (is_ice(cc->x,cc->y)) {
} else if (is_pool(cc->x,cc->y)) {
} else if (IS_GRAVE(ltyp)) {
#endif
#ifdef SINKS
} else if (IS_SINK(ltyp)) {
Strcpy(msg, "A tangled mass of plumbing remains below the sink.");
return FALSE;
#endif
} else if ((cc->x == xupladder && cc->y == yupladder) || /* "ladder up" */
(cc->x == xdnladder && cc->y == ydnladder)) { /* "ladder down" */
Strcpy(msg, "The ladder is unaffected.");
return FALSE;
} else {
const char *supporting = (const char *)0;
if (IS_FOUNTAIN(ltyp)) supporting = "fountain";
else if (IS_THRONE(ltyp)) supporting = "throne";
else if (IS_ALTAR(ltyp)) supporting = "altar";
else if ((cc->x == xupstair && cc->y == yupstair) ||
(cc->x == sstairs.sx && cc->y == sstairs.sy && sstairs.up))
/* "staircase up" */
supporting = "stairs";
else if ((cc->x == xdnstair && cc->y == ydnstair) ||
(cc->x == sstairs.sx && cc->y == sstairs.sy && !sstairs.up))
/* "staircase down" */
supporting = "stairs";
else if ((ltyp == DRAWBRIDGE_DOWN) || /* "lowered drawbridge" */
(ltyp == DBWALL)) /* "raised drawbridge" */
supporting = "drawbridge";
if (supporting) {
Sprintf(msg,
"The %s%ssupporting structures remain intact.",
supporting ? s_suffix(supporting) : "",
supporting ? " " : "");
return FALSE;
}
}
return TRUE;
}
/*
* Ensure that all conjoined pits fill up.
*/
STATIC_OVL void
pit_flow(trap, filltyp)
struct trap *trap;
schar filltyp;
{
int idx;
if (trap && (filltyp != ROOM) &&
(trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) {
struct trap t;
t = *trap;
levl[trap->tx][trap->ty].typ = filltyp;
liquid_flow(trap->tx, trap->ty, filltyp, trap,
(trap->tx == u.ux && trap->ty == u.uy) ?
"Suddenly %s flows in from the adjacent pit!":
(char *)0);
for(idx = 0; idx < 8; ++idx) {
if (t.conjoined[idx]) {
int x, y;
struct trap *t2;
x = t.tx + xdir[idx];
y = t.ty + ydir[idx];
t2 = t_at(x,y);
#if 0
/* cannot do this back-check; liquid_flow()
* called deltrap() which cleaned up the
* conjoined fields on both pits.
*/
if (t2 && t2->conjoined[(idx + 4) % 8])
#endif
/* recursion */
pit_flow(t2, filltyp);
}
}
}
}
struct obj *
buried_ball(cc)
coord *cc;
@@ -1651,7 +1899,7 @@ escape_tomb()
"ooze" : "phase", surface(u.ux, u.uy));
if(tunnels(youmonst.data) && !needspick(youmonst.data))
good = dighole(TRUE);
good = dighole(TRUE, (coord *)0);
else good = TRUE;
if(good) unearth_you();
}

View File

@@ -915,7 +915,7 @@ domove()
register xchar x,y;
struct trap *trap;
int wtcap;
boolean on_ice;
boolean on_ice, adj_pit = FALSE;
xchar chainx, chainy, ballx, bally; /* ball&chain new positions */
int bc_control; /* control for ball&chain */
boolean cause_delay = FALSE; /* dragging ball will skip a move */
@@ -1184,7 +1184,10 @@ domove()
}
if(u.utrap) {
if(u.utraptype == TT_PIT) {
climb_pit();
if (trap && trap->tseen &&
(trap->ttyp == PIT || trap->ttyp == SPIKED_PIT))
adj_pit = TRUE;
if (!adj_pit) climb_pit();
} else if (u.utraptype == TT_LAVA) {
if(flags.verbose) {
predicament = "stuck in the lava";
@@ -1281,7 +1284,7 @@ domove()
}
if((u.dx && u.dy) || !rn2(5)) u.utrap--;
}
return;
if (!adj_pit) return;
}
if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) {

View File

@@ -284,7 +284,7 @@ do_pit: chasm = maketrap(x,y,PIT);
* Adjust corresponding code in apply.c for
* exploding wand of digging if you alter this sequence.
*/
filltype = fillholetyp(x,y);
filltype = fillholetyp(x,y,FALSE);
if (filltype != ROOM) {
levl[x][y].typ = filltype;
liquid_flow(x, y, filltype, chasm, (char *)0);

View File

@@ -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.
*/