From 45013a90cc24aea587e45237bf96024d7e68a684 Mon Sep 17 00:00:00 2001 From: LordOfLunacy <64547205+LordOfLunacy@users.noreply.github.com> Date: Fri, 13 May 2022 19:18:46 -0400 Subject: [PATCH 1/6] Part of pathfinding rework --- src/openrct2/GameState.cpp | 4 +++ src/openrct2/entity/Peep.cpp | 3 +- src/openrct2/entity/Peep.h | 2 +- src/openrct2/entity/Staff.cpp | 8 +++-- src/openrct2/peep/GuestPathfinding.cpp | 18 +++++----- src/openrct2/peep/GuestPathfinding.h | 47 ++++++++++++++++++++------ test/tests/Pathfinding.cpp | 3 +- 7 files changed, 59 insertions(+), 26 deletions(-) diff --git a/src/openrct2/GameState.cpp b/src/openrct2/GameState.cpp index 08a196cefa..190017df95 100644 --- a/src/openrct2/GameState.cpp +++ b/src/openrct2/GameState.cpp @@ -27,6 +27,7 @@ #include "localisation/Localisation.h" #include "management/NewsItem.h" #include "network/network.h" +#include "./peep/GuestPathfinding.h" #include "platform/Platform.h" #include "profiling/Profiling.h" #include "ride/Vehicle.h" @@ -88,6 +89,9 @@ void GameState::InitAll(const TileCoordsXY& mapSize) CheatsReset(); ClearRestrictedScenery(); + // TODO: find a better place for this + gGuestPathfinder = new OriginalPathfinding(); + #ifdef ENABLE_SCRIPTING auto& scriptEngine = GetContext()->GetScriptEngine(); scriptEngine.ClearParkStorage(); diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index f95c868104..a096212f11 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -81,6 +81,7 @@ static void* _crowdSoundChannel = nullptr; static void peep_128_tick_update(Peep* peep, int32_t index); static void peep_release_balloon(Guest* peep, int16_t spawn_height); + static PeepActionSpriteType PeepSpecialSpriteToSpriteTypeMap[] = { PeepActionSpriteType::None, PeepActionSpriteType::HoldMat, @@ -2357,7 +2358,7 @@ void Peep::PerformNextAction(uint8_t& pathing_result, TileElement*& tile_result) if (guest != nullptr) { - result = guest_path_finding(guest); + result = gGuestPathfinder->guest_path_finding(guest); } else { diff --git a/src/openrct2/entity/Peep.h b/src/openrct2/entity/Peep.h index b59201fc70..9ba98efbbb 100644 --- a/src/openrct2/entity/Peep.h +++ b/src/openrct2/entity/Peep.h @@ -399,7 +399,7 @@ public: // Peep bool IsActionInterruptable() const; // Reset the peep's stored goal, which means they will forget any stored pathfinding history - // on the next peep_pathfind_choose_direction call. + // on the next GuestPathfinding::peep_pathfind_choose_direction call. void ResetPathfindGoal(); void SetDestination(const CoordsXY& coords); diff --git a/src/openrct2/entity/Staff.cpp b/src/openrct2/entity/Staff.cpp index d703d79174..ae9a54904c 100644 --- a/src/openrct2/entity/Staff.cpp +++ b/src/openrct2/entity/Staff.cpp @@ -66,6 +66,8 @@ colour_t gStaffHandymanColour; colour_t gStaffMechanicColour; colour_t gStaffSecurityColour; +GuestPathfinding* gGuestPathfinder; + // Maximum manhattan distance that litter can be for a handyman to seek to it const uint16_t MAX_LITTER_DISTANCE = 3 * COORDS_XY_STEP; @@ -181,7 +183,7 @@ bool Staff::CanIgnoreWideFlag(const CoordsXYZ& staffPos, TileElement* path) cons } /* test_element is a path */ - if (!IsValidPathZAndDirection(test_element, adjacPos.z / COORDS_Z_STEP, adjac_dir)) + if (!GuestPathfinding::IsValidPathZAndDirection(test_element, adjacPos.z / COORDS_Z_STEP, adjac_dir)) continue; /* test_element is a connected path */ @@ -722,7 +724,7 @@ Direction Staff::MechanicDirectionPath(uint8_t validDirections, PathElement* pat PathfindLoggingEnable(this); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 - Direction pathfindDirection = peep_pathfind_choose_direction(TileCoordsXYZ{ NextLoc }, this); + Direction pathfindDirection = gGuestPathfinder->peep_pathfind_choose_direction(TileCoordsXYZ{ NextLoc }, this); #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 PathfindLoggingDisable(); @@ -732,7 +734,7 @@ Direction Staff::MechanicDirectionPath(uint8_t validDirections, PathElement* pat { /* Heuristic search failed for all directions. * Reset the PathfindGoal - this means that the PathfindHistory - * will be reset in the next call to peep_pathfind_choose_direction(). + * will be reset in the next call to GuestPathfinding::peep_pathfind_choose_direction(). * This lets the heuristic search "try again" in case the player has * edited the path layout or the mechanic was already stuck in the * save game (e.g. with a worse version of the pathfinding). */ diff --git a/src/openrct2/peep/GuestPathfinding.cpp b/src/openrct2/peep/GuestPathfinding.cpp index 3b4056ad3f..2739153716 100644 --- a/src/openrct2/peep/GuestPathfinding.cpp +++ b/src/openrct2/peep/GuestPathfinding.cpp @@ -289,7 +289,7 @@ static uint8_t footpath_element_next_in_direction(TileCoordsXYZ loc, PathElement continue; if (nextTileElement->GetType() != TileElementType::Path) continue; - if (!IsValidPathZAndDirection(nextTileElement, loc.z, chosenDirection)) + if (!GuestPathfinding::IsValidPathZAndDirection(nextTileElement, loc.z, chosenDirection)) continue; if (nextTileElement->AsPath()->IsWide()) return PATH_SEARCH_WIDE; @@ -382,7 +382,7 @@ static uint8_t footpath_element_dest_in_dir(TileCoordsXYZ loc, Direction chosenD break; case TileElementType::Path: { - if (!IsValidPathZAndDirection(tileElement, loc.z, chosenDirection)) + if (!GuestPathfinding::IsValidPathZAndDirection(tileElement, loc.z, chosenDirection)) continue; if (tileElement->AsPath()->IsWide()) return PATH_SEARCH_WIDE; @@ -824,7 +824,7 @@ static void peep_pathfind_heuristic_search( * queue path. * Otherwise, peeps walk on path tiles to get to the goal. */ - if (!IsValidPathZAndDirection(tileElement, loc.z, test_edge)) + if (!GuestPathfinding::IsValidPathZAndDirection(tileElement, loc.z, test_edge)) continue; // Path may be sloped, so set z to path base height. @@ -1261,7 +1261,7 @@ static void peep_pathfind_heuristic_search( * * rct2: 0x0069A5F0 */ -Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) +Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) { PROFILED_FUNCTION(); @@ -1661,7 +1661,7 @@ static std::optional GetNearestParkEntrance(const CoordsXY& loc) * * rct2: 0x006952C0 */ -static int32_t GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges) +int32_t OriginalPathfinding::GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges) { // Send peeps to the nearest park entrance. auto chosenEntrance = GetNearestParkEntrance(peep->NextLoc); @@ -1710,7 +1710,7 @@ static uint8_t get_nearest_peep_spawn_index(uint16_t x, uint16_t y) * * rct2: 0x0069536C */ -static int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges) +int32_t OriginalPathfinding::GuestPathFindPeepSpawn(Peep* peep, uint8_t edges) { // Send peeps to the nearest spawn point. uint8_t chosenSpawn = get_nearest_peep_spawn_index(peep->NextLoc.x, peep->NextLoc.y); @@ -1741,7 +1741,7 @@ static int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges) * * rct2: 0x00695161 */ -static int32_t GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges) +int32_t OriginalPathfinding::GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges) { TileCoordsXYZ entranceGoal{}; if (peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN) @@ -1971,7 +1971,7 @@ static StationIndex guest_pathfinding_select_random_station( * * rct2: 0x00694C35 */ -int32_t guest_path_finding(Guest* peep) +int32_t OriginalPathfinding::guest_path_finding(Guest* peep) { #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 PathfindLoggingEnable(peep); @@ -2266,7 +2266,7 @@ int32_t guest_path_finding(Guest* peep) return peep_move_one_tile(direction, peep); } -bool IsValidPathZAndDirection(TileElement* tileElement, int32_t currentZ, int32_t currentDirection) +bool GuestPathfinding::IsValidPathZAndDirection(TileElement* tileElement, int32_t currentZ, int32_t currentDirection) { if (tileElement->AsPath()->IsSloped()) { diff --git a/src/openrct2/peep/GuestPathfinding.h b/src/openrct2/peep/GuestPathfinding.h index 5c7fde32b4..3e409de77c 100644 --- a/src/openrct2/peep/GuestPathfinding.h +++ b/src/openrct2/peep/GuestPathfinding.h @@ -17,6 +17,8 @@ struct Peep; struct Guest; struct TileElement; + + // The tile position of the place the peep is trying to get to (park entrance/exit, ride // entrance/exit, or the end of the queue line for a ride). // @@ -37,19 +39,42 @@ extern RideId gPeepPathFindQueueRideIndex; // In practice, if this is false, gPeepPathFindQueueRideIndex is always RIDE_ID_NULL. extern bool gPeepPathFindIgnoreForeignQueues; -// Given a peep 'peep' at tile 'loc', who is trying to get to 'gPeepPathFindGoalPosition', decide -// the direction the peep should walk in from the current tile. -Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep); +class GuestPathfinding +{ +public: + // Given a peep 'peep' at tile 'loc', who is trying to get to 'gPeepPathFindGoalPosition', decide + // the direction the peep should walk in from the current tile. + virtual Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) = 0; -// Test whether the given tile can be walked onto, if the peep is currently at height currentZ and -// moving in direction currentDirection. -bool IsValidPathZAndDirection(TileElement* tileElement, int32_t currentZ, int32_t currentDirection); + // Test whether the given tile can be walked onto, if the peep is currently at height currentZ and + // moving in direction currentDirection. + static bool IsValidPathZAndDirection(TileElement* tileElement, int32_t currentZ, int32_t currentDirection); -// Overall guest pathfinding AI. Sets up Peep::DestinationX/DestinationY (which they move to in a -// straight line, no pathfinding). Called whenever the guest has arrived at their previously set destination. -// -// Returns 0 if the guest has successfully had a new destination set up, nonzero otherwise. -int32_t guest_path_finding(Guest* peep); + // Overall guest pathfinding AI. Sets up Peep::DestinationX/DestinationY (which they move to in a + // straight line, no pathfinding). Called whenever the guest has arrived at their previously set destination. + // + // Returns 0 if the guest has successfully had a new destination set up, nonzero otherwise. + virtual int32_t guest_path_finding(Guest* peep) = 0; + +}; + +class OriginalPathfinding : public GuestPathfinding +{ +public: + Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep); + + int32_t guest_path_finding(Guest* peep); + +private: + int32_t GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges); + + int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges); + + int32_t GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges); +}; + +//TODO: Implement a better solution than a global variable for the utilized pathfinder +extern GuestPathfinding* gGuestPathfinder; #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 # define PATHFIND_DEBUG \ diff --git a/test/tests/Pathfinding.cpp b/test/tests/Pathfinding.cpp index 8816d2a2d1..35beed443c 100644 --- a/test/tests/Pathfinding.cpp +++ b/test/tests/Pathfinding.cpp @@ -16,6 +16,7 @@ using namespace OpenRCT2; + static std::ostream& operator<<(std::ostream& os, const TileCoordsXYZ& coords) { return os << "(" << coords.x << ", " << coords.y << ", " << coords.z << ")"; @@ -84,7 +85,7 @@ protected: // Pick the direction the peep should initially move in, given the goal position. // This will also store the goal position and initialize pathfinding data for the peep. gPeepPathFindGoalPosition = goal; - const Direction moveDir = peep_pathfind_choose_direction(*pos, peep); + const Direction moveDir = gGuestPathfinder->peep_pathfind_choose_direction(*pos, peep); if (moveDir == INVALID_DIRECTION) { // Couldn't determine a direction to move off in From eddda64e20fc55f4eab6651bb9b723518b9887b7 Mon Sep 17 00:00:00 2001 From: LordOfLunacy <64547205+LordOfLunacy@users.noreply.github.com> Date: Fri, 13 May 2022 19:59:47 -0400 Subject: [PATCH 2/6] Fixed formatting --- src/openrct2/GameState.cpp | 2 +- src/openrct2/entity/Peep.cpp | 1 - src/openrct2/peep/GuestPathfinding.h | 5 +---- test/tests/Pathfinding.cpp | 1 - 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/openrct2/GameState.cpp b/src/openrct2/GameState.cpp index 190017df95..70ec004eda 100644 --- a/src/openrct2/GameState.cpp +++ b/src/openrct2/GameState.cpp @@ -9,6 +9,7 @@ #include "GameState.h" +#include "./peep/GuestPathfinding.h" #include "Context.h" #include "Editor.h" #include "Game.h" @@ -27,7 +28,6 @@ #include "localisation/Localisation.h" #include "management/NewsItem.h" #include "network/network.h" -#include "./peep/GuestPathfinding.h" #include "platform/Platform.h" #include "profiling/Profiling.h" #include "ride/Vehicle.h" diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index a096212f11..bdf0fd01b2 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -81,7 +81,6 @@ static void* _crowdSoundChannel = nullptr; static void peep_128_tick_update(Peep* peep, int32_t index); static void peep_release_balloon(Guest* peep, int16_t spawn_height); - static PeepActionSpriteType PeepSpecialSpriteToSpriteTypeMap[] = { PeepActionSpriteType::None, PeepActionSpriteType::HoldMat, diff --git a/src/openrct2/peep/GuestPathfinding.h b/src/openrct2/peep/GuestPathfinding.h index 3e409de77c..9222e2f635 100644 --- a/src/openrct2/peep/GuestPathfinding.h +++ b/src/openrct2/peep/GuestPathfinding.h @@ -17,8 +17,6 @@ struct Peep; struct Guest; struct TileElement; - - // The tile position of the place the peep is trying to get to (park entrance/exit, ride // entrance/exit, or the end of the queue line for a ride). // @@ -55,7 +53,6 @@ public: // // Returns 0 if the guest has successfully had a new destination set up, nonzero otherwise. virtual int32_t guest_path_finding(Guest* peep) = 0; - }; class OriginalPathfinding : public GuestPathfinding @@ -73,7 +70,7 @@ private: int32_t GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges); }; -//TODO: Implement a better solution than a global variable for the utilized pathfinder +// TODO: Implement a better solution than a global variable for the utilized pathfinder extern GuestPathfinding* gGuestPathfinder; #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 diff --git a/test/tests/Pathfinding.cpp b/test/tests/Pathfinding.cpp index 35beed443c..faf1c35503 100644 --- a/test/tests/Pathfinding.cpp +++ b/test/tests/Pathfinding.cpp @@ -16,7 +16,6 @@ using namespace OpenRCT2; - static std::ostream& operator<<(std::ostream& os, const TileCoordsXYZ& coords) { return os << "(" << coords.x << ", " << coords.y << ", " << coords.z << ")"; From 4436289ff7b47d5a74af8ccde5f708ab3491e26a Mon Sep 17 00:00:00 2001 From: LordOfLunacy <64547205+LordOfLunacy@users.noreply.github.com> Date: Fri, 13 May 2022 20:25:58 -0400 Subject: [PATCH 3/6] Add appropriate tags to functions --- src/openrct2/peep/GuestPathfinding.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/openrct2/peep/GuestPathfinding.h b/src/openrct2/peep/GuestPathfinding.h index 9222e2f635..a68239e1f9 100644 --- a/src/openrct2/peep/GuestPathfinding.h +++ b/src/openrct2/peep/GuestPathfinding.h @@ -40,6 +40,10 @@ extern bool gPeepPathFindIgnoreForeignQueues; class GuestPathfinding { public: + GuestPathfinding() = delete; + + virtual ~GuestPathfinding() = default; + // Given a peep 'peep' at tile 'loc', who is trying to get to 'gPeepPathFindGoalPosition', decide // the direction the peep should walk in from the current tile. virtual Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) = 0; @@ -58,9 +62,9 @@ public: class OriginalPathfinding : public GuestPathfinding { public: - Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep); + Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) final override; - int32_t guest_path_finding(Guest* peep); + int32_t guest_path_finding(Guest* peep) final override; private: int32_t GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges); From 68fa8255244702c06f5d005a6683deaa6e7f83bc Mon Sep 17 00:00:00 2001 From: LordOfLunacy <64547205+LordOfLunacy@users.noreply.github.com> Date: Fri, 13 May 2022 20:39:42 -0400 Subject: [PATCH 4/6] Fixed constructor goof 4th times the charm? --- src/openrct2/peep/GuestPathfinding.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/openrct2/peep/GuestPathfinding.h b/src/openrct2/peep/GuestPathfinding.h index a68239e1f9..cf6324ab45 100644 --- a/src/openrct2/peep/GuestPathfinding.h +++ b/src/openrct2/peep/GuestPathfinding.h @@ -40,7 +40,6 @@ extern bool gPeepPathFindIgnoreForeignQueues; class GuestPathfinding { public: - GuestPathfinding() = delete; virtual ~GuestPathfinding() = default; From 428f7bd9ecc12c7b9e1049a1fcbc2e7c39829e63 Mon Sep 17 00:00:00 2001 From: LordOfLunacy <64547205+LordOfLunacy@users.noreply.github.com> Date: Fri, 13 May 2022 20:41:59 -0400 Subject: [PATCH 5/6] Fix formatting You can tell I'm new at this --- src/openrct2/peep/GuestPathfinding.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/openrct2/peep/GuestPathfinding.h b/src/openrct2/peep/GuestPathfinding.h index cf6324ab45..bb6d08b60e 100644 --- a/src/openrct2/peep/GuestPathfinding.h +++ b/src/openrct2/peep/GuestPathfinding.h @@ -40,7 +40,6 @@ extern bool gPeepPathFindIgnoreForeignQueues; class GuestPathfinding { public: - virtual ~GuestPathfinding() = default; // Given a peep 'peep' at tile 'loc', who is trying to get to 'gPeepPathFindGoalPosition', decide From fa71bbc1b2541fee78326826ae5eae80b3bf35d7 Mon Sep 17 00:00:00 2001 From: LordOfLunacy <64547205+LordOfLunacy@users.noreply.github.com> Date: Sat, 14 May 2022 15:28:24 -0400 Subject: [PATCH 6/6] Implement requested changes - Change the GuestPathfinder object to a smart pointer - Improved function signatures - Added javadoc comments to the abstract base class - Converted pointers to references in pathfinding function calls --- src/openrct2/GameState.cpp | 3 - src/openrct2/entity/Peep.cpp | 4 +- src/openrct2/entity/Peep.h | 2 +- src/openrct2/entity/Staff.cpp | 8 +- src/openrct2/peep/GuestPathfinding.cpp | 206 +++++++++++++------------ src/openrct2/peep/GuestPathfinding.h | 51 +++--- test/tests/Pathfinding.cpp | 2 +- 7 files changed, 145 insertions(+), 131 deletions(-) diff --git a/src/openrct2/GameState.cpp b/src/openrct2/GameState.cpp index 70ec004eda..11b4740a42 100644 --- a/src/openrct2/GameState.cpp +++ b/src/openrct2/GameState.cpp @@ -89,9 +89,6 @@ void GameState::InitAll(const TileCoordsXY& mapSize) CheatsReset(); ClearRestrictedScenery(); - // TODO: find a better place for this - gGuestPathfinder = new OriginalPathfinding(); - #ifdef ENABLE_SCRIPTING auto& scriptEngine = GetContext()->GetScriptEngine(); scriptEngine.ClearParkStorage(); diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index bdf0fd01b2..3e2e6b28a7 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -73,6 +73,8 @@ uint32_t gNextGuestNumber; uint8_t gPeepWarningThrottle[16]; +std::unique_ptr gGuestPathfinder = std::make_unique(); + static uint8_t _unk_F1AEF0; static TileElement* _peepRideEntranceExitElement; @@ -2357,7 +2359,7 @@ void Peep::PerformNextAction(uint8_t& pathing_result, TileElement*& tile_result) if (guest != nullptr) { - result = gGuestPathfinder->guest_path_finding(guest); + result = gGuestPathfinder->CalculateNextDestination(*guest); } else { diff --git a/src/openrct2/entity/Peep.h b/src/openrct2/entity/Peep.h index 9ba98efbbb..cedab9a448 100644 --- a/src/openrct2/entity/Peep.h +++ b/src/openrct2/entity/Peep.h @@ -399,7 +399,7 @@ public: // Peep bool IsActionInterruptable() const; // Reset the peep's stored goal, which means they will forget any stored pathfinding history - // on the next GuestPathfinding::peep_pathfind_choose_direction call. + // on the next GuestPathfinding::ChooseDirection call. void ResetPathfindGoal(); void SetDestination(const CoordsXY& coords); diff --git a/src/openrct2/entity/Staff.cpp b/src/openrct2/entity/Staff.cpp index ae9a54904c..7d34236353 100644 --- a/src/openrct2/entity/Staff.cpp +++ b/src/openrct2/entity/Staff.cpp @@ -66,8 +66,6 @@ colour_t gStaffHandymanColour; colour_t gStaffMechanicColour; colour_t gStaffSecurityColour; -GuestPathfinding* gGuestPathfinder; - // Maximum manhattan distance that litter can be for a handyman to seek to it const uint16_t MAX_LITTER_DISTANCE = 3 * COORDS_XY_STEP; @@ -721,10 +719,10 @@ Direction Staff::MechanicDirectionPath(uint8_t validDirections, PathElement* pat gPeepPathFindQueueRideIndex = RideId::GetNull(); #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 - PathfindLoggingEnable(this); + PathfindLoggingEnable(*this); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 - Direction pathfindDirection = gGuestPathfinder->peep_pathfind_choose_direction(TileCoordsXYZ{ NextLoc }, this); + Direction pathfindDirection = gGuestPathfinder->ChooseDirection(TileCoordsXYZ{ NextLoc }, *this); #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 PathfindLoggingDisable(); @@ -734,7 +732,7 @@ Direction Staff::MechanicDirectionPath(uint8_t validDirections, PathElement* pat { /* Heuristic search failed for all directions. * Reset the PathfindGoal - this means that the PathfindHistory - * will be reset in the next call to GuestPathfinding::peep_pathfind_choose_direction(). + * will be reset in the next call to GuestPathfinding::ChooseDirection(). * This lets the heuristic search "try again" in case the player has * edited the path layout or the mechanic was already stuck in the * save game (e.g. with a worse version of the pathfinding). */ diff --git a/src/openrct2/peep/GuestPathfinding.cpp b/src/openrct2/peep/GuestPathfinding.cpp index 2739153716..71a964d935 100644 --- a/src/openrct2/peep/GuestPathfinding.cpp +++ b/src/openrct2/peep/GuestPathfinding.cpp @@ -43,7 +43,7 @@ static bool _pathFindDebug = false; static utf8 _pathFindDebugPeepName[256]; #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 -static int32_t guest_surface_path_finding(Peep* peep); +static int32_t guest_surface_path_finding(Peep& peep); /* A junction history for the peep pathfinding heuristic search * The magic number 16 is the largest value returned by @@ -124,10 +124,10 @@ static int32_t path_get_permitted_edges(PathElement* pathElement) * * rct2: 0x0069524E */ -static int32_t peep_move_one_tile(Direction direction, Peep* peep) +static int32_t peep_move_one_tile(Direction direction, Peep& peep) { assert(direction_valid(direction)); - auto newTile = CoordsXY{ CoordsXY{ peep->NextLoc } + CoordsDirectionDelta[direction] }.ToTileCentre(); + auto newTile = CoordsXY{ CoordsXY{ peep.NextLoc } + CoordsDirectionDelta[direction] }.ToTileCentre(); if (newTile.x >= MAXIMUM_MAP_SIZE_BIG || newTile.y >= MAXIMUM_MAP_SIZE_BIG) { @@ -135,8 +135,8 @@ static int32_t peep_move_one_tile(Direction direction, Peep* peep) return guest_surface_path_finding(peep); } - peep->PeepDirection = direction; - if (peep->State != PeepState::Queuing) + peep.PeepDirection = direction; + if (peep.State != PeepState::Queuing) { // When peeps are walking along a path, we would like them to be spread out across the width of the path, // instead of all walking along the exact centre line of the path. @@ -159,19 +159,19 @@ static int32_t peep_move_one_tile(Direction direction, Peep* peep) if (direction == 0 || direction == 2) { // Peep is moving along X, so apply the offset to the X position of the destination and clamp their current Y - const int32_t centreLine = (peep->y & 0xFFE0) + COORDS_XY_HALF_TILE; + const int32_t centreLine = (peep.y & 0xFFE0) + COORDS_XY_HALF_TILE; newTile.x += offset; - newTile.y = std::clamp(peep->y, centreLine - 3, centreLine + 3); + newTile.y = std::clamp(peep.y, centreLine - 3, centreLine + 3); } else { // Peep is moving along Y, so apply the offset to the Y position of the destination and clamp their current X - const int32_t centreLine = (peep->x & 0xFFE0) + COORDS_XY_HALF_TILE; - newTile.x = std::clamp(peep->x, centreLine - 3, centreLine + 3); + const int32_t centreLine = (peep.x & 0xFFE0) + COORDS_XY_HALF_TILE; + newTile.x = std::clamp(peep.x, centreLine - 3, centreLine + 3); newTile.y += offset; } } - peep->SetDestination(newTile, 2); + peep.SetDestination(newTile, 2); return 0; } @@ -180,9 +180,9 @@ static int32_t peep_move_one_tile(Direction direction, Peep* peep) * * rct2: 0x00694C41 */ -static int32_t guest_surface_path_finding(Peep* peep) +static int32_t guest_surface_path_finding(Peep& peep) { - auto pathPos = CoordsXYRangedZ{ peep->NextLoc, peep->NextLoc.z, peep->NextLoc.z + PATH_CLEARANCE }; + auto pathPos = CoordsXYRangedZ{ peep.NextLoc, peep.NextLoc.z, peep.NextLoc.z + PATH_CLEARANCE }; Direction randDirection = scenario_rand() & 3; if (!fence_in_the_way(pathPos, randDirection)) @@ -208,8 +208,8 @@ static int32_t guest_surface_path_finding(Peep* peep) } randDirection &= 3; - pathPos.x = peep->NextLoc.x; - pathPos.y = peep->NextLoc.y; + pathPos.x = peep.NextLoc.x; + pathPos.y = peep.NextLoc.y; if (!fence_in_the_way(pathPos, randDirection)) { pathPos.x += CoordsDirectionDelta[randDirection].x; @@ -228,8 +228,8 @@ static int32_t guest_surface_path_finding(Peep* peep) randDirection -= 2; randDirection &= 3; - pathPos.x = peep->NextLoc.x; - pathPos.y = peep->NextLoc.y; + pathPos.x = peep.NextLoc.x; + pathPos.y = peep.NextLoc.y; if (!fence_in_the_way(pathPos, randDirection)) { pathPos.x += CoordsDirectionDelta[randDirection].x; @@ -460,14 +460,14 @@ static uint8_t footpath_element_destination_in_direction( * * rct2: 0x00695225 */ -static int32_t guest_path_find_aimless(Peep* peep, uint8_t edges) +static int32_t guest_path_find_aimless(Peep& peep, uint8_t edges) { if (scenario_rand() & 1) { // If possible go straight - if (edges & (1 << peep->PeepDirection)) + if (edges & (1 << peep.PeepDirection)) { - return peep_move_one_tile(peep->PeepDirection, peep); + return peep_move_one_tile(peep.PeepDirection, peep); } } @@ -486,21 +486,21 @@ static int32_t guest_path_find_aimless(Peep* peep, uint8_t edges) * * rct2: 0x0069A60A */ -static uint8_t peep_pathfind_get_max_number_junctions(Peep* peep) +static uint8_t peep_pathfind_get_max_number_junctions(Peep& peep) { - if (peep->Is()) + if (peep.Is()) return 8; // PEEP_FLAGS_2? It's cleared here but not set anywhere! - if ((peep->PeepFlags & PEEP_FLAGS_2)) + if ((peep.PeepFlags & PEEP_FLAGS_2)) { if ((scenario_rand() & 0xFFFF) <= 7281) - peep->PeepFlags &= ~PEEP_FLAGS_2; + peep.PeepFlags &= ~PEEP_FLAGS_2; return 8; } - auto* guest = peep->As(); + auto* guest = peep.As(); if (guest == nullptr) return 8; @@ -687,7 +687,7 @@ static constexpr const char* pathSearchToString(uint8_t pathFindSearchResult) * rct2: 0x0069A997 */ static void peep_pathfind_heuristic_search( - TileCoordsXYZ loc, Peep* peep, TileElement* currentTileElement, bool inPatrolArea, uint8_t counter, uint16_t* endScore, + TileCoordsXYZ loc, Peep& peep, TileElement* currentTileElement, bool inPatrolArea, uint8_t counter, uint16_t* endScore, Direction test_edge, uint8_t* endJunctions, TileCoordsXYZ junctionList[16], uint8_t directionList[16], TileCoordsXYZ* endXYZ, uint8_t* endSteps) { @@ -696,7 +696,7 @@ static void peep_pathfind_heuristic_search( bool currentElementIsWide = currentTileElement->AsPath()->IsWide(); if (currentElementIsWide) { - const Staff* staff = peep->As(); + const Staff* staff = peep.As(); if (staff != nullptr && staff->CanIgnoreWideFlag(loc.ToCoordsXYZ(), currentTileElement)) currentElementIsWide = false; } @@ -721,7 +721,7 @@ static void peep_pathfind_heuristic_search( } bool nextInPatrolArea = inPatrolArea; - auto* staff = peep->As(); + auto* staff = peep.As(); if (staff != nullptr && staff->IsMechanic()) { nextInPatrolArea = staff->IsLocationInPatrol(loc.ToCoordsXY()); @@ -1075,14 +1075,14 @@ static void peep_pathfind_heuristic_search( /* First check if going through the junction would be * a loop. If so, the current search path ends here. * Path finding loop detection can take advantage of both the - * peep->PathfindHistory - loops through remembered junctions + * peep.PathfindHistory - loops through remembered junctions * the peep has already passed through getting to its * current position while on the way to its current goal; * _peepPathFindHistory - loops in the current search path. */ bool pathLoop = false; - /* Check the peep->PathfindHistory to see if this junction has + /* Check the peep.PathfindHistory to see if this junction has * already been visited by the peep while heading for this goal. */ - for (auto& pathfindHistory : peep->PathfindHistory) + for (auto& pathfindHistory : peep.PathfindHistory) { if (pathfindHistory == loc) { @@ -1261,7 +1261,7 @@ static void peep_pathfind_heuristic_search( * * rct2: 0x0069A5F0 */ -Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) +Direction OriginalPathfinding::ChooseDirection(const TileCoordsXYZ& loc, Peep& peep) { PROFILED_FUNCTION(); @@ -1270,9 +1270,9 @@ Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXY /* The max number of tiles to check - a whole-search limit. * Mainly to limit the performance impact of the path finding. */ - int32_t maxTilesChecked = (peep->Is()) ? 50000 : 15000; + int32_t maxTilesChecked = (peep.Is()) ? 50000 : 15000; // Used to allow walking through no entry banners - _peepPathFindIsStaff = peep->Is(); + _peepPathFindIsStaff = peep.Is(); TileCoordsXYZ goal = gPeepPathFindGoalPosition; @@ -1322,7 +1322,7 @@ Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXY } /* Check if this path element is a thin junction. - * Only 'thin' junctions are remembered in peep->PathfindHistory. + * Only 'thin' junctions are remembered in peep.PathfindHistory. * NO attempt is made to merge the overlaid path elements and * check if the combination is 'thin'! * The junction is considered 'thin' simply if any of the @@ -1338,9 +1338,9 @@ Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXY permitted_edges &= 0xF; uint8_t edges = permitted_edges; - if (isThin && peep->PathfindGoal == goal) + if (isThin && peep.PathfindGoal == goal) { - /* Use of peep->PathfindHistory[]: + /* Use of peep.PathfindHistory[]: * When walking to a goal, the peep PathfindHistory stores * the last 4 thin junctions that the peep walked through. * For each of these 4 thin junctions the peep remembers @@ -1355,7 +1355,7 @@ Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXY /* If the peep remembers walking through this junction * previously while heading for its goal, retrieve the * directions it has not yet tried. */ - for (auto& pathfindHistory : peep->PathfindHistory) + for (auto& pathfindHistory : peep.PathfindHistory) { if (pathfindHistory == loc) { @@ -1405,15 +1405,15 @@ Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXY /* If this is a new goal for the peep. Store it and reset the peep's * PathfindHistory. */ - if (!direction_valid(peep->PathfindGoal.direction) || peep->PathfindGoal != goal) + if (!direction_valid(peep.PathfindGoal.direction) || peep.PathfindGoal != goal) { - peep->PathfindGoal = { goal, 0 }; + peep.PathfindGoal = { goal, 0 }; // Clear pathfinding history TileCoordsXYZD nullPos; nullPos.SetNull(); - std::fill(std::begin(peep->PathfindHistory), std::end(peep->PathfindHistory), nullPos); + std::fill(std::begin(peep.PathfindHistory), std::end(peep.PathfindHistory), nullPos); #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (_pathFindDebug) { @@ -1504,13 +1504,13 @@ Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXY uint8_t endDirectionList[16] = { 0 }; bool inPatrolArea = false; - auto* staff = peep->As(); + auto* staff = peep.As(); if (staff != nullptr && staff->IsMechanic()) { /* Mechanics are the only staff type that * pathfind to a destination. Determine if the * mechanic is in their patrol area. */ - inPatrolArea = staff->IsLocationInPatrol(peep->NextLoc); + inPatrolArea = staff->IsLocationInPatrol(peep.NextLoc); } #if defined(DEBUG_LEVEL_2) && DEBUG_LEVEL_2 @@ -1592,20 +1592,20 @@ Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXY { for (int32_t i = 0; i < 4; ++i) { - if (peep->PathfindHistory[i] == loc) + if (peep.PathfindHistory[i] == loc) { /* Peep remembers this junction, so remove the * chosen_edge from those left to try. */ - peep->PathfindHistory[i].direction &= ~(1 << chosen_edge); + peep.PathfindHistory[i].direction &= ~(1 << chosen_edge); /* Also remove the edge through which the peep * entered the junction from those left to try. */ - peep->PathfindHistory[i].direction &= ~(1 << direction_reverse(peep->PeepDirection)); + peep.PathfindHistory[i].direction &= ~(1 << direction_reverse(peep.PeepDirection)); #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (_pathFindDebug) { log_verbose( "Updating existing pf_history (in index: %d) for %d,%d,%d without entry edge %d & exit edge %d.", i, - loc.x, loc.y, loc.z, direction_reverse(peep->PeepDirection), chosen_edge); + loc.x, loc.y, loc.z, direction_reverse(peep.PeepDirection), chosen_edge); } #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 return chosen_edge; @@ -1614,20 +1614,20 @@ Direction OriginalPathfinding::peep_pathfind_choose_direction(const TileCoordsXY /* Peep does not remember this junction, so forget a junction * and remember this junction. */ - int32_t i = peep->PathfindGoal.direction++; - peep->PathfindGoal.direction &= 3; - peep->PathfindHistory[i] = { loc, permitted_edges }; + int32_t i = peep.PathfindGoal.direction++; + peep.PathfindGoal.direction &= 3; + peep.PathfindHistory[i] = { loc, permitted_edges }; /* Remove the chosen_edge from those left to try. */ - peep->PathfindHistory[i].direction &= ~(1 << chosen_edge); + peep.PathfindHistory[i].direction &= ~(1 << chosen_edge); /* Also remove the edge through which the peep * entered the junction from those left to try. */ - peep->PathfindHistory[i].direction &= ~(1 << direction_reverse(peep->PeepDirection)); + peep.PathfindHistory[i].direction &= ~(1 << direction_reverse(peep.PeepDirection)); #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (_pathFindDebug) { log_verbose( "Storing new pf_history (in index: %d) for %d,%d,%d without entry edge %d & exit edge %d.", i, loc.x, loc.y, - loc.z, direction_reverse(peep->PeepDirection), chosen_edge); + loc.z, direction_reverse(peep.PeepDirection), chosen_edge); } #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 } @@ -1661,10 +1661,10 @@ static std::optional GetNearestParkEntrance(const CoordsXY& loc) * * rct2: 0x006952C0 */ -int32_t OriginalPathfinding::GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges) +int32_t OriginalPathfinding::GuestPathFindParkEntranceEntering(Peep& peep, uint8_t edges) { // Send peeps to the nearest park entrance. - auto chosenEntrance = GetNearestParkEntrance(peep->NextLoc); + auto chosenEntrance = GetNearestParkEntrance(peep.NextLoc); // If no defined park entrances are found, walk aimlessly. if (!chosenEntrance.has_value()) @@ -1674,7 +1674,7 @@ int32_t OriginalPathfinding::GuestPathFindParkEntranceEntering(Peep* peep, uint8 gPeepPathFindIgnoreForeignQueues = true; gPeepPathFindQueueRideIndex = RideId::GetNull(); - Direction chosenDirection = peep_pathfind_choose_direction(TileCoordsXYZ{ peep->NextLoc }, peep); + Direction chosenDirection = ChooseDirection(TileCoordsXYZ{ peep.NextLoc }, peep); if (chosenDirection == INVALID_DIRECTION) return guest_path_find_aimless(peep, edges); @@ -1710,10 +1710,10 @@ static uint8_t get_nearest_peep_spawn_index(uint16_t x, uint16_t y) * * rct2: 0x0069536C */ -int32_t OriginalPathfinding::GuestPathFindPeepSpawn(Peep* peep, uint8_t edges) +int32_t OriginalPathfinding::GuestPathFindPeepSpawn(Peep& peep, uint8_t edges) { // Send peeps to the nearest spawn point. - uint8_t chosenSpawn = get_nearest_peep_spawn_index(peep->NextLoc.x, peep->NextLoc.y); + uint8_t chosenSpawn = get_nearest_peep_spawn_index(peep.NextLoc.x, peep.NextLoc.y); // If no defined spawns were found, walk aimlessly. if (chosenSpawn == 0xFF) @@ -1723,14 +1723,14 @@ int32_t OriginalPathfinding::GuestPathFindPeepSpawn(Peep* peep, uint8_t edges) Direction direction = peepSpawnLoc.direction; gPeepPathFindGoalPosition = TileCoordsXYZ(peepSpawnLoc); - if (peepSpawnLoc.x == peep->NextLoc.x && peepSpawnLoc.y == peep->NextLoc.y) + if (peepSpawnLoc.x == peep.NextLoc.x && peepSpawnLoc.y == peep.NextLoc.y) { return peep_move_one_tile(direction, peep); } gPeepPathFindIgnoreForeignQueues = true; gPeepPathFindQueueRideIndex = RideId::GetNull(); - direction = peep_pathfind_choose_direction(TileCoordsXYZ{ peep->NextLoc }, peep); + direction = ChooseDirection(TileCoordsXYZ{ peep.NextLoc }, peep); if (direction == INVALID_DIRECTION) return guest_path_find_aimless(peep, edges); @@ -1741,28 +1741,28 @@ int32_t OriginalPathfinding::GuestPathFindPeepSpawn(Peep* peep, uint8_t edges) * * rct2: 0x00695161 */ -int32_t OriginalPathfinding::GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges) +int32_t OriginalPathfinding::GuestPathFindParkEntranceLeaving(Peep& peep, uint8_t edges) { TileCoordsXYZ entranceGoal{}; - if (peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN) + if (peep.PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN) { - entranceGoal = peep->PathfindGoal; + entranceGoal = peep.PathfindGoal; auto* entranceElement = map_get_park_entrance_element_at(entranceGoal.ToCoordsXYZ(), false); // If entrance no longer exists, choose a new one if (entranceElement == nullptr) { - peep->PeepFlags &= ~(PEEP_FLAGS_PARK_ENTRANCE_CHOSEN); + peep.PeepFlags &= ~(PEEP_FLAGS_PARK_ENTRANCE_CHOSEN); } } - if (!(peep->PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)) + if (!(peep.PeepFlags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)) { - auto chosenEntrance = GetNearestParkEntrance(peep->NextLoc); + auto chosenEntrance = GetNearestParkEntrance(peep.NextLoc); if (!chosenEntrance.has_value()) return guest_path_find_aimless(peep, edges); - peep->PeepFlags |= PEEP_FLAGS_PARK_ENTRANCE_CHOSEN; + peep.PeepFlags |= PEEP_FLAGS_PARK_ENTRANCE_CHOSEN; entranceGoal = TileCoordsXYZ(*chosenEntrance); } @@ -1774,7 +1774,7 @@ int32_t OriginalPathfinding::GuestPathFindParkEntranceLeaving(Peep* peep, uint8_ PathfindLoggingEnable(peep); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 - Direction chosenDirection = peep_pathfind_choose_direction(TileCoordsXYZ{ peep->NextLoc }, peep); + Direction chosenDirection = ChooseDirection(TileCoordsXYZ{ peep.NextLoc }, peep); #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 PathfindLoggingDisable(); @@ -1942,9 +1942,9 @@ static void get_ride_queue_end(TileCoordsXYZ& loc) * appropriate. */ static StationIndex guest_pathfinding_select_random_station( - const Guest* guest, int32_t numEntranceStations, BitSet& entranceStations) + const Guest& guest, int32_t numEntranceStations, BitSet& entranceStations) { - int32_t select = guest->GuestNumRides % numEntranceStations; + int32_t select = guest.GuestNumRides % numEntranceStations; while (select > 0) { for (StationIndex::UnderlyingType i = 0; i < OpenRCT2::Limits::MaxStationsPerRide; i++) @@ -1971,22 +1971,22 @@ static StationIndex guest_pathfinding_select_random_station( * * rct2: 0x00694C35 */ -int32_t OriginalPathfinding::guest_path_finding(Guest* peep) +int32_t OriginalPathfinding::CalculateNextDestination(Guest& peep) { #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 PathfindLoggingEnable(peep); if (_pathFindDebug) { - log_info("Starting guest_path_finding for %s", _pathFindDebugPeepName); + log_info("Starting CalculateNextDestination for %s", _pathFindDebugPeepName); } #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 - if (peep->GetNextIsSurface()) + if (peep.GetNextIsSurface()) { return guest_surface_path_finding(peep); } - TileCoordsXYZ loc{ peep->NextLoc }; + TileCoordsXYZ loc{ peep.NextLoc }; auto* pathElement = map_get_path_element_at(loc); if (pathElement == nullptr) @@ -2002,7 +2002,7 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) return guest_surface_path_finding(peep); } - if (!peep->OutsideOfPark && peep->HeadingForRideOrParkExit()) + if (!peep.OutsideOfPark && peep.HeadingForRideOrParkExit()) { /* If this tileElement is adjacent to any non-wide paths, * remove all of the edges to wide paths. */ @@ -2024,14 +2024,14 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) edges = adjustedEdges; } - int32_t direction = direction_reverse(peep->PeepDirection); + int32_t direction = direction_reverse(peep.PeepDirection); // Check if in a dead end (i.e. only edge is where the peep came from) if (!(edges & ~(1 << direction))) { // In a dead end. Check if peep is lost, etc. - peep->CheckIfLost(); - peep->CheckCantFindRide(); - peep->CheckCantFindExit(); + peep.CheckIfLost(); + peep.CheckCantFindRide(); + peep.CheckCantFindExit(); } else { @@ -2048,7 +2048,7 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) if (_pathFindDebug) { log_info( - "Completed guest_path_finding for %s - taking only direction available: %d.", _pathFindDebugPeepName, + "Completed CalculateNextDestination for %s - taking only direction available: %d.", _pathFindDebugPeepName, direction); } PathfindLoggingDisable(); @@ -2060,16 +2060,16 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) // Peep is outside the park. // loc_694F19: - if (peep->OutsideOfPark) + if (peep.OutsideOfPark) { #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (_pathFindDebug) { - log_info("Completed guest_path_finding for %s - peep is outside the park.", _pathFindDebugPeepName); + log_info("Completed CalculateNextDestination for %s - peep is outside the park.", _pathFindDebugPeepName); } PathfindLoggingDisable(); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 - switch (peep->State) + switch (peep.State) { case PeepState::EnteringPark: return GuestPathFindParkEntranceEntering(peep, edges); @@ -2086,7 +2086,7 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) * In principle, peeps with food are not paying as much attention to * where they are going and are consequently more like to walk up * dead end paths, paths to ride exits, etc. */ - if (!peep->HasFoodOrDrink() && (scenario_rand() & 0xFFFF) >= 2184) + if (!peep.HasFoodOrDrink() && (scenario_rand() & 0xFFFF) >= 2184) { uint8_t adjustedEdges = edges; for (Direction chosenDirection : ALL_DIRECTIONS) @@ -2113,41 +2113,41 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) /* If there are still multiple directions to choose from, * peeps with maps will randomly read the map: probability of doing so * is much higher when heading for a ride or the park exit. */ - if (peep->HasItem(ShopItem::Map)) + if (peep.HasItem(ShopItem::Map)) { // If at least 2 directions consult map if (bitcount(edges) >= 2) { uint16_t probability = 1638; - if (peep->HeadingForRideOrParkExit()) + if (peep.HeadingForRideOrParkExit()) { probability = 9362; } if ((scenario_rand() & 0xFFFF) < probability) { - peep->ReadMap(); + peep.ReadMap(); } } } - if (peep->PeepFlags & PEEP_FLAGS_LEAVING_PARK) + if (peep.PeepFlags & PEEP_FLAGS_LEAVING_PARK) { #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (_pathFindDebug) { - log_info("Completed guest_path_finding for %s - peep is leaving the park.", _pathFindDebugPeepName); + log_info("Completed CalculateNextDestination for %s - peep is leaving the park.", _pathFindDebugPeepName); } PathfindLoggingDisable(); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 return GuestPathFindParkEntranceLeaving(peep, edges); } - if (peep->GuestHeadingToRideId.IsNull()) + if (peep.GuestHeadingToRideId.IsNull()) { #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (_pathFindDebug) { - log_info("Completed guest_path_finding for %s - peep is aimless.", _pathFindDebugPeepName); + log_info("Completed CalculateNextDestination for %s - peep is aimless.", _pathFindDebugPeepName); } PathfindLoggingDisable(); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 @@ -2155,7 +2155,7 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) } // Peep is heading for a ride. - RideId rideIndex = peep->GuestHeadingToRideId; + RideId rideIndex = peep.GuestHeadingToRideId; auto ride = get_ride(rideIndex); if (ride == nullptr || ride->status != RideStatus::Open) { @@ -2163,7 +2163,8 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) if (_pathFindDebug) { log_info( - "Completed guest_path_finding for %s - peep is heading to closed ride == aimless.", _pathFindDebugPeepName); + "Completed CalculateNextDestination for %s - peep is heading to closed ride == aimless.", + _pathFindDebugPeepName); } PathfindLoggingDisable(); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 @@ -2194,7 +2195,7 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) entranceStations[stationIndex.ToUnderlying()] = true; TileCoordsXYZD entranceLocation = station.Entrance; - auto score = CalculateHeuristicPathingScore(entranceLocation, TileCoordsXYZ{ peep->NextLoc }); + auto score = CalculateHeuristicPathingScore(entranceLocation, TileCoordsXYZ{ peep.NextLoc }); if (score < bestScore) { bestScore = score; @@ -2234,22 +2235,23 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) gPeepPathFindGoalPosition = loc; gPeepPathFindIgnoreForeignQueues = true; - direction = peep_pathfind_choose_direction(TileCoordsXYZ{ peep->NextLoc }, peep); + direction = ChooseDirection(TileCoordsXYZ{ peep.NextLoc }, peep); if (direction == INVALID_DIRECTION) { /* Heuristic search failed for all directions. * Reset the PathfindGoal - this means that the PathfindHistory - * will be reset in the next call to peep_pathfind_choose_direction(). + * will be reset in the next call to ChooseDirection(). * This lets the heuristic search "try again" in case the player has * edited the path layout or the mechanic was already stuck in the * save game (e.g. with a worse version of the pathfinding). */ - peep->ResetPathfindGoal(); + peep.ResetPathfindGoal(); #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (_pathFindDebug) { - log_info("Completed guest_path_finding for %s - failed to choose a direction == aimless.", _pathFindDebugPeepName); + log_info( + "Completed CalculateNextDestination for %s - failed to choose a direction == aimless.", _pathFindDebugPeepName); } PathfindLoggingDisable(); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 @@ -2259,7 +2261,7 @@ int32_t OriginalPathfinding::guest_path_finding(Guest* peep) #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (_pathFindDebug) { - log_info("Completed guest_path_finding for %s - direction chosen: %d.", _pathFindDebugPeepName, direction); + log_info("Completed CalculateNextDestination for %s - direction chosen: %d.", _pathFindDebugPeepName, direction); } PathfindLoggingDisable(); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 @@ -2311,18 +2313,18 @@ void Peep::ResetPathfindGoal() } #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 -void PathfindLoggingEnable([[maybe_unused]] Peep* peep) +void PathfindLoggingEnable([[maybe_unused]] Peep& peep) { # if defined(PATHFIND_DEBUG) && PATHFIND_DEBUG /* Determine if the pathfinding debugging is wanted for this peep. */ - format_string(gPathFindDebugPeepName, sizeof(gPathFindDebugPeepName), peep->name_string_idx, &(peep->Id)); + format_string(gPathFindDebugPeepName, sizeof(gPathFindDebugPeepName), peep.name_string_idx, &(peep.Id)); /* For guests, use the existing PEEP_FLAGS_TRACKING flag to * determine for which guest(s) the pathfinding debugging will * be output for. */ - if (peep->type == PEEP_TYPE_GUEST) + if (peep.type == PEEP_TYPE_GUEST) { - gPathFindDebug = peep->PeepFlags & PEEP_FLAGS_TRACKING; + gPathFindDebug = peep.PeepFlags & PEEP_FLAGS_TRACKING; } /* For staff, there is no tracking button (any other similar * suitable existing mechanism?), so fall back to a crude diff --git a/src/openrct2/peep/GuestPathfinding.h b/src/openrct2/peep/GuestPathfinding.h index bb6d08b60e..e9eb4a5ad8 100644 --- a/src/openrct2/peep/GuestPathfinding.h +++ b/src/openrct2/peep/GuestPathfinding.h @@ -42,38 +42,53 @@ class GuestPathfinding public: virtual ~GuestPathfinding() = default; - // Given a peep 'peep' at tile 'loc', who is trying to get to 'gPeepPathFindGoalPosition', decide - // the direction the peep should walk in from the current tile. - virtual Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) = 0; + /** + * Given a peep 'peep' at tile 'loc', who is trying to get to 'gPeepPathFindGoalPosition', decide the direction the peep + * should walk in from the current tile. + * + * @param loc Reference to the peep's current tile location + * @param peep Reference to the current peep struct + * @return The direction the peep should walk in + */ + virtual Direction ChooseDirection(const TileCoordsXYZ& loc, Peep& peep) = 0; - // Test whether the given tile can be walked onto, if the peep is currently at height currentZ and - // moving in direction currentDirection. + /** + * Test whether the given tile can be walked onto, if the peep is currently at height currentZ and + * moving in direction currentDirection + * + * @param tileElement A pointer to the tile that is being tested + * @param currentZ The height coord the peep is at + * @param currentDirection The direction the peep is facing in + * @return True if the given tile can be walked onto, false otherwise + */ static bool IsValidPathZAndDirection(TileElement* tileElement, int32_t currentZ, int32_t currentDirection); - // Overall guest pathfinding AI. Sets up Peep::DestinationX/DestinationY (which they move to in a - // straight line, no pathfinding). Called whenever the guest has arrived at their previously set destination. - // - // Returns 0 if the guest has successfully had a new destination set up, nonzero otherwise. - virtual int32_t guest_path_finding(Guest* peep) = 0; + /** + * Overall guest pathfinding AI. Sets up Peep::DestinationX/DestinationY (which they move to in a + * straight line, no pathfinding). Called whenever the guest has arrived at their previously set destination. + * + * @param peep A reference to a guest struct + * @returns 0 if the guest has successfully had a new destination set up, nonzero otherwise. + */ + virtual int32_t CalculateNextDestination(Guest& peep) = 0; }; class OriginalPathfinding : public GuestPathfinding { public: - Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) final override; + Direction ChooseDirection(const TileCoordsXYZ& loc, Peep& peep) final override; - int32_t guest_path_finding(Guest* peep) final override; + int32_t CalculateNextDestination(Guest& peep) final override; private: - int32_t GuestPathFindParkEntranceEntering(Peep* peep, uint8_t edges); + int32_t GuestPathFindParkEntranceEntering(Peep& peep, uint8_t edges); - int32_t GuestPathFindPeepSpawn(Peep* peep, uint8_t edges); + int32_t GuestPathFindPeepSpawn(Peep& peep, uint8_t edges); - int32_t GuestPathFindParkEntranceLeaving(Peep* peep, uint8_t edges); + int32_t GuestPathFindParkEntranceLeaving(Peep& peep, uint8_t edges); }; -// TODO: Implement a better solution than a global variable for the utilized pathfinder -extern GuestPathfinding* gGuestPathfinder; +extern std::unique_ptr gGuestPathfinder; #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 # define PATHFIND_DEBUG \ @@ -84,6 +99,6 @@ extern GuestPathfinding* gGuestPathfinder; // The following calls configure debug logging for the given peep // If they're a guest, pathfinding will be logged if they have PEEP_FLAGS_TRACKING set // If they're staff, pathfinding will be logged if their name is "Mechanic Debug" -void PathfindLoggingEnable(Peep* peep); +void PathfindLoggingEnable(Peep& peep); void PathfindLoggingDisable(); #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 diff --git a/test/tests/Pathfinding.cpp b/test/tests/Pathfinding.cpp index faf1c35503..cac06cb984 100644 --- a/test/tests/Pathfinding.cpp +++ b/test/tests/Pathfinding.cpp @@ -84,7 +84,7 @@ protected: // Pick the direction the peep should initially move in, given the goal position. // This will also store the goal position and initialize pathfinding data for the peep. gPeepPathFindGoalPosition = goal; - const Direction moveDir = gGuestPathfinder->peep_pathfind_choose_direction(*pos, peep); + const Direction moveDir = gGuestPathfinder->ChooseDirection(*pos, *peep); if (moveDir == INVALID_DIRECTION) { // Couldn't determine a direction to move off in