From 71219bf0930d7a0b04fabaeb3853e14c2d816c12 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Sat, 31 Jan 2009 08:03:41 +0000 Subject: [PATCH] mimic statues & 2009 startup banner (trunk only) A mimic posing as a statue was displayed as a tengu statue (and recognizeable as such now that statues are displayed as the corresponding monster rather than rock-class back tick), but the lookat code described it as a giant ant statue (since there was no obj->corpsenm available to indicate the monster type, it defaulted to 0). This adds monst->mextra field `mcorpsenm' so that mimics have a place to remember what sort of statue or corpse they are mimicking. And it picks a random monster type when they take such forms so that the old tengu hack becomes irrelevant. newmextra() and newoextra() initialized pointers via memset(...,0) which is not portable; switch to explicit assignments. The wizard mode code to display memory used for monsters and objects added in amounts for the miscellaneous things pointed to by monst->mextra and obj->oextra structs but didn't include memory for those structs themselves; add it. Simplify monster save/restore slightly; there's no need for extra zeroes to represent monst->mextra->X sizes when monst->mextra is null. Update the startup banner for 2009. I should have done this with a separate patch but I'm taking a shortcut. :-] --- doc/fixes35.0 | 1 + include/extern.h | 2 ++ include/mextra.h | 6 +++- include/patchlevel.h | 6 ++-- src/cmd.c | 3 ++ src/display.c | 7 ++-- src/makemon.c | 44 ++++++++++++++++++++---- src/mkobj.c | 8 +++-- src/mon.c | 4 +++ src/pager.c | 17 +++++++--- src/restore.c | 81 +++++++++++++++++++++----------------------- src/save.c | 16 ++++----- 12 files changed, 124 insertions(+), 71 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index a49b10eb4..b4d415bde 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -304,6 +304,7 @@ describe lit Sunsword as shining rather than glowing prevent poly'd shopkeepers from taking on forms that can't handle objects attempting to move direction 'u' as a grid bug performed #untrap command; the other diagonals reported "unknown command" instead of "you can't" +mimic posing as statue or corpse now picks and maintains particular monst type Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 809c2e400..811e71980 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1075,6 +1075,8 @@ E int FDECL(mongets, (struct monst *,int)); E int FDECL(golemhp, (int)); E boolean FDECL(peace_minded, (struct permonst *)); E void FDECL(set_malign, (struct monst *)); +E void FDECL(newmcorpsenm, (struct monst *)); +E void FDECL(freemcorpsenm, (struct monst *)); E void FDECL(set_mimic_sym, (struct monst *)); E int FDECL(mbirth_limit, (int)); E void FDECL(mimic_hit_msg, (struct monst *, SHORT_P)); diff --git a/include/mextra.h b/include/mextra.h index 3e72c8b8d..b99ba54be 100644 --- a/include/mextra.h +++ b/include/mextra.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mextra.h 3.5 2006/04/14 */ +/* SCCS Id: @(#)mextra.h 3.5 2009/01/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -173,6 +173,7 @@ struct mextra { struct eshk *eshk; struct emin *emin; struct edog *edog; + int mcorpsenm; /* obj->corpsenm for mimic posing as statue or corpse */ }; #define MNAME(mon) ((mon)->mextra->mname) @@ -181,6 +182,9 @@ struct mextra { #define ESHK(mon) ((mon)->mextra->eshk) #define EMIN(mon) ((mon)->mextra->emin) #define EDOG(mon) ((mon)->mextra->edog) +#define MCORPSENM(mon) ((mon)->mextra->mcorpsenm) + #define has_mname(mon) ((mon)->mextra && MNAME(mon)) +#define has_mcorpsenm(mon) ((mon)->mextra && MCORPSENM(mon) != NON_PM) #endif /* MEXTRA_H */ diff --git a/include/patchlevel.h b/include/patchlevel.h index b85553b30..ec4f58173 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)patchlevel.h 3.5 2008/07/20 */ +/* SCCS Id: @(#)patchlevel.h 3.5 2009/01/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -13,10 +13,10 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 41 +#define EDITLEVEL 42 #define COPYRIGHT_BANNER_A \ -"NetHack, Copyright 1985-2007" +"NetHack, Copyright 1985-2009" #define COPYRIGHT_BANNER_B \ " By Stichting Mathematisch Centrum and M. Stephenson." diff --git a/src/cmd.c b/src/cmd.c index fb8a10a51..dd3ed157d 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -2374,6 +2374,7 @@ struct obj *otmp; int sz = (int)sizeof (struct obj); if (otmp->oextra) { + sz += (int)sizeof (struct oextra); if (ONAME(otmp)) sz += (int)strlen(ONAME(otmp)) + 1; if (OMONST(otmp)) sz += (int)sizeof (struct monst); if (OMID(otmp)) sz += (int)sizeof (unsigned); @@ -2479,12 +2480,14 @@ struct monst *mtmp; int sz = (int)sizeof (struct monst); if (mtmp->mextra) { + sz += (int)sizeof (struct mextra); if (MNAME(mtmp)) sz += (int)strlen(MNAME(mtmp)) + 1; if (EGD(mtmp)) sz += (int)sizeof (struct egd); if (EPRI(mtmp)) sz += (int)sizeof (struct epri); if (ESHK(mtmp)) sz += (int)sizeof (struct eshk); if (EMIN(mtmp)) sz += (int)sizeof (struct emin); if (EDOG(mtmp)) sz += (int)sizeof (struct edog); + /* mextra->mcorpsenm doesn't point to more memory */ } return sz; } diff --git a/src/display.c b/src/display.c index dcc951611..22d5a6c90 100644 --- a/src/display.c +++ b/src/display.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)display.c 3.5 2007/06/25 */ +/* SCCS Id: @(#)display.c 3.5 2009/01/30 */ /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */ /* and Dave Cohrs, 1990. */ /* NetHack may be freely redistributed. See license for details. */ @@ -420,11 +420,12 @@ display_monster(x, y, mon, sightflags, worm_tail) case M_AP_OBJECT: { struct obj obj; /* Make a fake object to send */ /* to map_object(). */ - obj.oextra = (struct oextra *)0; + obj = zeroobj; obj.ox = x; obj.oy = y; obj.otyp = mon->mappearance; - obj.corpsenm = PM_TENGU; /* if mimicing a corpse */ + /* might be mimicing a corpse or statue */ + obj.corpsenm = has_mcorpsenm(mon) ? MCORPSENM(mon) : PM_TENGU; map_object(&obj,!sensed); break; } diff --git a/src/makemon.c b/src/makemon.c index 5fe0e23b9..ab9729a94 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)makemon.c 3.5 2007/03/23 */ +/* SCCS Id: @(#)makemon.c 3.5 2009/01/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -859,9 +859,15 @@ struct mextra * newmextra() { struct mextra *mextra; + mextra = (struct mextra *)alloc(sizeof(struct mextra)); - if (mextra) - (void) memset((genericptr_t)mextra, 0, sizeof(struct mextra)); + mextra->mname = 0; + mextra->egd = 0; + mextra->epri = 0; + mextra->eshk = 0; + mextra->emin = 0; + mextra->edog = 0; + mextra->mcorpsenm = NON_PM; return mextra; } @@ -1732,6 +1738,23 @@ struct monst *mtmp; mtmp->malign = abs(mal); } +/* allocate a new mcorpsenm field for a monster; only need mextra itself */ +void +newmcorpsenm(mtmp) +struct monst *mtmp; +{ + if (!mtmp->mextra) mtmp->mextra = newmextra(); + MCORPSENM(mtmp) = NON_PM; /* not initialized yet */ +} + +/* release monster's mcorpsenm field; basically a no-op */ +void +freemcorpsenm(mtmp) +struct monst *mtmp; +{ + if (has_mcorpsenm(mtmp)) MCORPSENM(mtmp) = NON_PM; +} + static NEARDATA char syms[] = { MAXOCLASSES, MAXOCLASSES+1, RING_CLASS, WAND_CLASS, WEAPON_CLASS, FOOD_CLASS, COIN_CLASS, SCROLL_CLASS, POTION_CLASS, ARMOR_CLASS, @@ -1836,15 +1859,14 @@ assign_sym: if (s_sym >= MAXOCLASSES) { ap_type = M_AP_FURNITURE; appear = s_sym == MAXOCLASSES ? S_upstair : S_dnstair; - } else if (s_sym == COIN_CLASS) { - ap_type = M_AP_OBJECT; - appear = GOLD_PIECE; } else { ap_type = M_AP_OBJECT; if (s_sym == S_MIMIC_DEF) { appear = STRANGE_OBJECT; + } else if (s_sym == COIN_CLASS) { + appear = GOLD_PIECE; } else { - otmp = mkobj( (char) s_sym, FALSE ); + otmp = mkobj((char) s_sym, FALSE); appear = otmp->otyp; /* make sure container contents are free'ed */ obfree(otmp, (struct obj *) 0); @@ -1853,6 +1875,14 @@ assign_sym: } mtmp->m_ap_type = ap_type; mtmp->mappearance = appear; + if (ap_type == M_AP_OBJECT && + (appear == STATUE || appear == CORPSE || + appear == FIGURINE || appear == EGG)) { + newmcorpsenm(mtmp); + MCORPSENM(mtmp) = rndmonnum(); + if (appear == EGG && !can_be_hatched(MCORPSENM(mtmp))) + MCORPSENM(mtmp) = NON_PM; /* revert to generic egg */ + } } /* release a monster from a bag of tricks; return number of monsters created */ diff --git a/src/mkobj.c b/src/mkobj.c index 01b165c46..d2bc82c29 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -83,9 +83,13 @@ struct oextra * newoextra() { struct oextra *oextra; + oextra = (struct oextra *)alloc(sizeof(struct oextra)); - if (oextra) - (void) memset((genericptr_t)oextra, 0, sizeof(struct oextra)); + oextra->oname = 0; + oextra->omonst = 0; + oextra->omid = 0; + oextra->olong = 0; + oextra->omailcmd = 0; return oextra; } diff --git a/src/mon.c b/src/mon.c index 1e73b710b..132a03b30 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1418,6 +1418,7 @@ struct monst *mtmp2, *mtmp1; (genericptr_t)EDOG(mtmp1), sizeof(struct edog)); } + if (has_mcorpsenm(mtmp1)) MCORPSENM(mtmp2) = MCORPSENM(mtmp1); } STATIC_OVL void @@ -1431,6 +1432,7 @@ struct mextra *x; if (x->eshk) free((genericptr_t)x->eshk); if (x->emin) free((genericptr_t)x->emin); if (x->edog) free((genericptr_t)x->edog); + /* [no action needed for x->mcorpsenm] */ free((genericptr_t)x); } } @@ -2331,6 +2333,8 @@ register struct monst *mtmp; unsigned old_app = mtmp->mappearance; uchar old_ap_type = mtmp->m_ap_type; + if (has_mcorpsenm(mtmp)) freemcorpsenm(mtmp); + mtmp->m_ap_type = M_AP_NOTHING; mtmp->mappearance = 0; diff --git a/src/pager.c b/src/pager.c index 0466ca2cd..1b09f240c 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pager.c 3.5 2008/07/20 */ +/* SCCS Id: @(#)pager.c 3.5 2009/01/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -213,15 +213,24 @@ lookat(x, y, buf, monbuf) } /* mtmp */ } else if (glyph_is_object(glyph)) { + int glyphotyp = glyph_to_obj(glyph); struct obj *otmp = vobj_at(x,y); - if (!otmp || otmp->otyp != glyph_to_obj(glyph)) { - if (glyph_to_obj(glyph) != STRANGE_OBJECT) { - otmp = mksobj(glyph_to_obj(glyph), FALSE, FALSE); + /* there might be a mimic here posing as an object */ + mtmp = m_at(x, y); + if (mtmp && mtmp->m_ap_type == M_AP_OBJECT && + mtmp->mappearance == glyphotyp) otmp = 0; + else mtmp = 0; + + if (!otmp || otmp->otyp != glyphotyp) { + if (glyphotyp != STRANGE_OBJECT) { + otmp = mksobj(glyphotyp, FALSE, FALSE); if (otmp->oclass == COIN_CLASS) otmp->quan = 2L; /* to force pluralization */ else if (otmp->otyp == SLIME_MOLD) otmp->spe = context.current_fruit; /* give it a type */ + if (mtmp && has_mcorpsenm(mtmp)) /* mimic as corpse/statue */ + otmp->corpsenm = MCORPSENM(mtmp); Strcpy(buf, distant_name(otmp, xname)); dealloc_obj(otmp); } diff --git a/src/restore.c b/src/restore.c index b8d4cba70..748a77e11 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)restore.c 3.5 2008/07/20 */ +/* SCCS Id: @(#)restore.c 3.5 2009/01/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -350,56 +350,53 @@ struct monst *mtmp; mread(fd, (genericptr_t) mtmp, sizeof(struct monst)); - /* any saved pointers are mostly invalid */ + /* next monster pointer is invalid */ mtmp->nmon = (struct monst *)0; - mtmp->mextra = (struct mextra *)0; + /* non-null mextra needs to be reconstructed */ + if (mtmp->mextra) { + mtmp->mextra = newmextra(); - /* read the length of the name and the name */ - mread(fd, (genericptr_t) &buflen, sizeof(buflen)); - if (buflen > 0) { + /* mname - monster's name */ + mread(fd, (genericptr_t) &buflen, sizeof(buflen)); + if (buflen > 0) { /* includes terminating '\0' */ new_mname(mtmp, buflen); mread(fd, (genericptr_t) MNAME(mtmp), buflen); - } - - /* egd */ - mread(fd, (genericptr_t) &buflen, sizeof(buflen)); - if (buflen > 0) { + } + /* egd - vault guard */ + mread(fd, (genericptr_t) &buflen, sizeof (buflen)); + if (buflen > 0) { newegd(mtmp); - mread(fd, (genericptr_t) EGD(mtmp), - sizeof(struct egd)); - } - - /* epri */ - mread(fd, (genericptr_t) &buflen, sizeof(buflen)); - if (buflen > 0) { + mread(fd, (genericptr_t) EGD(mtmp), sizeof (struct egd)); + } + /* epri - temple priest */ + mread(fd, (genericptr_t) &buflen, sizeof (buflen)); + if (buflen > 0) { newepri(mtmp); - mread(fd, (genericptr_t) EPRI(mtmp), - sizeof(struct epri)); - } - - /* eshk */ - mread(fd, (genericptr_t) &buflen, sizeof(buflen)); - if (buflen > 0) { + mread(fd, (genericptr_t) EPRI(mtmp), sizeof (struct epri)); + } + /* eshk - shopkeeper */ + mread(fd, (genericptr_t) &buflen, sizeof (buflen)); + if (buflen > 0) { neweshk(mtmp); - mread(fd, (genericptr_t) ESHK(mtmp), - sizeof(struct eshk)); - } - - /* emin */ - mread(fd, (genericptr_t) &buflen, sizeof(buflen)); - if (buflen > 0) { + mread(fd, (genericptr_t) ESHK(mtmp), sizeof (struct eshk)); + } + /* emin - minion */ + mread(fd, (genericptr_t) &buflen, sizeof (buflen)); + if (buflen > 0) { newemin(mtmp); - mread(fd, (genericptr_t) EMIN(mtmp), - sizeof(struct emin)); - } - - /* edog */ - mread(fd, (genericptr_t) &buflen, sizeof(buflen)); - if (buflen > 0) { + mread(fd, (genericptr_t) EMIN(mtmp), sizeof (struct emin)); + } + /* edog - pet */ + mread(fd, (genericptr_t) &buflen, sizeof (buflen)); + if (buflen > 0) { newedog(mtmp); - mread(fd, (genericptr_t) EDOG(mtmp), - sizeof(struct edog)); - } + mread(fd, (genericptr_t) EDOG(mtmp), sizeof (struct edog)); + } + /* mcorpsenm - obj->corpsenm for mimic posing as corpse or + statue (inline int rather than pointer to something) */ + mread(fd, (genericptr_t) &MCORPSENM(mtmp), + sizeof MCORPSENM(mtmp)); + } /* mextra */ } STATIC_OVL struct monst * diff --git a/src/save.c b/src/save.c index 8e5a09f65..bbe3befef 100644 --- a/src/save.c +++ b/src/save.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)save.c 3.5 2008/07/20 */ +/* SCCS Id: @(#)save.c 3.5 2009/01/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1046,14 +1046,7 @@ struct monst *mtmp; buflen = sizeof(struct monst); bwrite(fd, (genericptr_t) &buflen, sizeof(int)); bwrite(fd, (genericptr_t) mtmp, buflen); - if (!mtmp->mextra) { - bwrite(fd, (genericptr_t) &zerobuf, sizeof(int)); - bwrite(fd, (genericptr_t) &zerobuf, sizeof(int)); - bwrite(fd, (genericptr_t) &zerobuf, sizeof(int)); - bwrite(fd, (genericptr_t) &zerobuf, sizeof(int)); - bwrite(fd, (genericptr_t) &zerobuf, sizeof(int)); - bwrite(fd, (genericptr_t) &zerobuf, sizeof(int)); - } else { + if (mtmp->mextra) { if (MNAME(mtmp)) buflen = strlen(MNAME(mtmp)) + 1; else buflen = 0; bwrite(fd, (genericptr_t) &buflen, sizeof buflen); @@ -1089,6 +1082,11 @@ struct monst *mtmp; bwrite(fd, (genericptr_t) &buflen, sizeof(int)); if (buflen > 0) bwrite(fd, (genericptr_t) EDOG(mtmp), buflen); + + /* mcorpsenm is inline int rather than pointer to something, + so doesn't need to be preceded by a length field */ + bwrite(fd, (genericptr_t) &MCORPSENM(mtmp), + sizeof MCORPSENM(mtmp)); } }