def with_zero_x_area(self) -> "Launch":
     cls = type(self)
     # noinspection PyArgumentList
     return cls(
         area=self.area.with_zero_x(),
         path=[Point2D.get_zero_point()],
     )
 def __str__(self) -> str:
     """
     >>> print(":", Scanner2D.from_scanner_text('''
     ...     --- scanner 0 ---
     ...     0,2
     ...     4,1
     ...     3,3
     ... '''))
     : ...B.
     B....
     ....B
     S....
     """
     return self.plot([self], [Point2D.get_zero_point()])
    def get_highest_y_for_initial_y_that_lands_in_area_y(
        self, initial_y: int,
    ) -> Optional[int]:
        if not (self.area.min.x == self.area.max.x == 0):
            return self\
                .with_zero_x_area()\
                .get_highest_y_for_initial_y_that_lands_in_area_y(initial_y)

        path = self.generate_path(
            Point2D.get_zero_point(),
            Point2D(0, initial_y),
        )
        last_point = path[-1]
        if last_point not in self.area:
            return None
        _, (_, max_y) = min_and_max_tuples(path)
        return max_y
 def from_area_text(cls, area_text: str) -> "Launch":
     return cls(
         area=Area.from_area_text(area_text),
         path=[Point2D.get_zero_point()],
     )
 def travel(self) -> "Position":
     return self.travel_from(Point2D.get_zero_point())
 def make_initial(cls) -> "CavernMeasurerState":
     return cls(
         position=Point2D.get_zero_point(),
         distance=0,
     )
 def does_path_land_in_area(self, initial_velocity: Point2D) -> bool:
     path = self.generate_path(Point2D.get_zero_point(), initial_velocity)
     last_point = path[-1]
     return last_point in self.area