void editor_map::sanity_check() { int errors = 0; if (total_width() != static_cast<int>(tiles_.size())) { ERR_ED << "total_width is " << total_width() << " but tiles_.size() is " << tiles_.size() << "\n"; ++errors; } if (total_height() != static_cast<int>(tiles_[0].size())) { ERR_ED << "total_height is " << total_height() << " but tiles_[0].size() is " << tiles_.size() << "\n"; ++errors; } if (w() + 2 * border_size() != total_width()) { ERR_ED << "h is " << h_ << " and border_size is " << border_size() << " but total_width is " << total_width() << "\n"; ++errors; } if (h() + 2 * border_size() != total_height()) { ERR_ED << "w is " << w_ << " and border_size is " << border_size() << " but total_height is " << total_height() << "\n"; ++errors; } for (size_t i = 1; i < tiles_.size(); ++i) { if (tiles_[i].size() != tiles_[0].size()) { ERR_ED << "tiles_[ " << i << "] has size() " << tiles_[i].size() << " but tiles[0] has size() " << tiles_[0].size() << "\n"; ++errors; } } BOOST_FOREACH(const map_location& loc, selection_) { if (!on_board_with_border(loc)) { ERR_ED << "Off-map tile in selection: " << loc << "\n"; } } if (errors) { throw editor_map_integrity_error(); } }
void gamemap::set_terrain(const map_location& loc, const t_translation::t_terrain & terrain, const terrain_type_data::tmerge_mode mode, bool replace_if_failed) { if(!on_board_with_border(loc)) { // off the map: ignore request return; } t_translation::t_terrain new_terrain = tdata_->merge_terrains(get_terrain(loc), terrain, mode, replace_if_failed); if(new_terrain == t_translation::NONE_TERRAIN) { return; } if(on_board(loc)) { const bool old_village = is_village(loc); const bool new_village = tdata_->is_village(new_terrain); if(old_village && !new_village) { villages_.erase(std::remove(villages_.begin(),villages_.end(),loc),villages_.end()); } else if(!old_village && new_village) { villages_.push_back(loc); } } tiles_[loc.x + border_size_][loc.y + border_size_] = new_terrain; // Update the off-map autogenerated tiles map_location adj[6]; get_adjacent_tiles(loc,adj); for(int n = 0; n < 6; ++n) { remove_from_border_cache(adj[n]); } }
void gamemap::set_terrain(const map_location& loc, const t_translation::terrain_code & terrain, const terrain_type_data::merge_mode mode, bool replace_if_failed) { if(!on_board_with_border(loc)) { DBG_G << "set_terrain: " << loc << " is not on the map.\n"; // off the map: ignore request return; } t_translation::terrain_code new_terrain = tdata_->merge_terrains(get_terrain(loc), terrain, mode, replace_if_failed); if(new_terrain == t_translation::NONE_TERRAIN) { return; } if(on_board(loc)) { const bool old_village = is_village(loc); const bool new_village = tdata_->is_village(new_terrain); if(old_village && !new_village) { villages_.erase(std::remove(villages_.begin(),villages_.end(),loc),villages_.end()); } else if(!old_village && new_village) { villages_.push_back(loc); } } (*this)[loc] = new_terrain; }
t_translation::terrain_code gamemap::get_terrain(const map_location& loc) const { if(on_board_with_border(loc)) { return (*this)[loc]; } return loc == map_location::null_location() ? t_translation::NONE_TERRAIN : t_translation::terrain_code(); }
std::set<map_location> editor_map::get_contiguous_terrain_tiles(const map_location& start) const { t_translation::t_terrain terrain = get_terrain(start); std::set<map_location> result; std::deque<map_location> queue; result.insert(start); queue.push_back(start); //this is basically a breadth-first search along adjacent hexes do { map_location adj[6]; get_adjacent_tiles(queue.front(), adj); for (int i = 0; i < 6; ++i) { if (on_board_with_border(adj[i]) && get_terrain(adj[i]) == terrain && result.find(adj[i]) == result.end()) { result.insert(adj[i]); queue.push_back(adj[i]); } } queue.pop_front(); } while (!queue.empty()); return result; }
t_translation::t_terrain gamemap::get_terrain(const map_location& loc) const { if(on_board_with_border(loc)) { return tiles_[loc.x + border_size_][loc.y + border_size_]; } if ( loc == map_location::null_location() ) { return t_translation::NONE_TERRAIN; } const std::map<map_location, t_translation::t_terrain>::const_iterator itor = borderCache_.find(loc); if(itor != borderCache_.end()) return itor->second; // If not on the board, decide based on what surrounding terrain is t_translation::t_terrain items[6]; int number_of_items = 0; map_location adj[6]; get_adjacent_tiles(loc,adj); for(int n = 0; n != 6; ++n) { if(on_board(adj[n])) { items[number_of_items] = tiles_[adj[n].x][adj[n].y]; ++number_of_items; } else { // If the terrain is off map but already in the border cache, // this will be used to determine the terrain. // This avoids glitches // * on map with an even width in the top right corner // * on map with an odd height in the bottom left corner. // It might also change the result on other map and become random, // but the border tiles will be determined in the future, so then // this will no longer be used in the game // (The editor will use this feature to expand maps in a better way). std::map<map_location, t_translation::t_terrain>::const_iterator itor = borderCache_.find(adj[n]); // Only add if it is in the cache and a valid terrain if(itor != borderCache_.end() && itor->second != t_translation::NONE_TERRAIN) { items[number_of_items] = itor->second; ++number_of_items; } } } // Count all the terrain types found, // and see which one is the most common, and use it. t_translation::t_terrain used_terrain; int terrain_count = 0; for(int i = 0; i != number_of_items; ++i) { if(items[i] != used_terrain && !tdata_->is_village(items[i]) && !tdata_->is_keep(items[i])) { const int c = std::count(items+i+1,items+number_of_items,items[i]) + 1; if(c > terrain_count) { used_terrain = items[i]; terrain_count = c; } } } borderCache_.insert(std::pair<map_location, t_translation::t_terrain>(loc,used_terrain)); return used_terrain; }
bool editor_map::add_to_selection(const map_location& loc) { return on_board_with_border(loc) ? selection_.insert(loc).second : false; }