/** 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.move_cost( p ) == 0 || 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.move_cost( pt ) > 0 || 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; }
bool monster::can_move_to(map &m, int x, int y) { if (m.move_cost(x, y) == 0 && (!has_flag(MF_DESTROYS) || !m.is_destructable(x, y)) && ((!has_flag(MF_AQUATIC) && !has_flag(MF_SWIMS)) || !m.has_flag(swimmable, x, y))) return false; if (has_flag(MF_DIGS) && !m.has_flag(diggable, x, y)) return false; if (has_flag(MF_AQUATIC) && !m.has_flag(swimmable, x, y)) return false; return true; }