This does a 'fit_sort' whenever the state is changed. fit_sort effectively sorts the actions by distance+cost so that the cost is actually present unlike the original algorithm.

This commit is contained in:
Zed A. Shaw 2025-04-03 10:14:50 -04:00
parent c014e65c13
commit c1aba2d5c8
5 changed files with 30 additions and 27 deletions

View file

@ -4,6 +4,8 @@
#include "stats.hpp"
#include <queue>
// #define DEBUG_CYCLES 1
namespace ai {
using namespace nlohmann;
@ -63,11 +65,8 @@ namespace ai {
}
}
inline void path_invariant(std::unordered_map<Action, Action>& came_from, Action& current) {
#if defined(NDEBUG)
(void)came_from; // disable errors about unused
(void)current;
#else
inline void path_invariant(std::unordered_map<Action, Action>& came_from, Action current) {
#if defined(DEBUG_CYCLES)
bool final_found = current == FINAL_ACTION;
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);
dbc::sentinel("AI CYCLE FOUND!");
}
#else
(void)came_from; // disable errors about unused
(void)current;
#endif
}
@ -156,15 +158,21 @@ namespace ai {
auto neighbor = neighbor_action.apply_effect(current.state);
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 tentative_g_score = g_score[current.state] + d_score;
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);
g_score.insert_or_assign(neighbor, tentative_g_score);
ActionState neighbor_as{neighbor_action, neighbor};
int score = tentative_g_score + h(neighbor, goal);