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()
{
#if DEBUG
#if __WINDOWS__
#if defined(DEBUG)
#if defined(__WINDOWS__)
if (IsDebuggerPresent())
{
DebugBreak();

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,12 @@
#include "../common.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_HUNGER_WARNING_THRESHOLD 25

View File

@ -20,6 +20,7 @@
#include "../interface/viewport.h"
#include "../localisation/date.h"
#include "../localisation/string_ids.h"
#include "../localisation/localisation.h"
#include "../management/finance.h"
#include "../util/util.h"
#include "../world/sprite.h"
@ -999,9 +1000,12 @@ static uint8 staff_mechanic_direction_path_rand(rct_peep* peep, uint8 pathDirect
* rct2: 0x006C0121
*/
static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections, rct_map_element* pathElement) {
uint8 direction = 0xFF;
uint8 pathDirections = pathElement->properties.path.edges & 0xF;
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;
}
@ -1009,6 +1013,7 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
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)));
if (pathDirections == 0) {
pathDirections |= (1 << (peep->direction ^ (1 << 1)));
@ -1029,11 +1034,14 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
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) {
rct_ride* ride = get_ride(peep->current_ride);
uint8 z = ride->station_heights[peep->current_ride_station];
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];
if (location == 0xFFFF) {
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.y = chosenTile.y;
// Find the exit/entrance map_element
bool entranceFound = false;
rct_map_element* mapElement = map_get_first_element_at(chosenTile.x / 32, chosenTile.y / 32);
do {
@ -1068,12 +1077,15 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
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);
chosenTile.x -= TileDirectionDelta[entranceDirection].x;
chosenTile.y -= TileDirectionDelta[entranceDirection].y;
gPeepPathFindGoalPosition.x = chosenTile.x;
gPeepPathFindGoalPosition.y = chosenTile.y;
// Peep is about to walk into the target exit/entrance.
if (chosenTile.x == peep->next_x &&
chosenTile.y == peep->next_y &&
z == peep->next_z) {
@ -1083,8 +1095,22 @@ static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections
gPeepPathFindIgnoreForeignQueues = false;
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);
#if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
gPathFindDebug = false;
#endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1
if (pathfindDirection == -1) {
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;
footpath_clear_wide(x, y);
x += 0x20;
footpath_clear_wide(x, y);
y += 0x20;
footpath_clear_wide(x, y);
x -= 0x20;
footpath_clear_wide(x, y);
y -= 0x20;
/* Rather than clearing the wide flag of the following tiles and
* checking the state of them later, leave them intact and assume
* they were cleared. Consequently only the wide flag for this single
* tile is modified by this update.
* This is important for avoiding glitches in pathfinding that occurs
* between between the batches of updates to the path wide flags.
* 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);
do {
@ -1825,20 +1835,30 @@ void footpath_update_path_wide_flags(int x, int y)
if (mapElement->properties.path.edges & 2) {
F3EFA5 |= 0x8;
if (pathList[3] != NULL) {
if (footpath_element_is_wide(pathList[3])) {
F3EFA5 &= ~0x8;
}
}
/* In the following:
* footpath_element_is_wide(pathList[3])
* 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) {
F3EFA5 |= 0x20;
if (pathList[5] != NULL) {
if (footpath_element_is_wide(pathList[5])) {
F3EFA5 &= ~0x20;
}
}
/* In the following:
* footpath_element_is_wide(pathList[5])
* 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]))) {
@ -1849,27 +1869,44 @@ void footpath_update_path_wide_flags(int x, int y)
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) &&
(pathList[6] != NULL) && (!footpath_element_is_wide(pathList[6])) &&
((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;
}
}
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) &&
(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[1] != NULL) && (!footpath_element_is_wide(pathList[1]))) {
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) &&
(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[5] != NULL) && (!footpath_element_is_wide(pathList[5]))) {
(pathList[5] != NULL) && (true || !footpath_element_is_wide(pathList[5]))) {
F3EFA5 |= 0x10;
}
}