34 #include <SDL2/SDL_timer.h>
37 #define ERR_NG LOG_STREAM(err, log_mapgen)
38 #define LOG_NG LOG_STREAM(info, log_mapgen)
39 #define DBG_NG LOG_STREAM(debug, log_mapgen)
55 , windiness_(std::max<int>(1, cfg[
"road_windiness"].to_int()))
69 mutable std::map<t_translation::terrain_code, double> cache_;
72 double road_path_calculator::cost(
const map_location& loc,
const double )
const
75 if(loc.
x < 0 || loc.
y < 0 || loc.
x >= map_.w || loc.
y >= map_.h) {
87 double windiness = 1.0;
91 unsigned int a = (loc.
x + 92872973) ^ 918273;
92 unsigned int b = (loc.
y + 1672517) ^ 128123;
93 unsigned int c = a*
b + a +
b + seed_;
94 unsigned int random =
c*
c;
98 int noise = random % (windiness_ * 137) / 137;
103 const std::map<t_translation::terrain_code, double>::const_iterator itor = cache_.find(
c);
104 if(itor != cache_.end()) {
105 return itor->second*windiness;
108 static std::string terrain;
110 double res = getNoPathValue();
111 if(
auto child = cfg_.find_child(
"road_cost",
"terrain", terrain)) {
112 res = child[
"cost"].to_double();
115 cache_.emplace(
c, res);
116 return windiness*res;
123 bool operator()(
int x,
int y)
const;
130 : map_(map), terrain_(terrain_list)
134 bool is_valid_terrain::operator()(
int x,
int y)
const
136 if(x < 0 || x >= map_.w || y < 0 || y >= map_.h) {
141 return std::find(terrain_.begin(),terrain_.end(),map_[x][y]) != terrain_.end();
154 class terrain_height_mapper
157 explicit terrain_height_mapper(
const config& cfg);
159 bool convert_terrain(
const int height)
const;
167 terrain_height_mapper::terrain_height_mapper(
const config& cfg) :
168 terrain_height(cfg[
"height"]),
171 const std::string& terrain = cfg[
"terrain"];
172 if(!terrain.empty()) {
177 bool terrain_height_mapper::convert_terrain(
const int height)
const
179 return height >= terrain_height;
188 class terrain_converter
191 explicit terrain_converter(
const config& cfg);
197 int min_temp, max_temp, min_height, max_height;
202 terrain_converter::terrain_converter(
const config& cfg)
203 : min_temp(cfg[
"min_temperature"].to_int(-100000))
204 , max_temp(cfg[
"max_temperature"].to_int(100000))
205 , min_height(cfg[
"min_height"].to_int(-100000))
206 , max_height(cfg[
"max_height"].to_int(100000))
210 const std::string& to_str = cfg[
"to"];
211 if(!to_str.empty()) {
217 const int height,
const int temperature)
const
219 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;
257 size_t center_x = width/2;
258 size_t center_y = height/2;
260 LOG_NG <<
"off-centering...";
262 if(island_off_center != 0) {
265 center_x += island_off_center;
268 center_y += island_off_center;
271 if(center_x < island_off_center) {
274 center_x -= island_off_center;
278 if(center_y < island_off_center) {
281 center_y -= island_off_center;
286 return generate_height_map(width, height, iterations, hill_size, island_size, center_x, center_y);
291 height_map res(width, std::vector<int>(height,0));
293 DBG_NG << iterations <<
" iterations";
294 for(std::size_t
i = 0;
i != iterations; ++
i) {
307 bool is_valley =
false;
309 int x1 = island_size > 0 ? center_x - island_size + (
rng_()%(island_size*2)) :
static_cast<int>(
rng_()%width);
310 int y1 = island_size > 0 ? center_y - island_size + (
rng_()%(island_size*2)) :
static_cast<int>(
rng_()%height);
313 if(island_size != 0) {
314 const std::size_t diffx = std::abs(x1 -
static_cast<int>(center_x));
315 const std::size_t diffy = std::abs(y1 -
static_cast<int>(center_y));
316 const std::size_t dist = std::size_t(std::sqrt(
static_cast<double>(diffx*diffx + diffy*diffy)));
317 is_valley = dist > island_size;
320 const int radius =
rng_()%hill_size + 1;
321 DBG_NG <<
"placing hill at " << x1 <<
"," << y1 <<
" radius=" << radius <<
" is_valley=" << is_valley;
323 const int min_x = x1 - radius > 0 ? x1 - radius : 0;
324 const int max_x = x1 + radius < static_cast<long>(res.size()) ? x1 + radius : res.size();
325 const int min_y = y1 - radius > 0 ? y1 - radius : 0;
326 const int max_y = y1 + radius < static_cast<long>(res.front().size()) ? y1 + radius : res.front().size();
328 for(
int x2 = min_x; x2 < max_x; ++x2) {
329 for(
int y2 = min_y; y2 < max_y; ++y2) {
330 const int xdiff = (x2-x1);
331 const int ydiff = (y2-y1);
333 const int hill_height = radius -
static_cast<int>(std::sqrt(
static_cast<double>(xdiff*xdiff + ydiff*ydiff)));
335 if(hill_height > 0) {
337 if(hill_height > res[x2][y2]) {
340 res[x2][y2] -= hill_height;
343 res[x2][y2] += hill_height;
351 int highest = 0, lowest = 100000, x;
352 for(x = 0; std::size_t(x) != res.size(); ++x) {
353 for(
int y = 0; std::size_t(y) != res[x].size(); ++y) {
354 if(res[x][y] > highest) {
358 if(res[x][y] < lowest) {
364 LOG_NG <<
"generate_height_map"
365 <<
" lowest=" << lowest
366 <<
" highest =" << highest;
369 for(x = 0; std::size_t(x) != res.size(); ++x) {
370 for(
int y = 0; std::size_t(y) != res[x].size(); ++y) {
374 res[x][y] /= highest;
393 if(x < 0 || y < 0 || x >= terrain.
w || y >= terrain.
h || lake_fall_off < 0) {
397 unsigned int ulake_fall_off = lake_fall_off;
401 if((
rng_()%100) < ulake_fall_off) {
405 if((
rng_()%100) < ulake_fall_off) {
409 if((
rng_()%100) < ulake_fall_off) {
413 if((
rng_()%100) < ulake_fall_off) {
439 terrain_map& terrain,
int x,
int y, std::vector<map_location>& river,
440 std::set<map_location>& seen_locations,
int river_uphill)
442 const bool on_map = x >= 0 && y >= 0 &&
443 x < static_cast<long>(heights.size()) &&
444 y < static_cast<long>(heights.back().size());
446 if(on_map && !river.empty() && heights[x][y] >
447 heights[river.back().x][river.back().y] + river_uphill) {
456 LOG_NG <<
"generating river...";
459 for(
auto i : river) {
463 LOG_NG <<
"done generating river";
473 seen_locations.insert(current_loc);
474 river.push_back(current_loc);
476 if(seen_locations.count(loc) == 0) {
492 std::vector<map_location> river;
493 std::set<map_location> seen_locations;
508 const int side =
rng_()%4;
510 const int x =
rng_()%width;
511 const int y = side == 0 ? 0 : height-1;
514 const int y =
rng_()%height;
515 const int x = side == 2 ? 0 : width-1;
534 for(std::size_t y = begin_y; y != end_y; ++y) {
535 for(std::size_t x = begin_x; x != end_x; ++x) {
536 map[x - begin_x][y - begin_y] = terrain[x][y];
548 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)
552 std::size_t avg_distance = 0, lowest_distance = 1000;
554 for(std::vector<map_location>::const_iterator
c = other_castles.begin();
c != other_castles.end(); ++
c) {
560 if(distance < lowest_distance) {
561 lowest_distance = distance;
564 if(distance < min_distance) {
568 avg_distance += distance;
571 if(!other_castles.empty()) {
572 avg_distance /= other_castles.size();
575 for(
int i = x-1;
i <= x+1; ++
i) {
576 for(
int j = y-1; j <= y+1; ++j) {
577 if(!valid_terrain(
i,j)) {
583 const int x_from_border = std::min<int>(x - min_x,max_x - x);
584 const int y_from_border = std::min<int>(y - min_y,max_y - y);
586 const int border_ranking = min_distance - std::min<int>(x_from_border,y_from_border) + min_distance - x_from_border - y_from_border;
588 int current_ranking = border_ranking*2 + avg_distance*10 + lowest_distance*10;
589 static const int num_nearby_locations = 11*11;
591 const int max_possible_ranking = current_ranking + num_nearby_locations;
593 if(max_possible_ranking < highest_ranking) {
594 return current_ranking;
597 int surrounding_ranking = 0;
599 for(
int xpos = x-5; xpos <= x+5; ++xpos) {
600 for(
int ypos = y-5; ypos <= y+5; ++ypos) {
601 if(valid_terrain(xpos,ypos)) {
602 ++surrounding_ranking;
607 return surrounding_ranking + current_ranking;
613 const std::size_t x,
const std::size_t y,
const std::size_t radius,
const config& cfg,
617 std::set<map_location> locs;
622 if(
i.x < 0 ||
i.y < 0 ||
i.x >= map.
w ||
630 if(
auto child = cfg.
find_child(
"village",
"terrain", str)) {
633 if(l != adj_liked_cache.end()) {
634 adjacent_liked = &(l->second);
637 adjacent_liked = &(adj_liked_cache[
t]);
640 int rating = child[
"rating"];
642 if(adj.x < 0 || adj.y < 0 || adj.x >= map.
w || adj.y >= map.
h) {
647 rating += std::count(adjacent_liked->begin(),adjacent_liked->end(),t2);
650 if(rating > best_rating) {
652 best_rating = rating;
663 unsigned width,
unsigned height,
664 std::size_t label_count, std::map<map_location,std::string>* labels,
const std::string& full_name) {
670 if(
static_cast<unsigned>(adj.x) >= width / 3 ||
static_cast<unsigned>(adj.y) >= height / 3) {
676 tile_names.emplace(adj, name);
678 if(label_count % 6 == 0) {
679 labels->emplace(adj, full_name);
682 flood_name(adj, name, tile_names, tile_types, terrain, width, height, label_count++, labels, full_name);
691 LOG_NG <<
"default_generate_map parameters"
692 <<
" width=" <<
data.width
693 <<
" height=" <<
data.height
694 <<
" nplayers=" <<
data.nplayers
695 <<
" nvillages=" <<
data.nvillages
696 <<
" iterations=" <<
data.iterations
697 <<
" hill_size=" <<
data.hill_size
698 <<
" castle_size=" <<
data.castle_size
699 <<
" island_size=" <<
data.island_size
700 <<
" island_off_center=" <<
data.island_off_center
701 <<
" max_lakes=" <<
data.max_lakes
702 <<
" link_castles=" <<
data.link_castles
703 <<
" show_labels=" <<
data.show_labels;
711 int ticks = SDL_GetTicks();
728 std::map<map_location,std::string>* misc_labels = naming.
empty() ? nullptr : labels;
730 std::shared_ptr<name_generator>
731 base_name_generator, river_name_generator, lake_name_generator,
732 road_name_generator, bridge_name_generator, mountain_name_generator,
733 forest_name_generator, swamp_name_generator;
735 if(misc_labels !=
nullptr) {
736 name_generator_factory base_generator_factory{ naming, {
"male",
"base",
"bridge",
"road",
"river",
"forest",
"lake",
"mountain",
"swamp"} };
741 base_name_generator = base_generator_factory.get_name_generator( (naming.
has_attribute(
"base_names") || naming.
has_attribute(
"base_name_generator")) ?
"base" :
"male" );
742 river_name_generator = base_generator_factory.get_name_generator(
"river");
743 lake_name_generator = base_generator_factory.get_name_generator(
"lake");
744 road_name_generator = base_generator_factory.get_name_generator(
"road");
745 bridge_name_generator = base_generator_factory.get_name_generator(
"bridge");
746 mountain_name_generator = base_generator_factory.get_name_generator(
"mountain");
747 forest_name_generator = base_generator_factory.get_name_generator(
"forest");
748 swamp_name_generator = base_generator_factory.get_name_generator(
"swamp");
754 LOG_NG <<
"Done generating height map. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
755 ticks = SDL_GetTicks();
758 std::string flatland = cfg[
"default_flatland"];
759 if(flatland.empty()) {
765 std::vector<terrain_height_mapper> height_conversion;
767 height_conversion.emplace_back(
h);
771 for(std::size_t x = 0; x != heights.size(); ++x) {
772 for(std::size_t y = 0; y != heights[x].size(); ++y) {
773 for(
auto i : height_conversion) {
774 if(
i.convert_terrain(heights[x][y])) {
775 terrain[x][y] =
i.convert_to();
784 LOG_NG <<
"Placed landforms. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
785 ticks = SDL_GetTicks();
799 std::set<map_location> lake_locs;
801 std::map<map_location, std::string> river_names, lake_names, road_names, bridge_names, mountain_names, forest_names, swamp_names;
803 const std::size_t nlakes =
data.max_lakes > 0 ? (
rng_()%
data.max_lakes) : 0;
804 for(std::size_t lake = 0; lake != nlakes; ++lake) {
805 for(
int tries = 0; tries != 100; ++tries) {
809 if(heights[x][y] <= cfg[
"min_lake_height"].to_int()) {
813 std::vector<map_location> river =
generate_river(heights, terrain, x, y, cfg[
"river_frequency"]);
815 if(!river.empty() && misc_labels !=
nullptr) {
816 const std::string
base_name = base_name_generator->generate();
817 const std::string& name = river_name_generator->generate({{
"base",
base_name}});
818 LOG_NG <<
"Named river '" << name <<
"'";
820 std::size_t name_frequency = 20;
821 for(std::vector<map_location>::const_iterator r = river.begin(); r != river.end(); ++r) {
824 if(((r - river.begin())%name_frequency) == name_frequency/2) {
825 misc_labels->emplace(loc, name);
832 LOG_NG <<
"Generating lake...";
834 std::set<map_location> locs;
835 if(
generate_lake(terrain, x, y, cfg[
"lake_size"], locs) && misc_labels !=
nullptr) {
836 bool touches_other_lake =
false;
838 std::string
base_name = base_name_generator->generate();
839 const std::string& name = lake_name_generator->generate({{
"base",
base_name}});
844 if(lake_locs.count(
i) != 0) {
845 touches_other_lake =
true;
849 const std::map<map_location,std::string>::const_iterator other_name = lake_names.find(loc);
850 if(other_name != lake_names.end()) {
858 if(!touches_other_lake) {
860 misc_labels->erase(loc);
861 misc_labels->emplace(loc, name);
874 LOG_NG <<
"Generated rivers. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
875 ticks = SDL_GetTicks();
877 const std::size_t default_dimensions = 40*40*9;
888 static_cast<size_t>(cfg[
"temperature_iterations"].to_int()) *
data.width *
data.height / default_dimensions,
889 cfg[
"temperature_size"], 0, 0);
891 LOG_NG <<
"Generated temperature map. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
892 ticks = SDL_GetTicks();
894 std::vector<terrain_converter> converters;
896 converters.emplace_back(cv);
899 LOG_NG <<
"Created terrain converters. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
900 ticks = SDL_GetTicks();
903 for(
int x = 0; x !=
data.width; ++x) {
904 for(
int y = 0; y !=
data.height; ++y) {
905 for(
auto i : converters) {
906 if(
i.convert_terrain(terrain[x][y],heights[x][y],temperature_map[x][y])) {
907 terrain[x][y] =
i.convert_to();
914 LOG_NG <<
"Placing castles...";
925 std::vector<map_location> castles;
926 std::set<map_location> failed_locs;
937 for(
int player = 0; player !=
data.nplayers; ++player) {
938 LOG_NG <<
"placing castle for " << player;
940 const int min_x =
data.width/3 + 3;
941 const int min_y =
data.height/3 + 3;
942 const int max_x = (
data.width/3)*2 - 4;
943 const int max_y = (
data.height/3)*2 - 4;
944 int min_distance = castle_config[
"min_distance"];
947 int best_ranking = 0;
948 for(
int x = min_x; x != max_x; ++x) {
949 for(
int y = min_y; y != max_y; ++y) {
951 if(failed_locs.count(loc)) {
955 const int ranking =
rank_castle_location(x, y, terrain_tester, min_x, max_x, min_y, max_y, min_distance, castles, best_ranking);
957 failed_locs.insert(loc);
960 if(ranking > best_ranking) {
961 best_ranking = ranking;
967 if(best_ranking == 0) {
968 ERR_NG <<
"No castle location found, for " <<
data.nplayers <<
" players aborting. ";
969 const std::string error =
_(
"No valid castle location found. Too many or too few mountain hexes? (please check the ‘max hill size’ parameter)");
973 assert(std::find(castles.begin(), castles.end(), best_loc) == castles.end());
974 castles.push_back(best_loc);
977 failed_locs.insert(best_loc);
980 LOG_NG <<
"Placed castles. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
982 LOG_NG <<
"Placing roads...";
983 ticks = SDL_GetTicks();
988 int nroads = cfg[
"roads"];
989 if(
data.link_castles) {
990 nroads += castles.size()*castles.size();
993 std::set<map_location> bridges;
995 road_path_calculator calc(terrain, cfg,
rng_());
996 for(
int road = 0; road != nroads; ++road) {
1012 if(
data.link_castles && road <
static_cast<int>(castles.size() * castles.size())) {
1013 const std::size_t src_castle = road/castles.size();
1014 const std::size_t dst_castle = road%castles.size();
1015 if(src_castle >= dst_castle) {
1019 src = castles[src_castle];
1020 dst = castles[dst_castle];
1026 if(calc.cost(
src, 0.0) >= 1000.0 || calc.cost(
dst, 0.0) >= 1000.0) {
1033 const std::string& road_base_name = misc_labels !=
nullptr
1034 ? base_name_generator->generate()
1036 const std::string& road_name = misc_labels !=
nullptr
1037 ? road_name_generator->generate({{
"base", road_base_name}})
1039 const int name_frequency = 20;
1042 bool on_bridge =
false;
1046 for(std::vector<map_location>::const_iterator step = rt.
steps.begin();
1047 step != rt.
steps.end(); ++step) {
1049 const int x = step->x;
1050 const int y = step->y;
1052 if(x < 0 || y < 0 || x >=
static_cast<long>(
data.width) || y >=
static_cast<long>(
data.height)) {
1058 if(!child || child->empty()){
1069 const std::string& convert_to_bridge = child[
"convert_to_bridge"];
1070 if(!convert_to_bridge.empty()) {
1071 if(step == rt.
steps.begin() || step+1 == rt.
steps.end()) {
1082 if((last == adj[0] && next == adj[3]) || (last == adj[3] && next == adj[0])) {
1087 else if((last == adj[1] && next == adj[4]) || (last == adj[4] && next == adj[1])) {
1092 else if((last == adj[2] && next == adj[5]) || (last == adj[5] && next == adj[2])) {
1096 if(misc_labels !=
nullptr && !on_bridge) {
1098 std::string bridge_base_name = base_name_generator->generate();
1099 const std::string& name = bridge_name_generator->generate({{
"base", bridge_base_name}});
1101 misc_labels->emplace(loc, name);
1102 bridge_names.emplace(loc, bridge_base_name);
1103 bridges.insert(loc);
1106 if(direction != -1) {
1107 const std::vector<std::string> items =
utils::split(convert_to_bridge);
1108 if(std::size_t(direction) < items.size() && !items[direction].empty()) {
1119 const std::string& convert_to = child[
"convert_to"];
1120 if(!convert_to.empty()) {
1122 if(misc_labels !=
nullptr && terrain[x][y] != letter && name_count++ == name_frequency && !on_bridge) {
1127 terrain[x][y] = letter;
1128 if(misc_labels !=
nullptr) {
1130 if(!road_base_name.empty())
1131 road_names.emplace(loc, road_base_name);
1138 for(std::vector<map_location>::const_iterator
c = castles.begin();
c != castles.end(); ++
c) {
1145 const int player =
c - castles.begin() + 1;
1147 starting_positions.insert(t_translation::starting_positions::value_type(std::to_string(player), coord));
1150 const int castle_array[13][2] {
1151 {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {0, 1}, {-1, 1},
1152 {-2, 1}, {-2, 0}, {-2, -1}, {-1, -2}, {0, -2}, {1, -2}
1155 for(
int i = 0;
i <
data.castle_size - 1;
i++) {
1160 if(labels !=
nullptr) {
1162 for(
int i = 0;
i <
data.castle_size - 1;
i++) {
1168 LOG_NG <<
"Placed roads. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
1169 ticks = SDL_GetTicks();
1175 if(misc_labels !=
nullptr) {
1176 std::set<std::string> used_names;
1177 for(
int x =
data.width / 3; x < (
data.width / 3)*2; x++) {
1178 for(
int y =
data.height / 3; y < (
data.height / 3) * 2;y++) {
1186 if((
rng_() % 15) == 0) {
1187 for(std::size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1188 base_name = base_name_generator->generate();
1189 name = mountain_name_generator->generate({{
"base",
base_name}});
1191 misc_labels->emplace(loc, name);
1196 const std::map<map_location, std::string>::const_iterator forest_name = forest_names.find(loc);
1197 if(forest_name == forest_names.end()) {
1198 for(std::size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1199 base_name = base_name_generator->generate();
1200 name = forest_name_generator->generate({{
"base",
base_name}});
1208 const std::map<map_location, std::string>::const_iterator swamp_name = swamp_names.find(loc);
1209 if(swamp_name == swamp_names.end()) {
1210 for(std::size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1211 base_name = base_name_generator->generate();
1212 name = swamp_name_generator->generate({{
"base",
base_name}});
1220 used_names.insert(name);
1226 LOG_NG <<
"Named landforms. " << (SDL_GetTicks() - ticks) <<
" ticks elapsed";
1227 LOG_NG <<
"Placing villages...";
1228 ticks = SDL_GetTicks();
1235 std::set<map_location> villages;
1237 if(
data.nvillages > 0) {
1240 const std::size_t tiles_per_village = ((
data.width*
data.height)/9)/
data.nvillages;
1241 std::size_t village_x = 1, village_y = 1;
1246 while(village_x*village_y < tiles_per_village) {
1247 if(village_x < village_y) {
1254 std::set<std::string> used_names;
1264 std::map<map_location,std::string>* village_labels = village_naming.
empty() ? nullptr : labels;
1266 for(
int vx = 0; vx <
data.width; vx += village_x) {
1267 LOG_NG <<
"village at " << vx;
1269 for(
int vy =
rng_()%village_y; vy <
data.height; vy += village_y) {
1270 const std::size_t add =
rng_()%3;
1271 const std::size_t x = (vx + add) - 1;
1272 const std::size_t y = (vy + add) - 1;
1276 if(res.
x <
static_cast<long>(
data.width ) / 3 ||
1277 res.
x >=
static_cast<long>(
data.width * 2) / 3 ||
1278 res.
y <
static_cast<long>(
data.height ) / 3 ||
1279 res.
y >=
static_cast<long>(
data.height * 2) / 3) {
1285 const std::string& convert_to = cfg.
find_mandatory_child(
"village",
"terrain", str)[
"convert_to"].str();
1286 if(convert_to.empty()) {
1292 villages.insert(res);
1294 if(village_labels ==
nullptr) {
1299 {
"base",
"male",
"village",
"lake",
"river",
"bridge",
"grassland",
"forest",
"hill",
"mountain",
"mountain_anon",
"road",
"swamp"} };
1304 base_name_generator = village_name_generator_factory.get_name_generator(
1310 std::string name_type =
"village";
1317 std::size_t field_count = 0, forest_count = 0, mountain_count = 0, hill_count = 0;
1319 std::map<std::string,std::string> symbols;
1322 for(
n = 0;
n != 6; ++
n) {
1323 const std::map<map_location,std::string>::const_iterator road_name = road_names.find(adj[
n]);
1324 if(road_name != road_names.end()) {
1325 symbols[
"road"] = road_name->second;
1330 const std::map<map_location,std::string>::const_iterator river_name = river_names.find(adj[
n]);
1331 if(river_name != river_names.end()) {
1332 symbols[
"river"] = river_name->second;
1333 name_type =
"river";
1335 const std::map<map_location,std::string>::const_iterator bridge_name = bridge_names.find(adj[
n]);
1336 if(bridge_name != bridge_names.end()) {
1338 symbols[
"bridge"] = bridge_name->second;
1339 name_type =
"river_bridge";
1345 const std::map<map_location,std::string>::const_iterator forest_name = forest_names.find(adj[
n]);
1346 if(forest_name != forest_names.end()) {
1347 symbols[
"forest"] = forest_name->second;
1348 name_type =
"forest";
1352 const std::map<map_location,std::string>::const_iterator lake_name = lake_names.find(adj[
n]);
1353 if(lake_name != lake_names.end()) {
1354 symbols[
"lake"] = lake_name->second;
1359 const std::map<map_location,std::string>::const_iterator mountain_name = mountain_names.find(adj[
n]);
1360 if(mountain_name != mountain_names.end()) {
1361 symbols[
"mountain"] = mountain_name->second;
1362 name_type =
"mountain";
1366 const std::map<map_location,std::string>::const_iterator swamp_name = swamp_names.find(adj[
n]);
1367 if(swamp_name != swamp_names.end()) {
1368 symbols[
"swamp"] = swamp_name->second;
1369 name_type =
"swamp";
1375 if(std::count(field.begin(),field.end(),terr) > 0) {
1377 }
else if(std::count(forest.begin(),forest.end(),terr) > 0) {
1379 }
else if(std::count(hill.begin(),hill.end(),terr) > 0) {
1381 }
else if(std::count(mountain.begin(),mountain.end(),terr) > 0) {
1387 if(field_count == 6) {
1388 name_type =
"grassland";
1389 }
else if(forest_count >= 2) {
1390 name_type =
"forest";
1391 }
else if(mountain_count >= 1) {
1392 name_type =
"mountain_anon";
1393 }
else if(hill_count >= 2) {
1400 symbols[
"base"] = base_name_generator->generate();
1401 std::shared_ptr<name_generator> village_name_generator = village_name_generator_factory.get_name_generator(name_type);
1403 for(std::size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1404 name = village_name_generator->generate(symbols);
1407 used_names.insert(name);
1408 village_labels->emplace(loc, name);
1413 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)
Equivalent 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.
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...
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
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.