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.  :-]
This commit is contained in:
nethack.rankin
2009-01-31 08:03:41 +00:00
parent 0def692d5f
commit 71219bf093
12 changed files with 124 additions and 71 deletions

View File

@@ -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 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; attempting to move direction 'u' as a grid bug performed #untrap command;
the other diagonals reported "unknown command" instead of "you can't" 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 Platform- and/or Interface-Specific Fixes

View File

@@ -1075,6 +1075,8 @@ E int FDECL(mongets, (struct monst *,int));
E int FDECL(golemhp, (int)); E int FDECL(golemhp, (int));
E boolean FDECL(peace_minded, (struct permonst *)); E boolean FDECL(peace_minded, (struct permonst *));
E void FDECL(set_malign, (struct monst *)); 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 void FDECL(set_mimic_sym, (struct monst *));
E int FDECL(mbirth_limit, (int)); E int FDECL(mbirth_limit, (int));
E void FDECL(mimic_hit_msg, (struct monst *, SHORT_P)); E void FDECL(mimic_hit_msg, (struct monst *, SHORT_P));

View File

@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -173,6 +173,7 @@ struct mextra {
struct eshk *eshk; struct eshk *eshk;
struct emin *emin; struct emin *emin;
struct edog *edog; struct edog *edog;
int mcorpsenm; /* obj->corpsenm for mimic posing as statue or corpse */
}; };
#define MNAME(mon) ((mon)->mextra->mname) #define MNAME(mon) ((mon)->mextra->mname)
@@ -181,6 +182,9 @@ struct mextra {
#define ESHK(mon) ((mon)->mextra->eshk) #define ESHK(mon) ((mon)->mextra->eshk)
#define EMIN(mon) ((mon)->mextra->emin) #define EMIN(mon) ((mon)->mextra->emin)
#define EDOG(mon) ((mon)->mextra->edog) #define EDOG(mon) ((mon)->mextra->edog)
#define MCORPSENM(mon) ((mon)->mextra->mcorpsenm)
#define has_mname(mon) ((mon)->mextra && MNAME(mon)) #define has_mname(mon) ((mon)->mextra && MNAME(mon))
#define has_mcorpsenm(mon) ((mon)->mextra && MCORPSENM(mon) != NON_PM)
#endif /* MEXTRA_H */ #endif /* MEXTRA_H */

View File

@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -13,10 +13,10 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones * Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files. * and save files.
*/ */
#define EDITLEVEL 41 #define EDITLEVEL 42
#define COPYRIGHT_BANNER_A \ #define COPYRIGHT_BANNER_A \
"NetHack, Copyright 1985-2007" "NetHack, Copyright 1985-2009"
#define COPYRIGHT_BANNER_B \ #define COPYRIGHT_BANNER_B \
" By Stichting Mathematisch Centrum and M. Stephenson." " By Stichting Mathematisch Centrum and M. Stephenson."

View File

@@ -2374,6 +2374,7 @@ struct obj *otmp;
int sz = (int)sizeof (struct obj); int sz = (int)sizeof (struct obj);
if (otmp->oextra) { if (otmp->oextra) {
sz += (int)sizeof (struct oextra);
if (ONAME(otmp)) sz += (int)strlen(ONAME(otmp)) + 1; if (ONAME(otmp)) sz += (int)strlen(ONAME(otmp)) + 1;
if (OMONST(otmp)) sz += (int)sizeof (struct monst); if (OMONST(otmp)) sz += (int)sizeof (struct monst);
if (OMID(otmp)) sz += (int)sizeof (unsigned); if (OMID(otmp)) sz += (int)sizeof (unsigned);
@@ -2479,12 +2480,14 @@ struct monst *mtmp;
int sz = (int)sizeof (struct monst); int sz = (int)sizeof (struct monst);
if (mtmp->mextra) { if (mtmp->mextra) {
sz += (int)sizeof (struct mextra);
if (MNAME(mtmp)) sz += (int)strlen(MNAME(mtmp)) + 1; if (MNAME(mtmp)) sz += (int)strlen(MNAME(mtmp)) + 1;
if (EGD(mtmp)) sz += (int)sizeof (struct egd); if (EGD(mtmp)) sz += (int)sizeof (struct egd);
if (EPRI(mtmp)) sz += (int)sizeof (struct epri); if (EPRI(mtmp)) sz += (int)sizeof (struct epri);
if (ESHK(mtmp)) sz += (int)sizeof (struct eshk); if (ESHK(mtmp)) sz += (int)sizeof (struct eshk);
if (EMIN(mtmp)) sz += (int)sizeof (struct emin); if (EMIN(mtmp)) sz += (int)sizeof (struct emin);
if (EDOG(mtmp)) sz += (int)sizeof (struct edog); if (EDOG(mtmp)) sz += (int)sizeof (struct edog);
/* mextra->mcorpsenm doesn't point to more memory */
} }
return sz; return sz;
} }

View File

@@ -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 */ /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
/* and Dave Cohrs, 1990. */ /* and Dave Cohrs, 1990. */
/* NetHack may be freely redistributed. See license for details. */ /* 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: { case M_AP_OBJECT: {
struct obj obj; /* Make a fake object to send */ struct obj obj; /* Make a fake object to send */
/* to map_object(). */ /* to map_object(). */
obj.oextra = (struct oextra *)0; obj = zeroobj;
obj.ox = x; obj.ox = x;
obj.oy = y; obj.oy = y;
obj.otyp = mon->mappearance; 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); map_object(&obj,!sensed);
break; break;
} }

View File

@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -859,9 +859,15 @@ struct mextra *
newmextra() newmextra()
{ {
struct mextra *mextra; struct mextra *mextra;
mextra = (struct mextra *)alloc(sizeof(struct mextra)); mextra = (struct mextra *)alloc(sizeof(struct mextra));
if (mextra) mextra->mname = 0;
(void) memset((genericptr_t)mextra, 0, sizeof(struct mextra)); mextra->egd = 0;
mextra->epri = 0;
mextra->eshk = 0;
mextra->emin = 0;
mextra->edog = 0;
mextra->mcorpsenm = NON_PM;
return mextra; return mextra;
} }
@@ -1732,6 +1738,23 @@ struct monst *mtmp;
mtmp->malign = abs(mal); 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[] = { static NEARDATA char syms[] = {
MAXOCLASSES, MAXOCLASSES+1, RING_CLASS, WAND_CLASS, WEAPON_CLASS, MAXOCLASSES, MAXOCLASSES+1, RING_CLASS, WAND_CLASS, WEAPON_CLASS,
FOOD_CLASS, COIN_CLASS, SCROLL_CLASS, POTION_CLASS, ARMOR_CLASS, FOOD_CLASS, COIN_CLASS, SCROLL_CLASS, POTION_CLASS, ARMOR_CLASS,
@@ -1836,15 +1859,14 @@ assign_sym:
if (s_sym >= MAXOCLASSES) { if (s_sym >= MAXOCLASSES) {
ap_type = M_AP_FURNITURE; ap_type = M_AP_FURNITURE;
appear = s_sym == MAXOCLASSES ? S_upstair : S_dnstair; appear = s_sym == MAXOCLASSES ? S_upstair : S_dnstair;
} else if (s_sym == COIN_CLASS) {
ap_type = M_AP_OBJECT;
appear = GOLD_PIECE;
} else { } else {
ap_type = M_AP_OBJECT; ap_type = M_AP_OBJECT;
if (s_sym == S_MIMIC_DEF) { if (s_sym == S_MIMIC_DEF) {
appear = STRANGE_OBJECT; appear = STRANGE_OBJECT;
} else if (s_sym == COIN_CLASS) {
appear = GOLD_PIECE;
} else { } else {
otmp = mkobj( (char) s_sym, FALSE ); otmp = mkobj((char) s_sym, FALSE);
appear = otmp->otyp; appear = otmp->otyp;
/* make sure container contents are free'ed */ /* make sure container contents are free'ed */
obfree(otmp, (struct obj *) 0); obfree(otmp, (struct obj *) 0);
@@ -1853,6 +1875,14 @@ assign_sym:
} }
mtmp->m_ap_type = ap_type; mtmp->m_ap_type = ap_type;
mtmp->mappearance = appear; 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 */ /* release a monster from a bag of tricks; return number of monsters created */

View File

@@ -83,9 +83,13 @@ struct oextra *
newoextra() newoextra()
{ {
struct oextra *oextra; struct oextra *oextra;
oextra = (struct oextra *)alloc(sizeof(struct oextra)); oextra = (struct oextra *)alloc(sizeof(struct oextra));
if (oextra) oextra->oname = 0;
(void) memset((genericptr_t)oextra, 0, sizeof(struct oextra)); oextra->omonst = 0;
oextra->omid = 0;
oextra->olong = 0;
oextra->omailcmd = 0;
return oextra; return oextra;
} }

View File

@@ -1418,6 +1418,7 @@ struct monst *mtmp2, *mtmp1;
(genericptr_t)EDOG(mtmp1), (genericptr_t)EDOG(mtmp1),
sizeof(struct edog)); sizeof(struct edog));
} }
if (has_mcorpsenm(mtmp1)) MCORPSENM(mtmp2) = MCORPSENM(mtmp1);
} }
STATIC_OVL void STATIC_OVL void
@@ -1431,6 +1432,7 @@ struct mextra *x;
if (x->eshk) free((genericptr_t)x->eshk); if (x->eshk) free((genericptr_t)x->eshk);
if (x->emin) free((genericptr_t)x->emin); if (x->emin) free((genericptr_t)x->emin);
if (x->edog) free((genericptr_t)x->edog); if (x->edog) free((genericptr_t)x->edog);
/* [no action needed for x->mcorpsenm] */
free((genericptr_t)x); free((genericptr_t)x);
} }
} }
@@ -2331,6 +2333,8 @@ register struct monst *mtmp;
unsigned old_app = mtmp->mappearance; unsigned old_app = mtmp->mappearance;
uchar old_ap_type = mtmp->m_ap_type; uchar old_ap_type = mtmp->m_ap_type;
if (has_mcorpsenm(mtmp)) freemcorpsenm(mtmp);
mtmp->m_ap_type = M_AP_NOTHING; mtmp->m_ap_type = M_AP_NOTHING;
mtmp->mappearance = 0; mtmp->mappearance = 0;

View File

@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -213,15 +213,24 @@ lookat(x, y, buf, monbuf)
} /* mtmp */ } /* mtmp */
} else if (glyph_is_object(glyph)) { } else if (glyph_is_object(glyph)) {
int glyphotyp = glyph_to_obj(glyph);
struct obj *otmp = vobj_at(x,y); struct obj *otmp = vobj_at(x,y);
if (!otmp || otmp->otyp != glyph_to_obj(glyph)) { /* there might be a mimic here posing as an object */
if (glyph_to_obj(glyph) != STRANGE_OBJECT) { mtmp = m_at(x, y);
otmp = mksobj(glyph_to_obj(glyph), FALSE, FALSE); 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) if (otmp->oclass == COIN_CLASS)
otmp->quan = 2L; /* to force pluralization */ otmp->quan = 2L; /* to force pluralization */
else if (otmp->otyp == SLIME_MOLD) else if (otmp->otyp == SLIME_MOLD)
otmp->spe = context.current_fruit; /* give it a type */ 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)); Strcpy(buf, distant_name(otmp, xname));
dealloc_obj(otmp); dealloc_obj(otmp);
} }

View File

@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -350,56 +350,53 @@ struct monst *mtmp;
mread(fd, (genericptr_t) mtmp, sizeof(struct monst)); 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->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 */ /* mname - monster's name */
mread(fd, (genericptr_t) &buflen, sizeof(buflen)); mread(fd, (genericptr_t) &buflen, sizeof(buflen));
if (buflen > 0) { if (buflen > 0) { /* includes terminating '\0' */
new_mname(mtmp, buflen); new_mname(mtmp, buflen);
mread(fd, (genericptr_t) MNAME(mtmp), buflen); mread(fd, (genericptr_t) MNAME(mtmp), buflen);
} }
/* egd - vault guard */
/* egd */ mread(fd, (genericptr_t) &buflen, sizeof (buflen));
mread(fd, (genericptr_t) &buflen, sizeof(buflen)); if (buflen > 0) {
if (buflen > 0) {
newegd(mtmp); newegd(mtmp);
mread(fd, (genericptr_t) EGD(mtmp), mread(fd, (genericptr_t) EGD(mtmp), sizeof (struct egd));
sizeof(struct egd)); }
} /* epri - temple priest */
mread(fd, (genericptr_t) &buflen, sizeof (buflen));
/* epri */ if (buflen > 0) {
mread(fd, (genericptr_t) &buflen, sizeof(buflen));
if (buflen > 0) {
newepri(mtmp); newepri(mtmp);
mread(fd, (genericptr_t) EPRI(mtmp), mread(fd, (genericptr_t) EPRI(mtmp), sizeof (struct epri));
sizeof(struct epri)); }
} /* eshk - shopkeeper */
mread(fd, (genericptr_t) &buflen, sizeof (buflen));
/* eshk */ if (buflen > 0) {
mread(fd, (genericptr_t) &buflen, sizeof(buflen));
if (buflen > 0) {
neweshk(mtmp); neweshk(mtmp);
mread(fd, (genericptr_t) ESHK(mtmp), mread(fd, (genericptr_t) ESHK(mtmp), sizeof (struct eshk));
sizeof(struct eshk)); }
} /* emin - minion */
mread(fd, (genericptr_t) &buflen, sizeof (buflen));
/* emin */ if (buflen > 0) {
mread(fd, (genericptr_t) &buflen, sizeof(buflen));
if (buflen > 0) {
newemin(mtmp); newemin(mtmp);
mread(fd, (genericptr_t) EMIN(mtmp), mread(fd, (genericptr_t) EMIN(mtmp), sizeof (struct emin));
sizeof(struct emin)); }
} /* edog - pet */
mread(fd, (genericptr_t) &buflen, sizeof (buflen));
/* edog */ if (buflen > 0) {
mread(fd, (genericptr_t) &buflen, sizeof(buflen));
if (buflen > 0) {
newedog(mtmp); newedog(mtmp);
mread(fd, (genericptr_t) EDOG(mtmp), mread(fd, (genericptr_t) EDOG(mtmp), sizeof (struct edog));
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 * STATIC_OVL struct monst *

View File

@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1046,14 +1046,7 @@ struct monst *mtmp;
buflen = sizeof(struct monst); buflen = sizeof(struct monst);
bwrite(fd, (genericptr_t) &buflen, sizeof(int)); bwrite(fd, (genericptr_t) &buflen, sizeof(int));
bwrite(fd, (genericptr_t) mtmp, buflen); bwrite(fd, (genericptr_t) mtmp, buflen);
if (!mtmp->mextra) { 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 (MNAME(mtmp)) buflen = strlen(MNAME(mtmp)) + 1; if (MNAME(mtmp)) buflen = strlen(MNAME(mtmp)) + 1;
else buflen = 0; else buflen = 0;
bwrite(fd, (genericptr_t) &buflen, sizeof buflen); bwrite(fd, (genericptr_t) &buflen, sizeof buflen);
@@ -1089,6 +1082,11 @@ struct monst *mtmp;
bwrite(fd, (genericptr_t) &buflen, sizeof(int)); bwrite(fd, (genericptr_t) &buflen, sizeof(int));
if (buflen > 0) if (buflen > 0)
bwrite(fd, (genericptr_t) EDOG(mtmp), buflen); 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));
} }
} }