1
0
Fork 0

Intra-chapter refactoring

This commit is contained in:
Timothy Warren 2022-01-12 13:45:52 -05:00
parent 8e9f088c35
commit f947338c2d
6 changed files with 50 additions and 27 deletions

View File

@ -6,14 +6,12 @@ import numpy as np # type: ignore
import tcod
from actions import Action, MeleeAction, MovementAction, WaitAction
from components.base_component import BaseComponent
if TYPE_CHECKING:
from entity import Actor
class BaseAI(Action, BaseComponent):
entity: Actor
class BaseAI(Action):
def get_path_to(self, dest_x: int, dest_y: int) -> List[Tuple[int, int]]:
"""Compute and return a path to the target position.

View File

@ -5,11 +5,16 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from engine import Engine
from entity import Entity
from game_map import GameMap
class BaseComponent:
entity: Entity # Owning entity instance
parent: Entity # Owning entity instance
@property
def gamemap(self) -> GameMap:
return self.parent.gamemap
@property
def engine(self) -> Engine:
return self.entity.gamemap.engine
return self.gamemap.engine

View File

@ -12,7 +12,7 @@ if TYPE_CHECKING:
class Fighter(BaseComponent):
entity: Actor
parent: Actor
def __init__(self, hp: int, defense: int, power: int):
self.max_hp = hp
@ -27,23 +27,23 @@ class Fighter(BaseComponent):
@hp.setter
def hp(self, value: int) -> None:
self._hp = max(0, min(value, self.max_hp))
if self._hp == 0 and self.entity.ai:
if self._hp == 0 and self.parent.ai:
self.die()
def die(self) -> None:
if self.engine.player is self.entity:
if self.engine.player is self.parent:
death_message = "You died!"
death_message_color = color.player_die
self.engine.event_handler = GameOverEventHandler(self.engine)
else:
death_message = f"{self.entity.name} is dead!"
death_message = f"{self.parent.name} is dead!"
death_message_color = color.enemy_die
self.entity.char = "%"
self.entity.color = (191, 0, 0)
self.entity.blocks_movement = False
self.entity.ai = None
self.entity.name = f"remains of {self.entity.name}"
self.entity.render_order = RenderOrder.CORPSE
self.parent.char = "%"
self.parent.color = (191, 0, 0)
self.parent.blocks_movement = False
self.parent.ai = None
self.parent.name = f"remains of {self.parent.name}"
self.parent.render_order = RenderOrder.CORPSE
self.engine.message_log.add_message(death_message, death_message_color)

View File

@ -18,11 +18,11 @@ class Entity:
A generic object to represent players, enemies, items, etc.
"""
gamemap: GameMap
parent: GameMap
def __init__(
self,
gamemap: Optional[GameMap] = None,
parent: Optional[GameMap] = None,
x: int = 0,
y: int = 0,
char: str = "?",
@ -38,17 +38,21 @@ class Entity:
self.name = name
self.blocks_movement = blocks_movement
self.render_order = render_order
if gamemap:
if parent:
# If gamemap isn't provided now, it will be later.
self.gamemap = gamemap
gamemap.entities.add(self)
self.parent = parent
parent.entities.add(self)
@property
def gamemap(self) -> GameMap:
return self.parent.gamemap
def spawn(self: T, gamemap: GameMap, x: int, y: int) -> T:
"""Spawn a copy of this instance at the given location."""
clone = copy.deepcopy(self)
clone.x = x
clone.y = y
clone.gamemap = gamemap
clone.parent = gamemap
gamemap.entities.add(clone)
return clone
@ -57,10 +61,11 @@ class Entity:
self.x = x
self.y = y
if gamemap:
if hasattr(self, "gamemap"): # Possibly uninitialized
self.gamemap.entities.remove(self)
if hasattr(self, "parent"): # Possibly uninitialized
if self.parent is self.gamemap:
self.gamemap.entities.remove(self)
self.gamemap = gamemap
self.parent = gamemap
gamemap.entities.add(self)
def move(self, dx: int, dy: int):
@ -94,7 +99,7 @@ class Actor(Entity):
self.ai: Optional[BaseAI] = ai_cls(self)
self.fighter = fighter
self.fighter.entity = self
self.fighter.parent = self
@property
def is_alive(self) -> bool:

View File

@ -37,6 +37,10 @@ class GameMap:
order="F"
) # Tiles the player has seen before
@property
def gamemap(self) -> GameMap:
return self
@property
def actors(self) -> Iterator[Actor]:
"""Iterate over this map's living actors."""

View File

@ -1,4 +1,4 @@
from typing import List, Reversible, Tuple
from typing import Iterable, List, Reversible, Tuple
import textwrap
import tcod
@ -57,7 +57,18 @@ class MessageLog:
self.render_messages(console, x, y, width, height, self.messages)
@staticmethod
def wrap(string: str, width: int) -> Iterable[str]:
"""Return a wrapped text message."""
for line in string.splitlines(): # Handle newlines in messages.
yield from textwrap.wrap(
line,
width,
expand_tabs=True
)
@classmethod
def render_messages(
cls,
console: tcod.Console,
x: int,
y: int,
@ -72,7 +83,7 @@ class MessageLog:
y_offset = height - 1
for message in reversed(messages):
for line in reversed(textwrap.wrap(message.full_text, width)):
for line in reversed(list(cls.wrap(message.full_text, width))):
console.print(x=x, y=y + y_offset, string=line, fg=message.fg)
y_offset -= 1
if y_offset < 0: