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:
@@ -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
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -34,6 +34,7 @@ enum timeout_types {
|
||||
HATCH_EGG,
|
||||
FIG_TRANSFORM,
|
||||
MELT_ICE_AWAY,
|
||||
SHRINK_GLOB,
|
||||
|
||||
NUM_TIME_FUNCS
|
||||
};
|
||||
|
||||
20
src/eat.c
20
src/eat.c
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
225
src/mkobj.c
225
src/mkobj.c
@@ -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;
|
||||
|
||||
27
src/objnam.c
27
src/objnam.c
@@ -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,
|
||||
|
||||
12
src/pickup.c
12
src/pickup.c
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user