# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse # SPDX-License-Identifier: GPL-3.0-or-later from random import shuffle from .player import Player from ..interfaces import FightingEntity, Map class Monster(FightingEntity): """ The class for all monsters in the dungeon. A monster must override this class, and the parameters are given in the __init__ function. An example of the specification of a monster that has a strength of 4 and 20 max HP: class MyMonster(Monster): def __init__(self, strength: int = 4, maxhealth: int = 20, *args, **kwargs) -> None: super().__init__(name="my_monster", strength=strength, maxhealth=maxhealth, *args, **kwargs) With that way, attributes can be overwritten when the entity got created. """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def act(self, m: Map) -> None: """ By default, a monster will move randomly where it is possible And if a player is close to the monster, the monster run on the player. """ target = None for entity in m.entities: if self.distance_squared(entity) <= 25 and \ isinstance(entity, Player): target = entity break # A Dijkstra algorithm has ran that targets the player. # With that way, monsters can simply follow the path. # If they can't move and they are already close to the player, # They hit. if target and (self.y, self.x) in target.paths: # Move to target player by choosing the best avaliable path for next_y, next_x in target.paths[(self.y, self.x)]: moved = self.check_move(next_y, next_x, True) if moved: break if self.distance_squared(target) <= 1: self.map.logs.add_message(self.hit(target)) break else: # Move in a random direction # If the direction is not available, try another one moves = [self.move_up, self.move_down, self.move_left, self.move_right] shuffle(moves) for move in moves: if move(): break class Tiger(Monster): """ A tiger monster """ def __init__(self, name: str = "tiger", strength: int = 2, maxhealth: int = 20, *args, **kwargs) -> None: super().__init__(name=name, strength=strength, maxhealth=maxhealth, *args, **kwargs) class Hedgehog(Monster): """ A really mean hedgehog monster """ def __init__(self, name: str = "hedgehog", strength: int = 3, maxhealth: int = 10, *args, **kwargs) -> None: super().__init__(name=name, strength=strength, maxhealth=maxhealth, *args, **kwargs) class Rabbit(Monster): """ A rabbit monster """ def __init__(self, name: str = "rabbit", strength: int = 1, maxhealth: int = 15, critical: int = 30, *args, **kwargs) -> None: super().__init__(name=name, strength=strength, maxhealth=maxhealth, critical=critical, *args, **kwargs) class TeddyBear(Monster): """ A cute teddybear monster """ def __init__(self, name: str = "teddy_bear", strength: int = 0, maxhealth: int = 50, *args, **kwargs) -> None: super().__init__(name=name, strength=strength, maxhealth=maxhealth, *args, **kwargs)