Example #1
0
 def test_is_obstacle_higher_than_start_y_axis_pos_direction_false(self):
     elevations = {
         Point(0, 0): 0,
         Point(1, 0): 2,
         Point(2, 0): 0,
         Point(0, 1): 0,
         Point(1, 1): 0,
         Point(2, 1): 0,
         Point(0, 2): 0,
         Point(1, 2): 2,
         Point(2, 2): 0,
         Point(0, 3): 0,
         Point(1, 3): 2,
         Point(2, 3): 0
     }
     tiles = [
         Tile(point=point, elevation=elevation)
         for point, elevation in elevations.items()
     ]
     map_ = Map(3, 4, tiles)
     sighting_tool = LineOfSight(map_)
     start = Point(1, 3)
     finish = Point(1, 0)
     self.assertFalse(
         sighting_tool.is_obstacle_higher_than_start(start, finish))
Example #2
0
 def test_can_sight_target_target_lower(self):
     elevations = {
         Point(0, 0): 4,
         Point(1, 0): 2,
         Point(2, 0): 0,
         Point(0, 1): 4,
         Point(1, 1): 5,
         Point(2, 1): 1,
         Point(0, 2): 1,
         Point(1, 2): 1,
         Point(2, 2): 4,
         Point(0, 3): 4,
         Point(1, 3): 1,
         Point(2, 3): 4
     }
     tiles = [
         Tile(point=point, elevation=elevation)
         for point, elevation in elevations.items()
     ]
     map_ = Map(3, 4, tiles)
     sighting_tool = LineOfSight(map_)
     target = Point(2, 0)
     shooter_miss_1 = Point(0, 1)
     shooter_miss_2 = Point(0, 3)
     shooter_hit_1 = Point(0, 0)
     shooter_hit_2 = Point(2, 3)
     self.assertFalse(sighting_tool.can_sight_target(
         target, shooter_miss_1))
     self.assertFalse(sighting_tool.can_sight_target(
         target, shooter_miss_2))
     self.assertTrue(sighting_tool.can_sight_target(target, shooter_hit_1))
     self.assertTrue(sighting_tool.can_sight_target(target, shooter_hit_2))
Example #3
0
    def test_can_sight_target_missing_tile(self):
        elevations = {
            Point(0, 0): 1,
            Point(1, 0): 0,
            Point(2, 0): 0,
            Point(0, 1): 0,
            Point(1, 1): 3,
            Point(2, 1): 5,
            Point(1, 2): 1,
            Point(0, 3): 2,
            Point(1, 3): 0,
            Point(2, 3): 0
        }
        tiles = [
            Tile(point=point, elevation=elevation)
            for point, elevation in elevations.items()
        ]
        map_ = Map(3, 4, tiles)
        sighting_tool = LineOfSight(map_)
        target_true = Point(0, 0)
        shooter_true = Point(0, 3)
        self.assertTrue(
            sighting_tool.can_sight_target(target_true, shooter_true))

        target_false = Point(2, 3)
        shooter_false = Point(2, 0)
        self.assertFalse(
            sighting_tool.can_sight_target(target_false, shooter_false))
Example #4
0
 def test_is_target_above_shooter_false(self):
     elevations = {
         Point(0, 0): 0,
         Point(1, 0): 2,
         Point(2, 0): 3,
         Point(0, 1): 0,
         Point(1, 1): 2,
         Point(2, 1): 0,
         Point(0, 2): 4,
         Point(1, 2): 3,
         Point(2, 2): 4,
         Point(0, 3): 0,
         Point(1, 3): 4,
         Point(2, 3): 0
     }
     tiles = [
         Tile(point=point, elevation=elevation)
         for point, elevation in elevations.items()
     ]
     map_ = Map(3, 4, tiles)
     sighting_tool = LineOfSight(map_)
     target_below = Point(1, 0)
     target_equal = Point(1, 2)
     shooter = Point(2, 0)
     self.assertFalse(
         sighting_tool.is_target_above_shooter(target_below, shooter))
     self.assertFalse(
         sighting_tool.is_target_above_shooter(target_equal, shooter))
Example #5
0
 def test_is_obstacle_higher_than_start_slope_lt_neg_one_true(self):
     elevations = {
         Point(0, 0): 1,
         Point(1, 0): 0,
         Point(2, 0): 0,
         Point(0, 1): 0,
         Point(1, 1): 3,
         Point(2, 1): 0,
         Point(0, 2): 0,
         Point(1, 2): 1,
         Point(2, 2): 1,
         Point(0, 3): 2,
         Point(1, 3): 0,
         Point(2, 3): 0
     }
     tiles = [
         Tile(point=point, elevation=elevation)
         for point, elevation in elevations.items()
     ]
     map_ = Map(3, 4, tiles)
     sighting_tool = LineOfSight(map_)
     start = Point(0, 3)
     finish = Point(1, 0)
     self.assertTrue(
         sighting_tool.is_obstacle_higher_than_start(start, finish))
Example #6
0
 def __init__(self, map_: Map):
     self._map = map_
     self._sighter = LineOfSight(map_)
Example #7
0
class RangeFinder(object):
    def __init__(self, map_: Map):
        self._map = map_
        self._sighter = LineOfSight(map_)

    def get_all_usable_points_units_only(self, origin: Point, max_distance: int) -> Dict[int, List[Point]]:
        distances_to_points = {key: [] for key in range(max_distance+1)}
        largest_map_distance = sum(self._map.get_size())

        stop_checking_map = min(largest_map_distance, max_distance) + 1

        for distance in range(stop_checking_map):
            on_map_pts = [point for point in origin.at_distance(distance)
                          if self._map.has_unit(point)]
            distances_to_points[distance] = on_map_pts
        return distances_to_points

    def get_all_usable_points(self, origin: Point, max_distance: int) -> Dict[int, List[Point]]:
        distances_to_points = dict.fromkeys(range(max_distance + 1), [])
        largest_map_distance = sum(self._map.get_size())

        stop_checking_map = min(largest_map_distance, max_distance) + 1

        for distance in range(stop_checking_map):
            on_map_pts = [point for point in origin.at_distance(distance)
                          if self._map.is_on_map(point) and self._map.has_tile(point)]
            distances_to_points[distance] = on_map_pts
        return distances_to_points

    def get_all_units(self, origin: Point, max_distance: int) -> Dict[int, List[Soldier]]:
        distances_to_points = self.get_all_usable_points(origin, max_distance)
        distances_to_units = {}
        for distance, points in distances_to_points.items():
            units = [self._map.get_unit(point) for point in points if self._map.has_unit(point)]
            distances_to_units[distance] = units
        return distances_to_units

    def get_sight_ranges(self, origin: Point, max_distance: int) -> dict:
        points = self.get_all_usable_points(origin, max_distance)
        return {key: [point for point in val if self._sighter.can_sight_target(point, origin)]
                for key, val in points.items()}

    def get_sight_ranges_units_only(self, origin: Point, max_distance: int) -> dict:
        points = self.get_all_usable_points_units_only(origin, max_distance)
        return {key: [point for point in val if self._sighter.can_sight_target(point, origin)]
                for key, val in points.items()}

    def get_attack_ranges_ranged(self, origin: Point, range_: int) -> dict:
        distance_point_dict = self.get_sight_ranges(origin, range_)
        new_dict = {distance: self._get_advantage_list(origin, points)
                    for distance, points in distance_point_dict.items()}
        return new_dict

    def get_attack_ranges_ranged_units_only(self, origin: Point, range_: int) -> dict:
        distance_point_dict = self.get_sight_ranges_units_only(origin, range_)
        new_dict = {distance: self._get_advantage_list(origin, points)
                    for distance, points in distance_point_dict.items()}
        return new_dict

    def _get_advantage_list(self, shooter: Point, targets: List[Point]) -> List[Tuple[Point, int]]:
        return [(point, self._get_advantage_value(shooter, point)) for point in targets]

    def _get_advantage_value(self, shooter: Point, target: Point) -> int:
        shooter_el = self._map.get_elevation(shooter)
        target_el = self._map.get_elevation(target)
        if shooter_el > target_el:
            return 1
        elif shooter_el < target_el:
            return -1
        else:
            return 0

    def get_attack_ranges_melee(self, origin: Point, range_: int = 1) -> dict:
        """return dict of ranges: [(point, advantage_value)]
                elevation limit is +/- 3"""
        raw_answer = self.get_attack_ranges_ranged(origin, range_)

        answer = {distance: self._filter_by_melee_reach(point_advantage_list, origin)
                  for distance, point_advantage_list in raw_answer.items()}
        return answer

    def get_attack_ranges_melee_units_only(self, origin: Point, range_: int = 1) -> dict:
        """return dict of ranges: [(point, advantage_value)]
                elevation limit is +/- 3"""
        raw_answer = self.get_attack_ranges_ranged_units_only(origin, range_)

        answer = {distance: self._filter_by_melee_reach(point_advantage_list, origin)
                  for distance, point_advantage_list in raw_answer.items()}
        return answer

    def _filter_by_melee_reach(self, point_advantage_list, origin):
        melee_reach_limit = 3
        new_list = [point_advantage for point_advantage in point_advantage_list if
                    self._is_elevation_in_range(origin, point_advantage[0], melee_reach_limit)]
        return new_list

    def _is_elevation_in_range(self, shooter: Point, target: Point, el_range: int):
        shooter_el = self._map.get_elevation(shooter)
        target_el = self._map.get_elevation(target)
        distance = abs(shooter_el - target_el)
        if distance <= el_range:
            return True
        else:
            return False