Logo Search packages:      
Sourcecode: wesnoth-1.9 version File versions  Download package

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.

Try to find configuration for castles.

Definition at line 735 of file mapgen.cpp.

References config::child(), config::child_or_empty(), config::child_range(), config::empty(), config::find_child(), generate_height_map(), generate_lake(), get_adjacent_tiles(), output_map(), random_point_at_side(), pathfind::plain_route::steps, VALIDATE, map_location::x, and map_location::y.

{
      log_scope("map generation");

      // Odd widths are nasty
      VALIDATE(is_even(width), _("Random maps with an odd width aren't supported."));

      int ticks = SDL_GetTicks();

      // Find out what the 'flatland' on this map is, i.e. grassland.
      std::string flatland = cfg["default_flatland"];
      if(flatland == "") {
            flatland = t_translation::write_terrain_code(t_translation::GRASS_LAND);
      }

      const t_translation::t_terrain grassland = t_translation::read_terrain_code(flatland);

      // We want to generate a map that is 9 times bigger
      // than the actual size desired.
      // Only the middle part of the map will be used,
      // but the rest is so that the map we end up using
      // can have a context (e.g. rivers flowing from
      // out of the map into the map, same for roads, etc.)
      width *= 3;
      height *= 3;

      LOG_NG << "generating height map...\n";
      // Generate the height of everything.
      const height_map heights = generate_height_map(width,height,iterations,hill_size,island_size,island_off_center);
      LOG_NG << "done generating height map...\n";
      LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

      config naming = cfg.child_or_empty("naming");
      // HACK: dummy names to satisfy unit_race requirements
      naming["id"] = "village_naming";
      naming["plural_name"] = "villages";

      // Make a dummy race for generating names
      const unit_race name_generator(naming);

      std::vector<terrain_height_mapper> height_conversion;

      foreach (const config &h, cfg.child_range("height")) {
            height_conversion.push_back(terrain_height_mapper(h));
      }

      terrain_map terrain(width, t_translation::t_list(height, grassland));
      size_t x, y;
      for(x = 0; x != heights.size(); ++x) {
            for(y = 0; y != heights[x].size(); ++y) {
                  for(std::vector<terrain_height_mapper>::const_iterator i = height_conversion.begin();
                      i != height_conversion.end(); ++i) {
                        if(i->convert_terrain(heights[x][y])) {
                              terrain[x][y] = i->convert_to();
                              break;
                        }
                  }
            }
      }

      std::map<int, t_translation::coordinate> starting_positions;
      LOG_NG << output_map(terrain, starting_positions);
      LOG_NG << "placed land forms\n";
      LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

      // Now that we have our basic set of flatland/hills/mountains/water,
      // we can place lakes and rivers on the map.
      // All rivers are sourced at a lake.
      // Lakes must be in high land - at least 'min_lake_height'.
      // (Note that terrain below a certain altitude may be made
      // into bodies of water in the code above - i.e. 'sea',
      // but these are not considered 'lakes', because
      // they are not sources of rivers).
      //
      // We attempt to place 'max_lakes' lakes.
      // Each lake will be placed at a random location,
      // if that random location meets the minimum terrain requirements for a lake.
      // We will also attempt to source a river from each lake.
      std::set<location> lake_locs;

      std::map<location, std::string> river_names, lake_names, road_names, bridge_names, mountain_names, forest_names, swamp_names;

      const size_t nlakes = max_lakes > 0 ? (rand()%max_lakes) : 0;
      for(size_t lake = 0; lake != nlakes; ++lake) {
            for(int tries = 0; tries != 100; ++tries) {
                  const int x = rand()%width;
                  const int y = rand()%height;
                  if (heights[x][y] > cfg["min_lake_height"].to_int()) {
                        std::vector<location> river = generate_river(heights,
                              terrain, x, y, cfg["river_frequency"]);

                        if(river.empty() == false && labels != NULL) {
                              std::string base_name;
                              LOG_NG << "generating name for river...\n";
                              const std::string& name = generate_name(name_generator,"river_name",&base_name);
                              LOG_NG << "named river '" << name << "'\n";
                              size_t name_frequency = 20;
                              for(std::vector<location>::const_iterator r = river.begin(); r != river.end(); ++r) {

                                    const map_location loc(r->x-width/3,r->y-height/3);

                                    if(((r - river.begin())%name_frequency) == name_frequency/2) {
                                          labels->insert(std::pair<map_location,std::string>(loc,name));
                                    }

                                    river_names.insert(std::pair<location,std::string>(loc,base_name));
                              }

                              LOG_NG << "put down river name...\n";
                        }

                        LOG_NG << "generating lake...\n";
                        std::set<location> locs;
                        bool res = generate_lake(terrain, x, y, cfg["lake_size"], locs);
                        if(res && labels != NULL) {
                              bool touches_other_lake = false;

                              std::string base_name;
                              const std::string& name = generate_name(name_generator,"lake_name",&base_name);

                              std::set<location>::const_iterator i;

                              // Only generate a name if the lake hasn't touched any other lakes,
                              // so that we don't end up with one big lake with multiple names.
                              for(i = locs.begin(); i != locs.end(); ++i) {
                                    if(lake_locs.count(*i) != 0) {
                                          touches_other_lake = true;

                                          // Reassign the name of this lake to be the same as the other lake
                                          const location loc(i->x-width/3,i->y-height/3);
                                          const std::map<location,std::string>::const_iterator other_name = lake_names.find(loc);
                                          if(other_name != lake_names.end()) {
                                                base_name = other_name->second;
                                          }
                                    }

                                    lake_locs.insert(*i);
                              }

                              if(!touches_other_lake) {
                                    const map_location loc(x-width/3,y-height/3);
                                    labels->erase(loc);
                                    labels->insert(std::pair<map_location,std::string>(loc,name));
                              }

                              for(i = locs.begin(); i != locs.end(); ++i) {
                                    const location loc(i->x-width/3,i->y-height/3);
                                    lake_names.insert(std::pair<location, std::string>(loc, base_name));
                              }
                        }

                        break;
                  }
            }
      }

      LOG_NG << "done generating rivers...\n";
      LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

      const size_t default_dimensions = 40*40*9;

      /*
       * Convert grassland terrain to other types of flat terrain.
       *
       * We generate a 'temperature map' which uses the height generation
       * algorithm to generate the temperature levels all over the map.  Then we
       * can use a combination of height and terrain to divide terrain up into
       * more interesting types than the default.
       */
      const height_map temperature_map = generate_height_map(width,height,
            cfg["temperature_iterations"].to_int() * width * height / default_dimensions,
            cfg["temperature_size"], 0, 0);

      LOG_NG << "generated temperature map...\n";
      LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

      std::vector<terrain_converter> converters;
      foreach (const config &cv, cfg.child_range("convert")) {
            converters.push_back(terrain_converter(cv));
      }

      LOG_NG << "created terrain converters\n";
      LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();


      // Iterate over every flatland tile, and determine
      // what type of flatland it is, based on our [convert] tags.
      for(x = 0; x != width; ++x) {
            for(y = 0; y != height; ++y) {
                  for(std::vector<terrain_converter>::const_iterator i = converters.begin(); i != converters.end(); ++i) {
                        if(i->convert_terrain(terrain[x][y],heights[x][y],temperature_map[x][y])) {
                              terrain[x][y] = i->convert_to();
                              break;
                        }
                  }
            }
      }

      LOG_NG << "placing villages...\n";
      LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

      /*
       * Place villages in a 'grid', to make placing fair, but with villages
       * displaced from their position according to terrain and randomness, to
       * add some variety.
       */
      std::set<location> villages;

      LOG_NG << "placing castles...\n";

      /** Try to find configuration for castles. */
      const config &castle_config = cfg.child("castle");
      if (!castle_config) {
            LOG_NG << "Could not find castle configuration\n";
            return std::string();
      }

      /*
       * Castle configuration tag contains a 'valid_terrain' attribute which is a
       * list of terrains that the castle may appear on.
       */
      const t_translation::t_list list =
            t_translation::read_list(castle_config["valid_terrain"]);

      const is_valid_terrain terrain_tester(terrain, list);

      /*
       * Attempt to place castles at random.
       *
       * Once we have placed castles, we run a sanity check to make sure that the
       * castles are well-placed.  If the castles are not well-placed, we try
       * again.  Definition of 'well-placed' is if no two castles are closer than
       * 'min_distance' hexes from each other, and the castles appear on a
       * terrain listed in 'valid_terrain'.
       */
      std::vector<location> castles;
      std::set<location> failed_locs;

      for(size_t player = 0; player != nplayers; ++player) {
            LOG_NG << "placing castle for " << player << "\n";
            log_scope("placing castle");
            const int min_x = width/3 + 3;
            const int min_y = height/3 + 3;
            const int max_x = (width/3)*2 - 4;
            const int max_y = (height/3)*2 - 4;
            int min_distance = castle_config["min_distance"];

            location best_loc;
            int best_ranking = 0;
            for(int x = min_x; x != max_x; ++x) {
                  for(int y = min_y; y != max_y; ++y) {
                        const location loc(x,y);
                        if(failed_locs.count(loc)) {
                              continue;
                        }

                        const int ranking = rank_castle_location(x,y,terrain_tester,min_x,max_x,min_y,max_y,min_distance,castles,best_ranking);
                        if(ranking <= 0) {
                              failed_locs.insert(loc);
                        }

                        if(ranking > best_ranking) {
                              best_ranking = ranking;
                              best_loc = loc;
                        }
                  }
            }
            if(best_ranking == 0) {
                  //FIXME: Make this error message translatable (not possible atm due to string freeze)
                  ERR_NG << "No castle location found, aborting.\n";
                  std::string error = "No valid castle location found. Too many or too few mountain hexes? (please check the 'max hill size' parameter)";
                  throw mapgen_exception(error);
            }
            assert(std::find(castles.begin(), castles.end(), best_loc) == castles.end());
            castles.push_back(best_loc);
            // Make sure the location can't get a second castle.
            failed_locs.insert(best_loc);
      }

      LOG_NG << "placing roads...\n";
      LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

      // Place roads.
      // We select two tiles at random locations on the borders
      // of the map, and try to build roads between them.
      int nroads = cfg["roads"];
      if(roads_between_castles) {
            nroads += castles.size()*castles.size();
      }

      std::set<location> bridges;

      road_path_calculator calc(terrain,cfg);
      for (int road = 0; road != nroads; ++road) {
            log_scope("creating road");

            /*
             * We want the locations to be on the portion of the map we're actually
             * going to use, since roads on other parts of the map won't have any
             * influence, and doing it like this will be quicker.
             */
            location src = random_point_at_side(width/3 + 2,height/3 + 2);
            location dst = random_point_at_side(width/3 + 2,height/3 + 2);

            src.x += width/3 - 1;
            src.y += height/3 - 1;
            dst.x += width/3 - 1;
            dst.y += height/3 - 1;

            if (roads_between_castles && road < int(castles.size() * castles.size())) {
                  const size_t src_castle = road/castles.size();
                  const size_t dst_castle = road%castles.size();
                  if(src_castle >= dst_castle) {
                        continue;
                  }

                  src = castles[src_castle];
                  dst = castles[dst_castle];
            }

            // If the road isn't very interesting (on the same border), don't draw it.
            else if(src.x == dst.x || src.y == dst.y) {
                  continue;
            }

            if (calc.cost(src, 0.0) >= 1000.0 || calc.cost(dst, 0.0) >= 1000.0) {
                  continue;
            }

            // Search a path out for the road
            pathfind::plain_route rt = pathfind::a_star_search(src, dst, 10000.0, &calc, width, height);

            std::string road_base_name;
            const std::string& name = generate_name(name_generator, "road_name", &road_base_name);
            const int name_frequency = 20;
            int name_count = 0;

            bool on_bridge = false;

            // Draw the road.
            // If the search failed, rt.steps will simply be empty.
            for(std::vector<location>::const_iterator step = rt.steps.begin();
                        step != rt.steps.end(); ++step) {

                  const int x = step->x;
                  const int y = step->y;

                  if(x < 0 || y < 0 || x >= static_cast<long>(width) ||
                              y >= static_cast<long>(height)) {

                        continue;
                  }

                  // Find the configuration which tells us
                  // what to convert this tile to, to make it into a road.
                  if (const config &child = cfg.find_child("road_cost", "terrain",
                              t_translation::write_terrain_code(terrain[x][y])))
                  {
                        // Convert to bridge means that we want to convert
                        // depending upon the direction the road is going.
                        // Typically it will be in a format like,
                        // convert_to_bridge=\,|,/
                        // '|' will be used if the road is going north-south
                        // '/' will be used if the road is going south west-north east
                        // '\' will be used if the road is going south east-north west
                        // The terrain will be left unchanged otherwise
                        // (if there is no clear direction).
                        const std::string &convert_to_bridge = child["convert_to_bridge"];
                        if(convert_to_bridge.empty() == false) {
                              if(step == rt.steps.begin() || step+1 == rt.steps.end())
                                    continue;

                              const location& last = *(step-1);
                              const location& next = *(step+1);

                              location adj[6];
                              get_adjacent_tiles(*step,adj);

                              int direction = -1;

                              // If we are going north-south
                              if((last == adj[0] && next == adj[3]) || (last == adj[3] && next == adj[0])) {
                                    direction = 0;
                              }

                              // If we are going south west-north east
                              else if((last == adj[1] && next == adj[4]) || (last == adj[4] && next == adj[1])) {
                                    direction = 1;
                              }

                              // If we are going south east-north west
                              else if((last == adj[2] && next == adj[5]) || (last == adj[5] && next == adj[2])) {
                                    direction = 2;
                              }

                              if(labels != NULL && on_bridge == false) {
                                    on_bridge = true;
                                    std::string bridge_base_name;
                                    const std::string& name = generate_name(name_generator, "bridge_name", &bridge_base_name);
                                    const location loc(x - width / 3, y-height/3);
                                    labels->insert(std::pair<map_location,std::string>(loc,name));
                                    bridge_names.insert(std::pair<location,std::string>(loc, bridge_base_name)); //add to use for village naming
                                    bridges.insert(loc);
                              }

                              if(direction != -1) {
                                    const std::vector<std::string> items = utils::split(convert_to_bridge);
                                    if(size_t(direction) < items.size() && items[direction].empty() == false) {
                                          terrain[x][y] = t_translation::read_terrain_code(items[direction]);
                                    }

                                    continue;
                              }
                        } else {
                              on_bridge = false;
                        }

                        // Just a plain terrain substitution for a road
                        const std::string &convert_to = child["convert_to"];
                        if(convert_to.empty() == false) {
                              const t_translation::t_terrain letter =
                                    t_translation::read_terrain_code(convert_to);
                              if(labels != NULL && terrain[x][y] != letter && name_count++ == name_frequency && on_bridge == false) {
                                    labels->insert(std::pair<map_location,std::string>(map_location(x-width/3,y-height/3),name));
                                    name_count = 0;
                              }

                              terrain[x][y] = letter;
                              const location loc(x - width / 3, y - height / 3); //add to use for village naming
                              road_names.insert(std::pair<location,std::string>(loc, road_base_name));
                        }
                  }
            }

            LOG_NG << "looked at " << calc.calls << " locations\n";
      }


      // Now that road drawing is done, we can plonk down the castles.
      for(std::vector<location>::const_iterator c = castles.begin(); c != castles.end(); ++c) {
            if(c->valid() == false) {
                  continue;
            }

            const int x = c->x;
            const int y = c->y;
            const int player = c - castles.begin() + 1;
            const struct t_translation::coordinate coord = {x, y};
            starting_positions.insert(std::pair<int, t_translation::coordinate>(player, coord));
            terrain[x][y] = t_translation::HUMAN_KEEP;

            const int castles[13][2] = {
              {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {0, 1}, {-1, 1},
              {-2, 1}, {-2, 0}, {-2, -1}, {-1, -2}, {0, -2}, {1, -2}
            };

            for (size_t i = 0; i < castle_size - 1; i++) {
              terrain[x+castles[i][0]][y+castles[i][1]] = t_translation::HUMAN_CASTLE;
            }

            // Remove all labels under the castle tiles
            if(labels != NULL) {
              labels->erase(location(x-width/3,y-height/3));
              for (size_t i = 0; i < castle_size - 1; i++) {
                labels->erase(location(x+castles[i][0]-width/3,
                                 y+castles[i][1]-height/3));
              }

            }

      }

      LOG_NG << "placed castles\n";
      LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

      /*Random naming for landforms: mountains, forests, swamps, hills
       *we name these now that everything else is placed (as e.g., placing
       * roads could split a forest)
       */
      for (x = width / 3; x < (width / 3)*2; x++) {
            for (y = height / 3; y < (height / 3) * 2;y++) {
            //check the terrain of the tile
            const location loc(x - width / 3, y - height / 3);
            const t_translation::t_terrain terr = terrain[x][y];
            std::string name, base_name;
            std::set<std::string> used_names;
            if (t_translation::terrain_matches(terr, t_translation::ALL_MOUNTAINS)) {
                  //name every 15th mountain
                  if ((rand()%15) == 0) {
                        for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
                              name = generate_name(name_generator, "mountain_name", &base_name);
                        }
                        labels->insert(std::pair<map_location, std::string>(loc, name));
                        mountain_names.insert(std::pair<location, std::string>(loc, base_name));
                  }
            }
            else if (t_translation::terrain_matches(terr, t_translation::ALL_FORESTS)) {
                  //if the forest tile is not named yet, name it
                  const std::map<location, std::string>::const_iterator forest_name = forest_names.find(loc);
                  if(forest_name == forest_names.end()) {
                        for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
                              name = generate_name(name_generator, "forest_name", &base_name);
                        }
                        forest_names.insert(std::pair<location, std::string>(loc, base_name));
                        // name all connected forest tiles accordingly
                        flood_name(loc, base_name, forest_names, t_translation::ALL_FORESTS, terrain, width, height, 0, labels, name);
                  }
            }
            else if (t_translation::terrain_matches(terr, t_translation::ALL_SWAMPS)) {
                  //if the swamp tile is not named yet, name it
                  const std::map<location, std::string>::const_iterator swamp_name = swamp_names.find(loc);
                  if(swamp_name == swamp_names.end()) {
                        for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
                              name = generate_name(name_generator, "swamp_name", &base_name);
                        }
                        swamp_names.insert(std::pair<location, std::string>(loc, base_name));
                        // name all connected swamp tiles accordingly
                        flood_name(loc, base_name, swamp_names, t_translation::ALL_SWAMPS, terrain, width, height, 0, labels, name);
                  }
            }

            }
      }

      if (nvillages > 0)
      {
            config naming_cfg = cfg.child_or_empty("village_naming");
            // HACK: dummy names to satisfy unit_race requirements
            naming_cfg["id"] = "village_naming";
            naming_cfg["plural_name"] = "villages";

            const unit_race village_names_generator(naming_cfg);

            // First we work out the size of the x and y distance between villages
            const size_t tiles_per_village = ((width*height)/9)/nvillages;
            size_t village_x = 1, village_y = 1;

            // Alternate between incrementing the x and y value.
            // When they are high enough to equal or exceed the tiles_per_village,
            // then we have them to the value we want them at.
            while(village_x*village_y < tiles_per_village) {
                  if(village_x < village_y) {
                        ++village_x;
                  } else {
                        ++village_y;
                  }
            }

            std::set<std::string> used_names;
            tcode_list_cache adj_liked_cache;

            for(size_t vx = 0; vx < width; vx += village_x) {
                  LOG_NG << "village at " << vx << "\n";
                  for(size_t vy = rand()%village_y; vy < height; vy += village_y) {

                        const size_t add_x = rand()%3;
                        const size_t add_y = rand()%3;
                        const size_t x = (vx + add_x) - 1;
                        const size_t y = (vy + add_y) - 1;

                        const map_location res = place_village(terrain,x,y,2,cfg,adj_liked_cache);

                        if(res.x >= static_cast<long>(width) / 3 &&
                                    res.x  < static_cast<long>(width * 2) / 3 &&
                                    res.y >= static_cast<long>(height) / 3 &&
                                    res.y  < static_cast<long>(height * 2) / 3) {

                              const std::string str =
                                    t_translation::write_terrain_code(terrain[res.x][res.y]);
                              if (const config &child = cfg.find_child("village", "terrain", str))
                              {
                                    const std::string &convert_to = child["convert_to"];
                                    if(convert_to != "") {
                                          terrain[res.x][res.y] =
                                                t_translation::read_terrain_code(convert_to);

                                          villages.insert(res);

                                          if(labels != NULL && naming_cfg.empty() == false) {
                                                const map_location loc(res.x-width/3,res.y-height/3);

                                                map_location adj[6];
                                                get_adjacent_tiles(loc,adj);

                                                std::string name_type = "village_name";
                                                const t_translation::t_list
                                                      field    = t_translation::t_list(1, t_translation::GRASS_LAND),
                                                      forest   = t_translation::t_list(1, t_translation::FOREST),
                                                      mountain = t_translation::t_list(1, t_translation::MOUNTAIN),
                                                      hill     = t_translation::t_list(1, t_translation::HILL);

                                                size_t field_count = 0, forest_count = 0, mountain_count = 0, hill_count = 0;

                                                utils::string_map symbols;

                                                size_t n;
                                                for(n = 0; n != 6; ++n) {
                                                      const std::map<location,std::string>::const_iterator road_name = road_names.find(adj[n]);
                                                      if(road_name != road_names.end()) {
                                                            symbols["road"] = road_name->second;
                                                            name_type = "village_name_road";
                                                            break;
                                                      }

                                                      const std::map<location,std::string>::const_iterator river_name = river_names.find(adj[n]);
                                                      if(river_name != river_names.end()) {
                                                            symbols["river"] = river_name->second;
                                                            name_type = "village_name_river";

                                                            const std::map<location,std::string>::const_iterator bridge_name = bridge_names.find(adj[n]);
                                                            if(bridge_name != bridge_names.end()) {
                                                            //we should always end up here, since if there is an adjacent bridge, there has to be an adjacent river too
                                                            symbols["bridge"] = bridge_name->second;
                                                            name_type = "village_name_river_bridge";
                                                            }

                                                            break;
                                                      }

                                                      const std::map<location,std::string>::const_iterator forest_name = forest_names.find(adj[n]);
                                                      if(forest_name != forest_names.end()) {
                                                            symbols["forest"] = forest_name->second;
                                                            name_type = "village_name_forest";
                                                            break;
                                                      }

                                                      const std::map<location,std::string>::const_iterator lake_name = lake_names.find(adj[n]);
                                                      if(lake_name != lake_names.end()) {
                                                            symbols["lake"] = lake_name->second;
                                                            name_type = "village_name_lake";
                                                            break;
                                                      }

                                                      const std::map<location,std::string>::const_iterator mountain_name = mountain_names.find(adj[n]);
                                                      if(mountain_name != mountain_names.end()) {
                                                            symbols["mountain"] = mountain_name->second;
                                                            name_type = "village_name_mountain";
                                                            break;
                                                      }

                                                      const std::map<location,std::string>::const_iterator swamp_name = swamp_names.find(adj[n]);
                                                      if(swamp_name != swamp_names.end()) {
                                                            symbols["swamp"] = swamp_name->second;
                                                            name_type = "village_name_swamp";
                                                            break;
                                                      }

                                                      const t_translation::t_terrain terr =
                                                            terrain[adj[n].x+width/3][adj[n].y+height/3];

                                                      if(std::count(field.begin(),field.end(),terr) > 0) {
                                                            ++field_count;
                                                      } else if(std::count(forest.begin(),forest.end(),terr) > 0) {
                                                            ++forest_count;
                                                      } else if(std::count(hill.begin(),hill.end(),terr) > 0) {
                                                            ++hill_count;
                                                      } else if(std::count(mountain.begin(),mountain.end(),terr) > 0) {
                                                            ++mountain_count;
                                                      }
                                                }

                                                if(n == 6) {
                                                      if(field_count == 6) {
                                                            name_type = "village_name_grassland";
                                                      } else if(forest_count >= 2) {
                                                            name_type = "village_name_forest";
                                                      } else if(mountain_count >= 1) {
                                                            name_type = "village_name_mountain_anonymous";
                                                      } else if(hill_count >= 2) {
                                                            name_type = "village_name_hill";
                                                      }
                                                }

                                                std::string name;
                                                for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
                                                      name = generate_name(village_names_generator,name_type,NULL,&symbols);
                                                }

                                                used_names.insert(name);
                                                labels->insert(std::pair<map_location,std::string>(loc,name));
                                          }
                                    }
                              }
                        }
                  }
            }
      }

      LOG_NG << "placed villages\n";
      LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

      return output_map(terrain, starting_positions);
}


Generated by  Doxygen 1.6.0   Back to index