Lua NetHack obj bindings
This commit is contained in:
@@ -1671,6 +1671,11 @@ E struct selectionvar *FDECL(l_selection_check, (lua_State *, int));
|
||||
E int FDECL(l_selection_register, (lua_State *));
|
||||
#endif
|
||||
|
||||
/* ### nhlobj.c ### */
|
||||
#if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET)
|
||||
E int FDECL(l_obj_register, (lua_State *));
|
||||
#endif
|
||||
|
||||
/* ### nhlua.c ### */
|
||||
|
||||
#if !defined(CROSSCOMPILE) || defined(CROSSCOMPILE_TARGET)
|
||||
@@ -1681,6 +1686,9 @@ E void FDECL(nhl_error, (lua_State *, const char *)) NORETURN;
|
||||
E void FDECL(lcheck_param_table, (lua_State *));
|
||||
E schar FDECL(get_table_mapchr, (lua_State *, const char *));
|
||||
E schar FDECL(get_table_mapchr_opt, (lua_State *, const char *, SCHAR_P));
|
||||
E void FDECL(nhl_add_table_entry_int, (lua_State *, const char *, int));
|
||||
E void FDECL(nhl_add_table_entry_char, (lua_State *, const char *, CHAR_P));
|
||||
E void FDECL(nhl_add_table_entry_str, (lua_State *, const char *, const char *));
|
||||
E schar FDECL(splev_chr2typ, (CHAR_P));
|
||||
E schar FDECL(check_mapchr, (const char *));
|
||||
E int FDECL(get_table_int, (lua_State *, const char *));
|
||||
|
||||
356
src/nhlobj.c
Normal file
356
src/nhlobj.c
Normal file
@@ -0,0 +1,356 @@
|
||||
/* NetHack 3.7 nhlobj.c $NHDT-Date: 1574646948 2019/11/25 01:55:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.4 $ */
|
||||
/* Copyright (c) 2019 by Pasi Kallinen */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
#include "hack.h"
|
||||
#include "sp_lev.h"
|
||||
|
||||
struct _lua_obj {
|
||||
int state; /* UNUSED */
|
||||
struct obj *obj;
|
||||
};
|
||||
|
||||
struct _lua_obj *
|
||||
l_obj_check(L, index)
|
||||
lua_State *L;
|
||||
int index;
|
||||
{
|
||||
struct _lua_obj *lo;
|
||||
|
||||
luaL_checktype(L, index, LUA_TUSERDATA);
|
||||
lo = (struct _lua_obj *)luaL_checkudata(L, index, "obj");
|
||||
if (!lo)
|
||||
nhl_error(L, "Obj error");
|
||||
return lo;
|
||||
}
|
||||
|
||||
static int
|
||||
l_obj_gc(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||
|
||||
if (lo && lo->obj) {
|
||||
/* free-floating objects are deallocated */
|
||||
if (lo->obj->where == OBJ_FREE) {
|
||||
if (Has_contents(lo->obj)) {
|
||||
struct obj *otmp;
|
||||
while ((otmp = lo->obj->cobj) != 0) {
|
||||
obj_extract_self(otmp);
|
||||
dealloc_obj(otmp);
|
||||
}
|
||||
}
|
||||
dealloc_obj(lo->obj);
|
||||
}
|
||||
lo->obj = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct _lua_obj *
|
||||
l_obj_push(L, otmp)
|
||||
lua_State *L;
|
||||
struct obj *otmp;
|
||||
{
|
||||
struct _lua_obj *lo = (struct _lua_obj *)lua_newuserdata(L, sizeof(struct _lua_obj));
|
||||
luaL_getmetatable(L, "obj");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
lo->state = 0;
|
||||
lo->obj = otmp;
|
||||
|
||||
return lo;
|
||||
}
|
||||
|
||||
/* local o = obj.new("large chest");
|
||||
local cobj = o:contents(); */
|
||||
static int
|
||||
l_obj_getcontents(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||
struct obj *obj = lo->obj;
|
||||
|
||||
if (!obj)
|
||||
nhl_error(L, "l_obj_getcontents: no obj");
|
||||
if (!obj->cobj)
|
||||
nhl_error(L, "l_obj_getcontents: no cobj");
|
||||
|
||||
(void) l_obj_push(L, obj->cobj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* local box = obj.new("large chest");
|
||||
box.addcontent(obj.new("rock"));
|
||||
*/
|
||||
static int
|
||||
l_obj_add_to_container(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct _lua_obj *lobox = l_obj_check(L, 1);
|
||||
struct _lua_obj *lo = l_obj_check(L, 2);
|
||||
struct obj *otmp;
|
||||
|
||||
if (!lo->obj || !lobox->obj)
|
||||
nhl_error(L, "l_obj_add_to_container: no obj");
|
||||
|
||||
if (!Is_container(lobox->obj))
|
||||
nhl_error(L, "l_obj_add_to_container: not a container");
|
||||
|
||||
otmp = add_to_container(lobox->obj, lo->obj);
|
||||
|
||||
/* was lo->obj merged? FIXME: causes problems if both lo->obj and
|
||||
the one it merged with are handled by lua. Use lo->state? */
|
||||
if (otmp != lo->obj)
|
||||
lo->obj = otmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a lua table representation of the object, unpacking all the object fields.
|
||||
local o = obj.new("rock");
|
||||
local otbl = o:totable(); */
|
||||
static int
|
||||
l_obj_to_table(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||
struct obj *obj = lo->obj;
|
||||
char buf[BUFSZ];
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
if (!obj) {
|
||||
nhl_add_table_entry_int(L, "NO_OBJ", 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
nhl_add_table_entry_int(L, "has_contents", Has_contents(obj));
|
||||
nhl_add_table_entry_int(L, "is_container", Is_container(obj));
|
||||
nhl_add_table_entry_int(L, "o_id", obj->o_id);
|
||||
nhl_add_table_entry_int(L, "ox", obj->ox);
|
||||
nhl_add_table_entry_int(L, "oy", obj->oy);
|
||||
nhl_add_table_entry_int(L, "otyp", obj->otyp);
|
||||
if (OBJ_NAME(objects[obj->otyp]))
|
||||
nhl_add_table_entry_str(L, "otyp_name", OBJ_NAME(objects[obj->otyp]));
|
||||
if (OBJ_DESCR(objects[obj->otyp]))
|
||||
nhl_add_table_entry_str(L, "otyp_descr", OBJ_DESCR(objects[obj->otyp]));
|
||||
nhl_add_table_entry_int(L, "owt", obj->owt);
|
||||
nhl_add_table_entry_int(L, "quan", obj->quan);
|
||||
nhl_add_table_entry_int(L, "spe", obj->spe);
|
||||
nhl_add_table_entry_char(L, "oclass", def_oc_syms[obj->oclass].sym);
|
||||
nhl_add_table_entry_char(L, "invlet", obj->invlet);
|
||||
/* TODO: nhl_add_table_entry_char(L, "oartifact", obj->oartifact);*/
|
||||
nhl_add_table_entry_int(L, "where", obj->where);
|
||||
/* TODO: nhl_add_table_entry_int(L, "timed", obj->timed); */
|
||||
nhl_add_table_entry_int(L, "cursed", obj->cursed);
|
||||
nhl_add_table_entry_int(L, "blessed", obj->blessed);
|
||||
nhl_add_table_entry_int(L, "unpaid", obj->unpaid);
|
||||
nhl_add_table_entry_int(L, "no_charge", obj->no_charge);
|
||||
nhl_add_table_entry_int(L, "known", obj->known);
|
||||
nhl_add_table_entry_int(L, "dknown", obj->dknown);
|
||||
nhl_add_table_entry_int(L, "bknown", obj->bknown);
|
||||
nhl_add_table_entry_int(L, "rknown", obj->rknown);
|
||||
if (obj->oclass == POTION_CLASS)
|
||||
nhl_add_table_entry_int(L, "odiluted", obj->odiluted);
|
||||
else
|
||||
nhl_add_table_entry_int(L, "oeroded", obj->oeroded);
|
||||
nhl_add_table_entry_int(L, "oeroded2", obj->oeroded2);
|
||||
/* TODO: orotten, norevive */
|
||||
nhl_add_table_entry_int(L, "oerodeproof", obj->oerodeproof);
|
||||
nhl_add_table_entry_int(L, "olocked", obj->olocked);
|
||||
nhl_add_table_entry_int(L, "obroken", obj->obroken);
|
||||
if (is_poisonable(obj))
|
||||
nhl_add_table_entry_int(L, "opoisoned", obj->opoisoned);
|
||||
else
|
||||
nhl_add_table_entry_int(L, "otrapped", obj->otrapped);
|
||||
/* TODO: degraded_horn */
|
||||
nhl_add_table_entry_int(L, "recharged", obj->recharged);
|
||||
/* TODO: on_ice */
|
||||
nhl_add_table_entry_int(L, "lamplit", obj->lamplit);
|
||||
nhl_add_table_entry_int(L, "globby", obj->globby);
|
||||
nhl_add_table_entry_int(L, "greased", obj->greased);
|
||||
nhl_add_table_entry_int(L, "nomerge", obj->nomerge);
|
||||
nhl_add_table_entry_int(L, "was_thrown", obj->was_thrown);
|
||||
nhl_add_table_entry_int(L, "in_use", obj->in_use);
|
||||
nhl_add_table_entry_int(L, "bypass", obj->bypass);
|
||||
nhl_add_table_entry_int(L, "cknown", obj->cknown);
|
||||
nhl_add_table_entry_int(L, "lknown", obj->lknown);
|
||||
nhl_add_table_entry_int(L, "corpsenm", obj->corpsenm);
|
||||
if (obj->corpsenm != NON_PM && (obj->otyp == TIN || obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == FIGURINE || obj->otyp == STATUE))
|
||||
nhl_add_table_entry_str(L, "corpsenm_name", mons[obj->corpsenm].mname);
|
||||
/* TODO: leashmon, fromsink, novelidx, record_achieve_special */
|
||||
nhl_add_table_entry_int(L, "usecount", obj->usecount);
|
||||
/* TODO: spestudied */
|
||||
nhl_add_table_entry_int(L, "oeaten", obj->oeaten);
|
||||
nhl_add_table_entry_int(L, "age", obj->age);
|
||||
nhl_add_table_entry_int(L, "owornmask", obj->owornmask);
|
||||
/* TODO: more of oextra */
|
||||
nhl_add_table_entry_int(L, "has_oname", has_oname(obj));
|
||||
if (has_oname(obj))
|
||||
nhl_add_table_entry_str(L, "oname", ONAME(obj));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* create a new object via wishing routine */
|
||||
/* local o = obj.new("rock"); */
|
||||
static int
|
||||
l_obj_new_readobjnam(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 1) {
|
||||
char buf[BUFSZ];
|
||||
struct obj *otmp;
|
||||
Sprintf(buf, "%s", luaL_checkstring(L, 1));
|
||||
lua_pop(L, 1);
|
||||
otmp = readobjnam(buf, NULL);
|
||||
(void) l_obj_push(L, otmp);
|
||||
return 1;
|
||||
} else
|
||||
nhl_error(L, "l_obj_new_readobjname: Wrong args");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the topmost object on the map at x,y */
|
||||
/* local o = obj.at(x, y); */
|
||||
static int
|
||||
l_obj_at(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc == 2) {
|
||||
int x, y;
|
||||
x = luaL_checkinteger(L, 1);
|
||||
y = luaL_checkinteger(L, 2);
|
||||
lua_pop(L, 2);
|
||||
(void) l_obj_push(L, g.level.objects[x][y]);
|
||||
return 1;
|
||||
} else
|
||||
nhl_error(L, "l_obj_at: Wrong args");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Place an object on the map at (x,y).
|
||||
local o = obj.new("rock");
|
||||
o:placeobj(u.ux, u.uy); */
|
||||
static int
|
||||
l_obj_placeobj(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||
|
||||
if (argc != 3)
|
||||
nhl_error(L, "l_obj_placeobj: Wrong args");
|
||||
|
||||
if (lo && lo->obj) {
|
||||
int x, y;
|
||||
x = luaL_checkinteger(L, 2);
|
||||
y = luaL_checkinteger(L, 3);
|
||||
lua_pop(L, 3);
|
||||
|
||||
place_object(lo->obj, x, y);
|
||||
} else
|
||||
nhl_error(L, "l_obj_placeobj: Wrong args");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the next object in the object chain */
|
||||
/* local o = obj.at(x, y);
|
||||
local o2 = o:next();
|
||||
*/
|
||||
static int
|
||||
l_obj_nextobj(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||
|
||||
if (lo && lo->obj)
|
||||
(void) l_obj_push(L, lo->obj->where == OBJ_FLOOR ? lo->obj->nexthere : lo->obj->nobj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the container object is in */
|
||||
/* local box = o:container(); */
|
||||
static int
|
||||
l_obj_container(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||
|
||||
if (lo && lo->obj && lo->obj->where == OBJ_CONTAINED) {
|
||||
(void) l_obj_push(L, lo->obj->ocontainer);
|
||||
return 1;
|
||||
}
|
||||
(void) l_obj_push(L, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Is the object a null? */
|
||||
/* local badobj = o:isnull(); */
|
||||
static int
|
||||
l_obj_isnull(L)
|
||||
lua_State *L;
|
||||
{
|
||||
struct _lua_obj *lo = l_obj_check(L, 1);
|
||||
|
||||
lua_pushboolean(L, lo && lo->obj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const struct luaL_Reg l_obj_methods[] = {
|
||||
{ "new", l_obj_new_readobjnam },
|
||||
{ "isnull", l_obj_isnull },
|
||||
{ "at", l_obj_at },
|
||||
{ "next", l_obj_nextobj },
|
||||
{ "totable", l_obj_to_table },
|
||||
{ "placeobj", l_obj_placeobj },
|
||||
{ "container", l_obj_container },
|
||||
{ "contents", l_obj_getcontents },
|
||||
{ "addcontent", l_obj_add_to_container },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const luaL_Reg l_obj_meta[] = {
|
||||
{ "__gc", l_obj_gc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
l_obj_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, "obj");
|
||||
meta_id = lua_gettop(L);
|
||||
luaL_setfuncs(L, l_obj_meta, 0);
|
||||
|
||||
/* metatable.__index = _methods */
|
||||
luaL_newlib(L, l_obj_methods);
|
||||
lua_setfield(L, meta_id, "__index");
|
||||
|
||||
/* metatable.__metatable = _meta */
|
||||
luaL_newlib(L, l_obj_meta);
|
||||
lua_setfield(L, meta_id, "__metatable");
|
||||
|
||||
/* class.__metatable = metatable */
|
||||
lua_setmetatable(L, lib_id);
|
||||
|
||||
/* _G["obj"] = newclass */
|
||||
lua_setglobal(L, "obj");
|
||||
|
||||
return 0;
|
||||
}
|
||||
15
src/nhlua.c
15
src/nhlua.c
@@ -114,6 +114,19 @@ int value;
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
void
|
||||
nhl_add_table_entry_char(L, name, value)
|
||||
lua_State *L;
|
||||
const char *name;
|
||||
char value;
|
||||
{
|
||||
char buf[2];
|
||||
Sprintf(buf, "%c", value);
|
||||
lua_pushstring(L, name);
|
||||
lua_pushstring(L, buf);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
void
|
||||
nhl_add_table_entry_str(L, name, value)
|
||||
lua_State *L;
|
||||
@@ -874,6 +887,8 @@ nhl_init()
|
||||
l_selection_register(L);
|
||||
l_register_des(L);
|
||||
|
||||
l_obj_register(L);
|
||||
|
||||
if (!nhl_loadlua(L, "nhlib.lua")) {
|
||||
lua_close(L);
|
||||
return (lua_State *) 0;
|
||||
|
||||
@@ -316,7 +316,7 @@ SOBJ = $(O)msdos.o $(O)pcsys.o $(O)tty.o $(O)unix.o \
|
||||
VVOBJ = $(O)version.o
|
||||
|
||||
ifeq "$(ADD_LUA)" "Y"
|
||||
LUAOBJ = $(O)nhlua.o $(O)nhlsel.o
|
||||
LUAOBJ = $(O)nhlua.o $(O)nhlsel.o $(O)nhlobj.o
|
||||
LUA_QTEXT_FILE = "quest.lua"
|
||||
endif
|
||||
|
||||
@@ -1454,6 +1454,7 @@ $(O)muse.o: muse.c $(HACK_H)
|
||||
$(O)music.o: music.c $(HACK_H) #interp.c
|
||||
$(O)nhlua.o: nhlua.c $(HACK_H)
|
||||
$(O)nhlsel.o: nhlsel.c $(HACK_H)
|
||||
$(O)nhlobj.o: nhlobj.c $(HACK_H)
|
||||
$(O)o_init.o: o_init.c $(HACK_H) $(INCL)/lev.h
|
||||
$(O)objects.o: objects.c $(CONFIG_H) $(INCL)/obj.h $(INCL)/objclass.h \
|
||||
$(INCL)/prop.h $(INCL)/skills.h $(INCL)/color.h
|
||||
|
||||
@@ -320,7 +320,7 @@ VVOBJ = $(O)version.o
|
||||
MDLIB = $(O)mdlib.o
|
||||
|
||||
ifeq "$(ADD_LUA)" "Y"
|
||||
LUAOBJ = $(O)nhlua.o $(O)nhlsel.o
|
||||
LUAOBJ = $(O)nhlua.o $(O)nhlsel.o $(O)nhlobj.o
|
||||
LUA_QTEXT_FILE = "quest.lua"
|
||||
endif
|
||||
|
||||
|
||||
@@ -449,7 +449,7 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \
|
||||
lock.c mail.c makemon.c mapglyph.c mcastu.c mdlib.c mhitm.c \
|
||||
mhitu.c minion.c mklev.c mkmap.c mkmaze.c mkobj.c mkroom.c mon.c \
|
||||
mondata.c monmove.c monst.c mplayer.c mthrowu.c muse.c music.c \
|
||||
nhlua.c nhlsel.c o_init.c objects.c objnam.c \
|
||||
nhlua.c nhlsel.c nhlobj.c o_init.c objects.c objnam.c \
|
||||
options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \
|
||||
priest.c quest.c questpgr.c read.c rect.c region.c restore.c \
|
||||
rip.c rnd.c role.c rumors.c save.c sfstruct.c \
|
||||
@@ -516,7 +516,7 @@ HOBJ = $(FIRSTOBJ) allmain.o alloc.o apply.o artifact.o attrib.o ball.o \
|
||||
light.o lock.o mail.o makemon.o mapglyph.o mcastu.o mdlib.o mhitm.o \
|
||||
mhitu.o minion.o mklev.o mkmap.o mkmaze.o mkobj.o mkroom.o mon.o \
|
||||
mondata.o monmove.o mplayer.o mthrowu.o muse.o music.o \
|
||||
nhlua.o nhlsel.o o_init.o objnam.o options.o \
|
||||
nhlua.o nhlsel.o nhlobj.o o_init.o objnam.o options.o \
|
||||
pager.o pickup.o pline.o polyself.o potion.o pray.o priest.o \
|
||||
quest.o questpgr.o read.o rect.o region.o restore.o rip.o rnd.o \
|
||||
role.o rumors.o save.o sfstruct.o \
|
||||
|
||||
@@ -327,7 +327,7 @@ VOBJ28 = $(O)sfstruct.o
|
||||
#VOBJ31 = $(O)win10.o
|
||||
|
||||
ifeq "$(ADD_LUA)" "Y"
|
||||
LUAOBJ = $(O)nhlua.o $(O)nhlsel.o
|
||||
LUAOBJ = $(O)nhlua.o $(O)nhlsel.o $(O)nhlobj.o
|
||||
LUA_QTEXT_FILE = "quest.lua"
|
||||
endif
|
||||
|
||||
@@ -1593,6 +1593,7 @@ $(O)muse.o: muse.c $(HACK_H)
|
||||
$(O)music.o: music.c $(HACK_H) #interp.c
|
||||
$(O)nhlua.o: nhlua.c $(HACK_H)
|
||||
$(O)nhlsel.o: nhlsel.c $(HACK_H)
|
||||
$(O)nhlobj.o: nhlobj.c $(HACK_H)
|
||||
$(O)o_init.o: o_init.c $(HACK_H) $(INCL)/lev.h
|
||||
$(O)objects.o: objects.c $(CONFIG_H) $(INCL)/obj.h $(INCL)/objclass.h \
|
||||
$(INCL)/prop.h $(INCL)/skills.h $(INCL)/color.h
|
||||
|
||||
@@ -327,7 +327,7 @@ VOBJ26 = $(O)were.o $(O)wield.o $(O)windows.o $(O)wizard.o
|
||||
VOBJ27 = $(O)worm.o $(O)worn.o $(O)write.o $(O)zap.o
|
||||
VOBJ28 = $(O)sfstruct.o
|
||||
|
||||
LUAOBJ = $(O)nhlua.o $(O)nhlsel.o
|
||||
LUAOBJ = $(O)nhlua.o $(O)nhlsel.o $(O)nhlobj.o
|
||||
LUA_QTEXT_FILE = "quest.lua"
|
||||
|
||||
!IFDEF CROSSCOMPILE_HOST
|
||||
@@ -1882,6 +1882,7 @@ $(O)muse.o: muse.c $(HACK_H)
|
||||
$(O)music.o: music.c $(HACK_H) #interp.c
|
||||
$(O)nhlua.o: nhlua.c $(HACK_H)
|
||||
$(O)nhlsel.o: nhlsel.c $(HACK_H)
|
||||
$(O)nhlobj.o: nhlobj.c $(HACK_H)
|
||||
$(O)o_init.o: o_init.c $(HACK_H) $(INCL)\lev.h
|
||||
$(O)objnam.o: objnam.c $(HACK_H)
|
||||
$(O)options.o: options.c $(CONFIG_H) $(INCL)\objclass.h $(INCL)\flag.h \
|
||||
|
||||
41
test/test_obj.lua
Normal file
41
test/test_obj.lua
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
local o = obj.new("rock");
|
||||
o:placeobj(u.ux, u.uy);
|
||||
|
||||
local o2 = obj.at(u.ux, u.uy);
|
||||
local o2tbl = o2:totable();
|
||||
if (o2tbl.otyp_name ~= "rock") then
|
||||
error("no rock under you");
|
||||
end
|
||||
|
||||
|
||||
local box = obj.new("empty large box");
|
||||
local boxtbl = box:totable();
|
||||
if (boxtbl.has_contents ~= 0) then
|
||||
error("empty box has contents");
|
||||
end
|
||||
|
||||
box:addcontent(obj.new("diamond"));
|
||||
boxtbl = box:totable();
|
||||
if (boxtbl.has_contents ~= 1) then
|
||||
error("box has no contents");
|
||||
end
|
||||
|
||||
local diamond = box:contents():totable();
|
||||
if (diamond.otyp_name ~= "diamond") then
|
||||
error("box contents is not a diamond");
|
||||
end
|
||||
|
||||
box:placeobj(u.ux, u.uy);
|
||||
|
||||
local o3 = obj.at(u.ux, u.uy);
|
||||
local o3tbl = o3:totable();
|
||||
if (o3tbl.otyp_name ~= "large box") then
|
||||
error("no large box under you");
|
||||
end
|
||||
|
||||
local o4 = o3:next();
|
||||
local o4tbl = o4:totable();
|
||||
if (o4tbl.otyp_name ~= "rock") then
|
||||
error("no rock under the large box");
|
||||
end
|
||||
47
test/testwish.lua
Normal file
47
test/testwish.lua
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
local wishtest_objects = {
|
||||
["a rock"] = { otyp_name = "rock", quan = 1, oclass = "*" },
|
||||
["5 +3 blessed silver daggers"] = { otyp_name = "silver dagger", blessed = 1, cursed = 0, spe = 3, quan = 5 },
|
||||
["an empty locked large box"] = { otyp_name = "large box", is_container = 1, has_contents = 0, olocked = 1 },
|
||||
["potion of holy water"] = { otyp_name = "water", oclass = "!", blessed = 1, cursed = 0 },
|
||||
["potion of unholy water"] = { otyp_name = "water", oclass = "!", blessed = 0, cursed = 1 },
|
||||
["cursed greased +2 grey dragon scale mail"] = { otyp_name = "gray dragon scale mail", oclass = "[", blessed = 0, cursed = 1, spe = 2, greased = 1 },
|
||||
["uncursed magic marker (11)"] = { otyp_name = "magic marker", blessed = 0, cursed = 0, spe = 11 },
|
||||
["lit oil lamp"] = { otyp_name = "oil lamp", lamplit = 1 },
|
||||
["unlit oil lamp"] = { otyp_name = "oil lamp", lamplit = 0 },
|
||||
["2 blank scrolls"] = { otyp_name = "blank paper", quan = 2 },
|
||||
["3 rusty poisoned darts"] = { otyp_name = "dart", quan = 3, opoisoned = 1, oeroded = 1 },
|
||||
["broken empty chest"] = { otyp_name = "chest", obroken = 1 },
|
||||
["4 diluted dark green potions named whisky"] = { otyp_descr = "dark green", oclass = "!", quan = 4, odiluted = 1, has_oname = 1, oname = "whisky" },
|
||||
["poisoned food ration"] = { otyp_name = "food ration", oclass = "%", age = 1 },
|
||||
["empty tin"] = { otyp_name = "tin", oclass = "%", corpsenm = -1, spe = 0 },
|
||||
["blessed tin of spinach"] = { otyp_name = "tin", oclass = "%", corpsenm = -1, spe = 1, blessed = 1 },
|
||||
["trapped tin of floating eye meat"] = { otyp_name = "tin", oclass = "%", otrapped = 1, corpsenm_name = "floating eye" },
|
||||
["hill orc corpse"] = { otyp_name = "corpse", oclass = "%", corpsenm_name = "hill orc" },
|
||||
["destroy armor"] = { otyp_name = "destroy armor", oclass = "?" },
|
||||
["enchant weapon"] = { otyp_name = "enchant weapon", oclass = "?" },
|
||||
["scroll of food detection"] = { otyp_name = "food detection", oclass = "?" },
|
||||
["scroll of detect food"] = { otyp_name = "food detection", oclass = "?" },
|
||||
["spellbook of food detection"] = { otyp_name = "detect food", oclass = "+" },
|
||||
["spell"] = { NO_OBJ = 1 },
|
||||
["-1 ring mail"] = { otyp_name = "ring mail", oclass = "[", spe = -1 },
|
||||
["studded leather armor"] = { otyp_name = "studded leather armor", oclass = "[" },
|
||||
["leather armor"] = { otyp_name = "leather armor", oclass = "[" },
|
||||
["tooled horn"] = { otyp_name = "tooled horn", oclass = "(" },
|
||||
["meat ring"] = { otyp_name = "meat ring", oclass = "%" },
|
||||
["beartrap"] = { otyp_name = "beartrap", oclass = "(" },
|
||||
["bear trap"] = { otyp_name = "beartrap", oclass = "(" },
|
||||
["landmine"] = { otyp_name = "land mine", oclass = "(" },
|
||||
["land mine"] = { otyp_name = "land mine", oclass = "(" },
|
||||
-- ["partly eaten orange"] = { otyp_descr = "orange", oclass = "%", oeaten = ... },
|
||||
};
|
||||
|
||||
|
||||
for str, tbl in pairs(wishtest_objects) do
|
||||
local o = obj.new(str):totable();
|
||||
for field, value in pairs(tbl) do
|
||||
if (o[field] ~= value) then
|
||||
error("wished " .. str .. ", but " .. field .. " is " .. o[field] .. ", not " .. value);
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user