[Scummvm-git-logs] scummvm master -> 853c225331b17d58687bc109399a59c2dca0229a
tag2015
noreply at scummvm.org
Fri May 3 15:29:01 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
853c225331 AGS: Engine: fix legacy pathfinder imprecision in some old games
Commit: 853c225331b17d58687bc109399a59c2dca0229a
https://github.com/scummvm/scummvm/commit/853c225331b17d58687bc109399a59c2dca0229a
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2024-05-03T17:24:08+02:00
Commit Message:
AGS: Engine: fix legacy pathfinder imprecision in some old games
This complements c3a0553e25983651f4f823503e9c56ba8bcd3432
adding a configurable parameter. There are no functional differences
>From upstream 1c226816e2c3c9c18c3afb976e05535401fc5db4
Changed paths:
engines/ags/engine/ac/route_finder_impl_legacy.cpp
diff --git a/engines/ags/engine/ac/route_finder_impl_legacy.cpp b/engines/ags/engine/ac/route_finder_impl_legacy.cpp
index 53d969bb769..8e66f045e33 100644
--- a/engines/ags/engine/ac/route_finder_impl_legacy.cpp
+++ b/engines/ags/engine/ac/route_finder_impl_legacy.cpp
@@ -61,6 +61,18 @@ static int suggestx;
static int suggesty;
static int line_failed = 0;
+// Configuration for the pathfinder
+struct PathfinderConfig {
+ const int MaxGranularity = 3;
+
+ // Short sweep is performed in certain radius around requested destination,
+ // when searching for a nearest walkable area in the vicinity
+ const int ShortSweepRadius = 50;
+ int ShortSweepGranularity = 3; // variable, depending on loaded game version
+ // Full sweep is performed over a whole walkable area
+ const int FullSweepGranularity = 5;
+};
+
void init_pathfinder() {
pathbackx = (int *)malloc(sizeof(int) * MAXPATHBACK);
pathbacky = (int *)malloc(sizeof(int) * MAXPATHBACK);
@@ -138,9 +150,8 @@ int find_nearest_walkable_area(Bitmap *tempw, int fromX, int fromY, int toX, int
return 0;
}
-#define MAX_GRANULARITY 3
static int walk_area_granularity[MAX_WALK_AREAS + 1];
-static int is_route_possible(int fromx, int fromy, int tox, int toy, Bitmap *wss) {
+static int is_route_possible(int fromx, int fromy, int tox, int toy, Bitmap *wss, const PathfinderConfig &pfc) {
_G(wallscreen) = wss;
suggestx = -1;
@@ -203,41 +214,37 @@ static int is_route_possible(int fromx, int fromy, int tox, int toy, Bitmap *wss
// find the average "width" of a path in this walkable area
for (dd = 1; dd <= MAX_WALK_AREAS; dd++) {
if (walk_area_times[dd] == 0) {
- walk_area_granularity[dd] = MAX_GRANULARITY;
+ walk_area_granularity[dd] = pfc.MaxGranularity;
continue;
}
walk_area_granularity[dd] /= walk_area_times[dd];
if (walk_area_granularity[dd] <= 4)
walk_area_granularity[dd] = 2;
- // NB: Since MAX_GRANULARITY is 3, the following code is redundant causing compiler warnings
+ // NB: Since pfc.MaxGranularity is 3, the following code is redundant causing compiler warnings
#if 0
else if (walk_area_granularity[dd] <= 15)
walk_area_granularity[dd] = 3;
#endif
else
- walk_area_granularity[dd] = MAX_GRANULARITY;
+ walk_area_granularity[dd] = pfc.MaxGranularity;
#ifdef DEBUG_PATHFINDER
AGS::Shared::Debug::Printf("area %d: Gran %d", dd, walk_area_granularity[dd]);
#endif
}
- walk_area_granularity[0] = MAX_GRANULARITY;
+ walk_area_granularity[0] = pfc.MaxGranularity;
tempw->FloodFill(fromx, fromy, 232);
if (tempw->GetPixel(tox, toy) != 232) {
// Destination pixel is not walkable
- // Try the 100x100 square around the target first at 3-pixel granularity
- int tryFirstX = tox - 50, tryToX = tox + 50;
- int tryFirstY = toy - 50, tryToY = toy + 50;
-
- // This is a fix for the Treppenbug in old (pre-3.0) Maniac Mansion Mania games.
- // Using a higher granularity the find_nearest_walkable_area sets a wrong coordinate that prevents
- // the staircase in Bernard's home from working.
- int sweep_granularity = _G(loaded_game_file_version) > kGameVersion_272 ? 3 : 1;
- if (!find_nearest_walkable_area(tempw, tryFirstX, tryFirstY, tryToX, tryToY, tox, toy, sweep_granularity)) {
+ // Try the N x N square around the target first at 3-pixel granularity
+ int tryFirstX = tox - pfc.ShortSweepRadius, tryToX = tox + pfc.ShortSweepRadius;
+ int tryFirstY = toy - pfc.ShortSweepRadius, tryToY = toy + pfc.ShortSweepRadius;
+
+ if (!find_nearest_walkable_area(tempw, tryFirstX, tryFirstY, tryToX, tryToY, tox, toy, pfc.ShortSweepGranularity)) {
// Nothing found, sweep the whole room at 5 pixel granularity
- find_nearest_walkable_area(tempw, 0, 0, tempw->GetWidth(), tempw->GetHeight(), tox, toy, 5);
+ find_nearest_walkable_area(tempw, 0, 0, tempw->GetWidth(), tempw->GetHeight(), tox, toy, pfc.FullSweepGranularity);
}
delete tempw;
@@ -401,7 +408,7 @@ static void round_down_coords(int &tmpx, int &tmpy) {
}
}
-static int find_route_dijkstra(int fromx, int fromy, int destx, int desty) {
+static int find_route_dijkstra(int fromx, int fromy, int destx, int desty, const PathfinderConfig &pfc) {
int i, j;
assert(_G(wallscreen) != nullptr);
@@ -437,10 +444,10 @@ static int find_route_dijkstra(int fromx, int fromy, int destx, int desty) {
int granularity = 3, newx = -1, newy, foundAnswer = -1, numreplace;
int changeiter, numfound, adjcount;
- int destxlow = destx - MAX_GRANULARITY;
- int destylow = desty - MAX_GRANULARITY;
- int destxhi = destxlow + MAX_GRANULARITY * 2;
- int destyhi = destylow + MAX_GRANULARITY * 2;
+ int destxlow = destx - pfc.MaxGranularity;
+ int destylow = desty - pfc.MaxGranularity;
+ int destxhi = destxlow + pfc.MaxGranularity * 2;
+ int destyhi = destylow + pfc.MaxGranularity * 2;
int modifier = 0;
int totalfound = 0;
int DIRECTION_BONUS = 0;
@@ -507,10 +514,10 @@ static int find_route_dijkstra(int fromx, int fromy, int destx, int desty) {
// edges of screen pose a problem, so if current and dest are within
// certain distance of the edge, say we've got it
- if ((newx >= _G(wallscreen)->GetWidth() - MAX_GRANULARITY) && (destx >= _G(wallscreen)->GetWidth() - MAX_GRANULARITY))
+ if ((newx >= _G(wallscreen)->GetWidth() - pfc.MaxGranularity) && (destx >= _G(wallscreen)->GetWidth() - pfc.MaxGranularity))
newx = destx;
- if ((newy >= _G(wallscreen)->GetHeight() - MAX_GRANULARITY) && (desty >= _G(wallscreen)->GetHeight() - MAX_GRANULARITY))
+ if ((newy >= _G(wallscreen)->GetHeight() - pfc.MaxGranularity) && (desty >= _G(wallscreen)->GetHeight() - pfc.MaxGranularity))
newy = desty;
// Found the desination, abort loop
@@ -582,7 +589,7 @@ static int find_route_dijkstra(int fromx, int fromy, int destx, int desty) {
return 1;
}
-static int __find_route(int srcx, int srcy, short *tox, short *toy, int noredx) {
+static int __find_route(int srcx, int srcy, short *tox, short *toy, int noredx, const PathfinderConfig &pfc) {
assert(_G(wallscreen) != nullptr);
assert(beenhere != nullptr);
assert(tox != nullptr);
@@ -602,7 +609,7 @@ findroutebk:
return 1;
}
- if ((waspossible = is_route_possible(srcx, srcy, tox[0], toy[0], _G(wallscreen))) == 0) {
+ if ((waspossible = is_route_possible(srcx, srcy, tox[0], toy[0], _G(wallscreen), pfc)) == 0) {
if (suggestx >= 0) {
tox[0] = suggestx;
toy[0] = suggesty;
@@ -618,7 +625,7 @@ findroutebk:
}
// Try the new pathfinding algorithm
- if (find_route_dijkstra(srcx, srcy, tox[0], toy[0])) {
+ if (find_route_dijkstra(srcx, srcy, tox[0], toy[0], pfc)) {
return 1;
}
@@ -729,6 +736,11 @@ int find_route(short srcx, short srcy, short xx, short yy, int move_speed_x, int
assert(pathbackx != nullptr);
assert(pathbacky != nullptr);
+ // Setup pathfinder configuration, depending on the loaded game version;
+ // sweep granularity has changed between 3.0.0 and 3.0.1; see issue #663
+ PathfinderConfig pfc;
+ pfc.ShortSweepGranularity = (_G(loaded_game_file_version) > kGameVersion_300) ? 3 : 1;
+
#ifdef DEBUG_PATHFINDER
// __wnormscreen();
#endif
@@ -761,9 +773,9 @@ int find_route(short srcx, short srcy, short xx, short yy, int move_speed_x, int
for (aaa = 1; aaa < _G(wallscreen)->GetHeight(); aaa++)
beenhere[aaa] = beenhere[0] + aaa * (_G(wallscreen)->GetWidth());
- if (__find_route(srcx, srcy, &xx, &yy, nocross) == 0) {
+ if (__find_route(srcx, srcy, &xx, &yy, nocross, pfc) == 0) {
leftorright = 1;
- if (__find_route(srcx, srcy, &xx, &yy, nocross) == 0)
+ if (__find_route(srcx, srcy, &xx, &yy, nocross, pfc) == 0)
pathbackstage = -1;
}
free(beenhere[0]);
More information about the Scummvm-git-logs
mailing list