Extend the capabilities of corpse_xname() so that various callers can
be simplified. It can how handle an article prefix, effectively turning it
into corpse_doname() (not quite; still need doname() to see a count when
quantity is more than one, or to see bless/curse state). It can also handle
inclusion of adjectives like "partly eaten" or "bite-covered". For unique
monsters those come out in the form
the Chromatic Dragon's partly eaten corpse
instead of the old
partly eaten Chromatic Dragon corpse
[so wishing probably needs to be taught about potentially finding a monster
name before assorted adjectives such as blessed; also, name_to_mon() needs
to learn how to cope with the possessive suffix].
A sizeable chunk of this patch deals with consolidating some of the
redundant "petrified by a cockatrice corpse" handling. It may be possible
to consolidate all remaining instances together since they're quite similar,
but I didn't think about that until just now and I want to get this patch
over with.
From a bug report, amorphous creatures can fit underneath
closed doors but could still be considered too big to fit through diagonal
gaps. Let them and several other shapeless or flexibly shaped critters
squeeze through provided that they pass the not-carrying-too-much check.
The in_lava_effects flag should never be saved and restored; putting
it into the context struct was a mistake. Move it to the iflags struct
(where the branch code already has it). I haven't bumped the EDITLEVEL
setting. Save and bones files from more that a few days ago were breifly
invalid but should be viable again. Save and bones files from the past
couple of days are now no good; sorry about that.
Have killer_xname() handle corpses properly and also avoid having it
use user-supplied fruit names as per <Someone>'s suggestion. Also make
a start at eliminating the umpteen inconsitent checks for whether a monster
type (like "Oracle") ought to be prefixed by "the ".
I used a stub which looped over all object types, all artifacts, and
corpses of all monster types to print the output of killer_xname() for each
one; its prefix choice among {[no article], a, an, the} looked right.
While testing some killer_xname() changes, I noticed that it was
feasible to avoid having some gear destroyed by causing a hangup after
getting the destruction message. And while testing the fix for that, I
stumbled across a panic situation (not caused by my changes). If you
survive entering lava while wearing water walking boots (and aren't fire
resistant yourself, and don't have enough hit points to survive 6d6
damage, and your boots aren't fireproofed...), having those boots be
destroyed will dump you back into the same lava recursively (lava_effects
-> Boots_off -> spoteffects -> lava_effects). And if you survive that
(wizard/explore mode or life-saving), there will be a panic when finishing
deletion of the boots (useupall) because the recursive call will have
already done it (since they aren't worn anymore when inner call handles
them, no additional recursion gets triggered and object deletion happens).
Some of the other stuff I was working on is mixed in here because
this is the configuration I ended up using to test the panic fix.
Several Makefiles are missing the dependency for context.h (post-3.4.3
revision). If yours is, then you'll need to force a full rebuild after
applying this or you'll end up with havoc. (Mine was, but I noticed that
the expected full build wasn't happening and interrupted it to fix that.)
From a bug report: sleeping pet could
be shown as "eating" by stethoscope. Fixing that is a one-liner since all
(or should be all; sleeping gas trap wasn't utilizing it) cases of monster
being forced into sleep go through one routine. That wasn't the situation
for paralysis, but now it is. Paralyzed pets won't continue eating either.
Add support requested by a user for number_pad:3 to use a phone-style
keypad layout where 1,2,3 are on the top row and 7,8,9 on the bottom,
opposite of the adding machine layout adopted by computer keyboards. Also
number_pad:4 combines that with the number_pad:2 hack to give different
behavior for the 5 key (also meta-5 and meta-0). And number_pad:-1 is a
rather absurd way to support German keyboards which have y and z keys
swapped, avoiding the need to add a new option for that. With it, z moves
upper-left and y zaps wands, with corresponding swap of the upper case,
control, and meta variations of those two letters. (There is a "German
keyboard patch" for this floating around the net, but it implements a
compile time configuration setting which results in hard-coded behavior
for those keys. This implementation lets it be toggled on or off at will.)
There's more here, intended to ultimately simplify rhack() quite a
bit. Most of that isn't finished yet. However, the part that is done
should produce same run-time behavior as before. I hope....
iflags.num_pad and iflags.num_pad_mode should now be viewed as opaque
items used for communicating dynamically updated option settings to the
core only. Ports and/or interfaces which feel inclined to peek at them
should switch to Cmd.num_pad,&c instead. (I've made that switch for a
couple of places which would have stopped compiling due to sdir and ndir
going away, and for vms+tty where I could directly test the change(s),
possibly plus one or two places which got heldover over from my earlier
attempt that did try to update all of them. Ports which haven't made the
change yet ought to continue to work as-is though.)
Eventually ports/interfaces which implement alternate ways to invoke
commands (pull down menus or extra keyboard buttons or whatever) should be
able to scan Cmd.commands[] to figure out which input characters trigger
which nethack functions. The ones that currently use hardcoded key lists
will probably need to migrate before any dynamic key binding functionality
gets implemented. (Which may never happen; it's definitely not on my own
to-do list.) Cmd.serialno is intended to be the way for them figure out
when the commands have been changed (which right now only happens when 'O'
is used to alter the number_pad setting); perhaps a new interface callback
would be better suited for communicating this.
It may be necessary to rearrange header inclusion so that func_tab.h
gets included before flag.h (and/or struct cmd gets moved from the latter
to the former--but then func_tab.h would be needed in a bunch of places
which don't currently use it) to support some pre-ANSI compilers. And the
command initialization might need to be moved to somewhere earlier than
init_options() at some point if port/interface initialization starts caring
about it.
The fix to prevent naming an unknown gray stone "the Heart of Ahriman"
from revealing whether the object was a luckstone was inadequate to prevent
using the same trick with "the Mitre of Holiness" to determine if an unknown
helmet was a helm of brilliance. (I don't know whether whoever figured out
the first one has realized the second yet; no one had mentioned it in the
newsgroup the last time I looked.) To get this right we need to check for
objects sharing the same set of shuffled descriptions in addition to testing
whether they have identical descriptions. Doing that meant reorganizing how
object shuffling is done, but it produces the same behavior as before.
Angels used the epri extension even though they're never priests,
presumeably because they're sometimes flagged as "renegade". Since the
only priests ever flagged as renegade are roaming minions rather than
temple priests, move the renegade flag to the emin extension and switch
Angels over to that. Summoned Angels will now always have the isminion
flag set.
Makefiles need updating: monst.{c,o} now depends upon emin.h.
Let monsters use lock picks and credit cards in addition to keys for
opening doors. And the earlier code to have pets hang on to a key didn't
work as intended. It worked fine if the key was the only object carried,
but the monsters' item dropping code didn't give any special handling to
keys so they'd be dropped too if the pet carried another droppable item.
This eliminates second set of checks for handling some items specially--
dropping now uses the same routine as is used when pet movement decides
whether there's anything to drop.
Also, a couple more door message tweaks. "You see a door open" seems
strange when you watch your pet do the opening. Previously fixed for the
"unlock and open" case, this does the same for opening already unlocked
doors and for giants smashing down doors--it now gives a more specific
message when you see a monster perform the action.
Possible change in play balance: pets capable of picking up the
rogue's Master Key of Thievery or tourist's Platinum Yendorian Express
Card will keep one of them. So a player might accidentally lose one by
leaving it on the floor in a pet's path, or more significantly, the Card
will yield a means of giving magic resistance to a monster who can't wear
a cloak or dragon scales. It's neutral and the most interesting high-end
pets are lawful (hence won't pick it up), so that probably won't have much
impact.
Simplify is_lminion(); as a result, several source files no longer
need access to epri.h. (mondata.c already could have lived without it;
eshk.h as well.)
Makefile dependency changes:
mondata.{c,o} -- doesn't need epri.h or eshk.h
monmove.{c,o} -- doesn't need epri.h
wizard.{c,o} -- ditto
pline.{c,o} -- ditto (yesterday's patch)
From a bug report, the probing/stethoscope code assumed that all Angels
(the specific monster type, not the whole 'A' class) used the epri extension
to hold alignment, but that's not true for randomly generated ones. So
monster status feedback gave erroneous results, and it would vary based on
pet behavior if the random Angel had been tamed. Also, touch_artifact()
didn't know about special alignment handling for Angels and aligned priests
so always used their default alignment.
There are other problems with Angels--such as whether they should even
be allowed to be generated randomly in the first place--that this doesn't
attempt to address. The patch for that was starting to sprawl all over the
place so I pulled this simpler bit out for a first cut. Probing now shows
the Wizard of Yendor as unaligned instead of lumping him in with chaotics.
Another Makefile update needed: pline.[c,o] no longer needs epri.h.
Fix a couple of problems From a bug report. Eating a Rider corpse is fatal, but eating a live Rider's
brain was not--now it will be, both for monster mind flayers and for player
poly'd into one. Also, there was no check for cannibalism when poly'd hero
eats brains--now there is. Not mentioned in the report: eating Medusa's
brains will now be fatal just like eating her corpse. And pet mind flayers
who eat the hero's brains will gain some nutrition like they do when eating
monster brains.
Creating a common eat_brains() routine turned out to be something of
a mistake; there is only a tiny amount of overlap among the u-vs-m, m-vs-u,
and m-vs-m cases.
Makefiles need a dependency update to add edog.h for eat.c.
Noticed when incorporating the "vampire dancing" patch: losing a level
while polymorphed would subtract from your normal hit points but didn't
affect your monster hit points. Now they'll lose d8 from max and current,
similar to the amount they increase when gaining a level.
This also addresses an issue from the newsgroup a few weeks back:
someone mentioned an assumption that Stormbringer drained an amount other
than d8 for monsters who use some other formula for their hit points. It
wasn't true, but now it will be (approximately). Most monsters with unusual
hit points aren't subject to level drain, so it shouldn't have much impact.
Fix the problem pointed out by <email deleted>
where polymorphing into a new man at level 1 could be used to approximately
double or triple your hit points and spell power. With means to drain
level back down to 1 and with amulets of life saving to survive those times
you lose levels instead of gain, you could do this repeatedly and end up
with HP and Pw values in the millions.
This uses the earlier patch that records the HP and Pw increments from
level gains. Now when polymorphing into a new man, level based HP and Pw
are removed from the current values, remainder get multiplied by 80%, 90%,
100%, or 110% (average 95%, so tend to drop slightly), then a brand new set
of level gain increments (reflecting new man's Con and Wis) are added in.
Code for calculating spell energy is moved from pluslvl() and u_init()
into new routine newpw(). It and newhp() take over responsibility for
remembering the level based increments from pluslvl() which didn't deal
with the initial amount (stored in slot [0]; earlier patch didn't need it).
<email deleted> sent a report with
subject "Vampire-dancing can give you unlimited maxhp/maxmp" about how you
can manipulate your hit points and spell energy by using equipment to
lower Con and Wis prior to deliberately losing a level, then switching to
alternate gear to raise them prior to gaining the trivial 1 XP needed to
regain the lost level. With Stormbringer (to toss up so that it falls on
your head) or spell of drain level (to cast at yourself), you can do this
level toggling as much as you like since it doesn't consume any resources
in the process. All you is a supply of non-threatening monsters to kill
for the regaining half.
In March he sent "vampire-dancing (patch)" which didn't include a
patch but did give a URL ( http://nethack.angband.pl/vampdance.patch )
for one. That contained his suggested fix: recording the hit points and
energy points given each time you gain a level and then using those exact
amounts when you lose the corresponding level. It's still possible to
manipulate HP and Pw by losing multiple levels after you've boosted Con
and Wis to ascension ready status (you'll lose the original values but can
expect to get better ones when gaining levels back), but can only gain a
modest improvement and repeating it doesn't augment the effectiveness.
Plus it's much harder to regain multiple levels than it is to get just one.
His patch had a couple of bugs which I've fixed. I suppose that there
could be additional potential problems but the idea and its implementation
are both pretty straightforward. (This doesn't address the other recently
reported situation of using polymorph into "new man" while at level one to
multiply HP and Pw.)
I've gotten tired of seeing newsgroup claims along the lines of
"since devteam is aware of this and has chosen not to eliminate it, they
must endorse it", so weaken the tactic of "pudding farming". It is still
possible to gain unlimited experience (past level 15 or so there's not
much point), but will be less effective for gaining items and for providing
sacrifice fodder. Keep track of which monsters have been created via
cloning (mostly puddings; gremlins and blue jellies are affected too but
nobody's likely to care much about them) so that they can receive special
handling. Make cloned monsters progressively less likely to leave corpses
as the number killed for a particular type goes up, and also much less
likely to drop random items at death. This is sure to need some tuning
once hard core farmers point out how they can still abuse it. For the
absurdly extreme case, see
http://scavenger.homeip.net/farmbot/HomePage
FYI, farmbot/PuddingFarmingHOWTO includes an impressive screen shot of a
dungeon level where rampant farming is taking place.
Make it easier for a low level character with ordinary Max HP to get
the healing result from a successful prayer. Mid level characters are the
same as before: will be healed if at 1/7 (or worse) of max. High level
characters, or anyone with Max HP really high for their level, will need
to wait until current HP is lower before being able to obtain that result.
This mainly affects spoilers; the actual impact for any player who doesn't
know the old formula is fairly small. The exception is for "protection
racketeers" who manage to build up a high HP without gaining any levels;
a level 1 character will only get healed when at HP 5 or less, regardless
of what percentage of max their current hit points are.
Under the old system you could get healed at 6 HP if you had 42, at
7 HP out of 49, and so forth. Now you'll need to be at least level 2 to
get healed at 6 HP out of 30 or more, at least level 3 for 7-9 out of 35-45.
"Normal" max is capped at 15 times level and anyone above normal is treated
as if their max was that lesser normal value. Levels 1 to 5 use a new
threshold of current HP being 1/5 (or worse) of max, levels 6-13 use 1/6,
14-21 retain old 1/7 threshold, 22-29 now use 1/8, and level 30 uses 1/9.
The somewhat odd level break points are based on where rank titles change.
I think being asleep or unconscious ought to override vision the way
that being blinded does, but that's a more ambitious change than I care to
tackle. This replaces You("see ...") with You_see("..."), comparable to
You_hear(). It catches the reported door case and several variations of
light sources burning out while on the floor rather than in inventory, but
it probably misses some other cases. zap_over_floor() in particular is
highly suspect.
From a bug report. <Someone> as slashem-Bugs-883643 on 1/24/2004. To avoid
using the possibly invalid object pointer after calling bhit(), changed as
suggested to add another level of indirection allowing bhit to null the
object pointer before returning. Callers that are affected update their
object pointers after bhit returns.
Make petrification initiation or termination go through a new routine,
make_stoned(), instead of manipulating its countdown timer and delayed
killer directly. No change in behavior.
There's no reason in terms of bug risk or game play or saved data why
this shouldn't be done in the branch too, but so much of the surrounding
context has already diverged between trunk and branch that it's trunk only.
Make the names of the macros for handling the hero be similar to those
for monsters (where mis-use of `sensemon()' was the cause of a recently
reported bug). `senseself()' becomes more restrictive in what it specifies,
and current uses of it are replaced by new `canspotself()'.
A post-3.4.3 change dealing with reaching into pits resulted in "you
sit on the air" if you used the #sit command after escaping a pit trap.
Change can_reach_floor() so that caller explicitly controls whether being
on the brink of a pit is a condition that prevents reaching the floor.
This also splits a fairly common message about not being able to reach the
floor into a separate routine.
There is still oddness here: if you're polymorphed into a flyer,
#sit yields "you sit down" followed by "you fly over a pit" (latter occurs
when escaping trap activation). A ceiling hider behaves similarly, but
the second message is "you escape a pit" and doesn't sound quite as silly.
Perhaps #sit should pass TOOKPLUNGE to dotrap(), or maybe there's some
better way to handle this?
> clear stale prompt
[...]
> Can someone who understands the relevant windowing code fix ^R in getpos()?
I still don't understand why it wasn't working as expected, but moving
the existing cursor positioning after flush_screen() instead of before now
makes ^R work ok during getpos(). It doesn't restore the top line text so
isn't a transparent redraw but it now displays a prompt string there instead.
Likewise after typing '?' for help so that it should be move evident that
nethack is still waiting for you to move the cursor somewhere.
Also add support for ^L in numpad mode. I almost never use that and
didn't think of it the first time around.
This uses Michael's suggestion for keeping the display up to date when
removing a djinni or water demon in advance of granting a wish (so that it
won't be present in a bones file if the wish is fatal--problem with earlier
fix was that player could notice monster was already gone while responding
to the wish prompt). It's not quite as straightforward as I was hoping for
and would get a lot messier if it needed to cope with Warning & Warn_of_mon.
Pointed out by <Someone>: engraving with a cursed wand should pose a
risk of having it explode just like zapping does. [At the moment when one
explodes, any existing engraving doesn't get changed.] Suggested by someone
(<Someone>?) some time back: explosion due to recharging could be consolidated
with explosion due to zapping cursed wands. And noted by <Someone> in the
newsgroup: '+' in an engraving--perhaps written by someone trying to leave
bones file notes--should have a chance of being partially rubbed out to '-'.
Implement the suggestion that Fire Brand avoids damage from rust traps
by boiling away the water. Rather than making this be trap-specific, it
applies to all types of erosion which go through erode_obj(). That includes
hitting rust monsters but not dipping into potions or fountains, nor falling
into moats. And it doesn't provide 100% protection, just a high chance of
avoiding rust damage. Also, Frost Brand gets similar protection by freezing.
The message handling needed some rewriting for the branch version.
That compiles ok but hasn't been tested. It would have been simpler just to
move Yobjnam2() over even if nothing else was changed to use it yet....
For cancellation I accidentally used terrain type WATER when I meant
object type POT_WATER, so being charged for cancelling holy or unholy water
wasn't working. When I first put in COST_UNHOLY the name made some sense
based on its usage, but after later adding COST_UNBLSS it didn't any more;
change it to COST_UNCURS.
A shopkeeper's complaint that you're uncursing or unblessing his wares
(only applies to water) now sets bknown flag since you know that the object
has become uncursed. I hadn't realized that confused remove curse only
affects uncursed objects; this greatly simplifies extra code I added there
for costly_alteration().
[No fixes entry needed.]
<Someone> reported that when levitating and blind, he was getting
"You float over the hole" without it showing up on the map. Easiest way
to reproduce: zap a wand of digging downwards while levitating blind,
move off the spot and back over it.
Make sure that all traps created by the player are mapped. For other
traps, it was about 50:50 whether the trap triggering message yields enough
information to warrant forcibly mapping the trap when blind.
[This ought to be suitable for the branch version too but I'm not going to
spend the effort to migrate it there.]
Recently From a bug report, reducing
the value of a shop object via cursed enchantment was ignored by shopkeeper.
This replaces the existing costly_cancel() routine with costly_alteration()
which performs a similar task: bill for any item whose value has been made
less. The hero owns the resulting object but must pay for the original one
before being allowed to leave the shop.
This covers the majority of cases where bill_dummy_object() was already
being used: cancelling a charged or enchanted item, casting drain life at
same, diluting potions or blanking scrolls or books by dipping them into a
potion of water, dulling a weapon by engraving with it, eating unpaid food
or opening unpaid tins, applying a cream pie to hit yourself with it in the
face, applying a wand to break it, burning something by dipping it into lit
potion of oil, and clearing potions by dipping a unicorn horn into them.
The shop billing behavior for those actions hasn't been changed, just
consolidated into one place which delivers a common message for them.
This also covers many cases which weren't being handled: stripping
wand or magic tool charges via cursed scroll of charging, reducing a charged
ring's enchantment via same, reducing weapon or armor enchantment via cursed
scroll of enchant weapon or armor, stripping an item's rustproofing via
confused enchantment, making a crysknife revert to a worm tooth, unblessing
potions of holy water or uncursing potions of unholy water. (That last one
won't be billed if it's the result of prayer rather scroll, spell, or #dip.)
And this tries to handle the reverse situation more thoroughly too:
many actions which improve the value of an unpaid item now also cause the
shop bill to be updated to reflect its new higher price. Aside from the
basic enchanting and charging magic, it covers converting dragon scales into
dragon scale mail and worm tooth into crysknife. Some things which might be
expected to inflate shop prices, like rustproofing or increasing the number
of charges in a wand, don't actually affect the price. And there are bound
to be cases where the price is affected but I've overlooked.
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.
Allow health food stores to carry eggs and tins of veggy contents in
their stock. The tins will almost always contain spinach because random
tins containing meat are converted into that.
Also, allow health food stores to be placed with the level compiler
(not tested) and to be forcibly placed in wizard mode via SHOPTYPE setting
of "V". Increments EDITLEVEL in patchlevel.h because lighting store in
Minetown got renumbered and the special level for it needs to be rebuilt.
Groundwork for having health food shops carry tins as part of their
stock. (That part isn't finished yet.) The choice of which types of tin
preparation might be sold as health food is rather arbitrary. Tweak if
needed--but keep in mind that just because something is marketed as health
food doesn't necessary mean that it's actually healthy; vice versa as well.
Tin handling could be simplified if tin->spe for spinach was changed
from 1 to -1. Then checks for spinach could compare against SPINACH_TIN
instead of a magic number, and with non-spinach tin->spe would be a direct
index rather than needing negating and offsetting.
Revert mostly to <Someone>'s original approach for keeping track of whether
a container being applied or looted had been destroyed by the operation.
askchain() now knows not to attempt to re-merge an item that has been
destroyed (a theorhetical action since no stackable items can trigger a
magic bag explosion) like the earlier change to menu_loot(). Also have
use_container() clean up after itself so that current_container never has
an old pointer value left around.
A user recently complained that he started an activity such as
searching and specified a repeat count, right after getting--and not
realizing the significance of--the first message in the countdown
sequence for turning into stone. He suggested that subsequent messages
interrupt multi-turn activity so that the player has a chance to do
something to prevent imminent death. This implements that, with the
added wrinkle that it won't interrupt if the activity is something that
might save the character's life: attempting to eat a tin that is either
sure to help (if ID'd as food that cures stoning) or a desparate gamble
(if unID'd). Some hooks for similar behavior for other conditions like
turning into slime are included, although no tins can help for anything
other than petrification so far.
Shouldn't fatal illness have an end-is-near countdown too?
Implement a user suggestion that tame humanoids should avoid eating
corpses of their own species. Prevent them--except for kobolds, orcs, and
ogres--from doing so unless starving. Arbitrary: tame elves won't eat
other elves even when starving. A polymorphed character will incur the
effects of cannibalism when eating either his/her underlying race _or_
the current one (player orcs and cavemen aren't affected though).
o Add support for zlib compression via ZLIB_COMP in config.h (ZLIB_COMP
and COMPRESS are mutually exclusive).
o rlecomp and zerocomp are run time options available if RLECOMP and
ZEROCOMP are defined, but not turned on by default if either COMPRESS
or ZLIB_COMP are defined.
o Add information to the save file about internal compression options
used when writing the save file, particularly rlecomp and zerocomp
support.
o Automatically adjust rlecomp and zerocomp (if support compiled in)
when reading in an existing savefile that was saved with those options
turned on. Still allows writing out of savefile in preferred format.
o In order to support zlib and not conflict with compress and uncompress
routines there, the NetHack internal functions were changed to
nh_uncompress and nh_compress as done in the zlib contribution received
in 1999 from <Someone>.
I tagged the sources NETHACK_3_5_0_PREZLIB prior to applying these
changes.
<Someone> reported that if you polymorph into a flying monster while in a
pit, you must take u.utrap turns to first climb out before you can fly. Of
course, once you're out, you can swoop down into the pit to pick things up
w/o delay. Rather that have you automatically fly out (e.g. like quaffing
a potion of levitation), I thought it was better to take a turn to fly out,
so that's what I've implemented.
The code to deal with exiting a pit is moved to a new climb_pit function
and the "up" command now lets you climb from a pit too (something I've
found non-intuitive in the past).
Finally, I noticed that non-moving monsters could still go up/down even
though they couldn't move around. Added non-moving checks in doup/dodown.
Support negation syntax to restrict unwanted race, role, gender, align
options:
OPTIONS=role:!knight, role:!tourist, race:!orc
prevents them from being picked randomly or
appearing in the pick lists at the start of the game.