def closeToPlayer(self): """ Pathfind to the player, and attack him if possible. """ player_location = self.currentLevel.player.coords # If adjacent to the player, attack him. if coordinates.adjacent(player_location, self.coords): if rng.percentChance(self.specfreq): return action.SpecialMelee(self, self.currentLevel.player, self.spec) else: return action.Attack( self, self.currentLevel.player, "%(SOURCE_NAME)s attacks %(TARGET_NAME)s! (%(DAMAGE)d)") # Otherwise, pathfind toward him. else: path = pf.find_shortest_path(self.currentLevel, self.coords, player_location, False) if path != []: move_coords = coordinates.subtract(path[1], path[0]) return action.Move(self, move_coords) else: return action.Wait(self)
def traveling(self): """ Calculate the action of a monster moving to a specific location. Note that a "path" variable must exist for this to make sense. """ # self.path[0] should be the monster's current square. # self.path[1] should be the square the monster wants to move to. # self.path[-1] should be the monster's ultimate destination. assert self.path != None, "Despite the monster being in state TRAVELING, the path variable is null." if self.currentLevel.player in self.fov: self.state = ais.FIGHTING return self.fighting() else: path_is_invalid = False if len(self.path) == 0: assert False # This shouldn't happen! path_is_invalid = True elif self.coords != self.path[0]: # Something has moved the monster since its last turn. path_is_invalid = True elif len(self.path) == 1: # Since self.coords == self.path[0], the monster has reached its destination! self.state = ais.WANDERING return self.wandering() elif not self.canMove(self.path[1]): path_is_invalid = True if path_is_invalid: if len(self.path) == 0: # If the path is completely empty, something has gone wrong. assert False # Just give up and return to being stationary. self.state = ais.RESTING return self.resting() else: destination = self.path[-1] self.path = pf.find_shortest_path(self.currentLevel, self.coords, destination, True) if len(self.path) == 0: # There simply is no path to the destination! # Set self.path to only contain the destination, so that next turn, this code # attempts to find another path. self.path = [destination] return action.Wait(self) elif len(self.path) == 1: # This should not happen! assert False return action.Wait(self) if self.canMove(self.path[1]): move_direction = coordinates.subtract(self.path[1], self.coords) self.path.pop(0) return action.Move(self, move_direction) else: assert False, "The supposedly legal path contains an illegal move!" return action.Wait(self)
def fighting(self): """ Calculate the action of a monster who sees the player. """ if self.currentLevel.player not in self.fov: if self.player_last_location is not None: # The player has escaped! Find a likely square where he could have gone. adjacent_coords = coordinates.adjacent_coords( self.player_last_location) legal_coords = [ i for i in adjacent_coords if coordinates.legal(i, self.currentLevel.dimensions) ] passable_coords = [ i for i in legal_coords if self.currentLevel.isEmpty(i) ] out_of_vision_coords = \ [i for i in passable_coords if i not in self.fov] if len(out_of_vision_coords) > 0: # There is a possible escape route! Pursue! self.direction = coordinates.subtract( rng.choice(out_of_vision_coords), self.player_last_location) self.path = pf.find_shortest_path( self.currentLevel, self.coords, self.player_last_location, False) if self.path == []: # There is no route to the player's escape route. Wait, but stay in # state FIGHTING so as to take advantage of any route that opens up. return action.Wait(self) self.state = ais.TRAVELING return self.traveling() else: # There is no possible escape route; give up and rest. self.state = ais.RESTING return self.resting() else: assert False else: self.player_last_location = self.currentLevel.player.coords if self.AICode == "CLOSE": return self.closeToPlayer() elif self.AICode == "RANGEDAPPROACH": return self.rangedApproach() else: raise exc.InvalidDataWarning( "The monster %s has an unknown AICode, %s" % (self.name, self.AICode)) return action.Wait(self) assert False