diff --git a/include/extern.h b/include/extern.h index d14e6d30c..265b69259 100644 --- a/include/extern.h +++ b/include/extern.h @@ -257,6 +257,7 @@ extern char *do_statusline2(void); extern void bot(void); extern void timebot(void); extern int xlev_to_rank(int); +extern const char *rank(void); extern int rank_to_xlev(int); extern const char *rank_of(int, short, boolean); extern int title_to_mon(const char *, int *, int *); @@ -1442,6 +1443,8 @@ extern void mkmonmoney(struct monst *, long) NONNULLARG1; extern int bagotricks(struct obj *, boolean, int *); extern boolean propagate(int, boolean, boolean); extern void summon_furies(int); +extern void newformer(struct monst *) NONNULLARG1; +extern void free_former(struct monst *) NONNULLARG1; /* ### mcastu.c ### */ diff --git a/include/mextra.h b/include/mextra.h index f47010324..0089991af 100644 --- a/include/mextra.h +++ b/include/mextra.h @@ -182,6 +182,10 @@ struct edog { Bitfield(killed_by_u, 1); /* you attempted to kill him */ }; +struct former_incarnation { + char rank[25]; /* for bones' ghost rank in their former life */ +}; + /*** ** mextra.h -- collection of all monster extensions */ @@ -192,6 +196,7 @@ struct mextra { struct eshk *eshk; struct emin *emin; struct edog *edog; + struct former_incarnation *former; int mcorpsenm; /* obj->corpsenm for mimic posing as statue or corpse, * obj->spe (fruit index) for one posing as a slime mold, * or an alignment mask for one posing as an altar */ @@ -203,6 +208,7 @@ struct mextra { #define ESHK(mon) ((mon)->mextra->eshk) #define EMIN(mon) ((mon)->mextra->emin) #define EDOG(mon) ((mon)->mextra->edog) +#define FORMER(mon) ((mon)->mextra->former) #define MCORPSENM(mon) ((mon)->mextra->mcorpsenm) #define has_mgivenname(mon) ((mon)->mextra && MGIVENNAME(mon)) @@ -211,6 +217,7 @@ struct mextra { #define has_eshk(mon) ((mon)->mextra && ESHK(mon)) #define has_emin(mon) ((mon)->mextra && EMIN(mon)) #define has_edog(mon) ((mon)->mextra && EDOG(mon)) +#define has_former(mon) ((mon)->mextra && FORMER(mon)) #define has_mcorpsenm(mon) ((mon)->mextra && MCORPSENM(mon) != NON_PM) #endif /* MEXTRA_H */ diff --git a/include/mondata.h b/include/mondata.h index 80a177f76..5296361fa 100644 --- a/include/mondata.h +++ b/include/mondata.h @@ -260,6 +260,14 @@ || objects[(obj)->otyp].oc_material == VEGGY \ || ((obj)->otyp == CORPSE && (obj)->corpsenm == PM_LICHEN)))) +/* is_bones_monster() is currently only used by hardfought livelog, + * but is included as part of savefile field compatibility adjustments. + */ +#define is_bones_monster(ptr) \ + ((ptr) == &mons[PM_GHOST] || (ptr) == &mons[PM_GHOUL] \ + || (ptr) == &mons[PM_VAMPIRE] || (ptr) == &mons[PM_WRAITH] \ + || (ptr) == &mons[PM_GREEN_SLIME] || (ptr)->mlet == S_MUMMY) + #ifdef PMNAME_MACROS #define pmname(ptr,g) ((((g) == MALE || (g) == FEMALE) && (ptr)->pmnames[g]) \ ? (ptr)->pmnames[g] : (ptr)->pmnames[NEUTRAL]) diff --git a/include/you.h b/include/you.h index cd734ca42..2683eec8f 100644 --- a/include/you.h +++ b/include/you.h @@ -153,6 +153,7 @@ struct u_conduct { /* number of times... */ long polyselfs; /* transformed yourself */ long wishes; /* used a wish */ long wisharti; /* wished for an artifact */ + long hf_reserved1; /* hf uses for elbereth;for hf savefile compatiblity */ long sokocheat; /* violated special 'rules' in Sokoban */ long pets; /* obtained a pet */ /* genocides already listed at end of game */ diff --git a/src/bones.c b/src/bones.c index 3ecd93125..34adac268 100644 --- a/src/bones.c +++ b/src/bones.c @@ -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); diff --git a/src/botl.c b/src/botl.c index 51f15f19d..406796782 100644 --- a/src/botl.c +++ b/src/botl.c @@ -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); diff --git a/src/makemon.c b/src/makemon.c index a7e52bf47..62de076b6 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -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, diff --git a/src/mon.c b/src/mon.c index a59b1a13a..819cb7bdc 100644 --- a/src/mon.c +++ b/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 */ diff --git a/src/restore.c b/src/restore.c index 67be7cebb..5ab92311e 100644 --- a/src/restore.c +++ b/src/restore.c @@ -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) diff --git a/src/save.c b/src/save.c index a178fbdcd..e383b52b8 100644 --- a/src/save.c +++ b/src/save.c @@ -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) diff --git a/src/wizcmds.c b/src/wizcmds.c index 17dc08c5b..a37c469aa 100644 --- a/src/wizcmds.c +++ b/src/wizcmds.c @@ -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;