From: nhmall Date: Wed, 5 Jun 2019 12:08:32 +0000 (-0400) Subject: Merge branch 'NetHack-3.6' X-Git-Tag: NetHack-3.7.0_WIP~390 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bfc44455377b7e97428de3e9754fb0e98e66d37d;p=nethack Merge branch 'NetHack-3.6' --- bfc44455377b7e97428de3e9754fb0e98e66d37d diff --cc include/decl.h index 497463ae4,5ebaa326e..d07cc3ef4 --- a/include/decl.h +++ b/include/decl.h @@@ -380,6 -429,15 +380,13 @@@ struct plinemsg_type /* 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 diff --cc src/files.c index c7b81b2e0,92940c9b0..d56e10496 --- a/src/files.c +++ b/src/files.c @@@ -2889,10 -2946,10 +2889,10 @@@ struct obj *obj /* 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); diff --cc src/hack.c index 1bbaf44d9,74a13af98..9c08be267 --- a/src/hack.c +++ b/src/hack.c @@@ -2895,18 -2896,26 +2895,26 @@@ voi 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()) */ diff --cc src/makemon.c index b5af919cd,b2cb2c8a1..9d36a3835 --- a/src/makemon.c +++ b/src/makemon.c @@@ -1120,6 -1120,7 +1120,7 @@@ int mmflags 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)) diff --cc src/mkmaze.c index 9b157750e,2a11ba4ed..5f09d1bb3 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@@ -1390,10 -1400,10 +1390,10 @@@ 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) + if (!g.wportal) set_wportal(); vision_recalc(2); @@@ -1518,8 -1528,8 +1518,8 @@@ /* 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 */ diff --cc src/mkobj.c index 7501158f8,5f98fe34e..1cdf8426f --- a/src/mkobj.c +++ b/src/mkobj.c @@@ -1389,6 -1389,19 +1389,19 @@@ register struct obj *otmp return (!!otmp->blessed - !!otmp->cursed); } + /* 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 && moves > 1L) ++ 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. diff --cc src/mon.c index a385eb7a4,e281cb392..670a8945a --- a/src/mon.c +++ b/src/mon.c @@@ -2683,10 -2692,11 +2690,11 @@@ struct monst *mon 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) diff --cc src/objnam.c index b74ffafdf,5e51bee9b..73f1dc7d4 --- a/src/objnam.c +++ b/src/objnam.c @@@ -444,10 -449,13 +444,13 @@@ unsigned cxn_flags; /* bitmask of CXN_x */ 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; diff --cc src/pickup.c index 19be7a71b,77356b1fe..123fb7065 --- a/src/pickup.c +++ b/src/pickup.c @@@ -2489,20 -2506,18 +2493,18 @@@ boolean more_containers; /* True iff #l } 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:'. */ diff --cc src/polyself.c index eb5d10326,3f33c8e9b..87143cb61 --- a/src/polyself.c +++ b/src/polyself.c @@@ -158,8 -162,8 +158,8 @@@ STATIC_OVL voi 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) { @@@ -179,9 -183,10 +179,10 @@@ 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); @@@ -628,7 -633,8 +629,8 @@@ int mntmp /* 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) diff --cc src/potion.c index e80d3a068,a07fcd0d8..e6891ffdb --- a/src/potion.c +++ b/src/potion.c @@@ -182,8 -185,15 +182,15 @@@ const char *msg if (msg) pline("%s", msg); } - if (!Slimed) + if (!Slimed) { dealloc_killer(find_delayed_killer(SLIMED)); + /* fake appearance is set late in turn-to-slime countdown */ - if (youmonst.m_ap_type == M_AP_MONSTER - && youmonst.mappearance == PM_GREEN_SLIME) { - youmonst.m_ap_type = M_AP_NOTHING; - youmonst.mappearance = 0; ++ 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 */ diff --cc src/teleport.c index 24a4bd186,61ca40fa7..4ed074c41 --- a/src/teleport.c +++ b/src/teleport.c @@@ -59,16 -62,26 +59,26 @@@ unsigned gpflags mdat = mtmp->data; if (is_pool(x, y) && !ignorewater) { + /* [what about Breathless?] */ - if (mtmp == &youmonst) + if (mtmp == &g.youmonst) - return (Levitation || Flying || Wwalking || Swimming - || Amphibious); + 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) diff --cc src/timeout.c index 971503d73,54a2943c3..05f14fa92 --- a/src/timeout.c +++ b/src/timeout.c @@@ -399,21 -399,32 +399,32 @@@ struct kinfo *kptr * [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 */ diff --cc src/zap.c index 755fcc4d2,724dc3189..aa53e0f84 --- a/src/zap.c +++ b/src/zap.c @@@ -1891,9 -1901,9 +1893,9 @@@ struct obj *obj, *otmp (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; @@@ -2486,22 -2497,39 +2489,39 @@@ boolean ordinary 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: