If regex_compile() fails, free the regexp before doing anything else
in case failure reason is "out of memory". Feedback to the user is
highly likely to panic or crash after memory runs out; this should
let the regex failure message be issued and the game continue.
User sound regular expressions were never freed. This frees them
when FREE_ALL_MEMORY is enabled.
Fix for $USER, $LOGNAME, getlogin() values that have dashes in them:
keep dash and whatever follows as part of the name instead of stripping
it off for role/race/gender/alignment.
Before:
% USER=test-bar-fem ./nethack
|Shall I pick your female Barbarian's race and alignment for you?
and character ended up named 'test'.
After:
% USER=test-bar-fem ./nethack
|Shall I pick character's race, role, gender and alignment for you?
and character ends up named 'test-bar-fem'. However,
% ./nethack -u test-bar-fem
still behaves like the 'before' case.
|Shall I pick your female Barbarian's race and alignment for you?
Dash handling is only changed when the dash comes from user name (or
from envionment overriding user name), not from direct player input
or run-time config file.
drawing.c doesn't include extern.h, so the def_char_... functions
it defines aren't preceded by a prototype. Having such guaantees
that code in other files sees the same argument types as in the
defining code.
Implement the suggested feature that a camera's flash actually update
hero's memory of the map as it traverses across the level. Turned
out to be more work than anticipated despite having the code for a
thrown or kicked lit candle or lamp to build upon.
Among other things it needed to update the circle code to handle
previously unused radius 0 to operate on the center point only. I've
never touched that before and hope this hasn't introduced any bugs.
Also removes several instances of vision code operating on column #0.
(At least one is still present.)
and out of save files so restore doesn't need to clear stale data.
Behavior should be the same as before, except that when entering
the endgame branch and discarding the main dungeon and its other
branches, lua theme context is now discarded for those too.
Clean up a few things I recently noticed:
obsolete monstr.c was still present;
mdlib.c was out of alphabetical order;
monst_global_init() was listed under the wrong file.
Record reaching experience level 3, 6, 10, 14, 18, 22, 26, and 30,
the levels where the character gets a new rank title, and report
those as achievements at end of game. These achievements persist
even if enough levels to lose a rank are lost, and if lost ranks
are regained the original achievement is the one that gets tracked
and disclosed.
I added another goodpos flag to simplify handling displacer beast
and that pushed the total number of makemon and goodpos flags past
16. 'int' and 'unsigned' might be too small, so change the flags
and several function arguments to 'long'.
Replace the octagonal amulet placeholder for the two new tiles.
Give the "cubical amulet" a hint of being cube shaped and rename
"pentagonal amulet" to "perforated amulet" because it's easier to
draw that way.
Bump EDITLEVEL now for the extra objects and monsters because I
forgot to do so earlier.
Adds two monsters originally from slash'em. I used the slash'em
tiles this time, also its code as a starting point but made various
revisions. Both the tiles could benefit from some touch-ups.
displacer beast: blue 'f'. Attempting a melee hit (ie, trying to
move to its spot) has a 50:50 chance for it to swap places with you.
Fairly tough monster to begin with, then half your ordinary attacks
effectively miss and if you try to face a mob by retreating to a
corridor or backing into a corner you can end up being drawn back
into the open. I added bargethrough capability, and also it won't
be fooled about hero's location by Displacement. [It only swaps
places during combat when contact is initiated by the hero, not
when attacked by another monster or when attacking.]
genetic engineer: green 'Q'. Its attack causes the target to be
polymorphed unless that target resists. Hero will almost always
have magic resistance by the time this monster is encountered, but
it can make conflict become risky by hitting and polymorphing other
monsters. Slash'em flagged it hell-only but I took that flag off;
I also took away its ability to teleport. Slash'em polymorphs the
hero if a genetic engineer corpse is eaten; that's included and I
introduced that for monsters too.
I added both of these to the list of candidates for monster spell
'summon nasties' and for post-Wizard harassment.
I also gave all the 'f's infravision. Probably only matters if the
hero polymorphs into a feline.
Displacer beast is originally from AD&D which depicts it as a six-
legged cougar with a pair of tentacles; it has Displacement rather
be able to affect an attacker's location. I think genetic engineer
is original to slash'em where it expands Q class but seems mainly to
be the base monster for Dr.Frankenstein (a unique monster with a
one-level side-branch lair in slash'em's incarnation of Gehennom).
Switch win/share/*.c from hack.h to config.h plus miscellaenous
other headers. It's possible that there is conditional code that
didn't get exercised in my testing. The Unix Makefiles don't deal
with safeproc.c or tileset.c so I just compiled those without any
attempt to link.
This reverts commit eb704832a9.
That fix was insufficient.
The addition of
lua_State *themelua;
to the dungeon struct in dungeon.h prevents the build of host-side utilities that
include "hack.h" via the CROSSCOMPILER_HOST. Unfortunately, it is no longer possible
to cross-compile NetHack 3.7. That includes the cross-compiled MSDOS build.
This reverses all of c67f1dd710
except for the fixes37.0 entry and does a better job in a cleaner
fashion. If Sting is going to start glowing and "you materialize
on a different level" is pending, give the materialize message
before the glowing message. Otherwise handle both stop-glowing
and/or you-materialize in the normal fashion.
When level teleporting, Sting/Orcrish/Grimtooth would start or stop
glowing based on occupants of the new level before "you materialize
on another level". That wasn't necessarily incorrect for the glow
stopping but was clearly wrong for it starting. This fix uses a flag
as a hack to avoid finding and changing all the calls to docrt() and
see_monsters(). It ought to be fixed properly....
while 'mention_decor' is enabled. When stepping onto different
terrain and one or more objects remained on the new spot after
autopickup, describe_decor() was issuing its new-terrain message
right before look_here()'s similar under-the-objects message. If
autopickup grabbed everything or there weren't any objects to begin
with, look_here() doesn't issue any dfeature (terrain) message.
describe_decor() isn't smart enought to know whether that is going
to happen. Give look_here() a new flag argument so that its caller
can ask for the dfeature message to be skipped for the case where a
similar message has already been given.
Change obj->oextra->omid from a usually-Null pointer field in
oextra to a simple 'unsigned' that doesn't need any allocation
beyond obj->oextra itself. Value 0 means that it is not in use;
it is used to hold a monst.m_id and those are always non-zero.
Delete unused obj->oextra->olong. 'olong' used to be the last
field in struct obj, put there to force alignment of anything
which followed it back when obj structures were over-allocated to
append extra information. It had a comment about being used for
temporary gold but whatever that was, temporary gold was gone long
before obj->oextra got introduced.
Bump EDITLEVEL since this invalidates existing 3.7 save files.
Remove a bunch of tabs from obj.h and save.c.
Add some prototypes and add a new include to a couple of files that
use config.h instead of hack.h. So sys/unix/Makefile.src has been
changed slightly.
I added -Wmissing-prototypes to my CFLAGS and got a bunch of warnings.
This fixes the core ones (there are more for X11 that I haven't looked
at yet). While fixing these, I discovered a few option processing
issues: the non-Amiga 'altmeta' should be settable while the game is
in progress (not sure about the Amiga variation so left that as-is),
'altmeta' and 'menucolor' are booleans so shouldn't have had optfn_XXX
functions; 'MACgraphics' and 'subkeyvalue' were conditionally defined
differently in options.c than in optlist.h.
Allow crystal ball to search for furniture (stairs and ladders,
altar, throne, sink, fountain) as well as for a class or objects
or of monsters or all traps. Giving any of '<','>','_','\','#',
or '{' will find all of those rather than just the individual type
specified. Because of the default character conflict, '_' can no
longer be used to find chains; looking for altars is more useful.
The chance of getting the cursed effect due to failing a saving
throw against intelligence when the ball isn't actually cursed has
been reduced. If it is the hero's own quest artifact, it will
happen if rnd(8) is greater than Int, so Int of 8 or more will
never yield that effect. Otherwise if it is blessed, rnd(16) is
used so 16 or better Int means it can't act like it is cursed.
When uncursed and not hero's quest artifact, the old rnd(20) > Int
test is still used.
Crystal balls now start with 3..7 charges rather than 1..5, and
blessed charging sets the amount to 7 charges rather than 6 and
also blesses the ball. Recharing with uncursed scroll of charging
is slightly better (adds 1..2 charges instead of always just 1,
caps the amount at 7 rather than 5) and uncurses the ball. Cursed
scroll strips off all charges even if the ball is blessed and also
curses the ball so is harsher than before.
Crystal balls now cancel to -1 instead of 0, like wands, and using
one effect will destroy it, like zapping cancelled wands.
Also a minor tweak to the initial charges for can of grease (5..25
instead of 1..25) and horn of plenty and bag of tricks (both now
3..20 instead of 1..20).
name_to_mon() has a bunch of alternate monster names, such as
"gray-elf" to match "grey-elf" and "ki rin" to match "ki-rin". Those
worked as intended when they occurred at the end of a wish, but only
worked in the middle if their length was the same or one character
less than the canonical name in mons[].mname.
djinni figurine -> h - a figurine of a djinni
genie figurine -> i - a figurine of a djinni
figurine of mumak -> j - a figurine of a mumak
mumak figurine -> k - a figurine of a mumak
figurine of mumakil -> l - a figurine of a mumak
mumakil figurine -> nothing fitting that description exists
(The one-less case worked because its following space ended up being
implicitly removed when skipping ahead by the length of mons[].mname;
subsequent explicit removal didn't find a space so was a no-op.)
The bases[] array allows finding the index of the first object in
a particular class. Extend it so that bases[class + 1] - 1 is a
reliable way to find the last object in any class. The array had
to be extended by one so that the last class has a [class+1] entry
available, and object initialization now makes sure that classes
within objects[] are in ascending order so that [class+1] always
holds a higher index than [class].
Allows creating shaped or themed rooms for the Dungeons of Doom
via lua script.
Invalidates bones and saves.
Makefiles updated for unix/linux by adding themerms.lua, but other
OSes need to have that added.
Unicorn horns are just too good. Nerf it in similar way several
other variants have done: don't let it restore attribute loss.
This makes potion of restore ability more valuable, and the
int loss from the (nerfed) mind flayers matter more.
Changes domove() code to allow displacing peaceful monsters.
Specifically, is_safepet() now returns true if the monster is peaceful.
Peacefuls are slightly pickier than pets about whether they consent to
being displaced: they will not displace if a goodpos() check fails for
the displaced space, or if there is a trap on the displaced space, or if
they are your quest leader. is_safepet should probably be renamed to
something else.
In the process of doing this, some other changes were made: the code now
checks whether the player and monster should be swapping places at all
first (previously it ran some code for displacing pets out of traps
first, which was a little weird if the displacement didn't actually
happen.)
In the original commit for this, I needed to guard the spoteffects()
call made in domove with a clause testing whether the player actually
moved; it was previously possible to fail to displace a monster and then
re-trigger a trap on the space you were still standing on. However, the
devteam has apparently put in an if (u.umoved) clause in the same place
and serving the same purpose.
When rest and search refuse to operate because a hostile monster is
adjacent, include a reminder of how to force them to operate. Every
time if 'cmdassist' is On, or just once until after some subsequent
try actually does something.
This new rest and search behavior probably needs to be optional and
default to the old behavior. It isn't uncommon to deliberately rest
while adjacent to a hostile monster if also adjacent to a peaceful
one and trying to wait for Stun or Confusion to time out, or maybe
search while next to such a monster hoping to find a secret door to
run away through. A count prefix won't work and needing an extra
keystroke each time is going to be an annoyance.
When matching a terrain, allow using a "w" placeholder that matches
any solid wall:
For example:
local s = selection.match([[w.w]]);
would match all floor locations with a wall to the left and right of it.
The walls can be solid stone, horizontal, vertical, etc.
This applies to selection.match(), selection.filter_mapchar(), and
des.replace_terrain()
when hero is wielding a cockatrice corpse. Wands of undead turning
aren't generated as starting equipment but they will now be picked
up if come across while the hero is carrying any corpse, and used
in preference to any other item when carried and non-empty and hero
is wielding a petrifier's corpse.
Fixes#320
Avoid giving "you are back on the bottom" nearly every step when
moving around underwater.
Avoid "you are back on floor" followed by "you trip over <object>"
when fumbling in case that fumbling was due to being on ice when
taking the step to floor. Done for all fumbling rather than just
one-turn fumbling instigated by ice.
When moving from ice or water to ground, show "you are back on floor"
before listing objects at that spot instead of after.
I think there was at least one more thing but have lost track. At
any rate, 'mention_rate' potentially has a new set of bugs.
Adds a new level init type which directly creates a maze,
optionally setting corridor width and wall thickness,
and removing dead ends.
des.level_init({ style = "maze", corrwid = 3, wallthick = 1, deadends = false });
Uncomments and makes available selection.gradient in Lua. (The backend C
code for this still existed, it just wasn't used.)
The only valid way to specify a gradient is with a table. I considered
adding non-table versions, but decided that there are too many
independent variables that can be optional. A non-table version, without
named parameters, would be confusing to read, especially since most of
the arguments are ints.
Also adds an impossible in the (possibly unreachable) case that
selection_do_gradient gets called with a bad gradient type.
Reject arrows and darts as candidates for wielding two weapons at
once.
Make the check for being able to two-weapon when polymorphed be more
robust. Instead of just testing whether the monster form's second
atttack is a weapon attack and then assuming that the first one is
too, test the first three to validate that at least two of those are
AT_WEAP. The existing code works but seemed fragile.
The impetus for this was to avoid ugly constructions such as the one
below (none of which currently appear in vanilla NetHack):
mongets(mtmp, LONG_SWORD);
struct obj* sword = m_carrying(mtmp, LONG_SWORD);
if (sword)
/* do thing to sword */
Most cases where mongets is used discard the returned value (which used
to be the created object's spe); the only places that do use it are the
series of statements that give various human monsters armor and prevent
them from getting too much armor. These statements included hardcoded
constants representing the base AC of the armor, which would have caused
discrepancies if armor's base AC were ever changed.
With mongets now returning a pointer to the created object, it can just
be passed into ARM_BONUS instead, which covers both the base AC and the
enchantment. (It will also cover erosion, if anyone ever decides that
armor should rarely generate as pre-eroded).
The overall algorithm is not changed by this; human monsters should
receive armor with the same probabilities as before.
Shriekers only spawn purple worms when they're appropriate difficulty.
Non-tame Purple worms eat corpses off the ground.
Baby purple worms attack shriekers.
Hero polyed into baby purple worm is warned against shriekers.
Original changes by copperwater <aosdict@gmail.com>, added with some
formatting adjustments and consolidation.