decaying globs of {ooze,pudding,slime}

Globs never rotted away but did become tainted after a relatively
short while, which seemed like a contradiction.  Change them to never
be tainted but shrink by 1 unit of weight approximately every 25
turns.  An ordinary glob (one that hasn't combined with any others)
starts out weighing 20 units, so it takes about 500 turns to vanish.
That's roughly twice as long as a corpse takes to rot away.

Shrinking globs give feedback when in hero's invent or in a container
in hero's inventory, but rarely (when going from an exact multiple
of 20 weight units; that is, from integral number of N globs to
N-1 + 19/20, or if weight reduction triggers an encumbrance change).
When a glob goes away completely, there is feedback for those two
circumstances and also for seeing the glob vanish from the floor.

I haven't touched how much nutrition eating a glob confers.  I have
changed formatting of glob names to use "small", "medium", "large",
"very large" instead of "small", [no adjective], "large", &c.  You
still need to have at least five globs coalesced together for the
adjective to become "medium", same amount as before.

I don't think EDITLEVEL needs to be modified but have incremented it
anyway to play things safe.
This commit is contained in:
PatR
2021-11-06 18:24:36 -07:00
parent aa8fd3ab3c
commit e2ca016484
11 changed files with 293 additions and 59 deletions

View File

@@ -1228,6 +1228,10 @@ branch stairs have a different glyph, show up in yellow color in tty
duration of confusion when drinking booze depends upon hunger state
using 'D' allows dropping items picked up previously
bones piles can be ransacked by adjacent monsters
decaying globs of {ooze,pudding,slime} shrink over time based on their total
weight, eventually to nothing; for combined globs it can take a long
time, and while doing so they no longer give the tainted corpse food
poisoning effect when eaten
Platform- and/or Interface-Specific New Features

View File

@@ -668,6 +668,7 @@ extern void eatmupdate(void);
extern boolean is_edible(struct obj *);
extern void init_uhunger(void);
extern int Hear_again(void);
extern boolean eating_glob(struct obj *);
extern void reset_eat(void);
extern unsigned obj_nutrition(struct obj *);
extern int doeat(void);
@@ -1358,6 +1359,8 @@ extern struct obj *rnd_treefruit_at(int, int);
extern void set_corpsenm(struct obj *, int);
extern long rider_revival_time(struct obj *, boolean);
extern void start_corpse_timeout(struct obj *);
extern void start_glob_timeout(struct obj *, long);
extern void shrink_glob(anything *, long);
extern void maybe_adjust_light(struct obj *, int);
extern void bless(struct obj *);
extern void unbless(struct obj *);

View File

@@ -167,18 +167,21 @@ struct debug_flags {
#endif
};
struct instance_flags {
/* stuff that really isn't option or platform related. They are
* set and cleared during the game to control the internal
* behaviour of various NetHack functions and probably warrant
* a structure of their own elsewhere some day.
/*
* Stuff that really isn't option or platform related and does not
* get saved and restored. They are set and cleared during the game
* to control the internal behaviour of various NetHack functions
* and probably warrant a structure of their own elsewhere some day.
*/
boolean lua_testing; /* doing lua tests */
struct instance_flags {
boolean debug_fuzzer; /* fuzz testing */
boolean in_lua; /* executing a lua script */
boolean defer_plname; /* X11 hack: askname() might not set g.plname */
boolean herecmd_menu; /* use menu when mouseclick on yourself */
boolean invis_goldsym; /* gold symbol is ' '? */
boolean in_lua; /* executing a lua script */
boolean lua_testing; /* doing lua tests */
boolean partly_eaten_hack; /* extra flag for xname() used when it's called
* indirectly so we can't use xname_flags() */
boolean sad_feeling; /* unseen pet is dying */
int at_midnight; /* only valid during end of game disclosure */
int at_night; /* also only valid during end of game disclosure */

View File

@@ -17,7 +17,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
#define EDITLEVEL 44
#define EDITLEVEL 45
/*
* Development status possibilities.

View File

@@ -34,6 +34,7 @@ enum timeout_types {
HATCH_EGG,
FIG_TRANSFORM,
MELT_ICE_AWAY,
SHRINK_GLOB,
NUM_TIME_FUNCS
};

View File

@@ -1633,13 +1633,14 @@ eatcorpse(struct obj *otmp)
rotted -= 2L;
}
if (mnum != PM_ACID_BLOB && !stoneable && !slimeable && rotted > 5L) {
/* 3.7: globs don't become tainted, they shrink away */
if (mnum != PM_ACID_BLOB && !glob && !stoneable && !slimeable
&& rotted > 5L) {
boolean cannibal = maybe_cannibal(mnum, FALSE);
/* tp++; -- early return makes this unnecessary */
pline("Ulch - that %s was tainted%s!",
(mons[mnum].mlet == S_FUNGUS) ? "fungoid vegetation"
: glob ? "glob"
: vegetarian(&mons[mnum]) ? "protoplasm"
: "meat",
cannibal ? ", you cannibal" : "");
@@ -1803,6 +1804,13 @@ start_eating(struct obj *otmp, boolean already_partly_eaten)
set_occupation(eatfood, msgbuf, 0);
}
/* used by shrink_glob() timer routine */
boolean
eating_glob(struct obj *glob)
{
return (g.occupation == eatfood && glob == g.context.victual.piece);
}
/*
* Called on "first bite" of (non-corpse) food, after touchfood() has
* marked it 'partly eaten'. Used for non-rotten non-tin non-corpse food.
@@ -2322,8 +2330,8 @@ edibility_prompts(struct obj *otmp)
*/
char buf[BUFSZ], foodsmell[BUFSZ],
it_or_they[QBUFSZ], eat_it_anyway[QBUFSZ];
boolean cadaver = (otmp->otyp == CORPSE || otmp->globby),
stoneorslime = FALSE;
/* 3.7: decaying globs don't become tainted anymore; in 3.6, they did */
boolean cadaver = (otmp->otyp == CORPSE), stoneorslime = FALSE;
int material = objects[otmp->otyp].oc_material, mnum = otmp->corpsenm;
long rotted = 0L;
@@ -2334,7 +2342,9 @@ edibility_prompts(struct obj *otmp)
if (cadaver || otmp->otyp == EGG || otmp->otyp == TIN) {
/* These checks must match those in eatcorpse() */
stoneorslime = (mnum >= LOW_PM && flesh_petrifies(&mons[mnum]) && !Stone_resistance
stoneorslime = (mnum >= LOW_PM
&& flesh_petrifies(&mons[mnum])
&& !Stone_resistance
&& !poly_when_stoned(g.youmonst.data));
if (mnum == PM_GREEN_SLIME || otmp->otyp == GLOB_OF_GREEN_SLIME)

View File

@@ -236,11 +236,10 @@ loot_xname(struct obj *obj)
three group together */
if (obj->otyp == TOWEL)
obj->spe = 0;
/* group "<size> glob of <foo>" by <foo> rather than by <size> */
/* group globs by monster type rather than by size: force all to
have the same size adjective hence same "small glob of " prefix */
if (obj->globby)
obj->owt = 200; /* 200: weight of combined glob from ten creatures
(five or fewer is "small", more than fifteen is
"large", in between has no prefix) */
obj->owt = 20; /* weight of a fresh glob (one pudding's worth) */
/* suppress user-assigned name */
if (save_oname && !obj->oartifact)
ONAME(obj) = 0;

View File

@@ -7,6 +7,7 @@
static void mkbox_cnts(struct obj *);
static unsigned nextoid(struct obj *, struct obj *);
static int item_on_ice(struct obj *);
static void obj_timer_checks(struct obj *, xchar, xchar, int);
static void container_weight(struct obj *);
static struct obj *save_mtraits(struct obj *, struct monst *);
@@ -877,6 +878,7 @@ mksobj(int otyp, boolean init, boolean artif)
otmp->known = otmp->dknown = 1;
otmp->corpsenm = PM_GRAY_OOZE
+ (otmp->otyp - GLOB_OF_GRAY_OOZE);
start_glob_timeout(otmp, 0L);
} else {
if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING
&& otmp->otyp != KELP_FROND && !rn2(6)) {
@@ -1264,6 +1266,201 @@ start_corpse_timeout(struct obj *body)
(void) start_timer(when, TIMER_OBJECT, action, obj_to_any(body));
}
/* used by item_on_ice() and shrink_glob() */
enum obj_on_ice {
NOT_ON_ICE = 0,
SET_ON_ICE = 1,
BURIED_UNDER_ICE = 2
};
/* used by shrink_glob(); is 'item' or enclosing container on or under ice? */
static int
item_on_ice(struct obj *item)
{
struct obj *otmp;
xchar ox, oy;
otmp = item;
/* if in a container, it might be nested so find outermost one since
that's the item whose location needs to be checked */
while (otmp->where == OBJ_CONTAINED)
otmp = otmp->ocontainer;
if (get_obj_location(otmp, &ox, &oy, BURIED_TOO)) {
switch (otmp->where) {
case OBJ_FLOOR:
if (is_ice(ox, oy))
return SET_ON_ICE;
break;
case OBJ_BURIED:
if (is_ice(ox, oy))
return BURIED_UNDER_ICE;
break;
default:
break;
}
}
return NOT_ON_ICE;
}
/* schedule a timer that will shrink the target glob by 1 unit of weight */
void
start_glob_timeout(
struct obj *obj, /* glob */
long when) /* when to shrink; if 0L, use random value close to 25 */
{
if (!obj->globby) {
impossible("start_glob_timeout for non-glob [%s: %s]?",
obj->otyp, simpleonames(obj));
return; /* skip timer creation */
}
/* sanity precaution */
if (obj->timed)
(void) stop_timer(SHRINK_GLOB, obj_to_any(obj));
if (when < 1L) /* caller usually passes 0L; should never be negative */
when = 25L + (long) rn2(5) - 2L; /* 25+[0..4]-2 => 23..27, avg 25 */
/* 1 new glob weighs 20 units and loses 1 unit every 25 turns,
so lasts for 500 turns, twice as long as the average corpse */
(void) start_timer(when, TIMER_OBJECT, SHRINK_GLOB, obj_to_any(obj));
}
/* globs have quantity 1 and size which varies by multiples of 20 in owt;
they don't become tainted with age, but every 25 turns this timer runs
and reduces owt by 1; when it hits 0, destroy the glob (if some other
part of the program destroys it, the timer will be cancelled) */
void
shrink_glob(
anything *arg, /* glob (in arg->a_obj) */
long expire_time UNUSED) /* timer callback data, not referenced here */
{
char globnambuf[BUFSZ];
int globloc;
struct obj *obj = arg->a_obj;
boolean ininv = (obj->where == OBJ_INVENT),
shrink = FALSE, gone = FALSE, updinv = FALSE;
struct obj *contnr = (obj->where == OBJ_CONTAINED) ? obj->ocontainer : 0,
*topcontnr = 0;
unsigned old_top_owt = 0;
if (!obj->globby) {
impossible("shrink_glob for non-glob [%s: %s]?",
obj->otyp, simpleonames(obj));
return; /* old timer is gone, don't start a new one */
}
/* note: if check_glob() complains about a problem, the " obj " here
will be replaced in the feedback with info about this glob */
check_glob(obj, "shrink obj ");
/*
* When on ice, only shrink every third try. If buried under ice,
* don't shrink at all, similar to being contained in an ice box
* except that the timer remains active. [FIXME: stop the timer
* for obj in pool that becomes frozen, restart it if/when unburied.]
*
* If the glob is actively being eaten by hero, skip weight reduction
* to avoid messing up the context.victual data (if/when eaten by a
* monster, timer won't have a chance to run before meal is finished).
*/
if (eating_glob(obj)
|| (globloc = item_on_ice(obj)) == BURIED_UNDER_ICE
|| (globloc == SET_ON_ICE && (g.moves % 3L) == 1L)) {
/* schedule next shrink attempt; for the being eaten case, the
glob and its timer might be deleted before this kicks in */
start_glob_timeout(obj, 0L);
return;
}
/* format "Your/Shk's/The [partly eaten] glob of <goo>" into
globnambuf[] before shrinking the glob; Yname2() calls yname()
which calls xname() which ordinarly leaves "partly eaten" to
doname() rather than inserting that itself; ask xname() to add
that when appropriate */
iflags.partly_eaten_hack = TRUE;
Strcpy(globnambuf, Yname2(obj));
iflags.partly_eaten_hack = FALSE;
if (obj->owt > 0) {
shrink = (obj->owt % 20) == 0;
obj->owt -= 1;
/* if glob is partly eaten, reduce the amount still available (but
not all the way to 0 which would change it back to untouched) */
if (obj->oeaten > 1)
obj->oeaten -= 1;
}
gone = !obj->owt;
/* timer might go off when the glob is migrating to another level and
possibly delete it; messages are only given for in-open-inventory,
inside-container-in-invent, and going away when can-see-on-floor */
if (ininv) {
if (shrink || gone)
pline("%s %s.", globnambuf,
/* globs always have quantity 1 so we don't need otense()
because the verb always references a singular item */
gone ? "dissippates completely" : "shrinks");
updinv = TRUE;
} else if (contnr) {
/* when in a container, it might be nested so find outermost one */
topcontnr = contnr;
while (topcontnr->where == OBJ_CONTAINED)
topcontnr = topcontnr->ocontainer;
/* obj's weight has been reduced, but weight(s) of enclosing
container(s) haven't been adjusted for that yet */
old_top_owt = topcontnr->owt;
/* update those weights now; recursively updates nested containers */
container_weight(obj->ocontainer);
if (topcontnr->where == OBJ_INVENT) {
/* for regular containers, the weight will always be reduced
when glob's weight has been reduced but we only say so
when shrinking beneath an integral number of globs or
if we're going to report a change in carrying capacity;
for a non-cursed bag of holding the total weight might not
change because only a fraction of glob's weight is counted;
however, always say the bag is lighter for the 'gone' case */
if (gone || (shrink && topcontnr->owt != old_top_owt)
|| near_capacity() != g.oldcap)
pline("%s %s %s lighter.", Yname2(topcontnr),
/* containers also always have quantity 1 */
(topcontnr->owt != old_top_owt) ? "becomes" : "seems",
/* TODO? maybe also skip "slightly" if description
is changing (from "very large" to "large",
"large" to "medium", or "medium to "small") */
!gone ? "slightly " : "");
updinv = TRUE;
}
}
if (gone) {
xchar ox = 0, oy = 0;
/* check location for visibility before destroying obj */
boolean seeit = (obj->where == OBJ_FLOOR
&& get_obj_location(obj, &ox, &oy, 0)
&& cansee(ox, oy));
/* weight has been reduced to 0 so destroy the glob */
obj_extract_self(obj);
obfree(obj, (struct obj *) 0);
if (seeit) {
newsym(ox, oy);
if ((ox != u.ux || oy != u.uy) && !strncmp(globnambuf, "The ", 4))
/* fortunately none of the glob adjectives warrant "An " */
(void) strsubst(globnambuf, "The ", "A ");
/* again, quantity is always 1 so no need for otense()/vtense() */
pline("%s fades away.", globnambuf);
}
} else {
/* schedule next shrink ~25 turns from now */
start_glob_timeout(obj, 0L);
}
if (updinv) {
update_inventory();
(void) encumber_msg();
}
}
void
maybe_adjust_light(struct obj *obj, int old_range)
{
@@ -2636,9 +2833,15 @@ check_glob(struct obj *obj, const char *mesg)
#define HIGHEST_GLOB GLOB_OF_BLACK_PUDDING
if (obj->quan != 1L || obj->owt == 0
|| obj->otyp < LOWEST_GLOB || obj->otyp > HIGHEST_GLOB
#if 0 /*
* This was relevant before the shrink_glob timer was adopted but
* now any glob could have a weight that isn't a multiple of 20.
*/
/* a partially eaten glob could have any non-zero weight but an
intact one should weigh an exact multiple of base weight (20) */
|| ((obj->owt % objects[obj->otyp].oc_weight) != 0 && !obj->oeaten)) {
|| ((obj->owt % objects[obj->otyp].oc_weight) != 0 && !obj->oeaten)
#endif
) {
char mesgbuf[BUFSZ], globbuf[QBUFSZ];
Sprintf(globbuf, " glob %d,quan=%ld,owt=%u ",
@@ -2902,12 +3105,11 @@ obj_nexto_xy(struct obj *obj, int x, int y, boolean recurs)
}
/*
* Causes one object to absorb another, increasing
* weight accordingly. Frees obj2; obj1 remains and
* is returned.
* Causes one object to absorb another, increasing weight
* accordingly. Frees obj2; obj1 remains and is returned.
*/
struct obj *
obj_absorb(struct obj** obj1, struct obj** obj2)
obj_absorb(struct obj **obj1, struct obj **obj2)
{
struct obj *otmp1, *otmp2;
int o1wt, o2wt;
@@ -2934,11 +3136,22 @@ obj_absorb(struct obj** obj1, struct obj** obj2)
agetmp = (((g.moves - otmp1->age) * o1wt
+ (g.moves - otmp2->age) * o2wt)
/ (o1wt + o2wt));
otmp1->age = g.moves - agetmp; /* conv. relative back to absolute */
/* convert relative age back to absolute age */
otmp1->age = g.moves - agetmp;
otmp1->owt += o2wt;
if (otmp1->oeaten || otmp2->oeaten)
otmp1->oeaten = o1wt + o2wt;
otmp1->quan = 1L;
if (otmp1->globby && otmp2->globby) {
/* average (not weighted, no pun intended) the two globs'
shrink timers and use that to give otmp1 a new timer */
long tm1 = stop_timer(SHRINK_GLOB, obj_to_any(otmp1)),
tm2 = stop_timer(SHRINK_GLOB, obj_to_any(otmp2));
tm1 = ((tm1 ? tm1 : 25L) + (tm2 ? tm2 : 25L) + 1L) / 2L;
start_glob_timeout(otmp1, tm1);
}
/* get rid of second glob, return augmented first one */
obj_extract_self(otmp2);
dealloc_obj(otmp2);
*obj2 = (struct obj *) 0;

View File

@@ -502,10 +502,7 @@ xname_flags(
if (!Blind && !g.distantname)
obj->dknown = 1;
if (Role_if(PM_CLERIC))
obj->bknown = 1; /* actively avoid set_bknown();
* we mustn't call update_inventory() now because
* it would call xname() (via doname()) recursively
* and could end up clobbering all the obufs... */
obj->bknown = 1; /* avoid set_bknown() to bypass update_inventory() */
if (iflags.override_ID) {
known = dknown = bknown = TRUE;
@@ -604,6 +601,7 @@ xname_flags(
Strcat(buf, dn);
break;
case FOOD_CLASS:
/* we could include partly-eaten-hack on fruit but don't need to */
if (typ == SLIME_MOLD) {
struct fruit *f = fruit_from_indx(obj->spe);
@@ -630,15 +628,22 @@ xname_flags(
}
break;
}
if (iflags.partly_eaten_hack && obj->oeaten) {
/* normally "partly eaten" is supplied by doname() when
appropriate and omitted by xname(); shrink_glob() wants
it but uses Yname2() -> yname() -> xname() rather than
doname() so we've added an external flag to request it */
Strcat(buf, "partly eaten ");
}
if (obj->globby) {
Sprintf(buf, "%s%s",
Sprintf(eos(buf), "%s%s",
(obj->owt <= 100)
? "small "
: (obj->owt > 500)
? "very large "
: (obj->owt > 300)
? "large "
: "",
: "medium ",
actualn);
break;
}
@@ -3404,7 +3409,7 @@ readobjnam_init(char *bp, struct _readobjnam_data *d)
d->name = (const char *) 0;
d->ftype = g.context.current_fruit;
(void) memset(d->globbuf, '\0', sizeof d->globbuf);
(void) memset(d->fruitbuf, '\0', sizeof d->globbuf);
(void) memset(d->fruitbuf, '\0', sizeof d->fruitbuf);
}
/* return 1 if d->bp is empty or contains only various qualifiers like
@@ -3550,9 +3555,11 @@ readobjnam_preparse(struct _readobjnam_data *d)
break;
d->gsize = 1;
} else if (!strncmpi(d->bp, "medium ", l = 7)) {
/* xname() doesn't display "medium" but without this
there'd be no way to ask for the intermediate size
("glob" without size prefix yields smallest one) */
/* 3.7: in 3.6, "medium" was only used during wishing and the
mid-size glob had no adjective when formatted, but as of
3.7, "medium" has become an explicit part of the name for
combined globs of at least 5 individual ones (owt >= 100)
and less than 15 (owt < 300) */
d->gsize = 2;
} else if (!strncmpi(d->bp, "large ", l = 6)) {
/* "large" might be part of monster name (dog, cat, koboold,

View File

@@ -2351,12 +2351,7 @@ in_container(struct obj *obj)
/* boxes, boulders, and big statues can't fit into any container */
if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER
|| (obj->otyp == STATUE && bigmonst(&mons[obj->corpsenm]))) {
/*
* xname() uses a static result array. Save obj's name
* before g.current_container's name is computed. Don't
* use the result of strcpy() within You() --- the order
* of evaluation of the parameters is undefined.
*/
/* consumes multiple obufs but not enough to overwrite the result */
Strcpy(buf, the(xname(obj)));
You("cannot fit %s into %s.", buf, the(xname(g.current_container)));
return 0;
@@ -2391,6 +2386,8 @@ in_container(struct obj *obj)
/* if this is the corpse of a cancelled ice troll, uncancel it */
if (obj->corpsenm == PM_ICE_TROLL && has_omonst(obj))
OMONST(obj)->mcan = 0;
} else if (obj->globby && obj->timed) {
(void) stop_timer(SHRINK_GLOB, obj_to_any(obj));
}
} else if (Is_mbag(g.current_container) && mbag_explodes(obj, 0)) {
/* explicitly mention what item is triggering the explosion */
@@ -2531,6 +2528,9 @@ removed_from_icebox(struct obj *obj)
otherwise start a rot-away timer (even for other trolls) */
obj->norevive = iceT ? 0 : 1;
start_corpse_timeout(obj);
} else if (obj->globby) {
/* non-frozen globs gradually shrink away to nothing */
start_glob_timeout(obj, 0L);
}
}
}

View File

@@ -1011,7 +1011,7 @@ learn_egg_type(int mnum)
/* Attach a fig_transform timeout to the given figurine. */
void
attach_fig_transform_timeout(struct obj* figurine)
attach_fig_transform_timeout(struct obj *figurine)
{
int i;
@@ -1120,7 +1120,7 @@ slip_or_trip(void)
/* Print a lamp flicker message with tailer. */
static void
see_lamp_flicker(struct obj* obj, const char* tailer)
see_lamp_flicker(struct obj *obj, const char *tailer)
{
switch (obj->where) {
case OBJ_INVENT:
@@ -1135,7 +1135,7 @@ see_lamp_flicker(struct obj* obj, const char* tailer)
/* Print a dimming message for brass lanterns. */
static void
lantern_message(struct obj* obj)
lantern_message(struct obj *obj)
{
/* from adventure */
switch (obj->where) {
@@ -1158,7 +1158,7 @@ lantern_message(struct obj* obj)
* See begin_burn() for meanings of obj->age and obj->spe.
*/
void
burn_object(anything* arg, long timeout)
burn_object(anything *arg, long timeout)
{
struct obj *obj = arg->a_obj;
boolean canseeit, many, menorah, need_newsym, need_invupdate;
@@ -1466,7 +1466,7 @@ burn_object(anything* arg, long timeout)
* This is a "silent" routine - it should not print anything out.
*/
void
begin_burn(struct obj* obj, boolean already_lit)
begin_burn(struct obj *obj, boolean already_lit)
{
int radius = 3;
long turns = 0;
@@ -1558,7 +1558,7 @@ begin_burn(struct obj* obj, boolean already_lit)
* light source.
*/
void
end_burn(struct obj* obj, boolean timer_attached)
end_burn(struct obj *obj, boolean timer_attached)
{
if (!obj->lamplit) {
impossible("end_burn: obj %s not lit", xname(obj));
@@ -1582,19 +1582,18 @@ end_burn(struct obj* obj, boolean timer_attached)
* Cleanup a burning object if timer stopped.
*/
static void
cleanup_burn(anything* arg, long expire_time)
cleanup_burn(anything *arg, long expire_time)
{
struct obj *obj = arg->a_obj;
if (!obj->lamplit) {
impossible("cleanup_burn: obj %s not lit", xname(obj));
return;
}
del_light_source(LS_OBJECT, obj_to_any(obj));
/* restore unused time */
obj->age += expire_time - g.moves;
obj->lamplit = 0;
if (obj->where == OBJ_INVENT)
@@ -1721,15 +1720,9 @@ typedef struct {
timeout_proc f, cleanup;
#ifdef VERBOSE_TIMER
const char *name;
#define TTAB(a, b, c) \
{ \
a, b, c \
}
#define TTAB(a, b, c) { a, b, c }
#else
#define TTAB(a, b, c) \
{ \
a, b \
}
#define TTAB(a, b, c) { a, b } /* ignore c for !VERBOSE_TIMER */
#endif
} ttable;
@@ -1742,7 +1735,8 @@ static const ttable timeout_funcs[NUM_TIME_FUNCS] = {
TTAB(burn_object, cleanup_burn, "burn_object"),
TTAB(hatch_egg, (timeout_proc) 0, "hatch_egg"),
TTAB(fig_transform, (timeout_proc) 0, "fig_transform"),
TTAB(melt_ice_away, (timeout_proc) 0, "melt_ice_away")
TTAB(melt_ice_away, (timeout_proc) 0, "melt_ice_away"),
TTAB(shrink_glob, (timeout_proc) 0, "shrink_glob"),
};
#undef TTAB