void addons_client::send_request(const config& request, config& response) { check_connected(); response.clear(); this->conn_->transfer(request, response); }
static void cfg_to_value(const config &cfg, config &value) { if (const config &v = cfg.child("value")) { value = v; } else { value.clear(); } }
/** Read the file with the tips-of-the-day. */ void read_tips_of_day(config& tips_of_day) { tips_of_day.clear(); LOG_CF << "Loading tips of day\n"; try { scoped_istream stream = preprocess_file(get_wml_location("hardwired/tips.cfg")); read(tips_of_day, *stream); } catch(config::error&) { ERR_CF << "Could not read data/hardwired/tips.cfg\n"; } //We shuffle the tips after each initial loading. config::const_child_itors itors = tips_of_day.child_range("tip"); if (itors.first != itors.second ) { std::vector<config> tips(itors.first, itors.second); std::random_shuffle(tips.begin(), tips.end()); tips_of_day.clear(); foreach (const config &tip, tips) { tips_of_day.add_child("tip", tip); }
game_display* game_display::create_dummy_display(CVideo& video) { static unit_map dummy_umap; static config dummy_cfg; static gamemap dummy_map(dummy_cfg, ""); static gamestatus dummy_status(dummy_cfg, 0); static std::vector<team> dummy_teams; dummy_cfg.clear(); return new game_display(dummy_umap, video, dummy_map, dummy_status, dummy_teams, dummy_cfg, dummy_cfg, dummy_cfg); }
/** Read the file with the tips-of-the-day. */ static void read_tips_of_day(config& tips_of_day) { loadscreen::global_loadscreen->disable_increments = true; tips_of_day.clear(); #ifdef FREE_VERSION std::string filename = get_cache_dir() + "/tips_free"; #else std::string filename = get_cache_dir() + "/tips"; #endif std::string checkFilename = filename + ".cache.dat"; if (!file_exists(checkFilename)) { try { #ifdef FREE_VERSION scoped_istream stream = preprocess_file(get_wml_location("hardwired/tips_free.cfg")); #else scoped_istream stream = preprocess_file(get_wml_location("hardwired/tips.cfg")); #endif read(tips_of_day, *stream); } catch(config::error&) { // ERR_CONFIG << "Could not read data/hardwired/tips.cfg\n"; } tips_of_day.saveCache(filename); } else { tips_of_day.loadCache(filename); } //we shuffle the tips after each initial loading. We only shuffle if //the upload_log preference has been set. If it hasn't been set, it's the //user's first time playing since this feature has been added, so we'll //leave the tips in their default order, which will always contain a tip //regarding the upload log first, so the user sees it. config::child_itors tips = tips_of_day.child_range("tip"); if (tips.first != tips.second && preferences::has_upload_log()) { std::random_shuffle(tips.first, tips.second); } //Make sure that the upload log preference is set, if it's not already, so //that we know next time we've already seen the message about uploads. if(!preferences::has_upload_log()) { //preferences::set_upload_log(preferences::upload_log()); preferences::set_upload_log(false); } loadscreen::global_loadscreen->disable_increments = false; }
const config& load_campagin_scenario(const std::string& campaign_id, const std::string& scenario_id, const std::string& type) { config campaign_cfg; static config scenario_cfg; if (!scenario_id.empty() && scenario_id != "null") { wml_config_from_file(game_config::path + "/xwml/campaigns/" + campaign_id + ".bin", campaign_cfg); scenario_cfg = campaign_cfg.find_child(type, "id", scenario_id); } else { scenario_cfg.clear(); } return scenario_cfg; }
/** Read the file with the tips-of-the-day. */ void read_tips_of_day(config& tips_of_day) { tips_of_day.clear(); LOG_CF << "Loading tips of day\n"; try { scoped_istream stream = preprocess_file(get_wml_location("hardwired/tips.cfg")); read(tips_of_day, *stream); } catch(config::error&) { ERR_CF << "Could not read data/hardwired/tips.cfg\n"; } //we shuffle the tips after each initial loading. We only shuffle if //the upload_log preference has been set. If it hasn't been set, it's the //user's first time playing since this feature has been added, so we'll //leave the tips in their default order, which will always contain a tip //regarding the upload log first, so the user sees it. config::const_child_itors itors = tips_of_day.child_range("tip"); if (itors.first != itors.second && preferences::has_upload_log()) { std::vector<config> tips(itors.first, itors.second); std::random_shuffle(tips.begin(), tips.end()); tips_of_day.clear(); foreach (const config &tip, tips) { tips_of_day.add_child("tip", tip); }
bool addons_client::request_addons_list(config& cfg) { cfg.clear(); config response_buf; /** @todo FIXME: get rid of this legacy "campaign"/"campaigns" silliness */ this->send_simple_request("request_campaign_list", response_buf); this->wait_for_transfer_done(_("Downloading list of add-ons...")); cfg = response_buf.child("campaigns"); return !this->update_last_error(response_buf); }
static void enter_connect_mode(game_display& disp, const config& game_config, hero_map& heros, hero_map& heros_start, card_map& cards, config& gamelist, const mp_game_settings& params, const int num_turns, mp::controller default_controller, bool local_players_only = false) { mp::ui::result res; game_state state; const network::manager net_manager(1,1); network_game_manager m; gamelist.clear(); statistics::fresh_stats(); // if (gui2::new_widgets) { gui2::tmp_side_creator dlg(heros, disp, *resources::game_map, game_config, gamelist, params, num_turns, default_controller, local_players_only); dlg.show(disp.video()); switch (dlg.get_legacy_result()) { case gui2::tmp_side_creator::PLAY: res = mp::ui::PLAY; dlg.start_game(); state = dlg.get_state(); // lobby may modify hero's side_feature heros_start = heros; break; case gui2::tmp_side_creator::CREATE: res = mp::ui::CREATE; break; default: res = mp::ui::QUIT; } switch (res) { case mp::ui::PLAY: play_game(disp, state, game_config, heros, heros_start, cards, IO_SERVER); recorder.clear(); break; case mp::ui::CREATE: enter_create_mode(disp, game_config, heros, heros_start, cards, gamelist, default_controller, local_players_only); break; case mp::ui::QUIT: default: network::send_data(config("refresh_lobby"), 0); break; } }
bool addons_client::download_addon(config& archive_cfg, const std::string& id, const std::string& title) { archive_cfg.clear(); config request_buf; request_buf.add_child("request_campaign")["name"] = id; utils::string_map i18n_symbols; i18n_symbols["addon_title"] = title; LOG_ADDONS << "downloading " << id << '\n'; this->send_request(request_buf, archive_cfg); this->wait_for_transfer_done(vgettext("Downloading add-on <i>$addon_title</i>...", i18n_symbols)); return !this->update_last_error(archive_cfg); }
static void enter_wait_mode(game_display& disp, const config& game_config, mp::chat& chat, config& gamelist, bool observe) { mp::ui::result res; game_state state; network_game_manager m; upload_log nolog(false); gamelist.clear(); statistics::fresh_stats(); { mp::wait ui(disp, game_config, chat, gamelist); ui.join_game(observe); run_lobby_loop(disp, ui); res = ui.get_result(); if (res == mp::ui::PLAY) { ui.start_game(); // FIXME commented a pointeless if since the else does exactly the same thing //if (preferences::skip_mp_replay()){ //FIXME implement true skip replay //state = ui.request_snapshot(); //state = ui.get_state(); //} //else{ state = ui.get_state(); //} } } switch (res) { case mp::ui::PLAY: play_game(disp, state, game_config, nolog, IO_CLIENT, preferences::skip_mp_replay() && observe); recorder.clear(); break; case mp::ui::QUIT: default: break; } }
static void enter_connect_mode(game_display& disp, const config& game_config, mp::chat& chat, config& gamelist, const mp_game_settings& params, const int num_turns, mp::controller default_controller, bool local_players_only = false) { mp::ui::result res; game_state state; const network::manager net_manager(1,1); network_game_manager m; upload_log nolog(false); gamelist.clear(); statistics::fresh_stats(); { mp::connect ui(disp, game_config, chat, gamelist, params, num_turns, default_controller, local_players_only); run_lobby_loop(disp, ui); res = ui.get_result(); // start_game() updates the parameters to reflect game start, // so it must be called before get_level() if (res == mp::ui::PLAY) { ui.start_game(); state = ui.get_state(); } } switch (res) { case mp::ui::PLAY: play_game(disp, state, game_config, nolog, IO_SERVER); recorder.clear(); break; case mp::ui::CREATE: enter_create_mode(disp, game_config, chat, gamelist, default_controller, local_players_only); break; case mp::ui::QUIT: default: network::send_data(config("refresh_lobby"), 0, true); break; } }
bool addons_client::download_addon(config& archive_cfg, const std::string& id, const std::string& title, bool increase_downloads) { archive_cfg.clear(); config request_buf; config& request_body = request_buf.add_child("request_campaign"); request_body["name"] = id; request_body["increase_downloads"] = increase_downloads; utils::string_map i18n_symbols; i18n_symbols["addon_title"] = font::escape_text(title); LOG_ADDONS << "downloading " << id << '\n'; this->send_request(request_buf, archive_cfg); this->wait_for_transfer_done(VGETTEXT("Downloading add-on <i>$addon_title</i>...", i18n_symbols)); return !this->update_last_error(archive_cfg); }
void manager::read_save_file(const std::string& name, config& cfg, std::string* error_log) { std::string modified_name = name; replace_space2underbar(modified_name); // Try reading the file both with and without underscores, if needed append .gz as well scoped_istream file_stream = istream_file(get_saves_dir() + "/" + modified_name); if (file_stream->fail()) { file_stream = istream_file(get_saves_dir() + "/" + name); } if(file_stream->fail() && !is_gzip_file(modified_name)) { file_stream = istream_file(get_saves_dir() + "/" + modified_name + ".gz"); if (file_stream->fail()) { file_stream = istream_file(get_saves_dir() + "/" + name + ".gz"); } modified_name += ".gz"; } cfg.clear(); try{ /* * Test the modified name, since it might use a .gz * file even when not requested. */ if(is_gzip_file(modified_name)) { read_gz(cfg, *file_stream); } else { read(cfg, *file_stream); } } catch (config::error &err) { LOG_SAVE << err.message; if (error_log) *error_log += err.message; throw game::load_game_failed(); } if(cfg.empty()) { LOG_SAVE << "Could not parse file data into config\n"; throw game::load_game_failed(); } }
void wml_config_from_file(const std::string &fname, config &cfg, uint32_t* nfiles, uint32_t* sum_size, uint32_t* modified) { posix_file_t fp = INVALID_FILE; uint32_t datalen, fsizelow, fsizehigh, max_str_len, bytertd, tdcnt, idx, len; uint8_t *data = NULL, *namebuf = NULL, *valbuf = NULL; char tdname[MAXLEN_TEXTDOMAIN + 1]; std::vector<std::string> tdomain; posix_print("<xwml.cpp>::wml_config_from_file------fname: %s\n", fname.c_str()); cfg.clear(); // 首先清空,以下是增加方式 posix_fopen(fname.c_str(), GENERIC_READ, OPEN_EXISTING, fp); if (fp == INVALID_FILE) { posix_print("------<xwml.cpp>::wml_config_from_file, cannot create %s for read\n", fname.c_str()); goto exit; } posix_fsize(fp, fsizelow, fsizehigh); if (fsizelow <= 16) { goto exit; } posix_fseek(fp, 0, 0); posix_fread(fp, &len, 4, bytertd); // 判断是不是XWML if (len != mmioFOURCC('X', 'W', 'M', 'L')) { goto exit; } posix_fread(fp, &len, 4, bytertd); if (nfiles) { *nfiles = len; } posix_fread(fp, &len, 4, bytertd); if (sum_size) { *sum_size = len; } posix_fread(fp, &len, 4, bytertd); if (modified) { *modified = len; } posix_fread(fp, &max_str_len, sizeof(max_str_len), bytertd); // 读出po posix_fread(fp, &tdcnt, sizeof(tdcnt), bytertd); datalen = fsizelow - 16 - sizeof(max_str_len) - sizeof(tdcnt); for (idx = 0; idx < tdcnt; idx ++) { posix_fread(fp, &len, sizeof(uint32_t), bytertd); posix_fread(fp, tdname, len, bytertd); tdname[len] = 0; tdomain.push_back(tdname); datalen -= sizeof(uint32_t) + len; t_string::add_textdomain(tdomain.back(), get_intl_dir()); } data = (uint8_t *)malloc(datalen); namebuf = (uint8_t *)malloc(max_str_len + 1 + 1024); valbuf = (uint8_t *)malloc(max_str_len + 1 + 1024); // 剩下数据读出sram posix_fread(fp, data, datalen, bytertd); wml_config_from_data(data, datalen, namebuf, valbuf, tdomain, cfg); exit: if (fp != INVALID_FILE) { posix_fclose(fp); } if (data) { free(data); } if (namebuf) { free(namebuf); } if (valbuf) { free(valbuf); } return; }
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, config& economy_area) { 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; pathfind::reallocate_pq(width, height); 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"); // If the [naming] child is empty, we cannot provide good names. std::map<map_location,std::string>* misc_labels = naming.empty() ? NULL : labels; // 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; BOOST_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 && misc_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) { misc_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 && misc_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); misc_labels->erase(loc); misc_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; BOOST_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"); // tower fix const int min_x = width/3 + ((width >= 60)? 3: 1); const int min_y = height/3 + ((height >= 60)? 3: 1); const int max_x = (width/3)*2 - ((width >= 60)? 4: 1); const int max_y = (height/3)*2 - ((height >= 60)? 4: 1); 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) { 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(misc_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); misc_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(misc_labels != NULL && terrain[x][y] != letter && name_count++ == name_frequency && on_bridge == false) { misc_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. economy_area.clear(); 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; } if (!cfg["no_ea"].to_bool()) { // place economy area std::stringstream name, str; if (y > (int)height / 2) { terrain[x][y - 4] = t_translation::ECONOMY_AREA; str << "(" << x + 1 - width / 3 << "," << y - 3 - height / 3 << ")"; terrain[x + 1][y - 4] = t_translation::ECONOMY_AREA; str << "(" << x + 2 - width / 3 << "," << y - 3 - height / 3 << ")"; } else { terrain[x][y + 4] = t_translation::ECONOMY_AREA; str << "(" << x + 1 - width / 3 << "," << y + 5 - height / 3 << ")"; terrain[x + 1][y + 4] = t_translation::ECONOMY_AREA; str << "(" << x + 2 - width / 3 << "," << y + 5 - height / 3 << ")"; } name << "economy_area" << player; economy_area[name.str()] = str.str(); } // 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) */ if ( misc_labels != NULL ) { 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); } misc_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, misc_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, misc_labels, name); } } }//for (y) }//for (x) }//if (misc_labels) // don't process, remark villages nvillages = 0; if (nvillages > 0) { config naming_cfg = cfg.child_or_empty("village_naming"); // If the [village_naming] child is empty, we cannot provide good names. std::map<map_location,std::string>* village_labels = naming_cfg.empty() ? NULL : labels; // 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 ( village_labels != NULL ) { 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); village_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); }
void set_about(const config &cfg) { about_list.clear(); images.clear(); images_default = ""; for (const config &about : cfg.child_range("about")) { about_list.add_child("about", about); const std::string &im = about["images"]; if (!images.empty()) { if (images_default.empty()) images_default = im; else images_default += ',' + im; } } for (const config &campaign : cfg.child_range("campaign")) { config::const_child_itors abouts = campaign.child_range("about"); if (abouts.first == abouts.second) continue; config temp; std::ostringstream text; const std::string &id = campaign["id"]; temp["title"] = campaign["name"]; temp["id"] = id; std::string campaign_images; for (const config &about : abouts) { const std::string &subtitle = about["title"]; if (!subtitle.empty()) { text << '+'; if (subtitle[0] == '_') text << translation::gettext(subtitle.substr(1, subtitle.size() - 1).c_str()); else text << subtitle; text << '\n'; } for (const std::string &line : utils::split(about["text"], '\n')) { text << " " << line << '\n'; } for (const config &entry : about.child_range("entry")) { text << " " << entry["name"] << '\n'; } const std::string &im = about["images"]; if (!im.empty()) { if (campaign_images.empty()) campaign_images = im; else campaign_images += ',' + im; } } images[id] = campaign_images; temp["text"] = text.str(); about_list.add_child("about",temp); } }
static network::connection network_data_dialog(display& disp, const std::string& msg, config& cfg, network::connection connection_num, network::statistics (*get_stats)(network::connection handle)) { const size_t width = 300; const size_t height = 80; const size_t border = 20; const int left = disp.w()/2 - width/2; const int top = disp.h()/2 - height/2; const events::event_context dialog_events_context; gui::button cancel_button(disp.video(),_("Cancel")); std::vector<gui::button*> buttons_ptr(1,&cancel_button); gui::dialog_frame frame(disp.video(), msg, gui::dialog_frame::default_style, true, &buttons_ptr); SDL_Rect centered_layout = frame.layout(left,top,width,height).interior; centered_layout.x = disp.w() / 2 - centered_layout.w / 2; centered_layout.y = disp.h() / 2 - centered_layout.h / 2; // HACK: otherwise we get an empty useless space in the dialog below the progressbar centered_layout.h = height; frame.layout(centered_layout); frame.draw(); const SDL_Rect progress_rect = create_rect(centered_layout.x + border , centered_layout.y + border , centered_layout.w - border * 2 , centered_layout.h - border * 2); gui::progress_bar progress(disp.video()); progress.set_location(progress_rect); events::raise_draw_event(); disp.flip(); network::statistics old_stats = get_stats(connection_num); cfg.clear(); for(;;) { const network::connection res = network::receive_data(cfg,connection_num,100); const network::statistics stats = get_stats(connection_num); if(stats.current_max != 0 && stats != old_stats) { old_stats = stats; progress.set_progress_percent((stats.current*100)/stats.current_max); std::ostringstream stream; stream << stats.current/1024 << "/" << stats.current_max/1024 << _("KB"); progress.set_text(stream.str()); } events::raise_draw_event(); disp.flip(); events::pump(); if(res != 0) { return res; } if(cancel_button.pressed()) { return res; } } }