Intra-chapter refactoring
This commit is contained in:
parent
8e9f088c35
commit
f947338c2d
@ -6,14 +6,12 @@ import numpy as np # type: ignore
|
|||||||
import tcod
|
import tcod
|
||||||
|
|
||||||
from actions import Action, MeleeAction, MovementAction, WaitAction
|
from actions import Action, MeleeAction, MovementAction, WaitAction
|
||||||
from components.base_component import BaseComponent
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from entity import Actor
|
from entity import Actor
|
||||||
|
|
||||||
|
|
||||||
class BaseAI(Action, BaseComponent):
|
class BaseAI(Action):
|
||||||
entity: Actor
|
|
||||||
|
|
||||||
def get_path_to(self, dest_x: int, dest_y: int) -> List[Tuple[int, int]]:
|
def get_path_to(self, dest_x: int, dest_y: int) -> List[Tuple[int, int]]:
|
||||||
"""Compute and return a path to the target position.
|
"""Compute and return a path to the target position.
|
||||||
|
@ -5,11 +5,16 @@ from typing import TYPE_CHECKING
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from engine import Engine
|
from engine import Engine
|
||||||
from entity import Entity
|
from entity import Entity
|
||||||
|
from game_map import GameMap
|
||||||
|
|
||||||
|
|
||||||
class BaseComponent:
|
class BaseComponent:
|
||||||
entity: Entity # Owning entity instance
|
parent: Entity # Owning entity instance
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gamemap(self) -> GameMap:
|
||||||
|
return self.parent.gamemap
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def engine(self) -> Engine:
|
def engine(self) -> Engine:
|
||||||
return self.entity.gamemap.engine
|
return self.gamemap.engine
|
||||||
|
@ -12,7 +12,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
class Fighter(BaseComponent):
|
class Fighter(BaseComponent):
|
||||||
entity: Actor
|
parent: Actor
|
||||||
|
|
||||||
def __init__(self, hp: int, defense: int, power: int):
|
def __init__(self, hp: int, defense: int, power: int):
|
||||||
self.max_hp = hp
|
self.max_hp = hp
|
||||||
@ -27,23 +27,23 @@ class Fighter(BaseComponent):
|
|||||||
@hp.setter
|
@hp.setter
|
||||||
def hp(self, value: int) -> None:
|
def hp(self, value: int) -> None:
|
||||||
self._hp = max(0, min(value, self.max_hp))
|
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()
|
self.die()
|
||||||
|
|
||||||
def die(self) -> None:
|
def die(self) -> None:
|
||||||
if self.engine.player is self.entity:
|
if self.engine.player is self.parent:
|
||||||
death_message = "You died!"
|
death_message = "You died!"
|
||||||
death_message_color = color.player_die
|
death_message_color = color.player_die
|
||||||
self.engine.event_handler = GameOverEventHandler(self.engine)
|
self.engine.event_handler = GameOverEventHandler(self.engine)
|
||||||
else:
|
else:
|
||||||
death_message = f"{self.entity.name} is dead!"
|
death_message = f"{self.parent.name} is dead!"
|
||||||
death_message_color = color.enemy_die
|
death_message_color = color.enemy_die
|
||||||
|
|
||||||
self.entity.char = "%"
|
self.parent.char = "%"
|
||||||
self.entity.color = (191, 0, 0)
|
self.parent.color = (191, 0, 0)
|
||||||
self.entity.blocks_movement = False
|
self.parent.blocks_movement = False
|
||||||
self.entity.ai = None
|
self.parent.ai = None
|
||||||
self.entity.name = f"remains of {self.entity.name}"
|
self.parent.name = f"remains of {self.parent.name}"
|
||||||
self.entity.render_order = RenderOrder.CORPSE
|
self.parent.render_order = RenderOrder.CORPSE
|
||||||
|
|
||||||
self.engine.message_log.add_message(death_message, death_message_color)
|
self.engine.message_log.add_message(death_message, death_message_color)
|
||||||
|
23
entity.py
23
entity.py
@ -18,11 +18,11 @@ class Entity:
|
|||||||
A generic object to represent players, enemies, items, etc.
|
A generic object to represent players, enemies, items, etc.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
gamemap: GameMap
|
parent: GameMap
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
gamemap: Optional[GameMap] = None,
|
parent: Optional[GameMap] = None,
|
||||||
x: int = 0,
|
x: int = 0,
|
||||||
y: int = 0,
|
y: int = 0,
|
||||||
char: str = "?",
|
char: str = "?",
|
||||||
@ -38,17 +38,21 @@ class Entity:
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.blocks_movement = blocks_movement
|
self.blocks_movement = blocks_movement
|
||||||
self.render_order = render_order
|
self.render_order = render_order
|
||||||
if gamemap:
|
if parent:
|
||||||
# If gamemap isn't provided now, it will be later.
|
# If gamemap isn't provided now, it will be later.
|
||||||
self.gamemap = gamemap
|
self.parent = parent
|
||||||
gamemap.entities.add(self)
|
parent.entities.add(self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gamemap(self) -> GameMap:
|
||||||
|
return self.parent.gamemap
|
||||||
|
|
||||||
def spawn(self: T, gamemap: GameMap, x: int, y: int) -> T:
|
def spawn(self: T, gamemap: GameMap, x: int, y: int) -> T:
|
||||||
"""Spawn a copy of this instance at the given location."""
|
"""Spawn a copy of this instance at the given location."""
|
||||||
clone = copy.deepcopy(self)
|
clone = copy.deepcopy(self)
|
||||||
clone.x = x
|
clone.x = x
|
||||||
clone.y = y
|
clone.y = y
|
||||||
clone.gamemap = gamemap
|
clone.parent = gamemap
|
||||||
gamemap.entities.add(clone)
|
gamemap.entities.add(clone)
|
||||||
return clone
|
return clone
|
||||||
|
|
||||||
@ -57,10 +61,11 @@ class Entity:
|
|||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
if gamemap:
|
if gamemap:
|
||||||
if hasattr(self, "gamemap"): # Possibly uninitialized
|
if hasattr(self, "parent"): # Possibly uninitialized
|
||||||
|
if self.parent is self.gamemap:
|
||||||
self.gamemap.entities.remove(self)
|
self.gamemap.entities.remove(self)
|
||||||
|
|
||||||
self.gamemap = gamemap
|
self.parent = gamemap
|
||||||
gamemap.entities.add(self)
|
gamemap.entities.add(self)
|
||||||
|
|
||||||
def move(self, dx: int, dy: int):
|
def move(self, dx: int, dy: int):
|
||||||
@ -94,7 +99,7 @@ class Actor(Entity):
|
|||||||
self.ai: Optional[BaseAI] = ai_cls(self)
|
self.ai: Optional[BaseAI] = ai_cls(self)
|
||||||
|
|
||||||
self.fighter = fighter
|
self.fighter = fighter
|
||||||
self.fighter.entity = self
|
self.fighter.parent = self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_alive(self) -> bool:
|
def is_alive(self) -> bool:
|
||||||
|
@ -37,6 +37,10 @@ class GameMap:
|
|||||||
order="F"
|
order="F"
|
||||||
) # Tiles the player has seen before
|
) # Tiles the player has seen before
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gamemap(self) -> GameMap:
|
||||||
|
return self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def actors(self) -> Iterator[Actor]:
|
def actors(self) -> Iterator[Actor]:
|
||||||
"""Iterate over this map's living actors."""
|
"""Iterate over this map's living actors."""
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from typing import List, Reversible, Tuple
|
from typing import Iterable, List, Reversible, Tuple
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
import tcod
|
import tcod
|
||||||
@ -57,7 +57,18 @@ class MessageLog:
|
|||||||
self.render_messages(console, x, y, width, height, self.messages)
|
self.render_messages(console, x, y, width, height, self.messages)
|
||||||
|
|
||||||
@staticmethod
|
@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(
|
def render_messages(
|
||||||
|
cls,
|
||||||
console: tcod.Console,
|
console: tcod.Console,
|
||||||
x: int,
|
x: int,
|
||||||
y: int,
|
y: int,
|
||||||
@ -72,7 +83,7 @@ class MessageLog:
|
|||||||
y_offset = height - 1
|
y_offset = height - 1
|
||||||
|
|
||||||
for message in reversed(messages):
|
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)
|
console.print(x=x, y=y + y_offset, string=line, fg=message.fg)
|
||||||
y_offset -= 1
|
y_offset -= 1
|
||||||
if y_offset < 0:
|
if y_offset < 0:
|
||||||
|
Loading…
Reference in New Issue
Block a user