diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 4df27bcc5..392c7e196 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -51,7 +51,8 @@ similar perm_invent issue when lock state known and/or contents known become blessed scroll of remove curse read while confused might be shown to operate on itself by perm_invent after player is told that it has disappeared fix memory leak if corpse auto-revival attempt failed ("you feel less hassled") - +allow a parent function to issue an an unplacebc() call that restricts + subsequent placebc() calls to that parent only Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository ------------------------------------------------------------------ diff --git a/include/decl.h b/include/decl.h index 0b7a929a1..5ebaa326e 100644 --- a/include/decl.h +++ b/include/decl.h @@ -431,6 +431,7 @@ struct plinemsg_type { E struct plinemsg_type *plinemsg_types; +enum bcargs {override_restriction = -1}; struct breadcrumbs { const char *funcnm; int linenum; diff --git a/include/extern.h b/include/extern.h index f7e762bda..5f78cb5e7 100644 --- a/include/extern.h +++ b/include/extern.h @@ -130,11 +130,19 @@ E void NDECL(ballfall); #ifndef BREADCRUMBS E void NDECL(placebc); E void NDECL(unplacebc); +E int NDECL(unplacebc_and_covet_placebc); +E void FDECL(lift_covet_and_placebc, (int)); #else E void FDECL(Placebc, (const char *, int)); E void FDECL(Unplacebc, (const char *, int)); +E int FDECL(Unplacebc_and_covet_placebc, (const char *, int)); +E void FDECL(Lift_covet_and_placebc, (int, const char *, int)); #define placebc() Placebc(__FUNCTION__, __LINE__) #define unplacebc() Unplacebc(__FUNCTION__, __LINE__) +#define unplacebc_and_covet_placebc() \ + Unplacebc_and_covet_placebc(__FUNCTION__, __LINE__) +#define lift_covet_and_placebc(x) \ + Lift_covet_and_placebc(x, __FUNCTION__, __LINE__) #endif E void FDECL(set_bc, (int)); E void FDECL(move_bc, (int, int, XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P)); diff --git a/src/ball.c b/src/ball.c index 00352e2b7..81e2d6dd2 100644 --- a/src/ball.c +++ b/src/ball.c @@ -12,10 +12,11 @@ STATIC_DCL int NDECL(bc_order); STATIC_DCL void NDECL(litter); STATIC_OVL void NDECL(placebc_core); STATIC_OVL void NDECL(unplacebc_core); +STATIC_DCL boolean FDECL(check_restriction, (int)); +static int bcrestriction = 0; #ifdef BREADCRUMBS -static struct breadcrumbs bcpbreadcrumbs = { (const char *) 0, 0, FALSE}, - bcubreadcrumbs = { (const char *) 0, 0, FALSE}; +static struct breadcrumbs bcpbreadcrumbs = {0}, bcubreadcrumbs = {0}; #endif void @@ -137,34 +138,9 @@ placebc_core() u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph; /* pick up glyph */ newsym(u.ux, u.uy); + bcrestriction = 0; } -#ifdef BREADCRUMBS -void -Placebc(funcnm, linenum) -const char *funcnm; -int linenum; -{ - if (uball && bcpbreadcrumbs.in_effect && uball->where == OBJ_FLOOR) { - impossible("placebc collision from %s:%d, already placed by %s:%d", - funcnm, linenum, - bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); - return; - } - bcpbreadcrumbs.in_effect = TRUE; - bcubreadcrumbs.in_effect = FALSE; - bcpbreadcrumbs.funcnm = funcnm; - bcpbreadcrumbs.linenum = linenum; - placebc_core(); -} -#else -void -placebc() -{ - placebc_core(); -} -#endif - STATIC_OVL void unplacebc_core() { @@ -197,33 +173,190 @@ unplacebc_core() u.bc_felt = 0; /* feel nothing */ } -#ifdef BREADCRUMBS +STATIC_OVL boolean +check_restriction(restriction) +int restriction; +{ + boolean ret = FALSE; + + if (!bcrestriction || (restriction == override_restriction)) + ret = TRUE; + else + ret = (bcrestriction == restriction) ? TRUE : FALSE; + return ret; +} + +#ifndef BREADCRUMBS +void +placebc() +{ + if (!check_restriction(0)) { +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "placebc denied, restriction in effect"); + paniclog("placebc", panicbuf); +#endif + return; + } + if (uchain && uchain->where != OBJ_FREE) { + impossible("bc already placed?"); + return; + } + placebc_core(); +} + +void +unplacebc() +{ + if (bcrestriction) { + impossible("unplacebc denied, restriction in place"); + return; + } + unplacebc_core(); +} + +int +unplacebc_and_covet_placebc() +{ + int restriction = 0; + + if (bcrestriction) { + impossible("unplacebc_and_covet_placebc denied, already restricted"); + } else { + restriction = bcrestriction = rnd(400); + unplacebc_core(); + } + return restriction; +} + +void +lift_covet_and_placebc(pin) +int pin; +{ + if (!check_restriction(pin)) { +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "lift_covet_and_placebc denied, %s", + (pin != bcrestriction) ? + "pin mismatch" : "restriction in effect"); + paniclog("placebc", panicbuf); +#endif + return; + } + if (uchain && uchain->where != OBJ_FREE) { + impossible("bc already placed?"); + return; + } + placebc_core(); +} + +#else /* BREADCRUMBS */ + +void +Placebc(funcnm, linenum) +const char *funcnm; +int linenum; +{ + if (!check_restriction(0)) { +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "Placebc denied to %s:%d, restricted by %s:%d", + funcnm, linenum, + bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); + paniclog("Placebc", panicbuf); +#endif + return; + } + if ((uchain && uchain->where != OBJ_FREE) + && bcpbreadcrumbs.in_effect) { + impossible("Placebc collision at %s:%d, already placed by %s:%d", + funcnm, linenum, + bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); + return; + } + bcpbreadcrumbs.in_effect = TRUE; + bcubreadcrumbs.in_effect = FALSE; + bcpbreadcrumbs.funcnm = funcnm; + bcpbreadcrumbs.linenum = linenum; + placebc_core(); +} + void Unplacebc(funcnm, linenum) const char *funcnm; int linenum; { -#if 0 - if (uball && bcubreadcrumbs.in_effect && uball->where == OBJ_FREE) { - impossible("unplacebc collision from %s:%d, already placed by %s:%d", + + if (bcrestriction) { + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "Unplacebc from %s:%d, when restricted to %s:%d", funcnm, linenum, bcubreadcrumbs.funcnm, bcubreadcrumbs.linenum); - return; + paniclog("Unplacebc", panicbuf); } -#endif bcpbreadcrumbs.in_effect = FALSE; bcubreadcrumbs.in_effect = TRUE; bcubreadcrumbs.funcnm = funcnm; bcubreadcrumbs.linenum = linenum; unplacebc_core(); } -#else -void -unplacebc() + +int +Unplacebc_and_covet_placebc(funcnm, linenum) +const char *funcnm; +int linenum; { - unplacebc_core(); + int restriction = 0; + + if (bcrestriction) { + impossible( + "Unplacebc_and_covet_placebc denied to %s:%d, restricted by %s:%d", + funcnm, linenum, + bcubreadcrumbs.funcnm, bcubreadcrumbs.linenum); + } else { + restriction = bcrestriction = rnd(400); + bcpbreadcrumbs.in_effect = FALSE; + bcubreadcrumbs.in_effect = TRUE; + bcubreadcrumbs.funcnm = funcnm; + bcubreadcrumbs.linenum = linenum; + unplacebc_core(); + } + return restriction; } + +void +Lift_covet_and_placebc(pin, funcnm, linenum) +int pin; +char *funcnm; +int linenum; +{ + if (!check_restriction(pin)) { +#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) + char panicbuf[BUFSZ]; + + Sprintf(panicbuf, + "Lift_covet_and_placebc denied to %s:%d, restricted by %s:%d", + funcnm, linenum, + bcpbreadcrumbs.funcnm, bcpbreadcrumbs.linenum); + paniclog("Lift_covet_and_placebc", panicbuf); #endif + return; + } + if (uchain && uchain->where != OBJ_FREE) { + impossible("bc already placed?"); + return; + } + placebc_core(); +} +#endif /* BREADCRUMBS */ /* * Return the stacking of the hero's ball & chain. This assumes that the diff --git a/src/mkmaze.c b/src/mkmaze.c index f516e6927..2a11ba4ed 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -1400,7 +1400,7 @@ movebubbles() struct bubble *b; struct container *cons; struct trap *btrap; - int x, y, i, j; + int x, y, i, j, bcpin; /* set up the portal the first time bubbles are moved */ if (!wportal) @@ -1411,7 +1411,7 @@ movebubbles() if (Is_waterlevel(&u.uz)) { /* keep attached ball&chain separate from bubble objects */ if (Punished) - unplacebc(); + bcpin = unplacebc_and_covet_placebc(); /* * Pick up everything inside of a bubble then fill all bubble @@ -1528,7 +1528,7 @@ movebubbles() /* put attached ball&chain back */ if (Is_waterlevel(&u.uz) && Punished) - placebc(); + lift_covet_and_placebc(bcpin); vision_full_recalc = 1; }