diff options
author | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2007-02-07 12:56:34 +0000 |
---|---|---|
committer | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2007-02-07 12:56:34 +0000 |
commit | c30b530266ee87b352f98e54287bc3c054c88060 (patch) | |
tree | 0fb03ae79580117eb5be9ff5767b1f078e5d3a6d /crawl-ref | |
parent | 9a5dd81c99d8cd33c826d47f61eded48494a484e (diff) | |
download | crawl-ref-c30b530266ee87b352f98e54287bc3c054c88060.tar.gz crawl-ref-c30b530266ee87b352f98e54287bc3c054c88060.zip |
[1638394] Added support for portal vaults.
Included David's portal vaults for the Mines, Lair and Vaults.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@930 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/dat/splev.des | 143 | ||||
-rw-r--r-- | crawl-ref/source/dat/vaults.des | 2 | ||||
-rw-r--r-- | crawl-ref/source/direct.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 270 | ||||
-rw-r--r-- | crawl-ref/source/makefile.unix | 1 | ||||
-rw-r--r-- | crawl-ref/source/maps.cc | 96 | ||||
-rw-r--r-- | crawl-ref/source/maps.h | 12 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 6 |
8 files changed, 442 insertions, 91 deletions
diff --git a/crawl-ref/source/dat/splev.des b/crawl-ref/source/dat/splev.des index d6b2e5bac7..f41f624111 100644 --- a/crawl-ref/source/dat/splev.des +++ b/crawl-ref/source/dat/splev.des @@ -43,7 +43,8 @@ # % - normal item # * - higher level item (good) # | - acquirement-level item (almost guaranteed excellent) -# O - place an appropriate rune here +# O - place an appropriate rune here. In portal vaults, place the portal or +# branch stair here. # P - maybe place a rune here (50%) # R - honeycomb (2/3) or royal jelly (1/3) # Z - the Orb of Zot @@ -2230,3 +2231,143 @@ ENDMAP MONS: swamp dragon, swamp drake, hydra MONS: random, random, random, random + + +############################################################################## +# Portal vaults +############################################################################## +# These vaults are used when the dungeon builder tries to place a portal/stair +# to a branch. There's no guarantee that one of these will be used because +# portal vaults are placed last, after the rest of the level is generated, and +# will not be placed if they can't fit on the level without clobbering +# something. +# +# With portal vaults (as with minivaults), smaller is better, since the dungeon +# builder will frequently not be able to fit large vaults in anywhere (it +# doesn't try very hard). +# +# Note that the rune symbol (O) is used for the portal in portal vaults. If you +# do not put an O anywhere in the vault, there will be no portal for that +# branch! +# +############################################################################## +# Freedom of Choice (Orc entry) + +NAME: david_orc_choice +TAGS: orc_entry +MONS: hobgoblin, orc sorcerer, orc warrior, orc +ITEM: scroll of blinking / scroll of recharging / scroll of fear +ITEM: scroll of teleport / scroll of remove curse / scroll of identify +ORIENT: float + +MAP +xxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxx.........xxxxxxxx +xxxxx.......O.......xxxxx +xxxx.................xxxx +xxxx....x.......x....xxxx +xxx....xxx.....xxx....xxx +xxx...xxxxx...xxxxx...xxx +xx.....xxx.....xxx.....xx +xx.....xxx.....xxx.....xx +x.......x..I.I..x...I...x +x.......x.......x.......x +x..x.x..x..x=x..x..x+x..x +x.xx.xx.x.xx=xx.x.xx~xx.x +x.x.%.x.x.x.d.x.x.x.4.x.x +x.x.1.x.x.x.2.x.x.x.4.x.x +x.x.%.x.x.x.3.x.x.x.e.x.x +x.xx.xx.x.xx=xx.x.xx~xx.x +x..x.x..x..x=x..x..x+x..x +x.......x.......x.......x +x.......x..I.I..x...I...x +xx.....xxx.....xxx.....xx +xx.....+.+.....+.+.....xx +xxx...xxxxx...xxxxx...xxx +xxx.@.xxxxxxxxxxxxx.@.xxx +ENDMAP + +############################################################################## +# Generic Orc entry + +NAME: david_orc_1 +TAGS: orc_entry +MONS: orc +ORIENT: float +FLAGS: no_rotate + +MAP +xxxx..@..xxxx +x.....I.....x +x...........x +.....111..... +@I...1O1...I@ +.....111..... +x...........x +x.....I.....x +xxxx..@..xxxx +ENDMAP + +############################################################################## +# Generic Vaults entry + +NAME: david_vaults_1 +TAGS: vault_entry +MONS: human +ORIENT: float +FLAGS: no_rotate + +MAP +xxxxx.@.xxxxx +x...+...x...x +x...x...x...x +xxx=x111x...x +@.x.x111+.O.x +x.x.x111x...x +x.x.x...x...x +x.+.x...x...x +xxxxx.@.xxxxx +ENDMAP + +############################################################################## +# Generic Lair entry + +NAME: david_lair_1 +TAGS: lair_entry +MONS: giant lizard, giant snail, yak, plant +ORIENT: float +FLAGS: no_rotate +CHANCE: 5000 + +MAP +xxxx..@..xxxx +xx.........xx +x...2...44..x +...4..1...... +@....1O3....@ +..........4.. +x...4..2....x +xx.........xx +xxxx..@..xxxx +ENDMAP + +############################################################################## +# Shrubbed Lair entry + +NAME: david_lair_2 +TAGS: lair_entry +MONS: plant, lindwurm +ORIENT: float +FLAGS: no_rotate + +MAP +xxxxxxxxxxxxx +xx111111111xx +x112..111111x +x11.O..111... +x11...111...@ +x111111...... +x1..11......x +xx.........xx +xxxx..@..xxxx +ENDMAP
\ No newline at end of file diff --git a/crawl-ref/source/dat/vaults.des b/crawl-ref/source/dat/vaults.des index d6120a354d..ee8d0b81a3 100644 --- a/crawl-ref/source/dat/vaults.des +++ b/crawl-ref/source/dat/vaults.des @@ -48,7 +48,7 @@ # % - normal item # * - higher level item (good) # | - acquirement-level item (almost guaranteed excellent) -# O - place an appropriate rune here +# O - place an appropriate rune here. For portal vaults, place the portal here. # P - maybe place a rune here (50%) # R - honeycomb (2/3) or royal jelly (1/3) # Z - the Orb of Zot diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc index f8e77fcc8b..040d109f40 100644 --- a/crawl-ref/source/direct.cc +++ b/crawl-ref/source/direct.cc @@ -289,7 +289,8 @@ void direction(struct dist& moves, targeting_type restricts, // Prompts might get scrolled off if you have too few lines available. // We'll live with that. if ( !just_looking ) - mpr("Aim (press '?' for help, Shift-Dir to shoot in a straight line.)", MSGCH_PROMPT); + mpr("Aim (press '?' for help, Shift-Dir to shoot in a straight line.)", + MSGCH_PROMPT); while (1) { diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index ba8baac296..e63d6c3533 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -62,7 +62,7 @@ struct pit_mons_def int rare; }; -struct spec_t +struct spec_room { bool created; bool hooked_up; @@ -70,9 +70,11 @@ struct spec_t int y1; int x2; int y2; -}; -typedef struct spec_t spec_room; + spec_room() : created(false), hooked_up(false), x1(0), y1(0), x2(0), y2(0) + { + } +}; // DUNGEON BUILDERS static void build_dungeon_level(int level_number, int level_type); @@ -90,7 +92,7 @@ static int builder_basic(int level_number); static void builder_extras(int level_number, int level_type); static void builder_items(int level_number, char level_type, int items_wanted); static void builder_monsters(int level_number, char level_type, int mon_wanted); -static void place_specific_stair(unsigned char stair); +static void place_specific_stair(int stair, const std::string &tag = "", int dl = 0); static void place_branch_entrances(int dlevel, char level_type); static void place_special_minivaults(int level_number, int level_type); static void place_traps( int level_number ); @@ -108,7 +110,8 @@ static void many_pools(unsigned char pool_type); static bool join_the_dots( const coord_def &from, const coord_def &to, - const dgn_region_list &forbidden); + const dgn_region_list &forbidden, + bool early_exit = false); static void build_river(unsigned char river_type); //mv static void build_lake(unsigned char lake_type); //mv @@ -151,13 +154,15 @@ static void beehive(spec_room &sr); static void jelly_pit(int level_number, spec_room &sr); // VAULT FUNCTIONS -static void build_vaults(int level_number, int vault_number); +static bool build_secondary_vault(int level_number, int vault, int rune_subst = -1); +static bool build_vaults(int level_number, int vault_number, int rune_subst = -1, + bool build_only = false); static void build_minivaults(int level_number, int force_vault); static int vault_grid( vault_placement &, int level_number, int vx, int vy, int altar_count, FixedVector < char, 7 > &acq_item_class, char vgrid, std::vector<coord_def> &targets, - int &num_runes ); + int &num_runes, int rune_subst = -1); // ALTAR FUNCTIONS static int pick_an_altar(void); @@ -339,35 +344,32 @@ static bool valid_dungeon_level(int level_number, int level_type) return (true); } -static void build_dungeon_level(int level_number, int level_type) +static void reset_level() { - int i; // generic loop variable - int x,y; // generic map loop variables - level_vaults.clear(); no_monster_zones.clear(); no_pool_fixup_zones.clear(); no_door_fixup_zones.clear(); // blank level with DNGN_ROCK_WALL - make_box(0,0,GXM-1,GYM-1,DNGN_ROCK_WALL,DNGN_ROCK_WALL); + make_box(0, 0, GXM - 1, GYM - 1, DNGN_ROCK_WALL, DNGN_ROCK_WALL); // delete all traps - for (i = 0; i < MAX_TRAPS; i++) + for (int i = 0; i < MAX_TRAPS; i++) env.trap[i].type = TRAP_UNASSIGNED; // initialize all items - for (i = 0; i < MAX_ITEMS; i++) + for (int i = 0; i < MAX_ITEMS; i++) init_item( i ); // reset all monsters - for (i = 0; i < MAX_MONSTERS; i++) + for (int i = 0; i < MAX_MONSTERS; i++) menv[i].type = -1; // unlink all monsters and items from the grid - for(x=0; x<GXM; x++) + for(int x=0; x<GXM; x++) { - for(y=0; y<GYM; y++) + for(int y=0; y<GYM; y++) { mgrd[x][y] = NON_MONSTER; igrd[x][y] = NON_ITEM; @@ -377,10 +379,12 @@ static void build_dungeon_level(int level_number, int level_type) // reset all shops for (unsigned char shcount = 0; shcount < 5; shcount++) env.shop[shcount].type = SHOP_UNASSIGNED; +} - int skip_build; - - skip_build = builder_by_type(level_number, level_type); +static void build_layout_skeleton(int level_number, int level_type, + spec_room &sr) +{ + int skip_build = builder_by_type(level_number, level_type); if (skip_build < 0) return; @@ -392,8 +396,6 @@ static void build_dungeon_level(int level_number, int level_type) return; } - spec_room sr = { false, false, 0, 0, 0, 0 }; - if (skip_build == 0) { // do 'normal' building. Well, except for the swamp. @@ -407,6 +409,14 @@ static void build_dungeon_level(int level_number, int level_type) builder_extras(level_number, level_type); } } +} + +static void build_dungeon_level(int level_number, int level_type) +{ + spec_room sr; + + reset_level(); + build_layout_skeleton(level_number, level_type, sr); // Try to place minivaults that really badly want to be placed. Still // no guarantees, seeing this is a minivault. @@ -521,8 +531,8 @@ static void build_dungeon_level(int level_number, int level_type) player_branch_depth() == 1 && you.level_type == LEVEL_DUNGEON ) { - for (x = 1; x < GXM; x++) - for (y = 1; y < GYM; y++) + for (int x = 1; x < GXM; x++) + for (int y = 1; y < GYM; y++) if (grd[x][y] >= DNGN_STONE_STAIRS_UP_I && grd[x][y] <= DNGN_ROCK_STAIRS_UP) grd[x][y] = branches[(int)you.where_are_you].exit_stairs; @@ -532,8 +542,8 @@ static void build_dungeon_level(int level_number, int level_type) if ( player_branch_depth() == branches[(int)you.where_are_you].depth && you.level_type == LEVEL_DUNGEON) { - for (x = 1; x < GXM; x++) - for (y = 1; y < GYM; y++) + for (int x = 1; x < GXM; x++) + for (int y = 1; y < GYM; y++) if (grd[x][y] >= DNGN_STONE_STAIRS_DOWN_I && grd[x][y] <= DNGN_ROCK_STAIRS_DOWN) grd[x][y] = DNGN_ROCK_STAIRS_UP; @@ -553,9 +563,9 @@ static void build_dungeon_level(int level_number, int level_type) // hall of blades (1 level deal) - no down staircases, thanks! if (player_in_branch( BRANCH_HALL_OF_BLADES )) { - for (x = 1; x < GXM; x++) + for (int x = 1; x < GXM; x++) { - for (y = 1; y < GYM; y++) + for (int y = 1; y < GYM; y++) { if (grd[x][y] >= DNGN_STONE_STAIRS_DOWN_I && grd[x][y] <= DNGN_ROCK_STAIRS_UP) @@ -3876,6 +3886,20 @@ static int builder_by_type(int level_number, char level_type) return 0; } +static int random_portal_vault(const std::string &tag) +{ + return random_map_for_tag(tag, false); +} + +static bool place_portal_vault(int stair, const std::string &tag, int dlevel) +{ + const int vault = random_portal_vault(tag); + if (vault == -1) + return (false); + + return build_secondary_vault(dlevel, vault, stair); +} + static int random_map_for_dlevel(int level_number, bool wantmini = false) { int subdepth = subdungeon_depth(you.where_are_you, level_number); @@ -4309,7 +4333,7 @@ static void place_traps(int level_number) } // end "for i" } // end place_traps() -static void place_specific_stair(unsigned char stair) +static void place_specific_feature(int feat) { int sx, sy; @@ -4320,9 +4344,14 @@ static void place_specific_stair(unsigned char stair) } while(grd[sx][sy] != DNGN_FLOOR || mgrd[sx][sy] != NON_MONSTER); - grd[sx][sy] = stair; + grd[sx][sy] = feat; } +static void place_specific_stair(int stair, const std::string &tag, int dlevel) +{ + if (tag.empty() || !place_portal_vault(stair, tag, dlevel)) + place_specific_feature(stair); +} static void place_branch_entrances(int dlevel, char level_type) { @@ -4335,15 +4364,15 @@ static void place_branch_entrances(int dlevel, char level_type) { // stair to HELL if (dlevel >= 20 && dlevel <= 27) - place_specific_stair(DNGN_ENTER_HELL); + place_specific_stair(DNGN_ENTER_HELL, "hell_entry", dlevel); // stair to PANDEMONIUM if (dlevel >= 20 && dlevel <= 50 && (dlevel == 23 || one_chance_in(4))) - place_specific_stair(DNGN_ENTER_PANDEMONIUM); + place_specific_stair(DNGN_ENTER_PANDEMONIUM, "pan_entry", dlevel); // stairs to ABYSS if (dlevel >= 20 && dlevel <= 30 && (dlevel == 24 || one_chance_in(3))) - place_specific_stair(DNGN_ENTER_ABYSS); + place_specific_stair(DNGN_ENTER_ABYSS, "abyss_entry", dlevel); // level 26: replaces all down stairs with staircases to Zot: if (dlevel == 26) @@ -4374,7 +4403,15 @@ static void place_branch_entrances(int dlevel, char level_type) mprf(MSGCH_DIAGNOSTICS, "Placing stair to %s", branches[i].shortname); #endif - place_specific_stair(branches[i].entry_stairs); + + std::string entry_tag = std::string(branches[i].abbrevname); + entry_tag += "_entry"; + lowercase(entry_tag); + + place_specific_stair( + branches[i].entry_stairs, + entry_tag, + dlevel); } } } @@ -5323,7 +5360,7 @@ static void build_minivaults(int level_number, int force_vault) map_type vgrid; vault_placement place; - vault_main(vgrid, place, force_vault, level_number); + vault_main(vgrid, place, force_vault, &level_vaults); level_vaults.push_back(place); @@ -5498,7 +5535,7 @@ static void build_rooms(const dgn_region_list &excluded, } } -static coord_def dig_away_dir(vault_placement &place, +static coord_def dig_away_dir(const vault_placement &place, const coord_def &pos) { // Figure out which way we need to go to dig our way out of the vault. @@ -5602,14 +5639,94 @@ static void pick_float_exits(vault_placement &place, } } -static void build_vaults(int level_number, int force_vault) +static std::vector<coord_def> external_connection_points( + const vault_placement &place, + const std::vector<coord_def> &target_connections) +{ + std::vector<coord_def> ex_connection_points; + + // Giving target_connections directly to build_rooms causes + // problems with long, skinny vaults where paths to the exit + // tend to cut through the vault. By backing out of the vault + // one square, we improve connectibility. + for (int i = 0, size = target_connections.size(); i < size; ++i) + { + const coord_def &p = target_connections[i]; + ex_connection_points.push_back(p + dig_away_dir(place, p)); + } + + return (ex_connection_points); +} + +static dgn_region_list get_vault_regions() +{ + dgn_region_list vaults; + + for (int i = 0, size = level_vaults.size(); i < size; ++i) + { + const vault_placement &vp = level_vaults[i]; + vaults.push_back(dgn_region(vp.x, vp.y, vp.width, vp.height)); + } + + return (vaults); +} + +static coord_def find_random_grid(int grid, const dgn_region_list &excluded) +{ + for (int i = 0; i < 100; ++i) + { + coord_def c( random_range(MAPGEN_BORDER + 1, + GXM - MAPGEN_BORDER - 1), + random_range(MAPGEN_BORDER + 1, + GYM - MAPGEN_BORDER - 1) ); + + if (unforbidden(c, excluded) && grd(c) == grid) + return c; + } + return coord_def(0, 0); +} + +static void connect_vault(const vault_placement &vp) +{ + std::vector<coord_def> exc = external_connection_points(vp, vp.exits); + dgn_region_list vaults = get_vault_regions(); + + for (int i = 0, size = exc.size(); i < size; ++i) + { + const coord_def &p = exc[i]; + const coord_def floor = find_random_grid(DNGN_FLOOR, vaults); + + if (!floor.x && !floor.y) + continue; + + join_the_dots(p, floor, vaults, true); + } +} + +/* + * Places a vault somewhere in an already built level if possible. + * Returns true if the vault was successfully placed. + */ +static bool build_secondary_vault(int level_number, int vault, int rune_subst) +{ + if (build_vaults(level_number, vault, rune_subst, true)) + { + const vault_placement &vp = level_vaults[ level_vaults.size() - 1 ]; + connect_vault(vp); + + return (true); + } + return (false); +} + +static bool build_vaults(int level_number, int force_vault, int rune_subst, + bool build_only) { // for some weird reason can't put a vault on level 1, because monster equip // isn't generated. int altar_count = 0; FixedVector < char, 10 > stair_exist; char stx, sty; - std::vector<coord_def> target_connections; FixedVector < char, 7 > acq_item_class; // hack - passing chars through '...' promotes them to ints, which @@ -5624,26 +5741,33 @@ static void build_vaults(int level_number, int force_vault) map_type vgrid; vault_placement place; + std::vector<coord_def> &target_connections = place.exits; - int gluggy = vault_main(vgrid, place, force_vault, level_number); + const int gluggy = vault_main(vgrid, place, force_vault, &level_vaults); - level_vaults.push_back(place); + if (gluggy == MAP_NONE) + return (false); int vx, vy; int num_runes = 0; + dgn_region this_vault(place.x, place.y, place.width, place.height); // note: assumes *no* previous item (I think) or monster (definitely) // placement for (vx = 0; vx < GXM; vx++) { for (vy = 0; vy < GYM; vy++) { + if (!this_vault.contains( coord_def(vx, vy) )) + continue; + altar_count = vault_grid( place, level_number, vx, vy, altar_count, acq_item_class, vgrid[vy][vx], target_connections, - num_runes ); + num_runes, + rune_subst ); } } @@ -5658,13 +5782,18 @@ static void build_vaults(int level_number, int force_vault) no_pool_fixup_zones.push_back( dgn_region( place.x, place.y, place.width, place.height ) ); - // If the map takes the whole screen, our work is done. - if (gluggy == MAP_ENCOMPASS) - return; - if (gluggy == MAP_FLOAT && target_connections.empty()) pick_float_exits(place, target_connections); + // Must do this only after target_connections is finalised, or the vault + // exits will not be correctly set. + level_vaults.push_back(place); + + // If the map takes the whole screen or we were only requested to + // build, our work is done. + if (gluggy == MAP_ENCOMPASS || build_only) + return (true); + // Does this level require Dis treatment (metal wallification)? // XXX: Change this so the level definition can explicitly state what // kind of wallification it wants. @@ -5699,16 +5828,8 @@ static void build_vaults(int level_number, int force_vault) if (gluggy == MAP_FLOAT) nrooms += 10; - std::vector<coord_def> ex_connection_points; - // Giving target_connections directly to build_rooms causes - // problems with long, skinny vaults where paths to the exit - // tend to cut through the vault. By backing out of the vault - // one square, we improve connectability. - for (int i = 0, size = target_connections.size(); i < size; ++i) - { - const coord_def &p = target_connections[i]; - ex_connection_points.push_back(p + dig_away_dir(place, p)); - } + std::vector<coord_def> ex_connection_points = + external_connection_points(place, target_connections); build_rooms(excluded_regions, ex_connection_points, nrooms); @@ -5728,7 +5849,7 @@ static void build_vaults(int level_number, int force_vault) if (grd[stx][sty] >= DNGN_STONE_STAIRS_DOWN_I && grd[stx][sty] <= DNGN_ROCK_STAIRS_UP) { - stair_exist[grd[stx][sty] - 82] = 1; + stair_exist[grd[stx][sty] - DNGN_STONE_STAIRS_DOWN_I] = 1; } } } @@ -5746,8 +5867,10 @@ static void build_vaults(int level_number, int force_vault) { for (int i = 0; i < 2; i++) { - // does this look funny to *you*? {dlb} - if (stair_exist[(82 + j + (i * 4)) - 82] == 1) + const int stair = j + ((i == 0) ? DNGN_STONE_STAIRS_DOWN_I + : DNGN_STONE_STAIRS_UP_I); + + if (stair_exist[stair - DNGN_STONE_STAIRS_DOWN_I] == 1) continue; do @@ -5759,10 +5882,11 @@ static void build_vaults(int level_number, int force_vault) || (pos_x >= v1x && pos_x <= v2x && pos_y >= v1y && pos_y <= v2y)); - grd[pos_x][pos_y] = j + ((i == 0) ? DNGN_STONE_STAIRS_DOWN_I - : DNGN_STONE_STAIRS_UP_I); + grd[pos_x][pos_y] = stair; } } + + return (true); } // end build_vaults() static void dngn_place_item_explicit(int index, int x, int y, @@ -5810,7 +5934,8 @@ static int vault_grid( vault_placement &place, FixedVector < char, 7 > &acq_item_class, char vgrid, std::vector<coord_def> &targets, - int &num_runes) + int &num_runes, + int rune_subst ) { int not_used; @@ -5920,6 +6045,12 @@ static int vault_grid( vault_placement &place, } else // for 'P' (1 out of 3 times) {dlb} { + if (rune_subst != -1) + { + grd[vx][vy] = rune_subst; + break; + } + which_class = OBJ_MISCELLANY; which_type = MISC_RUNE_OF_ZOT; num_runes++; @@ -6034,7 +6165,8 @@ bool unforbidden(const coord_def &c, const dgn_region_list &forbidden) static bool join_the_dots( const coord_def &from, const coord_def &to, - const dgn_region_list &forbidden) + const dgn_region_list &forbidden, + bool early_exit) { if (from == to) return (true); @@ -6045,6 +6177,10 @@ static bool join_the_dots( do { join_count++; + + if (early_exit && at != from && grd(at) == DNGN_FLOOR) + return (true); + grd(at) = DNGN_FLOOR; if (join_count > 10000) // just insurance @@ -7349,7 +7485,7 @@ static char plan_1(void) if (temp_rand > 7) // 7 in 15 odds {dlb} { - spec_room sr = { false, false, 0,0,0,0 }; + spec_room sr; sr.x1 = 25; sr.y1 = 25; sr.x2 = (GXM - 25); @@ -7576,7 +7712,7 @@ static char plan_4(char forbid_x1, char forbid_y1, char forbid_x2, if (forbid_x1 == 0 && one_chance_in(4)) // a market square { - spec_room sr = { false, false, 0, 0, 0, 0 }; + spec_room sr; sr.x1 = 25; sr.y1 = 25; sr.x2 = 55; @@ -7616,7 +7752,7 @@ static char plan_5(void) static char plan_6(int level_number) { - spec_room sr = { false, false, 0,0,0,0 }; + spec_room sr; // circle of standing stones (well, kind of) sr.x1 = 10; @@ -8208,7 +8344,7 @@ static void diamond_rooms(int level_number) for (i = 0; i < numb_diam; i++) { - spec_room sr = { false, false, 0, 0, 0, 0 }; + spec_room sr; sr.x1 = 8 + random2(43); sr.y1 = 8 + random2(35); @@ -8239,7 +8375,7 @@ static void big_room(int level_number) unsigned char type_2 = DNGN_FLOOR; int i, j, k, l; - spec_room sr = { false, false, 0, 0, 0, 0 }; + spec_room sr; int oblique; if (one_chance_in(4)) diff --git a/crawl-ref/source/makefile.unix b/crawl-ref/source/makefile.unix index b8f3784aae..1b3f63d8eb 100644 --- a/crawl-ref/source/makefile.unix +++ b/crawl-ref/source/makefile.unix @@ -186,7 +186,6 @@ distclean: clean $(GAME): $(GAME_DEPENDS) ${CXX} ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB) - chmod ${MCHMOD} $(GAME) debug: $(GAME_DEPENDS) ${CXX} ${LDFLAGS} $(CFLAGS) $(OBJECTS) -o $(GAME) $(LIB) diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index 201090910d..f38314b8d8 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -24,16 +24,19 @@ #include "files.h" #include "monplace.h" #include "mapdef.h" +#include "misc.h" #include "stuff.h" #include "levcomp.h" static int write_vault(const map_def &mdef, map_type mt, - vault_placement &); + vault_placement &, + std::vector<vault_placement> *); static int apply_vault_definition( map_def &def, map_type map, - vault_placement &); + vault_placement &, + std::vector<vault_placement> *); static void resolve_map(map_def &def); @@ -55,8 +58,8 @@ static std::vector<map_def> vdefs; int vault_main( map_type vgrid, vault_placement &place, - int which_vault, - int many_many ) + int which_vault, + std::vector<vault_placement> *avoid) { #ifdef DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "Generating level: %s", @@ -74,18 +77,26 @@ int vault_main( } // NB - a return value of zero is not handled well by dungeon.cc (but there it is) 10mar2000 {dlb} - return write_vault( vdefs[which_vault], vgrid, place ); + return write_vault( vdefs[which_vault], vgrid, place, avoid ); } // end vault_main() static int write_vault(const map_def &mdef, map_type map, - vault_placement &place) + vault_placement &place, + std::vector<vault_placement> *avoid) { // Copy the map so we can monkey with it. place.map = mdef; - resolve_map(place.map); - return (place.orient = - apply_vault_definition(place.map, map, place)); + // Try so many times to place the map. This will always succeed + // unless there are conflicting map placements in 'avoid'. + int tries = 10; + do + resolve_map(place.map); + while ((place.orient = + apply_vault_definition(place.map, map, place, avoid)) == MAP_NONE + && tries-- > 0); + + return (place.orient); } // Mirror the map if appropriate, resolve substitutable symbols (?), @@ -106,8 +117,53 @@ static void resolve_map(map_def &map) map.rotate( coinflip() ); } -static void apply_vault_grid(map_def &def, map_type map, - vault_placement &place) +static bool is_grid_clobbered(int sx, int sy, int width, int height) +{ + for (int y = sy; y < sy + height; ++y) + { + for (int x = sx; x < sx + width; ++x) + { + int grid = grd[x][y]; + + if (!grid_is_opaque(grid) + && grid != DNGN_FLOOR + && grid != DNGN_CLOSED_DOOR + && grid != DNGN_OPEN_DOOR + && grid != DNGN_SECRET_DOOR) + { + return (true); + } + } + } + + return (false); +} + +// Determines if the region specified by (x, y, x + width - 1, y + height - 1) +// is a bad place to build a vault. +static bool bad_map_place(int x, int y, int width, int height, + std::vector<vault_placement> *avoid) +{ + if (!avoid) + return (false); + + const dgn_region thisvault(x, y, width, height); + + for (int i = 0, size = avoid->size(); i < size; ++i) + { + const vault_placement &vp = (*avoid)[i]; + const dgn_region vault(vp.x, vp.y, vp.width, vp.height); + + if (thisvault.overlaps(vault)) + return (true); + } + + return (is_grid_clobbered(x, y, width, height)); +} + +static bool apply_vault_grid(map_def &def, map_type map, + vault_placement &place, + std::vector<vault_placement> *avoid) { const map_lines &ml = def.map; const int orient = def.orient; @@ -146,6 +202,15 @@ static void apply_vault_grid(map_def &def, map_type map, starty = where.y; } + if (bad_map_place(startx, starty, width, height, avoid)) + { +#ifdef DEBUG_DIAGNOSTICS + mprf(MSGCH_DIAGNOSTICS, "Bad vault place: (%d,%d) dim (%d,%d)", + startx, starty, width, height); +#endif + return (false); + } + const std::vector<std::string> &lines = ml.get_lines(); #ifdef DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "Applying %s at (%d,%d), dimensions (%d,%d)", @@ -162,18 +227,23 @@ static void apply_vault_grid(map_def &def, map_type map, place.y = starty; place.width = width; place.height = height; + + return (true); } static int apply_vault_definition( map_def &def, map_type map, - vault_placement &place) + vault_placement &place, + std::vector<vault_placement> *avoid) { - apply_vault_grid(def, map, place); + if (!apply_vault_grid(def, map, place, avoid)) + return (MAP_NONE); int orient = def.orient; if (orient == MAP_NONE) orient = MAP_NORTH; + return (orient); } diff --git a/crawl-ref/source/maps.h b/crawl-ref/source/maps.h index 676d468190..6c098d11c4 100644 --- a/crawl-ref/source/maps.h +++ b/crawl-ref/source/maps.h @@ -16,6 +16,8 @@ #include "dungeon.h" #include "mapdef.h" +#include <vector> + class map_def; struct vault_placement { @@ -23,17 +25,19 @@ struct vault_placement int width, height; int orient; map_def map; + std::vector<coord_def> exits; vault_placement() - : x(-1), y(-1), width(0), height(0), map() + : x(-1), y(-1), width(0), height(0), map(), + exits() { } }; int vault_main(map_type vgrid, - vault_placement &vp, - int vault_force, - int many_many); + vault_placement &vp, + int vault_force, + std::vector<vault_placement> *avoid_vaults = NULL); const map_def *map_by_index(int index); int random_map_for_place(const std::string &place, bool mini = false); diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index cd5d9fcc56..b23ae18f15 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -2521,7 +2521,7 @@ void magic_mapping(int map_radius, int proportion) continue; } - if (grid_is_solid( grd[i + k][j + l] ) + if (grid_is_opaque( grd[i + k][j + l] ) && grd[i + k][j + l] != DNGN_CLOSED_DOOR) empty_count--; } @@ -2535,7 +2535,7 @@ void magic_mapping(int map_radius, int proportion) set_envmap_char(i, j, get_magicmap_char(grd[i][j])); #ifdef WIZARD - if (map_radius == 1000) + if (map_radius == 1000 && you.wizard) set_envmap_char(i, j, get_sightmap_char(grd[i][j])); #endif } @@ -2545,7 +2545,7 @@ void magic_mapping(int map_radius, int proportion) if ((you.mutation[MUT_PANDEMONIUM] > 1 && grd[i][j] == DNGN_EXIT_PANDEMONIUM) #ifdef WIZARD - || map_radius == 1000 + || (map_radius == 1000 && you.wizard) #endif ) { |