supply chest fixes for "odd encumbrance behavior"

Changing the quantity to 2 (50:50 chance) when creating a potion of
healing (also 50:50 chance for each attempt) to place inside a supply
chest wasn't updating the potion stack's weight, resulting in the odd
encumbrance behavior that was reported last December.

Taking the stack out of the container doesn't fix the weight but
drinking one of the potions splits the stack of 2 into two stacks
of 1 and does update the weight for both.  That gives the hero higher
encumbrance when the formerly weightless one has its proper weight.
Finishing drinking the potion uses it up, removing second potion's
weight again.  When below an encumbrance threshold by the weight of
one potion or less, player will see encumbrance increase and then
decrease, with healing message given before both due to sequencing.

Supply chests weren't having their own weight updated when they were
populated, so would behave as if empty if hero carried them around.
Removing something, breaking something by kicking the chest, or adding
something would update its weight to match its contents.

I also noticed a refutation (or should that be rebuttable?) to my own
remarks in this:

| commit cd91d0630b
| Author: PatR <rankin@nethack.org>
| Date:   Sat Dec 30 17:10:39 2023 -0800
|
| github issue #1180 - humans and murder
|
| Issue reported by Umbire:  reviving a human corpse into a human
| monster and then killing it entails murder penalty even when it is
| hostile.
|
| This is probably a non-issue.  Human monsters tend to not leave
| human corpses, they leave shopkeeper corpses or sergeant corpses
[...]

Dead fake hero corpses placed at trap locations on early levels are
leaving plain human|dwarf|elf|gnome|orc corpses rather than fake
player monster ones (which are always human but resurrect as player
monsters rather than as plain humans), so there are more plain human
corpses now than there were in 3.6.x or early to-be-3.7.  I've added
a comment about the situation.
This commit is contained in:
PatR
2024-01-23 15:42:19 -08:00
parent 829f9f65f7
commit 267daeaa0f
3 changed files with 71 additions and 39 deletions

View File

@@ -1838,6 +1838,13 @@ farlook at something that was on top of an engraving or grave would report
the engraving text or headstone epitaph along with the 'something'
when carrying 52 items (excluding gold), hero couldn't pick up a thrown,
stolen, or dropped item which was split off from a still-carried stack
supply chests on early levels weighed the same as empty chests until something
was added or removed
stacked pair of potions of healing in supply chest weighed same as one potion;
drinking one of the two gave a healing message, then both had their
weight updated as their stack was split; if close to an encumbrance
threshold, new weight would trigger an encumbrance increase message,
immediately followed a decrease message when the potion got used up
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository

View File

@@ -949,29 +949,27 @@ fill_ordinary_room(
supply_chest->olocked = !!(rn2(6));
do {
/* 50% this is a potion of healing */
if (rn2(2)) {
otyp = POT_HEALING;
} else {
static const int supply_items[] = {
POT_EXTRA_HEALING,
POT_SPEED,
POT_GAIN_ENERGY,
SCR_ENCHANT_WEAPON,
SCR_ENCHANT_ARMOR,
SCR_CONFUSE_MONSTER,
SCR_SCARE_MONSTER,
WAN_DIGGING,
SPE_HEALING,
};
static const int supply_items[] = {
POT_EXTRA_HEALING,
POT_SPEED,
POT_GAIN_ENERGY,
SCR_ENCHANT_WEAPON,
SCR_ENCHANT_ARMOR,
SCR_CONFUSE_MONSTER,
SCR_SCARE_MONSTER,
WAN_DIGGING,
SPE_HEALING,
};
otyp = ROLL_FROM(supply_items);
}
/* 50% this is a potion of healing */
otyp = rn2(2) ? POT_HEALING : ROLL_FROM(supply_items);
otmp = mksobj(otyp, TRUE, FALSE);
if (otyp == POT_HEALING && rn2(2))
if (otyp == POT_HEALING && rn2(2)) {
otmp->quan = 2;
otmp->owt = weight(otmp);
}
cursed = otmp->cursed;
add_to_container(supply_chest, otmp);
add_to_container(supply_chest, otmp); /* owt updated below */
++tryct;
if (tryct == 50) {
@@ -1004,21 +1002,29 @@ fill_ordinary_room(
otmp = mkobj(oclass, FALSE);
if (oclass == SPBOOK_no_NOVEL) {
/* bias towards lower level by generating again
and taking the lower-level book */
struct obj *otmp2 = mkobj(oclass, FALSE);
int pass, maxpass = (depth(&u.uz) > 2) ? 2 : 3;
if (objects[otmp->otyp].oc_level
<= objects[otmp2->otyp].oc_level) {
dealloc_obj(otmp2);
} else {
dealloc_obj(otmp);
otmp = otmp2;
/* bias towards lower level by generating again
and taking the lower-level book; do that three
times if on level 1 or 2, twice when deeper */
for (pass = 1; pass <= maxpass; ++pass) {
struct obj *otmp2 = mkobj(oclass, FALSE);
if (objects[otmp->otyp].oc_level
<= objects[otmp2->otyp].oc_level) {
dealloc_obj(otmp2);
} else {
dealloc_obj(otmp);
otmp = otmp2;
}
}
}
add_to_container(supply_chest, otmp);
add_to_container(supply_chest, otmp); /* owt updated below */
}
/* add_to_container() doesn't update the container's weight */
supply_chest->owt = weight(supply_chest);
skip_chests = TRUE; /* don't want a second chest in this room */
}
}
@@ -1029,7 +1035,8 @@ fill_ordinary_room(
* of rooms; about 5 - 7.5% for 2 boxes, least likely
* when few rooms; chance for 3 or more is negligible.
*/
if (!rn2(gn.nroom * 5 / 2) && somexyspace(croom, &pos) && !skip_chests)
/*assert(gn.nroom > 0); // must be true because we're filling a room*/
if (!skip_chests && rn2(gn.nroom * 5 / 2) && somexyspace(croom, &pos))
(void) mksobj_at(rn2(3) ? LARGE_BOX : CHEST,
pos.x, pos.y, TRUE, FALSE);
@@ -1702,8 +1709,7 @@ mktrap_victim(struct trap *ttmp)
otmp = mksobj(rn2(4) ? TALLOW_CANDLE : WAX_CANDLE,
TRUE, FALSE);
otmp->quan = 1;
otmp->blessed = 0;
otmp->cursed = 1;
curse(otmp);
otmp->owt = weight(otmp);
place_object(otmp, x, y);
}
@@ -1711,6 +1717,14 @@ mktrap_victim(struct trap *ttmp)
default:
/* the most common race */
victim_mnum = PM_HUMAN;
/*
* FIXME:
* If resurrected, this corpse will produce a plain human.
* PM_HUMAN is used as a placeholder for zombie/mummy/vampire
* corpses and doesn't ordinarily occur as a living monster.
* Maybe we should generate and attach montraits for a very low
* level fake player?
*/
break;
}
otmp = mkcorpstat(CORPSE, NULL, &mons[victim_mnum], x, y,

View File

@@ -220,6 +220,8 @@ mkobj_erosions(struct obj *otmp)
}
}
/* make a random object of class 'let' at a specific location;
'let' might be random class; place_object() will validate <x,y> */
struct obj *
mkobj_at(char let, coordxy x, coordxy y, boolean artif)
{
@@ -230,8 +232,12 @@ mkobj_at(char let, coordxy x, coordxy y, boolean artif)
return otmp;
}
/* make a specific object at a specific location */
struct obj *
mksobj_at(int otyp, coordxy x, coordxy y, boolean init, boolean artif)
mksobj_at(
int otyp,
coordxy x, coordxy y,
boolean init, boolean artif)
{
struct obj *otmp;
@@ -240,12 +246,13 @@ mksobj_at(int otyp, coordxy x, coordxy y, boolean init, boolean artif)
return otmp;
}
/* used for extra orctown loot */
struct obj *
mksobj_migr_to_species(
int otyp,
unsigned int mflags2,
boolean init,
boolean artif)
unsigned mflags2,
boolean init, boolean artif)
{
struct obj *otmp;
@@ -371,6 +378,7 @@ mkbox_cnts(struct obj *box)
}
(void) add_to_container(box, otmp);
}
/* caller will update box->owt */
}
/* select a random, common monster type */
@@ -848,8 +856,7 @@ unknow_object(struct obj *obj)
obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1;
}
/* do some initialization to a newly created object.
object otyp must be set. */
/* do some initialization to newly created object; otyp must already be set */
static void
mksobj_init(struct obj *otmp, boolean artif)
{
@@ -1124,7 +1131,7 @@ mksobj_init(struct obj *otmp, boolean artif)
otmp->corpsenm = rndmonnum();
if (!verysmall(&mons[otmp->corpsenm])
&& rn2(level_difficulty() / 2 + 10) > 10)
(void) add_to_container(otmp,
(void) add_to_container(otmp, /* callber will update owt */
mkobj(SPBOOK_no_NOVEL, FALSE));
}
/* boulder init'd below in the 'regardless of !init' code */
@@ -2578,6 +2585,10 @@ add_to_minv(struct monst *mon, struct obj *obj)
/*
* Add obj to container, make sure obj is "free". Returns (merged) obj.
* The input obj may be deleted in the process.
*
* Caveat: this does not update the container's weight [possibly to
* prevent that from being recalculated repeatedly when adding multiple
* items].
*/
struct obj *
add_to_container(struct obj *container, struct obj *obj)