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).
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.
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.
combine boolean and compound options into a single allopt[] array for
processing in options.c.
move the definitions of the options into new include/optlist.h file which
uses a set of macros to define them appropriately.
during compile of options.c each option described in include/optlist.h:
1. automatically results in a function prototype for an optfn called
optfn_xxxx (xxxx is the option name).
2. automatically results in an opt_xxxx enum value for referencing
its index throughout options.c (xxxx is the option name).
3. is used to initialize an element of the allopt[] array at index
opt_xxxx (xxxx is the option name) based on the settings in the
NHOPTB, NHOPTC, NHOPTP macros. Those macros only live during the
compilation of include/optlist.h.
each optfn_xxxx() function can be called with a req id of: do_init, do_set,
get_val or do_handler.
req do_init is called from options_init, and if initialization or memory
allocation or other initialization for that particular option is needed,
it can be done in response to the init req.
req do_set is called from parseoptions() for each option it encounters
and the optfn_xxxx() function is expected to react and set the option
based on the string values that parseoptions() passes to it.
req get_val expects each optfn_xxxx() function to write the current
option value into the buffer it is passed.
req do_handler is called during doset() operations in response to player
selections most likely from the 'O' option-setting menu, but only if the
option is identified as having do_handler support in the allopts[]
'has_handler' boolean flag. Not every optfn_xxxx() does.
function special_handling() is eliminated. It's code has been redistributed
to individual handler functions for the option or purpose that they serve.
moved reglyph_darkroom() function from options.c to display.c
This adds a pair of new glyphs: GLYPH_UNEXPLORED and GLYPH_NOTHING
GLYPH_UNEXPLORED is meant to be the glyph for areas of the map that
haven't been explored yet.
GLYPH_NOTHING is a glyph that represents that which cannot be seen,
for instance the dark part of a room when the dark_room option is
not set. Since the symbol for stone can now be overridden to
a players choice, it no longer made sense using S_stone for the
dark areas of the room with dark_room off. This allows the same
intended result even if S_stone symbol is mapped to something visible.
GLYPH_UNEXPLORED is what areas of the map get initialized to now
instead of STONE.
This adds a pair of new symbols: S_unexplored and S_nothing.
S_nothing is meant to be left as an unseen character (space) in
order to achieve the intended effect on the display.
S_unexplored is the symbol that is mapped to GLYPH_UNEXPLORED, and
is a distinct symbol from S_stone, even if they are set to the same
character. They don't have to be set to the same character.
Hopefully there are minimal bugs, but it is a deviation from a
fairly long-standing approach so there could be some unintended
glitches that will need repair.
Like lava when that looks the same as water with color Off, render ice
in inverse video if it looks the same as the floor of a room. (I tried
bold first but the result didn't look very good.)
Done for tty and curses; others may want to follow suit.
teleds() is used for more than just teleportations, the teleportation message
was also given when mounting a steed.
Trying out a new bit flags method parameter design pattern.
groundwork only - window port interface change
This changes the last parameter for add_menu() from a boolean
to an unsigned int, to allow additional itemflags in future
beyond just the "preselected" that the original boolean offered.
There shouldn't be any functionality changes with this groundwork-only
change, and if there are it is unintentional and should be reported.
If a punished player picks up the iron ball, gets engulfed and
saves, then the saved game will have missed saving the dangling
chain since it was not on the floor or in the inventory. Upon
restoring the saved game, the game will be in a bad state since
the ball will be worn but the chain will be missing.
Make some progress on a couple of next minor release checklist
items, hopefully without introducing too many new bugs. This
is just the initial commit, and work continues.
Checklist items:
Savefiles compatible between Windows versions, whether 64-bit
or 32-bit in little-endian field format.
Selection of file formats:
historical (structlevel saves),
lendian (little-endian, fieldlevel saves),
and just for proof-of-concept, ascii fieldlevel saves
(the ascii is huge! 10x bigger than little-endian).
For the fieldlevel save, all complex data structures recursively
get broken down until until it is one of the simple types that
can't be broken down any further, and that gets when it gets
written to the output file.
New files needed for this build:
hand-coded:
include/sfprocs.h
src/sfbase.c - really a dispatcher to one of the
output/input format routines.
src/sflendian.c - little-endian output writer/reader.
src/sfascii.c - ascii text output writer/reader.
auto-coded (generated):
include/sfproto.h
src/sfdata.c
This is just one approach. I'm sure there are countless others
and they have different pros and cons.
For producing the auto-coded files a utility called
universal-ctags, that is actively maintained and evolving,
was used to do all the heavy-lifting of parsing the
NetHack C sources to tabulate the data fields, and store
them in an intermediate file called util/nethack.tags
(not required for building NetHack if you already have a
generated include/sfproto.h and src/sfdata.c)
util/readtags (also not required for building NetHack
itself) will decipher the nethack.tags file and produce
the functions that can deal with the NetHack struct data
fields.
You can obtain the source for universal-ctags by cloning it
from here:
https://github.com/universal-ctags/ctags.git
The combination universal-ctags + util/readtags has been
tried and tested under both Windows and Linux, so it is
not tied to a particular platform.
Note: util/readtags will work only with universal-ctags
output, so other ctags are unlikely to work as-is.
Universal-ctags can be build from source very easily
under Linux, or under Windows using visual studio.
This doesn't solve the <0,0> problem but it does prevent mnexto()
from using uninitialized coordinates if enexto() fails. It also adds
several debugging messages.
enexto() was ignoring map row #0 (unlike column #0, row #0 contains
valid map locations). Fixing that doesn't matter for Plane of Water
though since that row is stone there--that's probably a bug. It was
also repeatedly re-testing the top+1 and bottom rows and left and
right columns after they had already failed to be acceptable. It
still does some of that, but less.
Extend 'putstr(WIN_MESSAGE, attribute, string)'s attribute so that
'custompline(SUPPRESS_HISTORY, ...)' can work with ^P's message
history like DUMPLOG history, in order to keep autodescribe feedback
and intermediate prompts for multi-digit count ('Count: 12', 'Count:
123') prompts out of recall history. The old autodescribe behavior
could easily push all real messages out of the recall buffer when
moving the cursor around for getpos, and the count behavior looked
silly for a four or five digit gold count if you set the msg_window
option to 'full' or 'combination' and viewed them all at once.
Other interfaces may want to follow suit, but this doesn't force them
to make any changes. I added a hook for "urgent messages" that might
be rendered in bold or red or some such and/or override the use of
ESC at --More-- from suppressing further messages, but there aren't
any custompline(URGENT_MESSAGE, ...) calls (potentially "You die...",
for instance) to exercise it. Other people have implemented similar
feature it different ways and I'm not sure whether this one is really
the way to go since the core needs to categorize each message that it
deems to be urgent. MSG_TYPE:stop may be sufficent, although MSG_TYPE
matching can entail a lot of regexp execution overhead at run-time.
add MM_NOGRP makemon() flag as a means of suppressing groups of monsters in
a couple places that warrant it when a specific monster type isn't
specified on the call to makemon()
Force trap to activate during failed untrap attempt if done while
already at the trap's location, to match the recent change in
behavior when failed attempt occurs while adjacent to the trap.
Most noticeable while flying over bear traps, but affects all
failed untrap attempts.
Changes to be committed:
modified: include/decl.h
modified: include/dungeon.h
modified: include/extern.h
modified: include/hack.h
modified: src/decl.c
modified: src/do_name.c
modified: src/dog.c
modified: src/dokick.c
modified: src/makemon.c
modified: src/mkmaze.c
modified: src/mkobj.c
modified: src/pager.c
This commit is an attempt to address the complaints about
the orc town variation taking away lots of stuff that is
normally available in mine town. The statement in the level
description says "A tragic accident has occurred in Frontier
Town...It has been overrun by orcs."
The changes in this commit attempt to uphold that premise,
while making things a bit more interesting and perhaps
more palatable for the player.
This update does the following in keeping with the mythos:
- While many of the orcs still remain to wander about the
level, many of the orcs took off deeper into the mines with
some of the stuff that they plundered. You may now be
able to hunt some of it down.
- Adds some appearance of this particular horde of marauding
orcs working as part of a larger collective.
- This evolves the Orc Town mine town variation into a
a feature over multiple levels of The Gnomish Mines,
rather than just the single-level "feature" that it was
previously.
- You may have to work longer and a bit harder for some
things than other mine town variations, but at least with
these changes, there is hope that some of it may be found
elsewhere.
Game mechanics notes (maybe spoily?)
- Add mechanism to place objects into limbo (okay, really
place them onto the migrating_objs list for transferring
between levels etc.) and destine them
to become part of the monster inventory of a particular
species. In this particular usage case, it's using the
M2_ORC flag setting to identify the recipients.
- At present, there is no mechanism in the level compiler
for placing objects onto the migrating objects, nor
with more sophisticated landing logic, so a somewhat
kludgy hard-coded fixup and supporting routines were used.
Some day the need for that might change if additional
capabilities move to the level compiler.
This is a NetHack-3.6.2-beta01 update. Please give it a workout.
Fixes#127
Build fix, avoid use of 'class'
include\hack.h(199): error C2236: unexpected token 'class'. Did you forget a ';'?
include\hack.h(199): error C2332: 'class': missing tag name
include\hack.h(199): error C2027: use of undefined type 'sortloot_item::<unnamed-tag>'
When objects are in the same class, sortloot orders them by their
formatted name. It was reformatting each object every time it got
compared to another object. Change that to remember the formatted
name so that any given object is formatted at most once (during the
current sort; future sorts will need to format it again).
Armor and weapon classes are subdivided into smaller subclasses
and the formatting plus alpha compare is only done for items in
the same subclass, so helms come out before cloaks and don't get
their names compared, for instance. [That was from my 'revamp'
rather than the original implementation.] This adds a couple more
subclass sets: food (named fruit, 'other' food, tins, eggs, corpses,
globs) and tools (containers, pseudo-containers [bag of tricks and
horn of plenty once those have become discovered; prior to discovery,
bag of tricks is classified as a container and horn of plenty as an
instrument], instruments, 'other' tools).
The main difference, aside from the formatting efficiency improvement,
is to change the previous sort order
| pink potion
| potion of enlightenment
| purple-red potion
to be
| pink potion
| purple-red potion
| potion of enlightenment
by grouping undiscovered items before discovered items when class and
subclass match. So discovery state is essentially a sub-subclass and
formatting plus string comparison is only done for members of the
same sub-subclass. There are actually four state values: unseen
(which applies to particular objects rather than to their type),
unknown (not discovered and not named), named (not discovered but has
player-assigned type name), and discovered (either fully discovered
or considered not interesting to discover [no alternate description,
not nameable]).
My testing was primarily done with pickup ('m,' with menustyle:T)
and sortloot:Loot (the default) plus !sortpack (not the default and
not a setting I ordinarily use, but less verbose without the class
separators). It won't astonish me if oddities crop up with other
usage combinations.
Yesterday's sortloot() overhaul didn't include some cockatrice corpse
handling for pickup. If there's an object class filter in place and
pickup has been told to care about cockatrice corpses, have sortloot()
include them in the loot array even if food class isn't accepted by
the filter. In the pre-sortloot days, and in 3.6.[01] which didn't
attempt to deliver a filtered subset of loot, the check for such
corpses was done before pickup checks the filter. They need to be in
the loot array to retain the same behavior.
H7205 - full-pack identify might skip items if perm_invent is on
because updating the inventory window might reorder 'invent'
while the identify code is in the midst of traversing it;
H7120 - pickup that doesn't pick anything up can change the glyph
shown on the map because the pile might be reordered such
that a different item is on top;
H5216 - performing a sortloot operation on a pile and then switching
back to sortloot:none doesn't restore pile's original order.
The 'revamp' that changed the contributed sortloot feature to switch
to simpler usage (object list itself was sorted rather than having a
parallel array that needed to be constructed, sorted, traversed, and
discarded) turns out to have too many problems. This reverts to a
hybrid solution that constructs an array for traversal, leaving the
linked list in its original order, but hides most of the details of
that from sortloot() callers. The 'revamp' benefit of being able to
use normal list traversal is lost, as is the potential to skip
sorting when the list turns out to already be in the desired order.
This could stand to have a lot more testing than it's had so far.
Defined strbuf_t and related routines to support dynamically sized
strings. Modified strip_newline() to strip the last newline in a string
instead of the first.
Simplified splash window code using new strbuf_t.
Prior to exiting game, re-enable getreturn and call wait_synch() in
case there is buffered raw prints that must be displayed to user.