Commit Graph

245 Commits

Author SHA1 Message Date
nhmall
48fa4fa5dd more warning bits 2020-10-10 16:28:17 -04:00
Pasi Kallinen
3d6551a70e Lua: Allow matching any wall
A 'w' in a map fragment will match any wall (IS_WALL macro):

   des.replace_terrain({ mapfragment = "w", toterrain = "F" });
2020-10-10 11:31:16 +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
f8ff58ed7e Fill special rooms recursively rather than only at top level
The fill_special_rooms function was only stocking two types of rooms:
top-level rooms in g.rooms, and their immediate subrooms. If there were
a special room 2 or more levels down, it would not get filled. (No
special levels currently define such a special room, so this bug is
latent.)

To address this, I changed fill_special_rooms to iterate only through
the top level rooms, and fill_special_room to recurse through all of its
subrooms (if any) before filling itself.
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
f57588cef1 Make fill_special_room avoid themed rooms
No code in this function would actually do anything if it were called on
a themed room, but since it is pretty clearly intended for the "regular"
special rooms, it's probably best to explicitly avoid themed rooms as
well.
2020-09-27 18:54:14 +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
PatR
9faaa1b25d pull request #345 - theme room dimensions
"When a room is created and passed down to a contents function in
Lua, the width and height properties of that room are computed by
subtracting lx from hx and ly from hy, which means e.g. a room
which is 8 floor squares wide and 5 tall appears to the contents
function as having a width of 7 and height of 4.  This patch fixes
that off-by-one."

I don't understand the details here:  should a room's dimensions
include its boundary walls or just the inner amount?  This change
didn't seem to cause any problems so I've put it in.

Closes #345
2020-09-23 17:57:19 -07:00
PatR
f20a6bb491 special level's lit state when changing terrain
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.
2020-09-06 16:17:33 -07:00
nhmall
ac9ba38449 file header bump from "NetHack 3.6" to "NetHack 3.7" 2020-08-03 22:07:36 -04:00
nhmall
dfcccfcf54 x64 64 bit pointers, 32 bit longs
../src/sp_lev.c: In function 'flip_level':
../src/sp_lev.c:816:24: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
             long ty = ((long) timer->arg.a_void) & 0xffff;
                        ^
../src/sp_lev.c:817:25: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
             long tx = (((long) timer->arg.a_void) >> 16) & 0xffff;
                         ^
../src/sp_lev.c:823:33: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
             timer->arg.a_void = (genericptr_t) ((tx << 16) | ty);
2020-04-29 15:58:55 -04:00
PatR
0ae84411a0 option fixes and missing prototypes
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.
2020-04-22 13:39:38 -07:00
PatR
579939010d lua.adoc typo
"not-cursed" was misspelled.
2020-04-19 15:42:32 -07:00
Pasi Kallinen
9784b5adef Fix heap use after free
In a lua script, if object was created inside a container, it
might've merged with another object.

Also prevent stacking, lighting, and burying contained objects.
2020-04-18 22:13:52 +03: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
copperwater
18d19c902b Allow specifying a montype on figurines in lua files
This was already allowed for the other montype-compatible objects like
statues, corpses, eggs and tins. I don't see a reason why figurines
shouldn't be part of this group; perhaps it was an oversight.
2020-04-15 06:47:58 +03:00
Pasi Kallinen
d78dcdcb9b Allow matching any wall map terrain in lua scripts
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()
2020-04-13 20:00:34 +03:00
Pasi Kallinen
665eacf40c Expose scaled mazes to special level lua
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 });
2020-04-07 19:20:39 +03:00
copperwater
0befdbfd02 Re-implement gradient selections
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.
2020-04-06 18:54:39 +03:00
Pasi Kallinen
c24b9f0f1a Fix one more prototype warning 2020-04-06 18:24:15 +03:00
Pasi Kallinen
d087746fd7 And some more warning fixes 2020-04-06 15:41:26 +03:00
Pasi Kallinen
e215f09ddb Fix even more warnings 2020-04-06 13:34:07 +03:00
Pasi Kallinen
13b8a9912f Flip poison gas clouds 2020-04-03 20:42:27 +03:00
Pasi Kallinen
42fc34691d Check for levl typ STONE explicitly
... instead of expecting 0 to be STONE (or unused space in this case)
2020-04-03 13:10:12 +03:00
Patric Mueller
acf6f5fdff Level compiler creates correct novel with supplied name
Before this commit, the name of a novel in the level files was ignored for
setting novelidx. But the name was set nevertheless, so you got a named novel
that showed quotes from a different novel.

Now, 'des.object({ id = "novel", name="Raising Steam"});' will work as
expected.
2020-04-01 22:36:30 +02:00
PatR
bb6be709d8 tweaks for #wizlevelflip
For interactive level flip, flip cached travel destination and
interrupted digging position.

Also, ball and chain handling wasn't right if the ball was carried.
The fix for that is untested because I don't know how to judge where
the flip area starts and stops and this code is for the case where
that boundary is straddled rather than having hero and ball and chain
all inside or all outside the flip area.
2020-03-30 04:58:28 -07:00
Pasi Kallinen
3776b7d382 Fix monsters overflowing out of rooms in special levels
In a special level, creating more monsters inside room contents
than was space in the room placed monsters outside the room,
possibly inside walls of rooms created afterwards.

Prevent monster creation if inside room contents and there's no
space for the monster.
2020-03-29 11:17:40 +03:00
PatR
3eed500886 fix #K669 - 'nasty' monster summoning
Report complained about multiple Archons causing his character to
be swarmed by monsters on the Plane of Fire.  I don't think that
the behavior has changed significantly from how it worked in 3.4.3.
Nobody can summon an Archon directly because they're excluded from
the nasties[] list.  But whenever summoning picks a genocided
'nasty', the result gets replaced by random monster of appropriate
difficulty for the level (which could be an Archon for a high level
character in the endgame).  [Note that that won't pick an Archon
in Gehennom or at arch-lich outside of there because the random
monster creation honors the only-in-hell and never-in-hell flags;
picking from the nasties[] list doesn't.]

This prevents that for any creature (except arch-lich or the Wizard)
casting the summon nasties spell.  If a replacement creature is a
spellcaster it now has to have lower difficulty than the summoner.
If not, it will be discarded even though its difficulty is classified
as appropriate.  So to summon an Archon, the summoner has to have
higher difficulty than an Archon; arch-lich and the Wizard are the
only ones meeting that criterium.  When summoner is an arch-lich,
it can't summon another arch-lich (since that wouldn't have lower
difficulty than the summoner) and can summon (via replacement for
genocided type, and only if outside of Gehennom) at most one Archon.
When summoner is the Wizard, he could summon an arch-lich (when in
Gehennom; demoted to master lich elsewhere--see below) or an Archon
(outside Gehennom only), but at most one per summoning.

For post-Wizard harassment, which effectively has infinite
difficulty level, it could still happen.  However, each instance of
harassment is only allowed to create at most one Archon or arch-lich
now, so chain summoning should be lessoned.  Also if it tries to
pick an arch-lich when outside of Gehennom it will switch to master
lich instead (which won't be allowed to summon an Archon or an arch-
lich or even another master lich).

(The monmove.c bit is unrelated, just some comment formatting that
I had laying around that got mixed in.)
2020-03-27 19:05:52 -07:00
Pasi Kallinen
e89c193a57 Fix flipping while punished
... if either you, the ball, or the chain are outside the flip area.
Just unplace the b&c and then put it down under the hero.
This can only happen via #wizlevelflip, as normal level flipping
is done when creating the level and b&c are not on the map.
2020-03-27 17:30:23 +02:00
PatR
24f0aa2dc9 warning fix
This one is more interesting that most....

|sp_lev.c:3745:9: warning: declaration shadows a variable in the
|      global scope [-Wshadow]
|boolean ladder;
|        ^
|../include/rm.h:538:20: note: expanded from macro 'ladder'
|#define ladder     flags /* up or down */
|                   ^
|../include/flag.h:428:29: note: previous declaration is here
|extern NEARDATA struct flag flags;
|                            ^
2020-03-19 15:08:43 -07:00
Pasi Kallinen
a142ac8140 Unify special level c code for stairways 2020-03-19 21:23:55 +02:00
Pasi Kallinen
44ba4a9e96 Don't flip column 0 2020-03-16 22:10:37 +02:00
Pasi Kallinen
55bfc8115a Flip timed effects
In wizard mode, freezing some water on the ground, then
flipping the level did not flip the coordinate of the ice
thawing timed effect. This could cause an impossible complaint.
2020-03-14 11:28:32 +02:00
Pasi Kallinen
2ff8523481 Fix priest generated inside temple wall
In a rare case, a random room's width can be 2 tiles, and if
that room was converted into a temple, the priest ended up
inside the wall. Try to put the priest on a random valid position
around the altar, or on it.
2020-03-12 19:17:06 +02:00
Pasi Kallinen
9adb11238a Flip locations only if inside the flip area
Objects and hero outside the level area (embedded in undiggable
rock by eg. polying into earth elemental) cannot be flipped.
2020-03-11 19:25:52 +02:00
Pasi Kallinen
ae471e71b2 Make sure random doors don't open into solid wall
When making a random door into a random wall or random position
in a room, keep trying harder to find a location that doesn't
have solid wall behind it.

Fixes the Wizard tower door.
2020-03-10 18:11:30 +02:00
Pasi Kallinen
9ea2fb7422 Fix flipping some monsters
Don't flip the guard waiting to be disposed of.
Don't flip the occasional monster (usually an earth elemental)
outside the level bounds.
2020-03-08 20:01:41 +02:00
Pasi Kallinen
f18b5bb59b Make special levels generate objects with genocided monster classes
If a special level explicitly requests eg. a statue with a genocided
monster class, allow generating it.

Rationale is that those objects were generated before the monsters
became extinct. Also fixes a lua error.
2020-03-08 14:08:32 +02:00
Pasi Kallinen
8b6ae1642d Fix flipping non-existent stairs
If the stair or ladder x coord is 0, it doesn't exist.
Flipping it, caused "u_on_newpos: trying to place hero off map <80,0>"
when coming back up from the valley into the castle, and the
castle was flipped.

Fixes #331
2020-03-07 17:07:10 +02:00
Pasi Kallinen
2fc9c02f88 lua special level feature flags
Allow des.feature() to set rm flags for the special features.
2020-03-06 20:30:15 +02:00
Pasi Kallinen
a6dfbfca2f Lua: Add contents function to room and map
The function will get the map/room width and height as a parameter.
2020-03-04 20:05:15 +02:00
Pasi Kallinen
c9b21e36a7 Add lua selection match method
Also improve the replace_terrain command parameters.
2020-03-02 16:17:53 +02:00
Pasi Kallinen
ce3b45944b Fix Fort Ludios room type
... and add an impossible when lua tries to create unknown room type.
2020-03-01 10:13:53 +02:00
Pasi Kallinen
22528d31f5 Allow coord in place of x and y in special level lua script 2020-02-28 22:14:36 +02:00
Pasi Kallinen
816079c8dd Lua: accept different params for gold function 2020-02-26 17:57:47 +02:00
nhmall
1003a8142e fix a couple of warnings seen on visual studio 2019
src/sp_lev.c(4278): warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int(__cdecl *)(int,int)'
  src/sp_lev.c(5021): warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int (__cdecl *)(int,int)'
2020-02-25 22:56:50 -05:00
Pasi Kallinen
ccb00f59bc Add new level init type, swamp
Creates a "relaxed blockwise maze".
Make Juiblex's swamp use it.
2020-02-25 19:24:58 +02:00
PatR
194b174bbc flipping current level with #wizlevelflip
Give wizard mode player control over how a level gets transposed by
prompting for the desired outcome.

Refreshing the screen showed that remembered, no longer in view wall
corners and T walls were shown with their old orientation instead of
being transposed along with the level.  This fixes that, but does so
by adding a chunk of code that will be irrelevant for normal play.
2020-02-24 17:07:01 -08:00
Pasi Kallinen
509576a8b7 Minor tweaks to level flipping 2020-02-23 15:06:44 +02:00
Pasi Kallinen
6648ecfe04 Make lua selection randline create a new selection 2020-02-22 16:34:50 +02:00