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:
100
src/cmd.c
100
src/cmd.c
@@ -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",
|
||||
|
||||
@@ -617,7 +617,8 @@ const struct instance_globals g_init = {
|
||||
NULL, /* lev_message */
|
||||
NULL, /* lregions */
|
||||
0, /* num_lregions */
|
||||
UNDEFINED_VALUES, /* SplLev_Map */
|
||||
UNDEFINED_VALUES, /* SpLev_Map */
|
||||
NULL, /* coder */
|
||||
UNDEFINED_VALUE, /* xstart */
|
||||
UNDEFINED_VALUE, /* ystart */
|
||||
UNDEFINED_VALUE, /* xsize */
|
||||
@@ -629,7 +630,6 @@ const struct instance_globals g_init = {
|
||||
{ UNDEFINED_PTR }, /* container_obj */
|
||||
0, /* container_idx */
|
||||
NULL, /* invent_carrying_monster */
|
||||
{ AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL }, /* ralign */
|
||||
|
||||
/* spells.c */
|
||||
0, /* spl_sortmode */
|
||||
|
||||
@@ -306,7 +306,7 @@ gloc_filter_init()
|
||||
{
|
||||
if (iflags.getloc_filter == GFILTER_AREA) {
|
||||
if (!g.gloc_filter_map) {
|
||||
g.gloc_filter_map = selection_opvar((char *) 0);
|
||||
g.gloc_filter_map = selection_new();
|
||||
}
|
||||
/* special case: if we're in a doorway, try to figure out which
|
||||
direction we're moving, and use that side of the doorway */
|
||||
@@ -326,8 +326,8 @@ void
|
||||
gloc_filter_done()
|
||||
{
|
||||
if (g.gloc_filter_map) {
|
||||
opvar_free_x(g.gloc_filter_map);
|
||||
g.gloc_filter_map = (struct opvar *) 0;
|
||||
selection_free(g.gloc_filter_map);
|
||||
g.gloc_filter_map = (struct selectionvar *) 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,10 @@
|
||||
char * trimspaces (char *)
|
||||
char * strip_newline (char *)
|
||||
char * stripchars (char *, const char *, const char *)
|
||||
char * stripdigits (char *)
|
||||
char * eos (char *)
|
||||
boolean str_end_is (const char *, const char *)
|
||||
int str_lines_maxlen (const char *)
|
||||
char * strkitten (char *,char)
|
||||
void copynchars (char *,const char *,int)
|
||||
char chrcasecpy (int,int)
|
||||
@@ -224,6 +226,31 @@ const char *str, *chkstr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* return the max line length from buffer comprising of newline-separated strings */
|
||||
int
|
||||
str_lines_maxlen(str)
|
||||
const char *str;
|
||||
{
|
||||
const char *s1, *s2;
|
||||
int len, max_len = 0;
|
||||
|
||||
s1 = str;
|
||||
while (s1 && *s1) {
|
||||
s2 = index(s1, '\n');
|
||||
if (s2) {
|
||||
len = (int) (s2 - s1);
|
||||
s1 = s2 + 1;
|
||||
} else {
|
||||
len = (int) strlen(s1);
|
||||
s1 = (char *) 0;
|
||||
}
|
||||
if (len > max_len)
|
||||
max_len = len;
|
||||
}
|
||||
|
||||
return max_len;
|
||||
}
|
||||
|
||||
/* append a character to a string (in place): strcat(s, {c,'\0'}); */
|
||||
char *
|
||||
strkitten(s, c)
|
||||
@@ -468,6 +495,21 @@ const char *stuff_to_strip, *orig;
|
||||
return bp;
|
||||
}
|
||||
|
||||
/* remove digits from string */
|
||||
char *
|
||||
stripdigits(s)
|
||||
char *s;
|
||||
{
|
||||
char *s1, *s2;
|
||||
|
||||
for (s1 = s2 = s; *s1; s1++)
|
||||
if (*s1 < '0' || *s1 > '9')
|
||||
*s2++ = *s1;
|
||||
*s2 = '\0';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* substitute a word or phrase in a string (in place) */
|
||||
/* caller is responsible for ensuring that bp points to big enough buffer */
|
||||
char *
|
||||
|
||||
19
src/mklev.c
19
src/mklev.c
@@ -14,7 +14,6 @@ STATIC_DCL void FDECL(mksink, (struct mkroom *));
|
||||
STATIC_DCL void FDECL(mkaltar, (struct mkroom *));
|
||||
STATIC_DCL void FDECL(mkgrave, (struct mkroom *));
|
||||
STATIC_DCL void NDECL(makevtele);
|
||||
STATIC_DCL void NDECL(clear_level_structures);
|
||||
STATIC_DCL void NDECL(makelevel);
|
||||
STATIC_DCL boolean FDECL(bydoor, (XCHAR_P, XCHAR_P));
|
||||
STATIC_DCL struct mkroom *FDECL(find_branch_room, (coord *));
|
||||
@@ -354,6 +353,14 @@ register struct mkroom *aroom;
|
||||
register int tmp;
|
||||
int i;
|
||||
|
||||
if (aroom->doorct) {
|
||||
for (i = 0; i < aroom->doorct; i++) {
|
||||
tmp = aroom->fdoor + i;
|
||||
if (g.doors[tmp].x == x && g.doors[tmp].y == y)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (aroom->doorct == 0)
|
||||
aroom->fdoor = g.doorindex;
|
||||
|
||||
@@ -573,7 +580,7 @@ makevtele()
|
||||
* special) but it's easier to put it all in one place than make sure
|
||||
* each type initializes what it needs to separately.
|
||||
*/
|
||||
STATIC_OVL void
|
||||
void
|
||||
clear_level_structures()
|
||||
{
|
||||
static struct rm zerorm = { cmap_to_glyph(S_stone),
|
||||
@@ -637,6 +644,14 @@ clear_level_structures()
|
||||
xdnladder = ydnladder = xupladder = yupladder = 0;
|
||||
g.made_branch = FALSE;
|
||||
clear_regions();
|
||||
g.xstart = 1;
|
||||
g.ystart = 0;
|
||||
g.xsize = COLNO - 1;
|
||||
g.ysize = ROWNO;
|
||||
if (g.lev_message) {
|
||||
free(g.lev_message);
|
||||
g.lev_message = (char *) 0;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
|
||||
@@ -28,8 +28,10 @@ schar bg_typ;
|
||||
register int i, j;
|
||||
|
||||
for (i = 1; i < COLNO; i++)
|
||||
for (j = 0; j < ROWNO; j++)
|
||||
for (j = 0; j < ROWNO; j++) {
|
||||
levl[i][j].typ = bg_typ;
|
||||
levl[i][j].lit = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
|
||||
723
src/nhlsel.c
Normal file
723
src/nhlsel.c
Normal file
@@ -0,0 +1,723 @@
|
||||
/* NetHack 3.6 nhlua.c $NHDT-Date: 1524287226 2018/04/21 05:07:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
|
||||
/* Copyright (c) 2018 by Pasi Kallinen */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#include "hack.h"
|
||||
#include "sp_lev.h"
|
||||
|
||||
/* lua_CFunction prototypes */
|
||||
STATIC_DCL int FDECL(l_selection_new, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_clone, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_getpoint, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_setpoint, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_not, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_filter_percent, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_rndcoord, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_line, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_randline, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_rect, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_fillrect, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_fillrect, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_grow, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_filter_mapchar, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_flood, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_circle, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_ellipse, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_gradient, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_iterate, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_gc, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_not, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_and, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_or, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_xor, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_not, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_add, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_sub, (lua_State *));
|
||||
STATIC_DCL int FDECL(l_selection_ipairs, (lua_State *));
|
||||
|
||||
struct selectionvar *
|
||||
l_selection_check(L, index)
|
||||
lua_State *L;
|
||||
int index;
|
||||
{
|
||||
struct selectionvar *sel;
|
||||
|
||||
luaL_checktype(L, index, LUA_TUSERDATA);
|
||||
sel = (struct selectionvar *)luaL_checkudata(L, index, "selection");
|
||||
if (!sel)
|
||||
nhl_error(L, "Selection error");
|
||||
return sel;
|
||||
}
|
||||
|
||||
static int
|
||||
l_selection_gc(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct selectionvar *sel = l_selection_check(L, 1);
|
||||
if (sel)
|
||||
selection_free(sel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct selectionvar *
|
||||
l_selection_to(L, index)
|
||||
lua_State *L;
|
||||
int index;
|
||||
{
|
||||
struct selectionvar *sel = (struct selectionvar *)lua_touserdata(L, index);
|
||||
if (!sel)
|
||||
nhl_error(L, "Selection error");
|
||||
return sel;
|
||||
}
|
||||
|
||||
static struct selectionvar *
|
||||
l_selection_push(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct selectionvar *tmp = selection_new();
|
||||
struct selectionvar *sel = (struct selectionvar *)lua_newuserdata(L, sizeof(struct selectionvar));
|
||||
luaL_getmetatable(L, "selection");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
sel->wid = tmp->wid;
|
||||
sel->hei = tmp->hei;
|
||||
sel->map = dupstr(tmp->map);
|
||||
selection_free(tmp);
|
||||
|
||||
return sel;
|
||||
}
|
||||
|
||||
/* local sel = selection.new(); */
|
||||
static int
|
||||
l_selection_new(L)
|
||||
lua_State *L;
|
||||
{
|
||||
(void) l_selection_push(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local sel = selection.clone(sel); */
|
||||
static int
|
||||
l_selection_clone(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct selectionvar *sel = l_selection_check(L, 1);
|
||||
struct selectionvar *tmp;
|
||||
/* int x,y; */ /* REVIEW: unreferenced */
|
||||
lua_pop(L, 1);
|
||||
(void) l_selection_new(L);
|
||||
tmp = l_selection_check(L, 1);
|
||||
if (tmp->map)
|
||||
free(tmp->map);
|
||||
tmp->map = dupstr(sel->map);
|
||||
tmp->wid = sel->wid;
|
||||
tmp->hei = sel->hei;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* selection.set(sel, x, y); */
|
||||
/* selection.set(sel, x, y, value); */
|
||||
/* local sel = selection.set(); */
|
||||
/* local sel = sel:set(); */
|
||||
/* local sel = selection.set(sel); */
|
||||
/* TODO: allow setting multiple coordinates at once: set({x,y}, {x,y}, ...); */
|
||||
static int
|
||||
l_selection_setpoint(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct selectionvar *sel = (struct selectionvar *) 0;
|
||||
/* REVIEW: initializer added */
|
||||
schar x = -1, y = -1;
|
||||
int val = 1;
|
||||
int argc = lua_gettop(L);
|
||||
long coord;
|
||||
|
||||
if (argc == 0) {
|
||||
(void) l_selection_new(L);
|
||||
} else if (argc == 1) {
|
||||
sel = l_selection_check(L, 1);
|
||||
} else if (argc == 2) {
|
||||
x = (schar) luaL_checkinteger(L, 1);
|
||||
y = (schar) luaL_checkinteger(L, 2);
|
||||
lua_pop(L, 2);
|
||||
(void) l_selection_new(L);
|
||||
sel = l_selection_check(L, 1);
|
||||
} else {
|
||||
sel = l_selection_check(L, 1);
|
||||
x = (schar) luaL_checkinteger(L, 2);
|
||||
y = (schar) luaL_checkinteger(L, 3);
|
||||
val = (int) luaL_optinteger(L, 4, 1);
|
||||
}
|
||||
|
||||
if (!sel || !sel->map) {
|
||||
nhl_error(L, "Selection setpoint error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (x == -1 && y == -1)
|
||||
coord = SP_COORD_PACK_RANDOM(0);
|
||||
else
|
||||
coord = SP_COORD_PACK(x,y);
|
||||
get_location_coord(&x, &y, ANY_LOC, g.coder ? g.coder->croom : NULL, coord);
|
||||
selection_setpoint(x, y, sel, val);
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local value = selection.get(sel, x, y); */
|
||||
static int
|
||||
l_selection_getpoint(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct selectionvar *sel = l_selection_check(L, 1);
|
||||
schar x = (schar) luaL_checkinteger(L, 2);
|
||||
schar y = (schar) luaL_checkinteger(L, 3);
|
||||
int val;
|
||||
long coord;
|
||||
|
||||
if (x == -1 && y == -1)
|
||||
coord = SP_COORD_PACK_RANDOM(0);
|
||||
else
|
||||
coord = SP_COORD_PACK(x,y);
|
||||
get_location_coord(&x, &y, ANY_LOC, g.coder ? g.coder->croom : NULL, coord);
|
||||
|
||||
val = selection_getpoint(x, y, sel);
|
||||
lua_settop(L, 0);
|
||||
lua_pushnumber(L, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local s = selection.negate(sel); */
|
||||
/* local s = selection.negate(); */
|
||||
static int
|
||||
l_selection_not(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct selectionvar *sel;
|
||||
|
||||
if (argc == 0)
|
||||
(void) l_selection_new(L);
|
||||
sel = l_selection_check(L, 1);
|
||||
selection_not(sel);
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local sel = selection.area(4,5, 40,10) & selection.rect(7,8, 60,14); */
|
||||
static int
|
||||
l_selection_and(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int x,y;
|
||||
struct selectionvar *sela = l_selection_check(L, 1);
|
||||
struct selectionvar *selb = l_selection_check(L, 2);
|
||||
|
||||
for (x = 0; x < sela->wid; x++)
|
||||
for (y = 0; y < sela->hei; y++) {
|
||||
int val = selection_getpoint(x, y, sela) & selection_getpoint(x, y, selb);
|
||||
selection_setpoint(x, y, sela, val);
|
||||
}
|
||||
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local sel = selection.area(4,5, 40,10) | selection.rect(7,8, 60,14); */
|
||||
static int
|
||||
l_selection_or(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int x,y;
|
||||
struct selectionvar *sela = l_selection_check(L, 1);
|
||||
struct selectionvar *selb = l_selection_check(L, 2);
|
||||
|
||||
for (x = 0; x < sela->wid; x++)
|
||||
for (y = 0; y < sela->hei; y++) {
|
||||
int val = selection_getpoint(x, y, sela) | selection_getpoint(x, y, selb);
|
||||
selection_setpoint(x, y, sela, val);
|
||||
}
|
||||
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local sel = selection.area(4,5, 40,10) ~ selection.rect(7,8, 60,14); */
|
||||
static int
|
||||
l_selection_xor(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int x,y;
|
||||
struct selectionvar *sela = l_selection_check(L, 1);
|
||||
struct selectionvar *selb = l_selection_check(L, 2);
|
||||
|
||||
for (x = 0; x < sela->wid; x++)
|
||||
for (y = 0; y < sela->hei; y++) {
|
||||
int val = selection_getpoint(x, y, sela) ^ selection_getpoint(x, y, selb);
|
||||
selection_setpoint(x, y, sela, val);
|
||||
}
|
||||
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* local s = selection.percentage(sel, 50); */
|
||||
static int
|
||||
l_selection_filter_percent(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct selectionvar *sel = l_selection_check(L, 1);
|
||||
int p = (int) luaL_checkinteger(L, 2);
|
||||
selection_filter_percent(sel, p);
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local x,y = selection.rndcoord(sel); */
|
||||
/* local x,y = selection.rndcoord(sel, 1); */
|
||||
static int
|
||||
l_selection_rndcoord(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct selectionvar *sel = l_selection_check(L, 1);
|
||||
int removeit = (int) luaL_optinteger(L, 2, 0);
|
||||
schar x, y;
|
||||
selection_rndcoord(sel, &x, &y, removeit);
|
||||
update_croom();
|
||||
if (g.coder && g.coder->croom) {
|
||||
x -= g.coder->croom->lx;
|
||||
y -= g.coder->croom->ly;
|
||||
} else {
|
||||
x -= g.xstart;
|
||||
y -= g.ystart;
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
lua_pushnumber(L, x);
|
||||
lua_pushnumber(L, y);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* local s = selection.line(sel, x1,y1, x2,y2); */
|
||||
/* local s = selection.line(x1,y1, x2,y2); */
|
||||
/* s:line(x1,y1, x2,y2); */
|
||||
static int
|
||||
l_selection_line(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct selectionvar *sel;
|
||||
schar x1;
|
||||
schar y1;
|
||||
schar x2;
|
||||
schar y2;
|
||||
|
||||
if (argc == 4) {
|
||||
(void) l_selection_new(L);
|
||||
x1 = (schar) luaL_checkinteger(L, 1);
|
||||
y1 = (schar) luaL_checkinteger(L, 2);
|
||||
x2 = (schar) luaL_checkinteger(L, 3);
|
||||
y2 = (schar) luaL_checkinteger(L, 4);
|
||||
sel = l_selection_check(L, 5);
|
||||
lua_remove(L, 1);
|
||||
lua_remove(L, 1);
|
||||
lua_remove(L, 1);
|
||||
lua_remove(L, 1);
|
||||
} else {
|
||||
sel = l_selection_check(L, 1);
|
||||
x1 = (schar) luaL_checkinteger(L, 2);
|
||||
y1 = (schar) luaL_checkinteger(L, 3);
|
||||
x2 = (schar) luaL_checkinteger(L, 4);
|
||||
y2 = (schar) luaL_checkinteger(L, 5);
|
||||
}
|
||||
|
||||
get_location_coord(&x1, &y1, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x1,y1));
|
||||
get_location_coord(&x2, &y2, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x2,y2));
|
||||
|
||||
selection_do_line(x1,y1,x2,y2, sel);
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local s = selection.rect(sel, x1,y1, x2,y2); */
|
||||
static int
|
||||
l_selection_rect(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct selectionvar *sel;
|
||||
schar x1;
|
||||
schar y1;
|
||||
schar x2;
|
||||
schar y2;
|
||||
|
||||
if (argc == 4) {
|
||||
(void) l_selection_new(L);
|
||||
x1 = (schar) luaL_checkinteger(L, 1);
|
||||
y1 = (schar) luaL_checkinteger(L, 2);
|
||||
x2 = (schar) luaL_checkinteger(L, 3);
|
||||
y2 = (schar) luaL_checkinteger(L, 4);
|
||||
sel = l_selection_check(L, 5);
|
||||
lua_remove(L, 1);
|
||||
lua_remove(L, 1);
|
||||
lua_remove(L, 1);
|
||||
lua_remove(L, 1);
|
||||
} else {
|
||||
sel = l_selection_check(L, 1);
|
||||
x1 = (schar) luaL_checkinteger(L, 2);
|
||||
y1 = (schar) luaL_checkinteger(L, 3);
|
||||
x2 = (schar) luaL_checkinteger(L, 4);
|
||||
y2 = (schar) luaL_checkinteger(L, 5);
|
||||
}
|
||||
|
||||
get_location_coord(&x1, &y1, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x1,y1));
|
||||
get_location_coord(&x2, &y2, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x2,y2));
|
||||
|
||||
selection_do_line(x1,y1,x2,y1, sel);
|
||||
selection_do_line(x1,y1,x1,y2, sel);
|
||||
selection_do_line(x2,y1,x2,y2, sel);
|
||||
selection_do_line(x1,y2,x2,y2, sel);
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local s = selection.fillrect(sel, x1,y1, x2,y2); */
|
||||
/* local s = selection.fillrect(x1,y1, x2,y2); */
|
||||
/* s:fillrect(x1,y1, x2,y2); */
|
||||
/* selection.area(x1,y1, x2,y2); */
|
||||
static int
|
||||
l_selection_fillrect(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct selectionvar *sel;
|
||||
int y;
|
||||
schar x1;
|
||||
schar y1;
|
||||
schar x2;
|
||||
schar y2;
|
||||
|
||||
if (argc == 4) {
|
||||
(void) l_selection_new(L);
|
||||
x1 = (schar) luaL_checkinteger(L, 1);
|
||||
y1 = (schar) luaL_checkinteger(L, 2);
|
||||
x2 = (schar) luaL_checkinteger(L, 3);
|
||||
y2 = (schar) luaL_checkinteger(L, 4);
|
||||
sel = l_selection_check(L, 5);
|
||||
lua_remove(L, 1);
|
||||
lua_remove(L, 1);
|
||||
lua_remove(L, 1);
|
||||
lua_remove(L, 1);
|
||||
} else {
|
||||
sel = l_selection_check(L, 1);
|
||||
x1 = (schar) luaL_checkinteger(L, 2);
|
||||
y1 = (schar) luaL_checkinteger(L, 3);
|
||||
x2 = (schar) luaL_checkinteger(L, 4);
|
||||
y2 = (schar) luaL_checkinteger(L, 5);
|
||||
}
|
||||
|
||||
get_location_coord(&x1, &y1, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x1,y1));
|
||||
get_location_coord(&x2, &y2, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x2,y2));
|
||||
|
||||
if (x1 == x2) {
|
||||
for (y = y1; y <= y2; y++)
|
||||
selection_setpoint(x1, y, sel, 1);
|
||||
} else {
|
||||
for (y = y1; y <= y2; y++)
|
||||
selection_do_line(x1,y,x2,y, sel);
|
||||
}
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local s = selection.randline(sel, x1,y1, x2,y2, roughness); */
|
||||
/* local s = selection.randline(x1,y1, x2,y2, roughness); */
|
||||
/* TODO: selection.randline(x1,y1, x2,y2, roughness); */
|
||||
/* TODO: selection.randline({x1,y1}, {x2,y2}, roughness); */
|
||||
static int
|
||||
l_selection_randline(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct selectionvar *sel = (struct selectionvar *) 0;
|
||||
/* REVIEW: initializer added */
|
||||
schar x1, y1, x2, y2;
|
||||
int roughness = 7;
|
||||
|
||||
if (argc == 6) {
|
||||
sel = l_selection_check(L, 1);
|
||||
x1 = (schar) luaL_checkinteger(L, 2);
|
||||
y1 = (schar) luaL_checkinteger(L, 3);
|
||||
x2 = (schar) luaL_checkinteger(L, 4);
|
||||
y2 = (schar) luaL_checkinteger(L, 5);
|
||||
roughness = (int) luaL_checkinteger(L, 6);
|
||||
} else if (argc == 5 && lua_type(L, 1) == LUA_TNUMBER) {
|
||||
x1 = (schar) luaL_checkinteger(L, 1);
|
||||
y1 = (schar) luaL_checkinteger(L, 2);
|
||||
x2 = (schar) luaL_checkinteger(L, 3);
|
||||
y2 = (schar) luaL_checkinteger(L, 4);
|
||||
roughness = (int) luaL_checkinteger(L, 5);
|
||||
lua_pop(L, 5);
|
||||
(void) l_selection_new(L);
|
||||
sel = l_selection_check(L, 1);
|
||||
}
|
||||
|
||||
get_location_coord(&x1, &y1, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x1,y1));
|
||||
get_location_coord(&x2, &y2, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x2,y2));
|
||||
|
||||
selection_do_randline(x1,y1, x2,y2, roughness, 12, sel);
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local s = selection.grow(sel); */
|
||||
/* local s = selection.grow(sel, "north"); */
|
||||
static int
|
||||
l_selection_grow(L)
|
||||
lua_State *L;
|
||||
{
|
||||
const char *const growdirs[] = { "all", "random", "north", "west", "east", "south", NULL };
|
||||
const int growdirs2i[] = { W_ANY, -1, W_NORTH, W_WEST, W_EAST, W_SOUTH, 0 };
|
||||
|
||||
struct selectionvar *sel = l_selection_check(L, 1);
|
||||
int dir = growdirs2i[luaL_checkoption(L, 2, "all", growdirs)];
|
||||
selection_do_grow(sel, dir);
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* local s = selection.filter_mapchar(sel, mapchar, lit); */
|
||||
static int
|
||||
l_selection_filter_mapchar(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct selectionvar *sel = l_selection_check(L, 1);
|
||||
char *mapchr = dupstr(luaL_checkstring(L, 2));
|
||||
xchar typ = check_mapchr(mapchr);
|
||||
int lit = (int) luaL_optinteger(L, 3, -2); /* TODO: special lit values */
|
||||
struct selectionvar *tmp = selection_filter_mapchar(sel, typ, lit);
|
||||
|
||||
if (typ == INVALID_TYPE)
|
||||
nhl_error(L, "Erroneous map char");
|
||||
|
||||
if (sel->map)
|
||||
free(sel->map);
|
||||
sel->map = tmp->map;
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
if (mapchr)
|
||||
free(mapchr);
|
||||
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* local s = selection.floodfill(sel, x, y); */
|
||||
/* local s = selection.floodfill(x,y); */
|
||||
static int
|
||||
l_selection_flood(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct selectionvar *sel = (struct selectionvar *) 0;
|
||||
/* REVIEW: initializer added */
|
||||
schar x, y;
|
||||
|
||||
if (argc == 3) {
|
||||
sel = l_selection_check(L, 1);
|
||||
x = (schar) luaL_checkinteger(L, 2);
|
||||
y = (schar) luaL_checkinteger(L, 3);
|
||||
} else if (argc == 2) {
|
||||
x = (schar) luaL_checkinteger(L, 1);
|
||||
y = (schar) luaL_checkinteger(L, 2);
|
||||
lua_pop(L, 2);
|
||||
(void) l_selection_new(L);
|
||||
sel = l_selection_check(L, 1);
|
||||
} else {
|
||||
nhl_error(L, "wrong parameters");
|
||||
}
|
||||
|
||||
get_location_coord(&x, &y, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x,y));
|
||||
|
||||
if (isok(x,y)) {
|
||||
set_floodfillchk_match_under(levl[x][y].typ);
|
||||
selection_floodfill(sel, x, y, FALSE);
|
||||
}
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* local s = selection.circle(x,y, radius); */
|
||||
/* local s = selection.circle(x, y, radius, filled); */
|
||||
/* local s = selection.circle(sel, x, y, radius); */
|
||||
/* local s = selection.circle(sel, x, y, radius, filled); */
|
||||
static int
|
||||
l_selection_circle(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct selectionvar *sel = (struct selectionvar *) 0;
|
||||
/* REVIEW: initializer added */
|
||||
schar x, y;
|
||||
int r, filled = 0;
|
||||
|
||||
if (argc == 3) {
|
||||
x = (schar) luaL_checkinteger(L, 1);
|
||||
y = (schar) luaL_checkinteger(L, 2);
|
||||
r = (int) luaL_checkinteger(L, 3);
|
||||
lua_pop(L, 3);
|
||||
(void) l_selection_new(L);
|
||||
sel = l_selection_check(L, 1);
|
||||
filled = 0;
|
||||
} else if (argc == 4 && lua_type(L, 1) == LUA_TNUMBER) {
|
||||
x = (schar) luaL_checkinteger(L, 1);
|
||||
y = (schar) luaL_checkinteger(L, 2);
|
||||
r = (int) luaL_checkinteger(L, 3);
|
||||
filled = (int) luaL_checkinteger(L, 4); /* TODO: boolean*/
|
||||
lua_pop(L, 4);
|
||||
(void) l_selection_new(L);
|
||||
sel = l_selection_check(L, 1);
|
||||
} else if (argc == 4 || argc == 5) {
|
||||
sel = l_selection_check(L, 1);
|
||||
x = (schar) luaL_checkinteger(L, 2);
|
||||
y = (schar) luaL_checkinteger(L, 3);
|
||||
r = (int) luaL_checkinteger(L, 4);
|
||||
filled = (int) luaL_optinteger(L, 5, 0); /* TODO: boolean */
|
||||
} else {
|
||||
nhl_error(L, "wrong parameters");
|
||||
}
|
||||
|
||||
get_location_coord(&x, &y, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x,y));
|
||||
|
||||
selection_do_ellipse(sel, x,y, r,r, !filled);
|
||||
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local s = selection.ellipse(x, y, radius1, radius2); */
|
||||
/* local s = selection.ellipse(x, y, radius1, radius2, filled); */
|
||||
/* local s = selection.ellipse(sel, x, y, radius1, radius2); */
|
||||
/* local s = selection.ellipse(sel, x, y, radius1, radius2, filled); */
|
||||
static int
|
||||
l_selection_ellipse(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct selectionvar *sel = (struct selectionvar *) 0;
|
||||
/* REVIEW: initializer added */
|
||||
schar x, y;
|
||||
int r1, r2, filled = 0;
|
||||
|
||||
if (argc == 4) {
|
||||
x = (schar) luaL_checkinteger(L, 1);
|
||||
y = (schar) luaL_checkinteger(L, 2);
|
||||
r1 = (int) luaL_checkinteger(L, 3);
|
||||
r2 = (int) luaL_checkinteger(L, 4);
|
||||
lua_pop(L, 4);
|
||||
(void) l_selection_new(L);
|
||||
sel = l_selection_check(L, 1);
|
||||
filled = 0;
|
||||
} else if (argc == 5 && lua_type(L, 1) == LUA_TNUMBER) {
|
||||
x = (schar) luaL_checkinteger(L, 1);
|
||||
y = (schar) luaL_checkinteger(L, 2);
|
||||
r1 = (int) luaL_checkinteger(L, 3);
|
||||
r2 = (int) luaL_checkinteger(L, 4);
|
||||
filled = (int) luaL_optinteger(L, 5, 0); /* TODO: boolean */
|
||||
lua_pop(L, 5);
|
||||
(void) l_selection_new(L);
|
||||
sel = l_selection_check(L, 1);
|
||||
} else if (argc == 5 || argc == 6) {
|
||||
sel = l_selection_check(L, 1);
|
||||
x = (schar) luaL_checkinteger(L, 2);
|
||||
y = (schar) luaL_checkinteger(L, 3);
|
||||
r1 = (int) luaL_checkinteger(L, 4);
|
||||
r2 = (int) luaL_checkinteger(L, 5);
|
||||
filled = (int) luaL_optinteger(L, 6, 0); /* TODO: boolean */
|
||||
} else {
|
||||
nhl_error(L, "wrong parameters");
|
||||
}
|
||||
|
||||
get_location_coord(&x, &y, ANY_LOC, g.coder ? g.coder->croom : NULL, SP_COORD_PACK(x,y));
|
||||
|
||||
selection_do_ellipse(sel, x,y, r1,r2, !filled);
|
||||
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const struct luaL_Reg l_selection_methods[] = {
|
||||
{ "new", l_selection_new },
|
||||
{ "clone", l_selection_clone },
|
||||
{ "get", l_selection_getpoint },
|
||||
{ "set", l_selection_setpoint },
|
||||
{ "negate", l_selection_not },
|
||||
{ "percentage", l_selection_filter_percent },
|
||||
{ "rndcoord", l_selection_rndcoord },
|
||||
{ "line", l_selection_line },
|
||||
{ "randline", l_selection_randline },
|
||||
{ "rect", l_selection_rect },
|
||||
{ "fillrect", l_selection_fillrect },
|
||||
{ "area", l_selection_fillrect },
|
||||
{ "grow", l_selection_grow },
|
||||
{ "filter_mapchar", l_selection_filter_mapchar },
|
||||
{ "floodfill", l_selection_flood },
|
||||
{ "circle", l_selection_circle },
|
||||
{ "ellipse", l_selection_ellipse },
|
||||
/* TODO:
|
||||
{ "gradient", l_selection_gradient },
|
||||
{ "iterate", l_selection_iterate },
|
||||
*/
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const luaL_Reg l_selection_meta[] = {
|
||||
{ "__gc", l_selection_gc },
|
||||
{ "__unm", l_selection_not },
|
||||
{ "__band", l_selection_and },
|
||||
{ "__bor", l_selection_or },
|
||||
{ "__bxor", l_selection_xor },
|
||||
{ "__bnot", l_selection_not },
|
||||
/* TODO: http://lua-users.org/wiki/MetatableEvents
|
||||
{ "__add", l_selection_add },
|
||||
{ "__sub", l_selection_sub },
|
||||
{ "__ipairs", l_selection_ipairs },
|
||||
*/
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
l_selection_register(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int lib_id, meta_id;
|
||||
|
||||
/* newclass = {} */
|
||||
lua_createtable(L, 0, 0);
|
||||
lib_id = lua_gettop(L);
|
||||
|
||||
/* metatable = {} */
|
||||
luaL_newmetatable(L, "selection");
|
||||
meta_id = lua_gettop(L);
|
||||
luaL_setfuncs(L, l_selection_meta, 0);
|
||||
|
||||
/* metatable.__index = _methods */
|
||||
luaL_newlib(L, l_selection_methods);
|
||||
lua_setfield(L, meta_id, "__index");
|
||||
|
||||
/* metatable.__metatable = _meta */
|
||||
luaL_newlib(L, l_selection_meta);
|
||||
lua_setfield(L, meta_id, "__metatable");
|
||||
|
||||
/* class.__metatable = metatable */
|
||||
lua_setmetatable(L, lib_id);
|
||||
|
||||
/* _G["selection"] = newclass */
|
||||
lua_setglobal(L, "selection");
|
||||
|
||||
return 0;
|
||||
}
|
||||
883
src/nhlua.c
Normal file
883
src/nhlua.c
Normal file
@@ -0,0 +1,883 @@
|
||||
/* NetHack 3.6 nhlua.c $NHDT-Date: 1524287226 2018/04/21 05:07:06 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
|
||||
/* Copyright (c) 2018 by Pasi Kallinen */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#include "hack.h"
|
||||
#include "dlb.h"
|
||||
|
||||
/*
|
||||
#- include <lua5.3/lua.h>
|
||||
#- include <lua5.3/lualib.h>
|
||||
#- include <lua5.3/lauxlib.h>
|
||||
*/
|
||||
|
||||
/* */
|
||||
|
||||
/* lua_CFunction prototypes */
|
||||
STATIC_DCL int FDECL(nhl_test, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_getmap, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_setmap, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_pline, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_verbalize, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_menu, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_getlin, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_makeplural, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_makesingular, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_s_suffix, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_ing_suffix, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_an, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_meta_u_index, (lua_State *));
|
||||
STATIC_DCL int FDECL(nhl_meta_u_newindex, (lua_State *));
|
||||
STATIC_DCL int FDECL(traceback_handler, (lua_State *));
|
||||
|
||||
void
|
||||
nhl_error(L, msg)
|
||||
lua_State *L;
|
||||
const char *msg;
|
||||
{
|
||||
lua_Debug ar;
|
||||
char buf[BUFSZ];
|
||||
lua_getstack(L, 1, &ar);
|
||||
lua_getinfo(L, "lS", &ar);
|
||||
Sprintf(buf, "%s (line %i%s)", msg, ar.currentline, ar.source);
|
||||
lua_pushstring(L, buf);
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
/* Check that parameters are nothing but single table,
|
||||
or if no parameters given, put empty table there */
|
||||
void
|
||||
lcheck_param_table(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc < 1)
|
||||
lua_createtable(L, 0, 0);
|
||||
|
||||
/* discard any extra arguments passed in */
|
||||
lua_settop(L, 1);
|
||||
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
}
|
||||
|
||||
schar
|
||||
get_table_mapchr(L, name)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
{
|
||||
char *ter;
|
||||
xchar typ;
|
||||
|
||||
ter = get_table_str(L, name);
|
||||
typ = check_mapchr(ter);
|
||||
if (typ == INVALID_TYPE)
|
||||
nhl_error(L, "Erroneous map char");
|
||||
if (ter)
|
||||
free(ter);
|
||||
return typ;
|
||||
}
|
||||
|
||||
schar
|
||||
get_table_mapchr_opt(L, name, defval)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
schar defval;
|
||||
{
|
||||
char *ter;
|
||||
xchar typ;
|
||||
|
||||
ter = get_table_str_opt(L, name, "");
|
||||
if (name && *ter) {
|
||||
typ = check_mapchr(ter);
|
||||
if (typ == INVALID_TYPE)
|
||||
nhl_error(L, "Erroneous map char");
|
||||
} else
|
||||
typ = defval;
|
||||
if (ter)
|
||||
free(ter);
|
||||
return typ;
|
||||
}
|
||||
|
||||
void
|
||||
nhl_add_table_entry_int(L, name, value)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
int value;
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
lua_pushinteger(L, value);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
void
|
||||
nhl_add_table_entry_str(L, name, value)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
const char *value;
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
lua_pushstring(L, dupstr(value));
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
void
|
||||
nhl_add_table_entry_bool(L, name, value)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
boolean value;
|
||||
{
|
||||
lua_pushstring(L, name);
|
||||
lua_pushboolean(L, value);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
/* converting from special level "map character" to levl location type
|
||||
and back. order here is important. */
|
||||
const struct {
|
||||
char ch;
|
||||
schar typ;
|
||||
} char2typ[] = {
|
||||
{ ' ', STONE },
|
||||
{ '#', CORR },
|
||||
{ '.', ROOM },
|
||||
{ '-', HWALL },
|
||||
{ '-', TLCORNER },
|
||||
{ '-', TRCORNER },
|
||||
{ '-', BLCORNER },
|
||||
{ '-', BRCORNER },
|
||||
{ '-', CROSSWALL },
|
||||
{ '-', TUWALL },
|
||||
{ '-', TDWALL },
|
||||
{ '-', TLWALL },
|
||||
{ '-', TRWALL },
|
||||
{ '-', DBWALL },
|
||||
{ '|', VWALL },
|
||||
{ '+', DOOR },
|
||||
{ 'A', AIR },
|
||||
{ 'C', CLOUD },
|
||||
{ 'S', SDOOR },
|
||||
{ 'H', SCORR },
|
||||
{ '{', FOUNTAIN },
|
||||
{ '\\', THRONE },
|
||||
{ 'K', SINK },
|
||||
{ '}', MOAT },
|
||||
{ 'P', POOL },
|
||||
{ 'L', LAVAPOOL },
|
||||
{ 'I', ICE },
|
||||
{ 'W', WATER },
|
||||
{ 'T', TREE },
|
||||
{ 'F', IRONBARS }, /* Fe = iron */
|
||||
{ 'x', MAX_TYPE }, /* "see-through" */
|
||||
{ 'B', CROSSWALL }, /* hack: boundary location */
|
||||
{ '\0', STONE },
|
||||
};
|
||||
|
||||
schar
|
||||
splev_chr2typ(c)
|
||||
char c;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; char2typ[i].ch; i++)
|
||||
if (c == char2typ[i].ch)
|
||||
return char2typ[i].typ;
|
||||
return (INVALID_TYPE);
|
||||
}
|
||||
|
||||
schar
|
||||
check_mapchr(s)
|
||||
const char *s;
|
||||
{
|
||||
if (s && strlen(s) == 1)
|
||||
return splev_chr2typ(s[0]);
|
||||
return INVALID_TYPE;
|
||||
}
|
||||
|
||||
char
|
||||
splev_typ2chr(typ)
|
||||
schar typ;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; char2typ[i].typ < MAX_TYPE; i++)
|
||||
if (typ == char2typ[i].typ)
|
||||
return char2typ[i].ch;
|
||||
return 'x';
|
||||
}
|
||||
|
||||
/* local loc = getmap(x,y) */
|
||||
static int
|
||||
nhl_getmap(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 2) {
|
||||
int x = (int) lua_tonumber(L, 1);
|
||||
int y = (int) lua_tonumber(L, 2);
|
||||
|
||||
if (x >= 0 && x < COLNO && y >= 0 && y < ROWNO) {
|
||||
char buf[BUFSZ];
|
||||
lua_newtable(L);
|
||||
|
||||
/* FIXME: some should be boolean values */
|
||||
nhl_add_table_entry_int(L, "glyph", levl[x][y].glyph);
|
||||
nhl_add_table_entry_int(L, "typ", levl[x][y].typ);
|
||||
Sprintf(buf, "%c", splev_typ2chr(levl[x][y].typ));
|
||||
nhl_add_table_entry_str(L, "mapchr", buf);
|
||||
nhl_add_table_entry_int(L, "seenv", levl[x][y].seenv);
|
||||
nhl_add_table_entry_bool(L, "horizontal", levl[x][y].horizontal);
|
||||
nhl_add_table_entry_bool(L, "lit", levl[x][y].lit);
|
||||
nhl_add_table_entry_bool(L, "waslit", levl[x][y].waslit);
|
||||
nhl_add_table_entry_int(L, "roomno", levl[x][y].roomno);
|
||||
nhl_add_table_entry_bool(L, "edge", levl[x][y].edge);
|
||||
nhl_add_table_entry_bool(L, "candig", levl[x][y].candig);
|
||||
|
||||
/* TODO: FIXME: levl[x][y].flags */
|
||||
|
||||
lua_pushliteral(L, "flags");
|
||||
lua_newtable(L);
|
||||
|
||||
if (IS_DOOR(levl[x][y].typ)) {
|
||||
nhl_add_table_entry_bool(L, "nodoor", (levl[x][y].flags & D_NODOOR));
|
||||
nhl_add_table_entry_bool(L, "broken", (levl[x][y].flags & D_BROKEN));
|
||||
nhl_add_table_entry_bool(L, "isopen", (levl[x][y].flags & D_ISOPEN));
|
||||
nhl_add_table_entry_bool(L, "closed", (levl[x][y].flags & D_CLOSED));
|
||||
nhl_add_table_entry_bool(L, "locked", (levl[x][y].flags & D_LOCKED));
|
||||
nhl_add_table_entry_bool(L, "trapped", (levl[x][y].flags & D_TRAPPED));
|
||||
} else if (IS_ALTAR(levl[x][y].typ)) {
|
||||
/* TODO: bits 0, 1, 2 */
|
||||
nhl_add_table_entry_bool(L, "shrine", (levl[x][y].flags & AM_SHRINE));
|
||||
} else if (IS_THRONE(levl[x][y].typ)) {
|
||||
nhl_add_table_entry_bool(L, "looted", (levl[x][y].flags & T_LOOTED));
|
||||
} else if (levl[x][y].typ == TREE) {
|
||||
nhl_add_table_entry_bool(L, "looted", (levl[x][y].flags & TREE_LOOTED));
|
||||
nhl_add_table_entry_bool(L, "swarm", (levl[x][y].flags & TREE_SWARM));
|
||||
} else if (IS_FOUNTAIN(levl[x][y].typ)) {
|
||||
nhl_add_table_entry_bool(L, "looted", (levl[x][y].flags & F_LOOTED));
|
||||
nhl_add_table_entry_bool(L, "warned", (levl[x][y].flags & F_WARNED));
|
||||
} else if (IS_SINK(levl[x][y].typ)) {
|
||||
nhl_add_table_entry_bool(L, "pudding", (levl[x][y].flags & S_LPUDDING));
|
||||
nhl_add_table_entry_bool(L, "dishwasher", (levl[x][y].flags & S_LDWASHER));
|
||||
nhl_add_table_entry_bool(L, "ring", (levl[x][y].flags & S_LRING));
|
||||
}
|
||||
/* TODO: drawbridges, walls, ladders, room=>ICED_xxx */
|
||||
|
||||
lua_settable(L, -3);
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
/* TODO: return zerorm instead? */
|
||||
nhl_error(L, "Coordinates out of range");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
nhl_error(L, "Incorrect arguments");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* pline("It hits!") */
|
||||
static int
|
||||
nhl_pline(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1)
|
||||
pline("%s", luaL_checkstring(L, 1));
|
||||
else
|
||||
nhl_error(L, "Wrong args");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verbalize("Fool!") */
|
||||
static int
|
||||
nhl_verbalize(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1)
|
||||
verbalize("%s", luaL_checkstring(L, 1));
|
||||
else
|
||||
nhl_error(L, "Wrong args");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
str = getlin("What do you want to call this dungeon level?");
|
||||
*/
|
||||
static int
|
||||
nhl_getlin(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1) {
|
||||
const char *prompt = luaL_checkstring(L, 1);
|
||||
char buf[BUFSZ];
|
||||
|
||||
getlin(prompt, buf);
|
||||
lua_pushstring(L, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
nhl_error(L, "Wrong args");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
selected = menu("prompt", default, pickX, { "a" = "option a", "b" = "option b", ...})
|
||||
pickX = 0,1,2, or "none", "one", "any" (PICK_X in code)
|
||||
|
||||
selected = menu("prompt", default, pickX,
|
||||
{ {key:"a", text:"option a"}, {key:"b", text:"option b"}, ... } ) */
|
||||
static int
|
||||
nhl_menu(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
const char *prompt;
|
||||
const char *defval = "";
|
||||
const char *const pickX[] = {"none", "one", "any"}; /* PICK_NONE, PICK_ONE, PICK_ANY */
|
||||
int pick = PICK_ONE, pick_cnt;
|
||||
winid tmpwin;
|
||||
anything any;
|
||||
menu_item *picks = (menu_item *) 0;
|
||||
|
||||
if (argc < 2 || argc > 4) {
|
||||
nhl_error(L, "Wrong args");
|
||||
return 0;
|
||||
}
|
||||
|
||||
prompt = luaL_checkstring(L, 1);
|
||||
if (lua_isstring(L, 2))
|
||||
defval = luaL_checkstring(L, 2);
|
||||
if (lua_isstring(L, 3))
|
||||
pick = luaL_checkoption(L, 3, "one", pickX);
|
||||
luaL_checktype(L, argc, LUA_TTABLE);
|
||||
|
||||
tmpwin = create_nhwindow(NHW_MENU);
|
||||
start_menu(tmpwin);
|
||||
|
||||
lua_pushnil(L); /* first key */
|
||||
while (lua_next(L, argc) != 0) {
|
||||
const char *str = "";
|
||||
const char *key = "";
|
||||
|
||||
/* key @ index -2, value @ index -1 */
|
||||
if (lua_istable(L, -1)) {
|
||||
lua_pushliteral(L, "key");
|
||||
lua_gettable(L, -2);
|
||||
key = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_pushliteral(L, "text");
|
||||
lua_gettable(L, -2);
|
||||
str = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
/* TODO: glyph, attr, accel, group accel (all optional) */
|
||||
} else if (lua_isstring(L, -1)) {
|
||||
str = luaL_checkstring(L, -1);
|
||||
key = luaL_checkstring(L, -2);
|
||||
}
|
||||
|
||||
any = cg.zeroany;
|
||||
if (*key)
|
||||
any.a_char = key[0];
|
||||
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, str,
|
||||
(*defval && *key && defval[0] == key[0]) ? MENU_SELECTED : MENU_UNSELECTED);
|
||||
|
||||
lua_pop(L, 1); /* removes 'value'; keeps 'key' for next iteration */
|
||||
}
|
||||
|
||||
end_menu(tmpwin, prompt);
|
||||
pick_cnt = select_menu(tmpwin, pick, &picks);
|
||||
destroy_nhwindow(tmpwin);
|
||||
|
||||
if (pick_cnt > 0) {
|
||||
char buf[2];
|
||||
buf[0] = picks[0].item.a_char;
|
||||
|
||||
if (pick == PICK_ONE && pick_cnt > 1 && *defval && defval[0] == picks[0].item.a_char)
|
||||
buf[0] = picks[1].item.a_char;
|
||||
|
||||
buf[1] = '\0';
|
||||
lua_pushstring(L, buf);
|
||||
/* TODO: pick any */
|
||||
} else {
|
||||
char buf[2];
|
||||
buf[0] = defval[0];
|
||||
buf[1] = '\0';
|
||||
lua_pushstring(L, buf);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* makeplural("zorkmid") */
|
||||
static int
|
||||
nhl_makeplural(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1)
|
||||
lua_pushstring(L, makeplural(luaL_checkstring(L, 1)));
|
||||
else
|
||||
nhl_error(L, "Wrong args");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* makesingular("zorkmids") */
|
||||
static int
|
||||
nhl_makesingular(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1)
|
||||
lua_pushstring(L, makesingular(luaL_checkstring(L, 1)));
|
||||
else
|
||||
nhl_error(L, "Wrong args");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* s_suffix("foo") */
|
||||
static int
|
||||
nhl_s_suffix(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1)
|
||||
lua_pushstring(L, s_suffix(luaL_checkstring(L, 1)));
|
||||
else
|
||||
nhl_error(L, "Wrong args");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ing_suffix("foo") */
|
||||
static int
|
||||
nhl_ing_suffix(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1)
|
||||
lua_pushstring(L, ing_suffix(luaL_checkstring(L, 1)));
|
||||
else
|
||||
nhl_error(L, "Wrong args");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* an("foo") */
|
||||
static int
|
||||
nhl_an(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1)
|
||||
lua_pushstring(L, an(luaL_checkstring(L, 1)));
|
||||
else
|
||||
nhl_error(L, "Wrong args");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get mandatory integer value from table */
|
||||
int
|
||||
get_table_int(L, name)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
{
|
||||
int ret;
|
||||
|
||||
lua_getfield(L, 1, name);
|
||||
ret = (int) luaL_checkinteger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get optional integer value from table */
|
||||
int
|
||||
get_table_int_opt(L, name, defval)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
int defval;
|
||||
{
|
||||
int ret = defval;
|
||||
|
||||
lua_getfield(L, 1, name);
|
||||
if (!lua_isnil(L, -1)) {
|
||||
ret = (int) luaL_checkinteger(L, -1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
get_table_str(L, name)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
{
|
||||
char *ret;
|
||||
|
||||
lua_getfield(L, 1, name);
|
||||
ret = dupstr(luaL_checkstring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get optional string value from table.
|
||||
return value must be freed by caller. */
|
||||
char *
|
||||
get_table_str_opt(L, name, defval)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
char *defval;
|
||||
{
|
||||
const char *ret;
|
||||
|
||||
lua_getfield(L, 1, name);
|
||||
ret = luaL_optstring(L, -1, defval);
|
||||
lua_pop(L, 1);
|
||||
return ret ? dupstr(ret) : NULL;
|
||||
}
|
||||
|
||||
int
|
||||
get_table_boolean(L, name)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
{
|
||||
int ltyp;
|
||||
int ret = -1;
|
||||
|
||||
lua_getfield(L, 1, name);
|
||||
ltyp = lua_type(L, -1);
|
||||
if (ltyp == LUA_TSTRING) {
|
||||
const char *const boolstr[] = { "true", "false", "yes", "no", NULL };
|
||||
const int boolstr2i[] = { TRUE, FALSE, TRUE, FALSE, -1 };
|
||||
ret = luaL_checkoption(L, -1, NULL, boolstr);
|
||||
} else if (ltyp == LUA_TBOOLEAN) {
|
||||
ret = lua_toboolean(L, -1);
|
||||
} else if (ltyp == LUA_TNUMBER) {
|
||||
ret = (int) luaL_checkinteger(L, -1);
|
||||
if ( ret < 0 || ret > 1)
|
||||
ret = -1;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
if (ret == -1)
|
||||
nhl_error(L, "Expected a boolean");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
get_table_boolean_opt(L, name, defval)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
int defval;
|
||||
{
|
||||
int ret = defval;
|
||||
|
||||
lua_getfield(L, 1, name);
|
||||
if (lua_type(L, -1) != LUA_TNIL) {
|
||||
lua_pop(L, 1);
|
||||
return get_table_boolean(L, name);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
get_table_option(L, name, defval, opts)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
const char *defval;
|
||||
const char *const opts[]; /* NULL-terminated list */
|
||||
{
|
||||
int ret;
|
||||
|
||||
lua_getfield(L, 1, name);
|
||||
ret = luaL_checkoption(L, -1, defval, opts);
|
||||
lua_pop(L, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
test( { x = 123, y = 456 } );
|
||||
*/
|
||||
static int
|
||||
nhl_test(L)
|
||||
lua_State *L;
|
||||
{
|
||||
/* discard any extra arguments passed in */
|
||||
lua_settop(L, 1);
|
||||
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
int x = get_table_int(L, "x");
|
||||
int y = get_table_int(L, "y");
|
||||
char *name = get_table_str_opt(L, "name", "Player");
|
||||
|
||||
pline("TEST:{ x=%i, y=%i, name=\"%s\" }", x,y, name);
|
||||
|
||||
free(name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg nhl_functions[] = {
|
||||
{"test", nhl_test},
|
||||
|
||||
{"getmap", nhl_getmap},
|
||||
/*{"setmap", nhl_setmap},*/
|
||||
|
||||
{"pline", nhl_pline},
|
||||
{"verbalize", nhl_verbalize},
|
||||
{"menu", nhl_menu},
|
||||
{"getlin", nhl_getlin},
|
||||
|
||||
{"makeplural", nhl_makeplural},
|
||||
{"makesingular", nhl_makesingular},
|
||||
{"s_suffix", nhl_s_suffix},
|
||||
{"ing_suffix", nhl_ing_suffix},
|
||||
{"an", nhl_an},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
long value;
|
||||
} nhl_consts[] = {
|
||||
{ "COLNO", COLNO },
|
||||
{ "ROWNO", ROWNO },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
/* register and init the constants table */
|
||||
void
|
||||
init_nhc_data(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int i;
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
for (i = 0; nhl_consts[i].name; i++) {
|
||||
lua_pushstring(L, nhl_consts[i].name);
|
||||
lua_pushinteger(L, nhl_consts[i].value);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
lua_setglobal(L, "nhc");
|
||||
}
|
||||
|
||||
int
|
||||
nhl_push_anything(L, anytype, src)
|
||||
lua_State *L;
|
||||
int anytype;
|
||||
void *src;
|
||||
{
|
||||
anything any = cg.zeroany;
|
||||
switch (anytype) {
|
||||
case ANY_INT: any.a_int = *(int *)src; lua_pushinteger(L, any.a_int); break;
|
||||
case ANY_UCHAR: any.a_uchar = *(uchar *)src; lua_pushinteger(L, any.a_uchar); break;
|
||||
case ANY_SCHAR: any.a_schar = *(schar *)src; lua_pushinteger(L, any.a_schar); break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
nhl_meta_u_index(L)
|
||||
lua_State *L;
|
||||
{
|
||||
const char *tkey = luaL_checkstring(L, 2);
|
||||
const struct {
|
||||
const char *name;
|
||||
void *ptr;
|
||||
int type;
|
||||
} ustruct[] = {
|
||||
{ "ux", &(u.ux), ANY_UCHAR },
|
||||
{ "uy", &(u.uy), ANY_UCHAR },
|
||||
{ "dx", &(u.dx), ANY_SCHAR },
|
||||
{ "dy", &(u.dy), ANY_SCHAR },
|
||||
{ "dz", &(u.dz), ANY_SCHAR },
|
||||
{ "tx", &(u.tx), ANY_UCHAR },
|
||||
{ "ty", &(u.ty), ANY_UCHAR },
|
||||
{ "ulevel", &(u.ulevel), ANY_INT },
|
||||
{ "ulevelmax", &(u.ulevelmax), ANY_INT },
|
||||
{ "uhunger", &(u.uhunger), ANY_INT },
|
||||
{ "nv_range", &(u.nv_range), ANY_INT },
|
||||
{ "xray_range", &(u.xray_range), ANY_INT },
|
||||
{ "umonster", &(u.umonster), ANY_INT },
|
||||
{ "umonnum", &(u.umonnum), ANY_INT },
|
||||
{ "mh", &(u.mh), ANY_INT },
|
||||
{ "mhmax", &(u.mhmax), ANY_INT },
|
||||
{ "mtimedone", &(u.mtimedone), ANY_INT },
|
||||
};
|
||||
int i;
|
||||
|
||||
/* FIXME: doesn't really work, eg. negative values for u.dx */
|
||||
for (i = 0; i < SIZE(ustruct); i++)
|
||||
if (!strcmp(tkey, ustruct[i].name)) {
|
||||
return nhl_push_anything(L, ustruct[i].type, ustruct[i].ptr);
|
||||
}
|
||||
|
||||
nhl_error(L, "Unknown u table index");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nhl_meta_u_newindex(L)
|
||||
lua_State *L;
|
||||
{
|
||||
nhl_error(L, "Cannot set u table values");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
init_u_data(L)
|
||||
lua_State *L;
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_newtable(L);
|
||||
lua_pushcfunction(L, nhl_meta_u_index);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, nhl_meta_u_newindex);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "u");
|
||||
}
|
||||
|
||||
int
|
||||
nhl_set_package_path(L, path)
|
||||
lua_State *L;
|
||||
const char *path;
|
||||
{
|
||||
lua_getglobal(L, "package");
|
||||
lua_pushstring(L, path);
|
||||
lua_setfield(L, -2, "path");
|
||||
lua_pop(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
traceback_handler(L)
|
||||
lua_State *L;
|
||||
{
|
||||
luaL_traceback(L, L, lua_tostring(L, 1), 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
boolean
|
||||
nhl_loadlua(L, fname)
|
||||
lua_State *L;
|
||||
const char *fname;
|
||||
{
|
||||
boolean ret = TRUE;
|
||||
dlb *fh;
|
||||
char *buf = (char *) 0;
|
||||
long buflen;
|
||||
int c, llret;
|
||||
long bufidx = 0;
|
||||
|
||||
fh = dlb_fopen(fname, "r");
|
||||
if (!fh) {
|
||||
impossible("nhl_loadlua: Error loading %s", fname);
|
||||
ret = FALSE;
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
dlb_fseek(fh, 0L, SEEK_END);
|
||||
buflen = dlb_ftell(fh);
|
||||
buf = (char *) alloc(sizeof(char) * (buflen + 1));
|
||||
if (!buf) {
|
||||
impossible("alloc: Error allocating %i bytes for loading lua file %s", buflen, fname);
|
||||
ret = FALSE;
|
||||
goto give_up;
|
||||
}
|
||||
dlb_fseek(fh, 0L, SEEK_SET);
|
||||
|
||||
do {
|
||||
c = dlb_fgetc(fh);
|
||||
if (c == EOF)
|
||||
break;
|
||||
buf[bufidx++] = (char) c;
|
||||
} while (bufidx < buflen);
|
||||
buf[bufidx] = '\0';
|
||||
(void) dlb_fclose(fh);
|
||||
|
||||
llret = luaL_loadstring(L, buf);
|
||||
if (llret != LUA_OK) {
|
||||
impossible("luaL_loadstring: Error loading %s (errcode %i)", fname, llret);
|
||||
ret = FALSE;
|
||||
goto give_up;
|
||||
} else {
|
||||
lua_pushcfunction(L, traceback_handler);
|
||||
lua_insert(L, 1);
|
||||
if (lua_pcall(L, 0, LUA_MULTRET, -2)) {
|
||||
impossible("Lua error: %s", lua_tostring(L, -1));
|
||||
ret = FALSE;
|
||||
goto give_up;
|
||||
}
|
||||
}
|
||||
|
||||
give_up:
|
||||
if (buf) {
|
||||
free(buf);
|
||||
buf = (char *) 0;
|
||||
buflen = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
boolean
|
||||
load_lua(name)
|
||||
const char *name;
|
||||
{
|
||||
boolean ret = TRUE;
|
||||
lua_State *L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
|
||||
nhl_set_package_path(L, "./?.lua");
|
||||
|
||||
/* register nh -table, and functions for it */
|
||||
lua_newtable(L);
|
||||
luaL_setfuncs(L, nhl_functions, 0);
|
||||
lua_setglobal(L, "nh");
|
||||
|
||||
/* init nhc -table */
|
||||
init_nhc_data(L);
|
||||
|
||||
/* init u -table */
|
||||
init_u_data(L);
|
||||
|
||||
l_selection_register(L);
|
||||
l_register_des(L);
|
||||
|
||||
if (!nhl_loadlua(L, "nhlib.lua")) {
|
||||
ret = FALSE;
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
if (!nhl_loadlua(L, name)) {
|
||||
ret = FALSE;
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
give_up:
|
||||
lua_close(L);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -662,10 +662,14 @@ xchar lev;
|
||||
saveobjchn(nhfp, g.billobjs);
|
||||
if (release_data(nhfp)) {
|
||||
int x,y;
|
||||
|
||||
/* TODO: maybe use clear_level_structures() */
|
||||
for (y = 0; y < ROWNO; y++)
|
||||
for (x = 0; x < COLNO; x++)
|
||||
for (x = 0; x < COLNO; x++) {
|
||||
g.level.monsters[x][y] = 0;
|
||||
g.level.objects[x][y] = 0;
|
||||
levl[x][y].seenv = 0;
|
||||
levl[x][y].glyph = cmap_to_glyph(S_stone);
|
||||
}
|
||||
fmon = 0;
|
||||
g.ftrap = 0;
|
||||
fobj = 0;
|
||||
|
||||
4690
src/sp_lev.c
4690
src/sp_lev.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user