Commit Graph

124 Commits

Author SHA1 Message Date
copperwater
99715e005f Make sure xstart and ystart are always zero when not in_mklev
Running #wizloadlua to run Lua scripts that use coordinates in any way
would work differently if you were on certain levels for the first time
versus leaving and returning to them. This is because various bits of
level creation routines can leave xstart and ystart set to non-zero
values, which are then zeroed at some point when leaving and returning
to the level.

Since xstart and ystart are only relevant to level creation and lua
commands, this fixes the problem by zeroing them after leaving mklev
routines. (Saving them with the level doesn't work because xstart and
ystart are relative to the last used des.map, of which there could be
multiple, e.g. in Asmodeus's level or if two map-based themed rooms
happen to generate. I can envision a more complex solution in which
every des.map used in the level can be associated with an identifier,
whose xstart and ystart are saved for use by later post-level-creation
lua scripts, but currently I just want to make them consistent between
level visits.)
2022-04-08 10:05:43 -07:00
PatR
27b1c38c50 mkstairs() sanity check
Complain during level creation if stairs are placed on top of anything
other than the expected room/corridor/ice terrain.  This won't prevent
the bug of upstairs and downstairs existing on the same spot (github
issue #702, also a newsgroup posting by a hardfought player) but might
at least warn players if/when that happens.
2022-03-23 13:20:26 -07:00
Pasi Kallinen
074476758c Change map terrain changing from macro to function
The function handles setting lava lit, and removing ice melt timers.
2022-03-16 20:59:58 +02:00
Pasi Kallinen
d1ca594d1c Remove melting ice timeouts when terrain changes
If special level lua code creates a melting ice timeout, but
later in the code places stairs, or a trap which might change
the ice to room floor, the timer sanity checking doesn't
like that.
2022-03-16 16:51:53 +02:00
Pasi Kallinen
473ae4a6a0 Prevent segfault trying to make non-existent trap seen 2022-03-01 15:31:22 +02:00
Pasi Kallinen
2777f45bd5 Get rid of force_mintrap, allow passing flags to mintrap
It uses the same flags as dotrap, so simulate force_mintrap
by passing FORCETRAP flag.
2022-02-24 17:13:23 +02:00
Pasi Kallinen
c434236f1e Allow creating unhidden traps in special levels
des.trap({ type = "rust", seen = true });
2022-02-19 12:38:28 +02:00
PatR
495cda17b7 some reformatting
Replace some
  (foo &&
   bar)
that had crept back into the code with
  (foo
   && bar)
to match the reformatting which took place before 3.6.0.  There are a
couple of lines ending in '||' still present but they look intentional.
isaac64.c has some trailing '|' bit operators that could/should be
moved to the start of the next line but I didn't touch that file.

While in the affected files, I tried to shorten most overly wide lines
(the right margin is supposed to at column 78 and there are quite a
few lines which are 79 characters long, but I left most of those
rather than introduce new line splits).  Also replace a handful of
tabs with spaces.  I was a little surprised not find any trailing
spaces (in the dozen or so files being updated).  I didn't look for
trailing arithmetic or '?'/':' operators which aught to be moved to
the start of the next line.
2021-12-14 07:43:40 -08:00
Pasi Kallinen
6dc99f69b7 Prevent impossible trying to find a door position
When random dungeon level generation looks for room walls
to place doors at (for joining corridors or creating niches),
it complained about impossible, if the shaped theme room
doesn't have a valid place for a door.

Make the position routine return FALSE and let the
caller deal with it...

Observed this with the small circular themeroom which had
all 4 valid positions already joined with corridors, and
the niche function tried to add a niche to the room.
2021-08-22 18:44:20 +03:00
PatR
8a6c48034f description of stair destination for level 1 up
Having the opposite side of the stairs up from level 1 be unknown is
weird because the hero conceptually just came down those stairs at
the start of the game.  But it's tricky because remote destination
varies depending on whether the Amulet is being carried.  This gives
an accurate description of where the stairs lead (if you step on
them with the 'mention_decor' option On, or use the ':' command when
already on them).

|"There is a staircase up out of the dungeon here."
or
|"There is a branch staircase up to the Elemental Planes here."

It gives away a little information when carrying the Amulet, but not
much and anyone who gets that far deserves a break.
2021-08-05 13:46:20 -07:00
Pasi Kallinen
7f39d53ad3 Lua: improve level testing
Add des.finalize_level() used for testing in conjunction with
des.reset_level().
Add nhc.DLB to return 0 or 1 if DLB was defined at compile-time.
Change the test_lev.lua to give more informative messages instead of
just lua error when required file doesn't exist.
Add bigrm-11 to the level tests.
2021-07-24 10:49:06 +03:00
Pasi Kallinen
f25a6e26ee Use enums and defines for directions 2021-06-27 15:46:56 +03:00
Pasi Kallinen
5ea652e0c6 Explicitly check for not STONE in corridor join
... instead of relying STONE being 0
2021-06-26 16:59:11 +03:00
Pasi Kallinen
5ad45fc696 Make anti-magic fields drain more energy
... and make them actually deal damage based on the energy
it would've drained, if you have Antimagic.
Also prevent them appearing too early in the dungeon.

Allow drain energy attacks (and anti-magic traps) drain more
than your level of energy.

Make eating magical monsters such as wizards and shamans give
the same tiny buzz bonus as eating a newt.
2021-05-20 21:35:23 +03:00
Pasi Kallinen
1e1d580336 Allow webs to be placed without a giant spider on them
Allow creating webs without spiders in the lua level scripts:

des.trap({ type = "web", spider_on_web = 0 });

Based on xNetHack commit by copperwater <aosdict@gmail.com>.

Also changes the Spider nest themed room to generate without
spiders when the level difficulty is 8 or less.
2021-05-10 17:48:51 +03:00
PatR
8bd08ebb71 level teleporters vs Ft.Ludios
From newsgroup discussion where slash'em changes have revealed a
latent nethack bug:  prevent placing level teleporters in single-
level branches.  The Knox level doesn't have any level teleporters
(or random traps) but wizard mode wishing could create them there.
They wouldn't do anything because the only possible destination
would be the same level.  Pushing a boulder onto one used to trigger
an infinite loop (and still does in slash'em, which has other
single-level branches besides Ft.Ludios) trying to relocate it.

Boulder pushing was changed 15 years ago to prevent the infinite
loop and to avoid giving "the boulder disappears" message when a
level teleporter failed, but rolling boulder traversal lacked that
same change--it wasn't vulnerable to looping but could give an
inaccurate message claiming that the boulder disappeared when it
actually didn't.  Fixing this is a bit late; rolling boulder trap
creation was recently changed to not choose a path that rolls over
teleportation or level tele traps any more.
2021-04-12 13:25:52 -07:00
PatR
a203ff9feb fix pull request #471 - error message segfault
for invalid 'O' values when option error messages are issued after
theme rooms have left iflags.in_lua set.  The pull request just
turned the flag off but lua code turns back on and off after that
for other dungeon levels.  nhlua probably shouldn't be sharing the
same error routine as options processing, or at least it should
toggle the flag on and off at need instead of pretending that it
can be global.

Fixes #471
2021-03-16 18:45:56 -07:00
copperwater
18dc88505d Convert room 'joined' and 'needjoining' into booleans
des.region() accepted booleans for the joined field, whereas des.room
accepted xchars. These were only being used as truth values, so this
converts the room ones into booleans for consistency. I don't think
accidentally using an int or a boolean wrongly would actually crash the
level generator, but consistency is good.

This converts an schar field in struct mkroom into a boolean; on most
systems these are probably 1-byte types and save files won't be broken,
but it might be best to treat this as a save breaker anyway.
2021-02-19 17:09:41 +02:00
PatR
79ca1dc422 mklev.c's mkroom qsort
Get rid of some obsolete qsort hackery.  Use of prototypes makes
it unnecessary.  Even before that it was the only one of a dozen
instances of qsort() usage that cared about pre-ANSI implementation.

Also, reformat a couple of comments.
2021-02-11 15:18:12 -08:00
Pasi Kallinen
9576154690 Add in_lua flag
In preparation of making config errors available to lua scripts,
instead outputting them via pline.
2021-02-10 17:06:12 +02:00
nhmall
7900632b50 Qt c++ function name shadow warnings
We have a struct called mkroom and a function called mkroom()
so c++ complains about the mkroom() function hiding the
initializer for the struct.

Similarly, we have a struct called attack and a function
called attack().

There may be a more elegant way of eliminating those two
warnings, but renaming mkroom() to do_mkroom() and
attack() to do_attack() was straightforward enough.
2021-02-03 10:55:07 -05:00
nhmall
41fc278cfb CFDECLSPEC -> QSORTCALLBACK
also remove one inappropriate use of CFDECLSPEC
2021-01-31 13:58:19 -05:00
nhmall
f963c5aca7 switch source tree from k&r to c99 2021-01-26 21:06:16 -05:00
nhmall
939f20e2ea fix warning differently mklev.c 2021-01-26 08:48:38 -05:00
nhmall
62f25fd000 clear five warnings for "set but not used" variables
Note: the line numbers referenced in the warning messages below are not in sync
with the NetHack-3.7 branch and should be disregarded

files.c: In function 'get_saved_games':
files.c:1168:9: warning: unused variable 'n' [-Wunused-variable]
 1168 |     int n, j = 0;
      |         ^

mhitm.c: In function 'mdamagem':
mhitm.c:843:13: warning: variable 'cancelled' set but not used [-Wunused-but-set-variable]
  843 |     boolean cancelled;
      |             ^~~~~~~~~

mhitu.c: In function 'hitmu':
mhitu.c:943:9: warning: variable 'uncancelled' set but not used [-Wunused-but-set-variable]
  943 |     int uncancelled;
      |         ^~~~~~~~~~~

mklev.c: In function 'place_branch':
mklev.c:1214:20: warning: variable 'br_room' set but not used [-Wunused-but-set-variable]
 1214 |     struct mkroom *br_room;
      |                    ^~~~~~~

monmove.c: In function 'm_move':
monmove.c:874:43: warning: variable 'doorbuster' set but not used [-Wunused-but-set-variable]
  874 |     boolean can_open = 0, can_unlock = 0, doorbuster = 0;
      |                                           ^~~~~~~~~~
2021-01-25 12:57:47 -05:00
Pasi Kallinen
44f4085f69 Add a new themed room: "Twin business"
This themed room boasts two shops, a weapons and an armor store,
that can generate in a number of different configurations.

Makes the random corridor joining routine obey unjoined areas.

Fixes a bug in shopkeeper naming routine, where multiple shops
of the same type on the same level might reuse the shopkeeper name.

This is modified and consolidated commit from xNetHack by
copperwater <aosdict@gmail.com>.
2020-12-19 13:45:35 +02:00
PatR
6cbd2c5d85 warning fixes
Using 'ladder' as a variable conflicts with 'struct flag flags'
because of a macro in rm.h.  Also remove or hide a couple of
unused variables.

The hack.c diff is unrelated; just a reformatting bit that I had
laying around.
2020-11-13 14:11:54 -08:00
Pasi Kallinen
6ec55a3624 Rework stairs structure
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.
2020-11-13 20:27:17 +02:00
copperwater
06d1b3353e Fix: randomly generated vaults weren't being filled
This also caused the unexpected "You hear someone searching" message on
a level with an unlooted vault.
2020-09-28 20:00:12 +03:00
copperwater
b67092b2a0 Fix: stairs could generate in themed rooms if others were available
This is a simple && vs || bug. The clear intention of the code is that
stairs aren't supposed to generate in themed rooms unless there is no
other choice.

Fixes #348
2020-09-28 20:00:12 +03:00
copperwater
3d03a472f6 Stock all special rooms at the end of level creation
This unifies the two separate special-room-stocking code paths, one in
the standard dungeon generator and one in the special level generator
(neither of which reacted to themed rooms, which is the reason for this
commit) into the end of makelevel(), placing the special room stocking
as the very last step of level creation.

Under the new system, when a regular or special level decides to create
a special room, it sets that room's rtype, but the room is not stocked
until later. It already worked this way for special levels, so the main
difference here is in the normal level generation, where the mkroom
family of functions identifies and marks a room as a special room, but
stops short of filling it. (I suppose perhaps the mkroom, mkzoo, mkshop
family of functions would be better off changing their names to
"pickroom" and so on.)

This also restructures makelevel() itself a bit, but the only real
change is that the paths that call makemaz don't return immediately
afterward; they continue to the special room stocking code. Also, this
code was lifted from fill_special_rooms, which is now not used
anywhere, so it has been deleted.

I don't really like how fill_ordinary_room is in mklev.c and
fill_special_room is in sp_lev.c; they seem like they'd be better off in
mkroom.c, but in the interest of not making unnecessary code changes,
I'll just recommend it.
2020-09-27 18:54:15 +03:00
copperwater
0fef8fce9f Unify all special level filling options
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).
2020-09-27 18:54:15 +03:00
copperwater
0b2b0965a8 Allow themed room subrooms to be filled
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.
2020-09-27 18:54:14 +03:00
nhmall
ac9ba38449 file header bump from "NetHack 3.6" to "NetHack 3.7" 2020-08-03 22:07:36 -04:00
PatR
a51e44e532 move lua context out of dungeons[]
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.
2020-05-05 18:06:00 -07:00
Pasi Kallinen
54aa84eeea Prevent branch stairs generating in unjoined room 2020-04-21 18:41:08 +03:00
Pasi Kallinen
776ebd809e No trying themed rooms if lua init failed 2020-04-20 16:34:22 +03:00
PatR
8c744de8cd || vs &&
Add some parentheses.
2020-04-19 03:20:01 -07:00
Pasi Kallinen
9b74ea0b22 Shaped and themed rooms
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.
2020-04-18 19:55:09 +03:00
Pasi Kallinen
5f9714bf92 Remove workarounds for ancient compilers 2020-04-03 08:21:08 +03:00
Pasi Kallinen
408321b4f7 Use TAINT_AGE for old corpses instead of hardcoded value 2020-03-16 11:28:09 +02:00
nhmall
a213811975 stone/unexplored glyph follow-up
typo
2020-02-13 17:37:55 -05:00
Pasi Kallinen
df137029c0 Unify finding room pos for some features 2020-02-08 19:47:36 +02:00
nhmall
d37fa196b2 make a distinction between rock and unexplored area
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.
2020-02-08 00:48:03 -05:00
Pasi Kallinen
33cd6befe0 Dehardcode minefill
Instead of hardcoding the minefill levels in the core,
allow defining fill levels for a dungeon branch in the dungeon.lua
2020-02-01 18:31:39 +02:00
Pasi Kallinen
f83dede8e5 Fixes for degenerate RNG
Assume a degenerate RNG that always returns the same number.
With these fixes, the game starts and is almost playable.
There are still some places that will go into infinite loop, eg.
the mines level generation.
2020-01-06 11:48:19 +02:00
nhmall
223c31af0c some build fix-ups 2019-11-06 13:43:27 -05:00
nhmall
bcb627100b Merge branch 'paxed-lua-merged3' into paxed-lua-v2-merged 2019-11-06 12:56:21 -05:00
Pasi Kallinen
fd55d9118e Use lua for special level files
Game is playable, and should compile on linux and Windows.
Assumes you have a lua 5.3 library available.

Removes level compiler and associated files.
Replaces special level des-files with lua scripts.
Exposes some NetHack internals to lua:
 - des-table with commands to create special levels
 - nh-table with NetHack core commands
 - nhc-table with some constants
 - u-table with some player-specific data (u-struct)
 - selection userdata

Adds some rudimentary tests.

Adds new extended command #wizloadlua to run a specific script,
and #wizloaddes to run a specific level-creation script.

nhlib.lua is loaded for every lua script.

Download and untar lua:
  mkdir lib
  cd lib
  curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz
  tar zxf lua-5.3.5.tar.gz

Then make nethack normally.
2019-11-06 18:43:20 +02:00
nhmall
0d34f43830 remove STATIC_DCL, STATIC_OVL, STATIC_VAR, STATIC_PTR from core 2019-07-14 17:24:58 -04:00