2022-01-02 17:19:43 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
import copy
|
2022-01-02 21:43:44 +00:00
|
|
|
from typing import Tuple, TypeVar, TYPE_CHECKING, Optional, Type
|
|
|
|
|
|
|
|
from render_order import RenderOrder
|
2022-01-02 17:19:43 +00:00
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
2022-01-02 21:43:44 +00:00
|
|
|
from components.ai import BaseAI
|
|
|
|
from components.fighter import Fighter
|
2022-01-02 17:19:43 +00:00
|
|
|
from game_map import GameMap
|
|
|
|
|
|
|
|
T = TypeVar("T", bound="Entity")
|
|
|
|
|
2022-01-02 15:23:25 +00:00
|
|
|
|
|
|
|
class Entity:
|
|
|
|
"""
|
|
|
|
A generic object to represent players, enemies, items, etc.
|
|
|
|
"""
|
2022-01-02 17:19:43 +00:00
|
|
|
|
2022-01-02 17:50:33 +00:00
|
|
|
gamemap: GameMap
|
|
|
|
|
2022-01-02 21:43:44 +00:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
gamemap: Optional[GameMap] = None,
|
|
|
|
x: int = 0,
|
|
|
|
y: int = 0,
|
|
|
|
char: str = "?",
|
|
|
|
color: Tuple[int, int, int] = (255, 255, 255),
|
|
|
|
name: str = "<Unnamed>",
|
|
|
|
blocks_movement: bool = False,
|
|
|
|
render_order: RenderOrder = RenderOrder.CORPSE,
|
2022-01-02 17:19:43 +00:00
|
|
|
):
|
2022-01-02 15:23:25 +00:00
|
|
|
self.x = x
|
|
|
|
self.y = y
|
|
|
|
self.char = char
|
|
|
|
self.color = color
|
2022-01-02 17:19:43 +00:00
|
|
|
self.name = name
|
|
|
|
self.blocks_movement = blocks_movement
|
2022-01-02 21:43:44 +00:00
|
|
|
self.render_order = render_order
|
2022-01-02 17:50:33 +00:00
|
|
|
if gamemap:
|
|
|
|
self.gamemap = gamemap
|
|
|
|
gamemap.entities.add(self)
|
2022-01-02 17:19:43 +00:00
|
|
|
|
|
|
|
def spawn(self: T, gamemap: GameMap, x: int, y: int) -> T:
|
|
|
|
"""Spawns a copy of this instance at the given location"""
|
|
|
|
clone = copy.deepcopy(self)
|
|
|
|
clone.x = x
|
|
|
|
clone.y = y
|
2022-01-02 17:50:33 +00:00
|
|
|
clone.gamemap = gamemap
|
2022-01-02 17:19:43 +00:00
|
|
|
gamemap.entities.add(clone)
|
|
|
|
return clone
|
2022-01-02 15:23:25 +00:00
|
|
|
|
2022-01-02 17:50:33 +00:00
|
|
|
def place(self, x: int, y: int, gamemap: Optional[GameMap] = None) -> None:
|
|
|
|
self.x = x
|
|
|
|
self.y = y
|
|
|
|
if gamemap:
|
|
|
|
if hasattr(self, "gamemap"):
|
|
|
|
self.gamemap.entities.remove(self)
|
|
|
|
self.gamemap = gamemap
|
|
|
|
gamemap.entities.add(self)
|
|
|
|
|
2022-01-02 15:23:25 +00:00
|
|
|
def move(self, dx: int, dy: int) -> None:
|
|
|
|
self.x += dx
|
|
|
|
self.y += dy
|
2022-01-02 21:43:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Actor(Entity):
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
*,
|
|
|
|
x: int = 0,
|
|
|
|
y: int = 0,
|
|
|
|
char: str = "?",
|
|
|
|
color: Tuple[int, int, int] = (255, 255, 255),
|
|
|
|
name: str = "<Unnamed>",
|
|
|
|
ai_cls: Type[BaseAI],
|
|
|
|
fighter: Fighter
|
|
|
|
):
|
|
|
|
super().__init__(
|
|
|
|
x=x,
|
|
|
|
y=y,
|
|
|
|
char=char,
|
|
|
|
color=color,
|
|
|
|
name=name,
|
|
|
|
blocks_movement=True,
|
|
|
|
render_order=RenderOrder.ACTOR,
|
|
|
|
)
|
|
|
|
|
|
|
|
self.ai: Optional[BaseAI] = ai_cls(self)
|
|
|
|
|
|
|
|
self.fighter = fighter
|
|
|
|
self.fighter.entity = self
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_alive(self) -> bool:
|
|
|
|
"""returns as long as can return actions."""
|
|
|
|
return bool(self.ai)
|