Adds test/monplace.lua to test placing monsters using the Lua direct monster creation binding (does not exercise all the map code).
Allow choosing what tests to run with "crawl -test test1,test2".
QAXFREFPBXN7YIBORITM2TAGA4QYF43XMSCLWW2BHONZFGEGMRUQC TY33BSNJWG6DYLBARYXL72GPP7MZRA3QTG3A6H2OVUKW5QK7TH3AC UXAYLVZCSKTOC23AZORWJBQWYXKWC6QD2FPV2DRG7G6J5S7U2QLAC C25ULNTKMNOXT72ERWSFQZQW5E2OIM3TOGAAA33Z7EZQMZHRS2MAC QLV7Y2LTDKTVMYFLM7UCNRUXU6PC5535XV6UE27N56AHHIGXEIWAC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC 55PFDYPVE6JVGDYPCFUE4XS2523PVSV4CSIFRW6A2GGX4I6VWRWQC AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC 2WWSPLCXLSMBGTXUC33EQ5YBOA5IBFSMJSTZ2TU6HZIMZZWZJWGAC S6ZETU2X3HBTKBDL2KTAMCNPMPGHEZO2JGMILIWETWC7XXRS5RYQC X5OHFTHRXTI5KHFIYFJ6DB3W5MY3JUJKNTL4HF37MKABYNCOBOZAC 3FBKOX4Y5QYPMBOCSAMHNZXCY7Z75YDQDL4EJZHZIGDXL7RMZ7TAC 3IMZJEIBQTRXX5OLN7NUZ3QSGNVH2VPVTBDESVVWXIYURTHF3VXAC ZNMT5CZHP2FC4HTLNA7KYEDGFBXSCUE5QHJOALVPE6RDPHSEDXRQC K7J2IGELTIQL5KAMBV62MFVIVMEZEWCOLZ7GHFXHYPANYIF7BRZAC AVEOSLDREJHWFZE6ULAWGQPDT24YX4OAOGL7YAUCFVRGHCS22UCAC -- Monster placement tests.local place = dgn.point(20, 20)local function place_monster_on(x, y, monster, feature)dgn.grid(place.x, place.y, feature)return dgn.create_monster(x, y, monster)endlocal function assert_place_monster_on(monster, feature)dgn.dismiss_monsters()crawl.mpr("Placing " .. monster .. " on " .. feature)assert(place_monster_on(place.x, place.y, monster, feature),"Could not place monster " .. monster .. " on " .. feature)endassert_place_monster_on("quokka", "floor")assert_place_monster_on("necrophage", "altar_zin")assert_place_monster_on("rat", "shallow water")-- [ds] One wonders why due has this morbid fetish involving flying-- skulls and lava...assert_place_monster_on("flying skull", "lava")assert_place_monster_on("rock worm", "rock_wall")
// Make all of the monster's original equipment disappear, unless it's a fixed// artefact or unrand artefact.static void _vanish_orig_eq(monsters* mons){for (int i = 0; i < NUM_MONSTER_SLOTS; ++i){if (mons->inv[i] == NON_ITEM)continue;item_def &item(mitm[mons->inv[i]]);if (!is_valid_item(item))continue;if (item.orig_place != 0 || item.orig_monnum != 0|| !item.inscription.empty()|| is_unrandom_artefact(item)|| (item.flags & (ISFLAG_DROPPED | ISFLAG_THROWN | ISFLAG_NOTED_GET| ISFLAG_BEEN_IN_INV) ) ){continue;}item.flags |= ISFLAG_SUMMONED;}}int dismiss_monsters(std::string pattern) {// Make all of the monsters' original equipment disappear unless "keepitem"// is found in the regex (except for fixed arts and unrand arts).const bool keep_item = strip_tag(pattern, "keepitem");// Dismiss by regextext_pattern tpat(pattern);int ndismissed = 0;for (int mon = 0; mon < MAX_MONSTERS; mon++){monsters *monster = &menv[mon];if (monster->alive() &&(tpat.empty() || tpat.matches(monster->name(DESC_PLAIN, true)))){if (!keep_item)_vanish_orig_eq(monster);monster_die(monster, KILL_DISMISSED, NON_MONSTER, false, true);++ndismissed;}}return (ndismissed);}
}// Make all of the monster's original equipment disappear, unless it's a fixed// artefact or unrand artefact.static void _vanish_orig_eq(monsters* mons){for (int i = 0; i < NUM_MONSTER_SLOTS; ++i){if (mons->inv[i] == NON_ITEM)continue;item_def &item(mitm[mons->inv[i]]);if (!is_valid_item(item))continue;if (item.orig_place != 0 || item.orig_monnum != 0|| !item.inscription.empty()|| is_unrandom_artefact(item)|| (item.flags & (ISFLAG_DROPPED | ISFLAG_THROWN | ISFLAG_NOTED_GET| ISFLAG_BEEN_IN_INV) ) ){continue;}item.flags |= ISFLAG_SUMMONED;}
// Make all of the monsters' original equipment disappear unless "keepitem"// is found in the regex (except for fixed arts and unrand arts).bool keep_item = false;if (strstr(buf, "keepitem") != NULL){std::string str = replace_all(buf, "keepitem", "");trim_string(str);strcpy(buf, str.c_str());keep_item = true;}// Dismiss allif (buf[0] == '\0' || force_all){// Genocide... "unsummon" all the monsters from the level.for (int mon = 0; mon < MAX_MONSTERS; mon++){monsters *monster = &menv[mon];if (monster->alive()){if (!keep_item)_vanish_orig_eq(monster);monster_die(monster, KILL_DISMISSED, NON_MONSTER, false, true);}}// If it was turned off turn autopickup back on.
dismiss_monsters(buf);// If it was turned off turn autopickup back on if all monsters went away.if (!*buf)
return;}// Dismiss by regextext_pattern tpat(buf);for (int mon = 0; mon < MAX_MONSTERS; mon++){monsters *monster = &menv[mon];if (monster->alive() && tpat.matches(monster->name(DESC_PLAIN, true))){if (!keep_item)_vanish_orig_eq(monster);monster_die(monster, KILL_DISMISSED, NON_MONSTER, false, true);}}
}bool is_test_selected(const std::string &testname){if (crawl_state.tests_selected.empty())return (true);for (int i = 0, size = crawl_state.tests_selected.size();i < size; ++i){const std::string &phrase(crawl_state.tests_selected[i]);if (testname.find(phrase) != std::string::npos)return (true);}return (false);