diff options
author | Robert Vollmert <rvollmert@gmx.net> | 2009-10-20 16:06:40 +0200 |
---|---|---|
committer | Robert Vollmert <rvollmert@gmx.net> | 2009-10-20 16:06:40 +0200 |
commit | 7c97899cefb5ed1dd3547b9800f96b5a4cb24bf6 (patch) | |
tree | d5919fca6288501561cafd6332ad2a72fb1183f4 /crawl-ref | |
parent | fb872b6780842d10abf30d9fc1cff7273039b765 (diff) | |
download | crawl-ref-7c97899cefb5ed1dd3547b9800f96b5a4cb24bf6.tar.gz crawl-ref-7c97899cefb5ed1dd3547b9800f96b5a4cb24bf6.zip |
Move clua crawl_lib from clua to l_crawl.cc.
To avoid name clashes, rename dlua libs from *_lib to *_dlib.
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/clua.cc | 571 | ||||
-rw-r--r-- | crawl-ref/source/dlua.cc | 29 | ||||
-rw-r--r-- | crawl-ref/source/l_crawl.cc | 593 | ||||
-rw-r--r-- | crawl-ref/source/l_debug.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/l_dgn.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/l_dgnbld.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/l_dgnevt.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/l_dgngrd.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/l_dgnit.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/l_dgnlvl.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/l_dgnmon.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/l_dgntil.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/l_file.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/l_libs.h | 36 | ||||
-rw-r--r-- | crawl-ref/source/l_los.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/l_mapmrk.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/l_you.cc | 2 |
17 files changed, 649 insertions, 617 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc index 44f4cd0393..e71f432229 100644 --- a/crawl-ref/source/clua.cc +++ b/crawl-ref/source/clua.cc @@ -9,6 +9,7 @@ #include <sstream> #include "clua.h" +#include "l_libs.h" #include "abl-show.h" #include "artefact.h" @@ -593,7 +594,6 @@ extern void luaopen_kills(lua_State *ls); void luaopen_you(lua_State *ls); void luaopen_item(lua_State *ls); void luaopen_food(lua_State *ls); -void luaopen_crawl(lua_State *ls); void luaopen_file(lua_State *ls); void luaopen_options(lua_State *ls); void luaopen_monsters(lua_State *ls); @@ -623,7 +623,7 @@ void CLua::init_lua() luaopen_you(_state); luaopen_item(_state); luaopen_food(_state); - luaopen_crawl(_state); + cluaopen_crawl(_state); luaopen_file(_state); luaopen_options(_state); luaopen_monsters(_state); @@ -1784,573 +1784,6 @@ void luaopen_food(lua_State *ls) luaL_openlib(ls, "food", food_lib, 0); } -///////////////////////////////////////////////////////////////////// -// General game bindings. -// - -static int crawl_mpr(lua_State *ls) -{ - if (!crawl_state.io_inited) - return (0); - - const char *message = luaL_checkstring(ls, 1); - if (!message) - return (0); - - int ch = MSGCH_PLAIN; - if (lua_isnumber(ls, 2)) - ch = luaL_checkint(ls, 2); - else - { - const char *channel = lua_tostring(ls, 2); - if (channel) - ch = str_to_channel(channel); - } - - if (ch < 0 || ch >= NUM_MESSAGE_CHANNELS) - ch = MSGCH_PLAIN; - - mpr(message, static_cast<msg_channel_type>(ch)); - return (0); -} - -static int crawl_formatted_mpr(lua_State *ls) -{ - if (!crawl_state.io_inited) - return (0); - - const char *message = luaL_checkstring(ls, 1); - if (!message) - return (0); - - int ch = MSGCH_PLAIN; - if (lua_isnumber(ls, 2)) - ch = luaL_checkint(ls, 2); - else - { - const char *channel = lua_tostring(ls, 2); - if (channel) - ch = str_to_channel(channel); - } - - if (ch < 0 || ch >= NUM_MESSAGE_CHANNELS) - ch = MSGCH_PLAIN; - - formatted_mpr(formatted_string::parse_string(message), - static_cast<msg_channel_type>(ch)); - return (0); -} - -LUAWRAP(crawl_more, more()) -LUAWRAP(crawl_mesclr, mesclr()) -LUAWRAP(crawl_redraw_screen, redraw_screen()) - -static int crawl_input_line(lua_State *ls) -{ - // This is arbitrary, but anybody entering so many characters is psychotic. - char linebuf[500]; - - get_input_line(linebuf, sizeof linebuf); - lua_pushstring(ls, linebuf); - return (1); -} - -static int crawl_c_input_line(lua_State *ls) -{ - char linebuf[500]; - - bool valid = !cancelable_get_line(linebuf, sizeof linebuf); - if (valid) - lua_pushstring(ls, linebuf); - else - lua_pushnil(ls); - return (1); -} - -LUARET1(crawl_getch, number, getch()) -LUARET1(crawl_kbhit, number, kbhit()) -LUAWRAP(crawl_flush_input, flush_input_buffer(FLUSH_LUA)) - -static char _lua_char(lua_State *ls, int ndx, char defval = 0) -{ - return (lua_isnone(ls, ndx) || !lua_isstring(ls, ndx)? defval - : lua_tostring(ls, ndx)[0]); -} - -static int crawl_yesno(lua_State *ls) -{ - const char *prompt = luaL_checkstring(ls, 1); - const bool safe = lua_toboolean(ls, 2); - const int safeanswer = _lua_char(ls, 3); - const bool clear_after = - lua_isnone(ls, 4) ? true : lua_toboolean(ls, 4); - const bool interrupt_delays = - lua_isnone(ls, 5) ? true : lua_toboolean(ls, 5); - const bool noprompt = - lua_isnone(ls, 6) ? false : lua_toboolean(ls, 6); - - cursor_control con(true); - lua_pushboolean(ls, yesno(prompt, safe, safeanswer, clear_after, - interrupt_delays, noprompt)); - return (1); -} - -static int crawl_yesnoquit(lua_State *ls) -{ - const char *prompt = luaL_checkstring(ls, 1); - const bool safe = lua_toboolean(ls, 2); - const int safeanswer = _lua_char(ls, 3); - const bool allow_all = - lua_isnone(ls, 4) ? false : lua_toboolean(ls, 4); - const bool clear_after = - lua_isnone(ls, 5) ? true : lua_toboolean(ls, 5); - - // Skipping the other params until somebody needs them. - - cursor_control con(true); - lua_pushnumber(ls, yesnoquit(prompt, safe, safeanswer, allow_all, - clear_after)); - return (1); -} - -static void crawl_sendkeys_proc(lua_State *ls, int argi) -{ - if (lua_isstring(ls, argi)) - { - const char *keys = luaL_checkstring(ls, argi); - if (!keys) - return; - - for ( ; *keys; ++keys) - macro_buf_add(*keys); - } - else if (lua_istable(ls, argi)) - { - for (int i = 1; ; ++i) - { - lua_rawgeti(ls, argi, i); - if (lua_isnil(ls, -1)) - { - lua_pop(ls, 1); - return; - } - - crawl_sendkeys_proc(ls, lua_gettop(ls)); - lua_pop(ls, 1); - } - } - else if (lua_isnumber(ls, argi)) - { - int key = luaL_checkint(ls, argi); - macro_buf_add(key); - } -} - -static int crawl_sendkeys(lua_State *ls) -{ - int top = lua_gettop(ls); - for (int i = 1; i <= top; ++i) - crawl_sendkeys_proc(ls, i); - return (0); -} - -// Tell Crawl to process one command. -static int crawl_process_command(lua_State *ls) -{ - const bool will_process = - current_delay_action() == DELAY_MACRO || !you_are_delayed(); - - if (will_process) - { - // This should only be called from a macro delay, but run_macro - // may not have started the macro delay; do so now. - if (!you_are_delayed()) - start_delay(DELAY_MACRO, 1); - start_delay(DELAY_MACRO_PROCESS_KEY, 1); - } - - lua_pushboolean(ls, will_process); - return (1); -} - -static int crawl_playsound(lua_State *ls) -{ - const char *sf = luaL_checkstring(ls, 1); - if (!sf) - return (0); - play_sound(sf); - return (0); -} - -static int crawl_runmacro(lua_State *ls) -{ - const char *macroname = luaL_checkstring(ls, 1); - if (!macroname) - return (0); - run_macro(macroname); - return (0); -} - -static int crawl_setopt(lua_State *ls) -{ - if (!lua_isstring(ls, 1)) - return (0); - - const char *s = lua_tostring(ls, 1); - if (s) - { - // Note that the conditional script can contain nested Lua[ ]Lua code. - read_options(s, true); - } - - return (0); -} - -static int crawl_read_options(lua_State *ls) -{ - if (!lua_isstring(ls, 1)) - return (0); - - const char* filename = lua_tostring(ls, 1); - Options.include(filename, true, true); - return (0); -} - -static int crawl_bindkey(lua_State *ls) -{ - const char *s = NULL; - if (lua_isstring(ls, 1)) - { - s = lua_tostring(ls, 1); - } - - if (!s || !lua_isfunction(ls, 2) || lua_gettop(ls) != 2) - return (0); - - lua_pushvalue(ls, 2); - std::string name = clua.setuniqregistry(); - if (lua_gettop(ls) != 2) - { - fprintf(stderr, "Stack top has changed!\n"); - lua_settop(ls, 2); - } - macro_userfn(s, name.c_str()); - return (0); -} - -static int crawl_msgch_num(lua_State *ls) -{ - const char *s = luaL_checkstring(ls, 1); - if (!s) - return (0); - int ch = str_to_channel(s); - if (ch == -1) - return (0); - - lua_pushnumber(ls, ch); - return (1); -} - -static int crawl_msgch_name(lua_State *ls) -{ - int num = luaL_checkint(ls, 1); - std::string name = channel_to_str(num); - lua_pushstring(ls, name.c_str()); - return (1); -} - -static int crawl_take_note(lua_State *ls) -{ - const char* msg = luaL_checkstring(ls, 1); - take_note(Note(NOTE_MESSAGE, 0, 0, msg)); - return (0); -} - -#define REGEX_METATABLE "crawl.regex" -#define MESSF_METATABLE "crawl.messf" - -static int crawl_regex(lua_State *ls) -{ - const char *s = luaL_checkstring(ls, 1); - if (!s) - return (0); - - - text_pattern **tpudata = - clua_new_userdata< text_pattern* >(ls, REGEX_METATABLE); - if (tpudata) - { - *tpudata = new text_pattern(s); - return (1); - } - return (0); -} - -static int crawl_regex_find(lua_State *ls) -{ - text_pattern **pattern = - clua_get_userdata< text_pattern* >(ls, REGEX_METATABLE); - if (!pattern) - return (0); - - const char *text = luaL_checkstring(ls, -1); - if (!text) - return (0); - - lua_pushboolean(ls, (*pattern)->matches(text)); - return (1); -} - -static const luaL_reg crawl_regex_ops[] = -{ - { "matches", crawl_regex_find }, - { NULL, NULL } -}; - -static int crawl_message_filter(lua_State *ls) -{ - const char *pattern = luaL_checkstring(ls, 1); - if (!pattern) - return (0); - - int num = lua_isnumber(ls, 2)? luaL_checkint(ls, 2) : -1; - message_filter **mf = - clua_new_userdata< message_filter* >( ls, MESSF_METATABLE ); - if (mf) - { - *mf = new message_filter( num, pattern ); - return (1); - } - return (0); -} - -static int crawl_messf_matches(lua_State *ls) -{ - message_filter **mf = - clua_get_userdata< message_filter* >(ls, MESSF_METATABLE); - if (!mf) - return (0); - - const char *pattern = luaL_checkstring(ls, 2); - int ch = luaL_checkint(ls, 3); - if (pattern) - { - bool filt = (*mf)->is_filtered(ch, pattern); - lua_pushboolean(ls, filt); - return (1); - } - return (0); -} - -static const luaL_reg crawl_messf_ops[] = -{ - { "matches", crawl_messf_matches }, - { NULL, NULL } -}; - -static int crawl_trim(lua_State *ls) -{ - const char *s = luaL_checkstring(ls, 1); - if (!s) - return (0); - std::string text = s; - trim_string(text); - lua_pushstring(ls, text.c_str()); - return (1); -} - -static int crawl_split(lua_State *ls) -{ - const char *s = luaL_checkstring(ls, 1), - *token = luaL_checkstring(ls, 2); - if (!s || !token) - return (0); - - std::vector<std::string> segs = split_string(token, s); - lua_newtable(ls); - for (int i = 0, count = segs.size(); i < count; ++i) - { - lua_pushstring(ls, segs[i].c_str()); - lua_rawseti(ls, -2, i + 1); - } - return (1); -} - -static int _crawl_grammar(lua_State *ls) -{ - description_level_type ndesc = DESC_PLAIN; - if (lua_isstring(ls, 2)) - ndesc = description_type_by_name(lua_tostring(ls, 2)); - PLUARET(string, - thing_do_grammar(ndesc, false, - false, luaL_checkstring(ls, 1)).c_str()); -} - -static int crawl_article_a(lua_State *ls) -{ - const char *s = luaL_checkstring(ls, 1); - - bool lowercase = true; - if (lua_isboolean(ls, 2)) - lowercase = lua_toboolean(ls, 2); - - lua_pushstring(ls, article_a(s, lowercase).c_str()); - - return (1); -} - -LUARET1(crawl_game_started, boolean, crawl_state.need_save) -LUARET1(crawl_random2, number, random2( luaL_checkint(ls, 1) )) -LUARET1(crawl_one_chance_in, boolean, one_chance_in( luaL_checkint(ls, 1) )) -LUARET1(crawl_random2avg, number, - random2avg( luaL_checkint(ls, 1), luaL_checkint(ls, 2) )) -LUARET1(crawl_random_range, number, - random_range( luaL_checkint(ls, 1), luaL_checkint(ls, 2), - lua_isnumber(ls, 3)? luaL_checkint(ls, 3) : 1 )) -LUARET1(crawl_coinflip, boolean, coinflip()) -LUARET1(crawl_roll_dice, number, - lua_gettop(ls) == 1 - ? roll_dice( 1, luaL_checkint(ls, 1) ) - : roll_dice( luaL_checkint(ls, 1), luaL_checkint(ls, 2) )) - -static int crawl_random_element(lua_State *ls) -{ - const int table_idx = 1; - const int value_idx = 2; - - if (lua_gettop(ls) == 0) - { - lua_pushnil(ls); - return 1; - } - - // Only the first arg does anything now. Maybe this should - // select from a variable number of table args? - lua_pop(ls, lua_gettop(ls) - 1); - - // Keep max value on the stack, as it could be any type of value. - lua_pushnil(ls); - int rollsize = 0; - - lua_pushnil(ls); - while (lua_next(ls, table_idx) != 0) - { - const int weight_idx = -1; - const int key_idx = -2; - - int this_weight = lua_isnil(ls, weight_idx) ? - 1 : (int)lua_tonumber(ls, weight_idx); - - if (rollsize > 0) - { - rollsize += this_weight; - if (x_chance_in_y(this_weight, rollsize)) - { - lua_pushvalue(ls, key_idx); - lua_replace(ls, value_idx); - } - } - else - { - lua_pushvalue(ls, key_idx); - lua_replace(ls, value_idx); - rollsize = this_weight; - } - - lua_pop(ls, 1); - } - - lua_pushvalue(ls, value_idx); - - return 1; -} - -static int crawl_err_trace(lua_State *ls) -{ - const int nargs = lua_gettop(ls); - const int err = lua_pcall(ls, nargs - 1, LUA_MULTRET, 0); - - if (err) - { - // This code from lua.c:traceback() (mostly) - const char *errs = lua_tostring(ls, 1); - std::string errstr = errs? errs : ""; - lua_getfield(ls, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(ls, -1)) - { - lua_pop(ls, 1); - return lua_error(ls); - } - lua_getfield(ls, -1, "traceback"); - if (!lua_isfunction(ls, -1)) - { - lua_pop(ls, 2); - return lua_error(ls); - } - lua_pushvalue(ls, 1); - lua_pushinteger(ls, 2); // Skip crawl_err_trace and traceback. - lua_call(ls, 2, 1); - - // What's on top should be the error. - lua_error(ls); - } - - return (lua_gettop(ls)); -} - -static const struct luaL_reg crawl_lib[] = -{ - { "mpr", crawl_mpr }, - { "formatted_mpr", crawl_formatted_mpr }, - { "more", crawl_more }, - { "mesclr", crawl_mesclr }, - { "random2", crawl_random2 }, - { "one_chance_in", crawl_one_chance_in }, - { "random2avg" , crawl_random2avg }, - { "coinflip", crawl_coinflip }, - { "roll_dice", crawl_roll_dice }, - { "random_range", crawl_random_range }, - { "random_element", crawl_random_element }, - { "redraw_screen", crawl_redraw_screen }, - { "input_line", crawl_input_line }, - { "c_input_line", crawl_c_input_line}, - { "getch", crawl_getch }, - { "yesno", crawl_yesno }, - { "yesnoquit", crawl_yesnoquit }, - { "kbhit", crawl_kbhit }, - { "flush_input", crawl_flush_input }, - { "sendkeys", crawl_sendkeys }, - { "process_command", crawl_process_command }, - { "playsound", crawl_playsound }, - { "runmacro", crawl_runmacro }, - { "bindkey", crawl_bindkey }, - { "setopt", crawl_setopt }, - { "read_options", crawl_read_options }, - { "msgch_num", crawl_msgch_num }, - { "msgch_name", crawl_msgch_name }, - { "take_note", crawl_take_note }, - - { "regex", crawl_regex }, - { "message_filter", crawl_message_filter }, - { "trim", crawl_trim }, - { "split", crawl_split }, - { "grammar", _crawl_grammar }, - { "article_a", crawl_article_a }, - { "game_started", crawl_game_started }, - { "err_trace", crawl_err_trace }, - - { NULL, NULL }, -}; - -void luaopen_crawl(lua_State *ls) -{ - clua_register_metatable(ls, REGEX_METATABLE, crawl_regex_ops, - lua_object_gc<text_pattern>); - clua_register_metatable(ls, MESSF_METATABLE, crawl_messf_ops, - lua_object_gc<message_filter>); - - luaL_openlib(ls, "crawl", crawl_lib, 0); -} /////////////////////////////////////////////////////////// // File operations diff --git a/crawl-ref/source/dlua.cc b/crawl-ref/source/dlua.cc index 4461a99748..27898f1b81 100644 --- a/crawl-ref/source/dlua.cc +++ b/crawl-ref/source/dlua.cc @@ -306,20 +306,21 @@ void init_dungeon_lua() { lua_stack_cleaner clean(dlua); - luaL_openlib(dlua, "dgn", dgn_lib, 0); - luaL_openlib(dlua, "dgn", dgn_build_lib, 0); - luaL_openlib(dlua, "dgn", dgn_event_lib, 0); - luaL_openlib(dlua, "dgn", dgn_grid_lib, 0); - luaL_openlib(dlua, "dgn", dgn_item_lib, 0); - luaL_openlib(dlua, "dgn", dgn_level_lib, 0); - luaL_openlib(dlua, "dgn", dgn_mons_lib, 0); - luaL_openlib(dlua, "dgn", dgn_tile_lib, 0); - - luaL_openlib(dlua, "crawl", crawl_lib, 0); - luaL_openlib(dlua, "debug", debug_lib, 0); - luaL_openlib(dlua, "file", file_lib, 0); - luaL_openlib(dlua, "you", you_lib, 0); - luaL_openlib(dlua, "los", los_lib, 0); + dluaopen_crawl(dlua); + + luaL_openlib(dlua, "dgn", dgn_dlib, 0); + luaL_openlib(dlua, "dgn", dgn_build_dlib, 0); + luaL_openlib(dlua, "dgn", dgn_event_dlib, 0); + luaL_openlib(dlua, "dgn", dgn_grid_dlib, 0); + luaL_openlib(dlua, "dgn", dgn_item_dlib, 0); + luaL_openlib(dlua, "dgn", dgn_level_dlib, 0); + luaL_openlib(dlua, "dgn", dgn_mons_dlib, 0); + luaL_openlib(dlua, "dgn", dgn_tile_dlib, 0); + + luaL_openlib(dlua, "debug", debug_dlib, 0); + luaL_openlib(dlua, "file", file_dlib, 0); + luaL_openlib(dlua, "you", you_dlib, 0); + luaL_openlib(dlua, "los", los_dlib, 0); dlua.execfile("clua/dungeon.lua", true, true); dlua.execfile("clua/luamark.lua", true, true); diff --git a/crawl-ref/source/l_crawl.cc b/crawl-ref/source/l_crawl.cc index b50a407a49..5f248e8dc8 100644 --- a/crawl-ref/source/l_crawl.cc +++ b/crawl-ref/source/l_crawl.cc @@ -1,9 +1,24 @@ +/* + * File: l_crawl.cc + * Summary: General game bindings. + */ + #include "AppHdr.h" +#include "clua.h" #include "dlua.h" #include "l_libs.h" + +#include "cio.h" +#include "delay.h" +#include "directn.h" +#include "format.h" #include "initfile.h" #include "itemname.h" +#include "macro.h" +#include "message.h" +#include "notes.h" +#include "player.h" #include "stuff.h" #include "view.h" @@ -12,6 +27,578 @@ #include <time.h> #endif +///////////////////////////////////////////////////////////////////// +// User accessible +// + +static int crawl_mpr(lua_State *ls) +{ + if (!crawl_state.io_inited) + return (0); + + const char *message = luaL_checkstring(ls, 1); + if (!message) + return (0); + + int ch = MSGCH_PLAIN; + if (lua_isnumber(ls, 2)) + ch = luaL_checkint(ls, 2); + else + { + const char *channel = lua_tostring(ls, 2); + if (channel) + ch = str_to_channel(channel); + } + + if (ch < 0 || ch >= NUM_MESSAGE_CHANNELS) + ch = MSGCH_PLAIN; + + mpr(message, static_cast<msg_channel_type>(ch)); + return (0); +} + +static int crawl_formatted_mpr(lua_State *ls) +{ + if (!crawl_state.io_inited) + return (0); + + const char *message = luaL_checkstring(ls, 1); + if (!message) + return (0); + + int ch = MSGCH_PLAIN; + if (lua_isnumber(ls, 2)) + ch = luaL_checkint(ls, 2); + else + { + const char *channel = lua_tostring(ls, 2); + if (channel) + ch = str_to_channel(channel); + } + + if (ch < 0 || ch >= NUM_MESSAGE_CHANNELS) + ch = MSGCH_PLAIN; + + formatted_mpr(formatted_string::parse_string(message), + static_cast<msg_channel_type>(ch)); + return (0); +} + +LUAWRAP(crawl_more, more()) +LUAWRAP(crawl_mesclr, mesclr()) +LUAWRAP(crawl_redraw_screen, redraw_screen()) + +static int crawl_input_line(lua_State *ls) +{ + // This is arbitrary, but anybody entering so many characters is psychotic. + char linebuf[500]; + + get_input_line(linebuf, sizeof linebuf); + lua_pushstring(ls, linebuf); + return (1); +} + +static int crawl_c_input_line(lua_State *ls) +{ + char linebuf[500]; + + bool valid = !cancelable_get_line(linebuf, sizeof linebuf); + if (valid) + lua_pushstring(ls, linebuf); + else + lua_pushnil(ls); + return (1); +} + +LUARET1(crawl_getch, number, getch()) +LUARET1(crawl_kbhit, number, kbhit()) +LUAWRAP(crawl_flush_input, flush_input_buffer(FLUSH_LUA)) + +static char _lua_char(lua_State *ls, int ndx, char defval = 0) +{ + return (lua_isnone(ls, ndx) || !lua_isstring(ls, ndx)? defval + : lua_tostring(ls, ndx)[0]); +} + +static int crawl_yesno(lua_State *ls) +{ + const char *prompt = luaL_checkstring(ls, 1); + const bool safe = lua_toboolean(ls, 2); + const int safeanswer = _lua_char(ls, 3); + const bool clear_after = + lua_isnone(ls, 4) ? true : lua_toboolean(ls, 4); + const bool interrupt_delays = + lua_isnone(ls, 5) ? true : lua_toboolean(ls, 5); + const bool noprompt = + lua_isnone(ls, 6) ? false : lua_toboolean(ls, 6); + + cursor_control con(true); + lua_pushboolean(ls, yesno(prompt, safe, safeanswer, clear_after, + interrupt_delays, noprompt)); + return (1); +} + +static int crawl_yesnoquit(lua_State *ls) +{ + const char *prompt = luaL_checkstring(ls, 1); + const bool safe = lua_toboolean(ls, 2); + const int safeanswer = _lua_char(ls, 3); + const bool allow_all = + lua_isnone(ls, 4) ? false : lua_toboolean(ls, 4); + const bool clear_after = + lua_isnone(ls, 5) ? true : lua_toboolean(ls, 5); + + // Skipping the other params until somebody needs them. + + cursor_control con(true); + lua_pushnumber(ls, yesnoquit(prompt, safe, safeanswer, allow_all, + clear_after)); + return (1); +} + +static void crawl_sendkeys_proc(lua_State *ls, int argi) +{ + if (lua_isstring(ls, argi)) + { + const char *keys = luaL_checkstring(ls, argi); + if (!keys) + return; + + for ( ; *keys; ++keys) + macro_buf_add(*keys); + } + else if (lua_istable(ls, argi)) + { + for (int i = 1; ; ++i) + { + lua_rawgeti(ls, argi, i); + if (lua_isnil(ls, -1)) + { + lua_pop(ls, 1); + return; + } + + crawl_sendkeys_proc(ls, lua_gettop(ls)); + lua_pop(ls, 1); + } + } + else if (lua_isnumber(ls, argi)) + { + int key = luaL_checkint(ls, argi); + macro_buf_add(key); + } +} + +static int crawl_sendkeys(lua_State *ls) +{ + int top = lua_gettop(ls); + for (int i = 1; i <= top; ++i) + crawl_sendkeys_proc(ls, i); + return (0); +} + +// Tell Crawl to process one command. +static int crawl_process_command(lua_State *ls) +{ + const bool will_process = + current_delay_action() == DELAY_MACRO || !you_are_delayed(); + + if (will_process) + { + // This should only be called from a macro delay, but run_macro + // may not have started the macro delay; do so now. + if (!you_are_delayed()) + start_delay(DELAY_MACRO, 1); + start_delay(DELAY_MACRO_PROCESS_KEY, 1); + } + + lua_pushboolean(ls, will_process); + return (1); +} + +static int crawl_playsound(lua_State *ls) +{ + const char *sf = luaL_checkstring(ls, 1); + if (!sf) + return (0); + play_sound(sf); + return (0); +} + +static int crawl_runmacro(lua_State *ls) +{ + const char *macroname = luaL_checkstring(ls, 1); + if (!macroname) + return (0); + run_macro(macroname); + return (0); +} + +static int crawl_setopt(lua_State *ls) +{ + if (!lua_isstring(ls, 1)) + return (0); + + const char *s = lua_tostring(ls, 1); + if (s) + { + // Note that the conditional script can contain nested Lua[ ]Lua code. + read_options(s, true); + } + + return (0); +} + +static int crawl_read_options(lua_State *ls) +{ + if (!lua_isstring(ls, 1)) + return (0); + + const char* filename = lua_tostring(ls, 1); + Options.include(filename, true, true); + return (0); +} + +static int crawl_bindkey(lua_State *ls) +{ + const char *s = NULL; + if (lua_isstring(ls, 1)) + { + s = lua_tostring(ls, 1); + } + + if (!s || !lua_isfunction(ls, 2) || lua_gettop(ls) != 2) + return (0); + + lua_pushvalue(ls, 2); + std::string name = clua.setuniqregistry(); + if (lua_gettop(ls) != 2) + { + fprintf(stderr, "Stack top has changed!\n"); + lua_settop(ls, 2); + } + macro_userfn(s, name.c_str()); + return (0); +} + +static int crawl_msgch_num(lua_State *ls) +{ + const char *s = luaL_checkstring(ls, 1); + if (!s) + return (0); + int ch = str_to_channel(s); + if (ch == -1) + return (0); + + lua_pushnumber(ls, ch); + return (1); +} + +static int crawl_msgch_name(lua_State *ls) +{ + int num = luaL_checkint(ls, 1); + std::string name = channel_to_str(num); + lua_pushstring(ls, name.c_str()); + return (1); +} + +static int crawl_take_note(lua_State *ls) +{ + const char* msg = luaL_checkstring(ls, 1); + take_note(Note(NOTE_MESSAGE, 0, 0, msg)); + return (0); +} + +#define REGEX_METATABLE "crawl.regex" +#define MESSF_METATABLE "crawl.messf" + +static int crawl_regex(lua_State *ls) +{ + const char *s = luaL_checkstring(ls, 1); + if (!s) + return (0); + + + text_pattern **tpudata = + clua_new_userdata< text_pattern* >(ls, REGEX_METATABLE); + if (tpudata) + { + *tpudata = new text_pattern(s); + return (1); + } + return (0); +} + +static int crawl_regex_find(lua_State *ls) +{ + text_pattern **pattern = + clua_get_userdata< text_pattern* >(ls, REGEX_METATABLE); + if (!pattern) + return (0); + + const char *text = luaL_checkstring(ls, -1); + if (!text) + return (0); + + lua_pushboolean(ls, (*pattern)->matches(text)); + return (1); +} + +static const luaL_reg crawl_regex_ops[] = +{ + { "matches", crawl_regex_find }, + { NULL, NULL } +}; + +static int crawl_message_filter(lua_State *ls) +{ + const char *pattern = luaL_checkstring(ls, 1); + if (!pattern) + return (0); + + int num = lua_isnumber(ls, 2)? luaL_checkint(ls, 2) : -1; + message_filter **mf = + clua_new_userdata< message_filter* >( ls, MESSF_METATABLE ); + if (mf) + { + *mf = new message_filter( num, pattern ); + return (1); + } + return (0); +} + +static int crawl_messf_matches(lua_State *ls) +{ + message_filter **mf = + clua_get_userdata< message_filter* >(ls, MESSF_METATABLE); + if (!mf) + return (0); + + const char *pattern = luaL_checkstring(ls, 2); + int ch = luaL_checkint(ls, 3); + if (pattern) + { + bool filt = (*mf)->is_filtered(ch, pattern); + lua_pushboolean(ls, filt); + return (1); + } + return (0); +} + +static const luaL_reg crawl_messf_ops[] = +{ + { "matches", crawl_messf_matches }, + { NULL, NULL } +}; + +static int crawl_trim(lua_State *ls) +{ + const char *s = luaL_checkstring(ls, 1); + if (!s) + return (0); + std::string text = s; + trim_string(text); + lua_pushstring(ls, text.c_str()); + return (1); +} + +static int crawl_split(lua_State *ls) +{ + const char *s = luaL_checkstring(ls, 1), + *token = luaL_checkstring(ls, 2); + if (!s || !token) + return (0); + + std::vector<std::string> segs = split_string(token, s); + lua_newtable(ls); + for (int i = 0, count = segs.size(); i < count; ++i) + { + lua_pushstring(ls, segs[i].c_str()); + lua_rawseti(ls, -2, i + 1); + } + return (1); +} + +static int _crawl_grammar(lua_State *ls) +{ + description_level_type ndesc = DESC_PLAIN; + if (lua_isstring(ls, 2)) + ndesc = description_type_by_name(lua_tostring(ls, 2)); + PLUARET(string, + thing_do_grammar(ndesc, false, + false, luaL_checkstring(ls, 1)).c_str()); +} + +static int crawl_article_a(lua_State *ls) +{ + const char *s = luaL_checkstring(ls, 1); + + bool lowercase = true; + if (lua_isboolean(ls, 2)) + lowercase = lua_toboolean(ls, 2); + + lua_pushstring(ls, article_a(s, lowercase).c_str()); + + return (1); +} + +LUARET1(crawl_game_started, boolean, crawl_state.need_save) +LUARET1(crawl_random2, number, random2( luaL_checkint(ls, 1) )) +LUARET1(crawl_one_chance_in, boolean, one_chance_in( luaL_checkint(ls, 1) )) +LUARET1(crawl_random2avg, number, + random2avg( luaL_checkint(ls, 1), luaL_checkint(ls, 2) )) +LUARET1(crawl_random_range, number, + random_range( luaL_checkint(ls, 1), luaL_checkint(ls, 2), + lua_isnumber(ls, 3)? luaL_checkint(ls, 3) : 1 )) +LUARET1(crawl_coinflip, boolean, coinflip()) +LUARET1(crawl_roll_dice, number, + lua_gettop(ls) == 1 + ? roll_dice( 1, luaL_checkint(ls, 1) ) + : roll_dice( luaL_checkint(ls, 1), luaL_checkint(ls, 2) )) + +static int crawl_random_element(lua_State *ls) +{ + const int table_idx = 1; + const int value_idx = 2; + + if (lua_gettop(ls) == 0) + { + lua_pushnil(ls); + return 1; + } + + // Only the first arg does anything now. Maybe this should + // select from a variable number of table args? + lua_pop(ls, lua_gettop(ls) - 1); + + // Keep max value on the stack, as it could be any type of value. + lua_pushnil(ls); + int rollsize = 0; + + lua_pushnil(ls); + while (lua_next(ls, table_idx) != 0) + { + const int weight_idx = -1; + const int key_idx = -2; + + int this_weight = lua_isnil(ls, weight_idx) ? + 1 : (int)lua_tonumber(ls, weight_idx); + + if (rollsize > 0) + { + rollsize += this_weight; + if (x_chance_in_y(this_weight, rollsize)) + { + lua_pushvalue(ls, key_idx); + lua_replace(ls, value_idx); + } + } + else + { + lua_pushvalue(ls, key_idx); + lua_replace(ls, value_idx); + rollsize = this_weight; + } + + lua_pop(ls, 1); + } + + lua_pushvalue(ls, value_idx); + + return 1; +} + +static int crawl_err_trace(lua_State *ls) +{ + const int nargs = lua_gettop(ls); + const int err = lua_pcall(ls, nargs - 1, LUA_MULTRET, 0); + + if (err) + { + // This code from lua.c:traceback() (mostly) + const char *errs = lua_tostring(ls, 1); + std::string errstr = errs? errs : ""; + lua_getfield(ls, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(ls, -1)) + { + lua_pop(ls, 1); + return lua_error(ls); + } + lua_getfield(ls, -1, "traceback"); + if (!lua_isfunction(ls, -1)) + { + lua_pop(ls, 2); + return lua_error(ls); + } + lua_pushvalue(ls, 1); + lua_pushinteger(ls, 2); // Skip crawl_err_trace and traceback. + lua_call(ls, 2, 1); + + // What's on top should be the error. + lua_error(ls); + } + + return (lua_gettop(ls)); +} + +static const struct luaL_reg crawl_clib[] = +{ + { "mpr", crawl_mpr }, + { "formatted_mpr", crawl_formatted_mpr }, + { "more", crawl_more }, + { "mesclr", crawl_mesclr }, + { "random2", crawl_random2 }, + { "one_chance_in", crawl_one_chance_in }, + { "random2avg" , crawl_random2avg }, + { "coinflip", crawl_coinflip }, + { "roll_dice", crawl_roll_dice }, + { "random_range", crawl_random_range }, + { "random_element", crawl_random_element }, + { "redraw_screen", crawl_redraw_screen }, + { "input_line", crawl_input_line }, + { "c_input_line", crawl_c_input_line}, + { "getch", crawl_getch }, + { "yesno", crawl_yesno }, + { "yesnoquit", crawl_yesnoquit }, + { "kbhit", crawl_kbhit }, + { "flush_input", crawl_flush_input }, + { "sendkeys", crawl_sendkeys }, + { "process_command", crawl_process_command }, + { "playsound", crawl_playsound }, + { "runmacro", crawl_runmacro }, + { "bindkey", crawl_bindkey }, + { "setopt", crawl_setopt }, + { "read_options", crawl_read_options }, + { "msgch_num", crawl_msgch_num }, + { "msgch_name", crawl_msgch_name }, + { "take_note", crawl_take_note }, + + { "regex", crawl_regex }, + { "message_filter", crawl_message_filter }, + { "trim", crawl_trim }, + { "split", crawl_split }, + { "grammar", _crawl_grammar }, + { "article_a", crawl_article_a }, + { "game_started", crawl_game_started }, + { "err_trace", crawl_err_trace }, + + { NULL, NULL }, +}; + +void cluaopen_crawl(lua_State *ls) +{ + clua_register_metatable(ls, REGEX_METATABLE, crawl_regex_ops, + lua_object_gc<text_pattern>); + clua_register_metatable(ls, MESSF_METATABLE, crawl_messf_ops, + lua_object_gc<message_filter>); + + luaL_openlib(ls, "crawl", crawl_clib, 0); +} + +///////////////////////////////////////////////////////////////////// +// Non-user-accessible bindings (dlua). +// + LUAFN(_crawl_args) { return dlua_stringtable(ls, SysEnv.cmd_args); @@ -70,7 +657,7 @@ std::string _crawl_make_name(lua_State *ls) LUARET1(crawl_make_name, string, _crawl_make_name(ls).c_str()) -const struct luaL_reg crawl_lib[] = +static const struct luaL_reg crawl_dlib[] = { { "args", _crawl_args }, { "mark_milestone", _crawl_milestone }, @@ -82,3 +669,7 @@ const struct luaL_reg crawl_lib[] = { NULL, NULL } }; +void dluaopen_crawl(lua_State *ls) +{ + luaL_openlib(ls, "crawl", crawl_dlib, 0); +} diff --git a/crawl-ref/source/l_debug.cc b/crawl-ref/source/l_debug.cc index 4a52860822..ac7ca63654 100644 --- a/crawl-ref/source/l_debug.cc +++ b/crawl-ref/source/l_debug.cc @@ -70,7 +70,7 @@ LUAFN(_debug_test_explore) return (0); } -const struct luaL_reg debug_lib[] = +const struct luaL_reg debug_dlib[] = { { "goto_place", debug_goto_place }, { "flush_map_memory", debug_flush_map_memory }, diff --git a/crawl-ref/source/l_dgn.cc b/crawl-ref/source/l_dgn.cc index 3555c541b8..e640177406 100644 --- a/crawl-ref/source/l_dgn.cc +++ b/crawl-ref/source/l_dgn.cc @@ -1491,7 +1491,7 @@ LUAFN(_dgn_reuse_map) LUAWRAP(_dgn_reset_level, dgn_reset_level()) -const struct luaL_reg dgn_lib[] = +const struct luaL_reg dgn_dlib[] = { { "reset_level", _dgn_reset_level }, diff --git a/crawl-ref/source/l_dgnbld.cc b/crawl-ref/source/l_dgnbld.cc index a13a59f56a..bb51b62bf4 100644 --- a/crawl-ref/source/l_dgnbld.cc +++ b/crawl-ref/source/l_dgnbld.cc @@ -338,7 +338,7 @@ static int dgn_fill_disconnected_zones(lua_State *ls) return 0; } -const struct luaL_reg dgn_build_lib[] = +const struct luaL_reg dgn_build_dlib[] = { { "grd_table", dgn_grd_table }, { "width", dgn_width }, diff --git a/crawl-ref/source/l_dgnevt.cc b/crawl-ref/source/l_dgnevt.cc index 73574309fe..f776f5c402 100644 --- a/crawl-ref/source/l_dgnevt.cc +++ b/crawl-ref/source/l_dgnevt.cc @@ -49,7 +49,7 @@ static int dgnevent_arg2(lua_State *ls) PLUARET(number, dev->arg2); } -static const struct luaL_reg dgnevent_lib[] = +static const struct luaL_reg dgnevent_dlib[] = { { "type", dgnevent_type }, { "pos", dgnevent_place }, @@ -62,7 +62,7 @@ static const struct luaL_reg dgnevent_lib[] = void luaopen_dgnevent(lua_State *ls) { - luaopen_setmeta(ls, "dgnevent", dgnevent_lib, DEVENT_METATABLE); + luaopen_setmeta(ls, "dgnevent", dgnevent_dlib, DEVENT_METATABLE); } /* @@ -119,7 +119,7 @@ static int dgn_dgn_event(lua_State *ls) return (retvals); } -const struct luaL_reg dgn_event_lib[] = +const struct luaL_reg dgn_event_dlib[] = { { "dgn_event_type", dgn_dgn_event }, diff --git a/crawl-ref/source/l_dgngrd.cc b/crawl-ref/source/l_dgngrd.cc index 1b109e7243..bedac0fde3 100644 --- a/crawl-ref/source/l_dgngrd.cc +++ b/crawl-ref/source/l_dgngrd.cc @@ -227,7 +227,7 @@ LUAFN(_dgn_is_opaque) return (1); } -const struct luaL_reg dgn_grid_lib[] = +const struct luaL_reg dgn_grid_dlib[] = { { "feature_number", dgn_feature_number }, { "feature_name", dgn_feature_name }, diff --git a/crawl-ref/source/l_dgnit.cc b/crawl-ref/source/l_dgnit.cc index 4fb101d4e3..4f9cebd86c 100644 --- a/crawl-ref/source/l_dgnit.cc +++ b/crawl-ref/source/l_dgnit.cc @@ -86,7 +86,7 @@ static int dgn_create_item(lua_State *ls) return (0); } -const struct luaL_reg dgn_item_lib[] = +const struct luaL_reg dgn_item_dlib[] = { { "item_from_index", dgn_item_from_index }, { "items_at", dgn_items_at }, diff --git a/crawl-ref/source/l_dgnlvl.cc b/crawl-ref/source/l_dgnlvl.cc index c72b09174e..a5237096f1 100644 --- a/crawl-ref/source/l_dgnlvl.cc +++ b/crawl-ref/source/l_dgnlvl.cc @@ -142,7 +142,7 @@ LUAFN(dgn_set_level_type_origin) return(0); } -const struct luaL_reg dgn_level_lib[] = +const struct luaL_reg dgn_level_dlib[] = { { "br_floorcol", dgn_br_floorcol }, { "br_rockcol", dgn_br_rockcol }, diff --git a/crawl-ref/source/l_dgnmon.cc b/crawl-ref/source/l_dgnmon.cc index a464a4fb50..ca1eef82a5 100644 --- a/crawl-ref/source/l_dgnmon.cc +++ b/crawl-ref/source/l_dgnmon.cc @@ -253,7 +253,7 @@ LUAFN(dgn_dismiss_monsters) luaL_checkstring(ls, 1))); } -const struct luaL_reg dgn_mons_lib[] = +const struct luaL_reg dgn_mons_dlib[] = { { "set_random_mon_list", dgn_set_random_mon_list }, { "mons_from_index", dgn_mons_from_index }, diff --git a/crawl-ref/source/l_dgntil.cc b/crawl-ref/source/l_dgntil.cc index 05b6df309b..2a47a333bc 100644 --- a/crawl-ref/source/l_dgntil.cc +++ b/crawl-ref/source/l_dgntil.cc @@ -144,7 +144,7 @@ LUAFN(dgn_rtile) #endif } -const struct luaL_reg dgn_tile_lib[] = +const struct luaL_reg dgn_tile_dlib[] = { { "lrocktile", dgn_lrocktile }, { "lfloortile", dgn_lfloortile }, diff --git a/crawl-ref/source/l_file.cc b/crawl-ref/source/l_file.cc index 5e204dbceb..78eb10f289 100644 --- a/crawl-ref/source/l_file.cc +++ b/crawl-ref/source/l_file.cc @@ -126,7 +126,7 @@ static int file_unmarshall_meta(lua_State *ls) return (0); } -const struct luaL_reg file_lib[] = +const struct luaL_reg file_dlib[] = { { "marshall", file_marshall }, { "marshall_meta", file_marshall_meta }, diff --git a/crawl-ref/source/l_libs.h b/crawl-ref/source/l_libs.h index aca91d8699..663b378832 100644 --- a/crawl-ref/source/l_libs.h +++ b/crawl-ref/source/l_libs.h @@ -9,23 +9,29 @@ #include "clua.h" /* + * Loaders for clua. + */ + +void cluaopen_crawl(lua_State *ls); + + +/* * Libraries and loaders, accessed from init_dungeon_lua(). */ -extern const struct luaL_reg crawl_lib[]; -extern const struct luaL_reg debug_lib[]; -extern const struct luaL_reg dgn_lib[]; -extern const struct luaL_reg dgn_build_lib[]; -extern const struct luaL_reg dgn_event_lib[]; -extern const struct luaL_reg dgn_grid_lib[]; -extern const struct luaL_reg dgn_item_lib[]; -extern const struct luaL_reg dgn_level_lib[]; -extern const struct luaL_reg dgn_mons_lib[]; -extern const struct luaL_reg dgn_tile_lib[]; -extern const struct luaL_reg file_lib[]; -extern const struct luaL_reg los_lib[]; -extern const struct luaL_reg mapmarker_lib[]; -extern const struct luaL_reg you_lib[]; +extern const struct luaL_reg debug_dlib[]; +extern const struct luaL_reg dgn_dlib[]; +extern const struct luaL_reg dgn_build_dlib[]; +extern const struct luaL_reg dgn_event_dlib[]; +extern const struct luaL_reg dgn_grid_dlib[]; +extern const struct luaL_reg dgn_item_dlib[]; +extern const struct luaL_reg dgn_level_dlib[]; +extern const struct luaL_reg dgn_mons_dlib[]; +extern const struct luaL_reg dgn_tile_dlib[]; +extern const struct luaL_reg file_dlib[]; +extern const struct luaL_reg los_dlib[]; +extern const struct luaL_reg mapmarker_dlib[]; +extern const struct luaL_reg you_dlib[]; void luaopen_dgnevent(lua_State *ls); void luaopen_mapmarker(lua_State *ls); @@ -34,6 +40,8 @@ void luaopen_ray(lua_State *ls); void register_monslist(lua_State *ls); void register_itemlist(lua_State *ls); void register_builder_funcs(lua_State *ls); + +void dluaopen_crawl(lua_State *ls); /* * Macros for processing object arguments. diff --git a/crawl-ref/source/l_los.cc b/crawl-ref/source/l_los.cc index b4d0f86fa1..e83c9358c7 100644 --- a/crawl-ref/source/l_los.cc +++ b/crawl-ref/source/l_los.cc @@ -41,7 +41,7 @@ LUAFN(los_cell_see_cell) PLUARET(number, cell_see_cell(p, q)); } -const struct luaL_reg los_lib[] = +const struct luaL_reg los_dlib[] = { { "findray", los_find_ray }, { "cell_see_cell", los_cell_see_cell }, @@ -88,7 +88,7 @@ LUAFN(ray_pos) return (2); } -static const struct luaL_reg ray_lib[] = +static const struct luaL_reg ray_dlib[] = { { "accx", ray_accx }, { "accy", ray_accy }, @@ -100,6 +100,5 @@ static const struct luaL_reg ray_lib[] = void luaopen_ray(lua_State *ls) { -// luaopen_setmeta(ls, "ray", ray_lib, RAY_METATABLE); - clua_register_metatable(ls, RAY_METATABLE, ray_lib, lua_object_gc<ray_def>); + clua_register_metatable(ls, RAY_METATABLE, ray_dlib, lua_object_gc<ray_def>); } diff --git a/crawl-ref/source/l_mapmrk.cc b/crawl-ref/source/l_mapmrk.cc index 98c2323546..2e25a2ff2b 100644 --- a/crawl-ref/source/l_mapmrk.cc +++ b/crawl-ref/source/l_mapmrk.cc @@ -21,7 +21,7 @@ static int mapmarker_move(lua_State *ls) return (0); } -const struct luaL_reg mapmarker_lib[] = +const struct luaL_reg mapmarker_dlib[] = { { "pos", mapmarker_pos }, { "move", mapmarker_move }, @@ -30,5 +30,5 @@ const struct luaL_reg mapmarker_lib[] = void luaopen_mapmarker(lua_State *ls) { - luaopen_setmeta(ls, "mapmarker", mapmarker_lib, MAPMARK_METATABLE); + luaopen_setmeta(ls, "mapmarker", mapmarker_dlib, MAPMARK_METATABLE); } diff --git a/crawl-ref/source/l_you.cc b/crawl-ref/source/l_you.cc index 4ecf0ef0cc..95149cb772 100644 --- a/crawl-ref/source/l_you.cc +++ b/crawl-ref/source/l_you.cc @@ -41,7 +41,7 @@ LUAFN(you_losight) return (0); } -const struct luaL_reg you_lib[] = +const struct luaL_reg you_dlib[] = { { "hear_pos", you_can_hear_pos }, { "x_pos", you_x_pos }, |