From f7d34b29bdd41086a10c8135466e4b974674eae5 Mon Sep 17 00:00:00 2001 From: dshaligram Date: Sun, 23 Nov 2008 14:22:58 +0000 Subject: Allow place:X in MONS specifications to place random monsters suitable for place X. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7550 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/docs/level_design.txt | 22 ++++++++++++++++++++++ crawl-ref/source/dungeon.cc | 38 ++++++++++++++++++++++++++++++++++++++ crawl-ref/source/mapdef.cc | 41 +++++++++++++++++++++++++++++++++++++++-- crawl-ref/source/mapdef.h | 8 +++++--- 4 files changed, 104 insertions(+), 5 deletions(-) (limited to 'crawl-ref') diff --git a/crawl-ref/docs/level_design.txt b/crawl-ref/docs/level_design.txt index bb5096a940..0615d49ec6 100644 --- a/crawl-ref/docs/level_design.txt +++ b/crawl-ref/docs/level_design.txt @@ -589,6 +589,28 @@ MONS: (list of monsters) Note that 8, 9, 0 also place monsters (see the table). + If you want to place a random monster suitable for the level + the map is generated on, you can use + MONS: random + + If you want to place a random monster suitable for some other + place, you can use a place: tag in the monster spec: + MONS: place:Abyss + or + MONS: place:Slime:6 + + Using place: with MONS implies that you want a random monster. + You can also request zombies from random monsters suitable + for some other depth as: + MONS: place:Elf:7 zombie + or + MONS: place:Zot:5 simulacrum + or + MONS: place:Vault:8 spectre + + The available modifiers are "zombie", "skeleton", + "simulacrum" and "spectre". + A monster can be given specific items by following the monster name with a semi-colon and then with an item list as described in ITEM:, but with slashes replaced with pipes and commas replaced diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index a57c96010d..9d8bc2c6f7 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -4918,6 +4918,36 @@ bool dgn_place_monster(mons_spec &mspec, } mgen_data mg(static_cast(mid)); + + if (mg.cls == RANDOM_MONSTER && mspec.place.is_valid()) + { + int lev = monster_level; + + if (mspec.place.level_type == LEVEL_DUNGEON) + lev = absdungeon_depth(mspec.place.branch, mspec.place.depth); + + if (mlev == -8) + lev = 4 + lev * 2; + else if (mlev == -9) + lev += 5; + + int tries = 100; + do + { + mg.cls = pick_random_monster(mspec.place, lev, lev); + } while (mg.cls != MONS_PROGRAM_BUG + && mons_class_is_zombified(mspec.monbase) + && !mons_zombie_size(mg.cls) + && tries-- > 0); + + if (mg.cls == MONS_PROGRAM_BUG + || (mons_class_is_zombified(mspec.monbase) + && !mons_zombie_size(mg.cls))) + { + mg.cls = RANDOM_MONSTER; + } + } + mg.power = monster_level; mg.behaviour = (m_generate_awake) ? BEH_WANDER : BEH_SLEEP; mg.base_type = mspec.monbase; @@ -4925,6 +4955,14 @@ bool dgn_place_monster(mons_spec &mspec, mg.colour = mspec.colour; mg.pos = where; + if (mons_class_is_zombified(mg.base_type)) + { + if (mons_class_is_zombified(mg.cls)) + mg.base_type = MONS_PROGRAM_BUG; + else + std::swap(mg.base_type, mg.cls); + } + if (m_patrolling) mg.flags |= MG_PATROLLING; diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 1c6a82c4cc..9058fde162 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -1990,6 +1990,26 @@ mons_list::mons_spec_slot mons_list::parse_mons_spec(std::string spec) mspec.generate_awake = strip_tag(mon_str, "generate_awake"); mspec.patrolling = strip_tag(mon_str, "patrolling"); + // place:Elf:7 to choose monsters appropriate for that level, + // for example. + const std::string place = strip_tag_prefix(mon_str, "place:"); + if (!place.empty()) + { + try + { + mspec.place = level_id::parse_level_id(place); + } + catch (const std::string &err) + { + error = err; + return (slot); + } + } + + mspec.mlevel = strip_number_tag(mon_str, "lev:"); + if (mspec.mlevel == TAG_UNFOUND) + mspec.mlevel = 0; + std::string colour = strip_tag_prefix(mon_str, "col:"); if (!colour.empty()) { @@ -2010,6 +2030,22 @@ mons_list::mons_spec_slot mons_list::parse_mons_spec(std::string spec) mspec.mlevel = -9; else if (check_mimic(mon_str, &mspec.mid, &mspec.fix_mons)) ; + else if (mspec.place.is_valid()) + { + // For monster specs such as place:Orc:4 zombie, we may + // have a monster modifier, in which case we set the + // modifier in monbase. + const mons_spec nspec = mons_by_name("orc " + mon_str); + if (nspec.mid != MONS_PROGRAM_BUG) + { + // Is this a modified monster? + if (nspec.monbase != MONS_PROGRAM_BUG + && mons_class_is_zombified(nspec.mid)) + { + mspec.monbase = static_cast(nspec.mid); + } + } + } else if (mon_str != "0") { const mons_spec nspec = mons_by_name(mon_str); @@ -2094,7 +2130,7 @@ void mons_list::get_zombie_type(std::string s, mons_spec &spec) const { static const char *zombie_types[] = { - " zombie", " skeleton", " simulacrum", NULL + " zombie", " skeleton", " simulacrum", " spectre", NULL }; // This order must match zombie_types, indexed from one. @@ -2103,7 +2139,8 @@ void mons_list::get_zombie_type(std::string s, mons_spec &spec) const { MONS_PROGRAM_BUG, MONS_PROGRAM_BUG }, { MONS_ZOMBIE_SMALL, MONS_ZOMBIE_LARGE }, { MONS_SKELETON_SMALL, MONS_SKELETON_LARGE }, - { MONS_SIMULACRUM_SMALL, MONS_SIMULACRUM_LARGE } + { MONS_SIMULACRUM_SMALL, MONS_SIMULACRUM_LARGE }, + { MONS_SPECTRAL_THING, MONS_SPECTRAL_THING }, }; const int mod = ends_with(s, zombie_types); diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h index 52bb196070..1b9dd721dc 100644 --- a/crawl-ref/source/mapdef.h +++ b/crawl-ref/source/mapdef.h @@ -361,6 +361,7 @@ struct item_spec int level; int race; int qty; + level_id place; item_spec() : genweight(10), base_type(OBJ_RANDOM), sub_type(OBJ_RANDOM), plus(0), plus2(0), ego(0), allow_uniques(1), level(-1), @@ -411,6 +412,7 @@ class mons_spec { public: int mid; + level_id place; monster_type monbase; // Base monster for zombies and dracs. int number; // Head count for hydras int genweight, mlevel; @@ -426,9 +428,9 @@ class mons_spec int num = 0, int gw = 10, int ml = 0, bool _fixmons = false, bool awaken = false, bool patrol = false) - : mid(id), monbase(base), number(num), genweight(gw), mlevel(ml), - fix_mons(_fixmons), generate_awake(awaken), patrolling(false), - colour(BLACK), items() + : mid(id), place(), monbase(base), number(num), genweight(gw), + mlevel(ml), fix_mons(_fixmons), generate_awake(awaken), + patrolling(false), colour(BLACK), items() { } }; -- cgit v1.2.3-54-g00ecf