@ -4,6 +4,8 @@
# include "stats.hpp"
# include "stats.hpp"
# include <queue>
# include <queue>
// #define DEBUG_CYCLES 1
namespace ai {
namespace ai {
using namespace nlohmann ;
using namespace nlohmann ;
@ -63,11 +65,8 @@ namespace ai {
}
}
}
}
inline void path_invariant ( std : : unordered_map < Action , Action > & came_from , Action & current ) {
inline void path_invariant ( std : : unordered_map < Action , Action > & came_from , Action current ) {
# if defined(NDEBUG)
# if defined(DEBUG_CYCLES)
( void ) came_from ; // disable errors about unused
( void ) current ;
# else
bool final_found = current = = FINAL_ACTION ;
bool final_found = current = = FINAL_ACTION ;
for ( size_t i = 0 ; i < = came_from . size ( ) & & came_from . contains ( current ) ; i + + ) {
for ( size_t i = 0 ; i < = came_from . size ( ) & & came_from . contains ( current ) ; i + + ) {
@ -79,6 +78,9 @@ namespace ai {
dump_came_from ( " CYCLE DETECTED! " , came_from , current ) ;
dump_came_from ( " CYCLE DETECTED! " , came_from , current ) ;
dbc : : sentinel ( " AI CYCLE FOUND! " ) ;
dbc : : sentinel ( " AI CYCLE FOUND! " ) ;
}
}
# else
( void ) came_from ; // disable errors about unused
( void ) current ;
# endif
# endif
}
}
@ -156,15 +158,21 @@ namespace ai {
auto neighbor = neighbor_action . apply_effect ( current . state ) ;
auto neighbor = neighbor_action . apply_effect ( current . state ) ;
if ( closed_set . contains ( neighbor ) ) continue ;
if ( closed_set . contains ( neighbor ) ) continue ;
// BUG: no matter what I do cost really doesn't impact the graph
// Additionally, every other GOAP implementation has the same problem, and
// it's probably because the selection of actions is based more on sets matching
// than actual weights of paths. This reduces the probability that an action will
// be chosen over another due to only cost.
int d_score = d ( current . state , neighbor ) + neighbor_action . cost ;
int d_score = d ( current . state , neighbor ) + neighbor_action . cost ;
int tentative_g_score = g_score [ current . state ] + d_score ;
int tentative_g_score = g_score [ current . state ] + d_score ;
int neighbor_g_score = g_score . contains ( neighbor ) ? g_score [ neighbor ] : SCORE_MAX ;
int neighbor_g_score = g_score . contains ( neighbor ) ? g_score [ neighbor ] : SCORE_MAX ;
if ( tentative_g_score < neighbor_g_score ) {
if ( tentative_g_score + neighbor_action . cost < neighbor_g_score ) {
came_from . insert_or_assign ( neighbor_action , current . action ) ;
came_from . insert_or_assign ( neighbor_action , current . action ) ;
g_score . insert_or_assign ( neighbor , tentative_g_score ) ;
g_score . insert_or_assign ( neighbor , tentative_g_score ) ;
ActionState neighbor_as { neighbor_action , neighbor } ;
ActionState neighbor_as { neighbor_action , neighbor } ;
int score = tentative_g_score + h ( neighbor , goal ) ;
int score = tentative_g_score + h ( neighbor , goal ) ;