from typing import Any import colors class BaseAction: entity: Any def __init__(self, entity): self.entity = entity def apply(self) -> bool: raise NotImplementedError() class QuitAction(BaseAction): def __init__(self): #override the base __init__ pass def apply(self) -> bool: raise SystemExit() class WaitAction(BaseAction): def apply(self) -> bool: return True class DirectionAction(BaseAction): def __init__(self, entity, xdir: int, ydir: int): super().__init__(entity) self.xdir = xdir self.ydir = ydir def apply(self) -> bool: raise NotImplementedError() class MovementAction(DirectionAction): def apply(self) -> bool: dest_x = self.entity.x + self.xdir dest_y = self.entity.y + self.ydir #bounds and collision checks if not self.entity.floor_map.in_bounds(dest_x, dest_y): return False if not self.entity.floor_map.tiles["walkable"][dest_x, dest_y]: return False if self.entity.floor_map.get_entity_at(dest_x, dest_y, unwalkable_only=True) is not None: return False self.entity.set_pos(dest_x, dest_y) return True class MeleeAction(DirectionAction): def apply(self) -> bool: dest_x = self.entity.x + self.xdir dest_y = self.entity.y + self.ydir target = self.entity.floor_map.get_actor_at(dest_x, dest_y) if not target: return False #apply damage damage = self.entity.fighter.attack - target.fighter.defense target.fighter.current_hp -= damage #calculate output engine = self.entity.floor_map.engine msg_text = f"{self.entity.name} attacked {target.name}" msg_color = colors.white if self.entity is engine.player: msg_color = colors.player_atk else: msg_color = colors.enemy_atk if damage > 0: msg_text += f" for {damage} damage" else: msg_text += f" but was ineffective" engine.message_log.add_message(text = msg_text, fg=msg_color) return True class BumpAction(DirectionAction): #bad name, deal with it def apply(self) -> bool: dest_x = self.entity.x + self.xdir dest_y = self.entity.y + self.ydir if self.entity.floor_map.get_entity_at(dest_x, dest_y, unwalkable_only=True): return MeleeAction(self.entity, self.xdir, self.ydir).apply() else: return MovementAction(self.entity, self.xdir, self.ydir).apply()