/* bitmask for callers of hide_unhide_msgtypes() */
#define MSGTYP_MASK_REP_SHOW ((1 << MSGTYP_NOREP) | (1 << MSGTYP_NOSHOW))
-E struct plinemsg_type *plinemsg_types;
+
+ enum bcargs {override_restriction = -1};
+ struct breadcrumbs {
+ const char *funcnm;
+ int linenum;
+ boolean in_effect;
+ };
-
#ifdef PANICTRACE
E const char *ARGV0;
#endif
/* subset of starting inventory pre-ID */
obj->dknown = 1;
if (Role_if(PM_PRIEST))
- obj->bknown = 1;
+ obj->bknown = 1; /* ok to bypass set_bknown() */
/* same criteria as lift_object()'s check for available inventory slot */
if (obj->oclass != COIN_CLASS && inv_cnt(FALSE) >= 52
- && !merge_choice(invent, obj)) {
+ && !merge_choice(g.invent, obj)) {
/* inventory overflow; can't just place & stack object since
hero isn't in position yet, so schedule for arrival later */
add_to_migration(obj);
unmul(msg_override)
const char *msg_override;
{
- multi = 0; /* caller will usually have done this already */
+ g.multi = 0; /* caller will usually have done this already */
if (msg_override)
- nomovemsg = msg_override;
- else if (!nomovemsg)
- nomovemsg = You_can_move_again;
- if (*nomovemsg) {
- pline("%s", nomovemsg);
+ g.nomovemsg = msg_override;
+ else if (!g.nomovemsg)
+ g.nomovemsg = You_can_move_again;
- if (*g.nomovemsg)
++ if (*g.nomovemsg) {
+ pline("%s", g.nomovemsg);
+ /* follow "you survived that attempt on your life" with a message
+ about current form if it's not the default; primarily for
+ life-saving while turning into green slime but is also a reminder
+ if life-saved while poly'd and Unchanging (explore or wizard mode
+ declining to die since can't be both Unchanging and Lifesaved) */
- if (Upolyd && !strncmpi(nomovemsg, "You survived that ", 18))
++ if (Upolyd && !strncmpi(g.nomovemsg, "You survived that ", 18))
+ You("are %s", an(mons[u.umonnum].mname)); /* (ignore Hallu) */
+ }
- nomovemsg = 0;
+ g.nomovemsg = 0;
u.usleep = 0;
- multi_reason = NULL;
- if (afternmv) {
- int NDECL((*f)) = afternmv;
+ g.multi_reason = NULL;
+ if (g.afternmv) {
+ int NDECL((*f)) = g.afternmv;
/* clear afternmv before calling it (to override the
encumbrance hack for levitation--see weight_cap()) */
struct monst fakemon;
cc.x = cc.y = 0; /* lint suppression */
- fakemon = zeromonst;
++ fakemon = cg.zeromonst;
fakemon.data = ptr; /* set up for goodpos */
if (!makemon_rnd_goodpos(ptr ? &fakemon : (struct monst *)0,
gpflags, &cc))
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)
+ if (!g.wportal)
set_wportal();
vision_recalc(2);
/* put attached ball&chain back */
if (Is_waterlevel(&u.uz) && Punished)
- placebc();
+ lift_covet_and_placebc(bcpin);
- vision_full_recalc = 1;
+ g.vision_full_recalc = 1;
}
/* when moving in water, possibly (1 in 3) alter the intended destination */
return (!!otmp->blessed - !!otmp->cursed);
}
- if (obj->where == OBJ_INVENT && moves > 1L)
+ /* set the object's bless/curse-state known flag */
+ void
+ set_bknown(obj, onoff)
+ struct obj *obj;
+ unsigned onoff; /* 1 or 0 */
+ {
+ if (obj->bknown != onoff) {
+ obj->bknown = onoff;
++ if (obj->where == OBJ_INVENT && g.moves > 1L)
+ update_inventory();
+ }
+ }
+
/*
* Calculate the weight of the given object. This will recursively follow
* and calculate the weight of any containers.
rloc_to(mon, mx, my); /* note: mon, not mtmp */
} else {
/* last resort - migrate mon to the next plane */
- if (Is_waterlevel(&u.uz) || Is_firelevel(&u.uz) || Is_earthlevel(&u.uz)) {
+ if (Is_waterlevel(&u.uz) || Is_firelevel(&u.uz)
+ || Is_earthlevel(&u.uz)) {
/* try sending mon on to the next plane */
xchar target_lev = 0, xyloc = 0;
- struct trap *trap = ftrap;
+ struct trap *trap = g.ftrap;
while (trap) {
if (trap->ttyp == MAGIC_PORTAL)
*/
if (!nn && ocl->oc_uses_known && ocl->oc_unique)
obj->known = 0;
- if (!Blind && !distantname)
+ if (!Blind && !g.distantname)
- obj->dknown = TRUE;
+ obj->dknown = 1;
if (Role_if(PM_PRIEST))
- obj->bknown = TRUE;
+ obj->bknown = 1; /* actively avoid set_bknown();
+ * we mustn't call update_inventory() now because
+ * it would call xname() (via doname()) recursively
+ * and could end up clobbering all the obufs... */
if (iflags.override_ID) {
known = dknown = bknown = TRUE;
} else if (obj->otrapped) {
if (held)
You("open %s...", the(xname(obj)));
- obj->lknown = 1;
(void) chest_trap(obj, HAND, FALSE);
/* even if the trap fails, you've used up this turn */
- if (multi >= 0) { /* in case we didn't become paralyzed */
+ if (g.multi >= 0) { /* in case we didn't become paralyzed */
nomul(-1);
- multi_reason = "opening a container";
- nomovemsg = "";
+ g.multi_reason = "opening a container";
+ g.nomovemsg = "";
}
- abort_looting = TRUE;
+ g.abort_looting = TRUE;
return 1;
}
- obj->lknown = 1;
- current_container = obj; /* for use by in/out_container */
+ g.current_container = obj; /* for use by in/out_container */
/*
* From here on out, all early returns go through 'containerdone:'.
*/
polyman(fmt, arg)
const char *fmt, *arg;
{
- boolean sticky = (sticks(youmonst.data) && u.ustuck && !u.uswallow),
+ boolean sticky = (sticks(g.youmonst.data) && u.ustuck && !u.uswallow),
- was_mimicking = (U_AP_TYPE == M_AP_OBJECT);
+ was_mimicking = (U_AP_TYPE != M_AP_NOTHING);
boolean was_blind = !!Blind;
if (Upolyd) {
uunstick();
find_ac();
if (was_mimicking) {
- if (multi < 0)
+ if (g.multi < 0)
unmul("");
- youmonst.m_ap_type = M_AP_NOTHING;
- youmonst.mappearance = 0;
+ g.youmonst.m_ap_type = M_AP_NOTHING;
++ g.youmonst.mappearance = 0;
}
newsym(u.ux, u.uy);
/* if becoming a non-mimic, stop mimicking anything */
if (mons[mntmp].mlet != S_MIMIC) {
/* as in polyman() */
- youmonst.m_ap_type = M_AP_NOTHING;
- youmonst.mappearance = 0;
+ g.youmonst.m_ap_type = M_AP_NOTHING;
++ g.youmonst.mappearance = 0;
}
if (is_male(&mons[mntmp])) {
if (flags.female)
if (msg)
pline("%s", msg);
}
- if (!Slimed)
+ if (!Slimed) {
dealloc_killer(find_delayed_killer(SLIMED));
- if (youmonst.m_ap_type == M_AP_MONSTER
- && youmonst.mappearance == PM_GREEN_SLIME) {
- youmonst.m_ap_type = M_AP_NOTHING;
- youmonst.mappearance = 0;
+ /* fake appearance is set late in turn-to-slime countdown */
++ if (g.youmonst.m_ap_type == M_AP_MONSTER
++ && g.youmonst.mappearance == PM_GREEN_SLIME) {
++ g.youmonst.m_ap_type = M_AP_NOTHING;
++ g.youmonst.mappearance = 0;
+ }
+ }
}
/* start or stop petrification */
mdat = mtmp->data;
if (is_pool(x, y) && !ignorewater) {
- if (mtmp == &youmonst)
+ /* [what about Breathless?] */
- return (Levitation || Flying || Wwalking || Swimming
- || Amphibious);
+ if (mtmp == &g.youmonst)
+ return (Swimming || Amphibious
+ || (!Is_waterlevel(&u.uz)
+ /* water on the Plane of Water has no surface
+ so there's no way to be on or above that */
+ && (Levitation || Flying || Wwalking)));
else
- return (is_floater(mdat) || is_flyer(mdat) || is_swimmer(mdat)
- || is_clinger(mdat));
+ return (is_swimmer(mdat)
+ || (!Is_waterlevel(&u.uz)
+ && (is_floater(mdat) || is_flyer(mdat)
+ || is_clinger(mdat))));
} else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) {
return FALSE;
} else if (is_lava(x, y)) {
- if (mtmp == &g.youmonst)
+ /* 3.6.3: floating eye can levitate over lava but it avoids
+ that due the effect of the heat causing it to dry out */
+ if (mdat == &mons[PM_FLOATING_EYE])
+ return FALSE;
- else if (mtmp == &youmonst)
++ else if (mtmp == &g.youmonst)
return (Levitation || Flying
|| (Fire_resistance && Wwalking && uarmf
&& uarmf->oerodeproof)
* [formerly implicit] change of form; polymon() takes care of that.
* Temporarily ungenocide if necessary.
*/
- if (emits_light(youmonst.data))
- del_light_source(LS_MONSTER, monst_to_any(&youmonst));
- save_mvflags = mvitals[PM_GREEN_SLIME].mvflags;
- mvitals[PM_GREEN_SLIME].mvflags = save_mvflags & ~G_GENOD;
+ if (emits_light(g.youmonst.data))
+ del_light_source(LS_MONSTER, monst_to_any(&g.youmonst));
+ save_mvflags = g.mvitals[PM_GREEN_SLIME].mvflags;
+ g.mvitals[PM_GREEN_SLIME].mvflags = save_mvflags & ~G_GENOD;
+ /* become a green slime; also resets youmonst.m_ap_type+.mappearance */
(void) polymon(PM_GREEN_SLIME);
- mvitals[PM_GREEN_SLIME].mvflags = save_mvflags;
+ g.mvitals[PM_GREEN_SLIME].mvflags = save_mvflags;
done(TURNED_SLIME);
/* life-saved; even so, hero still has turned into green slime;
player may have genocided green slimes after being infected */
- if ((mvitals[PM_GREEN_SLIME].mvflags & G_GENOD) != 0) {
+ if ((g.mvitals[PM_GREEN_SLIME].mvflags & G_GENOD) != 0) {
+ char slimebuf[BUFSZ];
+
- killer.format = KILLED_BY;
- Strcpy(killer.name, "slimicide");
+ g.killer.format = KILLED_BY;
+ Strcpy(g.killer.name, "slimicide");
- /* immediately follows "OK, so you don't die." */
- pline("Yes, you do. Green slime has been genocided...");
+ /* vary the message depending upon whether life-save was due to
+ amulet or due to declining to die in explore or wizard mode */
+ Strcpy(slimebuf, "green slime has been genocided...");
+ if (iflags.last_msg == PLNMSG_OK_DONT_DIE)
+ /* follows "OK, so you don't die." and arg is second sentence */
+ pline("Yes, you do. %s", upstart(slimebuf));
+ else
+ /* follows "The medallion crumbles to dust." */
+ pline("Unfortunately, %s", slimebuf);
+ /* die again; no possibility of amulet this time */
done(GENOCIDED);
/* could be life-saved again (only in explore or wizard mode)
but green slimes are gone; just stay in current form */
(void) boxlock(obj, otmp);
if (obj_shudders(obj)) {
- boolean cover =
- ((obj == g.level.objects[u.ux][u.uy]) && u.uundetected
- && hides_under(g.youmonst.data));
- boolean cover = ((obj == level.objects[u.ux][u.uy])
++ boolean cover = ((obj == g.level.objects[u.ux][u.uy])
+ && u.uundetected
- && hides_under(youmonst.data));
++ && hides_under(g.youmonst.data));
if (cansee(obj->ox, obj->oy))
learn_it = TRUE;
learn_it = TRUE;
unpunish();
}
- if (u.utrap) { /* escape web or bear trap */
- (void) openholdingtrap(&g.youmonst, &learn_it);
- } else {
+ /* invent is hit iff hero doesn't escape from a trap */
- if (!u.utrap || !openholdingtrap(&youmonst, &learn_it)) {
++ if (!u.utrap || !openholdingtrap(&g.youmonst, &learn_it)) {
struct obj *otmp;
+ boolean boxing = FALSE;
+
/* unlock carried boxes */
- for (otmp = invent; otmp; otmp = otmp->nobj)
+ for (otmp = g.invent; otmp; otmp = otmp->nobj)
- if (Is_box(otmp))
+ if (Is_box(otmp)) {
(void) boxlock(otmp, obj);
+ boxing = TRUE;
+ }
+ if (boxing)
+ update_inventory(); /* in case any box->lknown has changed */
+
/* trigger previously escaped trapdoor */
- (void) openfallingtrap(&youmonst, TRUE, &learn_it);
+ (void) openfallingtrap(&g.youmonst, TRUE, &learn_it);
}
break;
case WAN_LOCKING:
case SPE_WIZARD_LOCK:
- if (!u.utrap) {
- (void) closeholdingtrap(&g.youmonst, &learn_it);
+ /* similar logic to opening; invent is hit iff no trap triggered */
- if (u.utrap || !closeholdingtrap(&youmonst, &learn_it)) {
++ if (u.utrap || !closeholdingtrap(&g.youmonst, &learn_it)) {
+ struct obj *otmp;
+ boolean boxing = FALSE;
+
+ /* lock carried boxes */
- for (otmp = invent; otmp; otmp = otmp->nobj)
++ for (otmp = g.invent; otmp; otmp = otmp->nobj)
+ if (Is_box(otmp)) {
+ (void) boxlock(otmp, obj);
+ boxing = TRUE;
+ }
+ if (boxing)
+ update_inventory(); /* in case any box->lknown has changed */
}
break;
case WAN_DIGGING: