/** 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;
}