Ensure that a transit path exists for recruitment.

Networks can be disconnected even by airlift because FOBs are not
airports.

Fixes https://github.com/dcs-liberation/dcs_liberation/issues/1147
This commit is contained in:
Dan Albert 2021-05-28 16:26:21 -07:00
parent d4e843983d
commit a2abdcf5d3
2 changed files with 23 additions and 3 deletions

View File

@ -88,9 +88,27 @@ class TransitNetwork:
TransitConnection.Airlift: a.position.distance_to_point(b.position), TransitConnection.Airlift: a.position.distance_to_point(b.position),
}[self.link_type(a, b)] }[self.link_type(a, b)]
def has_path_between(
self,
origin: ControlPoint,
destination: ControlPoint,
seen: Optional[set[ControlPoint]] = None,
) -> bool:
if seen is None:
seen = set()
seen.add(origin)
for connection in self.connections_from(origin):
if connection in seen:
continue
if connection == destination:
return True
if self.has_path_between(connection, destination, seen):
return True
return False
def shortest_path_between( def shortest_path_between(
self, origin: ControlPoint, destination: ControlPoint self, origin: ControlPoint, destination: ControlPoint
) -> List[ControlPoint]: ) -> list[ControlPoint]:
return self.shortest_path_with_cost(origin, destination)[0] return self.shortest_path_with_cost(origin, destination)[0]
def shortest_path_with_cost( def shortest_path_with_cost(
@ -127,7 +145,7 @@ class TransitNetwork:
path: List[ControlPoint] = [] path: List[ControlPoint] = []
while current != origin: while current != origin:
path.append(current) path.append(current)
previous = came_from[current] previous = came_from.get(current)
if previous is None: if previous is None:
raise NoPathError(origin, destination) raise NoPathError(origin, destination)
current = previous current = previous

View File

@ -139,7 +139,9 @@ class PendingUnitDeliveries:
) -> Optional[ControlPoint]: ) -> Optional[ControlPoint]:
sources = [] sources = []
for control_point in game.theater.control_points_for(self.destination.captured): for control_point in game.theater.control_points_for(self.destination.captured):
if control_point.can_recruit_ground_units(game): if control_point.can_recruit_ground_units(
game
) and network.has_path_between(self.destination, control_point):
sources.append(control_point) sources.append(control_point)
if not sources: if not sources: