Commit Graph

444 Commits

Author SHA1 Message Date
PatR
7fa328fda3 redo itemized shop billing for containers
Finish shop changes begun in 2674a9904d.

Fix the longstanding bug where shop paying with itemized buying would
reveal container contents if any unpaid items were inside containers,
regardless of whether the containers' contents were known yet, even
when the container was a locked box/chest or a cursed bag of holding.
Paying by menu made that be more noticeable but it has been present
ever since itemized paying was introduced.  I can't find any old bug
reports for it though.  I did find an old message of mine that claims
it's in bugzilla with a "#Hnnnn" tag.

This changes how buying containers and their contained items behaves.
It's now an all or nothing operation.  Itemized billing will list
the container but not contents, and to buy what is inside you need
to pay for the whole thing as a single unit.  If the container itself
is unpaid then its price is part of that item's total cost.  If it is
hero-owned than it is listed as an item to buy but doesn't increase
the cost derived from its unpaid contents.  (If you decline to pay,
hero will still own the container and still owe for unpaid contents.)
2024-07-02 14:52:49 -07:00
PatR
2674a9904d github issue #1249 - menu pay of contained items
Issue reported by ars3niy:  unpaid containers containing one or
more other unpaid items appear on the menu for 'p' along with
separate menu entries for those other items.  Buying the container
buys the contents too, then if any of the contents were also picked
in the menu, an attempt will be made to pay for them separately.
Since they are no longer on the bill by that point, that triggers
an impossible warning.

This fixes that by paying for the container but not its contents.
(Temporarily, until more extensive changes get implemented.)  Then
those contents will still be on the bill.  It they've been chosen
in the 'p' menu, paying for them will work as expected.

This also fixes the pay menu for the case where the bill contains
any instances of a partly used up portion of some stack and also
the unpaid intact portion of the same stack.  With itemized billing,
you are allowed to buy the used up portion separately, then maybe
drop the unpaid portion.  (If you try to pay for the intact portion,
the shk won't accept the payment and will tell you to pay for the
used up portion first.)  With the recently added menu for billing,
they were lumped together as a single item and you had to pay for
their whole stack.

And it fixes a much older bug dealing with the cheapest item on
the shop bill.  If you don't have enough to pay for that, the rest
of buying gets skipped.  But stacks that had used up and intact
portions were lumping those together instead of separately checking
the two portions for possibly being the cheapest, so it was possible
to have enough gold to pay for one portion but be told that you
couldn't affort to pay for anything.  If it was the intact portion,
you wouldn't be able to buy it anyway, but if the cheapest item was
used up portion, being told you didn't have enough gold was wrong.

This commit does not fix the longstanding bug that itemized billing
reveals the contents of containers which haven't been opened.  It
was intended to do so but I've run out of steam.

(There is groundwork for that, where buying a container would
include payment for its unpaid contents without revealing what those
are, and they couldn't be purchased separately unless they get taken
out of the container.  Uncommenting '#define CONTAINED_BUYING' will
enable it, with updated pay menu handling but without being able to
pay for non-empty containers.)

Fixes #1249
2024-06-27 14:13:39 -07:00
PatR
6ebc3a7291 leash sanity checking
I still haven't found any explanation for the report by a hardfought
player recently that going down some stairs with a pair of leashed
pets got one into a confused state where it was flagged as leashed
but the corresponding leash was no longer in use.

This adds some new object and monster sanity checks regarding leashes,
and it changes o_unleash(obj) to clear obj->leashmon even if/when the
monster can't be found.

It also changes behavior for dipping an attached leash into a potion
of polymorph when that happens to yield another leash--now the new
one will end up being pre-attached.
2024-04-30 13:27:10 -07:00
Michael Meyer
b662134eba Fix: bill_dummy_obj billed excessively for stacks
Add a way to request that unpaid_cost() produce the cost for a single
item, which is necessary for the price adjustment made in
bill_dummy_object.  Another option would be to simply divide by quan in
bill_dummy_object, but this might be more future-proof in case
unpaid_cost ever involves more than simple multiplication by quan
(e.g. the use of alternate units vs the base price, as are used for
globs).

Fixes #1236
2024-04-27 18:42:50 -07:00
RainRat
7656804ae9 fix typos 2024-04-10 00:46:21 -07:00
PatR
dfd5ca6cad more display of T-shirt/apron text at end-of-game
This doesn't directly affect nethack, but it should prevent HTML
dumplog for variants that include that from showing T-shirt and
apron slogan text in tooltips for the 'gameover' map.  And it makes
end-of-game attribute disclosure slightly less susceptible to being
unintentionally reverted.

Code in pull request #300 shows that it uses do_screen_description()
for tooltips and do_screen_description() uses distant_name() for
objects so that's where I added this change that will trigger the
code from commit c6992777f5.
2024-03-30 07:52:23 -07:00
PatR
c6992777f5 end-of-game attribute disclosure in wizard mode
Disclosing final inventory while wearing an alchemy smock reported
the apron's slogan accurately but then disclosing attributes gave
different text if it was conferring poison resistance and/or acid
resistance.  The extra text was unneeded/unwanted there anyway, so
simply suppress it rather than force it to be accurate.

3.6.x had the same issue but it wasn't detectable there because it
only had extra text for T-shirts and they don't confer attributes.
2024-03-27 23:52:37 -07:00
Pasi Kallinen
9d97835686 Minor wishing alias improvement
Previously when wishing for "ring of protection from shape shifters",
you got a random ring instead of the protection from shape changers,
because the string matching alias was "protection from shape shifters"
without the object class.  Now, we'll check if the wish matched any
object class, but not existing object or alias, and try matching
the aliases again, but only those of the already matching obj class.

Add an alias for the ring of increase accuracy: "ring of accuracy",
and tests for it.
2024-03-16 16:59:58 +02:00
nhkeni
9c0ed8ae63 NOSTATICFN for src/* 2024-03-14 17:41:51 -04:00
RainRat
a3658f85ac fix typos 2024-02-28 20:15:56 -08:00
nhmall
0a985459f0 make style consistent for function ptr arguments 2024-02-19 17:21:04 -05:00
nhmall
688ac6ffbe remove register from variable declarations 2024-02-19 16:30:07 -05:00
PatR
576dd10bdd fix #K4088 and #K4089 - ring formatting
+/-N for charged rings with known enchantment was clobbering the
BUC formatting that had occurred earlier.  #K4088 thought it was a
problem with the implicit_cursed option; followup #K4089 from same
user correctly pointed out that the problem was present for any BUC
state.

This is the same line of code that inadvertently omitted the space
between +/-N and "ring of <type>".  That was fixed by commit
1a2b2a8cae a couple of days ago.

While in doname(), fix a potential issue calling corpse_xname().
That assigns a new value to gx.xnamep, clobbering the value that
doname() relied on when it was first called (but doesn't look at
again, so doesn't matter now but could conceivably in the future).
2024-01-24 00:37:09 -08:00
PatR
5d90499148 doname bounds checking bits
When ready to return, check for overlooked overflow (shouldn't happen)
and panic, or report the first excessively long but not overflown
description to paniclog, similar to xname.

Make ConcUpdate() more robust by not needing bp_eos to be previously
set.  Less efficient but I think that boat has left the barn?  :=}

Fix a comment typo.
2024-01-21 17:43:55 -08:00
PatR
9e640fb14e gcc warning fix
Avoid two new warnings in xname_flags() about strncpy() not supplying
a terminating '\0'.  That's exactly why strncpy() was being used.

The gcc manual lists -Wno-stringop-truncation to suppress the warning
but not -Wstringup-truncation to voluntarily enable it, so the pragma
stuff in warnings.h probably won't work for this.  Just switch from
strncpy() to memcpy() instead even though it seems like obfuscation.
2024-01-21 11:01:45 -08:00
PatR
1a2b2a8cae object formatting fix for charged rings
The bounds checking code for object formatting had a typo that left
out the space between +N and <ring of type>.
2024-01-21 07:58:25 -08:00
PatR
7b1ec30d0d bounds checking by doname() and xname()
Try harder to prevent buffer overflow when formatting objects.
I don't have any test cases where overflow has been happening so
don't really know whether this works reliably.  And it doesn't try
to check prefix construction by doname().  [Yet?]
2024-01-20 17:53:44 -08:00
nhmall
25a8c258e6 replace x >= LOW_PM with ismnum(x) shorthand macro 2024-01-11 14:01:10 -05:00
nhmall
4e19221e55 variable 'display' causes shadow variable warnings in X11 build
display.botl      -> disp.botl
display.botlx     -> disp.botlx
display.time_botl -> disp.time_botl
2024-01-05 05:58:51 -05:00
nhmall
49a5d043c0 consistent use of TRUE vs 1 with botl and botlx 2024-01-04 23:48:38 -05:00
nhmall
22e52ee905 bundle the display-related hints, that tell bot() and others
that an update is required, into a struct. Remove it from
context since there is no reason to save those.
2024-01-04 23:16:27 -05:00
PatR
35eb289cc3 "partly used candle" fix
If you wished for "lit candle" you'd get an unused candle that
is pre-lit but the feedback as it's added to inventory would be
"partly used candle (lit)".  If snuffed out immediately, it reverts
to "candle" (ie, not partly used).

This fixes the first aspect:  you will get "candle (lit)" added to
inventory.  On the next turn it changes to partly used as expected.
The second aspect, reverting to not-used-yet after being lit during
the wish is left as-is.
2023-12-23 16:15:38 -08:00
PatR
a696cb8d90 some NONNULLs
Update the prototypes of some functions which return a pointer that
will never be NULL.  Only covers pager.c and part of objnam.c.
2023-12-20 15:55:21 -08:00
nhmall
3bf2f0daee Revert "allow readobjnam arg to be nonnull"
This reverts commit 10f29a9760.
2023-12-17 07:20:35 -05:00
nhmall
10f29a9760 allow readobjnam arg to be nonnull
Have it key on &do_random_str instead of NULL,
and modify makewish() in zap.c for the new protocol.
2023-12-16 19:30:34 -05:00
PatR
4bd7f265f1 wizard mode terrain wishing at drawbridge spot
When trying to reproduce the wand of striking "interesting effect (0)"
report, I tried wishing for lava under the castle drawbridge.  That
wasn't handling drawbridges properly.  This fixes wishing for moat,
lava, ice, or floor at a drawbridge span location whether the bridge
is currently open of closed.  It also allows wishing for room or floor
or ground at room spots; that hasn't had much testing.

Wishing for furniture, pool|moat|water, or lava at an ice location
wasn't cancelling any pending melt timer.

ice_descr() was declared as returning const but returns its non-const
output buffer argument.  Change to 'char *' so that wizterrainwish()
can capitilize that output without jumping through any hoops.
2023-12-11 19:54:20 -08:00
nhmall
3230babae0 uhandedness follow-up
avoid (wielded in right hands)
2023-12-03 20:27:01 -05:00
nhmall
e4e8eea4e8 track the handedness of the hero
Don't make either LEFT_HANDED or RIGHT_HANDED be an advantage
or a disadvantage.

use suggested macros
2023-12-02 11:23:43 -05:00
PatR
dd6c249a8c remove obsolete comment 2023-11-12 10:26:59 -08:00
nhmall
76d328d86a gi.invalid_obj -> hands_obj 2023-11-11 19:49:38 -05:00
nhmall
27e727d7d7 another missed cast removal 2023-11-10 11:31:24 -05:00
nhmall
314a2a9489 use gi.invalid_obj instead of cg.zeroobj
cg.zeroobj was originally added (under its previous unprefixed name)
for providing a one-line way to zero out the fields of a struct obj.

    struct obj tempobj;
    tempobj = cg.zeroobj;

    initfn(struct obj *otmp)
    {
        if (otmp)
            *otmp = cg.zeroobj;
    }

More recently, the address of cg.zeroobj began to be used as a return
flag to indicate some things, but the 'const struct obj zeroobj' wasn't
an ideal fit for the purpose and required a number of casts, including
casting away const.

Provide a better fitting variable (gi.invalid_obj) and eliminate a
number of casts.
2023-11-10 11:07:49 -05:00
Pasi Kallinen
2e8adda028 Clouds cannot have engravings in them
... so delete the existing engraving if a cloud is put on the map.
2023-11-09 18:08:00 +02:00
PatR
4dc8429d9e thawing ice followup
Modifying an() [actually just_an()] to treat "<thickness> ice" and
"frozen <hallucinatory liquid>" as special cases which shouldn't be
prefixed with "a" or "an" affected using something like "shaved ice"
or "frozen yogurt" as named fruit.
 |a) shaved ice
 |b) frozen yogurt (weapon in hand)
now have article "a" preceding them:
 |a) a shaved ice
 |b) a frozen yogurt (weapon in hand)
However, the existing cases
 |c) iron bars
 |d) an iron bars (weapon in hand)
still get item 'c' wrong.  'd' is slightly odd but that's because the
fruit name is ambiguous as to whether it's singular or plural.
2023-10-26 01:28:56 -07:00
PatR
04d6789c98 report ice's thaw state
Classify nearby ice as "solid" (no melt timer), "sturdy" (more than
1000 turns left), "steady" (101 to 1000 turns left), "unsteady" (51
to 100 turns left), "thin" (15 to 50 turns left), or "slushy" (1 to
14 turns left, matching walking on ice with the Warning attribute).
[I'm not thrilled with "steady" and particularly "unsteady".]

I was originally going to do this just for probing downward, but ended
up also doing it for look-here and getpos's autodescribe.  It nearly
got out of hand and touched more files than anticipated.

'mention_decor' ought to treat moving from ice firmer than thin to
thin or slushy, from thin to slushy, from slushy to any other, and
from thin to firmer as if moving onto different terrain but I haven't
attempted to tackle that.

The melt timer could work more like a candle's burn timer, triggering
at intermediate stages and resetting itself, so that ice which changes
to a weaker state under the hero could be reported to the player.  But
this doesn't implement that.
2023-10-25 13:26:03 -07:00
PatR
78607a37a5 more obufs - two-handed weapon in "hands"
Pointed out by entrez:  prevent doname() from consuming two obuf[]
buffers when it constructs the plural of "hand" while formatting a
wielded two-handed weapon.

Since only one such item should be able to occur in any list of
objects, it is not likely to be the cause of any message oddities
that might happen when a cached value is in a formatting buffer gets
re-used too soon.  However, not releasing a second buffer right away
prevents an attempt to release the first one from succeeding because
it won't be the last one allocated anymore, so some buffer churn was
happening.
2023-08-16 18:16:11 -07:00
Michael Meyer
d57a359bba Add correct Cyclops pluralization
The correct plural of "Cyclops" is "Cyclopes", not "Cyclopses".  I don't
know if anyone would actually use that as a fruitname, but it wouldn't
hurt to add it -- especially since a Cyclops does appear in the game.
2023-07-04 22:37:38 -07:00
PatR
e9c58c2fe4 breaking crystal armor
Instead of a 5% chance for crystal plate mail or crystal helmet to
break each time it's subjected to breakage, switch to a 10% chance
but the damage is treated as erosion rather than break/don't-break.
'crystal foo' will need to go through four stages of damage before
breaking:  cracked crystal foo, very cracked crystal foo, thoroughly
cracked crystal foo, then gone.  Crackproof handling is included,
described as tempered crystal foo.

It mostly still applies to throwing and kicking the item.  Having
some hits trigger damage might be worthwhile but isn't implemented.

Object creation within lua code probably needs to be updated, and
when the Mitre of Holiness is created in the priest/priestess quest
it should start out as tempered (erodeproof).  Perhaps it ought to
be erodeproof regardless of where/how it's created.
2023-06-14 15:54:04 -07:00
PatR
450f060132 github issue #1060 - crystal helmet
Issue reported by vultur-cadens:  changing helm of brilliance to
crystal made it stop being classified as "hard helmet" so it gave
less protection against things falling onto the hero's head.

Change the is_metallic() tests used on helmets to new hard_helmet().
Unlike when thrown, crystal helmets don't break when objects fall
on them.

Fixes #1060
2023-06-14 06:13:11 -07:00
PatR
bf47cc878e fountain and sink bookkeeping
This replaces most of commit 0ca2af4d8b
from a couple of days ago with something more robust.  That change
actually introduced redundant code that caused fountain and/or sink
count to be off instead of preventing it.

Revise set_levltyp() to update level.flags.nfountains and
level.flags.nsinks if setting the type to or from fountain or sink.
A bunch of places that were setting levl[x][y].typ directly needed
to be revised to use set_levltyp() instead.  set_levltyp() itself
hadn't been updated to handle LAVAWALL (to force such to be lit).
2023-06-12 15:07:34 -07:00
PatR
0ca2af4d8b wizwish fountain and sink bookkeeping
Noticed while considering the pull request about loosening
restrictions on trap creation at furniture locations.  If you wish
for a terrain feature while on a fountain or sink, the counters
used to control whether sounds for those should be given will be
off by one.

It was incrementing the appropriate counter if you wished for a
fountain or sink, but it shouldn't do that if recreating the same
feature (perhaps to reset a magic fountain or looted sink) and it
needed to decrement when replacing either of those with some other
feature.  After the count became wrong, if all fountains or sinks
on the level were destroyed, those splashing, gurgling, &c sounds
would continue to be generated periodically.
2023-06-10 01:46:35 -07:00
nhmall
de79240dea some comment spelling fixes 2023-03-16 22:27:01 -04:00
nhmall
288cc01f3a Merge branch 'naming-overflow-fix2' into NetHack-3.7 2023-02-16 18:52:47 -05:00
Pasi Kallinen
7401b44fa1 Walls of lava
Add "walls of lava", basically lava which blocks vision and
require a bit more than just levitation or flight to move through.

No levels use this yet, as testing isn't thorough enough.
2023-02-06 19:23:42 +02:00
Pasi Kallinen
d3430bed9f Prevent certain items from random erosion
Prevent wished for items (unless specified), artifacts,
armor and weapons of NPC heroes, and ammo from Longbow of Diana
being generated eroded.
2023-02-05 16:46:54 +02:00
Pasi Kallinen
e1b01a5d7c Fix segfault when farlooking monster under generic object
A detected cave spider was hiding under a generic spellbook object;
farlooking at it produced a segfault.  OBJ_NAME is null for the generic
objects, so don't try to strcmp it.
2023-02-04 17:48:57 +02:00
PatR
b9bbf0205b Pending 3.7 edition of the naming overflow patch.
Like the 3.6.7 one, the original pieces have been combined into one
commit.  But it is separate from the one added to that version.
2023-01-28 13:02:46 -08:00
PatR
8952ea9bb5 add Japanese item names to discoveries list
When playing as a Samurai, add things like "osaku" to the discoveries
list even though they don't have separate descriptions to be used
when not yet discovered.  Non-magic ones are pre-discovered and
players can now use the '\' command to figure out what things like
"tanko" mean without resorting to '/?'.

"wooden harp" has been getting changed to "koto (harp)"; make that be
| koto [wooden harp] (koto)
"magic harp" has been staying as "magic harp (harp)"; add it to the
list of Japanese item names.  Since it's magic it isn't pre-discovered.
Once discovered it becomes
| magic koto [magic harp] (koto)

Those two needed special case handling, none of the other items did
aside from forcing them to be discoverable when lacking descriptions.
The discoveries list now has things like
| wakizashi [short sword]
| naginata [glaive] (single-edged polearm)
| gunyoki [food ration]
if--and only if--the hero is a Samurai.
2023-01-18 22:00:57 -08:00
PatR
97a90de172 another static analyzer bit - Japanese_item_name()
The analyzer complained that the second call to Japanese_item_name()
might return Null after the first one didn't.
|    if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
|        actualnm = Japanese_item_name(otyp);
even though the code involved is self-contained and deterministic.
Then later in obj_typename() 'actualnm' gets passed to strcat() or
strcpy() where Null isn't acceptable.

Could probably fix that by caching and reusing the first return value:
|    if (Role_if(PM_SAMURAI) && (jname = Japanese_item_name(otyp)) != 0)
|        actualnm = jname;
but I went a different route, revising that routine to take a second
argument:
|    if (Role_if(PM_SAMURAI))
|        actualnm = Japanese_item_name(otyp, actualnm);
It now passes back 'actualnm' instead of Null when no substitution
takes place.

The recent introduction of generic objects without names meant that
'actualnm' could actually be Null, but generic objects only occur
for map glyphs and only when dknown is 0, so the actual-name field
shouldn't ever be get used for them.  Give actualnm a fallback value
just in case.

Wishing is a place that loops over all of objects[] so have it skip
the generic objects.  They're all flagged no-wish so weren't being
chosen, but explicitly skipping them makes the intention clear.
2023-01-13 23:41:23 -08:00
nhmall
ba5356603a yn()
A number of C compiler suites have a math.h library that includes a yn()
function name that conflicts with NetHack's yn() macro:
"The y0(), y1(), and yn() functions are Bessel functions of the second kind,
for orders 0, 1, and n, respectively. The argument x must be positive. The
argument n should be greater than or equal to zero. If n is less than zero,
there will be a negative exponent in the result."

At one point, isaac64.h included math.h, although that has since been removed.

Some libraries used in NetHack (Qt for one) do include math.h and that required
build work-arounds to avoid the conflict.

Rename the NetHack macro from yn() to y_n() and avoid the math.h conflict
altogether, eliminating the need for that particular work-around.
2023-01-12 16:04:40 -05:00