@@ -604,6 +604,7 @@ def hillclimb2d(
604604
605605
606606def _world_array (shape : Tuple [int , ...], dtype : Any = np .int32 ) -> np .ndarray :
607+ """Return an array where ``ij == arr[ij]``."""
607608 return np .ascontiguousarray (
608609 np .transpose (
609610 np .meshgrid (
@@ -615,14 +616,16 @@ def _world_array(shape: Tuple[int, ...], dtype: Any = np.int32) -> np.ndarray:
615616 )
616617
617618
618- def _as_hashable (obj : Any ) -> Any :
619+ def _as_hashable (obj : Optional [np .ndarray ]) -> Optional [Any ]:
620+ """Return NumPy arrays as a more hashable form."""
619621 if obj is None :
620622 return obj
621623 return obj .ctypes .data , tuple (obj .shape ), tuple (obj .strides )
622624
623625
624626class Graph :
625- """
627+ """A modular graph defining how a pathfinder traverses the world.
628+
626629 Example::
627630
628631 >>> import tcod
@@ -765,7 +768,8 @@ def _compile_rules(self) -> Any:
765768
766769
767770class Pathfinder :
768- """
771+ """A generic modular pathfinder.
772+
769773 .. versionadded:: 11.13
770774 """
771775
@@ -793,16 +797,47 @@ def distance(self) -> np.ndarray:
793797 Unreachable or unresolved points will be at their maximum values.
794798 You can use :any:`numpy.iinfo` if you need to check for these.
795799
800+ Example::
801+
802+ pf # Resolved Pathfinder instance.
803+ reachable = pf.distance != numpy.iinfo(pf.distance.dtype).max
804+ reachable # A boolean array of reachable area.
805+
796806 You may edit this array manually, but the pathfinder won't know of
797807 your changes until :any:`rebuild_frontier` is called.
798808 """
799809 return self ._distance
800810
811+ @property
812+ def traversal (self ) -> np .ndarray :
813+ """An array used to generate paths from any point to the nearest root.
814+
815+ This array is stored in row-major "C" order. It has an extra
816+ dimension which includes the index of the next path.
817+
818+ Example::
819+
820+ # This example demonstrates the purpose of the traversal array.
821+ # In real code Pathfinder.path_from(...) should be used instead.
822+ pf # Resolved 2D Pathfinder instance.
823+ i, j = (3, 3) # Starting index.
824+ path = [(i, j)] # List of nodes from the start to the root.
825+ while not (pf.traversal[i, j] == (i, j)).all():
826+ i, j = pf.traversal[i, j]
827+ path.append((i, j))
828+
829+ The above example is slow and will not detect infinite loops. Use
830+ :any:`path_from` or :any:`path_to` when you need to get a path.
831+
832+ As the pathfinder is resolved this array is filled
833+ """
834+ return self ._travel
835+
801836 def clear (self ) -> None :
802837 """Reset the pathfinder to its initial state.
803838
804839 This sets all values on the :any:`distance` array to their maximum
805- values. Use :any:`numpy.iinfo` if you need to check these .
840+ value .
806841 """
807842 self ._distance [...] = np .iinfo (self ._distance .dtype ).max
808843 self ._travel = _world_array (self ._graph ._shape )
0 commit comments