Previously, the tetris-shaped rooms were always either
normal rooms, or turned into shops or other special rooms
in NetHack core. Now, the themed room lua code first picks
the themed room (which can be a themed or shaped), and some
of those will then pick a random filling (eg. ice floor,
traps, corpses, 3 altars).
Adds a new lua binding to create a selection picking locations
in current room.
The content-function in special level regions now get passed
the room data as a parameter.
This is a large iteration on a previous implementation of making
nh.getmap() parse its coordinates as relative to the last defined map or
room rather than absolute to the entire level. Now, everything in the
nh.* and obj.* functions interprets coords as relative rather than
absolute. (By default; if no map or room has been defined, or if the lua
code is executing after level creation is done, they will interpret the
coordinates as absolute).
The general motivation is basically the same - routines that use
absolute coordinates are difficult to use in level creation routines,
because then the designer has to remember to convert the relative
coordinate to an absolute one (and that was impossible before
nh.abscoord was added, particularly in themed rooms). And once
nh.getmap() takes relative coordinates, it would be very strange to have
all the other functions (setting timers, burying objects, etc) remain
with absolute ones.
In a couple places, code is changed to account for coordinates that are
relative to a *room* (which uses g.coder->croom->[lx,ly] as an offset,
instead of relative to a *map*, which uses [xstart,ystart].
Specifically, selection.iterate did not account for this, and without
this the ice themed room timer was not being started in the proper
place.
All tests are updated to respect the new behavior. Most of the modified
functions are not actually used anywhere in level files; the one
exception is starting a timer in a themed room, and that has been
adjusted.
Documentation updated as well to clarify when various things are tossing
around relative and absolute coordinates, both in comments and in
lua.adoc.
- Add bounds, so that we don't process any locations outside
as those locations are known to be unset
- The bounds are only recalculated if needed
- Replace instances of selection_not where we actually want
a new selection with all locations set
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
This is enough to prevent abuse by denying access to functions and
denial of service (RAM and instruction step limits), but not enough
to allow restricted use of things that require finer control (e.g.
filesystem access).
If something goes wrong, the whole thing can be turned off, for
now, in config.h (see NHL_SANDBOX).
None of the current functionality requires changes to build systems;
some of the possible future functionality may require some #defines
- TBD. There is lots of dead code (#ifdef notyet) for bits of that
additional functionality; we can rip it out if we don't want those
additions or we can complete (parts of) it depending on our needs.
All current uses of Lua are connected to sandboxes and guarded with
nhl_pcall (sandbox and lua_pcall wrapper); options and limits can
be set at the callsites in the passed nhl_sandbox_info. Some of
the error handling may be wrong - panic() vs. impossible() vs
silence.
Memory and instruction step limits should be tuned prior to release;
there's no point tuning them now.
Make selection rndcoord return a table with x and y keys.
Allow (most) coordinate parameters accept such a table.
Fix selection and des lua tests broken by the above changes and
an earlier change, because selections tried to set terrain
at column 0, and it now causes a complaint.
Noticed that when I set a selection to grow in a random direction, it
instead grew in all directions, which is not what I wanted. Turns out
the -1 random dir ended up being passed straight to the code which
checks bitmasks, without any form of randomizing among directions.
So this adds code to do that, and defines W_RANDOM as -1 rather than
using a magic number. In the process I also noticed that specifying
"random" as the wall for a door in a room made it rerandomize the
direction every iteration of its loop, essentially rolling two rn2(4)s
and only proceeding if they matched. That was pointless so I cleaned it
up a bit.
Also added safety checks in the form of an impossible for des.corridor()
being called with "random" as either walldir, because this is not
implemented currently.
And lastly, I noticed that create_secret_door was entirely unused
(secret door creation is handled in create_door), so I deleted it.
The only behavior change caused by this is that the Valkyrie quest lava
pools will be a little smaller, which is the only place grow is
currently used. If it's desired to keep them the same, that should be
changed to "all".
Selection difference is something I have found myself wanting a lot when
working on levels, and have had to defer to a clunkier xor-then-and
approach. This commit implements the TODO-ed addition and subtraction
operators on two sets.
I don't see how the addition operator would be any different from
logical or, so it just calls l_selection_or rather than implement a new
function.
../src/nhlsel.c(467) : warning C4701: potentially uninitialized local variable 'x1' used
../src/nhlsel.c(591) : warning C4701: potentially uninitialized local variable 'x' used
../src/nhlsel.c(467) : warning C4701: potentially uninitialized local variable 'y1' used
../src/nhlsel.c(591) : warning C4701: potentially uninitialized local variable 'y' used
../src/nhlsel.c(469) : warning C4701: potentially uninitialized local variable 'x2' used
../src/nhlsel.c(469) : warning C4701: potentially uninitialized local variable 'y2' used
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.
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.
There was a rare selection bug where selection was freed by the gc
but it was still in use. Don't remove the selections from the stack
while we're handling them.
A recent change has resulted in complaints about 'sel' not being
used in
struct selectionvar *sel = l_selection_check(L, 1);
struct selectionvar *ret;
int p = (int) luaL_checkinteger(L, 2);
lua_pop(L, 1);
(void) l_selection_clone(L);
ret = l_selection_check(L, 1);
selection_filter_percent(ret, p);
This preserves the semantics of that code while getting rid of the
warning, but I have no idea whether it makes any sense.
[...]
| Change selection_free(foo) to also free(foo) after freeing foo's
| fields. Every use was already
| selection_free(foo);
| free(foo);
| except for the two instances of memory leak.
And except for the three which aren't in sp_lev.c, one of which was
dealing with memory managed by Lua. This time it seems to be working
as intended.
Unix Makefile.utl wasn't aware of the dependency of makedefs.o on
src/mdlib.c so didn't rebuild makedefs when it should have.
Eliminate several warnings:
mdlib.c - #if inside the arguments to macro Sprintf();
nhlua.c - nhl_error() ends with a call to lua_error() which doesn't
return, but neither of them were declared that way;
nhlsel.c - because of the previous, the 'else error' case of
l_selection_ellipse() led to complaints about uninitialized
variables;
sp_lev.c - missing 'const'.
I did minimal testing which went ok, but revisiting a couple of levels
gave me un-freed memory allocated by restore.c line 1337. (I haven't
looked at that at all.)
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.