Adds sanity checks for mtrapped and mundetected states.
Fixes cases where those were left in wrong state.
1. Trapped monster (eg. a nymph) teleported out of a trap
2. Monster was hiding under ball or chain, which then got removed
3. While restoring a level, a zombie corpse revived while monster
was hiding under it
4. A general case where the only object was deleted off floor and
a monster was hiding under it
Monsters hiding under ball or chain will now get revealed when
the b or c are moved.
When SCORE_ON_BOTL is enabled, you could tell how much gold is
inside a container with unknown contents by having 'showsore' On
and watching how much the score changed on the status line when
picking the container up.
I was looking into adding a confirmation prompt for '!' and it
isn't very promising due to sequencing issues. (The check for
whether '!' is allowed should happen before the prompt about
running it but the latter should take place in the core rather
than in the port code.) In the mean time, I noticed that VMS was
ignoring the SHELLERS value from SYSCF.
Untested implementation of a SHELLERS check on VMS. Even if it
works, it should not be using $USER as the user name to verify.
Tweaks the Unix implementation of check_user_string() but doesn't
switch the testing loop to the simpler version used by VMS which
is derived from the generic users test used by Qt.
If we ever want huge maps with COLNO or ROWNO larger than signed char,
this will at least allow the game to compile and start when typedef'ing
xchar to int. Trying to use huge maps exposes more bugs.
Use a linked list to store stair and ladder information, instead
of having fixed up/down stairs/ladders and a single "special" (branch)
stair.
Breaks saves and bones.
Adds information to migrating objects and monsters for the dungeon
and level where they are migrating from.
Monsters with rust attacks (rust monster) and corrosion attacks
(black pudding, gray ooze) can eat or otherwise destroy iron bars
but xorns could only move through the iron bars spot without being
able to eat the metal there. Change xorn to eat bars instead of
phazing through them. Lets rock moles eat bars too.
Hero polymorphed into a rust monster would eat bars if trying to
move to their location but couldn't do so if already there (maybe
was in xorn form and now in rust monster form). Xorns could pass
through them but not eat them. Allow hero metallivores to eat
bars at the current location via 'e', similar to eating food off
the floor. Hero as rock mole behaves like rust monster.
When a zombie (or lich) kills a monster in melee without a weapon,
the monster can rise few turns later as a zombie.
The only creatures that can be zombified are ones that actually have
a zombie counterpart monster. A zombie cannot turn a jackal into
a zombie, for instance. But it could turn a shopkeeper into a human
zombie, or a dwarf king into a dwarf zombie.
Zombies will fight with monsters that can be turned into zombies.
Originally this was a SliceHack feature, but this is based on xNetHack
version of it, with some modifications.
... on the floor, in monster inventory, and in hero's inventory.
Items in your inventory being ignited produce a message even if you're
blind - you can see the lit-state by viewing inventory anyway, so just
give player the message.
(via xNetHack)
Disclaimer: This is a minimal recipe, just to get someone else
started if they have a desire to get a full cross-compile of
NetHack-3.7 going for the Amiga. Some NetHack code bitrot was
corrected, and it does seem able to compile the game itself
to a point. See caveats below.
- If you want to obtain the cross-compiler and tools/libs for Amiga
https://github.com/bebbo/amiga-gcc
To our knowledge, a pre-built copy isn't available, so you have to
obtain the source via git and build it on your system.
The build prerequisite packages for Ubuntu are easily obtained:
sudo apt install make wget git gcc g++ lhasa libgmp-dev \
libmpfr-dev libmpc-dev flex bison gettext texinfo ncurses-dev \
autoconf rsync
The build prerequisite packages for macOS are apparently easily
obtained via homebrew, but that was not tested:
brew install bash wget make lhasa gmp mpfr libmpc flex gettext \
texinfo gcc make autoconf
After installing the prerequite packages and the cross-compiler
it was a straightforward build:
git clone https://github.com/bebbo/amiga-gcc.git
cd amiga-gcc
make update
[Note that you may have to take ownership of the files in the
bebbo repo via chown before succesfully carrying out the next
steps]
make clean
make clean-prefix
date; make all -j3 >&b.log; date
The compiler pieces are installed in /opt/amiga by default which
was satisfactory for our initial attempt, but if you want you can
alter the prefix before you build if you want. That is all
spelled out on the page at: https://github.com/bebbo/amiga-gcc
The Amiga cross-compile can then be carried out by specifying
CROSS_TO_AMIGA=1 on the make command line.
For example:
make CROSS_TO_AMIGA=1 all
make CROSS_TO_AMIGA=1 package
You can explicitly include tty and curses support if desired, otherwise
you'll end up with a tty-only cross-compile build. The SDL1 pdcurses
support has not been tested.
make WANT_WIN_TTY=1 WANT_WIN_CURSES=1 CROSS_TO_AMIGA=1 all
Also note that building the amiga targets using the make command
above, does not preclude you from building local linux or macOS
targets as well. Just drop the CROSS_TO_AMIGA=1 from the make
command line.
The cross-compiler hints additions are enclosed inside ifdef sections
and won't interfere with the non-cross-compile build in that case.
CAVEATS: The original NetHack Amiga build steps included the source for
some utilities that were built and executed on the amiga: txt2iff and
xpm2iff as part of the NetHack build procedure on amiga. Those did not
compile out-of-the-box on the linux host. They will either have to be:
- ported to build and run on the linux or macOS cross-compile host
or
- their functionality will have to be rolled into amiga NetHack
itself and executed on the target Amiga the first time the game
is run, perhaps.
Good luck amiga aficionados, perhaps you'll be able to take this
initial effort forward and get NetHack-3.7 available on the amiga or
amiga-emulator. Let us know if you do, and we can roll changes in
if you provide them.
The existing system was a confusing mess of competing names (filled,
needfill, prefilled, etc) that had varying semantics, with prefilled
being the worst offender as it meant at least three different things in
various contexts. This commit unifies everything in the code under
"needfill", and everything in Lua under "filled", which defaults to 0
everywhere.
This also removes the second argument to fill_special_room; that
function now just checks the needfill of the room it's passed. As
before, a filled == 2 value is used for a special room to indicate that
the room should set the appropriate level flag, but shouldn't actually
be stocked with anything (for instance, King Arthur's throne room); the
difference is that this now comes directly from the lua script instead
of being manipulated within sp_lev.c.
The prefilled argument had one use case that is occasionally used in the
level files: if the level designer had specified an ordinary region with
prefilled = 1, it would become a room to control monster arrivals on a
level -- monsters that arrive within the bounds of a room are supposed
to stay there.
However, not all of the places where the comments indicated this was
being used were using it correctly; I tested this by letting a few
monsters fall through the knox portal (they're supposed to be
constrained to the entry room) and waiting a hundred turns, then going
through the portal; they were not constrained to the room and had
"wandered" through its walls.
Instead of trying to maintain this special case, I have added an
optional "arrival_room" boolean argument to des.region, which forces it
to create a room for the purposes of constraining monster arrival.
I have gone through and replaced occurrences of prefilled in lua files
with the appropriate filled option (or arrival, as needed). In some
cases, that resulted in questionable regions such as a filled ordinary
area in a non-themeroom (I just dropped the filled=1), or an area which
didn't do anything, not even lighting (which I deleted).
I noticed that any subrooms created within a themed room were bare -
they never had any monsters, objects, traps, or anything really,
regardless of whether filled = 1 was set on them. As a result, they're
pretty boring.
It turns out that the code in makelevel() responsible for stocking
ordinary rooms with stuff only looped through g.rooms, and completely
ignored subrooms. (Subrooms would not get stocked with items by virtue
of being part of the larger room; I tested this by dialing the item
generation in rooms way up, and none of those items ever got placed in a
subroom.)
To fix this, I've extracted the code that populates an ordinary room
into its own function, fill_ordinary_room, and made it recurse into its
own subrooms. (I also renamed fill_rooms and fill_room to include the
word "special" in their names, because they only deal with special
rooms.) Note that since special rooms follow a separate codepath, an
ordinary subroom of a special room won't get stocked; perhaps these
functions should be unified in the future.
The fill_ordinary_room code is pretty much a verbatim cut and paste from
makelevel, so there is not currently any consideration for the size of
the subroom or the fact that it is a subroom with respect to how many
monsters, traps, objects, etc get placed.
I'm not sure whether other things such as stair selection will ever
select themed room subrooms, or whether they too only look at g.rooms.
The short exclamations ("Gasp!", "Why?", &c) led to ambiguity
about which monster was vocalizing them. Use full sentences
which refer to the speaker. It can become quite a bit more
verbose but is less likely to lead to confusion. Perhaps it
should cut those off after a modest number of them have been
issued?
The code for peaceful monsters witnessing the hero attack another
peaceful monster and getting angry had a 20% of making them gasp in
surprise or exclaim "why?" in shock. It was only requiring them to
have humanoid shape rather than checking for speech capability, so
peaceful zruty or minotaur, possibly other animals, could exclaim
comprehensibly. Other things which shouldn't talk, like mummies,
would behave similarly.
This categorizes how a bunch of MS_foo types should react. It has
only been lightly tested.
Since teleporation gives a "you matrialize" message even when
arriving close by, the old behavior of not learning a scroll of
teleportation when you land quite close to your original spot
no longer made sense. Always [almost] discover teleport scroll
when reading it.
Also adds one-shot teleport control when reading a blessed scroll
of teleportation. I changed that to be prevented when hero is
stunned, same as with full-fledged teleport control.
I reworded or reformatted several of the comments. And removed
the EDITLEVEL increment in patchlevel.h; save and bones file
contents are not affected.
I've also added an unrelated comment about reading mechanics to
doread().
Closes#386
Report described this as a panic triggered by the sanity_check
option, but that's because it was running under the fuzzer, which
escalates any impossible() to panic(), rather than because nethack
panicked.
I couldn't find anything wrong--which doesn't mean that there
isn't something wrong--with place_worm_tail_randomly() and
random_dir(). They use xchar for map coordinates which should be
fine as long as no negative values are generated and I couldn't
discover any such. The suggested fix of changing xchar to int
might indicate a compiler bug (although the odds of that are low).
The bogus coordinate of -15000 in the report suggests that
typedef short int schar;
(which changes xchar too) is being used in the configuration but
I don't recall having any problems attributable to that.
This switches from xchar to int as a side-effect of replacing the
offending code entirely. The new code might produce an 'ny' of -1
before goodpos() rejects it, so xchar would be inappropriate now.
The old code is commented out via #if 0 _after_ changing it from
xchar to int.
This also adds an extra sanity_check for worm tails, unrelated to
the current bug. I'm not aware of any instance where it fails.
EXTRA_SANITY_CHECKS needs to be defined for it to do anything.
The Qt menu entries which were executing nethack's help command
(the '?' menu) were doing so because their command keystroke was
a meta-character and such characters are being converted to '?'
to indicate an error in conversion to Latin1 character set. The
old Qt3 code didn't perform any such conversion.
This fix feels fragile because there are two different places
deciding how to disambiguate partial extended commands (the code
for Qt's '#' handling and a new routine in the core). Qt menus
now send '#' and enough letters to satisfy '#' handling for any
command which uses M-c or has no regular keystroke nor M-c one.
(If it were to send the full extended command name, the letters
after the unambiguous prefix would be left in the input queue to
be processed as subsequent commands.)
There is a fundamental problem that this doesn't address: if
the player uses BIND directives in the run-time config file, the
Qt menu bindings will break unless the BINDs are all done before
selecting windowtype. Qt's menu bindings translate a click on
a menu entry into the keystroke used to invoke the corresponding
command, so using BIND to change that after the menus are set up
will result in the wrong commands being executed.
Tin handling code used tin->cknown to indicate that the variety
(soup, deep fried, pureed, &c) was known, but neither object
identification nor end of game disclosure was setting cknown for
that type of object.
^I behaves as if cknown is set, so the problem was hidden during
times when anyone was likely to be paying attention.
Adopt the suggestion that candy bar stacks which get split should
keep the same wrapper text for both halves of the stack. The patch
stuck with using obj->o_id to manage the wrapper which prior to the
patch wasn't a factor in merging and splitting. Switch to obj->spe
instead, comparable to tin varities, so mergability is already
taken care of.
End of game disclosure tacks on T-shirt text to formatted items.
Do the same for candy bar wrappers.
A check into github issue 364 confirmed that
ba6edbe5dc
had incorrectly updated the bwrite sizeof entry for sysflags.
The SYSFLAGS and MFLOPPY code is all in the outdated part of the tree, so just
remove it rather than re-correct it.
Closes#364Closes#207
A thieving monster could be killed while the hero was busy taking
off armor which needs multiple turns (normally a suit) and if that
happened on the same turn as the take-off finished, the warning
"stealarm(): dead monster stealing" was issued. Cited case was
having the thief be killed by a stinking cloud but it could happen
if the death was caused by a pet or by some other monster trying
to attack the hero. If the thief died sooner, the situation was
silently ignored. So this could have been fixed by just getting
rid of the impossible() feedback.
'stealmid' and 'stealoid' should have been static in steal.c rather
than global and as such should have been moved into 'struct g'.
This moves them there and then takes advantage of having access to
'stealmid' outside of steal.c. That's just a minor optimization
since m_detach() could call new thiefdead() unconditionally and the
latter could check whether the dead monster matches 'stealmid'.
Fixes#354
If a monster uses the 'summon insects' spell (which will resort to
snakes if all 'a' class critters are genocided or extinct) while the
hero is hallucinating, report the summoning of something unusual
rather than of insects or snakes. I bypassed "random creature"
direct to "hallucinatory creature" for the something unusual.
Fixes#351
If a monster uses the 'summon insects' spell (which will resort to
snakes if all 'a' class critters are genocided or extinct) while the
hero is hallucinating, report the summoning of something unusual
rather than of insects or snakes. I bypassed "random creature"
direct to "hallucinatory creature" for the something unusual.
Fixes#351
Rot and revive timers are turned off when a corpse gets put inside
an ice box. They get turned back on when taken out of the ice box
by the hero but were being left off if taken out by a monster.
That resulted in corpses of arbitrary type behaving like lizard
corpses and never rotting away.
This fixes that. It also changes troll corpse behavior. Once put
in an ice box, a troll corpse will not get a new revive timer when
taken out, just an ordinary rot timer.
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.
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'.
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).
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.
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.
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.