35 #include <SDL2/SDL_timer.h>
38 #define ERR_NG LOG_STREAM(err, log_mapgen)
39 #define LOG_NG LOG_STREAM(info, log_mapgen)
40 #define DBG_NG LOG_STREAM(debug, log_mapgen)
56 , windiness_(std::max<int>(1, cfg[
"road_windiness"].to_int()))
70 mutable std::map<t_translation::terrain_code, double> cache_;
73 double road_path_calculator::cost(
const map_location& loc,
const double )
const
76 if(loc.
x < 0 || loc.
y < 0 || loc.
x >= map_.w || loc.
y >= map_.h) {
88 double windiness = 1.0;
92 unsigned int a = (loc.
x + 92872973) ^ 918273;
93 unsigned int b = (loc.
y + 1672517) ^ 128123;
94 unsigned int c =
a*
b +
a +
b + seed_;
95 unsigned int random =
c*
c;
99 int noise = random % (windiness_ * 137) / 137;
104 const std::map<t_translation::terrain_code, double>::const_iterator itor = cache_.find(
c);
105 if(itor != cache_.end()) {
106 return itor->second*windiness;
109 static std::string terrain;
111 double res = getNoPathValue();
112 if(
auto child = cfg_.find_child(
"road_cost",
"terrain", terrain)) {
113 res = child[
"cost"].to_double();
116 cache_.emplace(
c, res);
117 return windiness*res;
124 bool operator()(
int x,
int y)
const;
131 : map_(map), terrain_(terrain_list)
135 bool is_valid_terrain::operator()(
int x,
int y)
const
137 if(x < 0 || x >= map_.w || y < 0 || y >= map_.h) {
142 return std::find(terrain_.begin(),terrain_.end(),map_[x][y]) != terrain_.end();
155 class terrain_height_mapper
158 explicit terrain_height_mapper(
const config& cfg);
160 bool convert_terrain(
const int height)
const;
168 terrain_height_mapper::terrain_height_mapper(
const config& cfg) :
169 terrain_height(cfg[
"height"]),
172 const std::string& terrain = cfg[
"terrain"];
173 if(!terrain.empty()) {
178 bool terrain_height_mapper::convert_terrain(
const int height)
const
180 return height >= terrain_height;
189 class terrain_converter
192 explicit terrain_converter(
const config& cfg);
198 int min_temp, max_temp, min_height, max_height;
203 terrain_converter::terrain_converter(
const config& cfg)
204 : min_temp(cfg[
"min_temperature"].to_int(-100000))
205 , max_temp(cfg[
"max_temperature"].to_int(100000))
206 , min_height(cfg[
"min_height"].to_int(-100000))
207 , max_height(cfg[
"max_height"].to_int(100000))
211 const std::string& to_str = cfg[
"to"];
212 if(!to_str.empty()) {
218 const int height,
const int temperature)
const
220 return std::find(from.begin(),from.end(),terrain) != from.end() && height >= min_height && height <= max_height && temperature >= min_temp && temperature <= max_temp && to !=
t_translation::NONE_TERRAIN;
258 size_t center_x = width/2;
259 size_t center_y = height/2;
261 LOG_NG <<
"off-centering...";
263 if(island_off_center != 0) {
266 center_x += island_off_center;
269 center_y += island_off_center;
272 if(center_x < island_off_center) {
275 center_x -= island_off_center;
279 if(center_y < island_off_center) {
282 center_y -= island_off_center;
287 return generate_height_map(width, height, iterations, hill_size, island_size, center_x, center_y);
292 height_map res(width, std::vector<int>(height,0));
294 DBG_NG << iterations <<
" iterations";
295 for(std::size_t
i = 0;
i != iterations; ++
i) {
308 bool is_valley =
false;
310 int x1 = island_size > 0 ? center_x - island_size + (
rng_()%(island_size*2)) :
static_cast<int>(
rng_()%width);
311 int y1 = island_size > 0 ? center_y - island_size + (
rng_()%(island_size*2)) :
static_cast<int>(
rng_()%height);
314 if(island_size != 0) {
315 const std::size_t diffx = std::abs(x1 -
static_cast<int>(center_x));
316 const std::size_t diffy = std::abs(y1 -
static_cast<int>(center_y));
317 const std::size_t dist = std::size_t(std::sqrt(
static_cast<double>(diffx*diffx + diffy*diffy)));
318 is_valley = dist > island_size;
321 const int radius =
rng_()%hill_size + 1;
322 DBG_NG <<
"placing hill at " << x1 <<
"," << y1 <<
" radius=" << radius <<
" is_valley=" << is_valley;
324 const int min_x = x1 - radius > 0 ? x1 - radius : 0;
325 const int max_x = x1 + radius < static_cast<long>(res.size()) ? x1 + radius : res.size();
326 const int min_y = y1 - radius > 0 ? y1 - radius : 0;
327 const int max_y = y1 + radius < static_cast<long>(res.front().size()) ? y1 + radius : res.front().size();
329 for(
int x2 = min_x; x2 < max_x; ++x2) {
330 for(
int y2 = min_y; y2 < max_y; ++y2) {
331 const int xdiff = (x2-x1);
332 const int ydiff = (y2-y1);
334 const int hill_height = radius -
static_cast<int>(std::sqrt(
static_cast<double>(xdiff*xdiff + ydiff*ydiff)));
336 if(hill_height > 0) {
338 if(hill_height > res[x2][y2]) {
341 res[x2][y2] -= hill_height;
344 res[x2][y2] += hill_height;
352 int highest = 0, lowest = 100000, x;
353 for(x = 0; std::size_t(x) != res.size(); ++x) {
354 for(
int y = 0; std::size_t(y) != res[x].size(); ++y) {
355 if(res[x][y] > highest) {
359 if(res[x][y] < lowest) {
365 LOG_NG <<
"generate_height_map"
366 <<
" lowest=" << lowest
367 <<
" highest =" << highest;
370 for(x = 0; std::size_t(x) != res.size(); ++x) {
371 for(
int y = 0; std::size_t(y) != res[x].size(); ++y) {
375 res[x][y] /= highest;
394 if(x < 0 || y < 0 || x >= terrain.
w || y >= terrain.
h || lake_fall_off < 0) {
398 unsigned int ulake_fall_off = lake_fall_off;
402 if((
rng_()%100) < ulake_fall_off) {
406 if((
rng_()%100) < ulake_fall_off) {
410 if((
rng_()%100) < ulake_fall_off) {
414 if((
rng_()%100) < ulake_fall_off) {
440 terrain_map& terrain,
int x,
int y, std::vector<map_location>& river,
441 std::set<map_location>& seen_locations,
int river_uphill)
443 const bool on_map = x >= 0 && y >= 0 &&
444 x < static_cast<long>(heights.size()) &&
445 y < static_cast<long>(heights.back().size());
447 if(on_map && !river.empty() && heights[x][y] >
448 heights[river.back().x][river.back().y] + river_uphill) {
457 LOG_NG <<
"generating river...";
460 for(
auto i : river) {
464 LOG_NG <<
"done generating river";
474 seen_locations.insert(current_loc);
475 river.push_back(current_loc);
477 if(seen_locations.count(loc) == 0) {
493 std::vector<map_location> river;
494 std::set<map_location> seen_locations;
509 const int side =
rng_()%4;
511 const int x =
rng_()%width;
512 const int y = side == 0 ? 0 : height-1;
515 const int y =
rng_()%height;
516 const int x = side == 2 ? 0 : width-1;
535 for(std::size_t y = begin_y; y != end_y; ++y) {
536 for(std::size_t x = begin_x; x != end_x; ++x) {
537 map[x - begin_x][y - begin_y] = terrain[x][y];
549 static int rank_castle_location(
int x,
int y,
const is_valid_terrain& valid_terrain,
int min_x,
int max_x,
int min_y,
int max_y, std::size_t min_distance,
const std::vector<map_location>& other_castles,
int highest_ranking)
553 std::size_t avg_distance = 0, lowest_distance = 1000;
555 for(std::vector<map_location>::const_iterator
c = other_castles.begin();
c != other_castles.end(); ++
c) {
561 if(distance < lowest_distance) {
562 lowest_distance = distance;
565 if(distance < min_distance) {
569 avg_distance += distance;
572 if(!other_castles.empty()) {
573 avg_distance /= other_castles.size();
576 for(
int i = x-1;
i <= x+1; ++
i) {
577 for(
int j = y-1; j <= y+1; ++j) {
578 if(!valid_terrain(
i,j)) {
584 const int x_from_border = std::min<int>(x - min_x,max_x - x);
585 const int y_from_border = std::min<int>(y - min_y,max_y - y);
587 const int border_ranking = min_distance - std::min<int>(x_from_border,y_from_border) + min_distance - x_from_border - y_from_border;
589 int current_ranking = border_ranking*2 + avg_distance*10 + lowest_distance*10;
590 static const int num_nearby_locations = 11*11;
592 const int max_possible_ranking = current_ranking + num_nearby_locations;
594 if(max_possible_ranking < highest_ranking) {
595 return current_ranking;
598 int surrounding_ranking = 0;
600 for(
int xpos = x-5; xpos <= x+5; ++xpos) {
601 for(
int ypos = y-5; ypos <= y+5; ++ypos) {
602 if(valid_terrain(xpos,ypos)) {
603 ++surrounding_ranking;
608 return surrounding_ranking + current_ranking;
614 const std::size_t x,
const std::size_t y,
const std::size_t radius,
const config& cfg,
618 std::set<map_location> locs;
623 if(
i.x < 0 ||
i.y < 0 ||
i.x >= map.
w ||
631 if(
auto child = cfg.
find_child(
"village",
"terrain", str)) {
634 if(l != adj_liked_cache.end()) {
635 adjacent_liked = &(l->second);
638 adjacent_liked = &(adj_liked_cache[
t]);
641 int rating = child[
"rating"];
643 if(adj.x < 0 || adj.y < 0 || adj.x >= map.
w || adj.y >= map.
h) {
648 rating += std::count(adjacent_liked->begin(),adjacent_liked->end(),t2);
651 if(rating > best_rating) {
653 best_rating = rating;
664 unsigned width,
unsigned height,
665 std::size_t label_count, std::map<map_location,std::string>* labels,
const std::string& full_name) {
671 if(
static_cast<unsigned>(adj.x) >= width / 3 ||
static_cast<unsigned>(adj.y) >= height / 3) {
677 tile_names.emplace(adj, name);
679 if(label_count % 6 == 0) {
680 labels->emplace(adj, full_name);
683 flood_name(adj, name, tile_names, tile_types, terrain, width, height, label_count++, labels, full_name);
692 LOG_NG <<
"default_generate_map parameters"
693 <<
" width=" <<
data.width
694 <<
" height=" <<
data.height
695 <<
" nplayers=" <<
data.nplayers
696 <<
" nvillages=" <<
data.nvillages
697 <<
" iterations=" <<
data.iterations
698 <<
" hill_size=" <<
data.hill_size
699 <<
" castle_size=" <<
data.castle_size
700 <<
" island_size=" <<
data.island_size
701 <<
" island_off_center=" <<
data.island_off_center
702 <<
" max_lakes=" <<
data.max_lakes
703 <<
" link_castles=" <<
data.link_castles
704 <<
" show_labels=" <<
data.show_labels;
712 int ticks = SDL_GetTicks();
729 std::map<map_location,std::string>* misc_labels = naming.
empty() ? nullptr : labels;
731 std::shared_ptr<name_generator>
732 base_name_generator, river_name_generator, lake_name_generator,
733 road_name_generator, bridge_name_generator, mountain_name_generator,
734 forest_name_generator, swamp_name_generator;
736 if(misc_labels !=
nullptr) {
737 name_generator_factory base_generator_factory{ naming, {
"male",
"base",
"bridge",
"road",
"river",
"forest",
"lake",
"mountain",
"swamp"} };
742 base_name_generator = base_generator_factory.get_name_generator( (naming.
has_attribute(
"base_names") || naming.
has_attribute(
"base_name_generator")) ?
"base" :
"male" );
743 river_name_generator = base_generator_factory.get_name_generator(
"river");
744 lake_name_generator = base_generator_factory.get_name_generator(
"lake");
745 road_name_generator = base_generator_factory.get_name_generator(
"road");
746 bridge_name_generator = base_generator_factory.get_name_generator(
"bridge");
747 mountain_name_generator = base_generator_factory.get_name_generator(
"mountain");
748 forest_name_generator = base_generator_factory.get_name_generator(
"forest");
749 swamp_name_generator = base_generator_factory.get_name_generator(
"swamp");
755 LOG_NG <<
"Done generating height map. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
756 ticks = SDL_GetTicks();
759 std::string flatland = cfg[
"default_flatland"];
760 if(flatland.empty()) {
766 std::vector<terrain_height_mapper> height_conversion;
768 height_conversion.emplace_back(
h);
772 for(std::size_t x = 0; x != heights.size(); ++x) {
773 for(std::size_t y = 0; y != heights[x].size(); ++y) {
774 for(
auto i : height_conversion) {
775 if(
i.convert_terrain(heights[x][y])) {
776 terrain[x][y] =
i.convert_to();
785 LOG_NG <<
"Placed landforms. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
786 ticks = SDL_GetTicks();
800 std::set<map_location> lake_locs;
802 std::map<map_location, std::string> river_names, lake_names, road_names, bridge_names, mountain_names, forest_names, swamp_names;
804 const std::size_t nlakes =
data.max_lakes > 0 ? (
rng_()%
data.max_lakes) : 0;
805 for(std::size_t lake = 0; lake != nlakes; ++lake) {
806 for(
int tries = 0; tries != 100; ++tries) {
810 if(heights[x][y] <= cfg[
"min_lake_height"].to_int()) {
814 std::vector<map_location> river =
generate_river(heights, terrain, x, y, cfg[
"river_frequency"]);
816 if(!river.empty() && misc_labels !=
nullptr) {
817 const std::string
base_name = base_name_generator->generate();
818 const std::string& name = river_name_generator->generate({{
"base",
base_name}});
819 LOG_NG <<
"Named river '" << name <<
"'";
821 std::size_t name_frequency = 20;
822 for(std::vector<map_location>::const_iterator r = river.begin(); r != river.end(); ++r) {
825 if(((r - river.begin())%name_frequency) == name_frequency/2) {
826 misc_labels->emplace(loc, name);
833 LOG_NG <<
"Generating lake...";
835 std::set<map_location> locs;
836 if(
generate_lake(terrain, x, y, cfg[
"lake_size"], locs) && misc_labels !=
nullptr) {
837 bool touches_other_lake =
false;
839 std::string
base_name = base_name_generator->generate();
840 const std::string& name = lake_name_generator->generate({{
"base",
base_name}});
845 if(lake_locs.count(
i) != 0) {
846 touches_other_lake =
true;
850 const std::map<map_location,std::string>::const_iterator other_name = lake_names.find(loc);
851 if(other_name != lake_names.end()) {
859 if(!touches_other_lake) {
861 misc_labels->erase(loc);
862 misc_labels->emplace(loc, name);
875 LOG_NG <<
"Generated rivers. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
876 ticks = SDL_GetTicks();
878 const std::size_t default_dimensions = 40*40*9;
889 cfg[
"temperature_iterations"].to_int() *
data.width *
data.height / default_dimensions,
890 cfg[
"temperature_size"], 0, 0);
892 LOG_NG <<
"Generated temperature map. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
893 ticks = SDL_GetTicks();
895 std::vector<terrain_converter> converters;
897 converters.emplace_back(cv);
900 LOG_NG <<
"Created terrain converters. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
901 ticks = SDL_GetTicks();
904 for(
int x = 0; x !=
data.width; ++x) {
905 for(
int y = 0; y !=
data.height; ++y) {
906 for(
auto i : converters) {
907 if(
i.convert_terrain(terrain[x][y],heights[x][y],temperature_map[x][y])) {
908 terrain[x][y] =
i.convert_to();
915 LOG_NG <<
"Placing castles...";
926 std::vector<map_location> castles;
927 std::set<map_location> failed_locs;
938 for(
int player = 0; player !=
data.nplayers; ++player) {
939 LOG_NG <<
"placing castle for " << player;
941 const int min_x =
data.width/3 + 3;
942 const int min_y =
data.height/3 + 3;
943 const int max_x = (
data.width/3)*2 - 4;
944 const int max_y = (
data.height/3)*2 - 4;
945 int min_distance = castle_config[
"min_distance"];
948 int best_ranking = 0;
949 for(
int x = min_x; x != max_x; ++x) {
950 for(
int y = min_y; y != max_y; ++y) {
952 if(failed_locs.count(loc)) {
956 const int ranking =
rank_castle_location(x, y, terrain_tester, min_x, max_x, min_y, max_y, min_distance, castles, best_ranking);
958 failed_locs.insert(loc);
961 if(ranking > best_ranking) {
962 best_ranking = ranking;
968 if(best_ranking == 0) {
969 ERR_NG <<
"No castle location found, for " <<
data.nplayers <<
" players aborting. ";
970 const std::string error =
_(
"No valid castle location found. Too many or too few mountain hexes? (please check the 'max hill size' parameter)");
974 assert(std::find(castles.begin(), castles.end(), best_loc) == castles.end());
975 castles.push_back(best_loc);
978 failed_locs.insert(best_loc);
981 LOG_NG <<
"Placed castles. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
983 LOG_NG <<
"Placing roads...";
984 ticks = SDL_GetTicks();
989 int nroads = cfg[
"roads"];
990 if(
data.link_castles) {
991 nroads += castles.size()*castles.size();
994 std::set<map_location> bridges;
996 road_path_calculator calc(terrain, cfg,
rng_());
997 for(
int road = 0; road != nroads; ++road) {
1008 src.
x +=
data.width/3 - 1;
1009 src.
y +=
data.height/3 - 1;
1010 dst.
x +=
data.width/3 - 1;
1011 dst.
y +=
data.height/3 - 1;
1013 if(
data.link_castles && road <
static_cast<int>(castles.size() * castles.size())) {
1014 const std::size_t src_castle = road/castles.size();
1015 const std::size_t dst_castle = road%castles.size();
1016 if(src_castle >= dst_castle) {
1020 src = castles[src_castle];
1021 dst = castles[dst_castle];
1022 }
else if(src.
x == dst.
x || src.
y == dst.
y) {
1027 if(calc.cost(src, 0.0) >= 1000.0 || calc.cost(dst, 0.0) >= 1000.0) {
1034 const std::string& road_base_name = misc_labels !=
nullptr
1035 ? base_name_generator->generate()
1037 const std::string& road_name = misc_labels !=
nullptr
1038 ? road_name_generator->generate({{
"base", road_base_name}})
1040 const int name_frequency = 20;
1043 bool on_bridge =
false;
1047 for(std::vector<map_location>::const_iterator step = rt.
steps.begin();
1048 step != rt.
steps.end(); ++step) {
1050 const int x = step->x;
1051 const int y = step->y;
1053 if(x < 0 || y < 0 || x >=
static_cast<long>(
data.width) || y >=
static_cast<long>(
data.height)) {
1059 if(!child || child->empty()){
1070 const std::string& convert_to_bridge = child[
"convert_to_bridge"];
1071 if(!convert_to_bridge.empty()) {
1072 if(step == rt.
steps.begin() || step+1 == rt.
steps.end()) {
1083 if((last == adj[0] && next == adj[3]) || (last == adj[3] && next == adj[0])) {
1088 else if((last == adj[1] && next == adj[4]) || (last == adj[4] && next == adj[1])) {
1093 else if((last == adj[2] && next == adj[5]) || (last == adj[5] && next == adj[2])) {
1097 if(misc_labels !=
nullptr && !on_bridge) {
1099 std::string bridge_base_name = base_name_generator->generate();
1100 const std::string& name = bridge_name_generator->generate({{
"base", bridge_base_name}});
1102 misc_labels->emplace(loc, name);
1103 bridge_names.emplace(loc, bridge_base_name);
1104 bridges.insert(loc);
1107 if(direction != -1) {
1109 if(std::size_t(direction) <
items.size() && !
items[direction].empty()) {
1120 const std::string& convert_to = child[
"convert_to"];
1121 if(!convert_to.empty()) {
1123 if(misc_labels !=
nullptr && terrain[x][y] != letter && name_count++ == name_frequency && !on_bridge) {
1128 terrain[x][y] = letter;
1129 if(misc_labels !=
nullptr) {
1131 if(!road_base_name.empty())
1132 road_names.emplace(loc, road_base_name);
1139 for(std::vector<map_location>::const_iterator
c = castles.begin();
c != castles.end(); ++
c) {
1146 const int player =
c - castles.begin() + 1;
1148 starting_positions.insert(t_translation::starting_positions::value_type(std::to_string(player), coord));
1151 const int castle_array[13][2] {
1152 {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {0, 1}, {-1, 1},
1153 {-2, 1}, {-2, 0}, {-2, -1}, {-1, -2}, {0, -2}, {1, -2}
1156 for(
int i = 0;
i <
data.castle_size - 1;
i++) {
1161 if(labels !=
nullptr) {
1163 for(
int i = 0;
i <
data.castle_size - 1;
i++) {
1169 LOG_NG <<
"Placed roads. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
1170 ticks = SDL_GetTicks();
1176 if(misc_labels !=
nullptr) {
1177 std::set<std::string> used_names;
1178 for(
int x =
data.width / 3; x < (
data.width / 3)*2; x++) {
1179 for(
int y =
data.height / 3; y < (
data.height / 3) * 2;y++) {
1187 if((
rng_() % 15) == 0) {
1188 for(std::size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1189 base_name = base_name_generator->generate();
1190 name = mountain_name_generator->generate({{
"base",
base_name}});
1192 misc_labels->emplace(loc, name);
1197 const std::map<map_location, std::string>::const_iterator forest_name = forest_names.find(loc);
1198 if(forest_name == forest_names.end()) {
1199 for(std::size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1200 base_name = base_name_generator->generate();
1201 name = forest_name_generator->generate({{
"base",
base_name}});
1209 const std::map<map_location, std::string>::const_iterator swamp_name = swamp_names.find(loc);
1210 if(swamp_name == swamp_names.end()) {
1211 for(std::size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1212 base_name = base_name_generator->generate();
1213 name = swamp_name_generator->generate({{
"base",
base_name}});
1221 used_names.insert(name);
1227 LOG_NG <<
"Named landforms. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
1228 LOG_NG <<
"Placing villages...";
1229 ticks = SDL_GetTicks();
1236 std::set<map_location> villages;
1238 if(
data.nvillages > 0) {
1241 const std::size_t tiles_per_village = ((
data.width*
data.height)/9)/
data.nvillages;
1242 std::size_t village_x = 1, village_y = 1;
1247 while(village_x*village_y < tiles_per_village) {
1248 if(village_x < village_y) {
1255 std::set<std::string> used_names;
1265 std::map<map_location,std::string>* village_labels = village_naming.
empty() ? nullptr : labels;
1267 for(
int vx = 0; vx <
data.width; vx += village_x) {
1268 LOG_NG <<
"village at " << vx;
1270 for(
int vy =
rng_()%village_y; vy <
data.height; vy += village_y) {
1271 const std::size_t add =
rng_()%3;
1272 const std::size_t x = (vx + add) - 1;
1273 const std::size_t y = (vy + add) - 1;
1277 if(res.
x <
static_cast<long>(
data.width ) / 3 ||
1278 res.
x >=
static_cast<long>(
data.width * 2) / 3 ||
1279 res.
y <
static_cast<long>(
data.height ) / 3 ||
1280 res.
y >=
static_cast<long>(
data.height * 2) / 3) {
1286 const std::string& convert_to = cfg.
find_mandatory_child(
"village",
"terrain", str)[
"convert_to"].str();
1287 if(convert_to.empty()) {
1293 villages.insert(res);
1295 if(village_labels ==
nullptr) {
1300 {
"base",
"male",
"village",
"lake",
"river",
"bridge",
"grassland",
"forest",
"hill",
"mountain",
"mountain_anon",
"road",
"swamp"} };
1305 base_name_generator = village_name_generator_factory.get_name_generator(
1311 std::string name_type =
"village";
1318 std::size_t field_count = 0, forest_count = 0, mountain_count = 0, hill_count = 0;
1320 std::map<std::string,std::string> symbols;
1323 for(
n = 0;
n != 6; ++
n) {
1324 const std::map<map_location,std::string>::const_iterator road_name = road_names.find(adj[
n]);
1325 if(road_name != road_names.end()) {
1326 symbols[
"road"] = road_name->second;
1331 const std::map<map_location,std::string>::const_iterator river_name = river_names.find(adj[
n]);
1332 if(river_name != river_names.end()) {
1333 symbols[
"river"] = river_name->second;
1334 name_type =
"river";
1336 const std::map<map_location,std::string>::const_iterator bridge_name = bridge_names.find(adj[
n]);
1337 if(bridge_name != bridge_names.end()) {
1339 symbols[
"bridge"] = bridge_name->second;
1340 name_type =
"river_bridge";
1346 const std::map<map_location,std::string>::const_iterator forest_name = forest_names.find(adj[
n]);
1347 if(forest_name != forest_names.end()) {
1348 symbols[
"forest"] = forest_name->second;
1349 name_type =
"forest";
1353 const std::map<map_location,std::string>::const_iterator lake_name = lake_names.find(adj[
n]);
1354 if(lake_name != lake_names.end()) {
1355 symbols[
"lake"] = lake_name->second;
1360 const std::map<map_location,std::string>::const_iterator mountain_name = mountain_names.find(adj[
n]);
1361 if(mountain_name != mountain_names.end()) {
1362 symbols[
"mountain"] = mountain_name->second;
1363 name_type =
"mountain";
1367 const std::map<map_location,std::string>::const_iterator swamp_name = swamp_names.find(adj[
n]);
1368 if(swamp_name != swamp_names.end()) {
1369 symbols[
"swamp"] = swamp_name->second;
1370 name_type =
"swamp";
1376 if(std::count(field.begin(),field.end(),terr) > 0) {
1378 }
else if(std::count(forest.begin(),forest.end(),terr) > 0) {
1380 }
else if(std::count(hill.begin(),hill.end(),terr) > 0) {
1382 }
else if(std::count(mountain.begin(),mountain.end(),terr) > 0) {
1388 if(field_count == 6) {
1389 name_type =
"grassland";
1390 }
else if(forest_count >= 2) {
1391 name_type =
"forest";
1392 }
else if(mountain_count >= 1) {
1393 name_type =
"mountain_anon";
1394 }
else if(hill_count >= 2) {
1401 symbols[
"base"] = base_name_generator->generate();
1402 std::shared_ptr<name_generator> village_name_generator = village_name_generator_factory.get_name_generator(name_type);
1404 for(std::size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1405 name = village_name_generator->generate(symbols);
1408 used_names.insert(name);
1409 village_labels->emplace(loc, name);
1414 LOG_NG <<
"Placed villages. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
A config object defines a single node in a WML file, with access to child nodes.
const attribute_value & get_old_attribute(config_key_type key, const std::string &old_key, const std::string &in_tag, const std::string &message="") const
Function to handle backward compatibility Get the value of key and if missing try old_key and log a d...
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
config & find_mandatory_child(config_key_type key, const std::string &name, const std::string &value)
optional_config_impl< config > find_child(config_key_type key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
bool has_attribute(config_key_type key) const
child_itors child_range(config_key_type key)
void append_attributes(const config &cfg)
Adds attributes from cfg.
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Euivalent to mandatory_child, but returns an empty optional if the nth child was not found.
height_map generate_height_map(size_t width, size_t height, size_t iterations, size_t hill_size, size_t island_size, size_t island_off_center)
Generate a height-map.
map_location random_point_at_side(std::size_t width, std::size_t height)
Returns a random tile at one of the borders of a map that is of the given dimensions.
std::string default_generate_map(generator_data data, std::map< map_location, std::string > *labels, const config &cfg)
Generate the map.
std::vector< map_location > generate_river(const height_map &heights, terrain_map &terrain, int x, int y, int river_uphill)
bool generate_lake(t_translation::ter_map &terrain, int x, int y, int lake_fall_off, std::set< map_location > &locs_touched)
Generate a lake.
const game_config_view & game_config_
bool generate_river_internal(const height_map &heights, terrain_map &terrain, int x, int y, std::vector< map_location > &river, std::set< map_location > &seen_locations, int river_uphill)
River generation.
std::vector< std::vector< int > > height_map
default_map_generator_job()
const config & mandatory_child(config_key_type key) const
static const int default_border
The default border style for a map.
static int rank_castle_location(int x, int y, const is_valid_terrain &valid_terrain, int min_x, int max_x, int min_y, int max_y, std::size_t min_distance, const std::vector< map_location > &other_castles, int highest_ranking)
std::map< t_translation::terrain_code, t_translation::ter_list > tcode_list_cache
static lg::log_domain log_mapgen("mapgen")
t_translation::ter_map terrain_map
static map_location place_village(const t_translation::ter_map &map, const std::size_t x, const std::size_t y, const std::size_t radius, const config &cfg, tcode_list_cache &adj_liked_cache)
static void flood_name(const map_location &start, const std::string &name, std::map< map_location, std::string > &tile_names, const t_translation::ter_match &tile_types, const terrain_map &terrain, unsigned width, unsigned height, std::size_t label_count, std::map< map_location, std::string > *labels, const std::string &full_name)
static std::string output_map(const terrain_map &terrain, t_translation::starting_positions &starting_positions)
Function which, given the map will output it in a valid format.
std::vector< std::vector< int > > height_map
static std::string _(const char *str)
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
std::size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Standard logging facilities (interface).
#define log_scope(description)
constexpr bool is_even(T num)
static bool is_valid_terrain(const t_translation::terrain_code &c)
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
std::string base_name(const std::string &file, const bool remove_extension)
Returns the base filename of a file, with directory name stripped.
Game configuration data as global variables.
std::vector< game_tip > shuffle(const std::vector< game_tip > &tips)
Shuffles the tips.
const std::vector< std::string > items
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator &calc, const std::size_t width, const std::size_t height, const teleport_map *teleports, bool border)
terrain_code read_terrain_code(std::string_view str, const ter_layer filler)
Reads a single terrain from a string.
const ter_match ALL_FORESTS
std::string write_game_map(const ter_map &map, const starting_positions &starting_positions, coordinate border_offset)
Write a gamemap in to a vector string.
const terrain_code SHALLOW_WATER
const ter_match ALL_SWAMPS("!,*^V*,*^B*,!,S*")
const terrain_code HUMAN_CASTLE
bool terrain_matches(const terrain_code &src, const terrain_code &dest)
Tests whether a specific terrain matches an expression, for matching rules see above.
std::vector< terrain_code > ter_list
const terrain_code GRASS_LAND
const terrain_code DEEP_WATER
boost::bimaps::bimap< boost::bimaps::set_of< std::string >, boost::bimaps::multiset_of< coordinate > > starting_positions
const terrain_code FOREST
ter_list read_list(std::string_view str, const ter_layer filler)
Reads a list of terrains from a string, when reading the.
const ter_match ALL_MOUNTAINS("!,*^V*,!,M*")
const terrain_code MOUNTAIN
std::string write_terrain_code(const terrain_code &tcode)
Writes a single terrain code to a string.
const terrain_code HUMAN_KEEP
const terrain_code NONE_TERRAIN
std::vector< std::string > split(const config_attribute_value &val)
std::string::const_iterator iterator
This module contains various pathfinding functions and utilities.
void get_tiles_radius(const map_location ¢er, std::size_t radius, std::set< map_location > &result)
Function that will add to result all locations within radius tiles of center (including center itself...
Encapsulates the map of the game.
static double getNoPathValue()
virtual double cost(const map_location &loc, const double so_far) const =0
Structure which holds a single route between one location and another.
std::vector< map_location > steps
This structure can be used for matching terrain strings.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
static map_location::DIRECTION n
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define VALIDATE(cond, message)
The macro to use for the validation of WML.