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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
17
src/pager.c
17
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);
|
||||
}
|
||||
|
||||
@@ -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 *
|
||||
|
||||
16
src/save.c
16
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user