git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7501 c06c8d41-db1a-0410-9941-cceddc491573
FQ7XALBL6NZAGBKKYIFHYQ7MUWIHR4TEU4TCS33EG4I3JTND5SQAC MD2ABJ4CWOV5UKIOLQHCIA3DREZXH32MU74UU6MHETQJAX6XU4FAC 5ZKNFOMHGEVRDWZSD5JEEMOVXXXNEKQNASXVWWKNPBUYJGTNDIFQC S74D5KQSRSDBHFN6OTSQQTLUEGNA3FZQMG7IPR5JXDUXJ3AOL2UAC 7MFGZW2K4OYHVLLCQHPCLQ7MWSD6DVJ4E32T6RW54KRE5HHGUVPQC A4WHP5XZMXDCFMGRPS43OVHXHMU5KJBZKF4IRIO6F3KTXNHKAERQC XUUXZ34SWMKSJCLJYPNFF6X2LDWYBGVRNL4NVUVVLHIHNDOJ74TAC ED62QWGKBPORWVKDFOQRKJXEIWZVNGR3O4KWQBDSRNPT36AYOQYAC JT672SIJK4BOIUAGL2WQ6NR2NF4PSWP3BT6Q4HMNRF25UN6JQ2MAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC OYTCBRC7LE44EUVRZVYTOOVKQWJ6P6YE3FXTOGUTNKEMLNWPHKSQC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC W52PCSHX72WAMWKG6L4BPUBVMO6E72KYYBNKAA7554KNOTY6V7WQC RZHJQU3Y6KKMNJKGL6P4IXBJTKWFO4YARAQSWYCETXXNSZG4BN7QC RGHXFBNIULRVRYLBGG5JZDMYVM2E2JJ2Y5KQPMU6PUS3V26G6ZXQC GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC W52PTX4I7TUG2LS36FJHLZ72DWCVXGUCTUIKPI3IGEYO5KWL6OVAC BW3XFNOS6LDAQLHOZ6RXARCMKCY5JVLVDSXDSSAX4DSYM3FANQBAC ANBVGN4RZOMY5LI4QSHOV2477FN55H353ZYLSVCPTXC7AWWSQZBAC 3PY3L3A4QRW3Z5Y7SHO4TMVOOP2VNCO27X2MX4DTOP2SADLBQUOAC 2C6B6QRTOK2ZMK2ZOF3EPSFUZTKG5B3IZXWBWIUYC4ZOVGQ2OV2QC 6ZCKL3LCJ2QYYRI6CVK7CU4VXZMIZ6RIOTFUDEM2QTM4EHKVUKMAC FIYBXLWALQINNQTHG2KNDUUTAQAZRDDLXW2XOVSKDKBADJ3XCJ4AC KXUQB3WNWC5IFL6VFWADEPQMMU3VV3NDI5FLA666PGOEWFYUHCLQC WTGKEI4F7WINPHW4UMWFADYQH7VK7TNV5V7RUORBVXGFSO5SNP5AC MI7CWKRDXHAU7PIHLXXOSFBULRGT2OOMIMOSQLMVYOUVGABIVXGAC D6AJOTSOJNLJBBLQC2RAQOTPJJQENNBBVNRP45CZKDUHLLZLBFFQC NH533CNPGAQGR3QSSXRKCAJHSPVSHSPSTEJXRDIRH5YPKMGMEHVAC AYAQKTO6HOZJ44NDH5UIP6WFNB54Z5EZ4UMUISIQ67ZOIDB6OIQAC MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC 56C44YMFHZ62GXAAOLYSLLGBVGRWXB53W2VI37Q26ZECEK2XG5SQC 6QWZDCP5HGYLTJO3WWYJJGRRT7QFY6IG64TC7TUB553Z7GAA2HIQC TLO257LZSB6ZO36STDUEWJBO2LETXFKTFGXELA6Y4BZBVAEIIINAC JDM27QE4HR52AYFSQE763BFF57ANOTF5MXKMO377PP5EXMN7SAOAC WF2DSJGR6PKLGQSXEFF4ZW4EZZFGMHXPXWUYAKYBPFJH6KJKAANQC AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC CUNNC574MESEMTTONZ6YB6CJ2S5P6VA3V7Z3OODESWAK37GYOBPAC ZVK4J5HTKFNOOIVCI62ZWEYGXEE5TYJ65DLYYZAZWTADFSXE62ZAC QUYSD2DWCIKAAQJGI43EENAWWPA5W33UT3I5WFRSHU6FPSSXTX2AC ZJLJGSB2XSBQU42OFQMXL3EG4CXAQGOYAU6YTV2SAWZEJIPFH2CAC 7Z37EO2GGM2DAS65DWEI5VVPRPXMGH6XHB6IADG3Q6KOITSV25MAC QFWQG7G6KTZX3GP52K3N4BDWLMNH7A3A5ILJLXDIK6PYYLF3KO3AC FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC 2YSMM7QMFZOPD5NXAD2OAMDJEY5LOZO4NCYBC7UCQVANKINJRNBAC UEI5JAVCMN7Y2SACTEZPZSNFJWOJTC55G24Q6LKQCT4XNDH5ZQIAC 34C4U6EQWERY75GZJKUCM5KVGU2OUICETS5LGZF6RMKMZT4R5SQAC B7MSPF6X2RLGWN4M6ZZF3WSOPKGYPTTD7LIJVST7DXN27DG6JHNAC 2EUWVLBXTKBIYLS7HVCIL6R7EERHRAIVFAXQPBRKDEMH5BGFEDQQC WLX2RQMMOMP2PYPAGJRM4VFD2WTLJTOAZZPPY3MV76FU2EGEJ54QC IE3INS4WUXZOBVXB5VWRBYPVPXADD2U2W5H3TBTOYNWJ3EGRSGQQC H3552BCIAVBLKAYKE4DHFLBLFW5RGRMYBMRRYHYEB5IPIJRUVU5QC EEPNZ3SHGXQ4NKLSWHI7X2WK3LU3AR2EDZZFFDGOXQQBK5LO5OYAC JYNLSDNQDNOBCHDPQLJP6TNOJQ2IB4V7JHBYLL6UAUCTZ7DUZAWQC EL2ZPHAS5JGUCCBWYMSDJOQAFQLR7QKLOIWM2FYZ77ATL57G5NGAC ZI6K4LOBYQJKSMHZ766HTJS66AL2KB6IYSBUYPETTKPOKW4ZNK7AC XXZGTB5UAFMP2SW2WWUHCTDY5TEM7LZEPAASEXKQLT7BSLBY3OTQC R4UPYSRDYDVGAKQAJOXVWHYDMASGKTJXTO2AVTO35ZYOJERELAKQC VZKO4ZQNMNGUK6WY7Y4A4TIW2OA6YGREQ6V7NZCWW3DAPSWXKK7AC OODLVVDEHPOTPPUSPKCGAEXBVGKRUX7YYGQPA6UI3RKWZVB2YKKAC S6YHCQQOD4BLRRLJ7BX2VI7EFJGOHFNZ6M6HJBFK7DWOGMLE5BAAC 3GOS6LZ7JSSXLASCIJCMCOOMCVH2SD22TCEVUQ3YAIPB7FUFJPCQC YWT3IVJQ2NI6S47ZLGEHIW7C6YUFHUNQ5XMU6MVYRBWE4T3ALQWQC IDGC4LG4GCIAM4DC4WOQUB7TGTY3PHGTBF6NGMGJDS24HHJNY35QC 5JRYIJOGYDTTIBNUQFB5DUHFPLCUEBSNMTZ4T34SDNTEDGHHCPIAC 5TKGFHC6X2JYR3MVN5T2XU2VWG45V7HGEI45H3BZ4B55WPULZEFAC VCISXSXE6WGRO6PQN7Y6IFZ7C4VFUMKQK6KGAXA6YZ5RCZIB64WAC CI5VTLSMB2L5W5ZVKDZEJFUARGSZP2FUSTRFV3MG6U44TDDUYH5AC ZFHVWIDJGBUGJP5XKKI26HOVFQCT5ALKYLFZANNDIJXRKIXAUMKQC JFJU5HJKIHKW7NRJMMM3BBAEK2SZYOWU5A5O22QFKFZX6QWECFUQC HZK3YN3SAISTDS5JI4COBYFG7YB4ABDVENXWZZEYLFA2LDI232VAC 32B6H524I6YHMCVYFWZPHP32R4BURWJHMFGLYAEWADGI45B27ZUQC ZRJSOM6JBS4EBKBNK4UZZ74KNMLDP7N6EWMDH2NF5GSBXXPEW3SQC ZWYVZW5QFM5I2F6BLMNDDTV7FROJUHOO3O2BCBG7WSCKMKXUEMTQC SPVHVYFXSG2RIHX5JBNTGOL3YP5SX3CYZEGN2HUE6AQDIXD3M42AC X2SXILGEVQERETVZAHSFJXUOP3ZHXOE3JSU37SFYYS2UYFZNWKRAC KFM2ARORBIJ6BGX456VFW7EAVRIYBVFUV53JH63GSKNOKVPJWQ2QC CS2XCJNU5NFVOQUDQJCRHEECDBXH7J4YL74OBJPKQ4CYPAQVQKJAC KESFTFAMZEQMX2KFQL3WXFSFS2VCKRPLGRFVDVOLNJHO7L63LH3AC RRADDS444JWSL4KOJKNZFAIMWMZRLFR4KZPC2MJBCJPEPINC5CPQC IGHO5UHUXYBLIHLUMLZ672YHAYUSK4FSFX7SA42XARIKLIMCVLUAC UBQTNLYGD3SNWMUNGWUPX7EXEGQXOXCFCPWIVWBFE7ID7DJLPFWAC OUEUG67YNHCAEAR5TYOBG3RMJYXG6WI52OAH5SL5OHZPNFHT7R7AC 53K44NBML2QHWLZNXU5HBY2MOIXRK7ZGFQYAWZFO663TCOJKVHZAC BNP25NWD5OXPQEPLM3YJRJCRE24DH55RZKFCZPUX5NLWGOSBIYGAC V2SIR47DZF52SZOVRUTQKTSJ4H7LKOFK654JGGHFZQWR64CLNAUQC ILN2K6ASDZSMEHOPJ22IZLZJUO6DDGZTKAKXM3YXG6JZZHJNLX4AC MXOCLQAUGWLOS7AOTYZ46JZDMRL4EVRK5YN4JJUQ76GLKBOBHEVAC R6XS2HO5QX2FJUGL5UQQRNETKCMYWTUFPHPPS5SYWK3OQA4UDUQQC // Returns a map for which PLACE: matches the given place.int random_map_for_place(const level_id &place, bool want_minivault){if (!place.is_valid())return (-1);
struct map_selector {private:enum select_type{PLACE,DEPTH,TAG};public:bool accept(const map_def &md) const;void announce(int vault) const;bool valid() const{return (sel == TAG || place.is_valid());}
for (unsigned i = 0, size = vdefs.size(); i < size; ++i)
static map_selector by_depth(const level_id &place, bool mini){return map_selector(map_selector::DEPTH, place, "", mini, true);}static map_selector by_tag(const std::string &tag, bool mini,bool check_depth)
// We also accept tagged levels here.if (vdefs[i].place == place&& vdefs[i].is_minivault() == want_minivault&& !vdefs[i].has_tag("layout")&& map_matches_layout_type(vdefs[i])&& vault_unforbidden(vdefs[i])){rollsize += vdefs[i].chance;
return map_selector(map_selector::TAG, level_id::current(), tag,mini, check_depth);}
if (rollsize && x_chance_in_y(vdefs[i].chance, rollsize))mapindex = i;}
private:map_selector(select_type _typ, const level_id &_pl,const std::string &_tag,bool _mini, bool _check_depth): ignore_chance(false), preserve_dummy(false),sel(_typ), place(_pl), tag(_tag),mini(_mini), check_depth(_check_depth),check_layout(sel == DEPTH && place == level_id::current()){
if (mapindex != -1 && vdefs[mapindex].has_tag("dummy"))mapindex = -1;
bool map_selector::accept(const map_def &mapdef) const{switch (sel){case PLACE:return (mapdef.place == place&& mapdef.is_minivault() == mini&& !mapdef.has_tag("layout")&& map_matches_layout_type(mapdef)&& vault_unforbidden(mapdef));case DEPTH:return (mapdef.is_minivault() == mini&& !mapdef.place.is_valid()&& mapdef.is_usable_in(place)// Some tagged levels cannot be selected by depth. This is// the only thing preventing Pandemonium demon vaults from// showing up in the main dungeon.&& !mapdef.has_tag_suffix("entry")&& !mapdef.has_tag("pan")&& !mapdef.has_tag("unrand")&& !mapdef.has_tag("bazaar")&& !mapdef.has_tag("layout")&& (!check_layout || map_matches_layout_type(mapdef))&& vault_unforbidden(mapdef));case TAG:return (mapdef.has_tag(tag) && mapdef.is_minivault() == mini&& (!check_depth || !mapdef.has_depth()|| mapdef.is_usable_in(place))&& map_matches_layout_type(mapdef)&& vault_unforbidden(mapdef));default:return (false);}}
if (mapindex != -1)mprf(MSGCH_DIAGNOSTICS, "Found map %s for %s",vdefs[mapindex].name.c_str(), place.describe().c_str());
if (vault != -1){const char *format =sel == PLACE? "[PLACE] Found map %s for %s" :sel == DEPTH? "[DEPTH] Found random map %s for %s" :"[TAG] Found map %s tagged '%s'";mprf(MSGCH_DIAGNOSTICS, format,vdefs[vault].name.c_str(),sel == TAG? tag.c_str() : place.describe().c_str());}
int random_map_in_depth(const level_id &place, bool want_minivault)
static std::string _vault_chance_tag(const map_def &map){if (map.has_tag_prefix("chance_")){const std::vector<std::string> tags = map.get_tags();for (int i = 0, size = tags.size(); i < size; ++i){if (tags[i].find("chance_") == 0)return (tags[i]);}}return ("");}static int _random_map_by_selector(const map_selector &sel)
const bool check_layout = (place == level_id::current());
typedef std::vector<unsigned> vault_indices;// First build a list of vaults that could be used:vault_indices eligible;// Vaults that are eligible and have >0 chance.vault_indices chance;
if (vdefs[i].is_minivault() == want_minivault&& !vdefs[i].place.is_valid()&& vdefs[i].is_usable_in(place)// Some tagged levels cannot be selected by depth. This is// the only thing preventing Pandemonium demon vaults from// showing up in the main dungeon.&& !vdefs[i].has_tag_suffix("entry")&& !vdefs[i].has_tag("pan")&& !vdefs[i].has_tag("unrand")&& !vdefs[i].has_tag("bazaar")&& !vdefs[i].has_tag("layout")&& (!check_layout || map_matches_layout_type(vdefs[i]))&& vault_unforbidden(vdefs[i]))
if (sel.accept(vdefs[i]))
rollsize += vdefs[i].chance;if (rollsize && x_chance_in_y(vdefs[i].chance, rollsize))mapindex = i;
if (!sel.ignore_chance && vdefs[i].chance > 0){// There may be several alternatives for a portal// vault that want to be governed by one common// CHANCE. In this case each vault will use a// CHANCE, and a common chance_xxx tag. Pick the// first such vault for the chance roll. Note that// at this point we ignore chance_priority.const std::string tag = _vault_chance_tag(vdefs[i]);if (chance_tags.find(tag) == chance_tags.end()){if (!tag.empty())chance_tags.insert(tag);chance.push_back(i);}}else{eligible.push_back(i);}
return (mapindex);}
// Check CHANCEs.for (vault_indices::const_iterator i = chance.begin();i != chance.end(); ++i){const map_def &map(vdefs[*i]);if (random2(CHANCE_ROLL) < map.chance){const std::string chance_tag = _vault_chance_tag(map);// If this map has a chance_ tag, convert the search into// a lookup for that tag.if (!chance_tag.empty()){map_selector msel = map_selector::by_tag(sel.tag, sel.mini,sel.check_depth);msel.ignore_chance = true;return _random_map_by_selector(msel);}
int random_map_for_tag(const std::string &tag,bool want_minivault,bool check_depth){int mapindex = -1;int rollsize = 0;
mapindex = *i;break;}}
if (vdefs[i].has_tag(tag) && vdefs[i].is_minivault() == want_minivault&& (!check_depth || !vdefs[i].has_depth()|| vdefs[i].is_usable_in(level_id::current()))&& map_matches_layout_type(vdefs[i])&& vault_unforbidden(vdefs[i]))
for (vault_indices::const_iterator i = eligible.begin();i != eligible.end(); ++i)
#ifdef DEBUG_DIAGNOSTICSif (mapindex != -1)mprf(MSGCH_DIAGNOSTICS, "Found map %s tagged '%s'",vdefs[mapindex].name.c_str(), tag.c_str());#endif
sel.announce(mapindex);
}// Returns a map for which PLACE: matches the given place.int random_map_for_place(const level_id &place, bool want_minivault){return _random_map_by_selector(map_selector::by_place(place, want_minivault));}int random_map_in_depth(const level_id &place, bool want_minivault){return _random_map_by_selector(map_selector::by_depth(place, want_minivault));}int random_map_for_tag(const std::string &tag,bool want_minivault,bool check_depth){return _random_map_by_selector(map_selector::by_tag(tag, want_minivault, check_depth));
if (vdefs[i].is_minivault() == wantmini&& !vdefs[i].place.is_valid()&& vdefs[i].is_usable_in(place)// Some tagged levels cannot be selected by depth. This is// the only thing preventing Pandemonium demon vaults from// showing up in the main dungeon.&& !vdefs[i].has_tag_suffix("entry")&& !vdefs[i].has_tag("pan")&& !vdefs[i].has_tag("unrand")&& !vdefs[i].has_tag("bazaar")){wms.push_back(weighted_map_name( vdefs[i].name, vdefs[i].chance ) );}
const int v = _mg_random_vault_here(place, wantmini);if (v == -1)map_counts["(none)"]++;elsemap_counts[vdefs[v].name]++;}for (map_count_t::const_iterator i = map_counts.begin();i != map_counts.end(); ++i){wms.push_back(*i);
// Base chance; this is not a percentage.chance = 10;
// Chance of using this level. Nonzero chance should be used// sparingly. When selecting vaults for a place, first those// vaults with chance > 0 are considered, in the order they were// loaded (which is arbitrary). If random2(100) < chance, the// vault is picked, and all other vaults are ignored for that// random selection. weight is ignored if the vault is chosen// based on its chance.chance = 0;// If multiple alternative vaults have a chance, the order in which// they're tested is based on chance_priority: higher priority vaults// are checked first. Vaults with the same priority are tested in// unspecified order.chance_priority = 0;// Weight for this map. When selecting a map, if no map with a// nonzero chance is picked, one of the other eligible vaults is// picked with a probability of weight / (sum of weights of all// eligible vaults).weight = 10;
static int dgn_chance(lua_State *ls){MAP(ls, 1, map);if (!lua_isnil(ls, 2) && !lua_isnil(ls, 3)){const int chance_priority = luaL_checkint(ls, 2);const int chance = luaL_checkint(ls, 3);if (chance < 0 || chance > CHANCE_ROLL)luaL_argerror(ls, 2,make_stringf("Chance must be in the range [0,%d]",CHANCE_ROLL).c_str());map->chance_priority = chance_priority;map->chance = chance;}PLUARET(number, map->chance);}
if (vault == -1&& use_random_maps&& one_chance_in(vault_chance))
if (vault == -1 && use_random_maps && can_create_vault)
"altar.des", "bazaar.des", "entry.des", "elf.des", "float.des", "hells.des","hive.des", "lab.des", "lair.des", "large.des", "layout.des", "mini.des","orc.des", "pan.des", "sewer.des", "temple.des", "vaults.des", "crypt.des","zot.des"
-- The dummy vaults that define global vault generation odds."dummy.des","altar.des", "bazaar.des", "entry.des", "elf.des", "float.des","hells.des", "hive.des", "lab.des", "lair.des", "large.des", "layout.des","mini.des", "orc.des", "pan.des", "sewer.des", "temple.des", "vaults.des","crypt.des", "zot.des"
CHANCE: (number with 10 being default)
CHANCE: <priority>:<roll> or <roll>CHANCE allows you to control the probability that your mapis used on any given level with an absolute roll.There are two ways to specify the CHANCE roll:CHANCE: 500orCHANCE: 5%If specified as a raw number, the chance of selecting thevault is <number> in 10000. If specified as a percentage,the chance of selecting the vault is <perc> * 100 in 10000.Note that CHANCE accepts only integers, no fractions ordecimals.For any map with alternatives, a CHANCE influences howlikely the map is to be picked instead of the alternatives.If a map has a CHANCE, Crawl will roll a random number inthe range 1-10000, and select the map if the CHANCE is >=the rolled random number.If there are multiple alternative maps with CHANCE, theywill be tested in an unspecified order; the first map thatmakes the CHANCE roll will be used. If you'd like to specifyan order of testing CHANCEs, specify a CHANCE with apriority:CHANCE: 10 : 20%This specifies a CHANCE of 20%, with a priority of 10, whichmeans this vault will be checked before any other vault witha lower priority (the default priority is 0).If no map with a CHANCE is picked, Crawl will select a mapbased on WEIGHT, ignoring vaults with a CHANCE set.Note that the Lua equivalent for CHANCE is a two-argumentfunction:: chance(<priority>, <number>)These lines are all equivalent:CHANCE: 5%CHANCE: 500CHANCE: 0 : 5%CHANCE: 0 : 500: chance(0, 500)WEIGHT: (number with 10 being default)