Disambiguate b_trapped null bodypart value

b_trapped was treating 0 as a null value for its bodypart parameter, but
0 is actually the value of ARM, so b_trapped(..., ARM) would be treated
as intending no A_CON abuse.  Add NO_PART = -1 to the bodypart_types
enum, and use that instead of 0 as the "no body part" value in
b_trapped, so that ARM can be passed to it without any ambiguity.

aosdict identified this issue in xNetHack and handled it differently; he
added NO_PART with a value of 0, incremented the existing bodypart_types
values, and padded the body part arrays so the actual body parts would
start at index 1.  I think using NO_PART = -1 is simpler, but that's an
alternative approach that can be used instead -- it is advantageous in
that it automatically fixes any other places where 0 is assumed to be a
non-body-part value that I may have overlooked.
This commit is contained in:
Michael Meyer
2023-09-27 10:40:27 +03:00
committed by Pasi Kallinen
parent 234c0da66f
commit fa1f1134c8
7 changed files with 12 additions and 6 deletions
+1
View File
@@ -132,6 +132,7 @@ enum bhit_call_types {
/* Macros for messages referring to hands, eyes, feet, etc... */ /* Macros for messages referring to hands, eyes, feet, etc... */
enum bodypart_types { enum bodypart_types {
NO_PART = -1,
ARM = 0, ARM = 0,
EYE = 1, EYE = 1,
FACE = 2, FACE = 2,
+1 -1
View File
@@ -1640,7 +1640,7 @@ openone(coordxy zx, coordxy zy, genericptr_t num)
cvt_sdoor_to_door(&levl[zx][zy]); /* .typ = DOOR */ cvt_sdoor_to_door(&levl[zx][zy]); /* .typ = DOOR */
if (levl[zx][zy].doormask & D_TRAPPED) { if (levl[zx][zy].doormask & D_TRAPPED) {
if (distu(zx, zy) < 3) if (distu(zx, zy) < 3)
b_trapped("door", 0); b_trapped("door", NO_PART);
else else
Norep("You %s an explosion!", Norep("You %s an explosion!",
cansee(zx, zy) ? "see" : (!Deaf ? "hear" cansee(zx, zy) ? "see" : (!Deaf ? "hear"
+1 -1
View File
@@ -454,7 +454,7 @@ dig(void)
} }
if (IS_DOOR(lev->typ) && (lev->doormask & D_TRAPPED)) { if (IS_DOOR(lev->typ) && (lev->doormask & D_TRAPPED)) {
lev->doormask = D_NODOOR; lev->doormask = D_NODOOR;
b_trapped("door", 0); b_trapped("door", NO_PART);
newsym(dpx, dpy); newsym(dpx, dpy);
} }
cleanup: cleanup:
+1 -1
View File
@@ -1465,7 +1465,7 @@ consume_tin(const char *mesg)
r = tin_variety(tin, FALSE); r = tin_variety(tin, FALSE);
if (tin->otrapped || (tin->cursed && r != HOMEMADE_TIN && !rn2(8))) { if (tin->otrapped || (tin->cursed && r != HOMEMADE_TIN && !rn2(8))) {
b_trapped("tin", 0); b_trapped("tin", NO_PART);
tin = costly_tin(COST_DSTROY); tin = costly_tin(COST_DSTROY);
goto use_up_tin; goto use_up_tin;
} }
+2 -2
View File
@@ -693,7 +693,7 @@ still_chewing(coordxy x, coordxy y)
} else if (lev->typ == SDOOR) { } else if (lev->typ == SDOOR) {
if (lev->doormask & D_TRAPPED) { if (lev->doormask & D_TRAPPED) {
lev->doormask = D_NODOOR; lev->doormask = D_NODOOR;
b_trapped("secret door", 0); b_trapped("secret door", NO_PART);
} else { } else {
digtxt = "chew through the secret door."; digtxt = "chew through the secret door.";
lev->doormask = D_BROKEN; lev->doormask = D_BROKEN;
@@ -707,7 +707,7 @@ still_chewing(coordxy x, coordxy y)
} }
if (lev->doormask & D_TRAPPED) { if (lev->doormask & D_TRAPPED) {
lev->doormask = D_NODOOR; lev->doormask = D_NODOOR;
b_trapped("door", 0); b_trapped("door", NO_PART);
} else { } else {
digtxt = "chew through the door."; digtxt = "chew through the door.";
lev->doormask = D_BROKEN; lev->doormask = D_BROKEN;
+5
View File
@@ -1988,6 +1988,11 @@ mbodypart(struct monst *mon, int part)
}; };
struct permonst *mptr = mon->data; struct permonst *mptr = mon->data;
if (part <= NO_PART) {
impossible("mbodypart: bad part %d", part);
return "mystery part";
}
/* some special cases */ /* some special cases */
if (mptr->mlet == S_DOG || mptr->mlet == S_FELINE if (mptr->mlet == S_DOG || mptr->mlet == S_FELINE
|| mptr->mlet == S_RODENT || mptr == &mons[PM_OWLBEAR]) { || mptr->mlet == S_RODENT || mptr == &mons[PM_OWLBEAR]) {
+1 -1
View File
@@ -6265,7 +6265,7 @@ b_trapped(const char* item, int bodypart)
wake_nearby(); wake_nearby();
losehp(Maybe_Half_Phys(dmg), "explosion", KILLED_BY_AN); losehp(Maybe_Half_Phys(dmg), "explosion", KILLED_BY_AN);
exercise(A_STR, FALSE); exercise(A_STR, FALSE);
if (bodypart) if (bodypart != NO_PART)
exercise(A_CON, FALSE); exercise(A_CON, FALSE);
make_stunned((HStun & TIMEOUT) + (long) dmg, TRUE); make_stunned((HStun & TIMEOUT) + (long) dmg, TRUE);
} }