/** Helper for place_player * Flood-fills the area from a given point, then returns the area it found. * Considers unpassable tiles passable if they can be bashed down or opened. * Will return INT_MAX if it reaches upstairs or map edge. * We can't really use map::route here, because it expects a destination * Maybe TODO: Allow "picking up" items or parts of bashable furniture * and using them to help with bash attempts. */ int rate_location( map &m, const tripoint &p, const bool must_be_inside, const int bash_str, const int attempt, int ( &checked )[MAPSIZE * SEEX][MAPSIZE * SEEY] ) { if( ( must_be_inside && m.is_outside( p ) ) || m.impassable( p ) || checked[p.x][p.y] > 0 ) { return 0; } // Vector that will be used as a stack std::vector<tripoint> st; st.reserve( MAPSIZE * SEEX * MAPSIZE * SEEY ); st.push_back( p ); // If not checked yet and either can be moved into, can be bashed down or opened, // add it on the top of the stack. const auto maybe_add = [&]( const int x, const int y, const tripoint & from ) { if( checked[x][y] >= attempt ) { return; } const tripoint pt( x, y, p.z ); if( m.passable( pt ) || m.bash_resistance( pt ) <= bash_str || m.open_door( pt, !m.is_outside( from ), true ) ) { st.push_back( pt ); } }; int area = 0; while( !st.empty() ) { area++; const tripoint cur = st.back(); st.pop_back(); checked[cur.x][cur.y] = attempt; if( cur.x == 0 || cur.x == SEEX * MAPSIZE - 1 || cur.y == 0 || cur.y == SEEY * MAPSIZE - 1 || m.has_flag( "GOES_UP", cur ) ) { return INT_MAX; } maybe_add( cur.x - 1, cur.y, cur ); maybe_add( cur.x, cur.y - 1, cur ); maybe_add( cur.x + 1, cur.y, cur ); maybe_add( cur.x, cur.y + 1, cur ); maybe_add( cur.x - 1, cur.y - 1, cur ); maybe_add( cur.x + 1, cur.y - 1, cur ); maybe_add( cur.x - 1, cur.y + 1, cur ); maybe_add( cur.x + 1, cur.y + 1, cur ); } return area; }