split g into multiple structures

The consolidation of global variables from scattered source
files into decl.c and declared in decl.h was begun in 3.7.0.
Their placement in common files was done for centralized
initialization and potential re-initialization during a
"play again" scenario.

It wasn't really necessary for all of them to be housed in a
single huge structure to meet the "play again" requirement,
and the single huge structure has been a little unwieldy when
it comes to maintenance.

Following this commit, instead of one single extremely large structure
named 'g' to house all of the relocated global variables, they
are distributed into several ga through gz.

To make things easy for the developer, each variable is placed
into the struct corresponding to the starting letter of the variable.
That way, no lookup is required in order to know which struct houses
a particular variable, it is a simple match to the starting letter
for all the centralized global variables.

A global variable named 'amulets', would be found in ga.
    ga.amulets
     ^ ^
A global varable named 'move', would be found in gm.
    gm.moves
     ^ ^
A global variable named 'val_for_n_or_more' would be found in gv.
    gv.val_for_n_or_more
     ^ ^
A global variable named 'youmonst' would be found in gy.
    gy.youmonst
     ^ ^
This commit is contained in:
nhmall
2022-11-29 21:53:21 -05:00
parent e64ed2859d
commit 02a48aa8cf
193 changed files with 10764 additions and 10148 deletions

View File

@@ -85,9 +85,9 @@ hack_artifacts(void)
artilist[ART_EXCALIBUR].role = NON_PM;
/* Fix up the quest artifact */
if (g.urole.questarti) {
artilist[g.urole.questarti].alignment = alignmnt;
artilist[g.urole.questarti].role = Role_switch;
if (gu.urole.questarti) {
artilist[gu.urole.questarti].alignment = alignmnt;
artilist[gu.urole.questarti].role = Role_switch;
}
return;
}
@@ -500,7 +500,7 @@ restrict_name(struct obj *otmp, const char *name)
if (!objects[otyp].oc_name_known
&& (odesc = OBJ_DESCR(objects[otyp])) != 0) {
obj_shuffle_range(otyp, &lo, &hi);
for (i = g.bases[ocls]; i < NUM_OBJECTS; i++) {
for (i = gb.bases[ocls]; i < NUM_OBJECTS; i++) {
if (objects[i].oc_class != ocls)
break;
if (!objects[i].oc_name_known
@@ -651,7 +651,7 @@ set_artifact_intrinsic(struct obj *otmp, boolean on, long wp_mask)
if (mask && wp_mask == W_ART && !on) {
/* find out if some other artifact also confers this intrinsic;
if so, leave the mask alone */
for (obj = g.invent; obj; obj = obj->nobj) {
for (obj = gi.invent; obj; obj = obj->nobj) {
if (obj != otmp && obj->oartifact) {
art = get_artifact(obj);
if (art && art->cary.adtyp == dtyp) {
@@ -672,7 +672,7 @@ set_artifact_intrinsic(struct obj *otmp, boolean on, long wp_mask)
spfx = (wp_mask != W_ART) ? oart->spfx : oart->cspfx;
if (spfx && wp_mask == W_ART && !on) {
/* don't change any spfx also conferred by other artifacts */
for (obj = g.invent; obj; obj = obj->nobj)
for (obj = gi.invent; obj; obj = obj->nobj)
if (obj != otmp && obj->oartifact) {
art = get_artifact(obj);
if (art)
@@ -694,7 +694,7 @@ set_artifact_intrinsic(struct obj *otmp, boolean on, long wp_mask)
* when restoring a game
*/
(void) make_hallucinated((long) !on,
g.program_state.restoring ? FALSE : TRUE,
gp.program_state.restoring ? FALSE : TRUE,
wp_mask);
}
if (spfx & SPFX_ESP) {
@@ -726,10 +726,10 @@ set_artifact_intrinsic(struct obj *otmp, boolean on, long wp_mask)
if (spec_m2(otmp)) {
if (on) {
EWarn_of_mon |= wp_mask;
g.context.warntype.obj |= spec_m2(otmp);
gc.context.warntype.obj |= spec_m2(otmp);
} else {
EWarn_of_mon &= ~wp_mask;
g.context.warntype.obj &= ~spec_m2(otmp);
gc.context.warntype.obj &= ~spec_m2(otmp);
}
see_monsters();
} else {
@@ -763,7 +763,7 @@ set_artifact_intrinsic(struct obj *otmp, boolean on, long wp_mask)
u.xray_range = 3;
else
u.xray_range = -1;
g.vision_full_recalc = 1;
gv.vision_full_recalc = 1;
}
if ((spfx & SPFX_REFLECT) && (wp_mask & W_WEP)) {
if (on)
@@ -808,7 +808,7 @@ touch_artifact(struct obj *obj, struct monst *mon)
if (!oart)
return 1;
yours = (mon == &g.youmonst);
yours = (mon == &gy.youmonst);
/* all quest artifacts are self-willed; if this ever changes, `badclass'
will have to be extended to explicitly include quest artifacts */
self_willed = ((oart->spfx & SPFX_INTEL) != 0);
@@ -907,7 +907,7 @@ spec_applies(const struct artifact *weap, struct monst *mtmp)
if (!(weap->spfx & (SPFX_DBONUS | SPFX_ATTK)))
return (weap->attk.adtyp == AD_PHYS);
yours = (mtmp == &g.youmonst);
yours = (mtmp == &gy.youmonst);
ptr = mtmp->data;
if (weap->spfx & SPFX_DMONS) {
@@ -919,7 +919,7 @@ spec_applies(const struct artifact *weap, struct monst *mtmp)
} else if (weap->spfx & SPFX_DFLAG2) {
return ((ptr->mflags2 & weap->mtype)
|| (yours
&& ((!Upolyd && (g.urace.selfmask & weap->mtype))
&& ((!Upolyd && (gu.urace.selfmask & weap->mtype))
|| ((weap->mtype & M2_WERE) && u.ulycn >= LOW_PM))));
} else if (weap->spfx & SPFX_DALIGN) {
return yours ? (u.ualign.type != weap->alignment)
@@ -986,15 +986,15 @@ spec_dbon(struct obj *otmp, struct monst *mon, int tmp)
if (!weap || (weap->attk.adtyp == AD_PHYS /* check for `NO_ATTK' */
&& weap->attk.damn == 0 && weap->attk.damd == 0))
g.spec_dbon_applies = FALSE;
gs.spec_dbon_applies = FALSE;
else if (is_art(otmp, ART_GRIMTOOTH))
/* Grimtooth has SPFX settings to warn against elves but we want its
damage bonus to apply to all targets, so bypass spec_applies() */
g.spec_dbon_applies = TRUE;
gs.spec_dbon_applies = TRUE;
else
g.spec_dbon_applies = spec_applies(weap, mon);
gs.spec_dbon_applies = spec_applies(weap, mon);
if (g.spec_dbon_applies)
if (gs.spec_dbon_applies)
return weap->attk.damd ? rnd((int) weap->attk.damd) : max(tmp, 1);
return 0;
}
@@ -1145,8 +1145,8 @@ Mb_hit(struct monst *magr, /* attacker */
{
struct permonst *old_uasmon;
const char *verb;
boolean youattack = (magr == &g.youmonst),
youdefend = (mdef == &g.youmonst),
boolean youattack = (magr == &gy.youmonst),
youdefend = (mdef == &gy.youmonst),
resisted = FALSE, do_stun, do_confuse, result;
int attack_indx, fakeidx, scare_dieroll = MB_MAX_DIEROLL / 2;
@@ -1156,14 +1156,14 @@ Mb_hit(struct monst *magr, /* attacker */
scare_dieroll /= (1 << (mb->spe / 3));
/* if target successfully resisted the artifact damage bonus,
reduce overall likelihood of the assorted special effects */
if (!g.spec_dbon_applies)
if (!gs.spec_dbon_applies)
dieroll += 1;
/* might stun even when attempting a more severe effect, but
in that case it will only happen if the other effect fails;
extra damage will apply regardless; 3.4.1: sometimes might
just probe even when it hasn't been enchanted */
do_stun = (max(mb->spe, 0) < rn2(g.spec_dbon_applies ? 11 : 7));
do_stun = (max(mb->spe, 0) < rn2(gs.spec_dbon_applies ? 11 : 7));
/* the special effects also boost physical damage; increments are
generally cumulative, but since the stun effect is based on a
@@ -1202,7 +1202,7 @@ Mb_hit(struct monst *magr, /* attacker */
/* now perform special effects */
switch (attack_indx) {
case MB_INDEX_CANCEL:
old_uasmon = g.youmonst.data;
old_uasmon = gy.youmonst.data;
/* No mdef->mcan check: even a cancelled monster can be polymorphed
* into a golem, and the "cancel" effect acts as if some magical
* energy remains in spellcasting defenders to be absorbed later.
@@ -1212,13 +1212,13 @@ Mb_hit(struct monst *magr, /* attacker */
} else {
do_stun = FALSE;
if (youdefend) {
if (g.youmonst.data != old_uasmon)
if (gy.youmonst.data != old_uasmon)
*dmgptr = 0; /* rehumanized, so no more damage */
if (u.uenmax > 0) {
u.uenmax--;
if (u.uen > 0)
u.uen--;
g.context.botl = TRUE;
gc.context.botl = TRUE;
You("lose magical energy!");
}
} else {
@@ -1229,7 +1229,7 @@ Mb_hit(struct monst *magr, /* attacker */
if (u.uenmax > u.uenpeak)
u.uenpeak = u.uenmax;
u.uen++;
g.context.botl = TRUE;
gc.context.botl = TRUE;
You("absorb magical energy!");
}
}
@@ -1242,9 +1242,9 @@ Mb_hit(struct monst *magr, /* attacker */
resisted = TRUE;
} else {
nomul(-3);
g.multi_reason = "being scared stiff";
g.nomovemsg = "";
if (magr && magr == u.ustuck && sticks(g.youmonst.data)) {
gm.multi_reason = "being scared stiff";
gn.nomovemsg = "";
if (magr && magr == u.ustuck && sticks(gy.youmonst.data)) {
set_ustuck((struct monst *) 0);
You("release %s!", mon_nam(magr));
}
@@ -1336,8 +1336,8 @@ artifact_hit(
int *dmgptr, /* output */
int dieroll) /* needed for Magicbane and vorpal blades */
{
boolean youattack = (magr == &g.youmonst);
boolean youdefend = (mdef == &g.youmonst);
boolean youattack = (magr == &gy.youmonst);
boolean youdefend = (mdef == &gy.youmonst);
boolean vis = (!youattack && magr && cansee(magr->mx, magr->my))
|| (!youdefend && cansee(mdef->mx, mdef->my))
|| (youattack && engulfing_u(mdef) && !Blind);
@@ -1367,12 +1367,12 @@ artifact_hit(
if (attacks(AD_FIRE, otmp)) {
if (realizes_damage)
pline_The("fiery blade %s %s%c",
!g.spec_dbon_applies
!gs.spec_dbon_applies
? "hits"
: (mdef->data == &mons[PM_WATER_ELEMENTAL])
? "vaporizes part of"
: "burns",
hittee, !g.spec_dbon_applies ? '.' : '!');
hittee, !gs.spec_dbon_applies ? '.' : '!');
if (!rn2(4))
(void) destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
if (!rn2(4))
@@ -1388,8 +1388,8 @@ artifact_hit(
if (attacks(AD_COLD, otmp)) {
if (realizes_damage)
pline_The("ice-cold blade %s %s%c",
!g.spec_dbon_applies ? "hits" : "freezes", hittee,
!g.spec_dbon_applies ? '.' : '!');
!gs.spec_dbon_applies ? "hits" : "freezes", hittee,
!gs.spec_dbon_applies ? '.' : '!');
if (!rn2(4))
(void) destroy_mitem(mdef, POTION_CLASS, AD_COLD);
return realizes_damage;
@@ -1397,9 +1397,9 @@ artifact_hit(
if (attacks(AD_ELEC, otmp)) {
if (realizes_damage)
pline_The("massive hammer hits%s %s%c",
!g.spec_dbon_applies ? "" : "! Lightning strikes",
hittee, !g.spec_dbon_applies ? '.' : '!');
if (g.spec_dbon_applies)
!gs.spec_dbon_applies ? "" : "! Lightning strikes",
hittee, !gs.spec_dbon_applies ? '.' : '!');
if (gs.spec_dbon_applies)
wake_nearto(mdef->mx, mdef->my, 4 * 4);
if (!rn2(5))
(void) destroy_mitem(mdef, RING_CLASS, AD_ELEC);
@@ -1410,10 +1410,10 @@ artifact_hit(
if (attacks(AD_MAGM, otmp)) {
if (realizes_damage)
pline_The("imaginary widget hits%s %s%c",
!g.spec_dbon_applies
!gs.spec_dbon_applies
? ""
: "! A hail of magic missiles strikes",
hittee, !g.spec_dbon_applies ? '.' : '!');
hittee, !gs.spec_dbon_applies ? '.' : '!');
return realizes_damage;
}
@@ -1422,7 +1422,7 @@ artifact_hit(
return Mb_hit(magr, mdef, otmp, dmgptr, dieroll, vis, hittee);
}
if (!g.spec_dbon_applies) {
if (!gs.spec_dbon_applies) {
/* since damage bonus didn't apply, nothing more to do;
no further attacks have side-effects on inventory */
return FALSE;
@@ -1441,7 +1441,7 @@ artifact_hit(
}
if (!youdefend) {
/* allow normal cutworm() call to add extra damage */
if (g.notonhead)
if (gn.notonhead)
return FALSE;
if (bigmonst(mdef->data)) {
@@ -1458,7 +1458,7 @@ artifact_hit(
otmp->dknown = TRUE;
return TRUE;
} else {
if (bigmonst(g.youmonst.data)) {
if (bigmonst(gy.youmonst.data)) {
pline("%s cuts deeply into you!",
magr ? Monnam(magr) : wepdesc);
*dmgptr *= 2;
@@ -1484,7 +1484,7 @@ artifact_hit(
return FALSE;
wepdesc = artilist[ART_VORPAL_BLADE].name;
if (!youdefend) {
if (!has_head(mdef->data) || g.notonhead || u.uswallow) {
if (!has_head(mdef->data) || gn.notonhead || u.uswallow) {
if (youattack)
pline("Somehow, you miss %s wildly.", mon_nam(mdef));
else if (vis)
@@ -1505,14 +1505,14 @@ artifact_hit(
otmp->dknown = TRUE;
return TRUE;
} else {
if (!has_head(g.youmonst.data)) {
if (!has_head(gy.youmonst.data)) {
pline("Somehow, %s misses you wildly.",
magr ? mon_nam(magr) : wepdesc);
*dmgptr = 0;
return TRUE;
}
if (noncorporeal(g.youmonst.data)
|| amorphous(g.youmonst.data)) {
if (noncorporeal(gy.youmonst.data)
|| amorphous(gy.youmonst.data)) {
pline("%s slices through your %s.", wepdesc,
body_part(NECK));
return TRUE;
@@ -1662,7 +1662,7 @@ arti_invoke(struct obj *obj)
if (oart->inv_prop > LAST_PROP) {
/* It's a special power, not "just" a property */
if (obj->age > g.moves) {
if (obj->age > gm.moves) {
/* the artifact is tired :-) */
You_feel("that %s %s ignoring you.", the(xname(obj)),
otense(obj, "are"));
@@ -1670,7 +1670,7 @@ arti_invoke(struct obj *obj)
obj->age += (long) d(3, 10);
return ECMD_TIME;
}
obj->age = g.moves + rnz(100);
obj->age = gm.moves + rnz(100);
switch (oart->inv_prop) {
case TAMING: {
@@ -1704,7 +1704,7 @@ arti_invoke(struct obj *obj)
make_slimed(0L, (char *) 0);
if (Blinded > creamed)
make_blinded(creamed, FALSE);
g.context.botl = TRUE;
gc.context.botl = TRUE;
break;
}
case ENERGY_BOOST: {
@@ -1716,7 +1716,7 @@ arti_invoke(struct obj *obj)
epboost = u.uenmax - u.uen;
if (epboost) {
u.uen += epboost;
g.context.botl = TRUE;
gc.context.botl = TRUE;
You_feel("re-energized.");
} else
goto nothing_special;
@@ -1757,13 +1757,13 @@ arti_invoke(struct obj *obj)
any = cg.zeroany; /* set all bits to zero */
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
/* use index+1 (cant use 0) as identifier */
for (i = num_ok_dungeons = 0; i < g.n_dgns; i++) {
if (!g.dungeons[i].dunlev_ureached)
for (i = num_ok_dungeons = 0; i < gn.n_dgns; i++) {
if (!gd.dungeons[i].dunlev_ureached)
continue;
any.a_int = i + 1;
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
ATR_NONE, clr,
g.dungeons[i].dname, MENU_ITEMFLAGS_NONE);
gd.dungeons[i].dname, MENU_ITEMFLAGS_NONE);
num_ok_dungeons++;
last_ok_dungeon = i;
}
@@ -1791,10 +1791,10 @@ arti_invoke(struct obj *obj)
* The closest level is either the entry or dunlev_ureached.
*/
newlev.dnum = i;
if (g.dungeons[i].depth_start >= depth(&u.uz))
newlev.dlevel = g.dungeons[i].entry_lev;
if (gd.dungeons[i].depth_start >= depth(&u.uz))
newlev.dlevel = gd.dungeons[i].entry_lev;
else
newlev.dlevel = g.dungeons[i].dunlev_ureached;
newlev.dlevel = gd.dungeons[i].dunlev_ureached;
if (u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev)
|| newlev.dnum == u.uz.dnum || !next_to_u()) {
@@ -1854,7 +1854,7 @@ arti_invoke(struct obj *obj)
if (mtmp->data->msound == MS_NEMESIS)
continue;
if (In_quest(&u.uz) && !g.quest_status.killed_nemesis)
if (In_quest(&u.uz) && !gq.quest_status.killed_nemesis)
chance += 10;
if (is_dprince(mtmp->data))
chance += 2;
@@ -1890,7 +1890,7 @@ arti_invoke(struct obj *obj)
iprop = u.uprops[oart->inv_prop].intrinsic;
boolean on = (eprop & W_ARTI) != 0; /* true if prop just set */
if (on && obj->age > g.moves) {
if (on && obj->age > gm.moves) {
/* the artifact is tired :-) */
u.uprops[oart->inv_prop].extrinsic ^= W_ARTI;
You_feel("that %s %s ignoring you.", the(xname(obj)),
@@ -1901,7 +1901,7 @@ arti_invoke(struct obj *obj)
} else if (!on) {
/* when turning off property, determine downtime */
/* arbitrary for now until we can tune this -dlc */
obj->age = g.moves + rnz(100);
obj->age = gm.moves + rnz(100);
}
if ((eprop & ~W_ARTI) || iprop) {
@@ -2096,9 +2096,9 @@ what_gives(long *abil)
spfx = abil_to_spfx(abil);
wornbits = (wornmask & *abil);
for (obj = g.invent; obj; obj = obj->nobj) {
for (obj = gi.invent; obj; obj = obj->nobj) {
if (obj->oartifact
&& (abil != &EWarn_of_mon || g.context.warntype.obj)) {
&& (abil != &EWarn_of_mon || gc.context.warntype.obj)) {
const struct artifact *art = get_artifact(obj);
if (art) {
@@ -2170,14 +2170,14 @@ Sting_effects(int orc_count) /* new count (warn_obj_cnt is old count); -1 is a f
if (u_wield_art(ART_STING)
|| u_wield_art(ART_ORCRIST)
|| u_wield_art(ART_GRIMTOOTH)) {
int oldstr = glow_strength(g.warn_obj_cnt),
int oldstr = glow_strength(gw.warn_obj_cnt),
newstr = glow_strength(orc_count);
if (orc_count == -1 && g.warn_obj_cnt > 0) {
if (orc_count == -1 && gw.warn_obj_cnt > 0) {
/* -1 means that blindness has just been toggled; give a
'continue' message that eventual 'stop' message will match */
pline("%s is %s.", bare_artifactname(uwep),
glow_verb(Blind ? 0 : g.warn_obj_cnt, TRUE));
glow_verb(Blind ? 0 : gw.warn_obj_cnt, TRUE));
} else if (newstr > 0 && newstr != oldstr) {
/* goto_level() -> docrt() -> see_monsters() -> Sting_effects();
if "you materialize on a different level" is pending, give
@@ -2193,10 +2193,10 @@ Sting_effects(int orc_count) /* new count (warn_obj_cnt is old count); -1 is a f
else if (oldstr == 0) /* quivers */
pline("%s %s slightly.", bare_artifactname(uwep),
otense(uwep, glow_verb(0, FALSE)));
} else if (orc_count == 0 && g.warn_obj_cnt > 0) {
} else if (orc_count == 0 && gw.warn_obj_cnt > 0) {
/* 'stop' message */
pline("%s stops %s.", bare_artifactname(uwep),
glow_verb(Blind ? 0 : g.warn_obj_cnt, TRUE));
glow_verb(Blind ? 0 : gw.warn_obj_cnt, TRUE));
}
}
}
@@ -2217,11 +2217,11 @@ retouch_object(
return 1;
}
if (touch_artifact(obj, &g.youmonst)) {
if (touch_artifact(obj, &gy.youmonst)) {
char buf[BUFSZ];
int dmg = 0, tmp;
boolean ag = (objects[obj->otyp].oc_material == SILVER && Hate_silver),
bane = bane_applies(get_artifact(obj), &g.youmonst);
bane = bane_applies(get_artifact(obj), &gy.youmonst);
/* nothing else to do if hero can successfully handle this object */
if (!ag && !bane)
@@ -2265,7 +2265,7 @@ retouch_object(
struct obj *otmp;
remove_worn_item(obj, FALSE);
for (otmp = g.invent; otmp; otmp = otmp->nobj)
for (otmp = gi.invent; otmp; otmp = otmp->nobj)
if (otmp == obj)
break;
if (!otmp)
@@ -2384,9 +2384,9 @@ retouch_equipment(int dropflag) /* 0==don't drop, 1==drop all, 2==drop weapon */
/* loss of levitation (silver ring, or Heart of Ahriman invocation)
might cause hero to lose inventory items (by dropping into lava,
for instance), so inventory traversal needs to rescan the whole
g.invent chain each time it moves on to another object; we use bypass
gi.invent chain each time it moves on to another object; we use bypass
handling to keep track of which items have already been processed */
while ((obj = nxt_unbypassed_obj(g.invent)) != 0)
while ((obj = nxt_unbypassed_obj(gi.invent)) != 0)
(void) untouchable(obj, dropit);
if (had_rings != (!!uleft + !!uright) && uarmg && uarmg->cursed)
@@ -2428,7 +2428,7 @@ count_surround_traps(coordxy x, coordxy y)
++ret;
continue;
}
for (otmp = g.level.objects[dx][dy]; otmp; otmp = otmp->nexthere)
for (otmp = gl.level.objects[dx][dy]; otmp; otmp = otmp->nexthere)
if (Is_container(otmp) && otmp->otrapped) {
++ret; /* we're counting locations, so just */
break; /* count the first one in a pile */
@@ -2455,13 +2455,13 @@ mkot_trap_warn(void)
if (!uarmg && u_wield_art(ART_MASTER_KEY_OF_THIEVERY)) {
int idx, ntraps = count_surround_traps(u.ux, u.uy);
if (ntraps != g.mkot_trap_warn_count) {
if (ntraps != gm.mkot_trap_warn_count) {
idx = min(ntraps, SIZE(heat) - 1);
pline_The("Key feels %s%c", heat[idx], (ntraps > 3) ? '!' : '.');
}
g.mkot_trap_warn_count = ntraps;
gm.mkot_trap_warn_count = ntraps;
} else
g.mkot_trap_warn_count = 0;
gm.mkot_trap_warn_count = 0;
}
/* Master Key is magic key if its bless/curse state meets our criteria:
@@ -2471,7 +2471,7 @@ is_magic_key(struct monst *mon, /* if null, non-rogue is assumed */
struct obj *obj)
{
if (is_art(obj, ART_MASTER_KEY_OF_THIEVERY)) {
if ((mon == &g.youmonst) ? Role_if(PM_ROGUE)
if ((mon == &gy.youmonst) ? Role_if(PM_ROGUE)
: (mon && mon->data == &mons[PM_ROGUE]))
return !obj->cursed; /* a rogue; non-cursed suffices for magic */
/* not a rogue; key must be blessed to behave as a magic one */
@@ -2488,8 +2488,8 @@ has_magic_key(struct monst *mon) /* if null, hero assumed */
short key = artilist[ART_MASTER_KEY_OF_THIEVERY].otyp;
if (!mon)
mon = &g.youmonst;
for (o = ((mon == &g.youmonst) ? g.invent : mon->minvent); o;
mon = &gy.youmonst;
for (o = ((mon == &gy.youmonst) ? gi.invent : mon->minvent); o;
o = nxtobj(o, key, FALSE)) {
if (is_magic_key(mon, o))
return o;