Autowalker is now using the GOAP AI system and works way better. Still quite a lot of jank in the code but that'll get removed over time. Next thing is being able to detect when its near an item/enemy and properly react.

This commit is contained in:
Zed A. Shaw 2025-03-12 12:15:21 -04:00
parent ff81c78d13
commit d15c9b12fd
9 changed files with 84 additions and 47 deletions

View file

@ -89,9 +89,12 @@ bool Autowalker::path_player(Pathing& paths, Point& target_out) {
bool found = paths.random_walk(target_out, false, PATHING_TOWARD);
if(!found) {
dbc::log("no neighbor found in any direction, aborting autowalk");
matrix::dump("NO TOWARD", paths.$paths, target_out.x, target_out.y);
return false;
// failed to find a linear path, try diagonal
if(!paths.random_walk(target_out, false, PATHING_TOWARD, MOVE_DIAGONAL)) {
dbc::log("couldn't find a diagonal direction");
matrix::dump("MOVE FAIL PATHS", paths.$paths, target_out.x, target_out.y);
return false;
}
}
if(!fsm.$level.map->can_move(target_out)) {
@ -111,6 +114,11 @@ void Autowalker::rotate_player(Point current, Point target) {
int facing = fsm.$main_ui.$compass_dir;
int target_facing = 0;
/* This is a massive pile of garbage. Need a way
* to determine player facing direction without
* hacking into the compass, and also do accurate
* turns.
*/
if(delta_x == -1 && delta_y == 0) {
// west
target_facing = 4;
@ -123,9 +131,21 @@ void Autowalker::rotate_player(Point current, Point target) {
} else if(delta_x == 0 && delta_y == -1) {
// north
target_facing = 6;
} else if(delta_x == 1 && delta_y == -1) {
// north east
target_facing = 5;
} else if(delta_x == 1 && delta_y == 1) {
// south east
target_facing = 1;
} else if(delta_x == -1 && delta_y == 1) {
// south west
target_facing = 3;
} else if(delta_x == -1 && delta_y == -1) {
// north west
target_facing = 5;
} else {
dbc::sentinel(
fmt::format("got more than 4 direction result: "
fmt::format("got more than 8 direction result: "
"current={},{} "
"target={},{} "
"delta={},{} ",
@ -197,31 +217,30 @@ void Autowalker::autowalk() {
// need a test for plan complete and only action is END
for(auto action : a_plan.script) {
if(action.$name == "find_enemy") {
if(action.name == "find_enemy") {
// this is where to test if enemy found and update state
fmt::println("FINDING AN ENEMY");
auto paths = path_to_enemies();
auto pos = get_current_position();
matrix::dump("FINDING", paths.$paths, pos.x, pos.y);
process_move(paths);
} else if(action.$name == "kill_enemy") {
send_event(gui::Event::ATTACK);
} else if(action.name == "kill_enemy") {
fmt::println("KILLING ENEMY");
process_combat();
} else if(action.$name == "find_healing") {
} else if(action.name == "find_healing") {
fmt::println("FINDING HEALING");
auto paths = path_to_items();
process_move(paths);
// do the path to healing thing
} else if(action.$name == "collect_items") {
} else if(action.name == "collect_items") {
fmt::println("COLLECTING ITEMS");
auto paths = path_to_items();
process_move(paths);
// path to the items and get them all
} else if(action.$name == "END") {
} else if(action == ai::FINAL_ACTION) {
fmt::println("END STATE, complete? {}", a_plan.complete);
fsm.autowalking = false;
} else {
fmt::println("Unknown action: {}", action.$name);
fmt::println("Unknown action: {}", action.name);
}
move_attempts++;