Skip to content

Commit

Permalink
Merge pull request #33885 from kevingranade/throttle-npc-find-item-v2
Browse files Browse the repository at this point in the history
Throttle NPC item search activity alternative
  • Loading branch information
ZhilkinSerg authored Sep 10, 2019
2 parents dc22a8e + 494ee52 commit 8e061f3
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
3 changes: 3 additions & 0 deletions src/npc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "calendar.h"
#include "faction.h"
#include "line.h"
#include "lru_cache.h"
#include "optional.h"
#include "pimpl.h"
#include "player.h"
Expand Down Expand Up @@ -495,6 +496,8 @@ struct npc_short_term_cache {
std::vector<sphere> dangerous_explosives;

std::map<direction, float> threat_map;
// Cache of locations the NPC has searched recently in npc::find_item()
lru_cache<tripoint, int> searched_tiles;
};

// DO NOT USE! This is old, use strings as talk topic instead, e.g. "TALK_AGREE_FOLLOW" instead of
Expand Down
40 changes: 34 additions & 6 deletions src/npcmove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2606,7 +2606,6 @@ void npc::find_item()
}

if( is_player_ally() && !rules.has_flag( ally_rule::allow_pick_up ) ) {

// Grabbing stuff not allowed by our "owner"
return;
}
Expand Down Expand Up @@ -2699,34 +2698,63 @@ void npc::find_item()
continue;
}

const tripoint abs_p = global_square_location() - pos() + p;
const int prev_num_items = ai_cache.searched_tiles.get( abs_p, -1 );
// Prefetch the number of items present so we can bail out if we already checked here.
const map_stack m_stack = g->m.i_at( p );
int num_items = m_stack.size();
const optional_vpart_position vp = g->m.veh_at( p );
if( vp ) {
const cata::optional<vpart_reference> cargo = vp.part_with_feature( VPFLAG_CARGO, true );
if( cargo ) {
vehicle_stack v_stack = cargo->vehicle().get_items( cargo->part_index() );
num_items += v_stack.size();
}
}
if( prev_num_items == num_items ) {
continue;
}
auto cache_tile = [this, &abs_p, num_items, &wanted]() {
if( wanted == nullptr ) {
ai_cache.searched_tiles.insert( 1000, abs_p, num_items );
}
};
bool can_see = false;
if( g->m.sees_some_items( p, *this ) && sees( p ) ) {
for( const item &it : g->m.i_at( p ) ) {
can_see = true;
for( const item &it : m_stack ) {
consider_item( it, p );
}
}

// Allow terrain check without sight, because it would cost more CPU than it is worth
consider_terrain( p );
// Not cached because it gets checked once and isn't expected to change.
if( can_see || sees( p ) ) {
can_see = true;
consider_terrain( p );
}

const optional_vpart_position vp = g->m.veh_at( p );
if( !vp || vp->vehicle().is_moving() || !sees( p ) ) {
if( !vp || vp->vehicle().is_moving() || !( can_see || sees( p ) ) ) {
cache_tile();
continue;
}
const cata::optional<vpart_reference> cargo = vp.part_with_feature( VPFLAG_CARGO, true );
static const std::string locked_string( "LOCKED" );
// TODO: Let player know what parts are safe from NPC thieves
if( !cargo || cargo->has_feature( locked_string ) ) {
cache_tile();
continue;
}

static const std::string cargo_locking_string( "CARGO_LOCKING" );
if( vp.part_with_feature( cargo_locking_string, true ) ) {
cache_tile();
continue;
}

for( const item &it : cargo->vehicle().get_items( cargo->part_index() ) ) {
consider_item( it, p );
}
cache_tile();
}

if( wanted != nullptr ) {
Expand Down

0 comments on commit 8e061f3

Please sign in to comment.