From e4d5c6039f79b6952919882a74482695bffba6f9 Mon Sep 17 00:00:00 2001 From: Matthew Cline Date: Wed, 11 Nov 2009 02:34:35 -0800 Subject: Place some of the altars outside of the Temple Framework for placing altars outside the Temple, into what I call "overflow temples". It currently places twelve altars in the Ecumenical Temple and two outside at D:2 through D:9, with each of the two overflow altars being placed in a "temple" which consists of a bare altar. The overflow temples can actually contain any number of altars, but I'm not a vault designer, so I went the minimalistic route. The levels the overflow temples are placed on can be listed with the wizard command "&:". --- crawl-ref/source/dat/temple.des | 13 ++++ crawl-ref/source/dungeon.cc | 141 ++++++++++++++++++++++++++++++++++++++-- crawl-ref/source/dungeon.h | 6 ++ crawl-ref/source/maps.cc | 2 + crawl-ref/source/newgame.cc | 1 + crawl-ref/source/ng-init.cc | 74 +++++++++++++++++++++ crawl-ref/source/ng-init.h | 1 + crawl-ref/source/wiz-dgn.cc | 25 +++++++ 8 files changed, 256 insertions(+), 7 deletions(-) diff --git a/crawl-ref/source/dat/temple.des b/crawl-ref/source/dat/temple.des index 840a89dea7..bd8f5d3c05 100644 --- a/crawl-ref/source/dat/temple.des +++ b/crawl-ref/source/dat/temple.des @@ -893,3 +893,16 @@ bbbbbbbbbbbbbbb.B.bbbbbbbbbbbbbbb bbbbbbbbbbbbbbb...bbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ENDMAP + +############################################################################## +# Overflow temples +############################################################################## + +############################################################################## +# Overflow temples with one altar, must have tag "overflow_temple_1" +# +NAME: overflow_temple_1_a +TAGS: overflow_temple_1 allow_dup +MAP +B +ENDMAP diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 9b9998584e..13ceeba164 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -211,10 +211,14 @@ static void _dgn_load_colour_grid(); static void _dgn_map_colour_fixup(); // ALTAR FUNCTIONS +static int _setup_temple_altars(CrawlHashTable &temple); +static dungeon_feature_type _pick_temple_altar(vault_placement &place); static dungeon_feature_type _pick_an_altar(); static void _place_altar(); static void _place_altars(); +static std::vector _temple_altar_list; + typedef std::list coord_list; // MISC FUNCTIONS @@ -295,6 +299,9 @@ bool builder(int level_number, int level_type) dgn_reset_level(); + if (player_in_branch(BRANCH_ECUMENICAL_TEMPLE)) + _setup_temple_altars(you.props); + // If we're getting low on available retries, disable random vaults // and minivaults (special levels will still be placed). if (tries < 5) @@ -1617,6 +1624,97 @@ static void _dgn_verify_connectivity(unsigned nvaults) } } +// Structure of OVERFLOW_TEMPLES: +// +// * A vector, with one cell per dungeon level (unset if there's no +// overflow temples on that level). +// +// * The cell of the previous vector is a vector, with one overlfow +// temple definition per cell. +// +// * The cell of the previous vector is a hash table, containing the +// list of gods for the overflow temple and (optionally) the name of +// the vault to use for the temple. If no map name is supplied, +// it will randomly pick from vaults tagged "overflow_vault_num", +// where "num" is the number of gods in the temple. Gods are listed +// in the order their altars are placed. +static void _build_overflow_temples(int level_number) +{ + if (!you.props.exists(OVERFLOW_TEMPLES_KEY)) + // Levels built while in testing mode. + return; + + CrawlVector &levels = you.props[OVERFLOW_TEMPLES_KEY].get_vector(); + + // Are we deeper than the last overflow temple? + if (level_number >= levels.size()) + return; + + CrawlStoreValue &val = levels[level_number]; + + // Does this level have an overflow temple? + if (val.get_flags() & SFLAG_UNSET) + return; + + CrawlVector &temples = val.get_vector(); + + if (temples.size() == 0) + return; + + if (!can_create_vault) + { + mpr("WARNING: Overriding can_create_vault", + MSGCH_DIAGNOSTICS); + can_create_vault = true; + } + + mprf(MSGCH_DIAGNOSTICS, "Placing %lu overflow temples", + temples.size()); + + for (unsigned int i = 0; i < temples.size(); i++) + { + CrawlHashTable &temple = temples[i].get_table(); + + const int num_gods = _setup_temple_altars(temple); + + const map_def *vault = NULL; + + if (temple.exists(TEMPLE_MAP_KEY)) + { + std::string name = temple[TEMPLE_MAP_KEY].get_string(); + + vault = find_map_by_name(name); + if (vault == NULL) + { + mprf(MSGCH_ERROR, + "Couldn't find overflow temple map '%s'!", + name.c_str()); + } + } + else + { + std::string vault_tag = + make_stringf("overflow_temple_%d", num_gods); + + vault = random_map_for_tag(vault_tag, true); + if (vault == NULL) + { + mprf(MSGCH_ERROR, + "Couldn't find overflow temple tag '%s'!", + vault_tag.c_str()); + } + } + + if (vault == NULL) + // Might as well build the rest of the level if we couldn't + // find the overflow temple map, so don't veto the level. + return; + + if (!_ensure_vault_placed(_build_vaults(level_number, vault), false)) + return; + } +} + static void _build_dungeon_level(int level_number, int level_type) { spec_room sr; @@ -1663,9 +1761,16 @@ static void _build_dungeon_level(int level_number, int level_type) // Any further vaults must make sure not to disrupt level layout. dgn_check_connectivity = !player_in_branch(BRANCH_SHOALS); + if (you.where_are_you == BRANCH_MAIN_DUNGEON) + { + _build_overflow_temples(level_number); + + if (dgn_level_vetoed) + return; + } + // Try to place minivaults that really badly want to be placed. Still // no guarantees, seeing this is a minivault. - _place_minivaults(); _place_branch_entrances( level_number, level_type ); _place_extra_vaults(); @@ -2517,6 +2622,18 @@ static const map_def *_dgn_random_map_for_place(bool minivault) return (vault); } +static int _setup_temple_altars(CrawlHashTable &temple) +{ + CrawlVector god_list = temple[TEMPLE_GODS_KEY].get_vector(); + + _temple_altar_list.clear(); + + for (unsigned int i = 0; i < god_list.size(); i++) + _temple_altar_list.push_back( (god_type) god_list[i].get_byte() ); + + return ( (int) god_list.size() ); +} + // Returns BUILD_SKIP if we should skip further generation, // BUILD_QUIT if we should immediately quit, and BUILD_CONTINUE // otherwise. @@ -4871,9 +4988,7 @@ static void _vault_grid( vault_placement &place, (vgrid == ']') ? DNGN_STONE_STAIRS_DOWN_III : (vgrid == '[') ? DNGN_STONE_STAIRS_UP_III : (vgrid == 'A') ? DNGN_STONE_ARCH : - (vgrid == 'B') ? - static_cast( - DNGN_ALTAR_FIRST_GOD + place.altar_count) :// see below + (vgrid == 'B') ? _pick_temple_altar(place) : (vgrid == 'C') ? _pick_an_altar() : // f(x) elsewhere {dlb} (vgrid == 'I') ? DNGN_ORCISH_IDOL : (vgrid == 'G') ? DNGN_GRANITE_STATUE : @@ -4890,9 +5005,6 @@ static void _vault_grid( vault_placement &place, // then, handle oddball grids {dlb}: switch (vgrid) { - case 'B': - place.altar_count++; - break; case '@': place.exits.push_back( where ); break; @@ -5311,6 +5423,21 @@ static void _many_pools(dungeon_feature_type pool_type) } } // end many_pools() +static dungeon_feature_type _pick_temple_altar(vault_placement &place) +{ + if (_temple_altar_list.empty()) + { + return (dungeon_feature_type) + (DNGN_ALTAR_FIRST_GOD + place.altar_count++); + } + + const god_type god = _temple_altar_list.back(); + + _temple_altar_list.pop_back(); + + return altar_for_god(god); +} + //jmf: Generate altar based on where you are, or possibly randomly. static dungeon_feature_type _pick_an_altar() { diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h index f6932d1cb6..eb4fae762e 100644 --- a/crawl-ref/source/dungeon.h +++ b/crawl-ref/source/dungeon.h @@ -29,6 +29,12 @@ #define YOU_PORTAL_VAULT_NAMES_KEY "you_portal_vault_names_key" +// See _build_overflow_temples() in dungeon.cc for details on overflow +// temples. +#define TEMPLE_GODS_KEY "temple_gods_key" +#define OVERFLOW_TEMPLES_KEY "overflow_temples_key" +#define TEMPLE_MAP_KEY "temple_map_key" + enum portal_type { PORTAL_NONE = 0, diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index 06a47f6100..7f6e304902 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -507,6 +507,7 @@ bool map_selector::accept(const map_def &mapdef) const && mapdef.place == place && !mapdef.has_tag("layout") && !mapdef.has_tag("place_unique") + && !mapdef.has_tag_prefix("overflow_temple_") && map_matches_layout_type(mapdef) && vault_unforbidden(mapdef)); case DEPTH: @@ -522,6 +523,7 @@ bool map_selector::accept(const map_def &mapdef) const && !mapdef.has_tag("bazaar") && !mapdef.has_tag("layout") && !mapdef.has_tag("place_unique") + && !mapdef.has_tag_prefix("overflow_temple_") && (!check_layout || map_matches_layout_type(mapdef)) && vault_unforbidden(mapdef)); case TAG: diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index 4223ef6c0e..f3115d6d48 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -893,6 +893,7 @@ game_start: Generated_Levels.clear(); initialise_branch_depths(); + initialise_temples(); init_level_connectivity(); // Generate the second name of Jiyva diff --git a/crawl-ref/source/ng-init.cc b/crawl-ref/source/ng-init.cc index 446c95af1a..ecc505cf05 100644 --- a/crawl-ref/source/ng-init.cc +++ b/crawl-ref/source/ng-init.cc @@ -10,9 +10,11 @@ #include "branch.h" #include "describe.h" +#include "dungeon.h" #include "itemname.h" #include "player.h" #include "random.h" +#include "store.h" static unsigned char _random_potion_description() { @@ -64,6 +66,78 @@ void initialise_branch_depths() branches[BRANCH_TOMB].startdepth = random_range(2, 3); } +#define MAX_OVERFLOW_LEVEL 9 + +// Determine which altars go into the Ecumenical Temple, which go into +// overflow temples, and on what level the overflow temples are. +void initialise_temples() +{ + std::vector god_list; + + for (int i = 0; i < NUM_GODS; i++) + { + god_type god = (god_type) i; + + // These never appear in any temples. + switch(god) + { + case GOD_NO_GOD: + case GOD_LUGONU: + case GOD_BEOGH: + case GOD_JIYVA: + continue; + + default: + break; + } + + god_list.push_back(god); + } + + std::random_shuffle(god_list.begin(), god_list.end()); + + std::vector overflow_gods; + + while (god_list.size() > 12) + { + overflow_gods.push_back(god_list.back()); + god_list.pop_back(); + } + + CrawlVector &temple_gods + = you.props[TEMPLE_GODS_KEY].new_vector(SV_BYTE); + + for (unsigned int i = 0; i < god_list.size(); i++) + temple_gods.push_back( (char) god_list[i] ); + + CrawlVector &overflow_temples + = you.props[OVERFLOW_TEMPLES_KEY].new_vector(SV_VEC); + overflow_temples.resize(MAX_OVERFLOW_LEVEL); + + // NOTE: The overflow temples don't have to contain only one + // altar; they can contain any number of altars, so long as there's + // at least one vault definition with the tag "overflow_temple_num" + // (where "num" is the number of altars). + for (unsigned int i = 0; i < overflow_gods.size(); i++) + { + const unsigned int level = random_range(2, MAX_OVERFLOW_LEVEL); + + // List of overflow temples on this level. + CrawlVector &level_temples + = overflow_temples[level - 1].get_vector(); + + CrawlHashTable temple; + + CrawlVector &gods + = temple[TEMPLE_GODS_KEY].new_vector(SV_BYTE); + + // Only single-altar overflow temples for now. + gods.push_back( (char) overflow_gods[i] ); + + level_temples.push_back(temple); + } +} + static int _get_random_porridge_desc() { return PDESCQ(PDQ_GLUGGY, one_chance_in(3) ? PDC_BROWN diff --git a/crawl-ref/source/ng-init.h b/crawl-ref/source/ng-init.h index 58fdce4514..dc41e8168d 100644 --- a/crawl-ref/source/ng-init.h +++ b/crawl-ref/source/ng-init.h @@ -3,6 +3,7 @@ void fix_up_jiyva_name(); void initialise_branch_depths(); +void initialise_temples(); void initialise_item_descriptions(); #endif diff --git a/crawl-ref/source/wiz-dgn.cc b/crawl-ref/source/wiz-dgn.cc index 5d178d02c1..2972d37398 100644 --- a/crawl-ref/source/wiz-dgn.cc +++ b/crawl-ref/source/wiz-dgn.cc @@ -366,6 +366,31 @@ void wizard_list_branches() "this game", i, branches[i].longname); } } + + if (!you.props.exists(OVERFLOW_TEMPLES_KEY)) + return; + + mpr("----", MSGCH_DIAGNOSTICS); + mpr("Overflow temples: ", MSGCH_DIAGNOSTICS); + + CrawlVector &levels = you.props[OVERFLOW_TEMPLES_KEY].get_vector(); + + for (unsigned int i = 0; i < levels.size(); i++) + { + CrawlStoreValue &val = levels[i]; + + // Does this level have an overflow temple? + if (val.get_flags() & SFLAG_UNSET) + continue; + + CrawlVector &temples = val.get_vector(); + + if (temples.size() == 0) + continue; + + mprf(MSGCH_DIAGNOSTICS, "%lu on D:%lu", temples.size(), + i + 1); + } } void wizard_map_level() -- cgit v1.2.3-54-g00ecf