The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
default_map_generator_job.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Map-generator, with standalone testprogram.
18  */
19 
20 #include "global.hpp"
21 
22 #include "gettext.hpp"
23 #include "language.hpp"
24 #include "log.hpp"
25 #include "map/map.hpp"
26 #include "map_generator.hpp"// mapgen_esxeption
28 #include "pathfind/pathfind.hpp"
29 #include "pathutils.hpp"
30 #include "util.hpp"
31 #include "wml_exception.hpp"
32 #include "formula/string_utils.hpp"
35 #include <SDL.h>
36 
37 #include "seed_rng.hpp"
38 static lg::log_domain log_mapgen("mapgen");
39 #define ERR_NG LOG_STREAM(err, log_mapgen)
40 #define LOG_NG LOG_STREAM(info, log_mapgen)
41 
43  : rng_(seed_rng::next_seed())
44 {
45 
46 }
47 
49  : rng_(seed)
50 {
51 
52 }
53 
54 
55 typedef std::vector<std::vector<int> > height_map;
58 
59 /**
60  * Generate a height-map.
61  *
62  * Basically we generate a lot of hills, each hill being centered at a certain
63  * point, with a certain radius - being a half sphere. Hills are combined
64  * additively to form a bumpy surface. The size of each hill varies randomly
65  * from 1-hill_size. We generate 'iterations' hills in total. The range of
66  * heights is normalized to 0-1000. 'island_size' controls whether or not the
67  * map should tend toward an island shape, and if so, how large the island
68  * should be. Hills with centers that are more than 'island_size' away from
69  * the center of the map will be inverted (i.e. be valleys). 'island_size' as
70  * 0 indicates no island.
71  */
73  size_t iterations, size_t hill_size,
74  size_t island_size, size_t island_off_center)
75 {
76  height_map res(width, std::vector<int>(height,0));
77 
78  size_t center_x = width/2;
79  size_t center_y = height/2;
80 
81  LOG_NG << "off-centering...\n";
82 
83  if(island_off_center != 0) {
84  switch(rng_()%4) {
85  case 0:
86  center_x += island_off_center;
87  break;
88  case 1:
89  center_y += island_off_center;
90  break;
91  case 2:
92  if(center_x < island_off_center)
93  center_x = 0;
94  else
95  center_x -= island_off_center;
96  break;
97  case 3:
98  if(center_y < island_off_center)
99  center_y = 0;
100  else
101  center_y -= island_off_center;
102  break;
103  }
104  }
105 
106  for(size_t i = 0; i != iterations; ++i) {
107 
108  // (x1,y1) is the location of the hill,
109  // and 'radius' is the radius of the hill.
110  // We iterate over all points, (x2,y2).
111  // The formula for the amount the height is increased by is:
112  // radius - sqrt((x2-x1)^2 + (y2-y1)^2) with negative values ignored.
113  //
114  // Rather than iterate over every single point, we can reduce the points
115  // to a rectangle that contains all the positive values for this formula --
116  // the rectangle is given by min_x,max_x,min_y,max_y.
117 
118  // Is this a negative hill? (i.e. a valley)
119  bool is_valley = false;
120 
121  int x1 = island_size > 0 ? center_x - island_size + (rng_()%(island_size*2)) :
122  int(rng_()%width);
123  int y1 = island_size > 0 ? center_y - island_size + (rng_()%(island_size*2)) :
124  int(rng_()%height);
125 
126  // We have to check whether this is actually a valley
127  if(island_size != 0) {
128  const size_t diffx = abs(x1 - int(center_x));
129  const size_t diffy = abs(y1 - int(center_y));
130  const size_t dist = size_t(std::sqrt(double(diffx*diffx + diffy*diffy)));
131  is_valley = dist > island_size;
132  }
133 
134  const int radius = rng_()%hill_size + 1;
135 
136  const int min_x = x1 - radius > 0 ? x1 - radius : 0;
137  const int max_x = x1 + radius < static_cast<long>(res.size()) ? x1 + radius : res.size();
138  const int min_y = y1 - radius > 0 ? y1 - radius : 0;
139  const int max_y = y1 + radius < static_cast<long>(res.front().size()) ? y1 + radius : res.front().size();
140 
141  for(int x2 = min_x; x2 < max_x; ++x2) {
142  for(int y2 = min_y; y2 < max_y; ++y2) {
143  const int xdiff = (x2-x1);
144  const int ydiff = (y2-y1);
145 
146  const int height = radius - int(std::sqrt(double(xdiff*xdiff + ydiff*ydiff)));
147 
148  if(height > 0) {
149  if(is_valley) {
150  if(height > res[x2][y2]) {
151  res[x2][y2] = 0;
152  } else {
153  res[x2][y2] -= height;
154  }
155  } else {
156  res[x2][y2] += height;
157  }
158  }
159  }
160  }
161  }
162 
163  // Find the highest and lowest points on the map for normalization:
164  int heighest = 0, lowest = 100000, x;
165  for(x = 0; size_t(x) != res.size(); ++x) {
166  for(int y = 0; size_t(y) != res[x].size(); ++y) {
167  if(res[x][y] > heighest)
168  heighest = res[x][y];
169 
170  if(res[x][y] < lowest)
171  lowest = res[x][y];
172  }
173  }
174 
175  // Normalize the heights to the range 0-1000:
176  heighest -= lowest;
177  for(x = 0; size_t(x) != res.size(); ++x) {
178  for(int y = 0; size_t(y) != res[x].size(); ++y) {
179  res[x][y] -= lowest;
180  res[x][y] *= 1000;
181  if(heighest != 0)
182  res[x][y] /= heighest;
183  }
184  }
185 
186  return res;
187 }
188 
189 /**
190  * Generate a lake.
191  *
192  * It will create water at (x,y), and then have 'lake_fall_off' % chance to
193  * make another water tile in each of the directions n,s,e,w. In each of the
194  * directions it does make another water tile, it will have 'lake_fall_off'/2 %
195  * chance to make another water tile in each of the directions. This will
196  * continue recursively.
197  */
198 bool default_map_generator_job::generate_lake(terrain_map& terrain, int x, int y, int lake_fall_off, std::set<location>& locs_touched)
199 {
200  if(x < 0 || y < 0 || size_t(x) >= terrain.size() || size_t(y) >= terrain.front().size() || lake_fall_off < 0) {
201  return false;
202  }
203  //we checked for this eariler.
204  unsigned int ulake_fall_off = lake_fall_off;
205  terrain[x][y] = t_translation::SHALLOW_WATER;
206  locs_touched.insert(location(x,y));
207 
208  if((rng_()%100) < ulake_fall_off) {
209  generate_lake(terrain,x+1,y,lake_fall_off/2,locs_touched);
210  }
211 
212  if((rng_()%100) < ulake_fall_off) {
213  generate_lake(terrain,x-1,y,lake_fall_off/2,locs_touched);
214  }
215 
216  if((rng_()%100) < ulake_fall_off) {
217  generate_lake(terrain,x,y+1,lake_fall_off/2,locs_touched);
218  }
219 
220  if((rng_()%100) < ulake_fall_off) {
221  generate_lake(terrain,x,y-1,lake_fall_off/2,locs_touched);
222  }
223 
224  return true;
225 }
226 
227 /**
228  * River generation.
229  *
230  * Rivers have a source, and then keep on flowing until they meet another body
231  * of water, which they flow into, or until they reach the edge of the map.
232  * Rivers will always flow downhill, except that they can flow a maximum of
233  * 'river_uphill' uphill. This is to represent the water eroding the higher
234  * ground lower.
235  *
236  * Every possible path for a river will be attempted, in random order, and the
237  * first river path that can be found that makes the river flow into another
238  * body of water or off the map will be used.
239  *
240  * If no path can be found, then the river's generation will be aborted, and
241  * false will be returned. true is returned if the river is generated
242  * successfully.
243  */
244 
245 namespace
246 {
247  struct for_randomshuffle
248  {
249  for_randomshuffle(boost::random::mt19937& rng) : rng_(rng) {}
250  boost::random::mt19937& rng_;
251  uint32_t operator ()(uint32_t end) { return rng_() % end; }
252  };
253 }
255  terrain_map& terrain, int x, int y, std::vector<location>& river,
256  std::set<location>& seen_locations, int river_uphill)
257 {
258  const bool on_map = x >= 0 && y >= 0 &&
259  x < static_cast<long>(heights.size()) &&
260  y < static_cast<long>(heights.back().size());
261 
262  if(on_map && !river.empty() && heights[x][y] >
263  heights[river.back().x][river.back().y] + river_uphill) {
264 
265  return false;
266  }
267 
268  // If we're at the end of the river
269  if(!on_map || terrain[x][y] == t_translation::SHALLOW_WATER ||
270  terrain[x][y] == t_translation::DEEP_WATER) {
271 
272  LOG_NG << "generating river...\n";
273 
274  // Generate the river
275  for(std::vector<location>::const_iterator i = river.begin();
276  i != river.end(); ++i) {
277  terrain[i->x][i->y] = t_translation::SHALLOW_WATER;
278  }
279 
280  LOG_NG << "done generating river\n";
281 
282  return true;
283  }
284 
285  location current_loc(x,y);
286  location adj[6];
287  get_adjacent_tiles(current_loc,adj);
288  int items[6] = {0,1,2,3,4,5};
289  for_randomshuffle shufflehelper(rng_);
290  std::random_shuffle(items, items + 4, shufflehelper);
291 
292  // Mark that we have attempted from this location
293  seen_locations.insert(current_loc);
294  river.push_back(current_loc);
295  for(int a = 0; a != 6; ++a) {
296  const location& loc = adj[items[a]];
297  if(seen_locations.count(loc) == 0) {
298  const bool res = generate_river_internal(heights,terrain,loc.x,loc.y,river,seen_locations,river_uphill);
299  if(res) {
300  return true;
301  }
302 
303  }
304  }
305 
306  river.pop_back();
307 
308  return false;
309 }
310 
311 std::vector<location> default_map_generator_job::generate_river(const height_map& heights, terrain_map& terrain, int x, int y, int river_uphill)
312 {
313  std::vector<location> river;
314  std::set<location> seen_locations;
315  const bool res = generate_river_internal(heights,terrain,x,y,river,seen_locations,river_uphill);
316  if(!res) {
317  river.clear();
318  }
319 
320  return river;
321 }
322 
323 /**
324  * Returns a random tile at one of the borders of a map that is of the given
325  * dimensions.
326  */
328 {
329  const int side = rng_()%4;
330  if(side < 2) {
331  const int x = rng_()%width;
332  const int y = side == 0 ? 0 : height-1;
333  return location(x,y);
334  } else {
335  const int y = rng_()%height;
336  const int x = side == 2 ? 0 : width-1;
337  return location(x,y);
338  }
339 }
340 
341 /** Function which, given the map will output it in a valid format. */
343  t_translation::tstarting_positions& starting_positions)
344 {
345  // Remember that we only want the middle 1/9th of the map.
346  // All other segments of the map are there only to give
347  // the important middle part some context.
348  // We also have a border so also adjust for that.
349  const size_t begin_x = terrain.size() / 3 - gamemap::default_border ;
350  const size_t end_x = terrain.size() * 2 / 3 + gamemap::default_border;
351  const size_t begin_y = terrain.front().size() / 3 - gamemap::default_border;
352  const size_t end_y = terrain.front().size() * 2 / 3 + gamemap::default_border;
353 
354  terrain_map map;
355  map.resize(end_x - begin_x);
356  for(size_t y = begin_y; y != end_y; ++y) {
357  for(size_t x = begin_x; x != end_x; ++x) {
358  if((y - begin_y) == 0){
359  map[x - begin_x].resize(end_y - begin_y);
360  }
361  map[x - begin_x][y - begin_y] = terrain[x][y];
362  }
363  }
364 
365  // Since the map has been resized,
366  // the starting locations also need to be fixed
367  for (auto it = starting_positions.left.begin(); it != starting_positions.left.end(); ++it) {
368  starting_positions.left.modify_data(it, [=](t_translation::coordinate& pos) { pos.x -= begin_x; pos.y -= begin_y; });
369  }
370  return t_translation::write_game_map(map, starting_positions);
371 }
372 
373 namespace {
374 
375 /**
376  * Calculates the cost of building a road over terrain. For use in the
377  * a_star_search algorithm.
378  */
379 struct road_path_calculator : pathfind::cost_calculator
380 {
381  road_path_calculator(const terrain_map& terrain, const config& cfg, int seed) :
382  calls(0),
383  map_(terrain),
384  cfg_(cfg),
385  // Find out how windy roads should be.
386  windiness_(std::max<int>(1, cfg["road_windiness"].to_int())),
387  seed_(seed),
388  cache_()
389  {
390  }
391 
392  virtual double cost(const location& loc, const double so_far) const;
393 
394  mutable int calls;
395 private:
396  const terrain_map& map_;
397  const config& cfg_;
398  int windiness_;
399  int seed_;
400  mutable std::map<t_translation::t_terrain, double> cache_;
401 };
402 
403 double road_path_calculator::cost(const location& loc,
404  const double /*so_far*/) const
405 {
406  ++calls;
407  if (loc.x < 0 || loc.y < 0 || loc.x >= static_cast<long>(map_.size()) ||
408  loc.y >= static_cast<long>(map_.front().size())) {
409 
411  }
412 
413  // We multiply the cost by a random amount,
414  // depending upon how 'windy' the road should be.
415  // If windiness is 1, that will mean that the cost is always genuine,
416  // and so the road always takes the shortest path.
417  // If windiness is greater than 1, we sometimes over-report costs
418  // for some segments, to make the road wind a little.
419 
420  double windiness = 1.0;
421 
422  if (windiness_ > 1) {
423  // modified pseudo_random taken from builder.cpp
424  unsigned int a = (loc.x + 92872973) ^ 918273;
425  unsigned int b = (loc.y + 1672517) ^ 128123;
426  unsigned int c = a*b + a + b + seed_;
427  unsigned int random = c*c;
428  // this is just "big random number modulo windiness_"
429  // but avoid the "modulo by a low number (like 2)"
430  // because it can increase arithmetic patterns
431  int noise = random % (windiness_ * 137) / 137;
432  windiness += noise;
433  }
434 
435  const t_translation::t_terrain c = map_[loc.x][loc.y];
436  const std::map<t_translation::t_terrain, double>::const_iterator itor = cache_.find(c);
437  if(itor != cache_.end()) {
438  return itor->second*windiness;
439  }
440 
441  static std::string terrain;
443  double res = getNoPathValue();
444  if (const config &child = cfg_.find_child("road_cost", "terrain", terrain)) {
445  res = child["cost"].to_double();
446  }
447 
448  cache_.insert(std::pair<t_translation::t_terrain, double>(c,res));
449  return windiness*res;
450 }
451 
452 struct is_valid_terrain
453 {
455  const t_translation::t_list& terrain_list);
456  bool operator()(int x, int y) const;
457 private:
459  const t_translation::t_list& terrain_;
460 };
461 
463  const t_translation::t_list& terrain_list)
464 : map_(map), terrain_(terrain_list)
465 {}
466 
467 bool is_valid_terrain::operator()(int x, int y) const
468 {
469  if(x < 0 || x >= static_cast<long>(map_.size()) ||
470  y < 0 || y >= static_cast<long>(map_[x].size())) {
471 
472  return false;
473  }
474 
475  return std::find(terrain_.begin(),terrain_.end(),map_[x][y]) != terrain_.end();
476 }
477 
478 }
479 
480 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,
481  size_t min_distance, const std::vector<map_location>& other_castles, int highest_ranking)
482 {
483  const map_location loc(x,y);
484 
485  size_t avg_distance = 0, lowest_distance = 1000;
486 
487  for(std::vector<map_location>::const_iterator c = other_castles.begin(); c != other_castles.end(); ++c) {
488  const size_t distance = distance_between(loc,*c);
489  if(distance < 6) {
490  return 0;
491  }
492 
493  if(distance < lowest_distance) {
494  lowest_distance = distance;
495  }
496 
497  if(distance < min_distance) {
498  avg_distance = 0;
499  return -1;
500  }
501 
502  avg_distance += distance;
503  }
504 
505  if(other_castles.empty() == false) {
506  avg_distance /= other_castles.size();
507  }
508 
509  for(int i = x-1; i <= x+1; ++i) {
510  for(int j = y-1; j <= y+1; ++j) {
511  if(!valid_terrain(i,j)) {
512  return 0;
513  }
514  }
515  }
516 
517  const int x_from_border = std::min<int>(x - min_x,max_x - x);
518  const int y_from_border = std::min<int>(y - min_y,max_y - y);
519 
520  const int border_ranking = min_distance - std::min<int>(x_from_border,y_from_border) +
521  min_distance - x_from_border - y_from_border;
522 
523  int current_ranking = border_ranking*2 + avg_distance*10 + lowest_distance*10;
524  static const int num_nearby_locations = 11*11;
525 
526  const int max_possible_ranking = current_ranking + num_nearby_locations;
527 
528  if(max_possible_ranking < highest_ranking) {
529  return current_ranking;
530  }
531 
532  int surrounding_ranking = 0;
533 
534  for(int xpos = x-5; xpos <= x+5; ++xpos) {
535  for(int ypos = y-5; ypos <= y+5; ++ypos) {
536  if(valid_terrain(xpos,ypos)) {
537  ++surrounding_ranking;
538  }
539  }
540  }
541 
542  return surrounding_ranking + current_ranking;
543 }
544 
545 typedef std::map<t_translation::t_terrain, t_translation::t_list> tcode_list_cache;
546 
548  const size_t x, const size_t y, const size_t radius, const config& cfg,
549  tcode_list_cache &adj_liked_cache)
550 {
551  const map_location loc(x,y);
552  std::set<map_location> locs;
553  get_tiles_radius(loc,radius,locs);
554  map_location best_loc;
555  int best_rating = 0;
556  for(std::set<map_location>::const_iterator i = locs.begin();
557  i != locs.end(); ++i) {
558 
559  if(i->x < 0 || i->y < 0 || i->x >= static_cast<long>(map.size()) ||
560  i->y >= static_cast<long>(map[i->x].size())) {
561 
562  continue;
563  }
564 
565  const t_translation::t_terrain t = map[i->x][i->y];
567  if (const config &child = cfg.find_child("village", "terrain", str)) {
568  tcode_list_cache::iterator l = adj_liked_cache.find(t);
569  t_translation::t_list *adjacent_liked;
570  if (l != adj_liked_cache.end()) {
571  adjacent_liked = &(l->second);
572  } else {
573  adj_liked_cache[t] = t_translation::read_list(child["adjacent_liked"]);
574  adjacent_liked = &(adj_liked_cache[t]);
575  }
576 
577  int rating = child["rating"];
578  map_location adj[6];
579  get_adjacent_tiles(map_location(i->x,i->y),adj);
580  for(size_t n = 0; n != 6; ++n) {
581  if(adj[n].x < 0 || adj[n].y < 0 ||
582  adj[n].x >= static_cast<long>(map.size()) ||
583  adj[n].y >= static_cast<long>(map[adj[n].x].size())) {
584 
585  continue;
586  }
587 
588  const t_translation::t_terrain t2 = map[adj[n].x][adj[n].y];
589  rating += std::count(adjacent_liked->begin(),adjacent_liked->end(),t2);
590  }
591 
592  if(rating > best_rating) {
593  best_loc = map_location(i->x,i->y);
594  best_rating = rating;
595  }
596  }
597  }
598 
599  return best_loc;
600 }
601 
603  std::string* base_name, utils::string_map* additional_symbols)
604 {
605  const std::vector<std::string>& options = utils::split(string_table[id].str());
606  if(!options.empty() && name_generator != nullptr) {
607  const size_t choice = rng_()%options.size();
608  LOG_NG << "calling name generator...\n";
609  const std::string& name = name_generator->generate();
610  LOG_NG << "name generator returned '" << name << "'\n";
611  if(base_name != nullptr) {
612  *base_name = name;
613  }
614 
615  LOG_NG << "assigned base name..\n";
617  if(additional_symbols == nullptr) {
618  additional_symbols = &table;
619  }
620 
621  LOG_NG << "got additional symbols\n";
622 
623  (*additional_symbols)["name"] = name;
624  LOG_NG << "interpolation variables into '" << options[choice] << "'\n";
625  return utils::interpolate_variables_into_string(options[choice], additional_symbols);
626  }
627 
628  return "";
629 }
630 
631 // "flood fill" a tile name to adjacent tiles of certain terrain
632 static void flood_name(const map_location& start, const std::string& name, std::map<map_location,std::string>& tile_names,
633  const t_translation::t_match& tile_types, const terrain_map& terrain,
634  unsigned width, unsigned height,
635  size_t label_count, std::map<map_location,std::string>* labels, const std::string& full_name) {
636  map_location adj[6];
637  get_adjacent_tiles(start,adj);
638  size_t n;
639  //if adjacent tiles are tiles and unnamed, name them
640  for (n = 0; n < 6; n++) {
641  //we do not care for tiles outside the middle part
642  //cast to unsigned to skip x < 0 || y < 0 as well.
643  if (unsigned(adj[n].x) >= width / 3 || unsigned(adj[n].y) >= height / 3) {
644  continue;
645  }
646 
647  const t_translation::t_terrain terr = terrain[adj[n].x + (width / 3)][adj[n].y + (height / 3)];
648  const location loc(adj[n].x, adj[n].y);
649  if((t_translation::terrain_matches(terr, tile_types)) && (tile_names.find(loc) == tile_names.end())) {
650  tile_names.insert(std::pair<location, std::string>(loc, name));
651  //labeling decision: this is result of trial and error on what looks best in game
652  if (label_count % 6 == 0) { //ensure that labels do not occur more often than every 6 recursions
653  labels->insert(std::pair<map_location, std::string>(loc, full_name));
654  label_count++; //ensure that no adjacent tiles get labeled
655  }
656  flood_name(adj[n], name, tile_names, tile_types, terrain, width, height, label_count++, labels, full_name);
657  }
658  }
659 }
660 
661 namespace {
662 
663 // the configuration file should contain a number of [height] tags:
664 // [height]
665 // height=n
666 // terrain=x
667 // [/height]
668 // These should be in descending order of n.
669 // They are checked sequentially, and if height is greater than n for that tile,
670 // then the tile is set to terrain type x.
671 class terrain_height_mapper
672 {
673 public:
674  explicit terrain_height_mapper(const config& cfg);
675 
676  bool convert_terrain(const int height) const;
677  t_translation::t_terrain convert_to() const;
678 
679 private:
680  int terrain_height;
682 };
683 
684 terrain_height_mapper::terrain_height_mapper(const config& cfg) :
685  terrain_height(cfg["height"]),
687 {
688  const std::string& terrain = cfg["terrain"];
689  if(terrain != "") {
690  to = t_translation::read_terrain_code(terrain);
691  }
692 }
693 
694 bool terrain_height_mapper::convert_terrain(const int height) const
695 {
696  return height >= terrain_height;
697 }
698 
699 t_translation::t_terrain terrain_height_mapper::convert_to() const
700 {
701  return to;
702 }
703 
704 class terrain_converter
705 {
706 public:
707  explicit terrain_converter(const config& cfg);
708 
709  bool convert_terrain(const t_translation::t_terrain & terrain, const int height, const int temperature) const;
710  t_translation::t_terrain convert_to() const;
711 
712 private:
713  int min_temp, max_temp, min_height, max_height;
716 };
717 
718 terrain_converter::terrain_converter(const config& cfg)
719  : min_temp(cfg["min_temperature"].to_int(-100000))
720  , max_temp(cfg["max_temperature"].to_int(100000))
721  , min_height(cfg["min_height"].to_int(-100000))
722  , max_height(cfg["max_height"].to_int(100000))
723  , from(t_translation::read_list(cfg["from"]))
725 {
726  const std::string& to_str = cfg["to"];
727  if(to_str != "") {
729  }
730 }
731 
732 bool terrain_converter::convert_terrain(const t_translation::t_terrain & terrain,
733  const int height, const int temperature) const
734 {
735  return std::find(from.begin(),from.end(),terrain) != from.end() && height >= min_height && height <= max_height &&
736  temperature >= min_temp && temperature <= max_temp && to != t_translation::NONE_TERRAIN;
737 }
738 
739 t_translation::t_terrain terrain_converter::convert_to() const
740 {
741  return to;
742 }
743 
744 } // end anon namespace
745 
746 std::string default_map_generator_job::default_generate_map(size_t width, size_t height, size_t island_size, size_t island_off_center,
747  size_t iterations, size_t hill_size,
748  size_t max_lakes, size_t nvillages, size_t castle_size, size_t nplayers, bool roads_between_castles,
749  std::map<map_location,std::string>* labels, const config& cfg)
750 {
751  log_scope("map generation");
752 
753  // Odd widths are nasty
754  VALIDATE(is_even(width), _("Random maps with an odd width aren't supported."));
755 
756  int ticks = SDL_GetTicks();
757 
758  // Find out what the 'flatland' on this map is, i.e. grassland.
759  std::string flatland = cfg["default_flatland"];
760  if(flatland == "") {
762  }
763 
765 
766  // We want to generate a map that is 9 times bigger
767  // than the actual size desired.
768  // Only the middle part of the map will be used,
769  // but the rest is so that the map we end up using
770  // can have a context (e.g. rivers flowing from
771  // out of the map into the map, same for roads, etc.)
772  width *= 3;
773  height *= 3;
774 
775  LOG_NG << "generating height map...\n";
776  // Generate the height of everything.
777  const height_map heights = generate_height_map(width,height,iterations,hill_size,island_size,island_off_center);
778  LOG_NG << "done generating height map...\n";
779  LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();
780 
781  config naming = cfg.child_or_empty("naming");
782  // If the [naming] child is empty, we cannot provide good names.
783  std::map<map_location,std::string>* misc_labels = naming.empty() ? nullptr : labels;
784 
786  if(naming.has_attribute("name_generator")) {
787  name_generator.reset(new context_free_grammar_generator(naming["name_generator"]));
788  if(!name_generator->is_valid()) {
789  name_generator.reset();
790  }
791  }
792  config::attribute_value markov_list = naming.get_old_attribute("names", "male_names",
793  "[naming]male_names is deprecated, use names instead");
794  if(!markov_list.blank()) {
795  name_generator.reset(new markov_generator(utils::split(markov_list), naming["markov_chain_size"], 12));
796  }
797 
798  std::vector<terrain_height_mapper> height_conversion;
799 
800  for(const config &h : cfg.child_range("height")) {
801  height_conversion.push_back(terrain_height_mapper(h));
802  }
803 
804  terrain_map terrain(width, t_translation::t_list(height, grassland));
805  size_t x, y;
806  for(x = 0; x != heights.size(); ++x) {
807  for(y = 0; y != heights[x].size(); ++y) {
808  for(std::vector<terrain_height_mapper>::const_iterator i = height_conversion.begin();
809  i != height_conversion.end(); ++i) {
810  if(i->convert_terrain(heights[x][y])) {
811  terrain[x][y] = i->convert_to();
812  break;
813  }
814  }
815  }
816  }
817 
818  t_translation::tstarting_positions starting_positions;
819  LOG_NG << output_map(terrain, starting_positions);
820  LOG_NG << "placed land forms\n";
821  LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();
822 
823  // Now that we have our basic set of flatland/hills/mountains/water,
824  // we can place lakes and rivers on the map.
825  // All rivers are sourced at a lake.
826  // Lakes must be in high land - at least 'min_lake_height'.
827  // (Note that terrain below a certain altitude may be made
828  // into bodies of water in the code above - i.e. 'sea',
829  // but these are not considered 'lakes', because
830  // they are not sources of rivers).
831  //
832  // We attempt to place 'max_lakes' lakes.
833  // Each lake will be placed at a random location,
834  // if that random location meets the minimum terrain requirements for a lake.
835  // We will also attempt to source a river from each lake.
836  std::set<location> lake_locs;
837 
838  std::map<location, std::string> river_names, lake_names, road_names, bridge_names, mountain_names, forest_names, swamp_names;
839 
840  const size_t nlakes = max_lakes > 0 ? (rng_()%max_lakes) : 0;
841  for(size_t lake = 0; lake != nlakes; ++lake) {
842  for(int tries = 0; tries != 100; ++tries) {
843  const int x = rng_()%width;
844  const int y = rng_()%height;
845  if (heights[x][y] > cfg["min_lake_height"].to_int()) {
846  std::vector<location> river = generate_river(heights,
847  terrain, x, y, cfg["river_frequency"]);
848 
849  if(river.empty() == false && misc_labels != nullptr) {
851  LOG_NG << "generating name for river...\n";
852  const std::string& name = generate_name(name_generator,"river_name",&base_name);
853  LOG_NG << "named river '" << name << "'\n";
854  size_t name_frequency = 20;
855  for(std::vector<location>::const_iterator r = river.begin(); r != river.end(); ++r) {
856 
857  const map_location loc(r->x-width/3,r->y-height/3);
858 
859  if(((r - river.begin())%name_frequency) == name_frequency/2) {
860  misc_labels->insert(std::pair<map_location,std::string>(loc,name));
861  }
862 
863  river_names.insert(std::pair<location,std::string>(loc,base_name));
864  }
865 
866  LOG_NG << "put down river name...\n";
867  }
868 
869  LOG_NG << "generating lake...\n";
870  std::set<location> locs;
871  bool res = generate_lake(terrain, x, y, cfg["lake_size"], locs);
872  if(res && misc_labels != nullptr) {
873  bool touches_other_lake = false;
874 
876  const std::string& name = generate_name(name_generator,"lake_name",&base_name);
877 
878  std::set<location>::const_iterator i;
879 
880  // Only generate a name if the lake hasn't touched any other lakes,
881  // so that we don't end up with one big lake with multiple names.
882  for(i = locs.begin(); i != locs.end(); ++i) {
883  if(lake_locs.count(*i) != 0) {
884  touches_other_lake = true;
885 
886  // Reassign the name of this lake to be the same as the other lake
887  const location loc(i->x-width/3,i->y-height/3);
888  const std::map<location,std::string>::const_iterator other_name = lake_names.find(loc);
889  if(other_name != lake_names.end()) {
890  base_name = other_name->second;
891  }
892  }
893 
894  lake_locs.insert(*i);
895  }
896 
897  if(!touches_other_lake) {
898  const map_location loc(x-width/3,y-height/3);
899  misc_labels->erase(loc);
900  misc_labels->insert(std::pair<map_location,std::string>(loc,name));
901  }
902 
903  for(i = locs.begin(); i != locs.end(); ++i) {
904  const location loc(i->x-width/3,i->y-height/3);
905  lake_names.insert(std::pair<location, std::string>(loc, base_name));
906  }
907  }
908 
909  break;
910  }
911  }
912  }
913 
914  LOG_NG << "done generating rivers...\n";
915  LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();
916 
917  const size_t default_dimensions = 40*40*9;
918 
919  /*
920  * Convert grassland terrain to other types of flat terrain.
921  *
922  * We generate a 'temperature map' which uses the height generation
923  * algorithm to generate the temperature levels all over the map. Then we
924  * can use a combination of height and terrain to divide terrain up into
925  * more interesting types than the default.
926  */
927  const height_map temperature_map = generate_height_map(width,height,
928  cfg["temperature_iterations"].to_int() * width * height / default_dimensions,
929  cfg["temperature_size"], 0, 0);
930 
931  LOG_NG << "generated temperature map...\n";
932  LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();
933 
934  std::vector<terrain_converter> converters;
935  for(const config &cv : cfg.child_range("convert")) {
936  converters.push_back(terrain_converter(cv));
937  }
938 
939  LOG_NG << "created terrain converters\n";
940  LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();
941 
942 
943  // Iterate over every flatland tile, and determine
944  // what type of flatland it is, based on our [convert] tags.
945  for(x = 0; x != width; ++x) {
946  for(y = 0; y != height; ++y) {
947  for(std::vector<terrain_converter>::const_iterator i = converters.begin(); i != converters.end(); ++i) {
948  if(i->convert_terrain(terrain[x][y],heights[x][y],temperature_map[x][y])) {
949  terrain[x][y] = i->convert_to();
950  break;
951  }
952  }
953  }
954  }
955 
956  LOG_NG << "placing villages...\n";
957  LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();
958 
959  /*
960  * Place villages in a 'grid', to make placing fair, but with villages
961  * displaced from their position according to terrain and randomness, to
962  * add some variety.
963  */
964  std::set<location> villages;
965 
966  LOG_NG << "placing castles...\n";
967 
968  /** Try to find configuration for castles. */
969  const config &castle_config = cfg.child("castle");
970  if (!castle_config) {
971  LOG_NG << "Could not find castle configuration\n";
972  return std::string();
973  }
974 
975  /*
976  * Castle configuration tag contains a 'valid_terrain' attribute which is a
977  * list of terrains that the castle may appear on.
978  */
979  const t_translation::t_list list =
980  t_translation::read_list(castle_config["valid_terrain"]);
981 
982  const is_valid_terrain terrain_tester(terrain, list);
983 
984  /*
985  * Attempt to place castles at random.
986  *
987  * Once we have placed castles, we run a sanity check to make sure that the
988  * castles are well-placed. If the castles are not well-placed, we try
989  * again. Definition of 'well-placed' is if no two castles are closer than
990  * 'min_distance' hexes from each other, and the castles appear on a
991  * terrain listed in 'valid_terrain'.
992  */
993  std::vector<location> castles;
994  std::set<location> failed_locs;
995 
996  for(size_t player = 0; player != nplayers; ++player) {
997  LOG_NG << "placing castle for " << player << "\n";
998  log_scope("placing castle");
999  const int min_x = width/3 + 3;
1000  const int min_y = height/3 + 3;
1001  const int max_x = (width/3)*2 - 4;
1002  const int max_y = (height/3)*2 - 4;
1003  int min_distance = castle_config["min_distance"];
1004 
1005  location best_loc;
1006  int best_ranking = 0;
1007  for(int x = min_x; x != max_x; ++x) {
1008  for(int y = min_y; y != max_y; ++y) {
1009  const location loc(x,y);
1010  if(failed_locs.count(loc)) {
1011  continue;
1012  }
1013 
1014  const int ranking = rank_castle_location(x,y,terrain_tester,min_x,max_x,min_y,max_y,min_distance,castles,best_ranking);
1015  if(ranking <= 0) {
1016  failed_locs.insert(loc);
1017  }
1018 
1019  if(ranking > best_ranking) {
1020  best_ranking = ranking;
1021  best_loc = loc;
1022  }
1023  }
1024  }
1025  if(best_ranking == 0) {
1026  ERR_NG << "No castle location found, aborting." << std::endl;
1027  std::string error = _("No valid castle location found. Too many or too few mountain hexes? (please check the 'max hill size' parameter)");
1028  throw mapgen_exception(error);
1029  }
1030  assert(std::find(castles.begin(), castles.end(), best_loc) == castles.end());
1031  castles.push_back(best_loc);
1032  // Make sure the location can't get a second castle.
1033  failed_locs.insert(best_loc);
1034  }
1035 
1036  LOG_NG << "placing roads...\n";
1037  LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();
1038 
1039  // Place roads.
1040  // We select two tiles at random locations on the borders
1041  // of the map, and try to build roads between them.
1042  int nroads = cfg["roads"];
1043  if(roads_between_castles) {
1044  nroads += castles.size()*castles.size();
1045  }
1046 
1047  std::set<location> bridges;
1048 
1049  road_path_calculator calc(terrain, cfg, rng_());
1050  for (int road = 0; road != nroads; ++road) {
1051  log_scope("creating road");
1052 
1053  /*
1054  * We want the locations to be on the portion of the map we're actually
1055  * going to use, since roads on other parts of the map won't have any
1056  * influence, and doing it like this will be quicker.
1057  */
1058  location src = random_point_at_side(width/3 + 2,height/3 + 2);
1059  location dst = random_point_at_side(width/3 + 2,height/3 + 2);
1060 
1061  src.x += width/3 - 1;
1062  src.y += height/3 - 1;
1063  dst.x += width/3 - 1;
1064  dst.y += height/3 - 1;
1065 
1066  if (roads_between_castles && road < int(castles.size() * castles.size())) {
1067  const size_t src_castle = road/castles.size();
1068  const size_t dst_castle = road%castles.size();
1069  if(src_castle >= dst_castle) {
1070  continue;
1071  }
1072 
1073  src = castles[src_castle];
1074  dst = castles[dst_castle];
1075  }
1076 
1077  // If the road isn't very interesting (on the same border), don't draw it.
1078  else if(src.x == dst.x || src.y == dst.y) {
1079  continue;
1080  }
1081 
1082  if (calc.cost(src, 0.0) >= 1000.0 || calc.cost(dst, 0.0) >= 1000.0) {
1083  continue;
1084  }
1085 
1086  // Search a path out for the road
1087  pathfind::plain_route rt = pathfind::a_star_search(src, dst, 10000.0, &calc, width, height);
1088 
1089  std::string road_base_name;
1090  const std::string& name = generate_name(name_generator, "road_name", &road_base_name);
1091  const int name_frequency = 20;
1092  int name_count = 0;
1093 
1094  bool on_bridge = false;
1095 
1096  // Draw the road.
1097  // If the search failed, rt.steps will simply be empty.
1098  for(std::vector<location>::const_iterator step = rt.steps.begin();
1099  step != rt.steps.end(); ++step) {
1100 
1101  const int x = step->x;
1102  const int y = step->y;
1103 
1104  if(x < 0 || y < 0 || x >= static_cast<long>(width) ||
1105  y >= static_cast<long>(height)) {
1106 
1107  continue;
1108  }
1109 
1110  // Find the configuration which tells us
1111  // what to convert this tile to, to make it into a road.
1112  if (const config &child = cfg.find_child("road_cost", "terrain",
1113  t_translation::write_terrain_code(terrain[x][y])))
1114  {
1115  // Convert to bridge means that we want to convert
1116  // depending upon the direction the road is going.
1117  // Typically it will be in a format like,
1118  // convert_to_bridge=\,|,/
1119  // '|' will be used if the road is going north-south
1120  // '/' will be used if the road is going south west-north east
1121  // '\' will be used if the road is going south east-north west
1122  // The terrain will be left unchanged otherwise
1123  // (if there is no clear direction).
1124  const std::string &convert_to_bridge = child["convert_to_bridge"];
1125  if(convert_to_bridge.empty() == false) {
1126  if(step == rt.steps.begin() || step+1 == rt.steps.end())
1127  continue;
1128 
1129  const location& last = *(step-1);
1130  const location& next = *(step+1);
1131 
1132  location adj[6];
1133  get_adjacent_tiles(*step,adj);
1134 
1135  int direction = -1;
1136 
1137  // If we are going north-south
1138  if((last == adj[0] && next == adj[3]) || (last == adj[3] && next == adj[0])) {
1139  direction = 0;
1140  }
1141 
1142  // If we are going south west-north east
1143  else if((last == adj[1] && next == adj[4]) || (last == adj[4] && next == adj[1])) {
1144  direction = 1;
1145  }
1146 
1147  // If we are going south east-north west
1148  else if((last == adj[2] && next == adj[5]) || (last == adj[5] && next == adj[2])) {
1149  direction = 2;
1150  }
1151 
1152  if(misc_labels != nullptr && on_bridge == false) {
1153  on_bridge = true;
1154  std::string bridge_base_name;
1155  const std::string& name = generate_name(name_generator, "bridge_name", &bridge_base_name);
1156  const location loc(x - width / 3, y-height/3);
1157  misc_labels->insert(std::pair<map_location,std::string>(loc,name));
1158  bridge_names.insert(std::pair<location,std::string>(loc, bridge_base_name)); //add to use for village naming
1159  bridges.insert(loc);
1160  }
1161 
1162  if(direction != -1) {
1163  const std::vector<std::string> items = utils::split(convert_to_bridge);
1164  if(size_t(direction) < items.size() && items[direction].empty() == false) {
1165  terrain[x][y] = t_translation::read_terrain_code(items[direction]);
1166  }
1167 
1168  continue;
1169  }
1170  } else {
1171  on_bridge = false;
1172  }
1173 
1174  // Just a plain terrain substitution for a road
1175  const std::string &convert_to = child["convert_to"];
1176  if(convert_to.empty() == false) {
1177  const t_translation::t_terrain letter =
1179  if(misc_labels != nullptr && terrain[x][y] != letter && name_count++ == name_frequency && on_bridge == false) {
1180  misc_labels->insert(std::pair<map_location,std::string>(map_location(x-width/3,y-height/3),name));
1181  name_count = 0;
1182  }
1183 
1184  terrain[x][y] = letter;
1185  const location loc(x - width / 3, y - height / 3); //add to use for village naming
1186  road_names.insert(std::pair<location,std::string>(loc, road_base_name));
1187  }
1188  }
1189  }
1190 
1191  LOG_NG << "looked at " << calc.calls << " locations\n";
1192  }
1193 
1194 
1195  // Now that road drawing is done, we can plonk down the castles.
1196  for(std::vector<location>::const_iterator c = castles.begin(); c != castles.end(); ++c) {
1197  if(c->valid() == false) {
1198  continue;
1199  }
1200 
1201  const int x = c->x;
1202  const int y = c->y;
1203  const int player = c - castles.begin() + 1;
1204  const struct t_translation::coordinate coord(x, y);
1205  starting_positions.insert(t_translation::tstarting_positions::value_type(std::to_string(player), coord));
1206  terrain[x][y] = t_translation::HUMAN_KEEP;
1207 
1208  const int castles[13][2] = {
1209  {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {0, 1}, {-1, 1},
1210  {-2, 1}, {-2, 0}, {-2, -1}, {-1, -2}, {0, -2}, {1, -2}
1211  };
1212 
1213  for (size_t i = 0; i < castle_size - 1; i++) {
1214  terrain[x+castles[i][0]][y+castles[i][1]] = t_translation::HUMAN_CASTLE;
1215  }
1216 
1217  // Remove all labels under the castle tiles
1218  if(labels != nullptr) {
1219  labels->erase(location(x-width/3,y-height/3));
1220  for (size_t i = 0; i < castle_size - 1; i++) {
1221  labels->erase(location(x+castles[i][0]-width/3,
1222  y+castles[i][1]-height/3));
1223  }
1224 
1225  }
1226 
1227  }
1228 
1229  LOG_NG << "placed castles\n";
1230  LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();
1231 
1232  /*Random naming for landforms: mountains, forests, swamps, hills
1233  *we name these now that everything else is placed (as e.g., placing
1234  * roads could split a forest)
1235  */
1236  if ( misc_labels != nullptr ) {
1237  for (x = width / 3; x < (width / 3)*2; x++) {
1238  for (y = height / 3; y < (height / 3) * 2;y++) {
1239  //check the terrain of the tile
1240  const location loc(x - width / 3, y - height / 3);
1241  const t_translation::t_terrain terr = terrain[x][y];
1243  std::set<std::string> used_names;
1245  //name every 15th mountain
1246  if ((rng_()%15) == 0) {
1247  for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1248  name = generate_name(name_generator, "mountain_name", &base_name);
1249  }
1250  misc_labels->insert(std::pair<map_location, std::string>(loc, name));
1251  mountain_names.insert(std::pair<location, std::string>(loc, base_name));
1252  }
1253  }
1255  //if the forest tile is not named yet, name it
1256  const std::map<location, std::string>::const_iterator forest_name = forest_names.find(loc);
1257  if(forest_name == forest_names.end()) {
1258  for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1259  name = generate_name(name_generator, "forest_name", &base_name);
1260  }
1261  forest_names.insert(std::pair<location, std::string>(loc, base_name));
1262  // name all connected forest tiles accordingly
1263  flood_name(loc, base_name, forest_names, t_translation::ALL_FORESTS, terrain, width, height, 0, misc_labels, name);
1264  }
1265  }
1267  //if the swamp tile is not named yet, name it
1268  const std::map<location, std::string>::const_iterator swamp_name = swamp_names.find(loc);
1269  if(swamp_name == swamp_names.end()) {
1270  for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1271  name = generate_name(name_generator, "swamp_name", &base_name);
1272  }
1273  swamp_names.insert(std::pair<location, std::string>(loc, base_name));
1274  // name all connected swamp tiles accordingly
1275  flood_name(loc, base_name, swamp_names, t_translation::ALL_SWAMPS, terrain, width, height, 0, misc_labels, name);
1276  }
1277  }
1278  }//for (y)
1279  }//for (x)
1280  }//if (misc_labels)
1281 
1282  if (nvillages > 0)
1283  {
1284  config naming_cfg = cfg.child_or_empty("village_naming");
1285  // If the [village_naming] child is empty, we cannot provide good names.
1286  std::map<map_location,std::string>* village_labels = naming_cfg.empty() ? nullptr : labels;
1287 
1288  // Specify "class" here because we also have a local variable with the same name
1289  boost::shared_ptr<class name_generator> village_names_generator;
1290  if(naming_cfg.has_attribute("name_generator")) {
1291  village_names_generator.reset(new context_free_grammar_generator(naming["name_generator"]));
1292  if(!village_names_generator->is_valid()) {
1293  village_names_generator.reset();
1294  }
1295  }
1296  config::attribute_value markov_list = naming_cfg.get_old_attribute("names", "male_names",
1297  "[village_naming]male_names is deprecated, use names instead");
1298  if(!markov_list.blank()) {
1299  village_names_generator.reset(new markov_generator(utils::split(markov_list), naming["markov_chain_size"], 12));
1300  }
1301 
1302  // First we work out the size of the x and y distance between villages
1303  const size_t tiles_per_village = ((width*height)/9)/nvillages;
1304  size_t village_x = 1, village_y = 1;
1305 
1306  // Alternate between incrementing the x and y value.
1307  // When they are high enough to equal or exceed the tiles_per_village,
1308  // then we have them to the value we want them at.
1309  while(village_x*village_y < tiles_per_village) {
1310  if(village_x < village_y) {
1311  ++village_x;
1312  } else {
1313  ++village_y;
1314  }
1315  }
1316 
1317  std::set<std::string> used_names;
1318  tcode_list_cache adj_liked_cache;
1319 
1320  for(size_t vx = 0; vx < width; vx += village_x) {
1321  LOG_NG << "village at " << vx << "\n";
1322  for(size_t vy = rng_()%village_y; vy < height; vy += village_y) {
1323 
1324  const size_t add_x = rng_()%3;
1325  const size_t add_y = rng_()%3;
1326  const size_t x = (vx + add_x) - 1;
1327  const size_t y = (vy + add_y) - 1;
1328 
1329  const map_location res = place_village(terrain,x,y,2,cfg,adj_liked_cache);
1330 
1331  if(res.x >= static_cast<long>(width) / 3 &&
1332  res.x < static_cast<long>(width * 2) / 3 &&
1333  res.y >= static_cast<long>(height) / 3 &&
1334  res.y < static_cast<long>(height * 2) / 3) {
1335 
1336  const std::string str =
1337  t_translation::write_terrain_code(terrain[res.x][res.y]);
1338  if (const config &child = cfg.find_child("village", "terrain", str))
1339  {
1340  const std::string &convert_to = child["convert_to"];
1341  if(convert_to != "") {
1342  terrain[res.x][res.y] =
1344 
1345  villages.insert(res);
1346 
1347  if ( village_labels != nullptr ) {
1348  const map_location loc(res.x-width/3,res.y-height/3);
1349 
1350  map_location adj[6];
1351  get_adjacent_tiles(loc,adj);
1352 
1353  std::string name_type = "village_name";
1354  const t_translation::t_list
1359 
1360  size_t field_count = 0, forest_count = 0, mountain_count = 0, hill_count = 0;
1361 
1362  utils::string_map symbols;
1363 
1364  size_t n;
1365  for(n = 0; n != 6; ++n) {
1366  const std::map<location,std::string>::const_iterator road_name = road_names.find(adj[n]);
1367  if(road_name != road_names.end()) {
1368  symbols["road"] = road_name->second;
1369  name_type = "village_name_road";
1370  break;
1371  }
1372 
1373  const std::map<location,std::string>::const_iterator river_name = river_names.find(adj[n]);
1374  if(river_name != river_names.end()) {
1375  symbols["river"] = river_name->second;
1376  name_type = "village_name_river";
1377 
1378  const std::map<location,std::string>::const_iterator bridge_name = bridge_names.find(adj[n]);
1379  if(bridge_name != bridge_names.end()) {
1380  //we should always end up here, since if there is an adjacent bridge, there has to be an adjacent river too
1381  symbols["bridge"] = bridge_name->second;
1382  name_type = "village_name_river_bridge";
1383  }
1384 
1385  break;
1386  }
1387 
1388  const std::map<location,std::string>::const_iterator forest_name = forest_names.find(adj[n]);
1389  if(forest_name != forest_names.end()) {
1390  symbols["forest"] = forest_name->second;
1391  name_type = "village_name_forest";
1392  break;
1393  }
1394 
1395  const std::map<location,std::string>::const_iterator lake_name = lake_names.find(adj[n]);
1396  if(lake_name != lake_names.end()) {
1397  symbols["lake"] = lake_name->second;
1398  name_type = "village_name_lake";
1399  break;
1400  }
1401 
1402  const std::map<location,std::string>::const_iterator mountain_name = mountain_names.find(adj[n]);
1403  if(mountain_name != mountain_names.end()) {
1404  symbols["mountain"] = mountain_name->second;
1405  name_type = "village_name_mountain";
1406  break;
1407  }
1408 
1409  const std::map<location,std::string>::const_iterator swamp_name = swamp_names.find(adj[n]);
1410  if(swamp_name != swamp_names.end()) {
1411  symbols["swamp"] = swamp_name->second;
1412  name_type = "village_name_swamp";
1413  break;
1414  }
1415 
1416  const t_translation::t_terrain terr =
1417  terrain[adj[n].x+width/3][adj[n].y+height/3];
1418 
1419  if(std::count(field.begin(),field.end(),terr) > 0) {
1420  ++field_count;
1421  } else if(std::count(forest.begin(),forest.end(),terr) > 0) {
1422  ++forest_count;
1423  } else if(std::count(hill.begin(),hill.end(),terr) > 0) {
1424  ++hill_count;
1425  } else if(std::count(mountain.begin(),mountain.end(),terr) > 0) {
1426  ++mountain_count;
1427  }
1428  }
1429 
1430  if(n == 6) {
1431  if(field_count == 6) {
1432  name_type = "village_name_grassland";
1433  } else if(forest_count >= 2) {
1434  name_type = "village_name_forest";
1435  } else if(mountain_count >= 1) {
1436  name_type = "village_name_mountain_anonymous";
1437  } else if(hill_count >= 2) {
1438  name_type = "village_name_hill";
1439  }
1440  }
1441 
1442  std::string name;
1443  for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
1444  name = generate_name(village_names_generator,name_type,nullptr,&symbols);
1445  }
1446 
1447  used_names.insert(name);
1448  village_labels->insert(std::pair<map_location,std::string>(loc,name));
1449  }
1450  }
1451  }
1452  }
1453  }
1454  }
1455  }
1456 
1457  LOG_NG << "placed villages\n";
1458  LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();
1459 
1460  return output_map(terrain, starting_positions);
1461 }
const attribute_value & get_old_attribute(const std::string &key, const std::string &old_key, const std::string &msg="") const
Function to handle backward compatibility Get the value of key and if missing try old_key and log msg...
Definition: config.cpp:948
child_itors child_range(const std::string &key)
Definition: config.cpp:613
Contains an x and y coordinate used for starting positions in maps.
Definition: translation.hpp:97
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator *calc, const size_t width, const size_t height, const teleport_map *teleports, bool border)
std::string default_generate_map(size_t width, size_t height, size_t island_size, size_t island_off_center, size_t iterations, size_t hill_size, size_t max_lakes, size_t nvillages, size_t castle_size, size_t nplayers, bool roads_between_castles, std::map< map_location, std::string > *labels, const config &cfg)
Generate the map.
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
boost::bimaps::bimap< boost::bimaps::set_of< std::string >, boost::bimaps::multiset_of< coordinate >> tstarting_positions
static map_location place_village(const t_translation::t_map &map, const size_t x, const size_t y, const size_t radius, const config &cfg, tcode_list_cache &adj_liked_cache)
t_list read_list(const std::string &str, const t_layer filler)
Reads a list of terrains from a string, when reading the.
std::vector< map_location > generate_river(const height_map &heights, terrain_map &terrain, int x, int y, int river_uphill)
std::string write_game_map(const t_map &map, const tstarting_positions &starting_positions, coordinate border_offset)
Write a gamemap in to a vector string.
const GLfloat * c
Definition: glew.h:12741
int pos
Definition: formula.cpp:800
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, size_t min_distance, const std::vector< map_location > &other_castles, int highest_ranking)
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
static void flood_name(const map_location &start, const std::string &name, std::map< map_location, std::string > &tile_names, const t_translation::t_match &tile_types, const terrain_map &terrain, unsigned width, unsigned height, size_t label_count, std::map< map_location, std::string > *labels, const std::string &full_name)
#define ERR_NG
const t_terrain HILL
variant map_
Definition: formula.cpp:306
const t_terrain NONE_TERRAIN
Definition: translation.hpp:56
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:29
const t_terrain MOUNTAIN
boost::uint32_t uint32_t
Definition: xbrz.hpp:45
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.hpp:274
static const int default_border
The default border style for a map.
Definition: map.hpp:201
const t_terrain DEEP_WATER
STL namespace.
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
GLenum src
Definition: glew.h:2392
const std::vector< std::string > items
const config & child_or_empty(const std::string &key) const
Returns the first child with the given key, or an empty config if there is none.
Definition: config.cpp:722
bool empty() const
Definition: config.cpp:1105
GLdouble GLdouble t
Definition: glew.h:1366
t_terrain read_terrain_code(const std::string &str, const t_layer filler)
Reads a single terrain from a string.
Variant for storing WML attributes.
Definition: config.hpp:223
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)
GLdouble l
Definition: glew.h:6966
static double getNoPathValue()
Definition: pathfind.hpp:64
bool blank() const
Tests for an attribute that was never set.
Definition: config.cpp:367
const t_terrain HUMAN_KEEP
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
std::vector< std::vector< t_terrain > > t_map
Definition: translation.hpp:76
const config & options()
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:82
const t_terrain GRASS_LAND
const t_match ALL_FORESTS
map_location random_point_at_side(size_t width, size_t height)
Returns a random tile at one of the borders of a map that is of the given dimensions.
GLuint GLuint end
Definition: glew.h:1221
std::vector< map_location > steps
Definition: pathfind.hpp:135
std::map< std::string, t_string > string_map
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
Structure which holds a single route between one location and another.
Definition: pathfind.hpp:132
const t_terrain FOREST
const std::string name_type
type of possible name identificator
This structure can be used for matching terrain strings.
Definition: translation.hpp:83
size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Definition: location.hpp:357
static text_list cache_
Definition: font.cpp:772
static std::string output_map(const terrain_map &terrain, t_translation::tstarting_positions &starting_positions)
Function which, given the map will output it in a valid format.
GLenum GLenum dst
Definition: glew.h:2392
std::string base_name(const std::string &file)
Returns the base filename of a file, with directory name stripped.
GLuint start
Definition: glew.h:1221
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
static void field(LexState *ls, struct ConsControl *cc)
Definition: lparser.cpp:707
static const ::config * terrain
The terrain used to create the cache.
Definition: minimap.cpp:135
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
Templates and utility-routines for strings and numbers.
GLuint GLuint GLsizei count
Definition: glew.h:1221
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:47
const t_terrain HUMAN_CASTLE
Encapsulates the map of the game.
Definition: location.hpp:38
GLuint res
Definition: glew.h:9258
#define LOG_NG
static lg::log_domain log_mapgen("mapgen")
std::map< std::string, tfilter >::iterator itor
Definition: filter.cpp:199
const t_match ALL_MOUNTAINS("!,*^V*,!,M*")
#define log_scope(description)
Definition: log.hpp:185
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:5910
size_t i
Definition: function.cpp:1057
bool terrain_matches(const t_terrain &src, const t_terrain &dest)
Tests whether a specific terrain matches an expression, for matching rules see above.
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
void get_tiles_radius(const map_location &center, size_t radius, std::set< map_location > &result)
Function that will add to result all locations within radius tiles of center (including center itself...
Definition: pathutils.cpp:70
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
t_translation::t_map terrain_map
std::string write_terrain_code(const t_terrain &tcode)
Writes a single terrain code to a string.
GLint GLint GLint GLint GLint GLint GLsizei GLsizei height
Definition: glew.h:1220
GLuint const GLchar * name
Definition: glew.h:1782
#define next(ls)
Definition: llex.cpp:27
GLsizeiptr size
Definition: glew.h:1649
uint32_t next_seed()
Definition: seed_rng.cpp:52
std::vector< std::vector< int > > height_map
GLclampd n
Definition: glew.h:5903
bool has_attribute(const std::string &key) const
Definition: config.cpp:514
virtual double cost(const map_location &loc, const double so_far) const =0
bool find(E event, F functor)
Tests whether an event handler is available.
bool generate_lake(t_translation::t_map &terrain, int x, int y, int lake_fall_off, std::set< map_location > &locs_touched)
Generate a lake.
symbol_table string_table
Definition: language.cpp:65
static bool is_valid_terrain(const t_translation::t_terrain &c)
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
config & find_child(const std::string &key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Definition: config.cpp:1010
Standard logging facilities (interface).
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.
const t_match ALL_SWAMPS("!,*^V*,*^B*,!,S*")
#define c
Definition: glew.h:12743
GLint GLint GLint GLint GLint GLint GLsizei width
Definition: glew.h:1220
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
map_location location
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
const t_terrain SHALLOW_WATER
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
This module contains various pathfinding functions and utilities.
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glew.h:3780
GLsizei const GLcharARB ** string
Definition: glew.h:4503
std::map< t_translation::t_terrain, t_translation::t_list > tcode_list_cache
std::vector< std::vector< int > > height_map
std::vector< t_terrain > t_list
Definition: translation.hpp:75
bool is_even(T num)
Definition: util.hpp:34
std::string generate_name(boost::shared_ptr< name_generator > &name_generator, const std::string &id, std::string *base_name=nullptr, utils::string_map *additional_symbols=nullptr)