diff --git a/code/astar.cpp b/code/astar.cpp index fb40cd0..732e5ee 100644 --- a/code/astar.cpp +++ b/code/astar.cpp @@ -181,6 +181,10 @@ double AStarClass::Get_Movement_Cost(CellClass **from, CellClass **to, bool brid clear = true; break; } + + if (facing == FACING_COUNT) { + break; + } } else { facing = occupier->PrimaryFacing.Current().As_Dir8(); } @@ -900,7 +904,7 @@ void AStarClass::Apply_Path_Collision_Avoidance(FootClass * foot) } marked_path = true; - while (blocker->Path[index] != FACING_NONE && index < ARRAY_SIZE(blocker->Path)) { + while (index < ARRAY_SIZE(blocker->Path) && blocker->Path[index] != FACING_NONE) { blocker_cell = Next_Cell(blocker_cell, blocker->Path[index]); Map[blocker_cell].IsPredictedPath = !Map[blocker_cell].IsPredictedPath; index++; diff --git a/code/drive.cpp b/code/drive.cpp index f70c01e..538c71b 100644 --- a/code/drive.cpp +++ b/code/drive.cpp @@ -1012,8 +1012,7 @@ bool DriveLocomotionClass::While_Moving(bool just_started) TubeClass * tube = Tubes[tubenum]; Cell c = tube->Exit; HeadToCoord = c.As_Coord(); - memcpy((char*)&LinkedTo->Path, (char*)&LinkedTo->Path[1], sizeof(LinkedTo->Path[0]) * (CONQUER_PATH_MAX-1)); - LinkedTo->Path[CONQUER_PATH_MAX-1] = FACING_NONE; + LinkedTo->Advance_Path(1); LinkedTo->CurrentTube = tubenum; LinkedTo->CurrentTubeDir = FACING_FIRST; LinkedTo->LastTubeCoord = Map[Adjacent_Cell((Cell)tube->Enter, tube->Dirs[0])].Cell_Coord(); @@ -1196,8 +1195,7 @@ bool DriveLocomotionClass::While_Moving(bool just_started) if (LinkedTo == NULL || !LinkedTo->IsActive || LinkedTo->IsInLimbo || LinkedTo->IsFalling) return(false); if (Start_Driver(c)) { LinkedTo->Set_Speed(oldspeed); - memcpy((char*)&LinkedTo->Path, (char*)&LinkedTo->Path[1], sizeof(LinkedTo->Path[0]) * (CONQUER_PATH_MAX-1)); - LinkedTo->Path[CONQUER_PATH_MAX-1] = FACING_NONE; + LinkedTo->Advance_Path(1); } break; @@ -1992,15 +1990,12 @@ bool DriveLocomotionClass::Start_Of_Move(bool & stop_processing, bool retry, boo } } else { - memcpy((char*)&LinkedTo->Path[0], (char*)&LinkedTo->Path[2], sizeof(LinkedTo->Path[0]) * (CONQUER_PATH_MAX-2)); - LinkedTo->Path[CONQUER_PATH_MAX-2] = FACING_NONE; + LinkedTo->Advance_Path(2); LinkedTo->IsPlanningToLook = true; } } else { - memcpy((char*)&LinkedTo->Path[0], (char*)&LinkedTo->Path[1], sizeof(LinkedTo->Path[0]) * (CONQUER_PATH_MAX-1)); + LinkedTo->Advance_Path(1); } - - LinkedTo->Path[CONQUER_PATH_MAX-1] = FACING_NONE; LinkedTo->LastPathingCell = dest.As_Cell(); LinkedTo->IsNewNavCom = false; TrackIndex = 0; diff --git a/code/foot.cpp b/code/foot.cpp index 3cc51c8..788064e 100644 --- a/code/foot.cpp +++ b/code/foot.cpp @@ -134,6 +134,8 @@ #include "tube.hh" #include +#include +#include DynamicVectorClass Feet; @@ -195,7 +197,7 @@ FootClass::FootClass(HouseClass * house) : CurrentTubeDir(0), NextWaypoint(0) { - Path[0] = FACING_NONE; + std::fill(std::begin(Path), std::end(Path), FACING_NONE); Feet.Add(this); TeamPtrTracker.Add(this); } @@ -427,12 +429,15 @@ bool FootClass::Basic_Path(Cell cell, int path_offset, int avoidance) PathStruct * path; // Pointer to path control structure. int skip_path = false; - if (path_offset == 0) { - Path[0] = FACING_NONE; + if (path_offset < 0 || path_offset >= ARRAY_SIZE(Path)) { + std::fill(std::begin(Path), std::end(Path), FACING_NONE); + return(false); } + // Keep an existing path prefix, but always terminate the new suffix. + std::fill(std::begin(Path) + path_offset, std::end(Path), FACING_NONE); + if (!Is_In_Same_Zone(cell)) { - Path[0] = FACING_NONE; return(false); } @@ -483,9 +488,6 @@ bool FootClass::Basic_Path(Cell cell, int path_offset, int avoidance) if (!skip_path) { Mark(MARK_UP); - if (path_offset == 0) { - Path[0] = FACING_NONE; // Probably not necessary, but... - } /* ** Try to find a path to the destination. If a failure occurs, then keep trying @@ -510,7 +512,8 @@ bool FootClass::Basic_Path(Cell cell, int path_offset, int avoidance) */ if (found) { Fixup_Path(&path1); - memcpy(&Path[path_offset], &workpath[0], std::min(path->Length, ARRAY_SIZE(Path) - path_offset) * sizeof(Path[0])); + int length = std::clamp(path->Length, 0, ARRAY_SIZE(Path) - path_offset); + memcpy(&Path[path_offset], &workpath[0], length * sizeof(Path[0])); } Mark(MARK_DOWN); @@ -581,6 +584,21 @@ bool FootClass::Basic_Path(Cell cell, int path_offset, int avoidance) return(false); } +/// +/// Removes completed steps from the front of the active movement path. +/// +void FootClass::Advance_Path(int count) +{ + if (count <= 0) { + return; + } + + int const advance = std::min(count, ARRAY_SIZE(Path)); + std::memmove(Path, Path + advance, (ARRAY_SIZE(Path) - advance) * sizeof(Path[0])); + std::fill(std::end(Path) - advance, std::end(Path), FACING_NONE); +} + + /*********************************************************************************************** * FootClass::Mission_Move -- AI process for moving a vehicle to its destination. * diff --git a/code/foot.h b/code/foot.h index a699072..93b3ccf 100644 --- a/code/foot.h +++ b/code/foot.h @@ -385,6 +385,7 @@ class FootClass : public TechnoClass ** Member function prototypes. */ bool Basic_Path(Cell cell, int path_offset = 0, int avoidance = 0); + void Advance_Path(int count); virtual void Compute_CRC(CRCEngine &) const override; virtual Coord Destination_Coord(void) const override; diff --git a/code/hover.cpp b/code/hover.cpp index ff3c001..b108e63 100644 --- a/code/hover.cpp +++ b/code/hover.cpp @@ -412,9 +412,8 @@ MoveType HoverLocomotionClass::While_Moving(bool first_pass) TubeClass * tube = Tubes[tubenum]; Cell exit = tube->Exit; HeadToCoord = exit.As_Coord(); - memcpy((char*)&LinkedTo->Path, (char*)&LinkedTo->Path[1], sizeof(LinkedTo->Path[0]) * (CONQUER_PATH_MAX-1)); + LinkedTo->Advance_Path(1); LinkedTo->LastPathingCell = HeadToCoord.As_Cell(); - LinkedTo->Path[CONQUER_PATH_MAX-1] = FACING_NONE; LinkedTo->CurrentTube = tubenum; LinkedTo->CurrentTubeDir = FACING_FIRST; LinkedTo->LastTubeCoord = Map[Adjacent_Cell((Cell)tube->Enter, tube->Dirs[0])].Cell_Coord() - Coord((Cell)tube->Enter) + LinkedTo->PositionCoord; @@ -515,8 +514,7 @@ MoveType HoverLocomotionClass::While_Moving(bool first_pass) if (LinkedTo->IsLocked) { LinkedTo->Set_Occupy_Bit(HeadToCoord); } - memcpy((char *)&LinkedTo->Path, (char *)&LinkedTo->Path[1], sizeof(LinkedTo->Path[0]) * (CONQUER_PATH_MAX - 1)); - LinkedTo->Path[CONQUER_PATH_MAX - 1] = FACING_NONE; + LinkedTo->Advance_Path(1); LinkedTo->LastPathingCell = HeadToCoord.As_Cell(); return(ok); diff --git a/code/mech.cpp b/code/mech.cpp index 8ec0a55..ee1d17c 100644 --- a/code/mech.cpp +++ b/code/mech.cpp @@ -178,7 +178,6 @@ void MechLocomotionClass::Movement_AI(bool continue_moving) if (HeadToCoord == COORD_NONE) { if (DestinationCoord != COORD_NONE) { - /* * A destination exists. If there is no current path then try to build * one. If a path already exists, fall through to dispatch the next leg. @@ -261,8 +260,7 @@ void MechLocomotionClass::Movement_AI(bool continue_moving) Cell cell = tubeptr->Exit; HeadToCoord = Coord(cell, 0); - memcpy(&LinkedTo->Path[0], &LinkedTo->Path[1], 92); - LinkedTo->Path[23] = FACING_NONE; + LinkedTo->Advance_Path(1); LinkedTo->CurrentTube = tube; LinkedTo->CurrentTubeDir = FACING_FIRST; @@ -491,8 +489,7 @@ void MechLocomotionClass::Movement_AI(bool continue_moving) LinkedTo->Path[1] = FACING_NONE; } - memcpy(&LinkedTo->Path[0], &LinkedTo->Path[1], 92); - LinkedTo->Path[23] = FACING_NONE; + LinkedTo->Advance_Path(1); LinkedTo->Set_Coord(HeadToCoord); LinkedTo->LastPathingCell = HeadToCoord.As_Cell(); diff --git a/code/walk.cpp b/code/walk.cpp index 3eb8974..d3996e1 100644 --- a/code/walk.cpp +++ b/code/walk.cpp @@ -287,8 +287,7 @@ void WalkLocomotionClass::Movement_AI(bool first_pass) Cell cell = tube_ptr->Exit; HeadToCoord = Coord(cell, 0); - memcpy(&LinkedTo->Path[0], &LinkedTo->Path[1], sizeof(LinkedTo->Path[0]) * (ARRAY_SIZE(LinkedTo->Path) - 1)); - LinkedTo->Path[ARRAY_SIZE(LinkedTo->Path) - 1] = FACING_NONE; + LinkedTo->Advance_Path(1); LinkedTo->CurrentTube = tube; LinkedTo->CurrentTubeDir = FACING_FIRST; @@ -459,8 +458,7 @@ void WalkLocomotionClass::Movement_AI(bool first_pass) LinkedTo->Path[1] = FACING_NONE; } - memcpy(&LinkedTo->Path[0], &LinkedTo->Path[1], sizeof(LinkedTo->Path[0]) * (ARRAY_SIZE(LinkedTo->Path) - 1)); - LinkedTo->Path[ARRAY_SIZE(LinkedTo->Path) - 1] = FACING_NONE; + LinkedTo->Advance_Path(1); LinkedTo->Set_Coord(HeadToCoord); LinkedTo->LastPathingCell = HeadToCoord.As_Cell();