diff options
-rw-r--r-- | crawl-ref/source/coordit.cc | 83 | ||||
-rw-r--r-- | crawl-ref/source/coordit.h | 29 | ||||
-rw-r--r-- | crawl-ref/source/dat/des/builder/layout_pools.des | 46 | ||||
-rw-r--r-- | crawl-ref/source/l_dgnbld.cc | 69 |
4 files changed, 195 insertions, 32 deletions
diff --git a/crawl-ref/source/coordit.cc b/crawl-ref/source/coordit.cc index 5851283ff3..78fb358a65 100644 --- a/crawl-ref/source/coordit.cc +++ b/crawl-ref/source/coordit.cc @@ -58,12 +58,93 @@ void rectangle_iterator::operator ++() current.x++; } - void rectangle_iterator::operator++(int dummy) { ++(*this); } + +random_rectangle_iterator::random_rectangle_iterator(const coord_def& corner1, + const coord_def& corner2) +{ + int left = min(corner1.x, corner2.x); + int right = max(corner1.x, corner2.x); + int top = min(corner1.y, corner2.y); + int bottom = max(corner1.y, corner2.y); + + top_left.x = left; + top_left.y = top; + + for(int y = top; y <= bottom; y++) + for(int x = left; x <= right; x++) + remaining.push_back(coord_def(x, y)); + + if(remaining.empty()) + current = 0; + else + current = random2(remaining.size()); +} + +random_rectangle_iterator::random_rectangle_iterator(int x_border_dist, + int y_border_dist) +{ + if (y_border_dist < 0) + y_border_dist = x_border_dist; + + int right = GXM - x_border_dist - 1; + int bottom = GYM - y_border_dist - 1; + + top_left.x = x_border_dist; + top_left.y = y_border_dist; + + for(int y = y_border_dist; y <= bottom; y++) + for(int x = x_border_dist; x <= right; x++) + remaining.push_back(coord_def(x, y)); + + if(remaining.empty()) + current = 0; + else + current = random2(remaining.size()); +} + +random_rectangle_iterator::operator bool() const +{ + return !remaining.empty(); +} + +coord_def random_rectangle_iterator::operator *() const +{ + if(remaining.empty()) + return top_left; + else + return remaining[current]; +} + +const coord_def* random_rectangle_iterator::operator->() const +{ + if(remaining.empty()) + return &top_left; + else + return &(remaining[current]); +} + +void random_rectangle_iterator::operator ++() +{ + if(!remaining.empty()) + { + remaining[current] = remaining.back(); + remaining.pop_back(); + if(!remaining.empty()) + current = random2(remaining.size()); + } +} + +void random_rectangle_iterator::operator++(int dummy) +{ + ++(*this); +} + + /* * circle iterator */ diff --git a/crawl-ref/source/coordit.h b/crawl-ref/source/coordit.h index 74ae22d878..9c9695882a 100644 --- a/crawl-ref/source/coordit.h +++ b/crawl-ref/source/coordit.h @@ -18,6 +18,35 @@ private: coord_def current, topleft, bottomright; }; +/** + * @class random_rectangle_iterator + * Iterator over coordinates in a rectangular region in a + * random order. This interator does not favour any given + * direction, but is slower than rectangle_iterator. + * + * When this iterator has returned all elements, it will just + * return the top left corner forever. + */ +class random_rectangle_iterator : public iterator<forward_iterator_tag, + coord_def> +{ +public: + random_rectangle_iterator(const coord_def& corner1, + const coord_def& corner2); + explicit random_rectangle_iterator(int x_border_dist, + int y_border_dist = -1); + operator bool() const PURE; + coord_def operator *() const PURE; + const coord_def* operator->() const PURE; + + void operator ++ (); + void operator ++ (int); +private: + coord_def top_left; + vector<coord_def> remaining; + int current; +}; + class circle_iterator { const circle_def &circle; diff --git a/crawl-ref/source/dat/des/builder/layout_pools.des b/crawl-ref/source/dat/des/builder/layout_pools.des index 2a066f4087..b18f81e8a1 100644 --- a/crawl-ref/source/dat/des/builder/layout_pools.des +++ b/crawl-ref/source/dat/des/builder/layout_pools.des @@ -8,6 +8,8 @@ # that the dungeon builder can add other vaults on top of them. # +: require("dlua/layout/zonify.lua") + ############################################################## @@ -148,7 +150,7 @@ ENDMAP # by doors and sometimes just by holes in the wall. # NAME: layout_honeycomb -DEPTH: D:12-,Snake:1-4,Dis +DEPTH: D:12-, Snake:1-4, Dis WEIGHT: 10 ORIENT: encompass TAGS: overwritable layout allow_dup unrand @@ -160,42 +162,24 @@ TAGS: overwritable layout allow_dup unrand make_circle { x = gxm/2, y = gym/2, radius = 10 } mapgrd[gxm/2][gym/2] = '.' - spotty_map { boxy = true, iterations = 1200 } + spotty_map { boxy = true, iterations = 1500 } widen_paths { find = "x", percent = 50 } remove_isolated_glyphs { find = "x", percent = 100 } - local fill = '.' - local border = 'x' - local connection = crawl.random_element({[fill] = 1, ["+"] = 2}) + local connection = {} + if you.in_branch("snake") then + connection = '.' + else + connection = crawl.random_element({['.'] = 1, ['+'] = 2}) + end add_pools { replace = ".", - contents = {[fill] = 1}, + contents = {['.'] = 1}, pool_size = 25 + crawl.random2(25), - border = border } - - -- connect rooms - for i = 1, crawl.random_range(800, 1200) do - local x = crawl.random_range(1, gxm - 2) - local y = crawl.random_range(1, gym - 2) - - if mapgrd[x][y] == border then - if mapgrd[x + 1][y] == border and - mapgrd[x - 1][y] == border and - mapgrd[x][y + 1] == fill and - mapgrd[x][y - 1] == fill then - mapgrd[x][y] = connection - elseif mapgrd[x + 1][y] == fill and - mapgrd[x - 1][y] == fill and - mapgrd[x][y + 1] == border and - mapgrd[x][y - 1] == border then - mapgrd[x][y] = connection - end - end - end - - replace_closest { x = gxm/2, y = gym/2, find = fill, replace = '@' } - fill_disconnected{wanted = '@'} - subst("@ = " .. fill) + border = 'x' } + connect_adjacent_rooms { wall = "x", floor = ".", replace = connection, + min = 1000, max = 1500 } + zonify.map_fill_zones(_G, 1, 'x') random_wall_material(_G) }} diff --git a/crawl-ref/source/l_dgnbld.cc b/crawl-ref/source/l_dgnbld.cc index 7a4a199eb5..e2912afd87 100644 --- a/crawl-ref/source/l_dgnbld.cc +++ b/crawl-ref/source/l_dgnbld.cc @@ -926,6 +926,74 @@ LUAFN(dgn_widen_paths) return 0; } +LUAFN(dgn_connect_adjacent_rooms) +{ + LINES(ls, 1, lines); + + TABLE_STR(ls, wall, "x"); + TABLE_STR(ls, floor, "."); + TABLE_CHAR(ls, replace, '.'); + TABLE_INT(ls, max, 1); + TABLE_INT(ls, min, max); + + int x1, y1, x2, y2; + if (!_coords(ls, lines, x1, y1, x2, y2)) + return 0; + + // we never go right up to the border to avoid looking off the map edge + if(x1 < 1) + x1 = 1; + if(x2 >= lines.width() - 1) + x2 = lines.width() - 2; + if(y1 < 1) + y1 = 1; + if(y2 >= lines.height() - 1) + y2 = lines.height() - 2; + + if (min < 0) + return luaL_error(ls, "Invalid min connections: %i", min); + if (max < min) + { + return luaL_error(ls, "Invalid max connections: %i (min is %i)", + max, min); + } + + int count = min + random2(max - min + 1); + for (random_rectangle_iterator ri(coord_def(x1, y1), + coord_def(x2, y2)); ri; ++ri) + { + if(count <= 0) + { + // stop when have checked enough spots + return 0; + } + + int x = ri->x; + int y = ri->y; + + if (strchr(wall, lines(*ri))) + { + if ( strchr(wall, lines(x - 1, y)) + && strchr(wall, lines(x + 1, y)) + && strchr(floor, lines(x, y - 1)) + && strchr(floor, lines(x, y + 1))) + { + lines(*ri) = replace; + } + else if ( strchr(floor, lines(x - 1, y)) + && strchr(floor, lines(x + 1, y)) + && strchr(wall, lines(x, y - 1)) + && strchr(wall, lines(x, y + 1))) + { + lines(*ri) = replace; + } + } + count--; + } + + return 0; +} + LUAFN(dgn_replace_area) { LINES(ls, 1, lines); @@ -1501,6 +1569,7 @@ const struct luaL_reg dgn_build_dlib[] = { "octa_room", &dgn_octa_room }, { "remove_isolated_glyphs", &dgn_remove_isolated_glyphs }, { "widen_paths", &dgn_widen_paths }, + { "connect_adjacent_rooms", &dgn_connect_adjacent_rooms }, { "replace_area", &dgn_replace_area }, { "replace_first", &dgn_replace_first }, { "replace_random", &dgn_replace_random }, |