LE5U6CTXEIETQN5GOVYF2K2VCISRXR3ULORXDKIKWYDVBG5GS3WAC RPP2JHUJDTD7XFHCUPPRE7FX6JZBSTJ5IOBW37LN53IMGCO6DU3AC PJXVVRYJ3TBADNHW4ULXKDO5YDVT3T2M6MSXPNZGA6KXQITBHINAC WEPYKUZS5NJG5NHBVK5IKE55VD3EOK42JUSURMBTU4MG4SBM5ILQC KDIKQLVZZKYHRBJFCSVMXNU3J56KVSK4RWMICAXTHHEHKB3OWRMAC G7DNYFW745Q567EF3TPR2FCQ4ATPN236ON7X5TLYC7TEPZW3BAFAC ZSGD4RAGTGAXYJCRPTUUZYDDLWEIHIHKQ6RBSRPMS7TZC2JMPIAAC YFJLINBBEHE7RBETTARSYNWSO6QJ6MSPXFMSPSH2742QFC3L55SQC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC T7CCGLOZ25B7BQKKGR6IA6LWBRKUWTXLTIRXUQ4YKQRVAA7AHZKQC W52PCSHX72WAMWKG6L4BPUBVMO6E72KYYBNKAA7554KNOTY6V7WQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC 7NROUYQFX5ZRHHNGZ5DMVBNQP6H3LWDRVP5WIGG6YS6LDKOJXR3AC 7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC EJ4GIPFSSQCQASUMRF4CR2WPUQOTEHFRGLOYEZ7BH6YEMIR6DN4QC QEEJFAETO6B2J4IWDIDCJ5UNIFNNHHG22IWF2CUJRTJJBNE47CWQC MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC 2EBEWIV4YHXXAFR4GG2GMZJ2K77NK762HNQ77CZLHI3LDVGX7RJAC ACZYEIX7WMPIIODKCATBCUE626AJ4ZGGBOMVC6BGXM27EQU2RECAC AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC AXAM3TX4CUCIPL6ILEJLGJ4D4SMCJYDXGLIB256PBQXXKBIKZ4QAC HACFCSUNUI74MDKMM4YOQ3JYK2MIEAC4RULIRN2GVRBQEFED4WYQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC MT3256427VMCV4JUFWCN7ULY4KXSND5ZL5THDKYNWWYOXXR5DLIQC RN242L3YZK35BFY7JRTCSYWD6FWDCRFUFDI7PKYFUCA2UPX6ZEAQC ED62QWGKBPORWVKDFOQRKJXEIWZVNGR3O4KWQBDSRNPT36AYOQYAC ZLQAAP55CJ77XIJN3DZVPT4GTTVLIBFJLIJJKI6L5UBSHX7VUK6AC LJPUO3NNFABVOQOBA5LUDNT2R5H4LMP6TPJBNVJ7VJBERCBYZIXQC JTTHP2BEYEPBQMSDM7IKANTMKRPY6ACGL2JN4D3OBZ7HFXKAYEGQC R55VDFKFAQM32BY36VJBAAJH2C5WJNNYGAXLAH5VEI4Y6NYRLFDQC C25ULNTKMNOXT72ERWSFQZQW5E2OIM3TOGAAA33Z7EZQMZHRS2MAC UBQTNLYGD3SNWMUNGWUPX7EXEGQXOXCFCPWIVWBFE7ID7DJLPFWAC CPBVQFT7NWEYLYD34D5VYZIEOZ32YADXYTSFMS635YNXX4OFIZVAC RGHXFBNIULRVRYLBGG5JZDMYVM2E2JJ2Y5KQPMU6PUS3V26G6ZXQC TLA5UN6LZPXGKERI27EFY4HKIIU3VU5Y7ZU54WXL6ANBUV2VOTMQC SM6YRPYZS6LMDQA6X3VAOK2PGMUFKPD7JMWJISOQSMX2CBR4ISPAC OYTCBRC7LE44EUVRZVYTOOVKQWJ6P6YE3FXTOGUTNKEMLNWPHKSQC B3SRWSFITQMJRVEBHGQQJARETYPSSDV6XKMQSSUTXEHTXRZKIQJQC WF2DSJGR6PKLGQSXEFF4ZW4EZZFGMHXPXWUYAKYBPFJH6KJKAANQC ASLW3Z5PAVZSWJEMMMVZT226P44EKSAD47QS72JIFJESAI3RPN3AC NCDWWDJQLAU5ORSAQGZKJJ5E22VTDGGPJMVVBWQFHQ2B3U3UFHDQC XALTSNKCNAFBIEBXUD5KFMCTYH65XHKY436W5OR5JNBAKEEUZVAAC EIZC76IFTDKBNDJOX6YPFBOAOVAY6RSXH3JUWFLLGCZ3PYJMW3GQC C22455VGUQOSUX2OORA32LROFQ7NNYDMD2ZDTTUZSAQLXK4AD6QAC 5TKGFHC6X2JYR3MVN5T2XU2VWG45V7HGEI45H3BZ4B55WPULZEFAC X7MFMKQTNZ2IWBFVGS6WQV7NRNKJ3DWQAW2X7IQMFQQXW24AHPZQC TV7L2BAXA5U3X7EXFQMXSBNEMXJ3TVU5EWLFWEXFEWJ4MZA6ZY6AC 55PFDYPVE6JVGDYPCFUE4XS2523PVSV4CSIFRW6A2GGX4I6VWRWQC GURIAIJVY6LEADNBTZF3SFBLODYJHWD6OGWFMUGEDI4L5KYO7UFAC FQ7XALBL6NZAGBKKYIFHYQ7MUWIHR4TEU4TCS33EG4I3JTND5SQAC 77MES6I23O3FEVX45F5L7LGABFIDYZA2CLESQBXALSVIHS5E2G6AC IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC NKONHW4JNY6HP2M63MNPM3H64ZWSUNUT5FX2STW4KTS4AMXJXXVQC UU5EKED2RA2U3CFZ3UEJQEWSWHQPEU7ZD4KH3I22IIVZFHD4Y67QC EERRG6FVPJDZD6UNX2W4UXG6HU7XAU7TDNDHMRCXTA4NN4VHFSAAC 3AKDLI4CTGZ2MUXGKJ5FRCBW75JLTGMR74JUHGRDCH4MPMMFGYOAC KF5BNN42PTO35TBQD5CNMDXFAXHYCSQTBOOXZV7I3ML5VASUUT5AC S4EQ7PCNVVEICLN73WSLN2MMW6AJY34AUNFT2D27C4YBVPDRREAQC M6VWYDIBVTO66B73TOWZ3OPT5XNE4UUWKKRF3BMW4OQED7Y6O3AAC Z6Q7JVMFQ32SC7FRGOB7CE7JS2HEOPAO3B2VLU3YR3UCUDZFIPFQC AFE345BJ7IX2YYYX3I5I6RYLXNWJCFE4WMH6F5JMIR6X7WUP75CAC AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC 45EMD3KLQPMERNMIKU5G76H6556XOMIW352TSBP7VLWJX2YYGS7AC TLO257LZSB6ZO36STDUEWJBO2LETXFKTFGXELA6Y4BZBVAEIIINAC DKISJVKAJJK2SVZSXGJ37K5SOVTDARVX6RPK3MAKVNGC36Z4YAZQC BW3XFNOS6LDAQLHOZ6RXARCMKCY5JVLVDSXDSSAX4DSYM3FANQBAC NOUFW6ACJ7KPVHSPF4WLRAVOWI7PZ6OAVYDRMI3WYNPXVMGAB3QAC 6LJ7HNA6M2RVACJM4OASJPQAQ42UZGCXW636AVJ4CPICGQZBKLWQC 23I5KJ245D43B6QYWS4TDQYJO2W2PKTDCLFBWPVAFDWS6L7NMGKQC TGJZXTUIAKCFZQJ54ZQEBGFBVZSJCAX6AWDRSH3TP7UJRLGUM5SAC 44YRMW5JNVUBYX3M6UFQOPENNHGO7G2CRZ7SGPIIUTQGYWTRWENAC 7IERR3KESLBDHEMGSFRYGA66PZBPGKPUGMFDCSFR3WDX7RXD5OTAC JPZE44DYTOYGNM2TQFLW33QDX4IOCZYV4B6WZU66TQFAYEXQQD7QC S34LKQDIQJLIWVIPASOJBBZ6ZCXDHP5KPS7TRBZJSCDRVNCLK6UAC LDBTCT5WIPLJPZWXS2RUQ26QKISCUUTLO77M464WOE6VSYSNPKYAC JCBEITRVUXBYKKJCDNMZPIKSOLBH5ZHIQBXTLSUFP2WBQNEHEVLQC 3DQXSE4YGFBBDUWK4YEOFWW4UPWILWELFSLP37SL6BERGAZJC5YAC SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC PRG7UT7G56GT4W3FQ3KG5JRPGMKKJBFDLVHDLYFQK6IZW25JQLBQC FL42U7W4FLFPPSBTLDNPCIRFJG6SU2X3GWWQBQPPE2EHZ72WOSOQC G277QSURADDFZIIO5PIMBA4YWHYULQCEGNMNI6TLBWZXHQOOP6FAC OMAUFQNBWGX4FDABHQCVPGDYRVKMDASGQJVRH7AOPPEMHAP2LQSQC 4N5PW5S3OV25HFN634NNWMMYX26NA2TB6TVFG4UMYSZ2VBJWKE4QC L2PY64KUK7XYXNWKTC6YUN5DZYDNHNQFQHICUVNRGRHBHZAXWH3AC ZWFOOUUA5VCYOXGAHE76DXW65ME4AH2DVN6JVNGZAKTHZNDTVOJAC CB7U6IEEN2Z74672EYQQHWTB4GXVNNMAYDRQYAGY6K3QSDYYEHYAC CI2RMLJLIAZMEGNN6LJN6PSHXHLPG7PXFIDYRGFPVMDPJ2R4S4NQC IHV7JHD4E67NEGLZEO3FPQGJPJF3IAV6QV5A63FPG4SU2VRFV47QC FKRLQJYHK3GB6HHSNNFQ7L57ZAR52LSTBG5B6SNJBYZ2LQ36P67AC N22Z7L4XI5LX7UVPSONQNHHPPZF3GLDHGUFDJU265JQYZ3JZEZTQC UXAYLVZCSKTOC23AZORWJBQWYXKWC6QD2FPV2DRG7G6J5S7U2QLAC QAXFREFPBXN7YIBORITM2TAGA4QYF43XMSCLWW2BHONZFGEGMRUQC 2ZZD6EYMSPVCXZTICL4VGYGGQRRWDLZ24KBCDBVIYC54OZ4C6GGAC JT672SIJK4BOIUAGL2WQ6NR2NF4PSWP3BT6Q4HMNRF25UN6JQ2MAC JUCA26S3JSQFMZTBL7566ITHCOXXEFTFT7KDOWSUXA5JLZK5QJWAC KSM4H3SBM6FIQTUEGHXXYATJXEOJ4EKUBAFCRMFKSHY7N2HWECRQC 5IB2YSN5CPEWGGKAWRH52576TKVRJKMNAJT2QP6NGNRZRV5B2MDQC 52J7CYVAW3QCUEWA5OKWPDGOP6JZR5NJSE3JDLZFBCR7B6LH5ASAC LUH6GAJODIQXNPBEHMSUTKH3KA3DYVRCKZ6GJJ4HHNHOIMMUEP6QC TQXNC2YQVJZXBPSLDEANMM2EDGHTH4DSN74OJIRMUF7D46SESHZAC OFTOEJSRSA2EZOAQOJCWWQNDX7IVVAR565JK3DZCBG54TBHHCIDQC HWTL2S7OVOJRJAAN66ZTT26HJDAOIW6RKAG5NFMNZJU63CTU2U5AC JDPJS5SNW6ZTY5DYV5QUBG2WVJ45FJ4CAOK6KDJKPEI2HLIHVLRQC FAGA7XVY7FB5VEMJZ625GU5CPQMTY4KTX2NCIXQWFPH7ZQYJSAFAC Q2NUCKXB4P7DHRXY764F5AMEJO436GV74AVVVOAVGNWKLMSVMDNQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC #include "describe.h"#include "directn.h"#include "dungeon.h"#include "files.h"#include "hiscores.h"
#include "l_los.h"#include "los.h"#include "luadgn.h"#include "mapdef.h"
static mons_list _lua_get_mlist(lua_State *ls, int ndx);static item_list _lua_get_ilist(lua_State *ls, int ndx);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);}template <typename list, typename lpush>static int dlua_gentable(lua_State *ls, const list &strings, lpush push)
static mons_list _lua_get_mlist(lua_State *ls, int ndx)
return (1);}inline static void dlua_pushcxxstring(lua_State *ls, const std::string &s){lua_pushstring(ls, s.c_str());}int dlua_stringtable(lua_State *ls, const std::vector<std::string> &s){return dlua_gentable(ls, s, dlua_pushcxxstring);}static int dlua_compiled_chunk_writer(lua_State *ls, const void *p,size_t sz, void *ud){std::ostringstream &out = *static_cast<std::ostringstream*>(ud);out.write((const char *) p, sz);return (0);}///////////////////////////////////////////////////////////////////////////// dlua_chunkdlua_chunk::dlua_chunk(const std::string &_context): file(), chunk(), compiled(), context(_context), first(-1),last(-1), error(){clear();}// Initialises a chunk from the function on the top of stack.// This function must not be a closure, i.e. must not have any upvalues.dlua_chunk::dlua_chunk(lua_State *ls): file(), chunk(), compiled(), context(), first(-1), last(-1), error(){clear();lua_stack_cleaner cln(ls);std::ostringstream out;const int err = lua_dump(ls, dlua_compiled_chunk_writer, &out);if (err){const char *e = lua_tostring(ls, -1);error = e? e : "Unknown error compiling chunk";}compiled = out.str();}dlua_chunk dlua_chunk::precompiled(const std::string &chunk){dlua_chunk dchunk;dchunk.compiled = chunk;return (dchunk);}void dlua_chunk::write(writer& outf) const{if (empty()){marshallByte(outf, CT_EMPTY);return;}if (!compiled.empty()){marshallByte(outf, CT_COMPILED);marshallString4(outf, compiled);}
marshallByte(outf, CT_SOURCE);marshallString4(outf, chunk);}marshallString4(outf, file);marshallLong(outf, first);}
mons_list **mlist =clua_get_userdata<mons_list*>(ls, MONSLIST_METATABLE, ndx);if (mlist)return (**mlist);
void dlua_chunk::read(reader& inf){clear();chunk_t type = static_cast<chunk_t>(unmarshallByte(inf));switch (type){case CT_EMPTY:return;case CT_SOURCE:unmarshallString4(inf, chunk);break;case CT_COMPILED:unmarshallString4(inf, compiled);break;
luaL_argerror(ls, ndx, "Expected monster list object or string");return mons_list();
unmarshallString4(inf, file);first = unmarshallLong(inf);}void dlua_chunk::clear(){file.clear();chunk.clear();first = last = -1;error.clear();compiled.clear();}void dlua_chunk::set_file(const std::string &s){file = s;}void dlua_chunk::add(int line, const std::string &s){if (first == -1)first = line;if (line != last && last != -1)while (last++ < line)chunk += '\n';chunk += " ";chunk += s;last = line;}void dlua_chunk::set_chunk(const std::string &s){chunk = s;}int dlua_chunk::check_op(CLua &interp, int err){error = interp.error;return (err);
int err = check_op( interp,interp.loadstring(chunk.c_str(), context.c_str()) );if (err)return (err);std::ostringstream out;err = lua_dump(interp, dlua_compiled_chunk_writer, &out);if (err){const char *e = lua_tostring(interp, -1);error = e? e : "Unknown error compiling chunk";lua_pop(interp, 2);
item_list ilist;const std::string err = ilist.add_item(spec);if (!err.empty())luaL_error(ls, err.c_str());return (ilist);
compiled = out.str();chunk.clear();return (err);}int dlua_chunk::run(CLua &interp){int err = load(interp);if (err)return (err);// callfn returns true on success, but we want to return 0 on success.return (check_op(interp, !interp.callfn(NULL, 0, 0)));}int dlua_chunk::load_call(CLua &interp, const char *fn){int err = load(interp);if (err == -1000)return (0);if (err)return (err);return check_op(interp, !interp.callfn(fn, fn? 1 : 0, 0));}std::string dlua_chunk::orig_error() const{rewrite_chunk_errors(error);return (error);}bool dlua_chunk::empty() const{return compiled.empty() && trimmed_string(chunk).empty();}bool dlua_chunk::rewrite_chunk_errors(std::string &s) const{const std::string contextm = "[string \"" + context + "\"]:";std::string::size_type dlwhere = s.find(contextm);if (dlwhere == std::string::npos)return (false);if (!dlwhere)
else
// Our chunk is mentioned, go back through and rewrite lines.std::vector<std::string> lines = split_string("\n", s);std::string newmsg = lines[0];bool wrote_prefix = false;for (int i = 2, size = lines.size() - 1; i < size; ++i){const std::string &st = lines[i];if (st.find(context) != std::string::npos){if (!wrote_prefix){newmsg = get_chunk_prefix(st) + ": " + newmsg;wrote_prefix = true;}elsenewmsg += "\n" + rewrite_chunk_prefix(st);}
luaL_argerror(ls, ndx, "Expected item list object or string");return item_list();
std::string s = line;const std::string contextm = "[string \"" + context + "\"]:";const std::string::size_type ps = s.find(contextm);if (ps == std::string::npos)return (s);const std::string::size_type lns = ps + contextm.length();std::string::size_type pe = s.find(':', ps + contextm.length());if (pe != std::string::npos){const std::string line_num = s.substr(lns, pe - lns);const int lnum = atoi(line_num.c_str());const std::string newlnum = make_stringf("%d", lnum + first - 1);s = s.substr(0, lns) + newlnum + s.substr(pe);pe = lns + newlnum.length();}return s.substr(0, ps) + (file.empty()? context : file) + ":"+ (skip_body? s.substr(lns, pe - lns): s.substr(lns));
clua_register_metatable(ls, MONSLIST_METATABLE, NULL,lua_object_gc<mons_list>);clua_register_metatable(ls, ITEMLIST_METATABLE, NULL,lua_object_gc<item_list>);
#define MAP(ls, n, var) \map_def *var = *(map_def **) luaL_checkudata(ls, n, MAP_METATABLE)#define DEVENT(ls, n, var) \dgn_event *var = *(dgn_event **) luaL_checkudata(ls, n, DEVENT_METATABLE)#define MAPMARKER(ls, n, var) \map_marker *var = *(map_marker **) luaL_checkudata(ls, n, MAPMARK_METATABLE)
"unseen", "closed_door", "detected_secret_door", "secret_door","wax_wall", "metal_wall", "green_crystal_wall", "rock_wall", "stone_wall","permarock_wall","clear_rock_wall", "clear_stone_wall", "clear_permarock_wall", "trees","open_sea", "orcish_idol", "", "", "", "", "","granite_statue", "statue_reserved_1", "statue_reserved_2","", "", "", "", "", "", "", "","", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "","", "", "", "", "", "", "", "", "", "", "", "", "", "lava","deep_water", "", "", "shallow_water", "water_stuck", "floor","floor_special", "floor_reserved", "exit_hell", "enter_hell","open_door", "", "", "trap_mechanical", "trap_magical", "trap_natural","undiscovered_trap", "", "enter_shop", "enter_labyrinth","stone_stairs_down_i", "stone_stairs_down_ii","stone_stairs_down_iii", "escape_hatch_down", "stone_stairs_up_i","stone_stairs_up_ii", "stone_stairs_up_iii", "escape_hatch_up", "","", "enter_dis", "enter_gehenna", "enter_cocytus","enter_tartarus", "enter_abyss", "exit_abyss", "stone_arch","enter_pandemonium", "exit_pandemonium", "transit_pandemonium","", "", "", "builder_special_wall", "builder_special_floor", "","", "", "enter_orcish_mines", "enter_hive", "enter_lair","enter_slime_pits", "enter_vaults", "enter_crypt","enter_hall_of_blades", "enter_zot", "enter_temple","enter_snake_pit", "enter_elven_halls", "enter_tomb","enter_swamp", "enter_shoals", "enter_reserved_2","enter_reserved_3", "enter_reserved_4", "", "", "","return_from_orcish_mines", "return_from_hive","return_from_lair", "return_from_slime_pits","return_from_vaults", "return_from_crypt","return_from_hall_of_blades", "return_from_zot","return_from_temple", "return_from_snake_pit","return_from_elven_halls", "return_from_tomb","return_from_swamp", "return_from_shoals", "return_reserved_2","return_reserved_3", "return_reserved_4", "", "", "", "", "", "","", "", "", "", "", "", "", "enter_portal_vault", "exit_portal_vault","", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "","", "", "altar_zin", "altar_shining_one", "altar_kikubaaqudgha","altar_yredelemnul", "altar_xom", "altar_vehumet","altar_okawaru", "altar_makhleb", "altar_sif_muna", "altar_trog","altar_nemelex_xobeh", "altar_elyvilon", "altar_lugonu","altar_beogh", "altar_jiyva", "altar_feawn", "", "", "", "","fountain_blue", "fountain_sparkling", "fountain_blood","dry_fountain_blue", "dry_fountain_sparkling", "dry_fountain_blood","permadry_fountain", "abandoned_shop"
"unseen", "closed_door", "detected_secret_door", "secret_door","wax_wall", "metal_wall", "green_crystal_wall", "rock_wall", "stone_wall","permarock_wall","clear_rock_wall", "clear_stone_wall", "clear_permarock_wall", "trees","open_sea", "orcish_idol", "", "", "", "", "","granite_statue", "statue_reserved_1", "statue_reserved_2","", "", "", "", "", "", "", "","", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "","", "", "", "", "", "", "", "", "", "", "", "", "", "lava","deep_water", "", "", "shallow_water", "water_stuck", "floor","floor_special", "floor_reserved", "exit_hell", "enter_hell","open_door", "", "", "trap_mechanical", "trap_magical", "trap_natural","undiscovered_trap", "", "enter_shop", "enter_labyrinth","stone_stairs_down_i", "stone_stairs_down_ii","stone_stairs_down_iii", "escape_hatch_down", "stone_stairs_up_i","stone_stairs_up_ii", "stone_stairs_up_iii", "escape_hatch_up", "","", "enter_dis", "enter_gehenna", "enter_cocytus","enter_tartarus", "enter_abyss", "exit_abyss", "stone_arch","enter_pandemonium", "exit_pandemonium", "transit_pandemonium","", "", "", "builder_special_wall", "builder_special_floor", "","", "", "enter_orcish_mines", "enter_hive", "enter_lair","enter_slime_pits", "enter_vaults", "enter_crypt","enter_hall_of_blades", "enter_zot", "enter_temple","enter_snake_pit", "enter_elven_halls", "enter_tomb","enter_swamp", "enter_shoals", "enter_reserved_2","enter_reserved_3", "enter_reserved_4", "", "", "","return_from_orcish_mines", "return_from_hive","return_from_lair", "return_from_slime_pits","return_from_vaults", "return_from_crypt","return_from_hall_of_blades", "return_from_zot","return_from_temple", "return_from_snake_pit","return_from_elven_halls", "return_from_tomb","return_from_swamp", "return_from_shoals", "return_reserved_2","return_reserved_3", "return_reserved_4", "", "", "", "", "", "","", "", "", "", "", "", "", "enter_portal_vault", "exit_portal_vault","", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "","", "", "altar_zin", "altar_shining_one", "altar_kikubaaqudgha","altar_yredelemnul", "altar_xom", "altar_vehumet","altar_okawaru", "altar_makhleb", "altar_sif_muna", "altar_trog","altar_nemelex_xobeh", "altar_elyvilon", "altar_lugonu","altar_beogh", "altar_jiyva", "altar_feawn", "", "", "", "","fountain_blue", "fountain_sparkling", "fountain_blood","dry_fountain_blue", "dry_fountain_sparkling", "dry_fountain_blood","permadry_fountain", "abandoned_shop"
"none", "turn", "mons_move", "player_move", "leave_level","entering_level", "entered_level", "player_los", "player_climb","monster_dies", "item_pickup", "item_moved", "feat_change","wall_hit"
"none", "turn", "mons_move", "player_move", "leave_level","entering_level", "entered_level", "player_los", "player_climb","monster_dies", "item_pickup", "item_moved", "feat_change","wall_hit"
lua_isnumber(ls, 2)?static_cast<description_level_type>(luaL_checkint(ls, 2)) :description_type_by_name(lua_tostring(ls, 2));
lua_isnumber(ls, 2)?static_cast<description_level_type>(luaL_checkint(ls, 2)) :description_type_by_name(lua_tostring(ls, 2));
lua_isnumber(ls, 3)?static_cast<description_level_type>(luaL_checkint(ls, 3)) :description_type_by_name(lua_tostring(ls, 3));
lua_isnumber(ls, 3)?static_cast<description_level_type>(luaL_checkint(ls, 3)) :description_type_by_name(lua_tostring(ls, 3));
for (int j = -1; j <= 1; j++){if (!map_bounds(x+i, y+j))continue;const dungeon_feature_type feat2 = grd[x+i][y+j];if (feat2 == DNGN_FLOOR|| feat2 == DNGN_UNDISCOVERED_TRAP){env.grid_colours[x+i][y+j] = colour;}}
for (int j = -1; j <= 1; j++){if (!map_bounds(x+i, y+j))continue;const dungeon_feature_type feat2 = grd[x+i][y+j];if (feat2 == DNGN_FLOOR|| feat2 == DNGN_UNDISCOVERED_TRAP){env.grid_colours[x+i][y+j] = colour;}}
const char *branch_name = luaL_checkstring(ls, pos); \branch_type req_branch_type = str_to_branch(branch_name); \if (req_branch_type == NUM_BRANCHES) \luaL_error(ls, "Expected branch name"); \Branch &br = branches[req_branch_type]
const char *branch_name = luaL_checkstring(ls, pos); \branch_type req_branch_type = str_to_branch(branch_name); \if (req_branch_type == NUM_BRANCHES) \luaL_error(ls, "Expected branch name"); \Branch &br = branches[req_branch_type]
const char *level_name = luaL_checkstring(ls, pos); \level_area_type lev = str_to_level_area_type(level_name); \if (lev == NUM_LEVEL_AREA_TYPES) \luaL_error(ls, "Expected level name"); \const char *branch_name = luaL_checkstring(ls, pos); \branch_type br = str_to_branch(branch_name); \if (lev == LEVEL_DUNGEON && br == NUM_BRANCHES) \luaL_error(ls, "Expected branch name");
const char *level_name = luaL_checkstring(ls, pos); \level_area_type lev = str_to_level_area_type(level_name); \if (lev == NUM_LEVEL_AREA_TYPES) \luaL_error(ls, "Expected level name"); \const char *branch_name = luaL_checkstring(ls, pos); \branch_type br = str_to_branch(branch_name); \if (lev == LEVEL_DUNGEON && br == NUM_BRANCHES) \luaL_error(ls, "Expected branch name");
if (!lua_special_room_spec.created || !in_bounds(lua_special_room_spec.tl)|| lua_special_room_level == -1){return (0);}lua_pushnumber(ls, lua_special_room_level);dlua_push_coord(ls, lua_special_room_spec.tl);dlua_push_coord(ls, lua_special_room_spec.br);return (5);
if (!lua_special_room_spec.created || !in_bounds(lua_special_room_spec.tl)|| lua_special_room_level == -1){return (0);}lua_pushnumber(ls, lua_special_room_level);dlua_push_coord(ls, lua_special_room_spec.tl);dlua_push_coord(ls, lua_special_room_spec.br);return (5);
static const struct luaL_reg dgn_lib[] ={{ "dbg_goto_place", dgn_dbg_goto_place },{ "dbg_flush_map_memory", dgn_dbg_flush_map_memory },{ "dbg_generate_level", dgn_dbg_generate_level },{ "dbg_dump_map", dgn_dbg_dump_map },{ "dbg_test_explore", dgn_dbg_test_explore },{ "reset_level", _dgn_reset_level },{ "dismiss_monsters", dgn_dismiss_monsters },{ "default_depth", dgn_default_depth },{ "name", dgn_name },{ "depth", dgn_depth },{ "place", dgn_place },{ "tags", dgn_tags },{ "tags_remove", dgn_tags_remove },{ "lflags", dgn_lflags },{ "bflags", dgn_bflags },{ "chance", dgn_chance },{ "weight", dgn_weight },{ "welcome", dgn_welcome },{ "orient", dgn_orient },{ "shuffle", dgn_shuffle },{ "subst", dgn_subst },{ "nsubst", dgn_nsubst },{ "colour", dgn_colour },{ "lfloorcol", dgn_lfloorcol},{ "lrockcol", dgn_lrockcol},{ "normalise", dgn_normalise },{ "map", dgn_map },{ "mons", dgn_mons },{ "item", dgn_item },{ "marker", dgn_marker },{ "lua_marker", dgn_lua_marker },{ "kfeat", dgn_kfeat },{ "kitem", dgn_kitem },{ "kmons", dgn_kmons },{ "kmask", dgn_kmask },{ "mapsize", dgn_map_size },{ "grid", dgn_grid },{ "is_wall", _dgn_is_wall },{ "max_bounds", dgn_max_bounds },{ "colour_at", dgn_colour_at },{ "terrain_changed", dgn_terrain_changed },{ "points_connected", dgn_points_connected },{ "any_point_connected", dgn_any_point_connected },{ "has_exit_from", dgn_has_exit_from },{ "gly_point", dgn_gly_point },{ "gly_points", dgn_gly_points },{ "original_map", dgn_original_map },{ "load_des_file", dgn_load_des_file },{ "feature_number", dgn_feature_number },{ "feature_name", dgn_feature_name },{ "dgn_event_type", dgn_dgn_event },{ "register_listener", dgn_register_listener },{ "remove_listener", dgn_remove_listener },{ "remove_marker", dgn_remove_marker },{ "num_matching_markers", dgn_num_matching_markers },{ "feature_desc", dgn_feature_desc },{ "feature_desc_at", dgn_feature_desc_at },{ "set_feature_desc_short", dgn_set_feature_desc_short },{ "set_feature_desc_long", dgn_set_feature_desc_long },{ "item_from_index", dgn_item_from_index },{ "mons_from_index", dgn_mons_from_index },{ "mons_at", dgn_mons_at },{ "items_at", dgn_items_at },{ "change_level_flags", dgn_change_level_flags },{ "change_branch_flags", dgn_change_branch_flags },{ "set_random_mon_list", dgn_set_random_mon_list },{ "get_floor_colour", dgn_get_floor_colour },{ "get_rock_colour", dgn_get_rock_colour },{ "change_floor_colour", dgn_change_floor_colour },{ "change_rock_colour", dgn_change_rock_colour },{ "set_lt_callback", lua_dgn_set_lt_callback },{ "fixup_stairs", dgn_fixup_stairs },{ "floor_halo", dgn_floor_halo },{ "random_walk", dgn_random_walk },{ "apply_area_cloud", dgn_apply_area_cloud },// building routines{ "grd_table", dgn_grd_table },{ "width", dgn_width },{ "height", dgn_height },{ "fill_area", dgn_fill_area },{ "replace_area", dgn_replace_area },{ "octa_room", dgn_octa_room },{ "make_pillars", dgn_make_pillars },{ "make_square", dgn_make_square },{ "make_rounded_square", dgn_make_rounded_square },{ "make_circle", dgn_make_circle },{ "in_bounds", dgn_in_bounds },{ "replace_first", dgn_replace_first },{ "replace_random", dgn_replace_random },{ "spotty_level", dgn_spotty_level },{ "smear_feature", dgn_smear_feature },{ "count_feature_in_box", dgn_count_feature_in_box },{ "count_antifeature_in_box", dgn_count_antifeature_in_box },{ "count_neighbours", dgn_count_neighbours },{ "join_the_dots", dgn_join_the_dots },{ "fill_disconnected_zones", dgn_fill_disconnected_zones },{ "is_opaque", _dgn_is_opaque },{ "is_passable", _dgn_is_passable },{ "register_feature_marker", dgn_register_feature_marker },{ "register_lua_marker", dgn_register_lua_marker },{ "create_monster", dgn_create_monster },{ "create_item", dgn_create_item },{ "monster_spec", _dgn_monster_spec },{ "item_spec", _dgn_item_spec },{ "max_monsters", _dgn_max_monsters },{ "with_map_bounds_fn", dgn_with_map_bounds_fn },{ "with_map_anchors", dgn_with_map_anchors },{ "br_floorcol", dgn_br_floorcol },{ "br_rockcol", dgn_br_rockcol },{ "br_has_shops", dgn_br_has_shops },{ "br_has_uniques", dgn_br_has_uniques },{ "br_parent_branch", dgn_br_parent_branch },{ "level_id", dgn_level_id },{ "level_name", dgn_level_name },{ "set_level_type_name", dgn_set_level_type_name },{ "set_level_type_name_abbrev", dgn_set_level_type_name_abbrev },{ "set_level_type_origin", dgn_set_level_type_origin },{ "map_by_tag", dgn_map_by_tag },{ "map_in_depth", dgn_map_in_depth },{ "map_by_place", dgn_map_by_place },{ "place_map", _dgn_place_map },{ "reuse_map", _dgn_reuse_map },{ "resolve_map", _dgn_resolve_map },{ "in_vault", _dgn_in_vault },{ "find_marker_prop", _dgn_find_marker_prop },{ "get_special_room_info", dgn_get_special_room_info },{ "lrocktile", dgn_lrocktile },{ "lfloortile", dgn_lfloortile },{ "rtile", dgn_rtile },{ "ftile", dgn_ftile },{ "change_rock_tile", dgn_change_rock_tile },{ "change_floor_tile", dgn_change_floor_tile },{ "lev_floortile", dgn_lev_floortile },{ "lev_rocktile", dgn_lev_rocktile },{ NULL, NULL }};LUAFN(_crawl_args){return dlua_stringtable(ls, SysEnv.cmd_args);}LUAFN(_crawl_milestone){#ifdef DGL_MILESTONESmark_milestone(luaL_checkstring(ls, 1),luaL_checkstring(ls, 2));#endifreturn (0);}LUAFN(_crawl_redraw_view){viewwindow(true, false);return (0);}#ifdef UNIXLUAFN(_crawl_millis){struct timeval tv;struct timezone tz;const int error = gettimeofday(&tv, &tz);if (error)luaL_error(ls, make_stringf("Failed to get time: %s",strerror(error)).c_str());lua_pushnumber(ls, tv.tv_sec * 1000 + tv.tv_usec / 1000);return (1);}#endifstatic const struct luaL_reg crawl_lib[] ={{ "args", _crawl_args },{ "mark_milestone", _crawl_milestone },{ "redraw_view", _crawl_redraw_view },#ifdef UNIX{ "millis", _crawl_millis },#endif{ NULL, NULL }};static int file_marshall(lua_State *ls){if (lua_gettop(ls) != 2)luaL_error(ls, "Need two arguments: tag header and value");writer &th(*static_cast<writer*>( lua_touserdata(ls, 1) ));if (lua_isnumber(ls, 2))marshallLong(th, luaL_checklong(ls, 2));else if (lua_isboolean(ls, 2))marshallByte(th, lua_toboolean(ls, 2));else if (lua_isstring(ls, 2))marshallString(th, lua_tostring(ls, 2));else if (lua_isfunction(ls, 2)){dlua_chunk chunk(ls);marshallString(th, chunk.compiled_chunk());}return (0);}static int file_unmarshall_boolean(lua_State *ls){if (lua_gettop(ls) != 1)luaL_error(ls, "Need reader as one argument");reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));lua_pushboolean(ls, unmarshallByte(th));return (1);}static int file_unmarshall_number(lua_State *ls){if (lua_gettop(ls) != 1)luaL_error(ls, "Need reader as one argument");reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));lua_pushnumber(ls, unmarshallLong(th));return (1);}static int file_unmarshall_string(lua_State *ls){if (lua_gettop(ls) != 1)luaL_error(ls, "Need reader as one argument");reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));lua_pushstring(ls, unmarshallString(th).c_str());return (1);}static int file_unmarshall_fn(lua_State *ls){if (lua_gettop(ls) != 1)luaL_error(ls, "Need reader as one argument");reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));const std::string s(unmarshallString(th, LUA_CHUNK_MAX_SIZE));dlua_chunk chunk = dlua_chunk::precompiled(s);if (chunk.load(dlua))lua_pushnil(ls);return (1);}enum lua_persist_type{LPT_NONE,LPT_NUMBER,LPT_STRING,LPT_FUNCTION,LPT_NIL,LPT_BOOLEAN};static int file_marshall_meta(lua_State *ls){if (lua_gettop(ls) != 2)luaL_error(ls, "Need two arguments: tag header and value");writer &th(*static_cast<writer*>( lua_touserdata(ls, 1) ));lua_persist_type ptype = LPT_NONE;if (lua_isnumber(ls, 2))ptype = LPT_NUMBER;else if (lua_isboolean(ls, 2))ptype = LPT_BOOLEAN;else if (lua_isstring(ls, 2))ptype = LPT_STRING;else if (lua_isfunction(ls, 2))ptype = LPT_FUNCTION;else if (lua_isnil(ls, 2))ptype = LPT_NIL;elseluaL_error(ls,make_stringf("Cannot marshall %s",lua_typename(ls, lua_type(ls, 2))).c_str());marshallByte(th, ptype);if (ptype != LPT_NIL)file_marshall(ls);return (0);}static int file_unmarshall_meta(lua_State *ls){reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));const lua_persist_type ptype =static_cast<lua_persist_type>(unmarshallByte(th));switch (ptype){case LPT_BOOLEAN:return file_unmarshall_boolean(ls);case LPT_NUMBER:return file_unmarshall_number(ls);case LPT_STRING:return file_unmarshall_string(ls);case LPT_FUNCTION:return file_unmarshall_fn(ls);case LPT_NIL:lua_pushnil(ls);return (1);default:luaL_error(ls, "Unexpected type signature.");}// Never get here.return (0);}static const struct luaL_reg file_lib[] ={{ "marshall", file_marshall },{ "marshall_meta", file_marshall_meta },{ "unmarshall_meta", file_unmarshall_meta },{ "unmarshall_number", file_unmarshall_number },{ "unmarshall_string", file_unmarshall_string },{ "unmarshall_fn", file_unmarshall_fn },{ NULL, NULL }};LUARET1(you_can_hear_pos, boolean,player_can_hear(coord_def(luaL_checkint(ls,1), luaL_checkint(ls, 2))))LUARET1(you_x_pos, number, you.pos().x)LUARET1(you_y_pos, number, you.pos().y)LUARET2(you_pos, number, you.pos().x, you.pos().y)// see_cell should not be exposed to user scripts. The game should// never disclose grid coordinates to the player. Therefore we load it// only into the core Lua interpreter (dlua), never into the user// script interpreter (clua).LUARET1(you_see_cell, boolean,see_cell(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))LUARET1(you_see_cell_no_trans, boolean,see_cell_no_trans(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))LUAFN(you_moveto){const coord_def place(luaL_checkint(ls, 1), luaL_checkint(ls, 2));ASSERT(map_bounds(place));you.moveto(place);return (0);}LUAFN(you_random_teleport){you_teleport_now(false, false);return (0);}LUAFN(you_losight){calc_show_los();return (0);}static const struct luaL_reg you_lib[] ={{ "hear_pos", you_can_hear_pos },{ "x_pos", you_x_pos },{ "y_pos", you_y_pos },{ "pos", you_pos },{ "moveto", you_moveto },{ "see_cell", you_see_cell },{ "see_cell_no_trans", you_see_cell_no_trans },{ "random_teleport", you_random_teleport },{ "losight", you_losight },{ NULL, NULL }};static int dgnevent_type(lua_State *ls){DEVENT(ls, 1, dev);PLUARET(number, dev->type);}static int dgnevent_place(lua_State *ls){DEVENT(ls, 1, dev);lua_pushnumber(ls, dev->place.x);lua_pushnumber(ls, dev->place.y);return (2);}static int dgnevent_dest(lua_State *ls){DEVENT(ls, 1, dev);lua_pushnumber(ls, dev->dest.x);lua_pushnumber(ls, dev->dest.y);return (2);}static int dgnevent_ticks(lua_State *ls){DEVENT(ls, 1, dev);PLUARET(number, dev->elapsed_ticks);}
DEVENT(ls, 1, dev);PLUARET(number, dev->arg1);}
{ "dbg_goto_place", dgn_dbg_goto_place },{ "dbg_flush_map_memory", dgn_dbg_flush_map_memory },{ "dbg_generate_level", dgn_dbg_generate_level },{ "dbg_dump_map", dgn_dbg_dump_map },{ "dbg_test_explore", dgn_dbg_test_explore },
static const struct luaL_reg dgnevent_lib[] ={{ "type", dgnevent_type },{ "pos", dgnevent_place },{ "dest", dgnevent_dest },{ "ticks", dgnevent_ticks },{ "arg1", dgnevent_arg1 },{ "arg2", dgnevent_arg2 },{ NULL, NULL }};
{ "default_depth", dgn_default_depth },{ "name", dgn_name },{ "depth", dgn_depth },{ "place", dgn_place },{ "tags", dgn_tags },{ "tags_remove", dgn_tags_remove },{ "lflags", dgn_lflags },{ "bflags", dgn_bflags },{ "chance", dgn_chance },{ "weight", dgn_weight },{ "welcome", dgn_welcome },{ "orient", dgn_orient },{ "shuffle", dgn_shuffle },{ "subst", dgn_subst },{ "nsubst", dgn_nsubst },{ "colour", dgn_colour },{ "lfloorcol", dgn_lfloorcol},{ "lrockcol", dgn_lrockcol},{ "normalise", dgn_normalise },{ "map", dgn_map },{ "mons", dgn_mons },{ "item", dgn_item },{ "marker", dgn_marker },{ "lua_marker", dgn_lua_marker },{ "kfeat", dgn_kfeat },{ "kitem", dgn_kitem },{ "kmons", dgn_kmons },{ "kmask", dgn_kmask },{ "mapsize", dgn_map_size },
void luaopen_setmeta(lua_State *ls,const char *global,const luaL_reg *lua_lib,const char *meta){luaL_newmetatable(ls, meta);lua_setglobal(ls, global);
{ "grid", dgn_grid },{ "is_wall", _dgn_is_wall },{ "max_bounds", dgn_max_bounds },{ "colour_at", dgn_colour_at },
luaL_openlib(ls, global, lua_lib, 0);
{ "terrain_changed", dgn_terrain_changed },{ "points_connected", dgn_points_connected },{ "any_point_connected", dgn_any_point_connected },{ "has_exit_from", dgn_has_exit_from },{ "gly_point", dgn_gly_point },{ "gly_points", dgn_gly_points },{ "original_map", dgn_original_map },{ "load_des_file", dgn_load_des_file },{ "feature_number", dgn_feature_number },{ "feature_name", dgn_feature_name },{ "dgn_event_type", dgn_dgn_event },{ "register_listener", dgn_register_listener },{ "remove_listener", dgn_remove_listener },{ "remove_marker", dgn_remove_marker },{ "num_matching_markers", dgn_num_matching_markers },{ "feature_desc", dgn_feature_desc },{ "feature_desc_at", dgn_feature_desc_at },{ "set_feature_desc_short", dgn_set_feature_desc_short },{ "set_feature_desc_long", dgn_set_feature_desc_long },{ "item_from_index", dgn_item_from_index },{ "mons_from_index", dgn_mons_from_index },{ "mons_at", dgn_mons_at },{ "items_at", dgn_items_at },{ "change_level_flags", dgn_change_level_flags },{ "change_branch_flags", dgn_change_branch_flags },{ "set_random_mon_list", dgn_set_random_mon_list },{ "get_floor_colour", dgn_get_floor_colour },{ "get_rock_colour", dgn_get_rock_colour },{ "change_floor_colour", dgn_change_floor_colour },{ "change_rock_colour", dgn_change_rock_colour },{ "set_lt_callback", lua_dgn_set_lt_callback },{ "fixup_stairs", dgn_fixup_stairs },{ "floor_halo", dgn_floor_halo },{ "random_walk", dgn_random_walk },{ "apply_area_cloud", dgn_apply_area_cloud },
// Do <global>.__index = <global>lua_pushstring(ls, "__index");lua_pushvalue(ls, -2);lua_settable(ls, -3);}static void luaopen_dgnevent(lua_State *ls){luaopen_setmeta(ls, "dgnevent", dgnevent_lib, DEVENT_METATABLE);}static int mapmarker_pos(lua_State *ls){MAPMARKER(ls, 1, mark);lua_pushnumber(ls, mark->pos.x);lua_pushnumber(ls, mark->pos.y);return (2);}
// building routines{ "grd_table", dgn_grd_table },{ "width", dgn_width },{ "height", dgn_height },{ "fill_area", dgn_fill_area },{ "replace_area", dgn_replace_area },{ "octa_room", dgn_octa_room },{ "make_pillars", dgn_make_pillars },{ "make_square", dgn_make_square },{ "make_rounded_square", dgn_make_rounded_square },{ "make_circle", dgn_make_circle },{ "in_bounds", dgn_in_bounds },{ "replace_first", dgn_replace_first },{ "replace_random", dgn_replace_random },{ "spotty_level", dgn_spotty_level },{ "smear_feature", dgn_smear_feature },{ "count_feature_in_box", dgn_count_feature_in_box },{ "count_antifeature_in_box", dgn_count_antifeature_in_box },{ "count_neighbours", dgn_count_neighbours },{ "join_the_dots", dgn_join_the_dots },{ "fill_disconnected_zones", dgn_fill_disconnected_zones },
static int mapmarker_move(lua_State *ls){MAPMARKER(ls, 1, mark);const coord_def dest( luaL_checkint(ls, 2), luaL_checkint(ls, 3) );env.markers.move_marker(mark, dest);return (0);}
{ "is_opaque", _dgn_is_opaque },{ "is_passable", _dgn_is_passable },
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);
{ "register_feature_marker", dgn_register_feature_marker },{ "register_lua_marker", dgn_register_lua_marker },
luaL_argerror(ls, ndx, "Expected monster list object or string");return mons_list();}}
{ "create_monster", dgn_create_monster },{ "create_item", dgn_create_item },
return (ilist);}else{item_list **ilist =clua_get_userdata<item_list*>(ls, ITEMLIST_METATABLE, ndx);if (ilist)return (**ilist);
{ "with_map_bounds_fn", dgn_with_map_bounds_fn },{ "with_map_anchors", dgn_with_map_anchors },
luaL_argerror(ls, ndx, "Expected item list object or string");return item_list();}}
{ "br_floorcol", dgn_br_floorcol },{ "br_rockcol", dgn_br_rockcol },{ "br_has_shops", dgn_br_has_shops },{ "br_has_uniques", dgn_br_has_uniques },{ "br_parent_branch", dgn_br_parent_branch },
static 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>);}
{ "level_id", dgn_level_id },{ "level_name", dgn_level_name },{ "set_level_type_name", dgn_set_level_type_name },{ "set_level_type_name_abbrev", dgn_set_level_type_name_abbrev },{ "set_level_type_origin", dgn_set_level_type_origin },{ "map_by_tag", dgn_map_by_tag },{ "map_in_depth", dgn_map_in_depth },{ "map_by_place", dgn_map_by_place },{ "place_map", _dgn_place_map },{ "reuse_map", _dgn_reuse_map },{ "resolve_map", _dgn_resolve_map },{ "in_vault", _dgn_in_vault },
static const struct luaL_reg mapmarker_lib[] ={{ "pos", mapmarker_pos },{ "move", mapmarker_move },{ NULL, NULL }};
{ "find_marker_prop", _dgn_find_marker_prop },
// Return the integer stored in the table (on the stack) with the key name.// If the key doesn't exist or the value is the wrong type, return defval.static int _table_int(lua_State *ls, int idx, const char *name, int defval){lua_pushstring(ls, name);lua_gettable(ls, idx < 0 ? idx - 1 : idx);bool nil = lua_isnil(ls, idx);bool valid = lua_isnumber(ls, idx);if (!nil && !valid)luaL_error(ls, "'%s' in table, but not an int.", name);int ret = (!nil && valid ? lua_tonumber(ls, idx) : defval);lua_pop(ls, 1);return (ret);}// Return the character stored in the table (on the stack) with the key name.// If the key doesn't exist or the value is the wrong type, return defval.static char _table_char(lua_State *ls, int idx, const char *name, char defval){lua_pushstring(ls, name);lua_gettable(ls, idx < 0 ? idx - 1 : idx);bool nil = lua_isnil(ls, idx);bool valid = lua_isstring(ls, idx);if (!nil && !valid)luaL_error(ls, "'%s' in table, but not a string.", name);char ret = defval;if (!nil && valid){const char *str = lua_tostring(ls, idx);if (str[0] && !str[1])ret = str[0];elseluaL_error(ls, "'%s' has more than one character.", name);}lua_pop(ls, 1);return (ret);}// Return the string stored in the table (on the stack) with the key name.// If the key doesn't exist or the value is the wrong type, return defval.static const char* _table_str(lua_State *ls, int idx, const char *name, const char *defval){lua_pushstring(ls, name);lua_gettable(ls, idx < 0 ? idx - 1 : idx);bool nil = lua_isnil(ls, idx);bool valid = lua_isstring(ls, idx);if (!nil && !valid)luaL_error(ls, "'%s' in table, but not a string.", name);const char *ret = (!nil && valid ? lua_tostring(ls, idx) : defval);lua_pop(ls, 1);return (ret);}// Return the boolean stored in the table (on the stack) with the key name.// If the key doesn't exist or the value is the wrong type, return defval.static bool _table_bool(lua_State *ls, int idx, const char *name, bool defval){lua_pushstring(ls, name);lua_gettable(ls, idx < 0 ? idx - 1 : idx);bool nil = lua_isnil(ls, idx);bool valid = lua_isboolean(ls, idx);if (!nil && !valid)luaL_error(ls, "'%s' in table, but not a bool.", name);bool ret = (!nil && valid ? lua_toboolean(ls, idx) : defval);lua_pop(ls, 1);return (ret);}#define BF_INT(ls, val, def) int val = _table_int(ls, -1, #val, def);#define BF_CHAR(ls, val, def) char val = _table_char(ls, -1, #val, def);#define BF_STR(ls, val, def) const char *val = _table_str(ls, -1, #val, def);#define BF_BOOL(ls, val, def) bool val = _table_bool(ls, -1, #val, def);static void bf_octa_room(lua_State *ls, map_lines &lines){int default_oblique = std::min(lines.width(), lines.height()) / 2 - 1;BF_INT(ls, oblique, default_oblique);BF_CHAR(ls, outside, 'x');BF_CHAR(ls, inside, '.');BF_STR(ls, replace, ".");coord_def tl, br;if (!lines.find_bounds(replace, tl, br))return;for (rectangle_iterator ri(tl, br); ri; ++ri){const coord_def mc = *ri;char glyph = lines(mc);if (replace[0] && !strchr(replace, glyph))continue;int ob = 0;ob += std::max(oblique + tl.x - mc.x, 0);ob += std::max(oblique + mc.x - br.x, 0);bool is_inside = (mc.y >= tl.y + ob && mc.y <= br.y - ob);lines(mc) = is_inside ? inside : outside;}}static void bf_smear(lua_State *ls, map_lines &lines){BF_INT(ls, iterations, 1);BF_CHAR(ls, smear, 'x');BF_STR(ls, onto, ".");BF_BOOL(ls, boxy, false);const int max_test_per_iteration = 10;int sanity = 0;int max_sanity = iterations * max_test_per_iteration;for (int i = 0; i < iterations; i++){bool diagonals, straights;coord_def mc;do{do{sanity++;mc.x = random_range(1, lines.width() - 2);mc.y = random_range(1, lines.height() - 2);}while (onto[0] && !strchr(onto, lines(mc)));// Prevent too many iterations.if (sanity > max_sanity)return;// Is there a "smear" feature along the diagonal from mc?diagonals = lines(coord_def(mc.x+1, mc.y+1)) == smear ||lines(coord_def(mc.x-1, mc.y+1)) == smear ||lines(coord_def(mc.x-1, mc.y-1)) == smear ||lines(coord_def(mc.x+1, mc.y-1)) == smear;// Is there a "smear" feature up, down, left, or right from mc?straights = lines(coord_def(mc.x+1, mc.y)) == smear ||lines(coord_def(mc.x-1, mc.y)) == smear ||lines(coord_def(mc.x, mc.y+1)) == smear ||lines(coord_def(mc.x, mc.y-1)) == smear;}while (!straights && (boxy || !diagonals));lines(mc) = smear;}}static void bf_extend(lua_State *ls, map_lines &lines){BF_INT(ls, height, 1);BF_INT(ls, width, 1);BF_CHAR(ls, fill, 'x');lines.extend(width, height, fill);}typedef void (*bf_func)(lua_State *ls, map_lines &lines);struct bf_entry{const char* name;bf_func func;};// Create a separate list of builder funcs so that we can automatically// generate a list of closures for them, rather than individually// and explicitly exposing them to the dgn namespace.static struct bf_entry bf_map[] ={{ "map_octa_room", &bf_octa_room },{ "map_smear", &bf_smear },{ "map_extend", &bf_extend }
{ NULL, NULL }
static int dgn_call_builder_func(lua_State *ls){// This function gets called for all the builder functions that// operate on map_lines.MAP(ls, 1, map);if (!lua_istable(ls, 2) && !lua_isfunction(ls, 2))return luaL_argerror(ls, 2, "Expected table");bf_func *func = (bf_func *)lua_topointer(ls, lua_upvalueindex(1));if (!func)return luaL_error(ls, "Expected C function in closure upval");// Put the table on top.lua_settop(ls, 2);// Call the builder func itself.(*func)(ls, map->map);return (0);}static void _register_builder_funcs(lua_State *ls){lua_getglobal(ls, "dgn");const size_t num_entries = sizeof(bf_map) / sizeof(bf_entry);for (size_t i = 0; i < num_entries; i++){// Push a closure with the C function into the dgn table.lua_pushlightuserdata(ls, &bf_map[i].func);lua_pushcclosure(ls, &dgn_call_builder_func, 1);lua_setfield(ls, -2, bf_map[i].name);}lua_pop(ls, 1);}void init_dungeon_lua(){lua_stack_cleaner clean(dlua);luaL_openlib(dlua, "dgn", dgn_lib, 0);// Add additional function to the Crawl module.luaL_openlib(dlua, "crawl", crawl_lib, 0);luaL_openlib(dlua, "file", file_lib, 0);luaL_openlib(dlua, "you", you_lib, 0);luaL_openlib(dlua, "los", los_lib, 0);dlua.execfile("clua/dungeon.lua", true, true);dlua.execfile("clua/luamark.lua", true, true);lua_getglobal(dlua, "dgn_run_map");luaopen_debug(dlua);luaL_newmetatable(dlua, MAP_METATABLE);luaopen_dgnevent(dlua);luaopen_mapmarker(dlua);luaopen_ray(dlua);_register_builder_funcs(dlua);_register_mapdef_tables(dlua);}// Can be called from within a debugger to look at the current Lua// call stack. (Borrowed from ToME 3)void print_dlua_stack(void){struct lua_Debug dbg;int i = 0;lua_State *L = dlua.state();fprintf(stderr, EOL);while (lua_getstack(L, i++, &dbg) == 1){lua_getinfo(L, "lnuS", &dbg);char* file = strrchr(dbg.short_src, '/');if (file == NULL)file = dbg.short_src;elsefile++;fprintf(stderr, "%s, function %s, line %d" EOL, file,dbg.name, dbg.currentline);}fprintf(stderr, EOL);}
#define MAP(ls, n, var) \map_def *var = *(map_def **) luaL_checkudata(ls, n, MAP_METATABLE)#define DEVENT(ls, n, var) \dgn_event *var = *(dgn_event **) luaL_checkudata(ls, n, DEVENT_METATABLE)#define MAPMARKER(ls, n, var) \map_marker *var = *(map_marker **) luaL_checkudata(ls, n, MAPMARK_METATABLE)extern const struct luaL_reg dgn_lib[];extern const struct luaL_reg los_lib[];
/** File: luadgn.cc* Summary: Dungeon-builder Lua interface.* Created by: dshaligram on Sat Jun 23 20:02:09 2007 UTC*/#include "AppHdr.h"#include <sstream>#include <algorithm>#include <memory>#include <cmath>#include "branch.h"#include "chardump.h"#include "clua.h"#include "cloud.h"#include "describe.h"#include "directn.h"#include "dlua.h"#include "dungeon.h"#include "files.h"#include "hiscores.h"#include "initfile.h"#include "items.h"#include "l_los.h"#include "los.h"#include "mapdef.h"#include "mapmark.h"#include "maps.h"#include "message.h"#include "misc.h"#include "mon-util.h"#include "monplace.h"#include "monstuff.h"#include "place.h"#include "spells3.h"#include "spl-util.h"#include "state.h"#include "stuff.h"#include "tags.h"#include "terrain.h"#include "view.h"#ifdef UNIX#include <sys/time.h>#include <time.h>#endiftemplate <typename list, typename lpush>static int dlua_gentable(lua_State *ls, const list &strings, lpush push){lua_newtable(ls);for (int i = 0, size = strings.size(); i < size; ++i){push(ls, strings[i]);lua_rawseti(ls, -2, i + 1);}return (1);}inline static void dlua_pushcxxstring(lua_State *ls, const std::string &s){lua_pushstring(ls, s.c_str());}int dlua_stringtable(lua_State *ls, const std::vector<std::string> &s){return dlua_gentable(ls, s, dlua_pushcxxstring);}static int dlua_compiled_chunk_writer(lua_State *ls, const void *p,size_t sz, void *ud){std::ostringstream &out = *static_cast<std::ostringstream*>(ud);out.write((const char *) p, sz);return (0);}///////////////////////////////////////////////////////////////////////////// dlua_chunkdlua_chunk::dlua_chunk(const std::string &_context): file(), chunk(), compiled(), context(_context), first(-1),last(-1), error(){clear();}// Initialises a chunk from the function on the top of stack.// This function must not be a closure, i.e. must not have any upvalues.dlua_chunk::dlua_chunk(lua_State *ls): file(), chunk(), compiled(), context(), first(-1), last(-1), error(){clear();lua_stack_cleaner cln(ls);std::ostringstream out;const int err = lua_dump(ls, dlua_compiled_chunk_writer, &out);if (err){const char *e = lua_tostring(ls, -1);error = e? e : "Unknown error compiling chunk";}compiled = out.str();}dlua_chunk dlua_chunk::precompiled(const std::string &chunk){dlua_chunk dchunk;dchunk.compiled = chunk;return (dchunk);}void dlua_chunk::write(writer& outf) const{if (empty()){marshallByte(outf, CT_EMPTY);return;}if (!compiled.empty()){marshallByte(outf, CT_COMPILED);marshallString4(outf, compiled);}else{marshallByte(outf, CT_SOURCE);marshallString4(outf, chunk);}marshallString4(outf, file);marshallLong(outf, first);}void dlua_chunk::read(reader& inf){clear();chunk_t type = static_cast<chunk_t>(unmarshallByte(inf));switch (type){case CT_EMPTY:return;case CT_SOURCE:unmarshallString4(inf, chunk);break;case CT_COMPILED:unmarshallString4(inf, compiled);break;}unmarshallString4(inf, file);first = unmarshallLong(inf);}void dlua_chunk::clear(){file.clear();chunk.clear();first = last = -1;error.clear();compiled.clear();}void dlua_chunk::set_file(const std::string &s){file = s;}void dlua_chunk::add(int line, const std::string &s){if (first == -1)first = line;if (line != last && last != -1)while (last++ < line)chunk += '\n';chunk += " ";chunk += s;last = line;}void dlua_chunk::set_chunk(const std::string &s){chunk = s;}int dlua_chunk::check_op(CLua &interp, int err){error = interp.error;return (err);}int dlua_chunk::load(CLua &interp){if (!compiled.empty())return check_op( interp,interp.loadbuffer(compiled.c_str(), compiled.length(),context.c_str()) );if (empty()){chunk.clear();return (-1000);}int err = check_op( interp,interp.loadstring(chunk.c_str(), context.c_str()) );if (err)return (err);std::ostringstream out;err = lua_dump(interp, dlua_compiled_chunk_writer, &out);if (err){const char *e = lua_tostring(interp, -1);error = e? e : "Unknown error compiling chunk";lua_pop(interp, 2);}compiled = out.str();chunk.clear();return (err);}int dlua_chunk::run(CLua &interp){int err = load(interp);if (err)return (err);// callfn returns true on success, but we want to return 0 on success.return (check_op(interp, !interp.callfn(NULL, 0, 0)));}int dlua_chunk::load_call(CLua &interp, const char *fn){int err = load(interp);if (err == -1000)return (0);if (err)return (err);return check_op(interp, !interp.callfn(fn, fn? 1 : 0, 0));}std::string dlua_chunk::orig_error() const{rewrite_chunk_errors(error);return (error);}bool dlua_chunk::empty() const{return compiled.empty() && trimmed_string(chunk).empty();}bool dlua_chunk::rewrite_chunk_errors(std::string &s) const{const std::string contextm = "[string \"" + context + "\"]:";std::string::size_type dlwhere = s.find(contextm);if (dlwhere == std::string::npos)return (false);if (!dlwhere){s = rewrite_chunk_prefix(s);return (true);}// Our chunk is mentioned, go back through and rewrite lines.std::vector<std::string> lines = split_string("\n", s);std::string newmsg = lines[0];bool wrote_prefix = false;for (int i = 2, size = lines.size() - 1; i < size; ++i){const std::string &st = lines[i];if (st.find(context) != std::string::npos){if (!wrote_prefix){newmsg = get_chunk_prefix(st) + ": " + newmsg;wrote_prefix = true;}elsenewmsg += "\n" + rewrite_chunk_prefix(st);}}s = newmsg;return (true);}std::string dlua_chunk::rewrite_chunk_prefix(const std::string &line,bool skip_body) const{std::string s = line;const std::string contextm = "[string \"" + context + "\"]:";const std::string::size_type ps = s.find(contextm);if (ps == std::string::npos)return (s);const std::string::size_type lns = ps + contextm.length();std::string::size_type pe = s.find(':', ps + contextm.length());if (pe != std::string::npos){const std::string line_num = s.substr(lns, pe - lns);const int lnum = atoi(line_num.c_str());const std::string newlnum = make_stringf("%d", lnum + first - 1);s = s.substr(0, lns) + newlnum + s.substr(pe);pe = lns + newlnum.length();}return s.substr(0, ps) + (file.empty()? context : file) + ":"+ (skip_body? s.substr(lns, pe - lns): s.substr(lns));}std::string dlua_chunk::get_chunk_prefix(const std::string &sorig) const{return rewrite_chunk_prefix(sorig, true);}LUAFN(_crawl_args){return dlua_stringtable(ls, SysEnv.cmd_args);}LUAFN(_crawl_milestone){#ifdef DGL_MILESTONESmark_milestone(luaL_checkstring(ls, 1),luaL_checkstring(ls, 2));#endifreturn (0);}LUAFN(_crawl_redraw_view){viewwindow(true, false);return (0);}#ifdef UNIXLUAFN(_crawl_millis){struct timeval tv;struct timezone tz;const int error = gettimeofday(&tv, &tz);if (error)luaL_error(ls, make_stringf("Failed to get time: %s",strerror(error)).c_str());lua_pushnumber(ls, tv.tv_sec * 1000 + tv.tv_usec / 1000);return (1);}#endifstatic const struct luaL_reg crawl_lib[] ={{ "args", _crawl_args },{ "mark_milestone", _crawl_milestone },{ "redraw_view", _crawl_redraw_view },#ifdef UNIX{ "millis", _crawl_millis },#endif{ NULL, NULL }};static int file_marshall(lua_State *ls){if (lua_gettop(ls) != 2)luaL_error(ls, "Need two arguments: tag header and value");writer &th(*static_cast<writer*>( lua_touserdata(ls, 1) ));if (lua_isnumber(ls, 2))marshallLong(th, luaL_checklong(ls, 2));else if (lua_isboolean(ls, 2))marshallByte(th, lua_toboolean(ls, 2));else if (lua_isstring(ls, 2))marshallString(th, lua_tostring(ls, 2));else if (lua_isfunction(ls, 2)){dlua_chunk chunk(ls);marshallString(th, chunk.compiled_chunk());}return (0);}static int file_unmarshall_boolean(lua_State *ls){if (lua_gettop(ls) != 1)luaL_error(ls, "Need reader as one argument");reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));lua_pushboolean(ls, unmarshallByte(th));return (1);}static int file_unmarshall_number(lua_State *ls){if (lua_gettop(ls) != 1)luaL_error(ls, "Need reader as one argument");reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));lua_pushnumber(ls, unmarshallLong(th));return (1);}static int file_unmarshall_string(lua_State *ls){if (lua_gettop(ls) != 1)luaL_error(ls, "Need reader as one argument");reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));lua_pushstring(ls, unmarshallString(th).c_str());return (1);}static int file_unmarshall_fn(lua_State *ls){if (lua_gettop(ls) != 1)luaL_error(ls, "Need reader as one argument");reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));const std::string s(unmarshallString(th, LUA_CHUNK_MAX_SIZE));dlua_chunk chunk = dlua_chunk::precompiled(s);if (chunk.load(dlua))lua_pushnil(ls);return (1);}enum lua_persist_type{LPT_NONE,LPT_NUMBER,LPT_STRING,LPT_FUNCTION,LPT_NIL,LPT_BOOLEAN};static int file_marshall_meta(lua_State *ls){if (lua_gettop(ls) != 2)luaL_error(ls, "Need two arguments: tag header and value");writer &th(*static_cast<writer*>( lua_touserdata(ls, 1) ));lua_persist_type ptype = LPT_NONE;if (lua_isnumber(ls, 2))ptype = LPT_NUMBER;else if (lua_isboolean(ls, 2))ptype = LPT_BOOLEAN;else if (lua_isstring(ls, 2))ptype = LPT_STRING;else if (lua_isfunction(ls, 2))ptype = LPT_FUNCTION;else if (lua_isnil(ls, 2))ptype = LPT_NIL;elseluaL_error(ls,make_stringf("Cannot marshall %s",lua_typename(ls, lua_type(ls, 2))).c_str());marshallByte(th, ptype);if (ptype != LPT_NIL)file_marshall(ls);return (0);}static int file_unmarshall_meta(lua_State *ls){reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));const lua_persist_type ptype =static_cast<lua_persist_type>(unmarshallByte(th));switch (ptype){case LPT_BOOLEAN:return file_unmarshall_boolean(ls);case LPT_NUMBER:return file_unmarshall_number(ls);case LPT_STRING:return file_unmarshall_string(ls);case LPT_FUNCTION:return file_unmarshall_fn(ls);case LPT_NIL:lua_pushnil(ls);return (1);default:luaL_error(ls, "Unexpected type signature.");}// Never get here.return (0);}static const struct luaL_reg file_lib[] ={{ "marshall", file_marshall },{ "marshall_meta", file_marshall_meta },{ "unmarshall_meta", file_unmarshall_meta },{ "unmarshall_number", file_unmarshall_number },{ "unmarshall_string", file_unmarshall_string },{ "unmarshall_fn", file_unmarshall_fn },{ NULL, NULL }};LUARET1(you_can_hear_pos, boolean,player_can_hear(coord_def(luaL_checkint(ls,1), luaL_checkint(ls, 2))))LUARET1(you_x_pos, number, you.pos().x)LUARET1(you_y_pos, number, you.pos().y)LUARET2(you_pos, number, you.pos().x, you.pos().y)// see_cell should not be exposed to user scripts. The game should// never disclose grid coordinates to the player. Therefore we load it// only into the core Lua interpreter (dlua), never into the user// script interpreter (clua).LUARET1(you_see_cell, boolean,see_cell(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))LUARET1(you_see_cell_no_trans, boolean,see_cell_no_trans(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))LUAFN(you_moveto){const coord_def place(luaL_checkint(ls, 1), luaL_checkint(ls, 2));ASSERT(map_bounds(place));you.moveto(place);return (0);}LUAFN(you_random_teleport){you_teleport_now(false, false);return (0);}LUAFN(you_losight){calc_show_los();return (0);}static const struct luaL_reg you_lib[] ={{ "hear_pos", you_can_hear_pos },{ "x_pos", you_x_pos },{ "y_pos", you_y_pos },{ "pos", you_pos },{ "moveto", you_moveto },{ "see_cell", you_see_cell },{ "see_cell_no_trans", you_see_cell_no_trans },{ "random_teleport", you_random_teleport },{ "losight", you_losight },{ NULL, NULL }};static int dgnevent_type(lua_State *ls){DEVENT(ls, 1, dev);PLUARET(number, dev->type);}static int dgnevent_place(lua_State *ls){DEVENT(ls, 1, dev);lua_pushnumber(ls, dev->place.x);lua_pushnumber(ls, dev->place.y);return (2);}static int dgnevent_dest(lua_State *ls){DEVENT(ls, 1, dev);lua_pushnumber(ls, dev->dest.x);lua_pushnumber(ls, dev->dest.y);return (2);}static int dgnevent_ticks(lua_State *ls){DEVENT(ls, 1, dev);PLUARET(number, dev->elapsed_ticks);}static int dgnevent_arg1(lua_State *ls){DEVENT(ls, 1, dev);PLUARET(number, dev->arg1);}static int dgnevent_arg2(lua_State *ls){DEVENT(ls, 1, dev);PLUARET(number, dev->arg2);}static const struct luaL_reg dgnevent_lib[] ={{ "type", dgnevent_type },{ "pos", dgnevent_place },{ "dest", dgnevent_dest },{ "ticks", dgnevent_ticks },{ "arg1", dgnevent_arg1 },{ "arg2", dgnevent_arg2 },{ NULL, NULL }};void luaopen_setmeta(lua_State *ls,const char *global,const luaL_reg *lua_lib,const char *meta){luaL_newmetatable(ls, meta);lua_setglobal(ls, global);luaL_openlib(ls, global, lua_lib, 0);// Do <global>.__index = <global>lua_pushstring(ls, "__index");lua_pushvalue(ls, -2);lua_settable(ls, -3);}static void luaopen_dgnevent(lua_State *ls){luaopen_setmeta(ls, "dgnevent", dgnevent_lib, DEVENT_METATABLE);}static int mapmarker_pos(lua_State *ls){MAPMARKER(ls, 1, mark);lua_pushnumber(ls, mark->pos.x);lua_pushnumber(ls, mark->pos.y);return (2);}static int mapmarker_move(lua_State *ls){MAPMARKER(ls, 1, mark);const coord_def dest( luaL_checkint(ls, 2), luaL_checkint(ls, 3) );env.markers.move_marker(mark, dest);return (0);}static const struct luaL_reg mapmarker_lib[] ={{ "pos", mapmarker_pos },{ "move", mapmarker_move },{ NULL, NULL }};static void luaopen_mapmarker(lua_State *ls){luaopen_setmeta(ls, "mapmarker", mapmarker_lib, MAPMARK_METATABLE);}// Return the integer stored in the table (on the stack) with the key name.// If the key doesn't exist or the value is the wrong type, return defval.static int _table_int(lua_State *ls, int idx, const char *name, int defval){lua_pushstring(ls, name);lua_gettable(ls, idx < 0 ? idx - 1 : idx);bool nil = lua_isnil(ls, idx);bool valid = lua_isnumber(ls, idx);if (!nil && !valid)luaL_error(ls, "'%s' in table, but not an int.", name);int ret = (!nil && valid ? lua_tonumber(ls, idx) : defval);lua_pop(ls, 1);return (ret);}// Return the character stored in the table (on the stack) with the key name.// If the key doesn't exist or the value is the wrong type, return defval.static char _table_char(lua_State *ls, int idx, const char *name, char defval){lua_pushstring(ls, name);lua_gettable(ls, idx < 0 ? idx - 1 : idx);bool nil = lua_isnil(ls, idx);bool valid = lua_isstring(ls, idx);if (!nil && !valid)luaL_error(ls, "'%s' in table, but not a string.", name);char ret = defval;if (!nil && valid){const char *str = lua_tostring(ls, idx);if (str[0] && !str[1])ret = str[0];elseluaL_error(ls, "'%s' has more than one character.", name);}lua_pop(ls, 1);return (ret);}// Return the string stored in the table (on the stack) with the key name.// If the key doesn't exist or the value is the wrong type, return defval.static const char* _table_str(lua_State *ls, int idx, const char *name, const char *defval){lua_pushstring(ls, name);lua_gettable(ls, idx < 0 ? idx - 1 : idx);bool nil = lua_isnil(ls, idx);bool valid = lua_isstring(ls, idx);if (!nil && !valid)luaL_error(ls, "'%s' in table, but not a string.", name);const char *ret = (!nil && valid ? lua_tostring(ls, idx) : defval);lua_pop(ls, 1);return (ret);}// Return the boolean stored in the table (on the stack) with the key name.// If the key doesn't exist or the value is the wrong type, return defval.static bool _table_bool(lua_State *ls, int idx, const char *name, bool defval){lua_pushstring(ls, name);lua_gettable(ls, idx < 0 ? idx - 1 : idx);bool nil = lua_isnil(ls, idx);bool valid = lua_isboolean(ls, idx);if (!nil && !valid)luaL_error(ls, "'%s' in table, but not a bool.", name);bool ret = (!nil && valid ? lua_toboolean(ls, idx) : defval);lua_pop(ls, 1);return (ret);}#define BF_INT(ls, val, def) int val = _table_int(ls, -1, #val, def);#define BF_CHAR(ls, val, def) char val = _table_char(ls, -1, #val, def);#define BF_STR(ls, val, def) const char *val = _table_str(ls, -1, #val, def);#define BF_BOOL(ls, val, def) bool val = _table_bool(ls, -1, #val, def);static void bf_octa_room(lua_State *ls, map_lines &lines){int default_oblique = std::min(lines.width(), lines.height()) / 2 - 1;BF_INT(ls, oblique, default_oblique);BF_CHAR(ls, outside, 'x');BF_CHAR(ls, inside, '.');BF_STR(ls, replace, ".");coord_def tl, br;if (!lines.find_bounds(replace, tl, br))return;for (rectangle_iterator ri(tl, br); ri; ++ri){const coord_def mc = *ri;char glyph = lines(mc);if (replace[0] && !strchr(replace, glyph))continue;int ob = 0;ob += std::max(oblique + tl.x - mc.x, 0);ob += std::max(oblique + mc.x - br.x, 0);bool is_inside = (mc.y >= tl.y + ob && mc.y <= br.y - ob);lines(mc) = is_inside ? inside : outside;}}static void bf_smear(lua_State *ls, map_lines &lines){BF_INT(ls, iterations, 1);BF_CHAR(ls, smear, 'x');BF_STR(ls, onto, ".");BF_BOOL(ls, boxy, false);const int max_test_per_iteration = 10;int sanity = 0;int max_sanity = iterations * max_test_per_iteration;for (int i = 0; i < iterations; i++){bool diagonals, straights;coord_def mc;do{do{sanity++;mc.x = random_range(1, lines.width() - 2);mc.y = random_range(1, lines.height() - 2);}while (onto[0] && !strchr(onto, lines(mc)));// Prevent too many iterations.if (sanity > max_sanity)return;// Is there a "smear" feature along the diagonal from mc?diagonals = lines(coord_def(mc.x+1, mc.y+1)) == smear ||lines(coord_def(mc.x-1, mc.y+1)) == smear ||lines(coord_def(mc.x-1, mc.y-1)) == smear ||lines(coord_def(mc.x+1, mc.y-1)) == smear;// Is there a "smear" feature up, down, left, or right from mc?straights = lines(coord_def(mc.x+1, mc.y)) == smear ||lines(coord_def(mc.x-1, mc.y)) == smear ||lines(coord_def(mc.x, mc.y+1)) == smear ||lines(coord_def(mc.x, mc.y-1)) == smear;}while (!straights && (boxy || !diagonals));lines(mc) = smear;}}static void bf_extend(lua_State *ls, map_lines &lines){BF_INT(ls, height, 1);BF_INT(ls, width, 1);BF_CHAR(ls, fill, 'x');lines.extend(width, height, fill);}typedef void (*bf_func)(lua_State *ls, map_lines &lines);struct bf_entry{const char* name;bf_func func;};// Create a separate list of builder funcs so that we can automatically// generate a list of closures for them, rather than individually// and explicitly exposing them to the dgn namespace.static struct bf_entry bf_map[] ={{ "map_octa_room", &bf_octa_room },{ "map_smear", &bf_smear },{ "map_extend", &bf_extend }};static int dgn_call_builder_func(lua_State *ls){// This function gets called for all the builder functions that// operate on map_lines.MAP(ls, 1, map);if (!lua_istable(ls, 2) && !lua_isfunction(ls, 2))return luaL_argerror(ls, 2, "Expected table");bf_func *func = (bf_func *)lua_topointer(ls, lua_upvalueindex(1));if (!func)return luaL_error(ls, "Expected C function in closure upval");// Put the table on top.lua_settop(ls, 2);// Call the builder func itself.(*func)(ls, map->map);return (0);}static void _register_builder_funcs(lua_State *ls){lua_getglobal(ls, "dgn");const size_t num_entries = sizeof(bf_map) / sizeof(bf_entry);for (size_t i = 0; i < num_entries; i++){// Push a closure with the C function into the dgn table.lua_pushlightuserdata(ls, &bf_map[i].func);lua_pushcclosure(ls, &dgn_call_builder_func, 1);lua_setfield(ls, -2, bf_map[i].name);}lua_pop(ls, 1);}void init_dungeon_lua(){lua_stack_cleaner clean(dlua);luaL_openlib(dlua, "dgn", dgn_lib, 0);// Add additional function to the Crawl module.luaL_openlib(dlua, "crawl", crawl_lib, 0);luaL_openlib(dlua, "file", file_lib, 0);luaL_openlib(dlua, "you", you_lib, 0);luaL_openlib(dlua, "los", los_lib, 0);dlua.execfile("clua/dungeon.lua", true, true);dlua.execfile("clua/luamark.lua", true, true);lua_getglobal(dlua, "dgn_run_map");luaopen_debug(dlua);luaL_newmetatable(dlua, MAP_METATABLE);luaopen_dgnevent(dlua);luaopen_mapmarker(dlua);luaopen_ray(dlua);_register_builder_funcs(dlua);register_mapdef_tables(dlua);}// Can be called from within a debugger to look at the current Lua// call stack. (Borrowed from ToME 3)void print_dlua_stack(void){struct lua_Debug dbg;int i = 0;lua_State *L = dlua.state();fprintf(stderr, EOL);while (lua_getstack(L, i++, &dbg) == 1){lua_getinfo(L, "lnuS", &dbg);char* file = strrchr(dbg.short_src, '/');if (file == NULL)file = dbg.short_src;elsefile++;fprintf(stderr, "%s, function %s, line %d" EOL, file,dbg.name, dbg.currentline);}fprintf(stderr, EOL);}