void get_tiles_radius(gamemap const &map, std::vector<map_location> const &locs, size_t radius, std::set<map_location> &res, xy_pred *pred) { typedef std::set<map_location> location_set; location_set not_visited(locs.begin(), locs.end()), must_visit, filtered_out; ++radius; for(;;) { location_set::const_iterator it = not_visited.begin(), it_end = not_visited.end(); std::copy(it,it_end,std::inserter(res,res.end())); for(; it != it_end; ++it) { map_location adj[6]; get_adjacent_tiles(*it, adj); for(size_t i = 0; i != 6; ++i) { map_location const &loc = adj[i]; if(map.on_board(loc) && !res.count(loc) && !filtered_out.count(loc)) { if(!pred || (*pred)(loc)) { must_visit.insert(loc); } else { filtered_out.insert(loc); } } } } if(--radius == 0 || must_visit.empty()) { break; } not_visited.swap(must_visit); must_visit.clear(); } }
/** * Clears shroud (and fog) at the provided location and its immediate neighbors. * This is an aid for the [teleport] action, allowing the destination to be * cleared before teleporting, while the unit's full visual range gets cleared * after. * The @a viewer is needed for correct firing of sighted events. * * @return whether or not information was uncovered (i.e. returns true if the * locations in question were fogged/shrouded under shared vision/maps). */ bool shroud_clearer::clear_dest(const map_location &dest, const unit &viewer) { team & viewing_team = resources::gameboard->get_team(viewer.side()); // A pair of dummy variables needed to simplify some logic. std::size_t enemies, friends; // Abort if there is nothing to clear. if ( !viewing_team.fog_or_shroud() ) return false; // Cache some values. const map_location & real_loc = viewer.get_location(); const std::size_t viewer_id = viewer.underlying_id(); // Clear the destination. bool cleared_something = clear_loc(viewing_team, dest, dest, real_loc, viewer_id, true, enemies, friends); // Clear the adjacent hexes (will be seen even if vision is 0, and the // graphics do not work so well for an isolated cleared hex). adjacent_loc_array_t adjacent; get_adjacent_tiles(dest, adjacent.data()); for (unsigned i = 0; i < adjacent.size(); ++i ) if ( clear_loc(viewing_team, adjacent[i], dest, real_loc, viewer_id, true, enemies, friends) ) cleared_something = true; if ( cleared_something ) invalidate_after_clear(); return cleared_something; }
time_of_day tod_manager::time_of_day_at(const unit_map& units,const map_location& loc, const gamemap& map) const { int lighten = std::max<int>(map.get_terrain_info(map.get_terrain(loc)).light_modification() , 0); int darken = std::min<int>(map.get_terrain_info(map.get_terrain(loc)).light_modification() , 0); time_of_day tod = get_time_of_day(lighten + darken,loc); if(loc.valid()) { map_location locs[7]; locs[0] = loc; get_adjacent_tiles(loc,locs+1); for(int i = 0; i != 7; ++i) { const unit_map::const_iterator itor = units.find(locs[i]); if(itor != units.end() && itor->second.get_ability_bool("illuminates") && !itor->second.incapacitated()) { unit_ability_list illum = itor->second.get_abilities("illuminates"); unit_abilities::effect illum_effect(illum,lighten,false); int mod = illum_effect.get_composite_value(); if(mod + tod.lawful_bonus > illum.highest("max_value").first) { mod = illum.highest("max_value").first - tod.lawful_bonus; } lighten = std::max<int>(mod, lighten); darken = std::min<int>(mod, darken); } } } tod = get_time_of_day(lighten + darken,loc); return tod; }
bool display_context::would_be_discovered(const map_location & loc, int side_num, bool see_all) { map_location adjs[6]; get_adjacent_tiles(loc,adjs); for (const map_location &u_loc : adjs) { unit_map::const_iterator u_it = units().find(u_loc); if (!u_it.valid()) { continue; } const unit & u = *u_it; if (get_team(side_num).is_enemy(u.side()) && !u.incapacitated()) { // Enemy spotted in adjacent tiles, check if we can see him. // Watch out to call invisible with see_all=true to avoid infinite recursive calls! if(see_all) { return true; } else if (!get_team(side_num).fogged(u_loc) && !u.invisible(u_loc, *this, true)) { return true; } } } return false; }
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]); } }
bool display_context::unit_can_move(const unit &u) const { if(!u.attacks_left() && u.movement_left()==0) return false; // Units with goto commands that have already done their gotos this turn // (i.e. don't have full movement left) should have red globes. if(u.has_moved() && u.has_goto()) { return false; } const team ¤t_team = get_team(u.side()); map_location locs[6]; get_adjacent_tiles(u.get_location(), locs); for(int n = 0; n != 6; ++n) { if (map().on_board(locs[n])) { const unit_map::const_iterator i = units().find(locs[n]); if (i.valid() && !i->incapacitated() && current_team.is_enemy(i->side())) { return true; } if (u.movement_cost(map()[locs[n]]) <= u.movement_left()) { return true; } } } return false; }
// "flood fill" a tile name to adjacent tiles of certain terrain 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) { map_location adj[6]; get_adjacent_tiles(start,adj); size_t n; //if adjacent tiles are tiles and unnamed, name them for (n = 0; n < 6; n++) { //we do not care for tiles outside the middle part //cast to unsigned to skip x < 0 || y < 0 as well. if (unsigned(adj[n].x) >= width / 3 || unsigned(adj[n].y) >= height / 3) { continue; } const t_translation::t_terrain terr = terrain[adj[n].x + (width / 3)][adj[n].y + (height / 3)]; const location loc(adj[n].x, adj[n].y); if((t_translation::terrain_matches(terr, tile_types)) && (tile_names.find(loc) == tile_names.end())) { tile_names.insert(std::pair<location, std::string>(loc, name)); //labeling decision: this is result of trial and error on what looks best in game if (label_count % 6 == 0) { //ensure that labels do not occur more often than every 6 recursions labels->insert(std::pair<map_location, std::string>(loc, full_name)); label_count++; //ensure that no adjacent tiles get labeled } flood_name(adj[n], name, tile_names, tile_types, terrain, width, height, label_count++, labels, full_name); } } }
bool can_generate(const gamemap& map, const std::vector<team>& teams, const unit_map& units, const unit& u, const map_location& loc) { if (!map.on_board(loc)) { return false; } if (u.movement_cost(map[loc]) == unit_movement_type::UNREACHABLE) { return false; } unit_map::const_iterator it = units.find(loc, false); if (it.valid() && !it->can_stand(u)) { return false; } map_location locs[6]; get_adjacent_tiles(loc, locs); for (int i = 0; i != 6; ++i) { if (!map.on_board(locs[i])) { continue; } if (u.movement_cost(map[locs[i]]) != unit_movement_type::UNREACHABLE) { return true; } } return false; }
bool backstab_check(const map_location& attacker_loc, const map_location& defender_loc, const unit_map& units, const std::vector<team>& teams) { const unit_map::const_iterator defender = units.find(defender_loc); if(defender == units.end()) return false; // No defender map_location adj[6]; get_adjacent_tiles(defender_loc, adj); int i; for(i = 0; i != 6; ++i) { if(adj[i] == attacker_loc) break; } if(i >= 6) return false; // Attack not from adjacent location const unit_map::const_iterator opp = units.find(adj[(i+3)%6]); if(opp == units.end()) return false; // No opposite unit if (opp->incapacitated()) return false; if (size_t(defender->side() - 1) >= teams.size() || size_t(opp->side() - 1) >= teams.size()) return true; // If sides aren't valid teams, then they are enemies if (teams[defender->side() - 1].is_enemy(opp->side())) return true; // Defender and opposite are enemies return false; // Defender and opposite are friends }
static void move_unit_between(const map_location& a, const map_location& b, unit& temp_unit,unsigned int step_num,unsigned int step_left) { game_display* disp = game_display::get_singleton(); if(!disp || disp->video().update_locked() || disp->video().faked() || (disp->fogged(a) && disp->fogged(b))) { return; } temp_unit.set_location(a); disp->invalidate(temp_unit.get_location()); temp_unit.set_facing(a.get_relative_dir(b)); unit_animator animator; animator.replace_anim_if_invalid(&temp_unit,"movement",a,b,step_num, false,"",0,unit_animation::INVALID,NULL,NULL,step_left); animator.start_animations(); animator.pause_animation(); disp->scroll_to_tiles(a,b,game_display::ONSCREEN,true,0.0,false); animator.restart_animation(); // useless now, previous short draw() just did one // new_animation_frame(); int target_time = animator.get_animation_time_potential(); // target_time must be short to avoid jumpy move // std::cout << "target time: " << target_time << "\n"; // we round it to the next multile of 200 target_time += 200; target_time -= target_time%200; // This code causes backwards teleport because the time > 200 causes offset > 1.0 // which will not match with the following -1.0 // if( target_time - animator.get_animation_time_potential() < 100 ) target_time +=200; animator.wait_until(target_time); // debug code, see unit_frame::redraw() // std::cout << " end\n"; map_location arr[6]; get_adjacent_tiles(a, arr); unsigned int i; for (i = 0; i < 6; ++i) { disp->invalidate(arr[i]); } get_adjacent_tiles(b, arr); for (i = 0; i < 6; ++i) { disp->invalidate(arr[i]); } }
void terrain_analyze::get_village_terrain() { BOOST_FOREACH(const map_location& loc, village_location_) { map_location adj[6]; get_adjacent_tiles(loc,adj); for(int i = 0; i < 6; i++) { add_village_battle(loc, adj[i]); } }
/** * River generation. * * Rivers have a source, and then keep on flowing until they meet another body * of water, which they flow into, or until they reach the edge of the map. * Rivers will always flow downhill, except that they can flow a maximum of * 'river_uphill' uphill. This is to represent the water eroding the higher * ground lower. * * Every possible path for a river will be attempted, in random order, and the * first river path that can be found that makes the river flow into another * body of water or off the map will be used. * * If no path can be found, then the river's generation will be aborted, and * false will be returned. true is returned if the river is generated * successfully. */ static bool generate_river_internal(const height_map& heights, terrain_map& terrain, int x, int y, std::vector<location>& river, std::set<location>& seen_locations, int river_uphill) { const bool on_map = x >= 0 && y >= 0 && x < static_cast<long>(heights.size()) && y < static_cast<long>(heights.back().size()); if(on_map && !river.empty() && heights[x][y] > heights[river.back().x][river.back().y] + river_uphill) { return false; } // If we're at the end of the river if(!on_map || terrain[x][y] == t_translation::SHALLOW_WATER || terrain[x][y] == t_translation::DEEP_WATER) { LOG_NG << "generating river...\n"; // Generate the river for(std::vector<location>::const_iterator i = river.begin(); i != river.end(); ++i) { terrain[i->x][i->y] = t_translation::SHALLOW_WATER; } LOG_NG << "done generating river\n"; return true; } location current_loc(x,y); location adj[6]; get_adjacent_tiles(current_loc,adj); static int items[6] = {0,1,2,3,4,5}; std::random_shuffle(items,items+4); // Mark that we have attempted from this location seen_locations.insert(current_loc); river.push_back(current_loc); for(int a = 0; a != 6; ++a) { const location& loc = adj[items[a]]; if(seen_locations.count(loc) == 0) { const bool res = generate_river_internal(heights,terrain,loc.x,loc.y,river,seen_locations,river_uphill); if(res) { return true; } } } river.pop_back(); return false; }
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) { const map_location loc(x,y); std::set<map_location> locs; get_tiles_radius(loc,radius,locs); map_location best_loc; int best_rating = 0; for(std::set<map_location>::const_iterator i = locs.begin(); i != locs.end(); ++i) { if(i->x < 0 || i->y < 0 || i->x >= static_cast<long>(map.size()) || i->y >= static_cast<long>(map[i->x].size())) { continue; } const t_translation::t_terrain t = map[i->x][i->y]; const std::string str = t_translation::write_terrain_code(t); if (const config &child = cfg.find_child("village", "terrain", str)) { tcode_list_cache::iterator l = adj_liked_cache.find(t); t_translation::t_list *adjacent_liked; if (l != adj_liked_cache.end()) { adjacent_liked = &(l->second); } else { adj_liked_cache[t] = t_translation::read_list(child["adjacent_liked"]); adjacent_liked = &(adj_liked_cache[t]); } int rating = child["rating"]; map_location adj[6]; get_adjacent_tiles(map_location(i->x,i->y),adj); for(size_t n = 0; n != 6; ++n) { if(adj[n].x < 0 || adj[n].y < 0 || adj[n].x >= static_cast<long>(map.size()) || adj[n].y >= static_cast<long>(map[adj[n].x].size())) { continue; } const t_translation::t_terrain t2 = map[adj[n].x][adj[n].y]; rating += std::count(adjacent_liked->begin(),adjacent_liked->end(),t2); } if(rating > best_rating) { best_loc = map_location(i->x,i->y); best_rating = rating; } } } return best_loc; }
boost::shared_ptr<attacks_vector> aspect_attacks::analyze_targets() const { const move_map& srcdst = get_srcdst(); const move_map& dstsrc = get_dstsrc(); const move_map& enemy_srcdst = get_enemy_srcdst(); const move_map& enemy_dstsrc = get_enemy_dstsrc(); boost::shared_ptr<attacks_vector> res(new attacks_vector()); unit_map& units_ = *resources::units; std::vector<map_location> unit_locs; for(unit_map::const_iterator i = units_.begin(); i != units_.end(); ++i) { if (i->side() == get_side() && i->attacks_left() && !(i->can_recruit() && get_passive_leader())) { if (!i->matches_filter(vconfig(filter_own_), i->get_location())) { continue; } unit_locs.push_back(i->get_location()); } } bool used_locations[6]; std::fill(used_locations,used_locations+6,false); moves_map dummy_moves; move_map fullmove_srcdst, fullmove_dstsrc; calculate_possible_moves(dummy_moves,fullmove_srcdst,fullmove_dstsrc,false,true); unit_stats_cache().clear(); for(unit_map::const_iterator j = units_.begin(); j != units_.end(); ++j) { // Attack anyone who is on the enemy side, // and who is not invisible or petrified. if (current_team().is_enemy(j->side()) && !j->incapacitated() && !j->invisible(j->get_location())) { if (!j->matches_filter(vconfig(filter_enemy_), j->get_location())) { continue; } map_location adjacent[6]; get_adjacent_tiles(j->get_location(), adjacent); attack_analysis analysis; analysis.target = j->get_location(); analysis.vulnerability = 0.0; analysis.support = 0.0; do_attack_analysis(j->get_location(), srcdst, dstsrc, fullmove_srcdst, fullmove_dstsrc, enemy_srcdst, enemy_dstsrc, adjacent,used_locations,unit_locs,*res,analysis, current_team()); } } return res; }
bool default_map_generator_job::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) { const bool on_map = x >= 0 && y >= 0 && x < static_cast<long>(heights.size()) && y < static_cast<long>(heights.back().size()); if(on_map && !river.empty() && heights[x][y] > heights[river.back().x][river.back().y] + river_uphill) { return false; } // If we're at the end of the river if(!on_map || terrain[x][y] == t_translation::SHALLOW_WATER || terrain[x][y] == t_translation::DEEP_WATER) { LOG_NG << "generating river...\n"; // Generate the river for(auto i : river) { terrain[i.x][i.y] = t_translation::SHALLOW_WATER; } LOG_NG << "done generating river\n"; return true; } map_location current_loc(x,y); map_location adj[6]; get_adjacent_tiles(current_loc,adj); std::shuffle(std::begin(adj), std::end(adj), rng_); // Mark that we have attempted from this map_location seen_locations.insert(current_loc); river.push_back(current_loc); for(const map_location& loc : adj) { if(seen_locations.count(loc) == 0) { const bool res = generate_river_internal(heights,terrain,loc.x,loc.y,river,seen_locations,river_uphill); if(res) { return true; } } } river.pop_back(); return false; }
/** * Expose map_location get_adjacent_tiles */ int intf_get_adjacent_tiles(lua_State* L) { map_location l1 = pop_map_location(L); map_location locs[6]; get_adjacent_tiles(l1, locs); for (int i = 0; i < 6; ++i) { push_map_location(L, locs[i]); } return 12; }
map_location pathfind::find_vacant_tile(const gamemap& map, const unit_map& units, const map_location& loc, pathfind::VACANT_TILE_TYPE vacancy, const unit* pass_check) { if (!map.on_board(loc)) return map_location(); std::set<map_location> pending_tiles_to_check, tiles_checked; pending_tiles_to_check.insert(loc); // Iterate out 50 hexes from loc for (int distance = 0; distance < 50; ++distance) { if (pending_tiles_to_check.empty()) return map_location(); //Copy over the hexes to check and clear the old set std::set<map_location> tiles_checking; tiles_checking.swap(pending_tiles_to_check); //Iterate over all the hexes we need to check foreach (const map_location &loc, tiles_checking) { //If this area is not a castle but should, skip it. if (vacancy == pathfind::VACANT_CASTLE && !map.is_castle(loc)) continue; const bool pass_check_and_unreachable = pass_check && pass_check->movement_cost(map[loc]) == unit_movement_type::UNREACHABLE; //If the unit can't reach the tile and we have searched //an area of at least radius 10 (arbitrary), skip the tile. //Neccessary for cases such as an unreachable //starting hex surrounded by 6 other unreachable hexes, in which case //the algorithm would not even search distance==1 //even if there's a reachable hex for distance==2. if (pass_check_and_unreachable && distance > 10) continue; //If the hex is empty and we do either no pass check or the hex is reachable, return it. if (units.find(loc) == units.end() && !pass_check_and_unreachable) return loc; map_location adjs[6]; get_adjacent_tiles(loc,adjs); foreach (const map_location &loc, adjs) { if (!map.on_board(loc)) continue; // Add the tile to be checked if it hasn't already been and // isn't being checked. if (tiles_checked.find(loc) == tiles_checked.end() && tiles_checking.find(loc) == tiles_checking.end()) { pending_tiles_to_check.insert(loc); } } } tiles_checked.swap(tiles_checking); } return map_location(); }
void cave_map_generator::cave_map_generator_job::build_chamber(map_location loc, std::set<map_location>& locs, size_t size, size_t jagged) { if(size == 0 || locs.count(loc) != 0 || !params.on_board(loc)) return; locs.insert(loc); map_location adj[6]; get_adjacent_tiles(loc,adj); for(size_t n = 0; n != 6; ++n) { if(int(rng_() % 100) < (100l - static_cast<long>(jagged))) { build_chamber(adj[n],locs,size-1,jagged); } } }
/** * Expose map_location get_adjacent_tiles */ int intf_get_adjacent_tiles(lua_State* L) { map_location l1; if(!luaW_tolocation(L, 1, l1)) { return luaL_argerror(L, 1, "expected a location"); } map_location locs[6]; get_adjacent_tiles(l1, locs); for (int i = 0; i < 6; ++i) { luaW_pushlocation(L, locs[i]); } return 6; }
void cave_map_generator::place_castle(int starting_position, const map_location &loc) { if (starting_position != -1) { set_terrain(loc, keep_); t_translation::coordinate coord = { loc.x + gamemap::default_border, loc.y + gamemap::default_border }; starting_positions_[starting_position] = coord; } map_location adj[6]; get_adjacent_tiles(loc,adj); for(size_t n = 0; n != 6; ++n) { set_terrain(adj[n],castle_); } }
void tile::calculate_corner(int n) { const DIRECTION neighbour_a = static_cast<DIRECTION>(n); const DIRECTION neighbour_b = static_cast<DIRECTION>((n+1)%6); const int point_a = (n+2)%6; const int point_b = (n+4)%6; const tile* adja = neighbours_[neighbour_a]; const tile* adjb = neighbours_[neighbour_b]; if(adja != NULL && adja->corners_[point_a].init) { corners_[n] = adja->corners_[point_a]; return; } if(adjb != NULL && adjb->corners_[point_b].init) { corners_[n] = adjb->corners_[point_b]; return; } location adj[6]; get_adjacent_tiles(loc_,adj); corners_[n].position.x() = (translate_x(loc_) + translate_x(adj[neighbour_a]) + translate_x(adj[neighbour_b]))/3.0; corners_[n].position.y() = (translate_y(loc_) + translate_y(adj[neighbour_a]) + translate_y(adj[neighbour_b]))/3.0; int sum = height_; int num = 1; if(adja != NULL) { sum += adja->height_; ++num; } if(adjb != NULL) { sum += adjb->height_; ++num; } sum /= num; corners_[n].position.z() = translate_height(sum); corners_[n].init = true; }
const time_of_day tod_manager::get_illuminated_time_of_day(const map_location& loc, int for_turn) const { // get ToD ignoring illumination time_of_day tod = get_time_of_day(loc, for_turn); // now add illumination const gamemap& map = *resources::game_map; const unit_map& units = *resources::units; int light_modif = map.get_terrain_info(map.get_terrain(loc)).light_modification(); int light = tod.lawful_bonus + light_modif; int illum_light = light; if(loc.valid()) { map_location locs[7]; locs[0] = loc; get_adjacent_tiles(loc,locs+1); for(int i = 0; i != 7; ++i) { const unit_map::const_iterator itor = units.find(locs[i]); if(itor != units.end() && itor->get_ability_bool("illuminates") && !itor->incapacitated()) { unit_ability_list illum = itor->get_abilities("illuminates"); unit_abilities::effect illum_effect(illum, light, false); illum_light = light + illum_effect.get_composite_value(); //max_value and min_value control the final result //unless ToD + terrain effect is stronger int max = std::max(light, illum.highest("max_value").first); int min = std::min(light, illum.lowest("min_value").first); if(illum_light > max) { illum_light = max; } else if (illum_light < min) { illum_light = min; } } } } tod.bonus_modified = illum_light - tod.lawful_bonus; tod.lawful_bonus = illum_light; return tod; }
map_location find_vacant_tile(const gamemap& map, const unit_map& units, const map_location& loc, VACANT_TILE_TYPE vacancy, const unit* pass_check) { std::set<map_location> pending_tiles_to_check; std::set<map_location> tiles_checked; pending_tiles_to_check.insert( loc ); // Iterate out 50 hexes from loc for (int distance = 0; distance < 50; ++distance) { if (pending_tiles_to_check.empty()) return map_location(); //Copy over the hexes to check and clear the old set std::set<map_location> tiles_checking = pending_tiles_to_check; std::set<map_location>::const_iterator tc_itor = tiles_checking.begin(); pending_tiles_to_check.clear(); //Iterate over all the hexes we need to check for ( ; tc_itor != tiles_checking.end(); ++tc_itor ) { //If the unit cannot reach this area or it's not a castle but should, skip it. if ((vacancy == VACANT_CASTLE && !map.is_castle(*tc_itor)) || (pass_check && pass_check->movement_cost(map[*tc_itor]) == unit_movement_type::UNREACHABLE)) continue; //If the hex is empty, return it. if (map.on_board(*tc_itor) && units.find(*tc_itor) == units.end()) return (*tc_itor); map_location adjs[6]; get_adjacent_tiles(*tc_itor,adjs); for (int i = 0; i != 6; ++i) { //Add the tile to be checked if it hasn't already been and isn't already //pending to be checked if (pending_tiles_to_check.find(adjs[i]) == pending_tiles_to_check.end() && tiles_checked.find(adjs[i]) == tiles_checked.end() && tiles_checking.find(adjs[i]) == tiles_checking.end()) { pending_tiles_to_check.insert(adjs[i]); } } } tiles_checked = tiles_checking; } return map_location(); }
void cave_map_generator::cave_map_generator_job::place_castle(int starting_position, const map_location &loc) { if (starting_position != -1) { set_terrain(loc, params.keep_); t_translation::coordinate coord( loc.x + gamemap::default_border , loc.y + gamemap::default_border); starting_positions_.insert(t_translation::tstarting_positions::value_type(std::to_string(starting_position), coord)); } map_location adj[6]; get_adjacent_tiles(loc,adj); for(size_t n = 0; n != 6; ++n) { set_terrain(adj[n], params.castle_); } }
map_location pathfind::find_vacant_tile(const gamemap& map, const unit_map& units, const map_location& loc, pathfind::VACANT_TILE_TYPE vacancy, const unit* pass_check) { if (!map.on_board(loc)) return map_location(); std::set<map_location> pending_tiles_to_check, tiles_checked; pending_tiles_to_check.insert(loc); // Iterate out 50 hexes from loc for (int distance = 0; distance < 50; ++distance) { if (pending_tiles_to_check.empty()) return map_location(); //Copy over the hexes to check and clear the old set std::set<map_location> tiles_checking; tiles_checking.swap(pending_tiles_to_check); //Iterate over all the hexes we need to check foreach (const map_location &loc, tiles_checking) { //If the unit cannot reach this area or it's not a castle but should, skip it. if ((vacancy == pathfind::VACANT_CASTLE && !map.is_castle(loc)) || (pass_check && pass_check->movement_cost(map[loc]) == unit_movement_type::UNREACHABLE)) continue; //If the hex is empty, return it. if (units.find(loc) == units.end()) return loc; map_location adjs[6]; get_adjacent_tiles(loc,adjs); foreach (const map_location &loc, adjs) { if (!map.on_board(loc)) continue; // Add the tile to be checked if it hasn't already been and // isn't being checked. if (tiles_checked.find(loc) == tiles_checked.end() && tiles_checking.find(loc) == tiles_checking.end()) { pending_tiles_to_check.insert(loc); } } } tiles_checked.swap(tiles_checking); } return map_location(); }
bool enemy_zoc(unit_map const &units, std::vector<team> const &teams, map_location const &loc, team const &viewing_team, int side, bool see_all) { map_location locs[6]; const team ¤t_team = teams[side-1]; get_adjacent_tiles(loc,locs); for (int i = 0; i != 6; ++i) { const unit *u = get_visible_unit(units, locs[i], viewing_team, see_all); if (u && u->side() != side && current_team.is_enemy(u->side()) && u->emits_zoc()) { return true; } } return false; }
static void get_tiles_radius_internal(const map_location& a, size_t radius, std::set<map_location>& res, std::map<map_location,int>& visited) { visited[a] = radius; res.insert(a); if(radius == 0) { return; } map_location adj[6]; get_adjacent_tiles(a,adj); for(size_t i = 0; i != 6; ++i) { if(visited.count(adj[i]) == 0 || visited[adj[i]] < int(radius)-1) { get_tiles_radius_internal(adj[i],radius-1,res,visited); } } }
void mouse_action_unit::move(editor_display& disp, const map_location& hex) { if (hex != previous_move_hex_) { update_brush_highlights(disp, hex); std::set<map_location> adjacent_set; map_location adjacent[6]; get_adjacent_tiles(previous_move_hex_, adjacent); for (int i = 0; i < 6; i++) adjacent_set.insert(adjacent[i]); disp.invalidate(adjacent_set); previous_move_hex_ = hex; const unit_map& units = disp.get_units(); const unit_map::const_unit_iterator unit_it = units.find(hex); if (unit_it != units.end()) { disp.set_mouseover_hex_overlay(NULL); SDL_Rect rect; rect.x = disp.get_location_x(hex); rect.y = disp.get_location_y(hex); rect.h = disp.hex_size(); rect.w = disp.hex_size(); std::stringstream str; str << N_("Identifier: ") << unit_it->id() << "\n" << N_("Name: ") << unit_it->name() << "\n" << N_("Type: ") << unit_it->type_name() << "\n" << N_("Level: ") << unit_it->level() << "\n" << N_("Cost: ") << unit_it->cost() << "\n" << N_("Recruit: ") << utils::join(unit_it->recruits()) << "\n"; tooltips::clear_tooltips(); tooltips::add_tooltip(rect, str.str()); } else { set_mouse_overlay(disp); } } }
void mouse_action_item::move(editor_display& disp, const map_location& hex) { if (hex != previous_move_hex_) { update_brush_highlights(disp, hex); std::set<map_location> adjacent_set; map_location adjacent[6]; get_adjacent_tiles(previous_move_hex_, adjacent); for (int i = 0; i < 6; i++) adjacent_set.insert(adjacent[i]); disp.invalidate(adjacent_set); previous_move_hex_ = hex; // const item_map& items = disp.get_items(); // const item_map::const_item_iterator item_it = items.find(hex); // if (item_it != items.end()) { // // disp.set_mouseover_hex_overlay(nullptr); // // SDL_Rect rect; // rect.x = disp.get_location_x(hex); // rect.y = disp.get_location_y(hex); // rect.h = disp.hex_size(); // rect.w = disp.hex_size(); // std::stringstream str; // str << N_("ID: ") << item_it->id() << "\n" // << N_("Name: ") << item_it->name() << "\n" // << N_("Type: ") << item_it->type_name(); // tooltips::clear_tooltips(); // tooltips::add_tooltip(rect, str.str()); // } // else { // set_mouse_overlay(disp); // } } }
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; }