intelligent peacefuls avoid digging shop or temple walls
fix bug making random subrooms never touching the right or bottom
wall of the parent room
+if a grave is created with the corpse lying on top (bones), don't find a
+ corpse or release a zombie or mummy when digging it up
+kicking a headstone might summon a ghoul
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
extern void del_engr(struct engr *);
extern void rloc_engr(struct engr *);
extern void make_grave(coordxy, coordxy, const char *);
+extern void disturb_grave(coordxy, coordxy);
/* ### exper.c ### */
#define drawbridgemask flags /* what's underneath when the span is open */
#define looted flags /* used for throne, tree, fountain, sink, door */
#define icedpool flags /* used for ice (in case it melts) */
+#define emptygrave flags /* no corpse in grave */
/* horizonal applies to walls, doors (including sdoor); also to iron bars
even though they don't have separate symbols for horizontal and vertical */
#define blessedftn horizontal /* a fountain that grants attribs */
-#define disturbed horizontal /* a grave that has been disturbed */
+#define disturbed horizontal /* kicking or engraving on a grave's headstone
+ * has summoned a ghoul */
struct damage {
struct damage *next;
dig_up_grave(coord *cc)
{
struct obj *otmp;
+ int what_happens;
coordxy dig_x, dig_y;
if (!cc) {
} else if (Role_if(PM_SAMURAI)) {
adjalign(-sgn(u.ualign.type));
You("disturb the honorable dead!");
- } else if ((u.ualign.type == A_LAWFUL) && (u.ualign.record > -10)) {
- adjalign(-sgn(u.ualign.type));
+ } else if (u.ualign.type == A_LAWFUL) {
+ if (u.ualign.record > -10)
+ adjalign(-1);
You("have violated the sanctity of this grave!");
}
- switch (rn2(5)) {
+ /* -1: force default case for empty grave */
+ what_happens = levl[dig_x][dig_y].emptygrave ? -1 : rn2(5);
+ switch (what_happens) {
case 0:
case 1:
You("unearth a corpse.");
break;
case 2:
if (!Blind)
- pline(Hallucination ? "Dude! The living dead!"
- : "The grave's owner is very upset!");
+ pline("%s!", Hallucination ? "Dude! The living dead"
+ : "The grave's owner is very upset");
(void) makemon(mkclass(S_ZOMBIE, 0), dig_x, dig_y, MM_NOMSG);
break;
case 3:
if (!Blind)
- pline(Hallucination ? "I want my mummy!"
- : "You've disturbed a tomb!");
+ pline("%s!", Hallucination ? "I want my mummy"
+ : "You've disturbed a tomb");
(void) makemon(mkclass(S_MUMMY, 0), dig_x, dig_y, MM_NOMSG);
break;
default:
/* No corpse */
- pline_The("grave seems unused. Strange....");
+ pline_The("grave is unoccupied. Strange...");
break;
}
- levl[dig_x][dig_y].typ = ROOM, levl[dig_x][dig_y].flags = 0;
+ levl[dig_x][dig_y].typ = ROOM;
+ levl[dig_x][dig_y].emptygrave = 0; /* clear 'flags' */
+ levl[dig_x][dig_y].disturbed = 0; /* clear 'horizontal' */
del_engr_at(dig_x, dig_y);
newsym(dig_x, dig_y);
return;
(void) find_drawbridge(&x, &y);
gm.maploc = &levl[x][y];
}
+ wake_nearto(x, y, 5 * 5);
}
if (!rn2(3))
set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
pline("Crash! %s a secret door!",
/* don't "kick open" when it's locked
unless it also happens to be trapped */
- (gm.maploc->doormask & (D_LOCKED | D_TRAPPED)) == D_LOCKED
- ? "Your kick uncovers"
- : "You kick open");
+ ((gm.maploc->doormask & (D_LOCKED | D_TRAPPED))
+ == D_LOCKED) ? "Your kick uncovers" : "You kick open");
exercise(A_DEX, TRUE);
if (gm.maploc->doormask & D_TRAPPED) {
gm.maploc->doormask = D_NODOOR;
if (IS_GRAVE(gm.maploc->typ)) {
if (Levitation) {
kick_dumb(x, y);
- return ECMD_TIME;
- }
- if (rn2(4)) {
+ } else if (rn2(4)) {
+ /* minor injury */
kick_ouch(x, y, "");
- return ECMD_TIME;
- }
- exercise(A_WIS, FALSE);
- if (Role_if(PM_ARCHEOLOGIST) || Role_if(PM_SAMURAI)
- || ((u.ualign.type == A_LAWFUL) && (u.ualign.record > -10))) {
- adjalign(-sgn(u.ualign.type));
- }
- gm.maploc->typ = ROOM;
- gm.maploc->doormask = 0;
- (void) mksobj_at(ROCK, x, y, TRUE, FALSE);
- del_engr_at(x, y);
- if (Blind)
- pline("Crack! %s broke!", Something);
- else {
- pline_The("headstone topples over and breaks!");
- newsym(x, y);
+ } else if (!gm.maploc->disturbed && !rn2(2)) {
+ /* disturb the grave: summon a ghoul (once only), same as
+ when engraving */
+ disturb_grave(x, y);
+ } else {
+ /* destroy the headstone, implicitly destroying any
+ not-yet-created contents (including zombie or mummy);
+ any already created contents will still be buried here */
+ exercise(A_WIS, FALSE);
+ if (Role_if(PM_ARCHEOLOGIST) || Role_if(PM_SAMURAI)
+ || (u.ualign.type == A_LAWFUL && u.ualign.record > -10))
+ adjalign(-sgn(u.ualign.type));
+ gm.maploc->typ = ROOM;
+ gm.maploc->emptygrave = 0; /* clear 'flags' */
+ gm.maploc->disturbed = 0; /* clear 'horizontal' */
+ (void) mksobj_at(ROCK, x, y, TRUE, FALSE);
+ del_engr_at(x, y);
+ if (Blind) {
+ /* [feel this happen if Deaf?] */
+ pline("Crack! %s broke!", Something);
+ } else {
+ pline_The("headstone topples over and breaks!");
+ newsym(x, y);
+ }
}
return ECMD_TIME;
}
&& !(gm.mvitals[u.umonnum].mvflags & G_NOCORPSE)) {
/* Base corpse on race when not poly'd since original u.umonnum
is based on role, and all role monsters are human. */
- int mnum = !Upolyd ? gu.urace.mnum : u.umonnum;
+ int mnum = !Upolyd ? gu.urace.mnum : u.umonnum,
+ was_already_grave = IS_GRAVE(levl[u.ux][u.uy].typ);
corpse = mk_named_object(CORPSE, &mons[mnum], u.ux, u.uy, gp.plname);
Sprintf(pbuf, "%s, ", gp.plname);
formatkiller(eos(pbuf), sizeof pbuf - Strlen(pbuf), how, TRUE);
make_grave(u.ux, u.uy, pbuf);
+ if (IS_GRAVE(levl[u.ux][u.uy].typ && !was_already_grave))
+ levl[u.ux][u.uy].emptygrave = 1; /* corpse isn't buried */
}
pbuf[0] = '\0'; /* clear grave text; also lint suppression */
surface(u.ux, u.uy));
return ECMD_OK;
} else if (!levl[u.ux][u.uy].disturbed) {
- You("disturb the undead!");
- levl[u.ux][u.uy].disturbed = 1;
- (void) makemon(&mons[PM_GHOUL], u.ux, u.uy, NO_MM_FLAGS);
- exercise(A_WIS, FALSE);
+ /* disturb the grave: summon a ghoul, same as sometimes
+ happens when kicking; sets levl[ux][uy]->disturbed so
+ that it'll only happen once */
+ disturb_grave(u.ux, u.uy);
return ECMD_TIME;
}
}
return;
}
+/* called when kicking or engraving on a grave's headstone */
+void
+disturb_grave(coordxy x, coordxy y)
+{
+ struct rm *lev = &levl[x][y];
+
+ if (!IS_GRAVE(lev->typ)) {
+ impossible("Disturing grave that isn't a grave? (%d)", lev->typ);
+ } else if (lev->disturbed) {
+ impossible("Disturing already disturbed grave?");
+ } else {
+ You("disturb the undead!");
+ lev->disturbed = 1;
+ (void) makemon(&mons[PM_GHOUL], x, y, NO_MM_FLAGS);
+ exercise(A_WIS, FALSE);
+ }
+}
+
static const char blind_writing[][21] = {
{0x44, 0x66, 0x6d, 0x69, 0x62, 0x65, 0x22, 0x45, 0x7b, 0x71,
0x65, 0x6d, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },