Skip to content

Commit

Permalink
Performance: Cache NPC goal (#54312)
Browse files Browse the repository at this point in the history
The goal cache is invalidated when the NPC moves to a different OMT.
  • Loading branch information
dseguin authored Jan 12, 2022
1 parent d23c6cb commit 6ae3e36
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 14 deletions.
7 changes: 7 additions & 0 deletions src/npc.h
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,11 @@ struct npc_short_term_cache {
cata::optional<int> closest_enemy_to_friendly_distance() const;
};

struct npc_need_goal_cache {
tripoint_abs_omt goal;
tripoint_abs_omt omt_loc;
};

// DO NOT USE! This is old, use strings as talk topic instead, e.g. "TALK_AGREE_FOLLOW" instead of
// TALK_AGREE_FOLLOW. There is also convert_talk_topic which can convert the enumeration values to
// the new string values (used to load old saves).
Expand Down Expand Up @@ -1300,6 +1305,8 @@ class npc : public Character
std::map<std::string, time_point> complaints;

npc_short_term_cache ai_cache;

std::map<npc_need, npc_need_goal_cache> goal_cache;
public:
const std::shared_ptr<npc_attack> &get_current_attack() const {
return ai_cache.current_attack;
Expand Down
36 changes: 22 additions & 14 deletions src/npcmove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4190,20 +4190,28 @@ void npc::set_omt_destination()

std::string dest_type;
for( const auto &fulfill : needs ) {
// look for the closest occurrence of any of that locations terrain types
omt_find_params find_params;
for( const oter_type_str_id &elem : get_location_for( fulfill )->get_all_terrains() ) {
std::pair<std::string, ot_match_type> temp_pair;
temp_pair.first = elem.str();
temp_pair.second = ot_match_type::type;
find_params.types.push_back( temp_pair );
}
// note: no shuffle of `find_params.types` is needed, because `find_closest`
// disregards `types` order anyway, and already returns random result among
// those having equal minimal distance
find_params.search_range = 75;
find_params.existing_only = false;
goal = overmap_buffer.find_closest( surface_omt_loc, find_params );
auto cache_iter = goal_cache.find( fulfill );
if( cache_iter != goal_cache.end() && cache_iter->second.omt_loc == surface_omt_loc ) {
goal = cache_iter->second.goal;
} else {
// look for the closest occurrence of any of that locations terrain types
omt_find_params find_params;
for( const oter_type_str_id &elem : get_location_for( fulfill )->get_all_terrains() ) {
std::pair<std::string, ot_match_type> temp_pair;
temp_pair.first = elem.str();
temp_pair.second = ot_match_type::type;
find_params.types.push_back( temp_pair );
}
// note: no shuffle of `find_params.types` is needed, because `find_closest`
// disregards `types` order anyway, and already returns random result among
// those having equal minimal distance
find_params.search_range = 75;
find_params.existing_only = false;
goal = overmap_buffer.find_closest( surface_omt_loc, find_params );
npc_need_goal_cache &cache = goal_cache[fulfill];
cache.goal = goal;
cache.omt_loc = surface_omt_loc;
}
omt_path.clear();
if( goal != overmap::invalid_tripoint ) {
omt_path = overmap_buffer.get_travel_path( surface_omt_loc, goal, overmap_path_params::for_npc() );
Expand Down

0 comments on commit 6ae3e36

Please sign in to comment.