From fba6ffe4e4ea96bc00ce316e184fe178f48214e8 Mon Sep 17 00:00:00 2001 From: ZhilkinSerg Date: Thu, 16 Jan 2020 13:35:36 +0300 Subject: [PATCH 1/3] Refactored `closest_(tri)points_first` functions - moved into `point` file; - rearranged function parameters; - removed duplicate code; - get rid of some `auto` and one time use variables; --- src/activity_item_handling.cpp | 2 +- src/crafting.cpp | 5 ++- src/game.cpp | 6 ++-- src/iexamine.cpp | 6 ++-- src/inventory_ui.cpp | 2 +- src/iuse.cpp | 4 +-- src/iuse_actor.cpp | 3 +- src/iuse_software_minesweeper.cpp | 10 ++---- src/map.cpp | 59 ++----------------------------- src/map.h | 3 -- src/map_selector.cpp | 2 +- src/mapgen_functions.cpp | 3 +- src/monattack.cpp | 6 ++-- src/mondefense.cpp | 2 +- src/monmove.cpp | 2 +- src/npc.cpp | 2 +- src/npcmove.cpp | 11 +++--- src/overmap.cpp | 20 ++++++----- src/point.cpp | 36 +++++++++++++++++++ src/point.h | 9 +++++ src/ranged.cpp | 4 +-- src/start_location.cpp | 2 +- src/vehicle.cpp | 2 +- src/vehicle_selector.cpp | 4 +-- src/wish.cpp | 2 +- tests/explosion_balance_test.cpp | 2 +- tests/overmap_test.cpp | 2 +- tests/visitable_remove_test.cpp | 8 ++--- 28 files changed, 99 insertions(+), 120 deletions(-) diff --git a/src/activity_item_handling.cpp b/src/activity_item_handling.cpp index 3b01e34faea11..e6664dd4f87cb 100644 --- a/src/activity_item_handling.cpp +++ b/src/activity_item_handling.cpp @@ -2950,7 +2950,7 @@ static cata::optional find_refuel_spot_trap( const std::vector adjacent = closest_tripoints_first( pos, PICKUP_RANGE ); adjacent.erase( adjacent.begin() ); cata::optional best_fire = starting_fire ? act.placement : find_best_fire( adjacent, diff --git a/src/crafting.cpp b/src/crafting.cpp index 1f8fa71ddc652..a6dce184c6cb2 100644 --- a/src/crafting.cpp +++ b/src/crafting.cpp @@ -444,7 +444,7 @@ std::vector player::get_eligible_containers_for_crafting() const } // get all potential containers within PICKUP_RANGE tiles including vehicles - for( const auto &loc : closest_tripoints_first( PICKUP_RANGE, pos() ) ) { + for( const tripoint &loc : closest_tripoints_first( pos(), PICKUP_RANGE ) ) { // can not reach this -> can not access its contents if( pos() != loc && !g->m.clear_path( pos(), loc, PICKUP_RANGE, 1, 100 ) ) { continue; @@ -628,8 +628,7 @@ static item *set_item_inventory( player &p, item &newit ) static item_location set_item_map( const tripoint &loc, item &newit ) { // Includes loc - const std::vector tiles = closest_tripoints_first( 2, loc ); - for( const tripoint &tile : tiles ) { + for( const tripoint &tile : closest_tripoints_first( loc, 2 ) ) { // Pass false to disallow overflow, null_item_reference indicates failure. item *it_on_map = &g->m.add_item_or_charges( tile, newit, false ); if( it_on_map != &null_item_reference() ) { diff --git a/src/game.cpp b/src/game.cpp index 4a7a810a92700..61d3b9e6745bc 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -6804,9 +6804,7 @@ std::vector game::find_nearby_items( int iRadius ) return ret; } - std::vector points = closest_tripoints_first( iRadius, u.pos() ); - - for( auto &points_p_it : points ) { + for( auto &points_p_it : closest_tripoints_first( u.pos(), iRadius ) ) { if( points_p_it.y >= u.posy() - iRadius && points_p_it.y <= u.posy() + iRadius && u.sees( points_p_it ) && m.sees_some_items( points_p_it, u ) ) { @@ -10191,7 +10189,7 @@ void game::vertical_move( int movez, bool force ) if( !npcs_to_bring.empty() ) { // Would look nicer randomly scrambled - auto candidates = closest_tripoints_first( 1, u.pos() ); + std::vector candidates = closest_tripoints_first( u.pos(), 1 ); std::remove_if( candidates.begin(), candidates.end(), [this]( const tripoint & c ) { return !is_empty( c ); } ); diff --git a/src/iexamine.cpp b/src/iexamine.cpp index 1f11110294960..35dc578b5e460 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -755,7 +755,7 @@ void iexamine::elevator( player &p, const tripoint &examp ) } else if( g->m.ter( critter.pos() ) == ter_id( "t_elevator" ) ) { tripoint critter_omt = ms_to_omt_copy( g->m.getabs( critter.pos() ) ); if( critter_omt == new_floor_omt ) { - for( const tripoint &candidate : closest_tripoints_first( 10, critter.pos() ) ) { + for( const tripoint &candidate : closest_tripoints_first( critter.pos(), 10 ) ) { if( g->m.ter( candidate ) != ter_id( "t_elevator" ) && g->m.passable( candidate ) && !g->critter_at( candidate ) ) { @@ -778,7 +778,7 @@ void iexamine::elevator( player &p, const tripoint &examp ) tripoint critter_omt = ms_to_omt_copy( g->m.getabs( critter.pos() ) ); if( critter_omt == original_floor_omt ) { - for( const tripoint &candidate : closest_tripoints_first( 10, p.pos() ) ) { + for( const tripoint &candidate : closest_tripoints_first( p.pos(), 10 ) ) { if( g->m.ter( candidate ) == ter_id( "t_elevator" ) && candidate != p.pos() && !g->critter_at( candidate ) ) { @@ -1876,7 +1876,7 @@ void iexamine::egg_sack_generic( player &p, const tripoint &examp, g->m.furn_set( examp, f_egg_sacke ); int monster_count = 0; if( one_in( 2 ) ) { - for( const tripoint &p : closest_tripoints_first( 1, examp ) ) { + for( const tripoint &p : closest_tripoints_first( examp, 1 ) ) { if( !one_in( 3 ) ) { continue; } else if( g->place_critter_at( montype, p ) ) { diff --git a/src/inventory_ui.cpp b/src/inventory_ui.cpp index 7fbf60b189378..ef0ff000b03e3 100644 --- a/src/inventory_ui.cpp +++ b/src/inventory_ui.cpp @@ -1202,7 +1202,7 @@ void inventory_selector::add_vehicle_items( const tripoint &target ) void inventory_selector::add_nearby_items( int radius ) { if( radius >= 0 ) { - for( const auto &pos : closest_tripoints_first( radius, u.pos() ) ) { + for( const tripoint &pos : closest_tripoints_first( u.pos(), radius ) ) { // can not reach this -> can not access its contents if( u.pos() != pos && !g->m.clear_path( u.pos(), pos, rl_dist( u.pos(), pos ), 1, 100 ) ) { continue; diff --git a/src/iuse.cpp b/src/iuse.cpp index 10556f4c7d21c..6a6cf0af4595f 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -1178,7 +1178,7 @@ static void spawn_spores( const player &p ) { int spores_spawned = 0; fungal_effects fe( *g, g->m ); - for( const tripoint &dest : closest_tripoints_first( 4, p.pos() ) ) { + for( const tripoint &dest : closest_tripoints_first( p.pos(), 4 ) ) { if( g->m.impassable( dest ) ) { continue; } @@ -5376,7 +5376,7 @@ int iuse::artifact( player *p, item *it, bool, const tripoint & ) case AEA_FIRESTORM: { p->add_msg_if_player( m_bad, _( "Fire rains down around you!" ) ); - std::vector ps = closest_tripoints_first( 3, p->pos() ); + std::vector ps = closest_tripoints_first( p->pos(), 3 ); for( auto p_it : ps ) { if( !one_in( 3 ) ) { g->m.add_field( p_it, fd_fire, 1 + rng( 0, 1 ) * rng( 0, 1 ), 3_minutes ); diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 6541fbab2dfaa..dcd65e9beede7 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -397,9 +397,8 @@ std::unique_ptr explosion_iuse::clone() const // They must also be passable. static std::vector points_for_gas_cloud( const tripoint ¢er, int radius ) { - const std::vector gas_sources = closest_tripoints_first( radius, center ); std::vector result; - for( const auto &p : gas_sources ) { + for( const auto &p : closest_tripoints_first( center, radius ) ) { if( g->m.impassable( p ) ) { continue; } diff --git a/src/iuse_software_minesweeper.cpp b/src/iuse_software_minesweeper.cpp index 6885ea0568cbd..c97eb61554ebb 100644 --- a/src/iuse_software_minesweeper.cpp +++ b/src/iuse_software_minesweeper.cpp @@ -18,8 +18,6 @@ #include "optional.h" #include "point.h" -std::vector closest_tripoints_first( int radius, const tripoint &p ); - minesweeper_game::minesweeper_game() { iMinY = 8; @@ -114,9 +112,7 @@ void minesweeper_game::new_level( const catacurses::window &w_minesweeper ) for( int y = 0; y < iLevelY; y++ ) { for( int x = 0; x < iLevelX; x++ ) { if( mLevel[y][x] == static_cast( bomb ) ) { - const auto circle = closest_tripoints_first( 1, {x, y, 0} ); - - for( const auto &p : circle ) { + for( const point &p : closest_points_first( {x, y}, 1 ) ) { if( p.x >= 0 && p.x < iLevelX && p.y >= 0 && p.y < iLevelY ) { if( mLevel[p.y][p.x] != static_cast( bomb ) ) { mLevel[p.y][p.x]++; @@ -217,9 +213,7 @@ int minesweeper_game::start_game() mLevelReveal[y][x] = seen; if( mLevel[y][x] == 0 ) { - const auto circle = closest_tripoints_first( 1, {x, y, 0} ); - - for( const auto &p : circle ) { + for( const point &p : closest_points_first( {x, y}, 1 ) ) { if( p.x >= 0 && p.x < iLevelX && p.y >= 0 && p.y < iLevelY ) { if( mLevelReveal[p.y][p.x] != seen ) { rec_reveal( p.y, p.x ); diff --git a/src/map.cpp b/src/map.cpp index 0e49e23ca4e64..7d98e9aae0ac9 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -4098,7 +4098,7 @@ item &map::add_item_or_charges( const tripoint &pos, item obj, bool overflow ) } else if( overflow ) { // ...otherwise try to overflow to adjacent tiles (if permitted) const int max_dist = 2; - auto tiles = closest_tripoints_first( max_dist, pos ); + std::vector tiles = closest_tripoints_first( pos, max_dist ); tiles.erase( tiles.begin() ); // we already tried this position const int max_path_length = 4 * max_dist; const pathfinding_settings setting( 0, max_dist, max_path_length, 0, false, true, false, false ); @@ -6248,10 +6248,10 @@ std::vector map::get_dir_circle( const tripoint &f, const tripoint &t // The line below can be crazy expensive - we only take the FIRST point of it const std::vector line = line_to( f, t, 0, 0 ); - const std::vector spiral = closest_tripoints_first( 1, f ); + const std::vector spiral = closest_tripoints_first( f, 1 ); const std::vector pos_index {1, 2, 4, 6, 8, 7, 5, 3}; - // All possible constellations (closest_points_first goes clockwise) + // All possible constellations (closest_tripoints_first goes clockwise) // 753 531 312 124 246 468 687 875 // 8 1 7 2 5 4 3 6 1 8 2 7 4 5 6 3 // 642 864 786 578 357 135 213 421 @@ -7741,59 +7741,6 @@ void map::build_map_cache( const int zlev, bool skip_lightmap ) } } -//this returns points in a spiral pattern starting at center_x/center_y until it hits the radius. clockwise fashion -//credit to Tom J Nowell; http://stackoverflow.com/a/1555236/1269969 -std::vector closest_points_first( int radius, const point ¢er ) -{ - std::vector points; - int X = radius * 2 + 1; - int Y = radius * 2 + 1; - int x = 0; - int y = 0; - int dx = 0; - int dy = -1; - int t = std::max( X, Y ); - int maxI = t * t; - for( int i = 0; i < maxI; i++ ) { - if( -X / 2 <= x && x <= X / 2 && -Y / 2 <= y && y <= Y / 2 ) { - points.push_back( center + point( x, y ) ); - } - if( x == y || ( x < 0 && x == -y ) || ( x > 0 && x == 1 - y ) ) { - t = dx; - dx = -dy; - dy = t; - } - x += dx; - y += dy; - } - return points; -} - -std::vector closest_tripoints_first( int radius, const tripoint ¢er ) -{ - std::vector points; - int X = radius * 2 + 1; - int Y = radius * 2 + 1; - int x = 0; - int y = 0; - int dx = 0; - int dy = -1; - int t = std::max( X, Y ); - int maxI = t * t; - for( int i = 0; i < maxI; i++ ) { - if( -X / 2 <= x && x <= X / 2 && -Y / 2 <= y && y <= Y / 2 ) { - points.push_back( center + point( x, y ) ); - } - if( x == y || ( x < 0 && x == -y ) || ( x > 0 && x == 1 - y ) ) { - t = dx; - dx = -dy; - dy = t; - } - x += dx; - y += dy; - } - return points; -} ////////// ///// coordinate helpers diff --git a/src/map.h b/src/map.h index 650d7e67be827..d7641db48e910 100644 --- a/src/map.h +++ b/src/map.h @@ -1826,9 +1826,6 @@ class map template void shift_bitset_cache( std::bitset &cache, const point &s ); -std::vector closest_points_first( int radius, const point ¢er ); -// Does not build "piles" - does the same as above functions, except in tripoints -std::vector closest_tripoints_first( int radius, const tripoint ¢er ); bool ter_furn_has_flag( const ter_t &ter, const furn_t &furn, ter_bitflags flag ); class tinymap : public map { diff --git a/src/map_selector.cpp b/src/map_selector.cpp index 62ef21aa64893..189935aab066c 100644 --- a/src/map_selector.cpp +++ b/src/map_selector.cpp @@ -13,7 +13,7 @@ map_selector::map_selector( const tripoint &pos, int radius, bool accessible ) { - for( const auto &e : closest_tripoints_first( radius, pos ) ) { + for( const tripoint &e : closest_tripoints_first( pos, radius ) ) { if( !accessible || g->m.clear_path( pos, e, radius, 1, 100 ) ) { data.emplace_back( e ); } diff --git a/src/mapgen_functions.cpp b/src/mapgen_functions.cpp index 9288b2c4d94ed..c735d202787af 100644 --- a/src/mapgen_functions.cpp +++ b/src/mapgen_functions.cpp @@ -3439,8 +3439,7 @@ void mapgen_lake_shore( mapgendata &dat ) const auto draw_shallow_water = [&]( const point & from, const point & to ) { std::vector points = line_to( from, to ); for( auto &p : points ) { - std::vector buffered_points = closest_points_first( 1, p ); - for( const point &bp : buffered_points ) { + for( const point &bp : closest_points_first( p, 1 ) ) { if( !map_boundaries.contains_inclusive( bp ) ) { continue; } diff --git a/src/monattack.cpp b/src/monattack.cpp index 6e56cb165d576..29a77297d1475 100644 --- a/src/monattack.cpp +++ b/src/monattack.cpp @@ -2282,7 +2282,7 @@ bool mattack::formblob( monster *z ) } bool didit = false; - auto pts = closest_tripoints_first( 1, z->pos() ); + std::vector pts = closest_tripoints_first( z->pos(), 1 ); // Don't check own tile pts.erase( pts.begin() ); for( const tripoint &dest : pts ) { @@ -2368,7 +2368,7 @@ bool mattack::callblobs( monster *z ) // and keep the rest near the brain blob for protection. tripoint enemy = g->u.pos(); std::list allies; - std::vector nearby_points = closest_tripoints_first( 3, z->pos() ); + std::vector nearby_points = closest_tripoints_first( z->pos(), 3 ); for( monster &candidate : g->all_monsters() ) { if( candidate.type->in_species( BLOB ) && candidate.type->id != mon_blob_brain ) { // Just give the allies consistent assignments. @@ -2401,7 +2401,7 @@ bool mattack::jackson( monster *z ) { // Jackson draws nearby zombies into the dance. std::list allies; - std::vector nearby_points = closest_tripoints_first( 3, z->pos() ); + std::vector nearby_points = closest_tripoints_first( z->pos(), 3 ); for( monster &candidate : g->all_monsters() ) { if( candidate.type->in_species( ZOMBIE ) && candidate.type->id != mon_zombie_jackson ) { // Just give the allies consistent assignments. diff --git a/src/mondefense.cpp b/src/mondefense.cpp index 45cd6f8ae3a60..06b3fa0d742e6 100644 --- a/src/mondefense.cpp +++ b/src/mondefense.cpp @@ -114,7 +114,7 @@ void mdefense::acidsplash( monster &m, Creature *const source, const tripoint initial_target = source == nullptr ? m.pos() : source->pos(); // Don't splatter directly on the `m`, that doesn't work well - auto pts = closest_tripoints_first( 1, initial_target ); + std::vector pts = closest_tripoints_first( initial_target, 1 ); pts.erase( std::remove( pts.begin(), pts.end(), m.pos() ), pts.end() ); projectile prj; diff --git a/src/monmove.cpp b/src/monmove.cpp index 7134d1a3fc288..9008ce33c8d83 100644 --- a/src/monmove.cpp +++ b/src/monmove.cpp @@ -1390,7 +1390,7 @@ bool monster::attack_at( const tripoint &p ) static tripoint find_closest_stair( const tripoint &near_this, const ter_bitflags stair_type ) { - for( const tripoint &candidate : closest_tripoints_first( 10, near_this ) ) { + for( const tripoint &candidate : closest_tripoints_first( near_this, 10 ) ) { if( g->m.has_flag( stair_type, candidate ) ) { return candidate; } diff --git a/src/npc.cpp b/src/npc.cpp index 75d9db694a02a..d3d4eec366102 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -734,7 +734,7 @@ void npc::place_on_map() return; } - for( const tripoint &p : closest_tripoints_first( SEEX + 1, pos() ) ) { + for( const tripoint &p : closest_tripoints_first( pos(), SEEX + 1 ) ) { if( g->is_empty( p ) ) { setpos( p ); return; diff --git a/src/npcmove.cpp b/src/npcmove.cpp index 18feda03e4e5e..a1ded9f9f9d8c 100644 --- a/src/npcmove.cpp +++ b/src/npcmove.cpp @@ -973,8 +973,7 @@ void npc::execute_action( npc_action action ) // Find a nice spot to sleep int best_sleepy = sleep_spot( pos() ); tripoint best_spot = pos(); - const auto points = closest_tripoints_first( 6, pos() ); - for( const tripoint &p : points ) { + for( const tripoint &p : closest_tripoints_first( pos(), 6 ) ) { if( !could_move_onto( p ) || !g->is_empty( p ) ) { continue; } @@ -2444,7 +2443,7 @@ void npc::avoid_friendly_fire() center.y = round( center.y / friend_count ); center.z = round( center.z / friend_count ); - auto candidates = closest_tripoints_first( 1, pos() ); + std::vector candidates = closest_tripoints_first( pos(), 1 ); candidates.erase( candidates.begin() ); std::sort( candidates.begin(), candidates.end(), [&tar, ¢er]( const tripoint & l, const tripoint & r ) { @@ -2558,7 +2557,7 @@ static cata::optional nearest_passable( const tripoint &p, const tripo // We need to path to adjacent tile, not the exact one // Let's pick the closest one to us that is passable - auto candidates = closest_tripoints_first( 1, p ); + std::vector candidates = closest_tripoints_first( p, 1 ); std::sort( candidates.begin(), candidates.end(), [ closest_to ]( const tripoint & l, const tripoint & r ) { return rl_dist( closest_to, l ) < rl_dist( closest_to, r ); @@ -2627,7 +2626,7 @@ void npc::move_away_from( const std::vector &spheres, bool no_bashing ) void npc::see_item_say_smth( const itype_id &object, const std::string &smth ) { - for( const tripoint &p : closest_tripoints_first( 6, pos() ) ) { + for( const tripoint &p : closest_tripoints_first( pos(), 6 ) ) { if( g->m.sees_some_items( p, *this ) && sees( p ) ) { for( const item &it : g->m.i_at( p ) ) { if( one_in( 100 ) && ( it.typeId() == object ) ) { @@ -2728,7 +2727,7 @@ void npc::find_item() } }; - for( const tripoint &p : closest_tripoints_first( range, pos() ) ) { + for( const tripoint &p : closest_tripoints_first( pos(), range ) ) { // TODO: Make this sight check not overdraw nearby tiles // TODO: Optimize that zone check if( is_player_ally() && g->check_zone( no_pickup, p ) ) { diff --git a/src/overmap.cpp b/src/overmap.cpp index 65de70c9a8e26..b4be4e1f383d3 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -2274,10 +2274,11 @@ void overmap::place_forest_trailheads() const auto trailhead_close_to_road = [&]( const tripoint & trailhead ) { bool close = false; - for( const point &nearby_point : closest_points_first( - settings.forest_trail.trailhead_road_distance, - trailhead.xy() ) ) { - if( check_ot( "road", ot_match_type::contains, tripoint( nearby_point, 0 ) ) ) { + for( const tripoint &nearby_point : closest_tripoints_first( + trailhead, + settings.forest_trail.trailhead_road_distance + ) ) { + if( check_ot( "road", ot_match_type::contains, nearby_point ) ) { close = true; } } @@ -2644,9 +2645,10 @@ void overmap::place_swamps() for( int y = 0; y < OMAPY; y++ ) { const tripoint pos( x, y, 0 ); if( is_ot_match( "river", ter( pos ), ot_match_type::contains ) ) { - std::vector buffered_points = closest_points_first( rng( - settings.overmap_forest.river_floodplain_buffer_distance_min, - settings.overmap_forest.river_floodplain_buffer_distance_max ), pos.xy() ); + std::vector buffered_points = closest_points_first( pos.xy(), + rng( + settings.overmap_forest.river_floodplain_buffer_distance_min, + settings.overmap_forest.river_floodplain_buffer_distance_max ) ); for( const point &p : buffered_points ) { if( !inbounds( p ) ) { continue; @@ -4157,8 +4159,8 @@ void overmap::place_specials( overmap_special_batch &enabled_specials ) std::vector nearest_candidates; // Since this starts at enabled_specials::origin, it will only place new overmaps // in the 5x5 area surrounding the initial overmap, bounding the amount of work we will do. - for( const point &candidate_addr : closest_points_first( 2, - custom_overmap_specials.get_origin() ) ) { + for( const point &candidate_addr : closest_points_first( + custom_overmap_specials.get_origin(), 2 ) ) { if( !overmap_buffer.has( candidate_addr ) ) { int current_distance = square_dist( pos(), candidate_addr ); if( nearest_candidates.empty() || current_distance == previous_distance ) { diff --git a/src/point.cpp b/src/point.cpp index 9b72b54cf4a5e..166cda4b25b41 100644 --- a/src/point.cpp +++ b/src/point.cpp @@ -37,3 +37,39 @@ point clamp_inclusive( const point &p, const rectangle &r ) { return point( clamp( p.x, r.p_min.x, r.p_max.x ), clamp( p.y, r.p_min.y, r.p_max.y ) ); } + +std::vector closest_tripoints_first( const tripoint ¢er, size_t radius ) +{ + std::vector points; + int X = radius * 2 + 1; + int Y = radius * 2 + 1; + int x = 0; + int y = 0; + int dx = 0; + int dy = -1; + int t = std::max( X, Y ); + int maxI = t * t; + for( int i = 0; i < maxI; i++ ) { + if( -X / 2 <= x && x <= X / 2 && -Y / 2 <= y && y <= Y / 2 ) { + points.push_back( center + point( x, y ) ); + } + if( x == y || ( x < 0 && x == -y ) || ( x > 0 && x == 1 - y ) ) { + t = dx; + dx = -dy; + dy = t; + } + x += dx; + y += dy; + } + return points; +} + +std::vector closest_points_first( const point ¢er, size_t radius ) +{ + const std::vector tripoints = closest_tripoints_first( tripoint( center, 0 ), radius ); + std::vector points; + for( const tripoint &p : tripoints ) { + points.push_back( p.xy() ); + } + return points; +} diff --git a/src/point.h b/src/point.h index c4df6b5249563..556cf65312eca 100644 --- a/src/point.h +++ b/src/point.h @@ -11,6 +11,7 @@ #include #include #include +#include #else @@ -259,6 +260,14 @@ struct box { } }; + +/** + * Following functions return points in a spiral pattern starting at center_x/center_y until it hits the radius. Clockwise fashion. + * Credit to Tom J Nowell; http://stackoverflow.com/a/1555236/1269969 + */ +std::vector closest_tripoints_first( const tripoint ¢er, size_t radius ); +std::vector closest_points_first( const point ¢er, size_t radius ); + static constexpr tripoint tripoint_zero { 0, 0, 0 }; static constexpr point point_zero{ tripoint_zero.xy() }; diff --git a/src/ranged.cpp b/src/ranged.cpp index a23593ceed864..a4be8ce67b38f 100644 --- a/src/ranged.cpp +++ b/src/ranged.cpp @@ -1208,7 +1208,7 @@ static void update_targets( player &pc, int range, std::vector &targ } } else { - auto adjacent = closest_tripoints_first( range, dst ); + const std::vector adjacent = closest_tripoints_first( dst, range ); const auto target_spot = std::find_if( adjacent.begin(), adjacent.end(), [&pc]( const tripoint & pt ) { return g->m.tr_at( pt ).id == tr_practice_target && pc.sees( pt ); @@ -2199,7 +2199,7 @@ int time_to_attack( const Character &p, const itype &firing ) static void cycle_action( item &weap, const tripoint &pos ) { // eject casings and linkages in random direction avoiding walls using player position as fallback - auto tiles = closest_tripoints_first( 1, pos ); + std::vector tiles = closest_tripoints_first( pos, 1 ); tiles.erase( tiles.begin() ); tiles.erase( std::remove_if( tiles.begin(), tiles.end(), [&]( const tripoint & e ) { return !g->m.passable( e ); diff --git a/src/start_location.cpp b/src/start_location.cpp index db320c81afedd..b5a156b4d3c6f 100644 --- a/src/start_location.cpp +++ b/src/start_location.cpp @@ -199,7 +199,7 @@ tripoint start_location::find_player_initial_location() const // Spiral out from the world origin scanning for a compatible starting location, // creating overmaps as necessary. const int radius = 3; - for( const point &omp : closest_points_first( radius, point_zero ) ) { + for( const point &omp : closest_points_first( point_zero, radius ) ) { overmap &omap = overmap_buffer.get( omp ); const tripoint omtstart = omap.find_random_omt( target() ); if( omtstart != overmap::invalid_tripoint ) { diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 02c2d76ed6c8e..75f79cc228ed6 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -6040,7 +6040,7 @@ void vehicle::leak_fuel( vehicle_part &pt ) } // leak in random directions but prefer closest tiles and avoid walls or other obstacles - auto tiles = closest_tripoints_first( 1, global_part_pos3( pt ) ); + std::vector tiles = closest_tripoints_first( global_part_pos3( pt ), 1 ); tiles.erase( std::remove_if( tiles.begin(), tiles.end(), []( const tripoint & e ) { return !g->m.passable( e ); } ), tiles.end() ); diff --git a/src/vehicle_selector.cpp b/src/vehicle_selector.cpp index 87efd4a6443d7..a8bd6b4e19430 100644 --- a/src/vehicle_selector.cpp +++ b/src/vehicle_selector.cpp @@ -10,7 +10,7 @@ vehicle_selector::vehicle_selector( const tripoint &pos, int radius, bool accessible, bool visibility_only ) { - for( const auto &e : closest_tripoints_first( radius, pos ) ) { + for( const tripoint &e : closest_tripoints_first( pos, radius ) ) { if( !accessible || ( visibility_only ? g->m.sees( pos, e, radius ) : g->m.clear_path( pos, e, radius, 1, 100 ) ) ) { if( const optional_vpart_position vp = g->m.veh_at( e ) ) { @@ -23,7 +23,7 @@ vehicle_selector::vehicle_selector( const tripoint &pos, int radius, bool access vehicle_selector::vehicle_selector( const tripoint &pos, int radius, bool accessible, const vehicle &ignore ) { - for( const auto &e : closest_tripoints_first( radius, pos ) ) { + for( const tripoint &e : closest_tripoints_first( pos, radius ) ) { if( !accessible || g->m.clear_path( pos, e, radius, 1, 100 ) ) { if( const optional_vpart_position vp = g->m.veh_at( e ) ) { if( &vp->vehicle() != &ignore ) { diff --git a/src/wish.cpp b/src/wish.cpp index 26c9f113e9aad..f54e0237654fa 100644 --- a/src/wish.cpp +++ b/src/wish.cpp @@ -413,7 +413,7 @@ void debug_menu::wishmonster( const cata::optional &p ) const mtype_id &mon_type = mtypes[ wmenu.ret ]->id; if( cata::optional spawn = p ? p : g->look_around() ) { int num_spawned = 0; - for( const tripoint &p : closest_tripoints_first( cb.group, *spawn ) ) { + for( const tripoint &p : closest_tripoints_first( *spawn, cb.group ) ) { monster *const mon = g->place_critter_at( mon_type, p ); if( !mon ) { continue; diff --git a/tests/explosion_balance_test.cpp b/tests/explosion_balance_test.cpp index 90807960a90f5..9c3ff822fe42a 100644 --- a/tests/explosion_balance_test.cpp +++ b/tests/explosion_balance_test.cpp @@ -37,7 +37,7 @@ static void check_lethality( const std::string &explosive_id, const int range, f // Spawn some monsters in a circle. tripoint origin( 30, 30, 0 ); int num_subjects_this_time = 0; - for( const tripoint monster_position : closest_tripoints_first( range, origin ) ) { + for( const tripoint &monster_position : closest_tripoints_first( origin, range ) ) { if( rl_dist( monster_position, origin ) != range ) { continue; } diff --git a/tests/overmap_test.cpp b/tests/overmap_test.cpp index 01bab81fe8b26..8753d703eb5f3 100644 --- a/tests/overmap_test.cpp +++ b/tests/overmap_test.cpp @@ -36,7 +36,7 @@ TEST_CASE( "set_and_get_overmap_scents" ) TEST_CASE( "default_overmap_generation_always_succeeds" ) { int overmaps_to_construct = 10; - for( point candidate_addr : closest_points_first( 10, point_zero ) ) { + for( const point &candidate_addr : closest_points_first( point_zero, 10 ) ) { // Skip populated overmaps. if( overmap_buffer.has( candidate_addr ) ) { continue; diff --git a/tests/visitable_remove_test.cpp b/tests/visitable_remove_test.cpp index a12f5aba9c730..2b8fce5a50d07 100644 --- a/tests/visitable_remove_test.cpp +++ b/tests/visitable_remove_test.cpp @@ -52,7 +52,7 @@ TEST_CASE( "visitable_remove", "[visitable]" ) // check if all tiles within radius are loaded within current submap and passable const auto suitable = []( const tripoint & pos, const int radius ) { - auto tiles = closest_tripoints_first( radius, pos ); + std::vector tiles = closest_tripoints_first( pos, radius ); return std::all_of( tiles.begin(), tiles.end(), []( const tripoint & e ) { if( !g->m.inbounds( e ) ) { return false; @@ -70,7 +70,7 @@ TEST_CASE( "visitable_remove", "[visitable]" ) // move player randomly until we find a suitable position while( !suitable( p.pos(), 1 ) ) { CHECK( !p.in_vehicle ); - p.setpos( random_entry( closest_tripoints_first( 1, p.pos() ) ) ); + p.setpos( random_entry( closest_tripoints_first( p.pos(), 1 ) ) ); } item temp_liquid( liquid_id ); @@ -290,7 +290,7 @@ TEST_CASE( "visitable_remove", "[visitable]" ) } GIVEN( "A player surrounded by several bottles of water" ) { - auto tiles = closest_tripoints_first( 1, p.pos() ); + std::vector tiles = closest_tripoints_first( p.pos(), 1 ); tiles.erase( tiles.begin() ); // player tile int our = 0; // bottles placed on player tile @@ -407,7 +407,7 @@ TEST_CASE( "visitable_remove", "[visitable]" ) } GIVEN( "An adjacent vehicle contains several bottles of water" ) { - auto tiles = closest_tripoints_first( 1, p.pos() ); + std::vector tiles = closest_tripoints_first( p.pos(), 1 ); tiles.erase( tiles.begin() ); // player tile tripoint veh = random_entry( tiles ); REQUIRE( g->m.add_vehicle( vproto_id( "shopping_cart" ), veh, 0, 0, 0 ) ); From 3d6049dd97d179c7474a0a845bbf9a56545a10ab Mon Sep 17 00:00:00 2001 From: ZhilkinSerg Date: Thu, 16 Jan 2020 17:10:53 +0300 Subject: [PATCH 2/3] Add missing header --- src/point.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/point.h b/src/point.h index 556cf65312eca..c89917b7c5c82 100644 --- a/src/point.h +++ b/src/point.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include From efc50bc136b1742311657b68d5723c1bb03964f4 Mon Sep 17 00:00:00 2001 From: ZhilkinSerg Date: Fri, 17 Jan 2020 08:22:51 +0300 Subject: [PATCH 3/3] Apply suggestions from code review --- src/point.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/point.h b/src/point.h index c89917b7c5c82..7d4199c228806 100644 --- a/src/point.h +++ b/src/point.h @@ -261,14 +261,6 @@ struct box { } }; - -/** - * Following functions return points in a spiral pattern starting at center_x/center_y until it hits the radius. Clockwise fashion. - * Credit to Tom J Nowell; http://stackoverflow.com/a/1555236/1269969 - */ -std::vector closest_tripoints_first( const tripoint ¢er, size_t radius ); -std::vector closest_points_first( const point ¢er, size_t radius ); - static constexpr tripoint tripoint_zero { 0, 0, 0 }; static constexpr point point_zero{ tripoint_zero.xy() }; @@ -307,6 +299,13 @@ struct sphere { #ifndef CATA_NO_STL +/** + * Following functions return points in a spiral pattern starting at center_x/center_y until it hits the radius. Clockwise fashion. + * Credit to Tom J Nowell; http://stackoverflow.com/a/1555236/1269969 + */ +std::vector closest_tripoints_first( const tripoint ¢er, size_t radius ); +std::vector closest_points_first( const point ¢er, size_t radius ); + inline point abs( const point &p ) { return point( abs( p.x ), abs( p.y ) );