Commit Graph

280 Commits

Author SHA1 Message Date
Pasi Kallinen
408aa4b3cb remove sp_lev execute bits 2021-09-12 22:34:19 +03:00
copperwater
1bb686f744 Fix: replace_terrain used wrong y2 coordinate 2021-09-03 08:27:44 +03:00
Pasi Kallinen
b080ea12c2 Debug flag allowing overwriting stairs
And using it in the movement tests, so running doesn't stop
at stairs.
2021-07-30 16:35:36 +03:00
Pasi Kallinen
e2c6cbe347 Fix missing Izchak shop
My recent commit broke Izchak's shop in minetn-6.
Fix it as per the suggestion from entrez.
Fixes #555
2021-07-24 20:18:44 +03: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
dbac44596e Lua: Allow boolean params in level_init 2021-07-22 18:02:58 +03:00
Pasi Kallinen
932b6d03c9 Lua: Make des.monster use boolean params 2021-07-22 11:05:40 +03:00
nhmall
a4711739c0 get rid of some recent signed/unsigned mismatches
src/mkroom.c(529): warning C4389: '!=': signed/unsigned mismatch
src/sp_lev.c(981): warning C4389: '==': signed/unsigned mismatch
src/sp_lev.c(983): warning C4389: '==': signed/unsigned mismatch
src/sp_lev.c(985): warning C4389: '==': signed/unsigned mismatch
src/sp_lev.c(987): warning C4389: '==': signed/unsigned mismatch
src/sp_lev.c(989): warning C4389: '==': signed/unsigned mismatch
2021-07-10 07:42:27 -04:00
Pasi Kallinen
2261f998a6 Fix des.room doors
Fix special level des.room shop doors broken by my recent commit.
Mark the shopdoor error as impossible, so the fuzzer stops there.
2021-07-09 20:32:00 +03:00
Pasi Kallinen
4050ec1670 Improve special level shop and door linking
When creating a shop via des.region, allow creating the shop door
either with a map character in a des.map, or with des.door
before or after the shop region.

Also allow a shop door to open directly into another shop.
2021-07-09 13:58:49 +03:00
Pasi Kallinen
3ddb2a91c7 Allow some makemon flags in lua monster creation
Also document the des.monster hash parameter values.
2021-06-24 14:38:12 +03:00
PatR
04a8ddcce1 fix github issue #531 - genderless corpses
Dead monsters that had traits saved with the corpse would revive as
the same gender, but ordinary corpses revived with random gender so
could be different from before they got killed.

Since corpses of monsters lacked gender, those for monsters with
gender-specific names were described by the neuter name.

This is a fairly big change for a fairly minor problem and needs a
lot more testing.

Fixes #531
2021-06-08 03:43:46 -07:00
PatR
0fda8504bb sp_lev.c reformatting
Mostly reformatting but fixes a bug in mapfrag_free(); would matter
if the same map fragment gets freed a second time.
2021-05-30 01:01:01 -07:00
PatR
72866e2252 special level loading error
For the baalz 'lit=0' fix, I first tried 'lit=false'.  That isn't
supported and triggered an error, but the error reporting passed
a null pointer to sprintf() for a %s argument.  OSX's stdio shows
"null" instead of crashing in that situation; most implementations
wouldn't be so forgiving.

It intends to complain about "false" but that won't work if the
unexpected value doesn't get put into the lua table.  I don't know
how to fix that aspect of this.  This fix just avoids passing a
null pointer to sprintf.  Plus some miscellaneous reformatting.
2021-05-29 13:34:32 -07: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
Pasi Kallinen
d2b331abf7 Accept "waiting" on special level des.monster() specifications
Allow specifying "waiting" for monsters created via lua level scripts.
This sets the monster strategy to make it wait for the hero
to be in visual range before allowing the monster to move.

Also makes the monster inside the Mausoleum themed room use this feature,
to prevent out of depth liches bothering the player unprovoked.

For example:

des.monster({ class = "D", waiting = 1 });
2021-05-09 12:24:27 +03:00
PatR
141cafb210 fix pull request #492 - select_do_line of a point
Latent bug:  selection_do_line() for a single point produced
spurious line(s).

I haven't got a test case so am taking this one on faith....

While in there, do some nearby formatting fixups in sp_lev.c.

Fixes #492
2021-04-18 14:13:57 -07:00
PatR
6c22520b1a fix pull request #479 - statues of stoning-immunes
Statues on Medusa's level are supposed to be from petrified creatures
rather than somebody's artwork, so creatures that can't be turned to
stone aren't eligible.  However, creatures who change form when hit
with stoning damage (foo golems to stone golem) were being allowed.
Also, statues in cockatrice nest rooms are supposed to be from former
characters and take their names from the high scores file.  But when
'record' is empty, the statue would be of a random creature instead
of being changed into a player character, so both not the latter and
possibly something that can't be petrified.

I've taken the Medusa part as-is but did the cockatrice nest part
differently.  It rejected statues of non-stonable creatures in case
the named character attempt failed.  I've changed things so that when
a named player character can't be created, it will use an unnamed one
instead of random creature.  The issue of maybe ending up with a non-
stonable form goes away because all player characters are vulnerable.

Fixes #479
2021-04-01 12:12:05 -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
copperwater
fa3041c9f9 Make g.coder->lvl_is_joined a boolean
Its value is only used as a boolean, so there's no real need to keep it
as a confusing int.

Shouldn't be a save-breaking change; it doesn't look like g.coder is
saved.
2021-02-19 17:09:41 +02:00
Dean Luick
5eaf028c0f Re-fix altar compiler warning
Implement a better fix for commit 2f4f7d22d ("Fix align type
mixup wth align mask") which was reverted in commit 4e35e8b5a
("Revert "Fix align type mixup wth align mask"").

In the present code, the field align in both struct altar and
struct monster is not an aligntyp, but an align mask with extra flags.
Change the type to match its actual use and improve the naming.

Consolidate duplicated code into a single routine.

Change the return type of induced_align() to be unsigned to match
amask usage.

Change the special level align mask values to be separate from
the normal align mask values.
2021-02-07 22:25:25 -06:00
nhmall
4e35e8b5a6 Revert "Fix align type mixup wth align mask"
This reverts commit 2f4f7d22d3
for now while the matter is investigated further.

Also closes #459
2021-02-06 14:54:54 -05:00
nhmall
5e5df4f6b9 remove an old #pragma from sp_lev.c that isn't actually accomplishing anything 2021-01-30 11:25:27 -05:00
Dean Luick
2f4f7d22d3 Fix align type mixup wth align mask
Fix two cases of missed conversion of an alignment to an align mask.

Change induced_align()'s return type to unsigned int since it returns
an align mask (unsigned), not an align type (signed).
2021-01-29 09:31:08 -06:00
nhmall
f963c5aca7 switch source tree from k&r to c99 2021-01-26 21:06:16 -05:00
nhmall
fb43299451 some Microsoft compiler warnings
src/muse.c(2255) : warning C4702: unreachable code
src/options.c(2549) : warning C4702: unreachable code
src/restore.c(930) : warning C4701: potentially uninitialized local variable 'stway' used
src/sp_lev.c(5118) : warning C4701: potentially uninitialized local variable 'x' used
src/sp_lev.c(5118) : warning C4701: potentially uninitialized local variable 'y' used
src/trap.c(2979) : warning C4701: potentially uninitialized local variable 'cc' used
src/trap.c(2985) : warning C4701: potentially uninitialized local variable 'bcc' used
2021-01-17 22:58:52 -05:00
nhmall
862c4064ab gender-specific names can be used in .lua files with the gender upheld
Revert "monster name references in .lua files"
This reverts commit 0e0aa7bdf6.
2020-12-31 18:51:00 -05:00
nhmall
0c3b9642e4 pmnames mons gender naming plus a window port interface change
add MALE, FEMALE, and gender-neutral names for individual monster species
to the mons array. The gender-neutral name (NEUTRAL) is mandatory, the
MALE and FEMALE versions are not.

replace code uses of the mname field of permonst with one of the three
potentially-available gender-specific names.

consolidate some separate mons entries that differed only by species into a
single mons entry (caveman, cavewoman and priest,priestess etc.)

consolidate several "* lord" and "* queen/* king" monst entries into
their single species, and allow both genders on some where it makes some
sense (there is probably more work and cleanup to come out of this at some
point, and the chosen gender-neutral name variations are not cast in stone
if someone has better suggestions).

related function or macro additions:
    pmname(pm, gender) to get the gender variation of the permonst name. It
    guards against monsters that haven't got anything except NEUTRAL naming
    and falls back to the NEUTRAL version if FEMALE and MALE versions are
    missing.

    Ugender to obtain the current hero gender.
    Mgender(mtmp) to obtain the gender of a monster

While the code can safely refer directly to pmnames[NEUTRAL] safely in the
code because it always exists, the other two (pmnames[MALE] and
pmnames[FEMALE] may not exist so use:
    pmname(ptr, gidx)
      where -ptr is a permonst *
            -gidx is an index into the pmnames array field of the
             permonst struct
pmname() checks for a valid index and checks for null-pointers for
pmnames[MALE] and pmnames[FEMALE], and will fall back to pmnames[NEUTRAL] if
the pointer requested if the requested variation is unavailable, or if the
gidx is out-of-range.

Allow code to specify makemon flags to request female or male (via MM_MALE
and MM_FEMALE flags respectively)to makedefs, since the species alone doesn't
distinguish male/female anymore. Specifying MM_MALE or MM_FEMALE won't
override the pm M2_MALE and M2_FEMALE flags on a mons[] entry.

male and female tiles have been added to win/share/monsters.txt.
The majority are duplicated placeholders except for those that were
separate mons entries before. Perhaps someone will contribute artwork in the
future to make the male and female variations visually distinguishable.

tilemapping via has the MALE tile indexes in the glyph2tile[]
array produced at build time. If a window port has information that the
FEMALE tile is required, it just has to increment the index returned
from the glyph2tile[] array by 1.

statues already preserved gender of the monster through STATUE_FEMALE
and STATUE_MALE, so ensure that pmnames takes that into consideration.

I expect some refinement will be required after broad play-testing puts it to
the test.

    consolidate caveman,cavewoman and priest,priestess monst.c entries etc

This commit will require a bump of editlevel in patchlevel.h because it alters
the index numbers of the monsters due to the consolidation of some. Those
index numbers are saved in some other structures, even though the mons[] array
itself is not part of the savefile.

Window Port Interface Change

Also add a parameter to print_glyph to convey additional information beyond
the glyph to the window ports. Every single window port was calling back to
mapglyph for the information anyway, so just included it in the interface and
produce the information right in the display core.

The mapglyph() function uses will be eliminated, although there are still some
in the code yet to be dealt with.

win32, tty, x11, Qt, msdos window ports have all had adjustments done to
utilize the new parameter instead of calling mapglyph, but some of those
window ports have not been thoroughly tested since the changes.

Interface change additional info:

    print_glyph(window, x, y, glyph, bkglyph, *glyphmod)
            -- Print the glyph at (x,y) on the given window.  Glyphs are
               integers at the interface, mapped to whatever the window-
               port wants (symbol, font, color, attributes, ...there's
               a 1-1 map between glyphs and distinct things on the map).
            -- bkglyph is a background glyph for potential use by some
               graphical or tiled environments to allow the depiction
               to fall against a background consistent with the grid
               around x,y. If bkglyph is NO_GLYPH, then the parameter
               should be ignored (do nothing with it).
                -- glyphmod provides extended information about the glyph
               that window ports can use to enhance the display in
               various ways.
                    unsigned int glyphmod[NUM_GLYPHMOD]
               where:
                    glyphmod[GM_TTYCHAR]  is the text characters associated
                                          with the original NetHack display.

                    glyphmod[GM_FLAGS]    are the special flags that denote
                                          additional information that window
                                          ports can use.

                    glyphmod[GM_COLOR] is the text character
                                       color associated with the original
                                       NetHack display.

Support for including the glyphmod info in the display glyph buffer
alongside the glyph itself was added and is the default operation.
That can be turned off by defining UNBUFFERED_GLYPHMOD at compile time.
With UNBUFFERED_GLYPHMOD operation, a call will be placed to map_glyphmod()
immediately prior to every print_glyph() call.
2020-12-26 11:23:23 -05:00
Pasi Kallinen
13359648dd Remove duplicate wallify_map code 2020-12-06 18:36:37 +02:00
PatR
7b50590654 rename #wizlevelflip to #wizfliplevel
Since ^V is dead key for me with Qt on OSX, I use #wizlevelport
instead.  It's annoying to have to type all the way up to the
'p' for it to become distinct.  Rename the biggest conflict,
\#wizlevelflip to #wizfliplevel.  I still have to type as far
as the first 'e' for #wizlevelport but 6 characters are easier
to type than 10.

It wasn't in the Guidebook so I've left things that way.  I am
adding it to 'wizhelp' though.
2020-11-19 01:57:13 -08:00
Pasi Kallinen
ccb5bc4b55 Avoid hard-coded bit twiddling 2020-11-15 19:56:35 +02:00
Pasi Kallinen
deb730d9b5 More hypothetical type mismatches 2020-11-15 13:51:47 +02:00
Pasi Kallinen
289c8d654d Futureproofing hypothetical type mismatches
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.
2020-11-14 13:53:09 +02: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
Bart House
d1404d345c Fix compiler warning. 2020-10-19 16:20:49 -07:00
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