add two unused fields for hardfought save compatability
There are two hardfought code additions that render save and bones files incompatible
with the upstream NetHack-3.7, and that makes testing with hardfought
save and bones files more challenging than it needs to be, when
investigating and troubleshooting bug reports.
Add some unused fields to advance towards achieving save file parity with
hardfought, which is a significant source of play-testing for NetHack-3.7.
1) the elbereth field addition to u_conduct
This adds an unused placeholder field named 'hf_reserved1', at the appropriate
place in u_conduct to achieve struct field parity with the one in use on
hardfought.
2) hardfought adds a field to struct monst:
char former_rank[25]; /* for bones' ghost rank in their former life */
Instead of adding that to every monst, this adds a new mextra struct
named 'former', which currently contains the equivalent 25-character
field called 'rank' which can hold the content that was in the
former_rank[25] field. That way, the field will only be added when it
is needed.
A pull request https://github.com/k21971/NetHack37/pull/2 has been
done on hardfought to do it the same way (untested there as of yet).
Even though NetHack-3.7 does not utilize that information presently,
this will be a further step toward allowing hardfought-generated save
and bones files to be used for troubleshooting, without modification,
on a similar architecture running stock NetHack-3.7 code.
That savefile parity won't be achieved until the after the
hardfought pull-request mentioned above (or equivalent) is merged.
As this change will not be compatible with existing save and bones
files, it will be accompanied with an EDITLEVEL increment.
This commit is contained in:
@@ -506,6 +506,13 @@ savebones(int how, time_t when, struct obj *corpse)
|
||||
mtmp->mhp = mtmp->mhpmax = u.uhpmax;
|
||||
mtmp->female = flags.female;
|
||||
mtmp->msleeping = 1;
|
||||
if (!has_former(mtmp))
|
||||
newformer(mtmp);
|
||||
if (has_former(mtmp)) {
|
||||
Snprintf(FORMER(mtmp)->rank,
|
||||
sizeof FORMER(mtmp)->rank,
|
||||
"%s", rank());
|
||||
}
|
||||
}
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||
set_ghostly_objlist(mtmp->minvent);
|
||||
|
||||
@@ -16,7 +16,6 @@ const char *const enc_stat[] = {
|
||||
"Strained", "Overtaxed", "Overloaded"
|
||||
};
|
||||
|
||||
staticfn const char *rank(void);
|
||||
staticfn void bot_via_windowport(void);
|
||||
staticfn void stat_update_time(void);
|
||||
staticfn char *get_strength_str(void);
|
||||
@@ -361,7 +360,7 @@ rank_of(int lev, short monnum, boolean female)
|
||||
return "Player";
|
||||
}
|
||||
|
||||
staticfn const char *
|
||||
const char *
|
||||
rank(void)
|
||||
{
|
||||
return rank_of(u.ulevel, Role_switch, flags.female);
|
||||
|
||||
@@ -1070,6 +1070,28 @@ newmextra(void)
|
||||
return mextra;
|
||||
}
|
||||
|
||||
void
|
||||
newformer(struct monst *mtmp)
|
||||
{
|
||||
if (!mtmp->mextra)
|
||||
mtmp->mextra = newmextra();
|
||||
if (!FORMER(mtmp)) {
|
||||
FORMER(mtmp) = (struct former_incarnation *) alloc(
|
||||
sizeof(struct former_incarnation *));
|
||||
(void) memset((genericptr_t) FORMER(mtmp), 0,
|
||||
sizeof(struct former_incarnation *));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free_former(struct monst *mtmp)
|
||||
{
|
||||
if (mtmp->mextra && FORMER(mtmp)) {
|
||||
free((genericptr_t) FORMER(mtmp));
|
||||
FORMER(mtmp) = (struct former_incarnation *) 0;
|
||||
}
|
||||
}
|
||||
|
||||
staticfn boolean
|
||||
makemon_rnd_goodpos(
|
||||
struct monst *mon,
|
||||
|
||||
26
src/mon.c
26
src/mon.c
@@ -2567,6 +2567,12 @@ copy_mextra(struct monst *mtmp2, struct monst *mtmp1)
|
||||
assert(has_edog(mtmp2));
|
||||
*EDOG(mtmp2) = *EDOG(mtmp1);
|
||||
}
|
||||
if (FORMER(mtmp1)) {
|
||||
if (!FORMER(mtmp2))
|
||||
newformer(mtmp2);
|
||||
assert(has_former(mtmp2));
|
||||
*FORMER(mtmp2) = *FORMER(mtmp1);
|
||||
}
|
||||
if (has_mcorpsenm(mtmp1))
|
||||
MCORPSENM(mtmp2) = MCORPSENM(mtmp1);
|
||||
}
|
||||
@@ -2589,6 +2595,8 @@ dealloc_mextra(struct monst *m)
|
||||
free((genericptr_t) x->emin), x->emin = 0;
|
||||
if (x->edog)
|
||||
free((genericptr_t) x->edog), x->edog = 0;
|
||||
if (x->former)
|
||||
free((genericptr_t) x->former), x->former = 0;
|
||||
x->mcorpsenm = NON_PM; /* no allocation to release */
|
||||
|
||||
free((genericptr_t) x);
|
||||
@@ -2991,8 +2999,6 @@ logdeadmon(struct monst *mtmp, int mndx)
|
||||
}
|
||||
}
|
||||
|
||||
#undef livelog_mon_nam
|
||||
|
||||
/* monster 'mtmp' has died; maybe life-save, otherwise unshapeshift and
|
||||
update vanquished stats and update map */
|
||||
void
|
||||
@@ -3635,10 +3641,26 @@ xkilled(
|
||||
|
||||
/* malign was already adjusted for u.ualign.type and randomization */
|
||||
adjalign(mtmp->malign);
|
||||
|
||||
#if 0 /* HARDFOUGHT-only at present */
|
||||
#ifdef LIVELOG
|
||||
if (is_bones_monster(mtmp->data)
|
||||
&& has_former(mtmp) && *FORMER(mtmp)->rank
|
||||
&& strlen(FORMER(mtmp)->rank) > 0) {
|
||||
if (mtmp->data == &mons[PM_GHOST])
|
||||
livelog_printf(LL_UMONST, "destroyed %s, the former %s",
|
||||
livelog_mon_nam(mtmp), FORMER(mtmp)->rank);
|
||||
else
|
||||
livelog_printf(LL_UMONST, "destroyed %s, and former %s",
|
||||
livelog_mon_nam(mtmp), FORMER(mtmp)->rank);
|
||||
}
|
||||
#endif /* LIVELOG */
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#undef LEVEL_SPECIFIC_NOCORPSE
|
||||
#undef livelog_mon_nam
|
||||
|
||||
/* changes the monster into a stone monster of the same type
|
||||
this should only be called when poly_when_stoned() is true */
|
||||
|
||||
@@ -370,6 +370,15 @@ restmon(NHFILE *nhfp, struct monst *mtmp)
|
||||
EDOG(mtmp)->apport = 1;
|
||||
}
|
||||
}
|
||||
/* former - info about former self, primarily for bones files */
|
||||
if (nhfp->structlevel)
|
||||
Mread(nhfp->fd, &buflen, sizeof buflen);
|
||||
if (buflen > 0) {
|
||||
newformer(mtmp);
|
||||
if (nhfp->structlevel)
|
||||
Mread(nhfp->fd, FORMER(mtmp),
|
||||
sizeof (struct former_incarnation));
|
||||
}
|
||||
/* mcorpsenm - obj->corpsenm for mimic posing as corpse or
|
||||
statue (inline int rather than pointer to something) */
|
||||
if (nhfp->structlevel)
|
||||
|
||||
@@ -943,6 +943,13 @@ savemon(NHFILE *nhfp, struct monst *mtmp)
|
||||
if (nhfp->structlevel)
|
||||
bwrite(nhfp->fd, (genericptr_t) EDOG(mtmp), buflen);
|
||||
}
|
||||
buflen = FORMER(mtmp) ? (int) sizeof (struct former_incarnation) : 0;
|
||||
if (nhfp->structlevel)
|
||||
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof (int));
|
||||
if (buflen > 0) {
|
||||
if (nhfp->structlevel)
|
||||
bwrite(nhfp->fd, (genericptr_t) FORMER(mtmp), buflen);
|
||||
}
|
||||
/* mcorpsenm is inline int rather than pointer to something,
|
||||
so doesn't need to be preceded by a length field */
|
||||
if (nhfp->structlevel)
|
||||
|
||||
@@ -1246,6 +1246,8 @@ size_monst(struct monst *mtmp, boolean incl_wsegs)
|
||||
sz += (int) sizeof (struct emin);
|
||||
if (EDOG(mtmp))
|
||||
sz += (int) sizeof (struct edog);
|
||||
if (FORMER(mtmp))
|
||||
sz += (int) sizeof (struct former_incarnation);
|
||||
/* mextra->mcorpsenm doesn't point to more memory */
|
||||
}
|
||||
return sz;
|
||||
|
||||
Reference in New Issue
Block a user