def probableRangedAttack(self): """ Return an action for a ranged attack on a target if such an attack is possible. Otherwise, return None. """ if "two_square_thrower" in self.tags: if self.currentLevel.player in self.fov \ and coordinates.minimumPath(self.coords, self.currentLevel.player.coords) in range(1, 4): possible_directions = ((2,0),(2,2),(0,2),(-2,2),(-2,0),(-2,-2),(0,-2),(2,-2)) possible_targets = [coordinates.add(self.coords, i) for i in possible_directions if self.currentLevel.isEmpty(coordinates.add(self.coords, i))] visible_targets = [coords for coords in possible_targets if coords in self.fov] close_targets = [coords for coords in visible_targets if (coordinates.minimumPath(coords, self.currentLevel.player.coords) <= 1)] actual_targets = [coords for coords in close_targets if coords not in self.currentLevel.dudeLayer] if len(actual_targets) == 0: return None final_target = rng.choice(actual_targets) return action.ThrowGrenade(self, final_target) else: return None elif "twelve_square_firer" in self.tags: direction = coordinates.get_cardinal_direction(self.coords, self.currentLevel.player.coords) dist = coordinates.minimumPath(self.coords, self.currentLevel.player.coords) if self.currentLevel.player in self.fov \ and direction is not None \ and dist < 12: return action.FireArrow(self, direction, 12) else: return None else: return None
def are_immediately_accessible(self, coords1, coords2): """ Returns true if a move from coords1 to coords2 is legal given the dungeon layout, false otherwise. This function does not take into account monsters on either square. """ # the given coordinates are legal result = (all(map(self.legalCoordinates, (coords1, coords2))) and # the movedDude can move on the dungeon tile of moveCoords all(map(self.isEmpty, (coords1, coords2))) and # moveCoords is only one square away (coordinates.minimumPath(coords1, coords2) == 1)) # a "corner move," of the following form, is NOT being performed # d. (moving from s to d) # #s if coordinates.are_diagonally_adjacent(coords1, coords2): adjacent_squares = ((coords1[0], coords2[1]), (coords2[0], coords1[1])) # Return true only if both adjacent squares are empty, i.e. disallow corner moves. result = result and all(map(lambda x: self.isEmpty(x), adjacent_squares)) return result
def rangedApproach(self): if ("prefer_melee" in self.tags and coordinates.minimumPath( self.coords, self.currentLevel.player.coords) == 1): # If the monster prefers melee and is in melee range, don't do a ranged attack. return self.closeToPlayer() ranged_attack = self.probableRangedAttack() if ranged_attack is not None: return ranged_attack else: return self.closeToPlayer()