A wand of stasis prevents teleportation (even in some cases where
it would normally not be prevented, e.g. the hero teleporting a
monster, or covetous monsters teleporting). This is intended to
provide an alternative tactic against covetous monsters (and their
AI has been adjusted to handle being under a stasis effect), but
might also be useful in other situations. It does not prevent
teleportation of objects, only the hero / monsters, and does not
at present prevent level teleportation (although I'm not sure about
this and it might well change in the future).
This breaks save compatibility, but is being pushed together with
other save-breaking changes to avoid the need for multiple bumps to
EDITLEVEL.
A comment in rm.h claimed that secret doors can't be trapped so I
used door flag D_TRAPPED to handle secret doors that should be shown
as trees instead of walls. But the comment was inaccurate and secret
doors can be trapped.
Such trapped secret doors in ordinary rooms ended up being shown as
trees too. Switch from using D_ARBOREAL in levl[][].doormask to new
levl[][].arboreal_sdoor which overloads levl[][].candig.
Also, wizard mode wishing for secret doors needed updating to allow
creating trapped ones (at wall or door locations).
This ought to update EDITLEVEL but I think existing save files can
live with secret door display issues. Untrapped secret doors in
garden-fill rooms will end up becoming trapped.
Replaces the fix for github issue #1309
Issue reported by elunna: when a room gets converted into a theme
room with fill type Garden, its walls are changed to trees but any
secret doors in those walls are still displayed as regular walls.
This adds a new D_ARBOREAL flag for secret doors, used to force them
to be displayed as a tree instead of a wall.
Fixes#1309
Related to #1309https://github.com/NetHack/NetHack/issues/1309
K2 commented: "This might help - k21971/EvilHack@afed641"
A comment in there states:
"Fix: sections of wall being visible when they shouldn't yet.
This has been a long-standing bug for as long as I can remember, and qt
appears to have figured it out. What was happening: the player would all
of the sudden see a section of wall in an area that they hadn't explored
yet. It was discovered that this was only occurring if that section of
wall had any type of tree up against it."
The fix there attempts to leave trees out of the check_pos non-zero return,
so give that a shot.
I didn't attempt to reproduce the situation myself,
and therefore cannot confirm that this does resolve it.
Feedback on effectiveness or side-effects are welcomed. If someone is
able to confirm that this resolves the issue without creating new
issues, we can close it, otherwise this can be reverted.
The g? structs had a mix of variables that were written to
the savefile, and those that were not.
For better clarity and to distinguish those that end up in
the savefile, relocate some g? variables that get written
directly to the savefile into different structs.
This updates EDITLEVEL, although technically it probably
didn't need to, since savefile contents are not changing.
Details:
gb.bases -> svb.bases
gb.bbubbles -> svb.bbubbles
gb.branches -> svb.branches
gc.context -> svc.context
gd.disco -> svd.disco
gd.dndest -> svd.dndest
gd.doors -> svd.doors
gd.doors_alloc -> svd.doors_alloc
gd.dungeon_topology -> svd.dungeon_topology
gd.dungeons -> svd.dungeons
ge.exclusion_zones -> sve.exclusion_zones
gh.hackpid -> svh.hackpid
gi.inv_pos -> svi.inv_pos
gk.killer -> svk.killer
gl.lastseentyp -> svl.lastseentyp
gl.level -> svl.level
gl.level_info -> svl.level_info
gm.mapseenchn -> svm.mapseenchn
gm.moves -> svm.moves
gm.mvitals -> svm.mvitals
gn.n_dgns -> svn.n_dgns
gn.n_regions -> svn.n_regions
gn.nroom -> svn.nroom
go.oracle_cnt -> svo.oracle_cnt
gp.pl_character -> svp.pl_character
gp.pl_fruit -> svp.pl_fruit
gp.plname -> svp.plname
gp.program_state -> svp.program_state
gq.quest_status -> svq.quest_status
gr.rooms -> svr.rooms
gs.sp_levchn -> svs.sp_levchn
gs.spl_book -> svs.spl_book
gt.timer_id -> svt.timer_id
gt.tune -> svt.tune
gu.updest -> svu.updest
gx.xmax -> svx.xmax
gx.xmin -> svx.xmin
gy.ymax -> svy.ymax
gy.ymin -> svy.ymin
Related note:
There are some pointer variables that are heads of chains that were not
moved from 'g?' to 'sv?', because they are not actually written to the
savefile directly, but the objects/monst/trap/lightsource/timer in the
chains they point to are. That can be changed, if desired.
Examples: gi.invent, gm.migrating_objs, gb.billobjs, gm.migrating_mons,
gf.ftrap, gl.light_base, gt.timer_base
Issue reported by vultur-cadens: arriving on the Mine Town level
via falling or level teleport won't register the "entered Minetown"
achievement if hero doesn't arrive inside a room.
Reorder some code in check_special_room() so that town entry will be
tested before the early return if no room entry has occurred. This
adds 'level.flags.has_town' to make the town test be cheaper when
the hero hasn't attained the achievement yet and is wandering around
the mines.
Fixes#1070
Pull request from entrez: the legend for wizard mode #terrain wasn't
updated to include terrain type "lava wall", so the entries for it
and everything that followed were inaccurate.
I've expanded the comment about level type codes in rm.h.
Closes#1052
This replaces most of commit 0ca2af4d8b
from a couple of days ago with something more robust. That change
actually introduced redundant code that caused fountain and/or sink
count to be off instead of preventing it.
Revise set_levltyp() to update level.flags.nfountains and
level.flags.nsinks if setting the type to or from fountain or sink.
A bunch of places that were setting levl[x][y].typ directly needed
to be revised to use set_levltyp() instead. set_levltyp() itself
hadn't been updated to handle LAVAWALL (to force such to be lit).
Get rid of some unnecessary code when ignoring unimplemented buried
monsters. A smart compiler probably optimizes away the useless bits
even when not explicitly optimizing but a dumb one isn't likely to.
m_at(x,y) was
| (levl.monsters[x][y] != 0
| && (levl.monsters[x][y] ? levl.monsters[x][y] : 0))
when
| levl.monsters[x][y]
accomplishes the same thing.
Engraving in an empty doorway and then using locking magic to create
a door there resulted in an impossible warning: "engraving sanity:
illegal surface (23)" if the 'sanity_check' option was On (wizard
mode only). Engraving in an open doorway and then simply closing
the existing door produced the same effect.
Accept engravings at closed doors. Presumably hero will be using
Passes_walls to attempt that so treat closed doors same as open ones.
Update the engraving sanity check to deal with that.
Bonus fix: engraving sanity checking stopped after the first problem
instead of checking every engraving. Have it continue instead.
Not fixed: vault wall repair and temporary corridor removal does
not delete engravings and can trigger the illegal surface warning if
player engraves before the repairs. I didn't test shop wall repair
but it doesn't have any engr references so probably has the same bug.
Add "walls of lava", basically lava which blocks vision and
require a bit more than just levitation or flight to move through.
No levels use this yet, as testing isn't thorough enough.
Pull request from entrez: if bones left dead hero's corpse on top
of a new grave, don't find a corpse or summon a zombie when digging
the grave up. It also removed the chance that a ghoul might be
summoned when engraving on a headstone, switching to zombie or mummy
instead.
Rather than adopting the pull request, this retains summoning a
ghoul via engraving and adds the possibly of doing so when kicking
a headstone. Having a ghoul prowl around the grave is independent
of whether there is a corpse or zombie inside the grave. To achieve
this, another flag in 'struct rm' is needed; the single bit for
'disturbed' isn't sufficient. The bigger 'flags' field wasn't in
use for graves so commandeer that for new 'emptygrave'. 'disturbed'
still uses the 'horizontal' bit in order to have engraving and/or
kicking summon at most one ghoul.
Closes#944
Allow setting a per-level "temperature": hot, cold, or temperate
via special level flags. Currently it only affects some messages
in Gehennom, but it could be expanded to ice melting, water freezing,
or monster generation, for example.
Invalidates saves and bones.
The consolidation of global variables from scattered source
files into decl.c and declared in decl.h was begun in 3.7.0.
Their placement in common files was done for centralized
initialization and potential re-initialization during a
"play again" scenario.
It wasn't really necessary for all of them to be housed in a
single huge structure to meet the "play again" requirement,
and the single huge structure has been a little unwieldy when
it comes to maintenance.
Following this commit, instead of one single extremely large structure
named 'g' to house all of the relocated global variables, they
are distributed into several ga through gz.
To make things easy for the developer, each variable is placed
into the struct corresponding to the starting letter of the variable.
That way, no lookup is required in order to know which struct houses
a particular variable, it is a simple match to the starting letter
for all the centralized global variables.
A global variable named 'amulets', would be found in ga.
ga.amulets
^ ^
A global varable named 'move', would be found in gm.
gm.moves
^ ^
A global variable named 'val_for_n_or_more' would be found in gv.
gv.val_for_n_or_more
^ ^
A global variable named 'youmonst' would be found in gy.
gy.youmonst
^ ^
viz_array[][] is indexed by coordinates but the data it contains has
nothing to do with them so it shouldn't have been changed to coordxy.
'char' was sufficient; 'uchar' would have been better; this invents
'seenV' instead. This led to a cascade of required changes. The
result is warning free and seems to be working but my fingers are
crosssed....
One of the drivers of this change was that screen coordinates require a
type that can hold values greater than 127. Parameters to the window
port routines require a large type in order to be able to have values
a fair bit larger than COLNO and ROWNO passed to them, particularly for
their use to the right of the map window.
This splits the uses of xchar into 3 different situations, and adjusts
their type and size:
xchar
|
-----------------------
| | |
coordxy xint16 xint8
coordxy: Actual x or y coordinates for various things (moved to 16-bits).
xint16: Same data size as coordxy, but for non-coordinate use (16-bits).
xint8: There are only a few use cases initially, where it was very
plain to see that the variable could remain as 8-bits, rather
than be bumped to 16-bits. There are probably more such cases
that could be changed after additional review.
Note: This first changed all xchar variables to coordxy. Some were
reviewed and got changed to xint16 or xint8 when it became apparent that
their usage was not for coordinates.
This increments EDITLEVEL in patchlevel.h
"add glyphs+tiles for door+chest traps",
commit d1217b9f25,
missed a couple of S_vibrating_square references, resulting in
screwed up rendering of zaps and explosions.
triggering an impossible warning about "wall_angle: unknown" due
to the known conflict between door state and wall info which both
overlay the flags field for map locations.
Reported and diagnosed by vultur-cadens: if a shop's wall was dug
open, followed by use of locking magic to plug the gap with a door,
and then unlocking that door, the D_CLOSED door flag was left as
invalid wall_info when shop damage was repaired. Map re-display
complained. Leaving the door locked or opening it after unlocking
did not result in any complaint because the values for those door
states do not conflict with wall angle values.
The problem was reproducible and is now fixed by adding an extra
field to the shop damage structure. A similar change has been
made to the vault guard's 'fake corridor' structure but I have no
test case for that so don't know whether it makes any difference.
At least it doesn't seem to have broken anything.
Existing save and bones files are invalidated by the fixes.
Fixes#606
There were multiple symbol-related lists that had to be kept
in sync in various places.
Consolidate some of that into a single new file
defsym.h
with a set of morphing macros that can be custom-called from
the various places that use the sym info without maintaining
multiple occurrences. Most maintenance can be done there.
Rename monsym.h to sym.h since it looks after some
symbols not related to monsters now too.
The defsym.h header file is included in multiple places to
produce different code depending on its use and the controlling
macro definitions in place prior to including it.
Its purpose is to have a definitive source for
pchar, objclass and mon symbol maintenance.
The controlling macros used to morph the resulting code are
used in these places:
- in include/sym.h for enums of some S_ symbol values
(define PCHAR_ENUM, MONSYMS_ENUM prior to #include defsym.h)
- in include/objclass.h for enums of some S_ symbol values
(define OBJCLASS_ENUM prior to #include defsym.h)
- in src/symbols.c for parsing S_ entries in config files
(define PCHAR_PARSE, MONSYMS_PARSE, OBJCLASS_PARSE prior
to #include defsym.h)
- in src/drawing.c for initializing some data structures/arrays
(define PCHAR_DRAWING, MONSYMS_DRAWING, OBJCLASS_DRAWING prior
to #include defsym.h)
- in win/share/tilemap.c for processing a tile file
(define PCHAR_TILES prior to #include defsym.h).
Different color for stairs that go to another dungeon branch.
Adds four new glyphs, S_br{up,dn}{stair,ladder}, which use the
same character as normal stairs/ladders, but yellow color.
In tiles, the up/down arrow is yellow-green instead of while-blue.
This feature has been around a lot and is in several different
variants, but this is implemented from scratch so tiles work too.
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.
Part of pull request #308: when using des.terrain to set terrain,
default for lit state becomes 'unchanged' rather than 'unlit'.
des.replace_terrain already operates that way. Replace lit state
magic numbers -1 and -2 with SET_LIT_RANDOM and SET_LIT_NOCHANGE.
Also change SET_TYPLIT() to not operate on map column 0 and move
it from rm.h to sp_lev.h. It never belonged there, is only used
in sp_lev.c, and now because of the SET_LIT_ macros it couldn't be
used anywhere else unless sp_lev.h gets included too.
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.
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()
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.
Try a lot harder to keep terrain/level flags in a sane state. They're
overloaded so it's not simple.
Creating a fountain or sink incremented the corresponding counter (for
controlling ambient sounds) but removing one by wishing for something
else in its place didn't decrement.
Allow wish for "disturbed grave" to create a grave with the 'disturbed'
flag set, similar to existing "magic fountain" and 'blessedftn' flag.
(I didn't add "looted throne", "looted tree", and several other things
that use the 'looted' overload of 'rm.flags'.)
Automate block_point (tree, cloud, secret corridor, or secret door in
open doorway) and add unblock_point (use Pass_wall to move into wall
or tree or stone, or just walk onto a cloud, then make iron bars or
almost any other wishable terrain to replace the blocking feature).
Allow wishing for secret doors and secret corridors. It's a bit
more strict about where the wish is performed than wishing for
furniture. Implemented in order to test drum of earthquake effects.
I spent a lot of time figuring out SDOOR details that somebody
already knew at some point but evidently didn't document--you can't
specify D_CLOSED for them or the display code will issue impossible
warnings about wall mode angles.