distinguish global variables that get written to savefile

The g? structs had a mix of variables that were written to
the savefile, and those that were not.

For better clarity and to distinguish those that end up in
the savefile, relocate some g? variables that get written
directly to the savefile into different structs.

This updates EDITLEVEL, although technically it probably
didn't need to, since savefile contents are not changing.

Details:

    gb.bases            -> svb.bases
    gb.bbubbles         -> svb.bbubbles
    gb.branches         -> svb.branches
    gc.context          -> svc.context
    gd.disco            -> svd.disco
    gd.dndest           -> svd.dndest
    gd.doors            -> svd.doors
    gd.doors_alloc      -> svd.doors_alloc
    gd.dungeon_topology -> svd.dungeon_topology
    gd.dungeons         -> svd.dungeons
    ge.exclusion_zones  -> sve.exclusion_zones
    gh.hackpid          -> svh.hackpid
    gi.inv_pos          -> svi.inv_pos
    gk.killer           -> svk.killer
    gl.lastseentyp      -> svl.lastseentyp
    gl.level            -> svl.level
    gl.level_info       -> svl.level_info
    gm.mapseenchn       -> svm.mapseenchn
    gm.moves            -> svm.moves
    gm.mvitals          -> svm.mvitals
    gn.n_dgns           -> svn.n_dgns
    gn.n_regions        -> svn.n_regions
    gn.nroom            -> svn.nroom
    go.oracle_cnt       -> svo.oracle_cnt
    gp.pl_character     -> svp.pl_character
    gp.pl_fruit         -> svp.pl_fruit
    gp.plname           -> svp.plname
    gp.program_state    -> svp.program_state
    gq.quest_status     -> svq.quest_status
    gr.rooms            -> svr.rooms
    gs.sp_levchn        -> svs.sp_levchn
    gs.spl_book         -> svs.spl_book
    gt.timer_id         -> svt.timer_id
    gt.tune             -> svt.tune
    gu.updest           -> svu.updest
    gx.xmax             -> svx.xmax
    gx.xmin             -> svx.xmin
    gy.ymax             -> svy.ymax
    gy.ymin             -> svy.ymin

Related note:
There are some pointer variables that are heads of chains that were not
moved from 'g?' to 'sv?', because they are not actually written to the
savefile directly, but the objects/monst/trap/lightsource/timer in the
chains they point to are. That can be changed, if desired.
Examples: gi.invent, gm.migrating_objs, gb.billobjs, gm.migrating_mons,
          gf.ftrap, gl.light_base, gt.timer_base
This commit is contained in:
nhmall
2024-07-13 14:57:50 -04:00
parent 0e4083153c
commit 6c0ae092c6
174 changed files with 3502 additions and 3305 deletions

126
src/mon.c
View File

@@ -40,8 +40,8 @@ extern const struct shclass shtypes[]; /* defined in shknam.c */
#define LEVEL_SPECIFIC_NOCORPSE(mdat) \
(Is_rogue_level(&u.uz) \
|| !gl.level.flags.deathdrops \
|| (gl.level.flags.graveyard && is_undead(mdat) && rn2(3)))
|| !svl.level.flags.deathdrops \
|| (svl.level.flags.graveyard && is_undead(mdat) && rn2(3)))
#if 0
@@ -98,7 +98,7 @@ sanity_check_single_mon(
#endif
return;
}
if (chk_geno && (gm.mvitals[mndx].mvflags & G_GENOD) != 0)
if (chk_geno && (svm.mvitals[mndx].mvflags & G_GENOD) != 0)
impossible("genocided %s in play (%s)",
pmname(mptr, Mgender(mtmp)), msg);
if (mtmp->mtame && !mtmp->mpeaceful)
@@ -255,7 +255,7 @@ mon_sanity_check(void)
if (x != u.ux || y != u.uy)
impossible("steed (%s) claims to be at <%d,%d>?",
fmt_ptr((genericptr_t) mtmp), x, y);
} else if (gl.level.monsters[x][y] != mtmp) {
} else if (svl.level.monsters[x][y] != mtmp) {
impossible("mon (%s) at <%d,%d> is not there!",
fmt_ptr((genericptr_t) mtmp), x, y);
} else if (mtmp->wormno) {
@@ -271,7 +271,7 @@ mon_sanity_check(void)
for (x = 1; x < COLNO; x++)
for (y = 0; y < ROWNO; y++)
if ((mtmp = gl.level.monsters[x][y]) != 0) {
if ((mtmp = svl.level.monsters[x][y]) != 0) {
for (m = fmon; m; m = m->nmon)
if (m == mtmp)
break;
@@ -530,7 +530,7 @@ pm_to_cham(int mndx)
|| is_reviver((mon)->data) \
/* normally quest leader will be unique, */ \
/* but he or she might have been polymorphed */ \
|| (mon)->m_id == gq.quest_status.leader_m_id \
|| (mon)->m_id == svq.quest_status.leader_m_id \
/* special cancellation handling for these */ \
|| (dmgtype((mon)->data, AD_SEDU) || dmgtype((mon)->data, AD_SSEX)))
@@ -866,7 +866,7 @@ make_corpse(struct monst *mtmp, unsigned int corpseflags)
default:
#endif
default_1:
if (gm.mvitals[mndx].mvflags & G_NOCORPSE) {
if (svm.mvitals[mndx].mvflags & G_NOCORPSE) {
return (struct obj *) 0;
} else {
corpstatflags |= CORPSTAT_INIT;
@@ -890,7 +890,7 @@ default_1:
/* if polymorph or undead turning has killed this monster,
prevent the same attack beam from hitting its corpse */
if (gc.context.bypasses)
if (svc.context.bypasses)
bypass_obj(obj);
if (has_mgivenname(mtmp))
@@ -1010,7 +1010,7 @@ minliquid_core(struct monst *mtmp)
hero to create lava beneath a monster, so the !mon_moving
case is not expected to happen (and we haven't made a
player-against-monster variation of the message above) */
if (gc.context.mon_moving)
if (svc.context.mon_moving)
mondead(mtmp); /* no corpse */
else
xkilled(mtmp, XKILL_NOMSG);
@@ -1046,7 +1046,7 @@ minliquid_core(struct monst *mtmp)
return 0;
}
if (cansee(mtmp->mx, mtmp->my)) {
if (gc.context.mon_moving)
if (svc.context.mon_moving)
pline_mon(mtmp, "%s drowns.", Monnam(mtmp));
else
/* hero used fire to melt ice that monster was on */
@@ -1058,7 +1058,7 @@ minliquid_core(struct monst *mtmp)
pline("%s sinks as %s rushes in and flushes you out.",
Monnam(mtmp), hliquid("water"));
}
if (gc.context.mon_moving)
if (svc.context.mon_moving)
mondied(mtmp); /* ok to leave corpse despite water */
else
xkilled(mtmp, XKILL_NOMSG);
@@ -1102,7 +1102,7 @@ mcalcmove(
else if (mon->mspeed == MFAST)
mmove = (4 * mmove + 2) / 3;
if (mon == u.usteed && u.ugallop && gc.context.mv) {
if (mon == u.usteed && u.ugallop && svc.context.mv) {
/* increase movement by a factor of 1.5; also increase variance of
movement speed (if it's naturally 24, we don't want it to always
become 36) */
@@ -1176,7 +1176,7 @@ movemon_singlemon(struct monst *mtmp)
if (u.utotype
#ifdef SAFERHANGUP
/* or if the program has lost contact with the user */
|| gp.program_state.done_hup
|| svp.program_state.done_hup
#endif
) {
gs.somebody_can_move = FALSE;
@@ -1191,9 +1191,9 @@ movemon_singlemon(struct monst *mtmp)
mon->isgd flag so that dmonsfree() will get rid of mon) */
if (mtmp->isgd && !mtmp->mx && !(mtmp->mstate & MON_MIGRATING)) {
/* parked at <0,0>; eventually isgd should get set to false */
if (gm.moves > mtmp->mlstmv) {
if (svm.moves > mtmp->mlstmv) {
(void) gd_move(mtmp);
mtmp->mlstmv = gm.moves;
mtmp->mlstmv = svm.moves;
}
return FALSE;
}
@@ -1218,7 +1218,7 @@ movemon_singlemon(struct monst *mtmp)
vision_recalc(0); /* vision! */
/* reset obj bypasses before next monster moves */
if (gc.context.bypasses)
if (svc.context.bypasses)
clear_bypasses();
clear_splitobjs();
if (minliquid(mtmp))
@@ -1291,7 +1291,7 @@ movemon(void)
if (any_light_source())
gv.vision_full_recalc = 1; /* in case a mon moved w/ a light source */
/* reset obj bypasses after last monster has moved */
if (gc.context.bypasses)
if (svc.context.bypasses)
clear_bypasses();
clear_splitobjs();
/* remove dead monsters; dead vault guard will be left at <0,0>
@@ -1432,7 +1432,7 @@ meatmetal(struct monst *mtmp)
return 0;
/* Eats topmost metal object if it is there */
for (otmp = gl.level.objects[mtmp->mx][mtmp->my]; otmp;
for (otmp = svl.level.objects[mtmp->mx][mtmp->my]; otmp;
otmp = otmp->nexthere) {
/* Don't eat indigestible/choking/inappropriate objects */
if ((mtmp->data == &mons[PM_RUST_MONSTER] && !is_rustprone(otmp))
@@ -1505,7 +1505,7 @@ meatobj(struct monst* mtmp) /* for gelatinous cubes */
/* eat organic objects, including cloth and wood, if present;
engulf others, except huge rocks and metal attached to player
[despite comment at top, doesn't assume that eater is a g-cube] */
for (otmp = gl.level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
for (otmp = svl.level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
otmp2 = otmp->nexthere;
/* avoid special items; once hero picks them up, they'll cease
@@ -1820,7 +1820,7 @@ mpickstuff(struct monst *mtmp)
if (!could_reach_item(mtmp, mtmp->mx, mtmp->my))
return FALSE;
for (otmp = gl.level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
for (otmp = svl.level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
otmp2 = otmp->nexthere;
/* avoid special items; once hero picks them up, they'll cease
@@ -2277,7 +2277,7 @@ mfndpos(
}
/* Note: ALLOW_SANCT only prevents movement, not
attack, into a temple. */
if (gl.level.flags.has_temple && *in_rooms(nx, ny, TEMPLE)
if (svl.level.flags.has_temple && *in_rooms(nx, ny, TEMPLE)
&& !*in_rooms(x, y, TEMPLE)
&& in_your_sanctuary((struct monst *) 0, nx, ny)) {
if (!(flag & ALLOW_SANCT))
@@ -2457,8 +2457,8 @@ replmon(struct monst *mtmp, struct monst *mtmp2)
}
mtmp->minvent = 0;
/* before relmon(mtmp), because it could clear polearm.hitmon */
if (gc.context.polearm.hitmon == mtmp)
gc.context.polearm.hitmon = mtmp2;
if (svc.context.polearm.hitmon == mtmp)
svc.context.polearm.hitmon = mtmp2;
/* remove the old monster from the map and from `fmon' list */
relmon(mtmp, (struct monst **) 0);
@@ -2621,14 +2621,14 @@ staticfn void
mon_leaving_level(struct monst *mon)
{
coordxy mx = mon->mx, my = mon->my;
boolean onmap = (isok(mx, my) && gl.level.monsters[mx][my] == mon);
boolean onmap = (isok(mx, my) && svl.level.monsters[mx][my] == mon);
/* to prevent an infinite relobj-flooreffects-hmon-killed loop */
mon->mtrapped = 0;
unstuck(mon); /* mon is not swallowing or holding you nor held by you */
/* vault guard might be at <0,0> */
if (onmap || mon == gl.level.monsters[0][0]) {
if (onmap || mon == svl.level.monsters[0][0]) {
if (mon->wormno)
remove_worm(mon);
else
@@ -2650,8 +2650,8 @@ mon_leaving_level(struct monst *mon)
newsym(mx, my);
}
/* if mon is a remembered target, forget it since it isn't here anymore */
if (mon == gc.context.polearm.hitmon)
gc.context.polearm.hitmon = (struct monst *) 0;
if (mon == svc.context.polearm.hitmon)
svc.context.polearm.hitmon = (struct monst *) 0;
}
/* 'mtmp' is going away; remove effects of mtmp from other data structures */
@@ -2789,7 +2789,7 @@ lifesaved_monster(struct monst *mtmp)
/* equip replacement amulet, if any, on next move */
check_gear_next_turn(mtmp);
surviver = !(gm.mvitals[monsndx(mtmp->data)].mvflags & G_GENOD);
surviver = !(svm.mvitals[monsndx(mtmp->data)].mvflags & G_GENOD);
mtmp->mcanmove = 1;
mtmp->mfrozen = 0;
if (mtmp->mtame && !mtmp->isminion) {
@@ -2818,7 +2818,7 @@ vamprises(struct monst *mtmp)
int mndx = mtmp->cham;
if (ismnum(mndx) && mndx != monsndx(mtmp->data)
&& !(gm.mvitals[mndx].mvflags & G_GENOD)) {
&& !(svm.mvitals[mndx].mvflags & G_GENOD)) {
coord new_xy;
char buf[BUFSZ];
/* alternate message phrasing for some monster types */
@@ -2890,7 +2890,7 @@ RESTORE_WARNING_FORMAT_NONLITERAL
staticfn void
logdeadmon(struct monst *mtmp, int mndx)
{
int howmany = gm.mvitals[mndx].died;
int howmany = svm.mvitals[mndx].died;
if (mndx == PM_MEDUSA && howmany == 1) {
record_achievement(ACH_MEDU); /* also generates a livelog event */
@@ -2899,7 +2899,7 @@ logdeadmon(struct monst *mtmp, int mndx)
|| (mtmp->isshk && !mtmp->mrevived)) {
char shkdetail[QBUFSZ];
const char *mkilled;
boolean herodidit = !gc.context.mon_moving;
boolean herodidit = !svc.context.mon_moving;
/*
* livelog event; unique_corpstat() includes the Wizard and
@@ -3010,7 +3010,7 @@ mondead(struct monst *mtmp)
set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT]);
/*
* gm.mvitals[].died does double duty as total number of dead monsters
* svm.mvitals[].died does double duty as total number of dead monsters
* and as experience factor for the player killing more monsters.
* this means that a dragon dying by other means reduces the
* experience the player gets for killing a dragon directly; this
@@ -3020,16 +3020,16 @@ mondead(struct monst *mtmp)
* for rings of conflict and such.
*/
mndx = monsndx(mtmp->data);
if (gm.mvitals[mndx].died < 255)
gm.mvitals[mndx].died++;
if (svm.mvitals[mndx].died < 255)
svm.mvitals[mndx].died++;
/* if it's a (possibly polymorphed) quest leader, mark him as dead */
if (mtmp->m_id == gq.quest_status.leader_m_id)
gq.quest_status.leader_is_dead = TRUE;
if (mtmp->m_id == svq.quest_status.leader_m_id)
svq.quest_status.leader_is_dead = TRUE;
#ifdef MAIL_STRUCTURES
/* if the mail daemon dies, no more mail delivery. -3. */
if (mndx == PM_MAIL_DAEMON)
gm.mvitals[mndx].mvflags |= G_GENOD;
svm.mvitals[mndx].mvflags |= G_GENOD;
#endif
if (mtmp->data->mlet == S_KOP) {
@@ -3092,9 +3092,9 @@ corpse_chance(
if (was_swallowed && magr) {
if (magr == &gy.youmonst) {
There("is an explosion in your %s!", body_part(STOMACH));
Sprintf(gk.killer.name, "%s explosion",
Sprintf(svk.killer.name, "%s explosion",
s_suffix(pmname(mdat, Mgender(mon))));
losehp(Maybe_Half_Phys(tmp), gk.killer.name, KILLED_BY_AN);
losehp(Maybe_Half_Phys(tmp), svk.killer.name, KILLED_BY_AN);
} else {
You_hear("an explosion.");
magr->mhp -= tmp;
@@ -3466,7 +3466,7 @@ xkilled(
int otyp;
/* illogical but traditional "treasure drop" */
if (!rn2(6) && !(gm.mvitals[mndx].mvflags & G_NOCORPSE)
if (!rn2(6) && !(svm.mvitals[mndx].mvflags & G_NOCORPSE)
/* no extra item from swallower or steed */
&& (x != u.ux || y != u.uy)
/* no extra item from kops--too easy to abuse */
@@ -3551,19 +3551,19 @@ xkilled(
}
/* give experience points */
tmp = experience(mtmp, (int) gm.mvitals[mndx].died);
tmp = experience(mtmp, (int) svm.mvitals[mndx].died);
more_experienced(tmp, 0);
newexplevel(); /* will decide if you go up */
/* adjust alignment points */
if (mtmp->m_id == gq.quest_status.leader_m_id) { /* REAL BAD! */
if (mtmp->m_id == svq.quest_status.leader_m_id) { /* REAL BAD! */
adjalign(-(u.ualign.record + (int) ALIGNLIM / 2));
u.ugangr += 7; /* instantly become "extremely" angry */
change_luck(-20);
pline("That was %sa bad idea...",
u.uevent.qcompleted ? "probably " : "");
} else if (mdat->msound == MS_NEMESIS) { /* Real good! */
if (!gq.quest_status.killed_leader)
if (!svq.quest_status.killed_leader)
adjalign((int) (ALIGNLIM / 4));
} else if (mdat->msound == MS_GUARDIAN) { /* Bad */
adjalign(-(int) (ALIGNLIM / 8));
@@ -3637,7 +3637,7 @@ vamp_stone(struct monst *mtmp)
/* this only happens if shapeshifted */
if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)
&& !(gm.mvitals[mndx].mvflags & G_GENOD)) {
&& !(svm.mvitals[mndx].mvflags & G_GENOD)) {
char buf[BUFSZ];
/* construct a format string before transformation */
@@ -3749,10 +3749,10 @@ elemental_clog(struct monst *mon)
if (In_endgame(&u.uz)) {
m1 = m2 = m3 = m4 = m5 = zm = (struct monst *) 0;
if (!msgmv || (gm.moves - msgmv) > 200L) {
if (!msgmv || (svm.moves - msgmv) > 200L) {
if (!msgmv || rn2(2))
You_feel("besieged.");
msgmv = gm.moves;
msgmv = svm.moves;
}
/*
* m1 an elemental from another plane.
@@ -4164,7 +4164,7 @@ setmangry(struct monst *mtmp, boolean via_attack)
qst_guardians_respond();
/* make other peaceful monsters react */
if (!gc.context.mon_moving)
if (!svc.context.mon_moving)
peacefuls_respond(mtmp);
}
@@ -4192,7 +4192,7 @@ wakeup(struct monst *mtmp, boolean via_attack)
have to lose his disguise */
if (M_AP_TYPE(mtmp) != M_AP_MONSTER)
seemimic(mtmp);
} else if (gc.context.forcefight && !gc.context.mon_moving
} else if (svc.context.forcefight && !svc.context.mon_moving
&& mtmp->mundetected) {
mtmp->mundetected = 0;
newsym(mtmp->mx, mtmp->my);
@@ -4236,11 +4236,11 @@ wake_nearto_core(coordxy x, coordxy y, int distance, boolean petcall)
mtmp->msleeping = 0; /* wake indeterminate sleep */
if (!(mtmp->data->geno & G_UNIQ))
mtmp->mstrategy &= ~STRAT_WAITMASK; /* wake 'meditation' */
if (gc.context.mon_moving || !petcall)
if (svc.context.mon_moving || !petcall)
continue;
if (mtmp->mtame) {
if (!mtmp->isminion)
EDOG(mtmp)->whistletime = gm.moves;
EDOG(mtmp)->whistletime = svm.moves;
/* Fix up a pet who is stuck "fleeing" its master */
mon_track_clear(mtmp);
}
@@ -4520,7 +4520,7 @@ maybe_unhide_at(coordxy x, coordxy y)
if (undetected
&& ((hides_under(mtmp->data)
&& (!OBJ_AT(x, y) || trapped
|| !can_hide_under_obj(gl.level.objects[x][y])))
|| !can_hide_under_obj(svl.level.objects[x][y])))
|| (mtmp->data->mlet == S_EEL && !is_pool(x, y))))
(void) hideunder(mtmp);
}
@@ -4557,7 +4557,7 @@ hideunder(struct monst *mtmp)
}
} else if (hides_under(mtmp->data)
/* hider-underers only hide under objects */
&& (otmp = gl.level.objects[x][y]) != 0
&& (otmp = svl.level.objects[x][y]) != 0
/* most things can be hidden under, but not all */
&& can_hide_under_obj(otmp)
/* aquatic creatures don't reach here; other swimmers
@@ -4767,7 +4767,7 @@ pickvampshape(struct monst *mon)
/* return to base form if chosen poly target has been genocided
or randomly if already in an alternate form (to prevent always
switching back and forth between bat and fog) */
if ((gm.mvitals[mndx].mvflags & G_GENOD) != 0
if ((svm.mvitals[mndx].mvflags & G_GENOD) != 0
|| (mon->data != &mons[mon->cham] && !rn2(4)))
return mon->cham;
@@ -4779,7 +4779,7 @@ staticfn boolean
isspecmon(struct monst *mon)
{
return (mon->isshk || mon->ispriest || mon->isgd
|| mon->m_id == gq.quest_status.leader_m_id);
|| mon->m_id == svq.quest_status.leader_m_id);
}
/* restrict certain special monsters (shopkeepers, aligned priests,
@@ -5028,7 +5028,7 @@ accept_newcham_form(struct monst *mon, int mndx)
if (mndx == NON_PM)
return 0;
mdat = &mons[mndx];
if ((gm.mvitals[mndx].mvflags & G_GENOD) != 0)
if ((svm.mvitals[mndx].mvflags & G_GENOD) != 0)
return 0;
if (is_placeholder(mdat))
return 0;
@@ -5129,7 +5129,7 @@ newcham(
} while (--tryct > 0);
if (!tryct)
return 0;
} else if (gm.mvitals[monsndx(mdat)].mvflags & G_GENOD)
} else if (svm.mvitals[monsndx(mdat)].mvflags & G_GENOD)
return 0; /* passed in mdat is genocided */
if (mdat == olddata)
@@ -5275,7 +5275,7 @@ newcham(
mon_break_armor(mtmp, polyspot);
if (!(mtmp->misc_worn_check & W_ARMG))
mselftouch(mtmp, "No longer petrify-resistant, ",
!gc.context.mon_moving);
!svc.context.mon_moving);
check_gear_next_turn(mtmp);
/* This ought to re-test can_carry() on each item in the inventory
@@ -5309,7 +5309,7 @@ newcham(
/* old form might not have been affected by Elbereth but perhaps the
new form is */
if (gc.context.mon_moving) {
if (svc.context.mon_moving) {
/* give 'mtmp' a new chance to pinpoint hero's location */
if (!u_at(mtmp->mux, mtmp->muy))
set_apparxy(mtmp);
@@ -5390,8 +5390,8 @@ dead_species(int m_idx, boolean egg)
*/
/* assert(ismnum(m_idx)); */
alt_idx = egg ? big_to_little(m_idx) : m_idx;
return (boolean) ((gm.mvitals[m_idx].mvflags & G_GENOD) != 0
|| (gm.mvitals[alt_idx].mvflags & G_GENOD) != 0);
return (boolean) ((svm.mvitals[m_idx].mvflags & G_GENOD) != 0
|| (svm.mvitals[alt_idx].mvflags & G_GENOD) != 0);
}
/* kill off any eggs of genocided monsters */
@@ -5449,8 +5449,8 @@ kill_genocided_monsters(void)
continue;
mndx = monsndx(mtmp->data);
kill_cham = (ismnum(mtmp->cham)
&& (gm.mvitals[mtmp->cham].mvflags & G_GENOD));
if ((gm.mvitals[mndx].mvflags & G_GENOD) || kill_cham) {
&& (svm.mvitals[mtmp->cham].mvflags & G_GENOD));
if ((svm.mvitals[mndx].mvflags & G_GENOD) || kill_cham) {
if (ismnum(mtmp->cham) && !kill_cham)
(void) newcham(mtmp, (struct permonst *) 0, NC_SHOW_MSG);
else
@@ -5463,7 +5463,7 @@ kill_genocided_monsters(void)
kill_eggs(gi.invent);
kill_eggs(fobj);
kill_eggs(gm.migrating_objs);
kill_eggs(gl.level.buriedobjlist);
kill_eggs(svl.level.buriedobjlist);
}
void