Something's wrong with the way lava was being handled in moveloop().
If you were trapped in lava (ie, moved into some but didn't die on the
spot thanks to fire resistance), you could sink and ultimately die without
ever taking another actual turn (typing ``i<space>'' repeatedly is an easy
way to reproduce). [`didmove' was only being checked for the sinking
deeper case and not for the decrement which ultimately leads to the fully
sunk case.] On the other hand, if you could manage to start an occupation
and avoid being interrupted, you would never sink while it was in progress.
[Lava handling followed ``if (multi && occupation) { ...; continue; }''.]
While testing some other code (lava vs slime, coming shortly) I ended
up with the cursor sitting on the status line while the game was waiting
for me to enter my next move. I don't really understand what's going on
there, and moving the lava handling before bot() might have hidden that
particular problem now by changing the point at which Slime will get taken
off the status line, but this attempts to fix it anyway.
From a bug report: you
can dip a worn item such as shirt or suit into a potion of polymorph and
it will become unworn--but as of a couple of days ago, unworn only if the
transformed object's new form can't be worn in the same slot--even if it
is covered by a cursed worn item (suit or cloak). It didn't seem like
trying to fix that special case would be very worthwhile; this fixes the
more general situation of "you could dip worn items even though they were
covered up by other worn items".
In the same report: you could apply grease to rings while wearing
cursed gloves. The code already prevented greasing a suit when it was
covered by a cloak (regardless of whether that cloak was cursed), and a
shirt when it was covered by a suit or cloak or both. This moves that
code into a separate routine which is used for dipping as well as for
applying grease, and now handles rings vs gloves.
Since covered rings, shirt, or suit are no longer eligible to be
dipped or greased, this also makes "?" for the pick-an-item prompt leave
such things out of the list of likely candidates.
From a bug report. That's hard to fix in the general case because armor
and tools might not fit back into the same equipment slot, but most other
types of worn items can be re-worn after being transformed. This makes
any transformed worn item stay worn if it is wearable in the same slot.
Eliminate the somewhat redundant "You die..." following "You turned
to stone..." when becoming petrified by touching a cockatrice (reported
by <email deleted> for kicking, but occurs for weaponless hitting too).
Also, if a cockatrice killed you with normal damage, your tombstone would
erroneously report petrification and presumeably there'd be a statue
instead of a ghost in the resulting bones file. This fixes both things.
Using #tip (post-3.4.3 code) on a container that's on a shop floor
didn't handle ownership correctly. Bag of tricks could be emptied for
free, and contents of other containers were being sold to the shop even
when the shop already owned them. This fixes bag of tricks and makes a
first cut at doing so for regular containers.
Message handling when #tipping any bag of tricks was also suboptimal
since the decision about message delivery was made again as each charge
released something instead of waiting until the whole bag was emptied.
So you could get inappropriate "nothing seems to happen" before or after
a monster visibily popped up if something unseen was also produced.
Some code I recently added was misusing count_unpaid() and would
traverse some or all of inventory instead of just container's contents
when looking for unpaid items. Add mew routine `is_unpaid(obj)' to do
what I was intending to do with count_unpaid().
Use verbalize instead of pline for shop "thank you, scum" message
(From a bug report. Suppress shop "you sneaky cad" message
when removing a hero-owned pick-axe from a container inside a shop if the
shk is unable to speak; also give it at most one time per move (taking
multiple pick-axes out of a bag at once was way too verbose). Honor
addtobill's silent flag for the bill overflow message when/if that occurs.
Also adds a safe_qbuf usage for the #tip command that I had pending
for pickup.c.
Inventory display adds "(unpaid, N zorkmids)" to carried unpaid
items, but it didn't show anything comparable for indirect unpaid ones
(hero-owned containers holding shop-owned objects). Now it will include
"(contents, N zorkmids)" in such cases.
Change safe_qbuf() so that instead of picking one of three strings
for sprintf() to plug into a prompt string, it actually constructs the
full prompt string itself. Also pass in the unformatted object and a pair
of formatting functions instead of performing dual formatting in advance.
The actual formatting is done via new routine short_oname() which also
takes an object and a pair of formatting routines plus a target length.
It uses the first routine, typically xname() or doname(), and formats the
object, then if the result is too long it makes some transformations, and
tries again. If truncating "called foo" and "named bar" down to 12 chars
and omitting "uncursed, rustproof, thoroughly corroded" attributes still
result in a string that's too long, it uses the other formatting routine.
The latter calls one of several jacket routines around simple_typename()
to produce a short result.
This has been through about four incarnations now and has gotten a
bit less testing each time, but I need to get it in place before I end up
running out of gas and abandoning it. I've got some changes to shk.c
(where safe_qbuf is needed but not currently used) that now need to be
redone and will come eventually.
From the newsgroup: if a pet was hiding under an object next to you
when you changed levels, it could arrive hidden at the destination if there
was something available to hide under there too, and sometimes you'd start
the new level with a hidden monster glyph at its location. I was able to
reproduce that once with current trunk code, but while trying to figure
out what is actually happening I've been unable to make it happen again.
However, it doesn't make sense for a monster to be able to remain in hiding
during the level change in the first place, so this patch prevents that.
(I'd still like to know how/why map_invisible() is sometimes getting called.
[The test character was a level 1 tourist without auto-search capability.]
I'm reasonably sure that it won't happen any more once this fix in place.)
This also brings adjacent pets out of hiding when they accompany you
during ascension or dungeon escape, but it seems that that wasn't actually
necessary. The end of game disclosure already lists such by name rather
than as "it", contrary to my expectations. (I had forgotten that end-of-
game forces true names so that blindness and hallucination don't interfere
with disclosure; obviously that ends up handling hidden monsters too.)
This patch attempts to add some levels of unicode support
to NetHack.
The master on/off switch for any Unicode support is
defining UNICODE_SUPPORT in config.h. Currently
there is code support for two subsets of unicode support:
UNICODE_DRAWING
If UNICODE_DRAWING is defined, then the data
structures used to house drawing symbols are expanded
to the size of wchar_t, big enough to hold unicode characters.
A typdef called `nhsym' is involved and if UNICODE_DRAWING
is defined, it is wchar_t, otherwise it is uchar.
UNICODE_WIDEWINPORT
If UNICODE_WIDEWINPORT is defined, then the data
structures inside the window port are expanded to the size of
wchar_t, big enough to hold unicode characters. Both map
symbols and text within the window port are expanded, in order
for potential support for displaying multinational characters some
day, but this patch only provides viewing of map symbols.
A typdef called `nhwchar' is involved and if UNICODE_WIDEWINPORT
is defined, it is wchar_t, otherwise it is char.
The only window port with code support for UNICODE_WIDEWINPORT
currently is the TTY port. Don't enable UNICODE_WIDEWINPORT
unless:
- it is a TTY port
- the underlying platform specific routines can
handle the larger data structures.
Don't enable UNICODE_SUPPORT unless:
- your compiler can handle wchar_t.
- your compiler can accept L'a' characters.
- your compiler can accept L"wide" strings.
Note that if your compiler can handle the above, you could
enable the larger data structures (currently if TTY) even if your
platform can't actually display unicode or UTF-8, by messing
with u_putch() in win/tty/wintty.c to only deal regular chars.
That should be the only function that actually pushes wide characters
out to the display.
If you enable UNICODE_SUPPORT, and your platform is capable
you will need to turn on the unicode run-time option to be able to
load unicode character sets from the symbol file, to be able to
push unicode characters to the display. You'll also want to load
a unicode symbol set once the unicode option is toggled on. In
a config file you would do that via these two lines:
OPTIONS=unicode
OPTIONS=symset:Unicode_non_US
The repository was stamped with NETHACK_PRE_UNICODE
prior to applying this patch, and stamped with
NETHACK_POST_UNICODE afterwards. The code differences
between those two tagged versions are this patch.
Add putmixed() to the window port. It allows map symbols to
be included in the string by encoding them in a unique fashion.
This was done because Unicode symbols, for instance, could be
longer than the size of a char.
The encoding of the map symbols in this patch is done by
prefixing a glyph value with \GXXXX, where XXXX is a
random value for the current game. The reason for the random
prefix is to minimize the possibility that a player can trigger
the escape sequence processing within text under their control
(dog names, etc.) the way they could if the sequence was fixed
in the source code. The random prefix remains the same throughout
the lifetime of a game because message window strings are
saved in the save file.
(There was actually a bug present because of the embedded
character even before the recent symbol changes, because if
someone was using a different set of characters between games,
the saved messages would reflect the original characters, rather
than the current. That bug was introduced with the ability to
save messages to the savefile.)
A window port does not have to supply an XXX_putmixed() routine,
it can use genl_putmixed() which uses the old behavior of
embedding the sequence as a character within the string
and calling putstr(). genl_putmixed() takes care of the decoding
of the escape sequence.
This also #ifdef's out code in pager.c for converting a glyph
to a character, and uses mapglyph() to do that instead. Does
anyone see a problem with doing that through mapglyph instead
of repeating similar code within pager.c?
From the newsgroup: if you were wielding a cockatrice corpse without
gloves while polymorphed into something capable of doing that, then were
turned to stone when rehumanizing, you'd be left wielding the untouchable
corpse if life-saving kept the game going. This causes it to stop being
wielded if you get that far. Likewise for monsters.
From the newsgroup: it was possible to saddle, mount, and ride on a
sleeping jabberwork without it ever waking up. Movement was checking for
timed sleep (!mon->mcanmove, set when mon->mfrozen contains a timer count
for either sleep or paralysis) but not indefinite sleep (mon->msleeping).
This moves the checking into its own routine which handles both types.
And it gives monsters a chance to wake up when they get saddled or mounted.
Extend the identifying information used to prefix paniclog entries
from version + date to version + date + time + userid + mode (where mode
is 'D' for wizard mode, 'X' for discover mode, and '-' for normal play).
hacklib.c ended up getting more of a revision than I intended, but
the date/time handling routines now have less clutter. I hope I didn't
break anything in the process.
<Someone> pointed out that bugles, although noisy, only affect soldiers.
This didn't make sense to me either. Added code so they will also affect
monsters near the bugler.
Clean up the preprocessing associated with the
loadable symbol stuff.
Base it on new LOADSYMSETS, rather than on the
previously existing ASCIIGRAPH preprocessor define.
- reduce the number of symbol tables for each graphics
set {PRIMARY, ROGUESET} from three {map, oc, mon}
tables for each of the display symbols, the loadable symbols,
and the rogue symbols, to one continguous table for
each:
showsyms: the current display symbols
l_syms: the loaded, alterable symbols
r_syms: the rogue symbols
- Modify mapglyph so that the index into the symbolt table is
available as a return value (it was a void function), rather than
just the char converted from the glyph.
- That makes it possible for a window port to use the same
index value to extract from another table (perhaps a unicode
table) for a different set of display symbols. The index
is much more useful than trying to convert the character
into another type of symbol, as some contributed patches
have done.
- It is much easier to load a single alternative flat table to
make substitutions, since the corresponding value just
has to get placed into the same index offset in the
alternative table.
This also fixes a bug I found in botl.c, where you could
go to the rogue level, and the bottom line gold symbol
was not being updated with the new character as it should.
The reason was because the gold value had not changed,
only the field symbol used had changed.
This updates multiple ports to place a (void) cast on
the mapglyph call, now that it returns a value, so this
is going to generate a lot of diff e-mails.
About six weeks back, <email deleted> suggested that
bear traps should deal out damage and be escapable via opening magic.
This doesn't do anything about the first part, but it does allow opening
magic (wand of opening, spell of knock, blessed Bell of Opening) to get
the hero out of bear traps and webs if zapped either at self or downwards.
Zaps across the floor which hit monsters will free them from such traps,
with a chance that releasing a hostile monster will pacify it (using
existing #untrap code). Conversely, if you are at a web or bear trap
location but not currently trapped, closing magic (wand of locking, spell
of wizard lock) will cause the trap to activate; you may or may not become
trapped. Likewise for zaps at monsters who are at such locations, which
is treated as an attack.
Opening magic which hits the hero or a monster located at a trap door
or falling rock trap spot will cause the trap to activate; as above, it's
an attack for the monster case. At the moment, zapping opening magic
downwards at the hero's location (but not zapping at self or at monsters)
will also cause holes, pits, and spiked pits to activate. (Zapping down
triggers falling rock traps and zapping up doesn't; that'll need to be
changed.) Zapping opening down while mounted will untrap, if stuck in a
web or bear trap, and will trap, for the falling cases, in precedence over
releasing the saddle and forcibly dismounting. The latter still occurs
when there is no applicable trap present though.
Zapping locking magic downwards at a hole location will convert the
hole into a trap door. Zapping breaking magic (wand of striking, spell of
force bolt) down at a trap door location will convert the trap door into a
hole. (Neither conversion currently alters the made-by-you flag for the
trap. However, the rationalization that distinctive style is what makes
made-by-you recognizable suggests that conversion should clear the flag.)
Lastly, the old behavior (which pre-dated bare holes) of destroying trap
doors when zapping down at them with locking magic has been removed--it
didn't seem to fit very well with the new cases. I'm starting to have
second thoughts about that but am going to commit this before discovery of
some more niggling details drags it out for another six weeks.
Pat Rankin wrote:
> Symbol set definitions need a description attribute, above and
> beyond allowing comments in the file, for inclusion in the 'O'
> command's menu entries for selecting them.
[...]
> mapglyph.c isn't the proper place to decide whether to define
> ROGUE_COLOR. That may need to become a symbol attribute,
> which we'd then specify on the Epyx rogue set(s).
Implement both of the suggestions above.
- Instead of checking for the Rogue level, check which
graphics are engaged (PRIMARY or ROGUESET) in the
SYMHANDLING() macro.
- track which graphics are active through 'currentgraphics'.
- Instead of symset and roguesymset and symhandling and roguehandling
variables, have symset and symhandling be arrays of two, with the
following indexes:
PRIMARY
ROGUESET
That reduced the amount of repeated code.
(Not to be confused with the 'symset' and 'roguesymset' config file options
both of which still exist)
- the symbol routines were adjusted to pass
the index , rather than 'rogueflag' and coding to roguesymset etc.
Other than fixing bugs that are encountered, this is probably
the last of the symbol stuff, with the exception of
making the symset and roguesymset config file options
accept the keyword value "default".
This is an overhaul to the NetHack drawing mechanism.
- eliminates the need to have separate lists in drawing.c
for the things and their associated explanations by grouping
those thing together on the same inializer in a struct.
- replaces all of these options: IBMgraphics, DECgraphics, MACgraphics,
graphics, monsters, objects, boulder, traps, effects
- drawing.c contains only the set of NetHack standard symbols for
the main game and a set of NetHack standard symbols for the
roguelevel.
- introduces a symbols file that contains named sets of
symbols that can be loaded at run time making it extensible
for situations like multinational code pages like those reported
by <Someone>, without hardcoding additional sets into the game code.
- symbols file uses names for the symbols, so offsets will not break
when new things are introduced into the game, the way the older
config file uchar load routines did.
- symbols file only contains exceptions to the standard NetHack
set, not entire sets so they are much less verbose than all of
the g_FILLER() entries that were previously in drawing.c
- 'symset' and 'roguesymset' config file options for
preselecting a symbol set from the file called 'symbols'
at startup time. The name of the symbols file is not under the
users control, only the symbol set name desired from within the
symbols file is.
- 'symset' config file option loads a desired symbol set for
everything but the rogue level.
- 'roguesymset' config file option loads a desired symbol set
for the rogue level.
- 'SYMBOLS' config file option allows the user to specify replacement
symbols on a per symbol basis. You can specify as many or as few symbols
as you wish. The symbols are identified by a name:value pair, and line
continuation is supported. Multiple symbol assignments can be made on
the same line if each name:value pair is separated by a comma.
For example:
SYMBOLS = S_bars:\xf0, S_tree: \xf1, S_room:\xfa \
S_fountain:\xf4 \
S_boulder:0
- 'symbols' file has the following structure:
start: DECgraphics
Handling: DEC
S_vwall: \xf8 # meta-x, vertical rule
S_hwall: \xf1 # meta-q, horizontal rule
finish
start: IBMgraphics
Handling: IBM
S_vwall: \xb3 # meta-3, vertical rule
S_hwall: \xc4 # meta-D, horizontal rule
finish
- 'symbols' file added to the source tree in the dat directory
- Port Makefiles/scripts will need to be adjusted to move them into
HACKDIR destination
From a bug report, having hallucination time out while
mimicking an orange (instead of gold, after eating a mimic corpse), you'd
still get the hallucinatory end-of-mimicking message about not wanting to
be peeled. If hallucination state is toggled, update the pending message
and change the hero's appearance. In practice, only the orange-to-gold
case can occur. Anything which might trigger gold-to-orange will have
terminated the hero's mimickery befort that happens.
Remove some more code that forced pointers into a long int, and
vice versa where information could be lost (P64 platforms such as
WIN64 have a 64 bit pointer size, but a 32 bit long size.)
This 2nd part deals with timeout functions switching
some arguments from type genericptr_t to 'anything'.
Like part 1, this needs to increment EDITLEVEL in patchlevel.h.
[the problem in the earlier rev was tracked to cleanup_burn(),
where arg was holding a (genericptr_t) timer id, and
passed directly to del_light_source() as is.]
P64 (Win64) has a 64 bit pointer size, but a 32 bit long size.
Remove some code that forced pointers into a long int, and
vice versa where information could be lost.
This part deals with light source functions and their
arguments mostly, and switches some arguments
from type genericptr_t to 'anything'.
P64 (Win64) has a 64 bit pointer size, but a 32 bit long size.
Remove some code that forced pointers into a long int, and
vice versa where information could be lost.
This part deals with light source functions and their
arguments mostly, and switches some arguments
from type genericptr_t to 'anything'.
Hide pointer formatting in alloc.c by eliminating the need for callers
to know how big a buffer is required. I generally prefer the caller to
pass in its own buffer for this sort of thing, but in this case the usage
is almost entirely for debugging so using static buffers results in less
clutter in the rest of the code.
<Someone> reported that he applied an unID'd bag and it became
discovered as a bag of tricks even though a spellbook appeared on the floor
next to him rather than having a monster show up (the monster was a mimic).
Suppress the bag discovery unless you can see or sense a monster appear.
(This doesn't really achieve much for most players, who'll recognize the
bag because they know that only one type of container doesn't prompt to
take things out and/or put things in, but I think it does make sense.)
While mucking with bag of tricks I decided that to be consistent with
the behavior of other containers, the #tip command should release all the
monsters in the bag instead of just one.
And after doing that, I realized that horn of plenty ought to behave
much the same, so #tip will operate on it now. However, it won't be listed
as a likely candidate in the "which item?" prompt unless/until it has been
discovered. (Attempting to empty any other type of horn yields "nothing
happens", same as for a horn of plenty with no charges left.) Emptying a
horn of plenty in a shop can be extremely verbose, but I don't think that
qualifies as a bug and don't currently have any plans to alter it.
Several polymorph tweaks, most dealing with specifying form under
polymorph control or for wizard #polyself:
1) allow "were<critter>" and "human were<critter>" for your type of
<critter> when you're inflicted with lycanthropy; now you'll toggle
shape rather than be told "you cannot polymorph into that".
2) allow your own role; now you'll become a new man (or whatever race)
rather than get "you can't".
3) allow "human" to force a new man (or whatever) regardless of race.
No change for human characters, but elves, dwarves, and such can now
use either their own race or "human". (They never become humans.)
4) for wizard #polyself only, override the 20% chance of becoming a new
man instead of taking on the selected form. (This implicitly prevents
the annoying "your new form isn't healthy enough to survive" death
since your experience level won't drop below 1.)
5) remove a redundant drowning check in polyself(); it's already handled
in polymon() and polyman(for newman()) via spoteffects().
This also gets rid of an old use of 0 as not-a-valid-monster (not
responisble for any bugs though since giant ants aren't lycanthropes).
The user (<email deleted>) who recently suggested a
dump command for containers also wanted atmospheric sounds on levels which
have altars. Right now we'd have to find unattended altars the hard way
(by scanning the entire level) but we could add a counter (or set of
counters, one per alignment) like for fountains and sinks if we really
wanted to do that. [Now that I think about it, the #overview patch may
have already done something of the sort.] But what noises would an altar
be expected to produce? This only adds sounds for temples, where the
attending priest can be the source of the noise.
I'm not real thrilled with the initial set of sounds, particularly
the hallucinating one, but the implementation works. The "carcass" one is
a little clumsy; it's intended to add a hint for new players who haven't
figured out what the #offer command does.
When the hero receives the quest artifact "got it" message, set the
artifact's dknown bit in case the hero is blinded. That message describes
the object by name, effectively the same as seeing it up close. (This
would have prevented the "now wearing an Eyes of the Overworld" grammar bug
for monks but not for non-monks, so the previous fix is still necessary.)
The code to have Izchak recognize the Candelabrum of Invocation
instead of just being uninterested in an item not stocked in his shop was
being skipped when the character is hallucinating. Make it work for any
lighting store (slash'em sometimes has another candle shop, run by a
randomly named shopkeeper), and make it recogize Izchak even when
hallucinating. Also, have him give a message about the need for 7 candles
if the candelabrum doesn't already have them attached.
Fix the bug From a bug report.alt.org server, where killing a monster by closing the
castle drawbridge resulted in a panic after the dead monster's possessions
were dropped into the moat and a potion of acid exploded in the process.
water_damage() deleted the object but had no way to tell flooreffects()
that it was gone, so flooreffects() couldn't tell its own caller not to
place and stack the object. After that, a chunk of freed memory became
part of the floor objects chain and eventually triggered a panic which
tried to make a save file but whose reason didn't get logged properly.
Provide a common routine that always does the right
thing with respect to timers and weight when altering
obj->corpsenm, and use it throughout the code.
Provide a command to easily verify that the rumor true/false
boundary offsets are correct for the rumors file.
If the boundary is pointing mid-line, the rumor at the boundary
won't decrypt properly.
Add Hojita Discordia's Dungeon Map overview as
conditional code for experimentation and testing.
Everything is guarded by
#ifdef DUNGEON_OVERVIEW
#endif
The notes that accompanied the original patch follow.
Dungeon Map Overview Patch for Nethack 3.4.3
Version 3
=============================================================================
Changelist:
v3: Changed #level to #annotate to avoid #levelchange collision. Fixed
handling of elemental planes and astral plane (oops). Changed
formatting to be slightly closer to print_dungeon()'s. Should be
"final" version for 3.4.3.
v2: Added tracking of trees. Changed ctrl-m command to ctrl-o. Portals
displayed as "sealed" instead of "closed".
v1: First release.
(Note: all versions are mutually save compatible.)
=============================================================================
This patch creates a dungeon map overview that is recorded as the player
explores the dungeon. I was tired of returning to a game a few days later
and having no idea what the dungeon looked like. Trying to name pieces
of armor with shorthand didn't work so well as an intermediate solution
either, especially around nymphs.
It can be assumed that this map is in the mind of the hero and thus
can't be stolen, can be read when blind, or when buried, or when the hero
doesn't have any hands, or eyes, or hands free, or...etc. On the other hand,
this implies that the hero doesn't remember all of the details ("a fountain",
"some fountains", "many fountains") and that the map is subject to amnesia
when applicable.
This overview tracks fountains, altars, stores, temples, sinks, thrones,
trees, and dungeon branches. It attempts to not spoil the player nor
reveal more information than the hero knows. For this reason, it only
tracks dungeon features found in the guidebook and dungeon branches.
This patch breaks save file compatibility. Sorry.
Added commands
=============================================================================
#overview (ctrl-o, if not in wizard mode) - displays overview
#annotate (ctrl-n, if using numpad) - names current level
Example Output From #overview
=============================================================================
The Dungeons of Doom: levels 1 to level 15
Level 1:
A fountain
Level 3: (My stash.)
An altar, some fountains
Stairs down to The Gnomish Mines
Level 7:
Many fountains
Level 8:
Stairs up to Sokoban, level 7
Level 15:
A general store
Sealed portal to The Quest
The Gnomish Mines: levels 4 to level 7
Level 7: <- You are here
Many stores, some fountains, a temple
More Details
=============================================================================
The overview shows only levels that have anything interesting to display and
doesn't show branches that don't have any interesting levels.
To avoid the map revealing more information than the hero knows, the overview
only displays things that the hero has seen or touched. (If the hero
blinds herself, levitates above a known fountain, and obliterates it with a
wand of digging, the overview will still say that there is a fountain.)
This is done, sadly, by adding 6 bits to the rm struct to track the last
known dungeon type. On the other hand, this change could potentially allow
a window port to do something like drawing an item and a fountain on the same
square.
Things That Could Be Better And Maybe Some Feedback Would Help
=============================================================================
"<- You Are Here" is pretty goofy
-...but an indicator of some sort is nice.
=============================================================================
Many thanks to all the kind folks on r.g.r.n. who had very good feedback
about this patch, in particular L (for the trees), <Someone> Papaganou (for the
#annotate suggestion and some formatting feedback), and <Someone> (for the suggestion
of just overriding ctrl-o instead of using the very broken ctrl-m.)
=============================================================================
20060311. Hojita Discordia. (My usenet email is bogus. Sorry.)
There were routines that were passed the
object name as an argument. Before the oextra
patch, ONAME() always returned a valid pointer
to a location within the obj struct. The oextra
patch worked around those cases by
using a temporary variable that was either set
to ONAME (if the obj passed the has_oname() test),
or to "" (pointer to an empty string) if no name was
present.
Since that might be a common thing to do, provide
the safe_oname() routine that you can use as a
function parameter without having to worry about
about whether ONAME(obj) is valid, and without
the need for the temporary variable.
The revised newmail() wouldn't compile (Strncpy doesn't exist, `buf'
was an array of pointers rather than of char). Simplify it substantially,
and adjust the one caller (vms) that relied on the old convoluted bit.
move oattached and oname and other things that vary
the size of the obj structure into a separate
non-adjacent oextra structure, similar to what has
already been done for mextra. The obj structure
itself becomes a fixed size.
New macros:
#define ONAME(o) ((o)->oextra->oname)
#define OMID(o) ((o)->oextra->omid)
#define OMONST(o) ((o)->oextra->omonst)
#define OLONG(o) ((o)->oextra->olong)
#define OMAILCMD(o) ((o)->oextra->omailcmd)
#define has_oname(o) ((o)->oextra && ONAME(o))
#define has_omid(o) ((o)->oextra && OMID(o))
#define has_omonst(o) ((o)->oextra && OMONST(o))
#define has_olong(o) ((o)->oextra && OLONG(o))
#define has_omailcmd(o) ((o)->oextra && OMAILCMD(o))
changed macros:
has_name(mon) becomes has_mname(mon) to correspond.
The CVS repository was tagged with
NETHACK_PRE_OEXTRA
before commiting these, and
tagged with
NETHACK_POST_OEXTRA
immediately after. The diff
between those two tags is this oextra patch.
The associated mail daemon changes to use an oextra
structure instead of a hidden command located in the
name after the terminating NUL, have not been tried
or tested.
<Someone> suggested that digging down on a land mine with a pick-axe ought
to set if off. I agree; this implements that and also for bear traps. In
the bear trap case, if you dig down once trapped, you will destroy that
trap explicitly rather than replace it with a pit, so it's now possible to
escape from one without leaving another trap in your wake. Once the bear
trap is gone, further digging there will make a pit as usual. While stuck
in one, digging down poses a modest risk of harming yourself.
|You now wield a pick-axe.
|You start digging downward. A bear trap closes on your foot!
|You start digging downward. You destroy the bear trap with your pick-axe.
|You continue digging downward. You dig a pit in the floor.
|You start digging downward. You dig a hole through the floor.
|You fall through...
[It seems a bit strange that finishing a pit discards all digging context,
so that resuming within the pit in order to make a hole "starts" digging
rather than "continues" it.]
Digging down with a wand or spell will disarm these two types of traps
and then leave the corresponding object (which may or may not fall through
the resulting hole, like any other object there). Digging to the side via
magic while trapped in a pit will also disarm such traps when it encounters
them. (When not in a pit, a digging beam which simply passes over an armed
bear trap or land mine won't have any effect on the trap.) Digging to the
side via tool behaves somewhat oddly ("no room for the rubble"?) and will
probably need some tweaking before eventual release; at present it doesn't
reach adjacent traps so didn't need any land mine or bear trap handling.
I put the fixes entry in the new features section.
<Someone> reported that thitu() was adding d20 damage for silver object
hitting silver-hating hero even though all the callers were using dmgval()
which also does that, resulting in doubled silver bonus/penalty. This
fixes that (including for boomerangs thrown by player, which weren't using
dmgval(), to handle a hyptothetical silver boomerang). While testing it,
I noticed that there was no "the silver sears your flesh" message when a
monster hit you with a wielded silver weapon, so this fixes that too.
(How did we miss that? And how did <Someone>? :-)
Move some internals-related code out of port-specific main so that
it isn't duplicated a bunch of times. One minor side-effect of this
change is that if you auto-pickup something at the very start of a game,
it will happen after any full moon/new moon/Friday 13th message rather
than before. There's a second change for some: the shared main() used
by several of the micro ports had a small difference in game play--if you
saved a game while on an engraving, it would automatically be read when
you resume--that will now occur for everybody [Elbereth weenies rejoice!].
pcmain() was also calling update_inventory() at start of play. That's
unnecessary for new games, where inventory initialization triggers a call
to it for each item added to your pack; but I wasn't sure about restored
games, so everybody gets it there now.
The Mac and BeOS ports evidently haven't been touched it some time;
they still referenced flags.move which got replaced by context.move quite
a while back. The Windows GUI code has a declaration for mswin_moveloop()
which appears to be non-existant, but I left it alone. I assume that the
Qt interface uses the existing main() routines; at least I couldn't find
any start of game code specific to it. vmsmain's revised main() is the
only one which has been tested.
Something I encountered while playing slash'em a while back, but
relevant to nethack: "Its orcish spears shatter from the force of your
blow!". I was using a two-handed weapon (at skilled or expert level) to
fight an invisible monster which was wielding a stack of multiple spears
(slash'em gives them out in groups of 3 for monsters' starting inventory).
After killing it, I found 2 orcish spears along with an invisible corpse
of somebody-or-other the Kobold King. The message suggested that the
whole spear stack had been destroyed (and the weapon shattering code in
hmon_hitmon() clearly expects that to be the case), but only one of them
had actually gotten used up.
I can't recall whether "shatter" was actually given as singular or
plural at the time; nethack handles that aspect correctly. Only object
destruction needed tweaking.
<email deleted> wrote:
> Eating gold in a vault (or polymorphing a pile of gold into 1 gold piece)
> doesn't anger the guard.
This addresses the eating part of that report, but the hero
has to get caught doing it.
This one turned out to be more effort than I had
originally anticipated.
We had a bug report requesting that zapping a wand of digging
laterally while in a pit should dig beside you. That seemed
like a reasonable enough request, but this ended up with
the following results:
- needed to check where this should not be permitted, or at
least where there should be special-case code because there is
something such as furniture on the surface above the dig
point.
- now tracks conjoined pits through new fields in the trap
structure, hence the pathlevel increment. The array of
8 boolean values represents each of the 8 directions
around a pit.
- Previously, pits could be adjacent to each other as two
individual pits, in which case moving between them
results in a fall as you went into the next pit. That
behavior is preserved.
- Pits created either by zapping a wand of digging
laterally while in a pit, or by "clearing debris"
between two adjacent pits via a pick-axe, sets the
conjoined fields for those two pits. You cannot
create a brand new adjacent pit via pick-axe, only
with the wand.
- The hero can pass between conjoined pits without
falling.
- dighole() was hijacked for adjacent pit digging,
so the ability to pass coordinates to it and
its downstream functions was added (dig_up_grave()
for example). dighole() does pretty much everything
appropriately for this adjacent digging, more so
than calling digactualhole() directly.
- moving into a conjoined pit that has spikes still
does damage, but less so that "falling" into the
spiked pit, and you "step on" the spikes rather
than falling into them.
- Not done: should pits with the conjoined fields
set be referred to as 'trenches' rather than pits
in messages and identifications?
From a bug report: when creating a
level, anthole rooms can be generated even when no ants are left, unlike
beehives which get suppressed once killer bees are gone. Also, if some
ants are available but the type chosen for the current level isn't (in his
case, soldier ants had been genocided), the anthole was filled will random
monsters instead of picking another type of ant. This fixes both issues.
Random monsters will only occur if the last type of ant gets used up while
filling an anthole that was started when some ants were available, same as
how monster generation for beehives and barracks works.