Specifically, item and monster-related functions to l_dgnit.cc and l_dgnmon.cc.
RXYHE3C7R3EGCRZEJT2ZO4ALLRDR3HF66VHZZNF7TT3DFWZ6BJCQC
34O32STE6HBHCGJASFVZ77CZ7ZH4WPWH53U7YBHJ3DHJZEZKOUOQC
63CAVB2MMXOQHGV2N7B5AE2HJKBPPSBKJDLX3EGKEZN52KUIWPQQC
A2JHMM2QW2Q5OZ4DY4N3VIT53SOPTI434NJB72XBMJD67YJRI4CQC
LE5U6CTXEIETQN5GOVYF2K2VCISRXR3ULORXDKIKWYDVBG5GS3WAC
RJIGO3YE7LKSLASPVA7K6CNWJAPKXD7ENJDURI5GXBGIEXFBBINAC
MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC
O6QYS2KYXUXMODO3X4SYX7SPZE7AOIFT2XJZHRABMMQFEUN4UXLAC
3A5FX3Y4RPKWQEHKKXZKXZJ7RKV6RKWT7GTR4WFE5UBWKV2HT4RQC
UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
ED62QWGKBPORWVKDFOQRKJXEIWZVNGR3O4KWQBDSRNPT36AYOQYAC
AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC
ZLQAAP55CJ77XIJN3DZVPT4GTTVLIBFJLIJJKI6L5UBSHX7VUK6AC
NKONHW4JNY6HP2M63MNPM3H64ZWSUNUT5FX2STW4KTS4AMXJXXVQC
55PFDYPVE6JVGDYPCFUE4XS2523PVSV4CSIFRW6A2GGX4I6VWRWQC
QAXFREFPBXN7YIBORITM2TAGA4QYF43XMSCLWW2BHONZFGEGMRUQC
SM6YRPYZS6LMDQA6X3VAOK2PGMUFKPD7JMWJISOQSMX2CBR4ISPAC
JTTHP2BEYEPBQMSDM7IKANTMKRPY6ACGL2JN4D3OBZ7HFXKAYEGQC
RGHXFBNIULRVRYLBGG5JZDMYVM2E2JJ2Y5KQPMU6PUS3V26G6ZXQC
ASLW3Z5PAVZSWJEMMMVZT226P44EKSAD47QS72JIFJESAI3RPN3AC
EIZC76IFTDKBNDJOX6YPFBOAOVAY6RSXH3JUWFLLGCZ3PYJMW3GQC
B3SRWSFITQMJRVEBHGQQJARETYPSSDV6XKMQSSUTXEHTXRZKIQJQC
C22455VGUQOSUX2OORA32LROFQ7NNYDMD2ZDTTUZSAQLXK4AD6QAC
GURIAIJVY6LEADNBTZF3SFBLODYJHWD6OGWFMUGEDI4L5KYO7UFAC
WEPYKUZS5NJG5NHBVK5IKE55VD3EOK42JUSURMBTU4MG4SBM5ILQC
7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC
IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC
TLA5UN6LZPXGKERI27EFY4HKIIU3VU5Y7ZU54WXL6ANBUV2VOTMQC
OMAUFQNBWGX4FDABHQCVPGDYRVKMDASGQJVRH7AOPPEMHAP2LQSQC
X7MFMKQTNZ2IWBFVGS6WQV7NRNKJ3DWQAW2X7IQMFQQXW24AHPZQC
UXAYLVZCSKTOC23AZORWJBQWYXKWC6QD2FPV2DRG7G6J5S7U2QLAC
Q2NUCKXB4P7DHRXY764F5AMEJO436GV74AVVVOAVGNWKLMSVMDNQC
#endif
/*
* File: l_dgnmon.cc
* Summary: Monster-related functions in lua library "dgn".
*/
#include "AppHdr.h"
#include "dlua.h"
#include "l_libs.h"
#include "dungeon.h"
#include "mapdef.h"
#include "mon-util.h"
#include "monplace.h"
#include "monstuff.h"
#define MONSLIST_METATABLE "crawldgn.monster_list"
static mons_list _lua_get_mlist(lua_State *ls, int ndx)
{
if (lua_isstring(ls, ndx))
{
const char *spec = lua_tostring(ls, ndx);
mons_list mlist;
const std::string err = mlist.add_mons(spec);
if (!err.empty())
luaL_error(ls, err.c_str());
return (mlist);
}
else
{
mons_list **mlist =
clua_get_userdata<mons_list*>(ls, MONSLIST_METATABLE, ndx);
if (mlist)
return (**mlist);
luaL_argerror(ls, ndx, "Expected monster list object or string");
return mons_list();
}
}
void register_monslist(lua_State *ls)
{
clua_register_metatable(ls, MONSLIST_METATABLE, NULL,
lua_object_gc<mons_list>);
}
static int dgn_set_random_mon_list(lua_State *ls)
{
// Don't complain if we're being called when the map is being loaded
// and validated.
if (you.level_type != LEVEL_PORTAL_VAULT &&
!(you.start_time == 0 && !you.entering_level && !Generating_Level))
{
luaL_error(ls, "Can only be used in portal vaults.");
return (0);
}
const int nargs = lua_gettop(ls);
map_def *map = NULL;
if (nargs > 2)
{
luaL_error(ls, "Too many arguments.");
return (0);
}
else if (nargs == 0)
{
luaL_error(ls, "Too few arguments.");
return (0);
}
else if (nargs == 2)
{
map_def **_map =
clua_get_userdata<map_def*>(ls, MAP_METATABLE, 1);
map = *_map;
}
if (map)
{
if (map->orient != MAP_ENCOMPASS || map->place.is_valid()
|| !map->depths.empty())
{
luaL_error(ls, "Can only be used in portal vaults.");
return (0);
}
}
int list_pos = (map != NULL) ? 2 : 1;
mons_list mlist = _lua_get_mlist(ls, list_pos);
if (mlist.size() == 0)
{
luaL_argerror(ls, list_pos, "Mon list is empty.");
return (0);
}
if (mlist.size() > 1)
{
luaL_argerror(ls, list_pos, "Mon list must contain only one slot.");
return (0);
}
const int num_mons = mlist.slot_size(0);
if (num_mons == 0)
{
luaL_argerror(ls, list_pos, "Mon list is empty.");
return (0);
}
std::vector<mons_spec> mons;
int num_lords = 0;
for (int i = 0; i < num_mons; i++)
{
mons_spec mon = mlist.get_monster(0, i);
// Pandemonium lords are pseudo-unique, so don't randomly generate
// them.
if (mon.mid == MONS_PANDEMONIUM_DEMON)
{
num_lords++;
continue;
}
std::string name;
if (mon.place.is_valid())
{
if (mon.place.level_type == LEVEL_LABYRINTH
|| mon.place.level_type == LEVEL_PORTAL_VAULT)
{
std::string err;
err = make_stringf("mon #%d: Can't use Lab or Portal as a "
"monster place.", i + 1);
luaL_argerror(ls, list_pos, err.c_str());
return(0);
}
name = mon.place.describe();
}
else
{
if (mon.mid == RANDOM_MONSTER || mon.monbase == RANDOM_MONSTER)
{
std::string err;
err = make_stringf("mon #%d: can't use random monster in "
"list specifying random monsters", i + 1);
luaL_argerror(ls, list_pos, err.c_str());
return(0);
}
if (mon.mid == -1)
mon.mid = MONS_PROGRAM_BUG;
name = mons_type_name(mon.mid, DESC_PLAIN);
}
mons.push_back(mon);
if (mon.number != 0)
mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : number for %s "
"being discarded.",
name.c_str());
if (mon.band)
mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : band request for "
"%s being ignored.",
name.c_str());
if (mon.colour != BLACK)
mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : colour for "
"%s being ignored.",
name.c_str());
if (mon.items.size() > 0)
mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : items for "
"%s being ignored.",
name.c_str());
} // for (int i = 0; i < num_mons; i++)
if (mons.size() == 0 && num_lords > 0)
{
luaL_argerror(ls, list_pos,
"Mon list contains only pandemonium lords.");
return (0);
}
if (map)
map->random_mons = mons;
else
set_vault_mon_list(mons);
return (0);
}
static int dgn_mons_from_index(lua_State *ls)
{
const int index = luaL_checkint(ls, 1);
monsters *mons = &menv[index];
if (mons->type != -1)
push_monster(ls, mons);
else
lua_pushnil(ls);
return (1);
}
static int dgn_mons_at(lua_State *ls)
{
COORDS(c, 1, 2);
monsters *mon = monster_at(c);
if (mon && mon->alive())
push_monster(ls, mon);
else
lua_pushnil(ls);
return (1);
}
static int dgn_create_monster(lua_State *ls)
{
COORDS(c, 1, 2);
mons_list mlist = _lua_get_mlist(ls, 3);
for (int i = 0, size = mlist.size(); i < size; ++i)
{
mons_spec mspec = mlist.get_monster(i);
const int mid = dgn_place_monster(mspec, you.your_level, c,
false, false, false);
if (mid != -1)
{
push_monster(ls, &menv[mid]);
return (1);
}
}
lua_pushnil(ls);
return (1);
}
static int _dgn_monster_spec(lua_State *ls)
{
const mons_list mlist = _lua_get_mlist(ls, 1);
dlua_push_object_type<mons_list>(ls, MONSLIST_METATABLE, mlist);
return (1);
}
LUARET1(_dgn_max_monsters, number, MAX_MONSTERS)
LUAFN(dgn_dismiss_monsters)
{
PLUARET(number,
dismiss_monsters(lua_gettop(ls) == 0 ? "" :
luaL_checkstring(ls, 1)));
}
const struct luaL_reg dgn_mons_lib[] =
{
{ "set_random_mon_list", dgn_set_random_mon_list },
{ "mons_from_index", dgn_mons_from_index },
{ "mons_at", dgn_mons_at },
{ "create_monster", dgn_create_monster },
{ "monster_spec", _dgn_monster_spec },
{ "max_monsters", _dgn_max_monsters },
{ "dismiss_monsters", dgn_dismiss_monsters },
{ NULL, NULL }
};
/*
* File: l_dgnit.cc
* Summary: Item-related functions in lua library "dgn".
*/
#include "AppHdr.h"
#include "dlua.h"
#include "l_libs.h"
#include "dungeon.h"
#include "items.h"
#include "mapdef.h"
#define ITEMLIST_METATABLE "crawldgn.item_list"
static item_list _lua_get_ilist(lua_State *ls, int ndx)
{
if (lua_isstring(ls, ndx))
{
const char *spec = lua_tostring(ls, ndx);
item_list ilist;
const std::string err = ilist.add_item(spec);
if (!err.empty())
luaL_error(ls, err.c_str());
return (ilist);
}
else
{
item_list **ilist =
clua_get_userdata<item_list*>(ls, ITEMLIST_METATABLE, ndx);
if (ilist)
return (**ilist);
luaL_argerror(ls, ndx, "Expected item list object or string");
return item_list();
}
}
void register_itemlist(lua_State *ls)
{
clua_register_metatable(ls, ITEMLIST_METATABLE, NULL,
lua_object_gc<item_list>);
}
static int dgn_item_from_index(lua_State *ls)
{
const int index = luaL_checkint(ls, 1);
item_def *item = &mitm[index];
if (is_valid_item(*item))
lua_pushlightuserdata(ls, item);
else
lua_pushnil(ls);
return (1);
}
static int dgn_items_at(lua_State *ls)
{
COORDS(c, 1, 2);
lua_push_items(ls, env.igrid(c));
return (1);
}
static int _dgn_item_spec(lua_State *ls)
{
const item_list ilist = _lua_get_ilist(ls, 1);
dlua_push_object_type<item_list>(ls, ITEMLIST_METATABLE, ilist);
return (1);
}
static int dgn_create_item(lua_State *ls)
{
COORDS(c, 1, 2);
item_list ilist = _lua_get_ilist(ls, 3);
const int level =
lua_isnumber(ls, 4) ? lua_tointeger(ls, 4) : you.your_level;
dgn_place_multiple_items(ilist, c, level);
link_items();
return (0);
}
const struct luaL_reg dgn_item_lib[] =
{
{ "item_from_index", dgn_item_from_index },
{ "items_at", dgn_items_at },
{ "create_item", dgn_create_item },
{ "item_spec", _dgn_item_spec },
{ NULL, NULL }
};
#define MONSLIST_METATABLE "crawldgn.monster_list"
#define ITEMLIST_METATABLE "crawldgn.item_list"
static mons_list _lua_get_mlist(lua_State *ls, int ndx)
{
if (lua_isstring(ls, ndx))
{
const char *spec = lua_tostring(ls, ndx);
mons_list mlist;
const std::string err = mlist.add_mons(spec);
if (!err.empty())
luaL_error(ls, err.c_str());
return (mlist);
}
else
{
mons_list **mlist =
clua_get_userdata<mons_list*>(ls, MONSLIST_METATABLE, ndx);
if (mlist)
return (**mlist);
luaL_argerror(ls, ndx, "Expected monster list object or string");
return mons_list();
}
}
static item_list _lua_get_ilist(lua_State *ls, int ndx)
{
if (lua_isstring(ls, ndx))
{
const char *spec = lua_tostring(ls, ndx);
item_list ilist;
const std::string err = ilist.add_item(spec);
if (!err.empty())
luaL_error(ls, err.c_str());
return (ilist);
}
else
{
item_list **ilist =
clua_get_userdata<item_list*>(ls, ITEMLIST_METATABLE, ndx);
if (ilist)
return (**ilist);
luaL_argerror(ls, ndx, "Expected item list object or string");
return item_list();
}
}
void register_mapdef_tables(lua_State *ls)
{
clua_register_metatable(ls, MONSLIST_METATABLE, NULL,
lua_object_gc<mons_list>);
clua_register_metatable(ls, ITEMLIST_METATABLE, NULL,
lua_object_gc<item_list>);
}
template <class T>
static void _push_object_type(lua_State *ls, const char *meta, const T &data)
{
T **ptr = clua_new_userdata<T*>(ls, meta);
*ptr = new T(data);
}
}
static int dgn_set_random_mon_list(lua_State *ls)
{
// Don't complain if we're being called when the map is being loaded
// and validated.
if (you.level_type != LEVEL_PORTAL_VAULT &&
!(you.start_time == 0 && !you.entering_level && !Generating_Level))
{
luaL_error(ls, "Can only be used in portal vaults.");
return (0);
}
const int nargs = lua_gettop(ls);
map_def *map = NULL;
if (nargs > 2)
{
luaL_error(ls, "Too many arguments.");
return (0);
}
else if (nargs == 0)
{
luaL_error(ls, "Too few arguments.");
return (0);
}
else if (nargs == 2)
{
map_def **_map =
clua_get_userdata<map_def*>(ls, MAP_METATABLE, 1);
map = *_map;
}
if (map)
{
if (map->orient != MAP_ENCOMPASS || map->place.is_valid()
|| !map->depths.empty())
{
luaL_error(ls, "Can only be used in portal vaults.");
return (0);
}
}
int list_pos = (map != NULL) ? 2 : 1;
mons_list mlist = _lua_get_mlist(ls, list_pos);
if (mlist.size() == 0)
{
luaL_argerror(ls, list_pos, "Mon list is empty.");
return (0);
}
if (mlist.size() > 1)
{
luaL_argerror(ls, list_pos, "Mon list must contain only one slot.");
return (0);
}
const int num_mons = mlist.slot_size(0);
if (num_mons == 0)
{
luaL_argerror(ls, list_pos, "Mon list is empty.");
return (0);
}
std::vector<mons_spec> mons;
int num_lords = 0;
for (int i = 0; i < num_mons; i++)
{
mons_spec mon = mlist.get_monster(0, i);
// Pandemonium lords are pseudo-unique, so don't randomly generate
// them.
if (mon.mid == MONS_PANDEMONIUM_DEMON)
{
num_lords++;
continue;
}
std::string name;
if (mon.place.is_valid())
{
if (mon.place.level_type == LEVEL_LABYRINTH
|| mon.place.level_type == LEVEL_PORTAL_VAULT)
{
std::string err;
err = make_stringf("mon #%d: Can't use Lab or Portal as a "
"monster place.", i + 1);
luaL_argerror(ls, list_pos, err.c_str());
return(0);
}
name = mon.place.describe();
}
else
{
if (mon.mid == RANDOM_MONSTER || mon.monbase == RANDOM_MONSTER)
{
std::string err;
err = make_stringf("mon #%d: can't use random monster in "
"list specifying random monsters", i + 1);
luaL_argerror(ls, list_pos, err.c_str());
return(0);
}
if (mon.mid == -1)
mon.mid = MONS_PROGRAM_BUG;
name = mons_type_name(mon.mid, DESC_PLAIN);
}
mons.push_back(mon);
if (mon.number != 0)
mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : number for %s "
"being discarded.",
name.c_str());
if (mon.band)
mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : band request for "
"%s being ignored.",
name.c_str());
if (mon.colour != BLACK)
mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : colour for "
"%s being ignored.",
name.c_str());
if (mon.items.size() > 0)
mprf(MSGCH_ERROR, "dgn.set_random_mon_list() : items for "
"%s being ignored.",
name.c_str());
} // for (int i = 0; i < num_mons; i++)
if (mons.size() == 0 && num_lords > 0)
{
luaL_argerror(ls, list_pos,
"Mon list contains only pandemonium lords.");
return (0);
}
if (map)
map->random_mons = mons;
else
set_vault_mon_list(mons);
return (0);
}
static int dgn_item_from_index(lua_State *ls)
{
const int index = luaL_checkint(ls, 1);
item_def *item = &mitm[index];
if (is_valid_item(*item))
lua_pushlightuserdata(ls, item);
else
lua_pushnil(ls);
return (1);
}
static int dgn_mons_from_index(lua_State *ls)
{
const int index = luaL_checkint(ls, 1);
monsters *mons = &menv[index];
if (mons->type != -1)
push_monster(ls, mons);
else
lua_pushnil(ls);
return (1);
}
static int dgn_mons_at(lua_State *ls)
{
COORDS(c, 1, 2);
monsters *mon = monster_at(c);
if (mon && mon->alive())
push_monster(ls, mon);
else
lua_pushnil(ls);
return (1);
}
static int dgn_create_monster(lua_State *ls)
{
COORDS(c, 1, 2);
mons_list mlist = _lua_get_mlist(ls, 3);
for (int i = 0, size = mlist.size(); i < size; ++i)
{
mons_spec mspec = mlist.get_monster(i);
const int mid = dgn_place_monster(mspec, you.your_level, c,
false, false, false);
if (mid != -1)
{
push_monster(ls, &menv[mid]);
return (1);
}
}
lua_pushnil(ls);
return (1);
}
static int _dgn_monster_spec(lua_State *ls)
{
const mons_list mlist = _lua_get_mlist(ls, 1);
_push_object_type<mons_list>(ls, MONSLIST_METATABLE, mlist);
return (1);
static int _dgn_item_spec(lua_State *ls)
{
const item_list ilist = _lua_get_ilist(ls, 1);
_push_object_type<item_list>(ls, ITEMLIST_METATABLE, ilist);
return (1);
}
LUARET1(_dgn_max_monsters, number, MAX_MONSTERS)
static int dgn_create_item(lua_State *ls)
{
COORDS(c, 1, 2);
item_list ilist = _lua_get_ilist(ls, 3);
const int level =
lua_isnumber(ls, 4) ? lua_tointeger(ls, 4) : you.your_level;
dgn_place_multiple_items(ilist, c, level);
link_items();
return (0);
}
{ "monster_spec", _dgn_monster_spec },
{ "item_spec", _dgn_item_spec },
{ "max_monsters", _dgn_max_monsters },