allow a parent function to restrict use of placebc

placebc was triggering an impossible sometimes on the plane of
water

It turned out to be because movebubbles issued an
unplacebc(), but a downstream function called
placebc(), so when movebubbles() issued its own
placebc() there was a problem.

The downstream function that beat movebubbles to the placebc()
turned out to be unstuck(). There could be others.
This commit is contained in:
nhmall
2019-06-04 21:18:46 -04:00
parent 05a0d10097
commit a65682f58e
5 changed files with 185 additions and 42 deletions

View File

@@ -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
------------------------------------------------------------------

View File

@@ -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;

View File

@@ -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));

View File

@@ -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

View File

@@ -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;
}