Merge pull request #4527 from zaxcav/fixPathfindHistory

Further pathfinding improvements
This commit is contained in:
Duncan 2016-10-07 12:08:36 +01:00 committed by GitHub
commit b29be9bfeb
7 changed files with 766 additions and 319 deletions

View File

@ -28,8 +28,8 @@ namespace Debug
{ {
void Break() void Break()
{ {
#if DEBUG #if defined(DEBUG)
#if __WINDOWS__ #if defined(__WINDOWS__)
if (IsDebuggerPresent()) if (IsDebuggerPresent())
{ {
DebugBreak(); DebugBreak();

View File

@ -62,6 +62,10 @@ enum {
#define DEBUG_LEVEL_3 0 #define DEBUG_LEVEL_3 0
#define DEBUG_LEVEL_2 0 #define DEBUG_LEVEL_2 0
#endif // DEBUG > 1 #endif // DEBUG > 1
#else
#define DEBUG_LEVEL_1 0
#define DEBUG_LEVEL_2 0
#define DEBUG_LEVEL_3 0
#endif // DEBUG > 0 #endif // DEBUG > 0
#else #else
#define DEBUG_LEVEL_3 0 #define DEBUG_LEVEL_3 0

View File

@ -55,7 +55,7 @@ extern "C" {
// This define specifies which version of network stream current build uses. // This define specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within // It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version. // single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "13" #define NETWORK_STREAM_VERSION "14"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
#ifdef __cplusplus #ifdef __cplusplus

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,12 @@
#include "../common.h" #include "../common.h"
#include "../world/map.h" #include "../world/map.h"
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
// Some variables used for the path finding debugging.
extern bool gPathFindDebug;
extern utf8 gPathFindDebugPeepName[256];
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
#define PEEP_MAX_THOUGHTS 5 #define PEEP_MAX_THOUGHTS 5
#define PEEP_HUNGER_WARNING_THRESHOLD 25 #define PEEP_HUNGER_WARNING_THRESHOLD 25

View File

@ -20,6 +20,7 @@
#include "../interface/viewport.h" #include "../interface/viewport.h"
#include "../localisation/date.h" #include "../localisation/date.h"
#include "../localisation/string_ids.h" #include "../localisation/string_ids.h"
#include "../localisation/localisation.h"
#include "../management/finance.h" #include "../management/finance.h"
#include "../util/util.h" #include "../util/util.h"
#include "../world/sprite.h" #include "../world/sprite.h"
@ -999,9 +1000,12 @@ static uint8 staff_mechanic_direction_path_rand(rct_peep* peep, uint8 pathDirect
* rct2: 0x006C0121 * rct2: 0x006C0121
*/ */
static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections, rct_map_element* pathElement) { static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections, rct_map_element* pathElement) {
uint8 direction = 0xFF; uint8 direction = 0xFF;
uint8 pathDirections = pathElement->properties.path.edges & 0xF; uint8 pathDirections = pathElement->properties.path.edges & 0xF;
if (peep->state != PEEP_STATE_ANSWERING && peep->state != PEEP_STATE_HEADING_TO_INSPECTION) { if (peep->state != PEEP_STATE_ANSWERING && peep->state != PEEP_STATE_HEADING_TO_INSPECTION) {
/* Mechanic is patrolling, so mask with the valid
* patrol directions */
pathDirections &= validDirections; pathDirections &= validDirections;
} }
@ -1009,6 +1013,7 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
return staff_mechanic_direction_surface(peep); return staff_mechanic_direction_surface(peep);
} }
// Check if this is dead end - i.e. only way out is the reverse direction.
pathDirections &= ~(1 << (peep->direction ^ (1 << 1))); pathDirections &= ~(1 << (peep->direction ^ (1 << 1)));
if (pathDirections == 0) { if (pathDirections == 0) {
pathDirections |= (1 << (peep->direction ^ (1 << 1))); pathDirections |= (1 << (peep->direction ^ (1 << 1)));
@ -1029,11 +1034,14 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
pathDirections |= (1 << direction); pathDirections |= (1 << direction);
// Mechanic is heading to ride (either broken down or for inspection).
if (peep->state == PEEP_STATE_ANSWERING || peep->state == PEEP_STATE_HEADING_TO_INSPECTION) { if (peep->state == PEEP_STATE_ANSWERING || peep->state == PEEP_STATE_HEADING_TO_INSPECTION) {
rct_ride* ride = get_ride(peep->current_ride); rct_ride* ride = get_ride(peep->current_ride);
uint8 z = ride->station_heights[peep->current_ride_station]; uint8 z = ride->station_heights[peep->current_ride_station];
gPeepPathFindGoalPosition.z = z; gPeepPathFindGoalPosition.z = z;
/* Find location of the exit for the target ride station
* or if the ride has no exit, the entrance */
uint16 location = ride->exits[peep->current_ride_station]; uint16 location = ride->exits[peep->current_ride_station];
if (location == 0xFFFF) { if (location == 0xFFFF) {
location = ride->entrances[peep->current_ride_station]; location = ride->entrances[peep->current_ride_station];
@ -1047,6 +1055,7 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
gPeepPathFindGoalPosition.x = chosenTile.x; gPeepPathFindGoalPosition.x = chosenTile.x;
gPeepPathFindGoalPosition.y = chosenTile.y; gPeepPathFindGoalPosition.y = chosenTile.y;
// Find the exit/entrance map_element
bool entranceFound = false; bool entranceFound = false;
rct_map_element* mapElement = map_get_first_element_at(chosenTile.x / 32, chosenTile.y / 32); rct_map_element* mapElement = map_get_first_element_at(chosenTile.x / 32, chosenTile.y / 32);
do { do {
@ -1068,12 +1077,15 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
return staff_mechanic_direction_path_rand(peep, pathDirections); return staff_mechanic_direction_path_rand(peep, pathDirections);
} }
/* Adjust the peep goal according to the direction of the
* exit/entrance. */
uint8 entranceDirection = map_element_get_direction(mapElement); uint8 entranceDirection = map_element_get_direction(mapElement);
chosenTile.x -= TileDirectionDelta[entranceDirection].x; chosenTile.x -= TileDirectionDelta[entranceDirection].x;
chosenTile.y -= TileDirectionDelta[entranceDirection].y; chosenTile.y -= TileDirectionDelta[entranceDirection].y;
gPeepPathFindGoalPosition.x = chosenTile.x; gPeepPathFindGoalPosition.x = chosenTile.x;
gPeepPathFindGoalPosition.y = chosenTile.y; gPeepPathFindGoalPosition.y = chosenTile.y;
// Peep is about to walk into the target exit/entrance.
if (chosenTile.x == peep->next_x && if (chosenTile.x == peep->next_x &&
chosenTile.y == peep->next_y && chosenTile.y == peep->next_y &&
z == peep->next_z) { z == peep->next_z) {
@ -1083,8 +1095,22 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
gPeepPathFindIgnoreForeignQueues = false; gPeepPathFindIgnoreForeignQueues = false;
gPeepPathFindQueueRideIndex = 255; gPeepPathFindQueueRideIndex = 255;
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
/* Determine if the pathfinding debugging is wanted for this peep. */
/* For staff, there is no tracking button (any other similar
* suitable existing mechanism?), so fall back to a crude
* string comparison with a compile time hardcoded name. */
format_string(gPathFindDebugPeepName, peep->name_string_idx, &(peep->id));
gPathFindDebug = strcmp(gPathFindDebugPeepName, "Mechanic Debug") == 0;
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
int pathfindDirection = peep_pathfind_choose_direction(peep->next_x, peep->next_y, peep->next_z, peep); int pathfindDirection = peep_pathfind_choose_direction(peep->next_x, peep->next_y, peep->next_z, peep);
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
gPathFindDebug = false;
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
if (pathfindDirection == -1) { if (pathfindDirection == -1) {
return staff_mechanic_direction_path_rand(peep, pathDirections); return staff_mechanic_direction_path_rand(peep, pathDirections);
} }

View File

@ -1757,13 +1757,23 @@ void footpath_update_path_wide_flags(int x, int y)
return; return;
footpath_clear_wide(x, y); footpath_clear_wide(x, y);
x += 0x20; /* Rather than clearing the wide flag of the following tiles and
footpath_clear_wide(x, y); * checking the state of them later, leave them intact and assume
y += 0x20; * they were cleared. Consequently only the wide flag for this single
footpath_clear_wide(x, y); * tile is modified by this update.
x -= 0x20; * This is important for avoiding glitches in pathfinding that occurs
footpath_clear_wide(x, y); * between between the batches of updates to the path wide flags.
y -= 0x20; * Corresponding pathList[] indexes for the following tiles
* are: 2, 3, 4, 5.
* Note: indexes 3, 4, 5 are reset in the current call;
* index 2 is reset in the previous call. */
//x += 0x20;
//footpath_clear_wide(x, y);
//y += 0x20;
//footpath_clear_wide(x, y);
//x -= 0x20;
//footpath_clear_wide(x, y);
//y -= 0x20;
rct_map_element *mapElement = map_get_first_element_at(x / 32, y / 32); rct_map_element *mapElement = map_get_first_element_at(x / 32, y / 32);
do { do {
@ -1825,20 +1835,30 @@ void footpath_update_path_wide_flags(int x, int y)
if (mapElement->properties.path.edges & 2) { if (mapElement->properties.path.edges & 2) {
F3EFA5 |= 0x8; F3EFA5 |= 0x8;
if (pathList[3] != NULL) { /* In the following:
if (footpath_element_is_wide(pathList[3])) { * footpath_element_is_wide(pathList[3])
F3EFA5 &= ~0x8; * is always false due to the tile update order
} * in combination with reset tiles.
} * Commented out since it will never occur. */
//if (pathList[3] != NULL) {
// if (footpath_element_is_wide(pathList[3])) {
// F3EFA5 &= ~0x8;
// }
//}
} }
if (mapElement->properties.path.edges & 4) { if (mapElement->properties.path.edges & 4) {
F3EFA5 |= 0x20; F3EFA5 |= 0x20;
if (pathList[5] != NULL) { /* In the following:
if (footpath_element_is_wide(pathList[5])) { * footpath_element_is_wide(pathList[5])
F3EFA5 &= ~0x20; * is always false due to the tile update order
} * in combination with reset tiles.
} * Commented out since it will never occur. */
//if (pathList[5] != NULL) {
// if (footpath_element_is_wide(pathList[5])) {
// F3EFA5 &= ~0x20;
// }
//}
} }
if ((F3EFA5 & 0x80) && (pathList[7] != NULL) && !(footpath_element_is_wide(pathList[7]))) { if ((F3EFA5 & 0x80) && (pathList[7] != NULL) && !(footpath_element_is_wide(pathList[7]))) {
@ -1849,27 +1869,44 @@ void footpath_update_path_wide_flags(int x, int y)
F3EFA5 |= 0x1; F3EFA5 |= 0x1;
} }
/* In the following:
* footpath_element_is_wide(pathList[5])
* is always false due to the tile update order
* in combination with reset tiles.
* Short circuit the logic appropriately. */
if ((F3EFA5 & 0x20) && if ((F3EFA5 & 0x20) &&
(pathList[6] != NULL) && (!footpath_element_is_wide(pathList[6])) && (pathList[6] != NULL) && (!footpath_element_is_wide(pathList[6])) &&
((pathList[6]->properties.path.edges & 3) == 3) && // N W ((pathList[6]->properties.path.edges & 3) == 3) && // N W
(pathList[5] != NULL) && (!footpath_element_is_wide(pathList[5]))) { (pathList[5] != NULL) && (true || !footpath_element_is_wide(pathList[5]))) {
F3EFA5 |= 0x40; F3EFA5 |= 0x40;
} }
} }
if ((F3EFA5 & 0x8) && (pathList[3] != NULL) && !(pathList[3]->type & 2)) { /* In the following:
* footpath_element_is_wide(pathList[2])
* footpath_element_is_wide(pathList[3])
* are always false due to the tile update order
* in combination with reset tiles.
* Short circuit the logic appropriately. */
if ((F3EFA5 & 0x8) && (pathList[3] != NULL) && (true || !footpath_element_is_wide(pathList[3]))) {
if ((F3EFA5 & 2) && if ((F3EFA5 & 2) &&
(pathList[2] != NULL) && (!footpath_element_is_wide(pathList[2])) && (pathList[2] != NULL) && (true || !footpath_element_is_wide(pathList[2])) &&
((pathList[2]->properties.path.edges & 0xC) == 0xC) && ((pathList[2]->properties.path.edges & 0xC) == 0xC) &&
(pathList[1] != NULL) && (!footpath_element_is_wide(pathList[1]))) { (pathList[1] != NULL) && (!footpath_element_is_wide(pathList[1]))) {
F3EFA5 |= 0x4; F3EFA5 |= 0x4;
} }
/* In the following:
* footpath_element_is_wide(pathList[4])
* footpath_element_is_wide(pathList[5])
* are always false due to the tile update order
* in combination with reset tiles.
* Short circuit the logic appropriately. */
if ((F3EFA5 & 0x20) && if ((F3EFA5 & 0x20) &&
(pathList[4] != NULL) && (!footpath_element_is_wide(pathList[4])) && (pathList[4] != NULL) && (true || !footpath_element_is_wide(pathList[4])) &&
((pathList[4]->properties.path.edges & 9) == 9) && ((pathList[4]->properties.path.edges & 9) == 9) &&
(pathList[5] != NULL) && (!footpath_element_is_wide(pathList[5]))) { (pathList[5] != NULL) && (true || !footpath_element_is_wide(pathList[5]))) {
F3EFA5 |= 0x10; F3EFA5 |= 0x10;
} }
} }