From c2d9c7a6d44de59f48349a775a19d0a12f4fdc6d Mon Sep 17 00:00:00 2001 From: zaxcav Date: Fri, 2 Dec 2016 09:50:39 +0100 Subject: [PATCH] Make path finding aware of ALL path elements when choosing a direction. This is applicable for overlaid paths placed with zero clearance. Previously the pathfinding only used the first path element. Notes: 1. Logic related to path slope still only uses the the first path element. Overlaying path elements with the same base height but different slopes may cause pathfinding glitches. 2. The heuristic search already uses a similar approach - the inconsistency could have caused pathfinding glitches. --- src/peep/peep.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/peep/peep.c b/src/peep/peep.c index 4f42005c54..80d8947549 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -9462,21 +9462,50 @@ int peep_pathfind_choose_direction(sint16 x, sint16 y, uint8 z, rct_peep *peep) // Get the path element at this location rct_map_element *dest_map_element = map_get_first_element_at(x / 32, y / 32); + /* Where there are multiple matching map elements placed with zero + * clearance, save the first one for later use to determine the path + * slope - this maintains the original behaviour (which only processes + * the first matching map element found) and is consistent with peep + * placement (i.e. height) on such paths with differing slopes. + * + * I cannot see a legitimate reason for building overlaid paths with + * differing slopes and do not recall ever seeing this in practise. + * Normal cases I have seen in practise are overlaid paths with the + * same slope (flat) in order to place scenery (e.g. benches) in the + * middle of a wide path that can still be walked through. + * Anyone attempting to overlay paths with different slopes should + * EXPECT to experience path finding irregularities due to those paths! + * In particular common edges at different heights will not work + * in a useful way. Simply do not do it! :-) */ + rct_map_element *first_map_element = NULL; + bool found = false; + uint8 permitted_edges = 0; + bool isThin = false; do { if (dest_map_element->base_height != z) continue; if (map_element_get_type(dest_map_element) != MAP_ELEMENT_TYPE_PATH) continue; found = true; - break; + if (first_map_element == NULL) { + first_map_element = dest_map_element; + } + + /* Check if this path element is a thin junction. + * Only 'thin' junctions are remembered in peep->pathfind_history. + * 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 + * overlaid path elements there is a 'thin junction'. */ + isThin = isThin || path_is_thin_junction(dest_map_element, x, y, z); + + // Collect the permitted edges of ALL matching path elements at this location. + permitted_edges |= path_get_permitted_edges(dest_map_element); } while (!map_element_is_last_for_tile(dest_map_element++)); // Peep is not on a path. if (!found) return -1; - /* Determine if the path is a thin junction. - * Only 'thin' junctions are remembered in peep->pathfind_history. */ - bool isThin = path_is_thin_junction(dest_map_element, x, y, z); - - uint8 edges = 0xF; + permitted_edges &= 0xF; + uint8 edges = permitted_edges; if (isThin && peep->pathfind_goal.x == goal.x && peep->pathfind_goal.y == goal.y && peep->pathfind_goal.z == goal.z @@ -9544,8 +9573,8 @@ int peep_pathfind_choose_direction(sint16 x, sint16 y, uint8 z, rct_peep *peep) edges &= ~(1 << test_edge); uint8 height = z; - if (footpath_element_is_sloped(dest_map_element) && - footpath_element_get_slope_direction(dest_map_element) == test_edge + if (footpath_element_is_sloped(first_map_element) && + footpath_element_get_slope_direction(first_map_element) == test_edge ) { height += 0x2; } @@ -9589,7 +9618,7 @@ int peep_pathfind_choose_direction(sint16 x, sint16 y, uint8 z, rct_peep *peep) rct_xyz8 endJunctionList[16] = { 0 }; uint8 endDirectionList[16] = { 0 }; - peep_pathfind_heuristic_search(x, y, height, peep, dest_map_element, 0, &score, test_edge, &endJunctions, endJunctionList, endDirectionList, &endXYZ, &endSteps); + peep_pathfind_heuristic_search(x, y, height, peep, first_map_element, 0, &score, test_edge, &endJunctions, endJunctionList, endDirectionList, &endXYZ, &endSteps); #if defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 if (gPathFindDebug) { log_verbose("Pathfind test edge: %d score: %d steps: %d end: %d,%d,%d junctions: %d", test_edge, score, endSteps, endXYZ.x, endXYZ.y, endXYZ.z, endJunctions);