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.
This commit is contained in:
Pasi Kallinen
2019-05-10 21:11:50 +03:00
parent 3e029d2900
commit fd55d9118e
189 changed files with 16653 additions and 27346 deletions

100
src/cmd.c
View File

@@ -148,6 +148,7 @@ STATIC_PTR int NDECL(wiz_where);
STATIC_PTR int NDECL(wiz_detect);
STATIC_PTR int NDECL(wiz_panic);
STATIC_PTR int NDECL(wiz_polyself);
STATIC_PTR int NDECL(wiz_load_lua);
STATIC_PTR int NDECL(wiz_level_tele);
STATIC_PTR int NDECL(wiz_level_change);
STATIC_PTR int NDECL(wiz_show_seenv);
@@ -785,16 +786,14 @@ wiz_identify(VOID_ARGS)
return 0;
}
/* #wizmakemap - discard current dungeon level and replace with a new one */
STATIC_PTR int
wiz_makemap(VOID_ARGS)
void
makemap_prepost(pre, wiztower)
boolean pre, wiztower;
{
NHFILE tmpnhfp;
struct monst *mtmp;
if (wizard) {
struct monst *mtmp;
boolean was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz);
if (pre) {
rm_mapseen(ledger_no(&u.uz));
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (mtmp->isgd) { /* vault is going away; get rid of guard */
@@ -844,14 +843,14 @@ wiz_makemap(VOID_ARGS)
angel on Astral or setting off alarm on Ft.Ludios are handled
by goto_level(do.c) so won't occur for replacement levels */
mklev();
} else {
vision_reset();
g.vision_full_recalc = 1;
cls();
/* was using safe_teleds() but that doesn't honor arrival region
on levels which have such; we don't force stairs, just area */
u_on_rndspot((u.uhave.amulet ? 1 : 0) /* 'going up' flag */
| (was_in_W_tower ? 2 : 0));
| (wiztower ? 2 : 0));
losedogs();
/* u_on_rndspot() might pick a spot that has a monster, or losedogs()
might pick the hero's spot (only if there isn't already a monster
@@ -870,6 +869,21 @@ wiz_makemap(VOID_ARGS)
#ifdef INSURANCE
save_currentstate();
#endif
}
}
/* #wizmakemap - discard current dungeon level and replace with a new one */
STATIC_PTR int
wiz_makemap(VOID_ARGS)
{
if (wizard) {
boolean was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz);
makemap_prepost(TRUE, was_in_W_tower);
/* create a new level; various things like bestowing a guardian
angel on Astral or setting off alarm on Ft.Ludios are handled
by goto_level(do.c) so won't occur for replacement levels */
mklev();
makemap_prepost(FALSE, was_in_W_tower);
} else {
pline(unavailcmd, "#wizmakemap");
}
@@ -930,6 +944,70 @@ wiz_detect(VOID_ARGS)
return 0;
}
STATIC_PTR int
wiz_load_lua(VOID_ARGS)
{
if (wizard) {
char buf[BUFSZ];
getlin("Load which lua file?", buf);
if (buf[0] == '\033' || buf[0] == '\0')
return 0;
if (!strchr(buf, '.'))
strcat(buf, ".lua");
(void) load_lua(buf);
} else
pline("Unavailable command 'wiz_load_lua'.");
return 0;
}
STATIC_PTR int
wiz_load_splua(VOID_ARGS)
{
if (wizard) {
boolean was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz);
char buf[BUFSZ];
int ridx;
getlin("Load which des lua file?", buf);
if (buf[0] == '\033' || buf[0] == '\0')
return 0;
if (!strchr(buf, '.'))
strcat(buf, ".lua");
makemap_prepost(TRUE, was_in_W_tower);
/* TODO: need to split some of this out of mklev(), makelevel(), makemaz() */
g.in_mklev = TRUE;
oinit(); /* assign level dependent obj probabilities */
clear_level_structures();
(void) load_special(buf);
bound_digging();
mineralize(-1, -1, -1, -1, FALSE);
g.in_mklev = FALSE;
if (g.level.flags.has_morgue)
g.level.flags.graveyard = 1;
if (!g.level.flags.is_maze_lev) {
struct mkroom *croom;
for (croom = &g.rooms[0]; croom != &g.rooms[g.nroom]; croom++)
#ifdef SPECIALIZATION
topologize(croom, FALSE);
#else
topologize(croom);
#endif
}
set_wall_state();
/* for many room types, g.rooms[].rtype is zeroed once the room has been
entered; g.rooms[].orig_rtype always retains original rtype value */
for (ridx = 0; ridx < SIZE(g.rooms); ridx++)
g.rooms[ridx].orig_rtype = g.rooms[ridx].rtype;
makemap_prepost(FALSE, was_in_W_tower);
} else
pline("Unavailable command 'wiz_load_splua'.");
return 0;
}
/* ^V command - level teleport */
STATIC_PTR int
wiz_level_tele(VOID_ARGS)
@@ -3452,6 +3530,10 @@ struct ext_func_tab extcmdlist[] = {
wiz_intrinsic, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ C('v'), "wizlevelport", "teleport to another level",
wiz_level_tele, IFBURIED | AUTOCOMPLETE | WIZMODECMD },
{ '\0', "wizloaddes", "load and execute a des-file lua script",
wiz_load_splua, IFBURIED | WIZMODECMD },
{ '\0', "wizloadlua", "load and execute a lua script",
wiz_load_lua, IFBURIED | WIZMODECMD },
{ '\0', "wizmakemap", "recreate the current level",
wiz_makemap, IFBURIED | WIZMODECMD },
{ C('f'), "wizmap", "map the level",