Needed to rewrite the pathing to get this to work. I actually had been using a purposefully broken pathing algorithm from when I was making random maps.
This commit is contained in:
parent
c894f6e094
commit
e92fd2b6f3
10 changed files with 169 additions and 111 deletions
77
pathing.cpp
77
pathing.cpp
|
@ -74,73 +74,40 @@ void Pathing::clear_target(const Point &at) {
|
|||
$input[at.y][at.x] = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a weird discovery, but if you randomly select a starting point on
|
||||
* the 8 compass, but only check 4 directions from there, it does the best
|
||||
* pathing so far. It will walk around items, navigate around enemies, find
|
||||
* paths through corners, etc. If you change slice_count/dist_count to just
|
||||
* 4 it fails more frequently.
|
||||
*
|
||||
* Look in the autowalker.cpp:path_player function for an example of what
|
||||
* I'm doing. I start with 4/8 and it finds paths 99% of the time, but
|
||||
* if that fails I do a full 8 direction search. This weirdly finds the
|
||||
* best directions to go more often.
|
||||
*/
|
||||
bool Pathing::random_walk(Point &out, bool random,
|
||||
int direction, size_t slice_count, size_t dist_size)
|
||||
PathingResult Pathing::find_path(Point &out, int direction, bool diag)
|
||||
{
|
||||
bool zero_found = false;
|
||||
|
||||
// first 4 directions are n/s/e/w for most enemies
|
||||
std::array<Point, DIRECTION_MAX> dirs{{
|
||||
{out.x,out.y-1}, // north
|
||||
{out.x+1,out.y}, // east
|
||||
{out.x,out.y+1}, // south
|
||||
{out.x-1,out.y}, // west
|
||||
|
||||
// the player and some enemies are more "agile"
|
||||
{out.x+1,out.y-1}, // north east
|
||||
{out.x+1,out.y+1}, // south east
|
||||
{out.x-1,out.y+1}, // south west
|
||||
{out.x-1,out.y-1} // north west
|
||||
}};
|
||||
|
||||
dbc::check(slice_count <= dirs.size(), "slize_count must be <= DIRECTION_MAX");
|
||||
dbc::check(dist_size <= dirs.size(), "dist_size must be <= DIRECTION_MAX");
|
||||
(void)diag;
|
||||
|
||||
// get the current dijkstra number
|
||||
int cur = $paths[out.y][out.x];
|
||||
|
||||
// pick a random start of directions
|
||||
int rand_start = Random::uniform<int>(0, dist_size);
|
||||
int target = cur;
|
||||
bool found = false;
|
||||
|
||||
// go through all possible directions
|
||||
for(size_t i = 0; i < slice_count; i++) {
|
||||
// but start at the random start, effectively randomizing
|
||||
// which valid direction to go
|
||||
// BUG: this might be wrong given the above ranom from 0-size
|
||||
Point dir = dirs[(i + rand_start) % dist_size];
|
||||
if(!shiterator::inbounds($paths, dir.x, dir.y)) continue; //skip unpathable stuff
|
||||
int weight = cur - $paths[dir.y][dir.x];
|
||||
for(matrix::box it{$paths, out.x, out.y, 1}; it.next();) {
|
||||
target = $paths[it.y][it.x];
|
||||
// don't go through walls
|
||||
if(target == WALL_PATH_LIMIT) continue;
|
||||
|
||||
int weight = cur - target;
|
||||
|
||||
if(weight == direction) {
|
||||
// no matter what we follow direct paths
|
||||
out = dir;
|
||||
return true;
|
||||
} else if(random && weight == 0) {
|
||||
// if random is selected and it's a 0 path take it
|
||||
out = dir;
|
||||
return true;
|
||||
out = {(size_t)it.x, (size_t)it.y};
|
||||
found = true;
|
||||
break;
|
||||
} else if(weight == 0) {
|
||||
// otherwise keep the last zero path for after
|
||||
out = dir;
|
||||
zero_found = true;
|
||||
out = {(size_t)it.x, (size_t)it.y};
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if we reach this then either zero was found and
|
||||
// zero_found is set true, or it wasn't and nothing found
|
||||
return zero_found;
|
||||
if(target == 0) {
|
||||
return PathingResult::FOUND;
|
||||
} else if(!found) {
|
||||
return PathingResult::FAIL;
|
||||
} else {
|
||||
return PathingResult::CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
bool Pathing::INVARIANT() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue