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(); }
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(); }
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(); }