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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
334
src/dig.c
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
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