This is based on a feature in UnNetHack (and I think some other variants
as well). If the hero intentionally drops an item with 'pickup_dropped'
disabled, don't autopick it back up when walking over that square again.
Typically when the player drops an item, it's because she doesn't want
it in her inventory any more, and this option stops autopickup from
defeating that goal (especially useful for tasks like stash management
without a container). Players have come up with workarounds to this
problem like toggling autopickup when approaching their stash pile or
adding name-based autopickup exceptions to allow them to exclude
individual items from autopickup, but this behavior should reduce the
need for those things.
I think 'pickup_dropped' is a little unfortunate because it suggests
equivalence to 'pickup_thrown' (i.e. any dropped items will be
automatically picked up regardless of autopickup exceptions). Calling
it something like 'nopick_dropped' might be better, but as far as I can
tell options cannot start with the word 'no' because it's interpreted as
a negation of the rest of the option name.
There were 6 brown 'd' monsters; move wolf and werewolf to grey,
and warg to black, as those colors had no canines.
The wolf tiles are already greyish; changed warg tile to be
slightly darker.
There are many red major demons, and hezrous and vrocks
now emit poison gas, so change the symbol color to green.
Also adjust vrock tiles to have green. The hezrou tiles
already are green.
Prior to this commit, there was no good way to deal with swarms of
weak, good-AC enemies using magic; trying to play a wizard as a
pure spellcaster would make bees and ants very difficult to deal
with (because they would usually dodge force bolts).
This commit adds a new spell designed to be very good against
swarms of weak enemies: "chain lightning", which does 2d6 lightning
damage to every monster around you. It has an initially short range,
but can chain from monster to monster to cover potentially large
distances (as long as none of the monsters en route are shock
resistant or tame/peaceful; the spell can't chain past shock
resistant monsters and avoids peacefuls). Monsters within one
space of the visible lightning bolts are affected. Unlike other
lightning effects, this one does only 2d6 damage, not enough to
blind affected monsters.
This commit breaks existing save and bones files (thus the
EDITLEVEL increase).
The same checks were being repeated for every damage type; this
sends them through two centralised functions (one for checking
whether an extrinsic blocks a specific instance of item destruction
and one for the enlightenment message), so that new mechanisms of
item destruction prevention will need to change only one point in
the code.
The tracks left by hero were cleared when player saved and
restored the game, or changed levels. Now the tracks are
saved in the dungeon level, so changing levels keeps the tracks
left by hero in that level.
Also increased the length of tracks from 50 to 100, and
simplify the tracking function.
Thing not done: fade out old tracks when returning to a level.
Breaks saves and bones.
Report was that converting a novel into a blank spellbook via water
damage resulted in a spellbook of blank paper that increased weight
when put into a bag of holding.
Spellbooks weigh 50 units but novels were defined with a weight of 0;
when one was created, a non-zero weight of 1 got assigned. Blanking
it didn't update the weight; that stayed at 1. Putting it into a
container reset the weight to match the new type: spellbook of blank
paper, so its weight increased.
Do that when blanking rather than wait until a container might fix it
up. If it is already in a [possibly nested] container, update that
container's weight too along with any outer ones.
This also changes the base weight of novel from 0 to 10, so it still
gets magically heavier when turned into a spellbook of blank paper.
(The alternative seems to be to destroy it instead.)
The Book of the Dead weighed only 20 units which seemed odd to be so
much less than a spellbook. This changes that to 50 to match those.
Currently, options.c is the only file that #includes "optlist.h".
In theory, if a source file did want to include optlist.h (perhaps
for the struct allopt_t declaration so they could deal with a
pointer to such a struct), they wouldn't be able to include it
because of a static function prototype that it contains.
Add some protection to only include that static function
prototype when optlist.h is included from options.c.
At present, potions of healing generate primarily in Gehennom,
which causes significant balance issues (e.g. you don't have them
to heal in the early game, or even if you do, you can't identify
them in time to use them). In this series of commits, I'm aiming to
make potions of healing a more viable early-game healing source,
which means making them both (much) more likely to generate, and
easier to identify so that they are actually usable in the early
game.
This commit radically increases the generation chance of potions
of healing (reducing the chance of most other potions slightly to
compensate), and gives them a unique base price. This should make
them fairly easy to identify either by price-ID or quantity-ID
(and the unique base price is chosen to be fairly easy to figure
out even for unspoiled players).
Previously, Wizards got a boost to the chance of writing unknown
spellbooks based purely on being a Wizard (with the chance still
luck-based), leading to a very large power spike when the Wizard
gained access to a luckstone and the ability to max out luck.
This had two main issues: this power spike came *after* the major
early-game difficulty spike, often leaving Wizards forced to deal
with it without having appropriate spells; and it promotes
grinding (for Luck and for Magicbane) at an early point in the
game, meaning that the Wizard early game effectively followed a
sequence of extreme difficulty -> grinding -> minimal difficulty,
which isn't very good balance-wise.
With this commit, Wizards lose their advantage to writing unknown
spellbooks by guessing, and instead learn spellbook IDs based on
their spell skills (advancing a skill gives knowledge of higher-
level spellbooks). This means that writing unknown spellbooks
becomes guaranteed with sufficient skill, but has no advantage
over non-Wizards in schools where the Wixard does not have
sufficient skill.
Due to Wizards' skill caps, there are two spells which they can't
ever write guaranteed: create familiar and charm monster. Create
familiar is a fairly niche spell (that doesn't match the Wizard
playstyle that well) and being unable to write it is not a major
problem. The inability to easily write charm monster is
intentional.
This is for completely destroying an altar with extra-powerful magical
digging -- the normal altar_wrath() punishment didn't seem sufficient
for such an outrage to me, so skip straight to slinging the lightning
bolts. Destroying an altar is unlikely to happen by accident (though
it's possible with poorly timed usage of a drum of earthquake).
character_race() was going out of bounds when scanning the races[]
array, relying on a field value that the fencepost entry didn't set.
This incorporates the previous fix for UNDEFINED_RACE but also changes
character_race() to not care about that anymore.
If any items are in use and hero isn't wielding anything, include
| - bare hands
in the primary weapon slot of the display of used items as an alert.
More useful for perm_invent than for #seeall.
If no items at all are in use, continue to show "not using any items"
without any specific weaponless alert.
When sortloot() is called for inuse_only, pass a filter that screens
out items which aren't in use so they won't be needlessly sorted.
For '*' and for persistent inventory with perminv_mode==inuse, show
the items in a specific order and within four labelled groups rather
than within their object classes:
|Accessories
| amulet
| right ring
| left ring
| blindfold
|Wielded/Readied Weapons
| primary weapon
| alternate or secondary weapon
| quiver/ammo pouch
|Armor
| suit
| cloak
| shield
| helmet
| gloves
| boots
| shirt
|Miscellaneous
| lit candles and/or lamps
| attached leashes
The accessories come first due to the default 'packorder' position
for amulets; weapons before armor likewise. If you wield a potion or
quiver some gold, those non-')' items will appear in the weapons
section since the ordering is based on slot rather than object class.
choose_classes_menu was declared extern. The only caller presently
was calling it was optfn_pickup_types() in options.c.
It could have had the extern declaration from include/extern.h and
declare it as static within options.c, if that was the only use
anticipated. Also, if the one existing caller were all there would
ever be, the argument passed to it that was the subject of pr #1146
could have just been removed along with the switch.
Checking the comments above the function, however, it was clearly
designed as a general-purpose function that could be called from
anywhere for the functionality desired, even though there's presently
just the one caller, passing just the one variation of the category
argument.
Relocate the general-purpose function over to src/windows.c, where
several interface-related / menu-related general-purpose functions
already reside.
options.c has gotten *huge* and this is a fitting opportunity to
reduce its size a little.
A very small number of relatively recent macro definitions got
placed in mondata.h, even though they had a 'struct monst *'
argument, rather than a 'struct permonst *' argument.
Relocate the macros with the 'struct monst *' argument to
include/monst.h, leaving the macros with the 'struct permonst *'
argument in include/mondata.h.
This is useful for debugging and it allows the index
to be used directly instead of calculated in a
monsndx() function, which has been removed.
I left monsndx() in as a simple short-hand macro for the value
and didn't change the use cases, the reasoning being that this:
monsndx(mon->data)
is arguably a little easier on the eyes than:
mon->data->pmidx
LOW_PM, NON_PM, SPECIAL_PM have been included in the 'enum monnums'
now, instead of as individual macro definitions.
I chose to add the pmidx field as an instance of the enum declaration,
because that has very advantageous results in some debuggers, where it is
then shown as:
pmidx PM_GRAND_MASTER (349) monnums
instead of the less-informative:
pmidx 349 int
Adding the element count to the extern declaration for mons from:
'extern struct permonst *mons[];'
to the more specific declaration to that in src/monst.c:
'extern struct permonst *mons[NUMMONS + 1];'
then allows navigation through the mons array in one of the debuggers.
Macros to conditionally include color fields in defsyms[] and objects[]
are no longer needed. The one for mons[] was already gone but traces
were present in a comment.
When picking up multiple items (or looting multiple items) in one
operation, only show encumbrance for the first item that causes that
to change instead of complaining about non-zero encumbrance on every
item. The very first item is treated as if it caused a change, so
you get "you have a little trouble lifting <obj>" even if you were
already burdened, same as before.
Only lightly tested.
Sync with decl.c. dbridge.c never had anything to do with these
variables. They were part of decl.c before they got collected into
struct g, then split among struct ga to gz. (This only fixes up
the comment in gl; there may be more, possibly quite a few more.)
These might be better classified as /*dungeon.c*/ although they
weren't defined there.
"engraved part of a room" and "engraved part of a corridor" sound
silly. Change to "engraving in a room" and "engraving in a corridor".
Still displayed to player as just "engraving".
An orhpaned wintype.h tweak got dragged in. Renumbers to_core_flags.
Sometimes I annotate a level with a note like "watch out, chameleon
below", which is useful to remind myself of some danger or thing to
remember when returning to the level -- but if saving and restoring on
the level itself there's no reminder of that annotation. If you restore
on a level with an annotation, print it as part of the "welcome back"
message.
<color>
off: map, menu items, menu headings, menu prompt/title all, everything should have color suppressed.
<curses guicolor>
on: map, menu items, menu headings, menu prompt/title can all feature color, as can
menu borders, menu-selector letters.
off: map, menu headings, menu prompt and menu items (menucolors on) can still feature color,
but all other non-map features such as menu borders, menu-selector
letters will not have color.
<menucolors>
on: menu items can have colors if they match one of the regex in config
file; menu headings, menu prompt can also be in color (based on menu_headings option).
off: menu items won't have colors, but menu headings, menu prompt still
will feature colors (based on menu_headings option); those are not impacted by turning
off menucolors.
This implements the mechanics to use the ctrl_nhwindow() interface
capability to pass down a setting change from the core to the active
window port, without resorting to accessing a core global variable
from within the window port, and without altering the interface..
The passed setting is honored in the tty and curses window ports.
X11 and mswin receive and store the values, but no implementation
to change the menu prompt style is there yet.
Qt does not store the values or have an implementation.
The setting change is done in allmain.c immediately after
creating the WIN_INVEN window.
If the value is "no color&none" report it as "no-color&none" in 'm O'
and for #saveoptions.
Allow "OPTIONS=menu_headings" without any color or attribute value to
mean "no-color&inverse" as it once did before the player could choose
which attribute or color was supported, and matching the default used
when 'menu_headings' hasn't been specified at all.
Accept "OPTIONS=!menu_headings", meaning "no-color&none".
Explicitly reject "OPTIONS=!menu_headings:anything". It was rejecting
that due to blanket rejection of negated option, but reporting "can't
both have a value and be negated" whether there was any value present
or not.
For preselected menu entries when interactively choosing a new value
via the submenu of 'm O', use the current color and attribute rather
than NO_COLOR and ATR_NONE.
Remove menu_color support from the window port side of the interface.
The window port just has to honor the color parameter that was added
to the add_menu() interface definition in June 2022 commit
2770223d10, and let the core-side of
the interface handle things.
To that end, this does the following:
Removes the #define of add_menu() from include/winprocs.h and add a
real core-side add_menu() function to windows.c which acts as a
trampoline to the window port win_add_menu() function, while providing
a single location to adjust the parameters passed to the window port
function. get_menu_coloring() is now called in there.
Moves get_menu_coloring() from options.c into windows.c and makes it
static.
Removes all the calls to get_menu_coloring() from the tty, Qt, X11,
curses, and win32 interfaces and adjusts their code to simply honor
the color parameter in add_menu, similar to what the menu_headings
change from earlier today did.