C25ULNTKMNOXT72ERWSFQZQW5E2OIM3TOGAAA33Z7EZQMZHRS2MAC GIDTM5YI3WHSH6CNS2MIQSQ3YZSNO3SZWNI4FUGSFDORFY6UDUAQC POACC5YR6QQGEX6GGMUJKGCDQNX6P6FUF4UQTYGOSHFOHJ26X4SQC R55VDFKFAQM32BY36VJBAAJH2C5WJNNYGAXLAH5VEI4Y6NYRLFDQC C7WZ2EB2RK7JH5UG34EHFFOLHG5UVJU7BDRJ5J5GCB2ZRIVQGLGAC Z5PVF4BKRAUD3CTW26IDYI2XV7H2YDKFKBWDQYWUUABCKWHF4KWAC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC KLJIFEBICFQ76DNM3MTS2PJ5LTEIOBIW5QZTNW722WHPKIST5UQQC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC 4Q5OYUKF2SGF7WHMIVYFZVXXDCFUCYY534VLOGKWYRSPYKRXMVDAC FSJKED4U2SOUP64DTHF2NEGAYY7EUMSIDKC2SATEXAXEVOCNL3CAC QLV7Y2LTDKTVMYFLM7UCNRUXU6PC5535XV6UE27N56AHHIGXEIWAC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC Y56C5OMUQ5XF2G6DKDV4R5MED44UOIUPTBBQVWQBUHYIXYA5MOZAC UBQTNLYGD3SNWMUNGWUPX7EXEGQXOXCFCPWIVWBFE7ID7DJLPFWAC ZLQAAP55CJ77XIJN3DZVPT4GTTVLIBFJLIJJKI6L5UBSHX7VUK6AC AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC 55PFDYPVE6JVGDYPCFUE4XS2523PVSV4CSIFRW6A2GGX4I6VWRWQC 7IERR3KESLBDHEMGSFRYGA66PZBPGKPUGMFDCSFR3WDX7RXD5OTAC FKRLQJYHK3GB6HHSNNFQ7L57ZAR52LSTBG5B6SNJBYZ2LQ36P67AC RN242L3YZK35BFY7JRTCSYWD6FWDCRFUFDI7PKYFUCA2UPX6ZEAQC 4N5PW5S3OV25HFN634NNWMMYX26NA2TB6TVFG4UMYSZ2VBJWKE4QC X7MFMKQTNZ2IWBFVGS6WQV7NRNKJ3DWQAW2X7IQMFQQXW24AHPZQC ED62QWGKBPORWVKDFOQRKJXEIWZVNGR3O4KWQBDSRNPT36AYOQYAC SM6YRPYZS6LMDQA6X3VAOK2PGMUFKPD7JMWJISOQSMX2CBR4ISPAC SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC 7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC OFTOEJSRSA2EZOAQOJCWWQNDX7IVVAR565JK3DZCBG54TBHHCIDQC PKXXBHS3LWLPZI2QVRX22MSQ4R2626IXRSNHFFYHXYTLJJQU54LQC C55G5JGGSVWMU7XVEJL6YZZLDXQZGRN7JQOAALS6WIKFPX3L2U6QC ASLW3Z5PAVZSWJEMMMVZT226P44EKSAD47QS72JIFJESAI3RPN3AC GSQ72ULBSL6WBJZUB3GJKAPQDXZIQV7B2TDBA5OP2WVGHVJMCQFQC FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC W45PMU4HNPSAMMEBJ4XH4MTHLPVIASZT4FXTBPID5LFXKIMNUBKAC DOZORMA366M4HB5JKSS27BMCR6ET7QNZNND2B7KV3NVEEPR5H7EAC ZHFUXYUHS6V47WK2NRH7OU6RX77NRKTXOZC3MND2GG7PEEWSGFTAC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC AUXVWXWIFSTWFA6VZXN2FMG7FQEKRZVV6MD32VQQ7J2RKCXHAVGAC ZFGIHLY6UMKMJOU62DUHJWHLFU76ML226WNDRIKOYHMG2BEL7PNQC OIAQU4VDTZ3EHBNC7FZIOW2QEQLTDHZ7O46XW2YWM6JRVBC66UPQC N7J2IWU7B34XIUYWHJF2RTRAXXAQLVVZLWWHFWN4FC5PLNFFEWCAC CH7JECYYH35H4TRHRNRTRJCQTQLZ2WRH62TKV72SUIU2RTK5OH7AC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC BA6B3ABSAZSAUBZTF2IWRQELSAS4IKFMDVBJZZ5ENHTP7J2Q52QQC GVDKSZGU5NDWQAADOPCIURSBQG2T7VMFDKAF75Z5T3KVVP6744VQC -- Vet LOS for symmetry.local FAILMAP = 'losfail.map'local checks = 0local function test_los()-- Send the player to a random spot on the level.you.random_teleport()-- Forcibly redo LOS.you.losight()-- And draw the view to keep the watcher entertained.crawl.redraw_view()checks = checks + 1local you_x, you_y = you.pos()local visible_spots = { }for y = -8, 8 dofor x = -8, 8 doif x ~= 0 or y ~= 0 thenlocal px, py = x + you_x, y + you_yif you.see_grid(px, py) thentable.insert(visible_spots, { px, py })endendendend-- For each position in LOS, jump to that position and make sure we-- can see the original spot.for _, spot in ipairs(visible_spots) dolocal x, y = unpack(spot)you.moveto(x, y)you.losight()if not you.see_grid(you_x, you_y) thencrawl.redraw_view()local this_p = dgn.point(x, y)local you_p = dgn.point(you_x, you_y)dgn.grid(you_x, you_y, "floor_special")dgn.dbg_dump_map(FAILMAP)assert(false,"LOS asymmetry detected (iter #" .. checks .. "): " .. you_p .." sees " .. this_p .. ", but not vice versa." .." Map saved to " .. FAILMAP)endendendlocal function run_los_tests(depth, nlevels, tests_per_level)local place = "D:" .. depthcrawl.mpr("Running LOS tests on " .. place)dgn.dbg_goto_place(place)for lev_i = 1, nlevels dodgn.dbg_flush_map_memory()dgn.dbg_generate_level()for t_i = 1, tests_per_level dotest_los()endendendfor depth = 1, 27 dorun_los_tests(depth, 10, 100)end
// WARNING: This is a very low-level call.LUAFN(dgn_dbg_goto_place){try{const level_id id = level_id::parse_level_id(luaL_checkstring(ls, 1));you.level_type = id.level_type;if (id.level_type == LEVEL_DUNGEON){you.where_are_you = static_cast<branch_type>(id.branch);you.your_level = absdungeon_depth(id.branch, id.depth);}}catch (const std::string &err){luaL_error(ls, err.c_str());}return (0);}LUAFN(dgn_dbg_flush_map_memory){dgn_flush_map_memory();init_level_connectivity();return (0);}LUAFN(dgn_dbg_generate_level){no_messages mx;env.show.init(0);env.map.init(map_cell());builder(you.your_level, you.level_type);return (0);}
// see_grid 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_grid, boolean,see_grid(luaL_checkint(ls, 1), luaL_checkint(ls, 2)))LUARET1(you_see_grid_no_trans, boolean,see_grid_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);}
}std::vector<std::string> get_dir_files_ext(const std::string &dir,const std::string &ext){const std::vector<std::string> allfiles(get_dir_files(dir));std::vector<std::string> filtered;for (int i = 0, size = allfiles.size(); i < size; ++i)if (ends_with(allfiles[i], ext))filtered.push_back(allfiles[i]);return (filtered);
#ifndef CTEST_H#define CTEST_H#include "AppHdr.h"#ifdef DEBUG_DIAGNOSTICSnamespace crawl_tests{void run_tests(bool exit_on_complete);}#endif#endif
/** File: ctest.cc* Summary: Crawl Lua test cases* Written by: Darshan Shaligram** Modified for Crawl Reference by $Author$ on $Date$** ctest runs Lua tests found in the test directory. The intent here* is to test parts of Crawl that can be easily tested from within Crawl* itself (such as LOS). As a side-effect, writing Lua bindings to support* tests will expand the available Lua bindings. :-)** Tests will run only with Crawl built in its source tree without* DATA_DIR_PATH set.*/#include "AppHdr.h"#if DEBUG_DIAGNOSTICS#include "clua.h"#include "files.h"#include "luadgn.h"#include "maps.h"#include "stuff.h"#include <algorithm>#include <vector>namespace crawl_tests{const std::string test_dir = "test";const std::string test_player_name = "Superbug99";int ntests = 0;int nsuccess = 0;typedef std::pair<std::string, std::string> file_error;std::vector<file_error> failures;void reset_test_data(){ntests = 0;nsuccess = 0;failures.clear();// XXX: Good grief, you.your_name is still not a C++ string?!strncpy(you.your_name, test_player_name.c_str(), kNameLen);you.your_name[kNameLen - 1] = 0;}int crawl_begin_test(lua_State *ls){mprf(MSGCH_PROMPT, "Starting tests: %s", luaL_checkstring(ls, 1));lua_pushnumber(ls, ++ntests);return (1);}int crawl_test_success(lua_State *ls){mprf(MSGCH_PROMPT, "Test success: %s", luaL_checkstring(ls, 1));lua_pushnumber(ls, ++nsuccess);return (1);}static const struct luaL_reg crawl_test_lib[] ={{ "begin_test", crawl_begin_test },{ "test_success", crawl_test_success },{ NULL, NULL }};void init_test_bindings(){lua_stack_cleaner clean(dlua);luaL_openlib(dlua, "crawl", crawl_test_lib, 0);}void run_test(const std::string &file){++ntests;const std::string path(catpath(test_dir, file));dlua.execfile(path.c_str(), true, false);if (dlua.error.empty())++nsuccess;elsefailures.push_back(file_error(file, dlua.error));}// Assumes curses has already been initialized.bool run_tests(bool exit_on_complete){run_map_preludes();reset_test_data();init_test_bindings();// Get a list of Lua files in test. Order of execution of// tests should be irrelevant.const std::vector<std::string> tests(get_dir_files_ext(test_dir, ".lua"));std::for_each(tests.begin(), tests.end(),run_test);if (exit_on_complete){cio_cleanup();for (int i = 0, size = failures.size(); i < size; ++i){const file_error &fe(failures[i]);fprintf(stderr, "Test error: %s\n",fe.second.c_str());}const int code = failures.empty() ? 0 : 1;end(code, false, "%d tests, %d succeeded, %d failed",ntests, nsuccess, failures.size());}return (failures.empty());}}#endif // DEBUG_DIAGNOSTICS