Fix a buglist entry: fracturing a boulder or statue owned by a shop
was ignored by the shopkeeper. The existing vague fixes entry of "some
shop thefts weren't charged" covers this.
Suppress "Mr" or "Ms" title for shopkeepers when they're going by a
first name rather than a surname. The bug report was for Izchak, but it
would have happened with the two last resort names (which I've never seen
in actual use) and for the "hippie names" used in post-3.4.x health food
shops. I have not attempted to specify gender for those, just flagged
them as first names. This prepends a prefix character to the name string
(see comment in shknam.c) to specify gender and/or first name vs surname.
Shop items stolen or destroyed without being in inventory were handled
inconsistently compared to simply picking up unpaid items because different
criteria got used to decide whether the shk cares about something. Last
December a hack to deal with this for container contents was introduced but
that left the problem for ordinary items. This patch attempts to address
it by using a common check for theft and for pickup's add-to-bill.
It hasn't had nearly enough testing and I won't be very surprised if
one or more new obscure shop bugs have now come into being, but perhaps
they'll at least be consistent bugs as far as shop billing is concerned....
A user reported that when breaking potions inside a box in a shop, he
wasn't charged for them. The code was calling stolen_value() as intended,
but that routine only charged for types of items which the shop normally
carries. That meant that breaking the contents of a box in a general
store would charge for them but doing so in a tool shop would, not even
though the tool shopkeeper would gladly sell such things when you picked
them up instead of causing them to go away.
When fixing this, I noticed that stolen_value() was only charging
for single items. Most of the time that was right, because throwing and
kicking things always split one off, but there are cases (such as zapping
a wand of teleportation at shop goods) where an entire stack gets stolen
as a group. This makes stolen_value() handle all quantities.
Patch was sent in by <Someone> on Sep 8:
This bug causes a number of impossible messages (starting with splitbill:
no resident shopkeeper??)
Repeat by:
Enter a large shop.
Wish for a large stack of projectiles.
Sell your projectiles and then pick them up again.
Trap shopkeeper against the door with a scroll of earth.
Throw the projectiles at the shopkeeper to anger him.
Move away from the boulder trap and wait for the shopkeeper to leave the
shop.
Throw one of the projectiles at the free space.
Fix the situation <Someone> reported where a shopkeeper removing a trap
from the shop doorway yielded "you see the shop door reappear" instead of
reporting about the trap. It made sense if the door had been destroyed
but not when intact.
For trunk only, try to fix up the shop repair message situation when
multiple repairs occur at the same time. Some things were being treated
as mutually exclusive when they aren't. This part needs more testing,
probably using a debugger to force multiple pending repairs to all occur
on the same turn. At any rate, using wizard mode and hoping for some
simultaneous activity was ineffective.
It was possible to get a shopkeeper to carry the Amulet from the
bottom of the dungeon up to the location of his shop, thereby bypassing
the usual labor of lugging it up yourself. [Drop the Amulet somewhere;
rob a shop so that the Kops are summoned and the shk comes after you;
when shk is next you, level teleport to the Amulet (probably two hops,
one to the Valley and another deeper into Gehennom); walk to the vicinity
of the Amulet; shk will eventually pick it up (shopkeepers like to pick
up magic items); now, pay him for the stolen goods--he'll be pacified
and migrate back to his shop, taking his inventory with him; lastly,
return to his shop and relieve him of his burder.] This patch makes
shopkeepers drop the Amulet or invocation tools if/when they set set to
migrate to their normal location.
Also fix another long standing risk that a monster that is sent
away (nurse when healing, Kops when you pacify a shopkeeper) might be
carrying the Amulet or one of the invocation tools and make the game
unwinnable. I doubt that that's ever actually happened but I think it'd
be possible if a monster that likes magic items ever got polymorphed
into a Kop. Such dismissed monsters will now drop the same stuff as
the shk above prior to leaving the game.
Pat verified something I had wondered about, that various tests of mcanmove
in shk.c should have also been testing mcanmove. There may well be other
tests of mcanmove in other files that need fixing.
+ Separate the two uses of flags.soundok.
+ Player-settable option is now called "acoustics".
+ Deafness is now handled as a full-fledged attribute.
+ Check for deafness in You_hear(), rather than caller.
+ Check for deafness in caller, rather than verbalize(),
because gods can speak to characters in spite of deafness.
+ Since changes are being made to prop.h, reorder it to the
same order as youprop.h and enlightenment.
There are still some extraneous checks and missing checks
for deafness, which will be followed up in a future patch.
Because of the size of this patch and its savefile incompatibilities,
it is only being applied to the trunk code. Portions of this patch
were written by Michael Allison.
Pat Rankin wrote:
> collect them all into some new struct and
> save that separately rather than jamming more non-option stuff
> into struct flags.
This patch:
- collects all context/tracking related fields from flags
into a new structure called "context."
It also adds the following to the new structure:
- stethoscope turn support
- victual support
- tin support
This patch introduces a change to yname() and Yname2() that avoids the
possessive "your" for the hero's normal, fully identified artifacts.
Quest artifacts still get the possessive, as do all other objects and all
objects not in the hero's possession. shk_your()/Shk_Your() are used in
many places with a specific, generalized name for the object, so I didn't
introduce the artifact behavior there, although I did change them to append
a space, which simplified some other code. Through added use of yname(),
there may be some places that used to just say "corpse" that will now be more
descriptive via yname()'s use of cxname(). I'm sure <Someone> will point
out any such places that are too onerous, although nothing obviously is.
I took the opportunity to inspect many uses of "your" and even Your(). Two
new functions are also introduced, yobjnam() and Yobjnam2(), which work
like aobjnam() and yname() combined, because I found that many uses of
aobjnam() were preceeded by "your" and I couldn't generally provide the
desired behavior for artifacts (or future artifacts) without a combined
function. In some cases, this change allowed better sharing of code.
rust_dmg() still takes a string as input which is sometimes initialized
from xname() and often prepends "your" to it. Currently, this isn't a
problem since there currently are no normal, armor artifacts. If/when any
are introduced, rust_dmg() will need to be addressed.
The patch is for the trunk only. A lot of research was required and I
didn't feel the upside was there for repeating it in the 3.4.3 branch.
Quoting the buglist: "If shk.c does get modified, I'd
like to see a call to rouse_shk() added at the start of rob_shop().
If the shk wakes up for buying and selling, he ought to wake up for
robbery--even when it's covered by the customer's credit--too."
A recent report noted that if you are invisible, teleport into a shop,
steal something, teleport out, and then return, the shopkeeper will become
pacified. This is because the pacification code occurred even if the
shopkeeper already knew your name, as long as the "Welcome" message had not
yet occurred. Implement <Someone>'s proposed fix: Before pacifying, either
the visitct must be zero (as per old code) or the customer name must
already be known. And, of course, the customer name must differ from the
current setting. This skips the pacification code in those situations
where the shopkeeper learned your name but was not happy about it (which is
what visitct > 0 implies, at least initially).
This also deals with an older bug report where you attack a shopkeeper
while outside the shop and then later enter the shop while the shopkeeper
is in it. hot_pursuit() sets the customer name, and the new check avoids
pacifying the shopkeeper for the same reason as noted above.
Although the overlay stuff is destined to be
removed someday, this patch just makes the
use of STATIC_DCL, STATIC_OVL consistent
in the trunk.
[As a side pointless experiment, I was able
to build a working 8086 port of 3.4.2 after
this change that worked correctly in limited
testing right up until it came time to enter
Ft. Ludios., where it couldn't allocated the
required amount of memory.]
Make a sleeping or paralyzed shopkeeper wake up if you drop something
he's interested in buying (covers the recently reported case where dropping
gold failed to add credit, but picking it back up increased shop dept) or
if you use the 'p'ay command while owing money. Sleeping shopkeeper is not
affected if you drop something he doesn't care about, or use 'p'ay when
there is no debt, or pick up shop goods (latter case is handled normally--
you'll owe money for the item even though the shk remains asleep).
This makes shopping become a little easier--you aren't stuck waiting
for the shopkeeper to wake up if you actually want to pay for something--
in the rare case where the shopkeeper has been put to sleep, but it's an
awful lot simpler than any other reasonable way I could think of to deal
with the [lack of] credit problem.
This makes the snoring message handling moot--it no longer exists.
(It wasn't very reasonable to begin with, because the program can't tell
whether mon->mfrozen is for timed sleep or timed paralysis so avoided
giving that message for temporary sleep. There ought to be two separate
counters; probing is another case where vague messages are given because
the program can't tell the reason why a monster can't move.)
Correct the unreachable "snores" message From a bug report.
Applied to trunk only in hopes that beta8 might be the last for 3.4.2.
The fixes entry is generic since I'm sure other similar messages will be fixed.
From the newsgroup: leash found inside a bones level shop was flagged
as "in use". 3.4.0 had a fix for that which works for most cases, but not
when the shopkeeper has taken the dead character's inventory just before
saving the bones file.
This also adds an entry to the branch copy of fixes34.2 to synchronize
it with the trunk copy.
If you zapped a WoStriking while outside a shop and broke the door and 2
separate objects, the shopkeeper would come out to get paid but if you
tried, it would result in "dopay: not to shopkeeper?" due to stolen_value
not adding the cost of the 2nd object to the right accumulator.
The "following" flag could get set in several places where it was not
obvious that the customer name would be remembered. Since the shopkeeper
should always get angry at the current player, set the name at the same
place that the flag is set.
While an object is being thrown, it isn't on any list. This means that
killing a shopkeeper with an unpaid object wouldn't be able to clear the
unpaid bit. By the time the object lands, the shopkeeper is gone, and then
it's too late. Added a new global to track a thrown object, set it and later
clear it in throwit(), also clear it as needed in dealloc_obj(), and check
it in setpaid(). It should be possible to use this global to avoid losing
thrown objects during hangup saves as well. But that can wait.
Building with an old version of gcc with various warnings enabled
generated a lot of noise. Most of it was due to not guarding string
literals with `const', but there were a couple of actual problems too.
Fix the reported problem of getting impossible warnings for unpaid
inventory items during final disclosure if you level teleport out of
the dungeon while holding shop goods. The fix makes you trigger a shop
robbery first; that required a minor end of game change to prevent the
shopkeeper from seeming to tag along (shk would take your possessions
as if you'd died on the shop level).
From a bug report. I haven't looked closely, but I think this bug is just
in the development code. If you dig in a shop with a wand while carrying
unpaid stuff, the shopkeeper would grab your pack, including the wand but
w/o clearing current_wand. It seems the right thing is to just not grab
the current_wand, since it's not in your pack while you're zapping it.
In 3.4.0, you lost the wand too.
Reported to the list. Player breaks a wand of digging causing the
shopkeeper to fall. This didn't clear unpaid items. For now, this can
only occur due to player action, so added a call to make_angry_shk to
handle this situation.
- Breaking wand of digging dug through rock which should be undiggable.
Checks assumed pits would never show up in solid rock.
- Breaking wand of digging near shop walls wouldn't anger the shopkeeper
Checks assumed pits would never show up in walls, also, added a special
case to pay_for_damage to handle the case where you're falling thru and
can't be asked to pay.
- Shop walls wouldn't be restored if there are pits in the way.
Checks assumed pits would never show up in walls.
- If there was a hole outside the shop, you could kick stuff out of the
door into the hole without shopkeeper noticing. Added the missing check.
Change the message for paying off consumed items to
"You paid for a xxxx at a cost of nnn gold pieces."
to distinguish it from objects that you still have in your inventory which is
"You bought a xxx for nnn gold pieces."
The worn bits, et al, were not all cleared when the shopkeeper grabbed your
pack. This currently affects only alternate (non-twoweap) and quivered
objects. This could lead to a panic or a crash.
[ Fix a bug reported in the newsgroup; I thought I sent this last
week, but it isn't in the current code so I must have forgotten. ]
When I split u_left_shop() into two routines I neglected to
propagate the early return condition from the second half to the
first. The result is that if you leave a shop with unpaid goods
but have enough credit there to cover the cost, the shopkeeper
will take that credit and be satisified, but the kops were still
getting summoned as if he had been robbed.
- when a shopkeeper leaves the shop to chase the player, and the player
enters the shop, bill_p is set to an unusual value. bill_p needs to be set
back to a valid value if the shopkeeper re-enters the shop.
- Also, the u.ushops state needs to be updated when a shop becomes tended
again if the player is in the shop.
- introduce a new after_shk_move function to handle this
There was at least one more special case aside from throwing
(jetisoning items to reduce weight after falling in water) which
have needed the same extra code. This is a more general fix.
- new cxname() to simplify doing the right thing in increasingly common cases
- use for bullwhip snagging
- in shopkeeper offer code
- in a couple other existing places rather than duplicating CORPSE checks
- use singular(...) in "swings" cases, since only one can hit. Singular uses
corpse_xname automatically when appropriate
includes container contents, not just the cost of the
container itself (a prices in inventory phenomenon).
Along the way I discovered a peculiarity -
contained_cost() was adding up the cost of everything in
a container, even if you had stashed items in it that were your
own and not marked unpaid it seems.
I added a flag to force the code to only add objects
that were marked "unpaid" so I could use it in this new
instance, but I didn't change any of
the existing usages (I left the flag at FALSE which leaves
the consideration of the unpaid status alone just as
before).
Some of this is correction of some messages that were
wrong prior to this when dealing with selling of objects
inside a container when only part of the contents was unpaid.