Remove QuitAction and ActionWithActor!
Move quit event handling to the interface and flatten the Action class hierarchy. There are no longer any actions that don't take an Actor. This has the happy side effect of resolving some pylint errors too. :)
This commit is contained in:
parent
02ed3d1e4a
commit
327cc90b2e
6 changed files with 24 additions and 43 deletions
|
@ -12,6 +12,10 @@ if TYPE_CHECKING:
|
||||||
class Action:
|
class Action:
|
||||||
'''An action with no specific actor'''
|
'''An action with no specific actor'''
|
||||||
|
|
||||||
|
def __init__(self, actor: Actor):
|
||||||
|
super().__init__()
|
||||||
|
self.actor = actor
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def perform(self, engine: 'Engine') -> ActionResult:
|
def perform(self, engine: 'Engine') -> ActionResult:
|
||||||
'''Perform this action.
|
'''Perform this action.
|
||||||
|
@ -42,17 +46,3 @@ class Action:
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'{self.__class__.__name__}()'
|
return f'{self.__class__.__name__}()'
|
||||||
|
|
||||||
|
|
||||||
class ActionWithActor(Action):
|
|
||||||
'''An action that assigned to an actor'''
|
|
||||||
|
|
||||||
def __init__(self, actor: Actor):
|
|
||||||
super().__init__()
|
|
||||||
self.actor = actor
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f'{self.__class__.__name__} for {self.actor!s}'
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f'{self.__class__.__name__}({self.actor!r})'
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ Action : Base class of all actions
|
||||||
BumpAction
|
BumpAction
|
||||||
WalkAction
|
WalkAction
|
||||||
MeleeAction
|
MeleeAction
|
||||||
ExitAction
|
|
||||||
WaitAction
|
WaitAction
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -22,21 +21,14 @@ from .. import items
|
||||||
from .. import log
|
from .. import log
|
||||||
from ..geometry import Vector
|
from ..geometry import Vector
|
||||||
from ..object import Actor, Item
|
from ..object import Actor, Item
|
||||||
from .action import Action, ActionWithActor
|
from .action import Action
|
||||||
from .result import ActionResult
|
from .result import ActionResult
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..engine import Engine
|
from ..engine import Engine
|
||||||
|
|
||||||
|
|
||||||
class ExitAction(Action):
|
class MoveAction(Action):
|
||||||
'''Exit the game.'''
|
|
||||||
|
|
||||||
def perform(self, engine: 'Engine') -> ActionResult:
|
|
||||||
raise SystemExit()
|
|
||||||
|
|
||||||
|
|
||||||
class MoveAction(ActionWithActor):
|
|
||||||
'''An abstract Action that requires a direction to complete.'''
|
'''An abstract Action that requires a direction to complete.'''
|
||||||
|
|
||||||
def __init__(self, actor: Actor, direction: Vector):
|
def __init__(self, actor: Actor, direction: Vector):
|
||||||
|
@ -157,7 +149,7 @@ class MeleeAction(MoveAction):
|
||||||
return self.success()
|
return self.success()
|
||||||
|
|
||||||
|
|
||||||
class WaitAction(ActionWithActor):
|
class WaitAction(Action):
|
||||||
'''Wait a turn'''
|
'''Wait a turn'''
|
||||||
|
|
||||||
def perform(self, engine: 'Engine') -> ActionResult:
|
def perform(self, engine: 'Engine') -> ActionResult:
|
||||||
|
@ -174,7 +166,7 @@ class WaitAction(ActionWithActor):
|
||||||
return self.success()
|
return self.success()
|
||||||
|
|
||||||
|
|
||||||
class DieAction(ActionWithActor):
|
class DieAction(Action):
|
||||||
'''Kill an Actor'''
|
'''Kill an Actor'''
|
||||||
|
|
||||||
def perform(self, engine: 'Engine') -> ActionResult:
|
def perform(self, engine: 'Engine') -> ActionResult:
|
||||||
|
@ -193,7 +185,7 @@ class DieAction(ActionWithActor):
|
||||||
return self.success()
|
return self.success()
|
||||||
|
|
||||||
|
|
||||||
class DropItemAction(ActionWithActor):
|
class DropItemAction(Action):
|
||||||
'''Drop an item'''
|
'''Drop an item'''
|
||||||
|
|
||||||
def __init__(self, actor: 'Actor', item: 'Item'):
|
def __init__(self, actor: 'Actor', item: 'Item'):
|
||||||
|
@ -205,7 +197,7 @@ class DropItemAction(ActionWithActor):
|
||||||
return self.success()
|
return self.success()
|
||||||
|
|
||||||
|
|
||||||
class HealAction(ActionWithActor):
|
class HealAction(Action):
|
||||||
'''Heal a target actor some number of hit points'''
|
'''Heal a target actor some number of hit points'''
|
||||||
|
|
||||||
def __init__(self, actor: 'Actor', hit_points_to_recover: int):
|
def __init__(self, actor: 'Actor', hit_points_to_recover: int):
|
||||||
|
|
|
@ -7,7 +7,7 @@ import numpy as np
|
||||||
import tcod
|
import tcod
|
||||||
|
|
||||||
from . import log
|
from . import log
|
||||||
from .actions.action import ActionWithActor
|
from .actions.action import Action
|
||||||
from .actions.game import BumpAction, WaitAction
|
from .actions.game import BumpAction, WaitAction
|
||||||
from .components import Component
|
from .components import Component
|
||||||
from .geometry import Direction, Point
|
from .geometry import Direction, Point
|
||||||
|
@ -26,7 +26,7 @@ class AI(Component):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.entity = entity
|
self.entity = entity
|
||||||
|
|
||||||
def act(self, engine: 'Engine') -> Optional[ActionWithActor]:
|
def act(self, engine: 'Engine') -> Optional[Action]:
|
||||||
'''Produce an action to perform'''
|
'''Produce an action to perform'''
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class HostileEnemy(AI):
|
||||||
beeline for her.
|
beeline for her.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def act(self, engine: 'Engine') -> Optional[ActionWithActor]:
|
def act(self, engine: 'Engine') -> Optional[Action]:
|
||||||
visible_tiles = tcod.map.compute_fov(
|
visible_tiles = tcod.map.compute_fov(
|
||||||
engine.map.tiles['transparent'],
|
engine.map.tiles['transparent'],
|
||||||
pov=tuple(self.entity.position),
|
pov=tuple(self.entity.position),
|
||||||
|
|
|
@ -9,7 +9,7 @@ import tcod
|
||||||
|
|
||||||
from . import log
|
from . import log
|
||||||
from . import monsters
|
from . import monsters
|
||||||
from .actions.action import Action, ActionWithActor
|
from .actions.action import Action
|
||||||
from .actions.result import ActionResult
|
from .actions.result import ActionResult
|
||||||
from .ai import HostileEnemy
|
from .ai import HostileEnemy
|
||||||
from .configuration import Configuration
|
from .configuration import Configuration
|
||||||
|
@ -110,7 +110,7 @@ class Engine:
|
||||||
|
|
||||||
def process_input_action(self, action: Action):
|
def process_input_action(self, action: Action):
|
||||||
'''Process an Action from player input'''
|
'''Process an Action from player input'''
|
||||||
if not isinstance(action, ActionWithActor):
|
if not isinstance(action, Action):
|
||||||
action.perform(self)
|
action.perform(self)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ class Engine:
|
||||||
if action:
|
if action:
|
||||||
self._perform_action_until_done(action)
|
self._perform_action_until_done(action)
|
||||||
|
|
||||||
def _perform_action_until_done(self, action: ActionWithActor) -> ActionResult:
|
def _perform_action_until_done(self, action: Action) -> ActionResult:
|
||||||
'''Perform the given action and any alternate follow-up actions until the action chain is done.'''
|
'''Perform the given action and any alternate follow-up actions until the action chain is done.'''
|
||||||
result = action.perform(self)
|
result = action.perform(self)
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ class Engine:
|
||||||
|
|
||||||
if log.ACTIONS_TREE.isEnabledFor(log.INFO) and self.map.visible[tuple(action.actor.position)]:
|
if log.ACTIONS_TREE.isEnabledFor(log.INFO) and self.map.visible[tuple(action.actor.position)]:
|
||||||
if result.alternate:
|
if result.alternate:
|
||||||
alternate_string = f'{result.alternate.__class__.__name__}[{result.alternate.actor.symbol}]'
|
alternate_string = f'{result.alternate.__class__.__name__}[{result.alternate.actor}]'
|
||||||
else:
|
else:
|
||||||
alternate_string = str(result.alternate)
|
alternate_string = str(result.alternate)
|
||||||
log.ACTIONS_TREE.info(
|
log.ACTIONS_TREE.info(
|
||||||
|
|
|
@ -6,7 +6,7 @@ import tcod
|
||||||
import tcod.event as tev
|
import tcod.event as tev
|
||||||
|
|
||||||
from .actions.action import Action
|
from .actions.action import Action
|
||||||
from .actions.game import BumpAction, ExitAction, WaitAction
|
from .actions.game import BumpAction, WaitAction
|
||||||
from .geometry import Direction
|
from .geometry import Direction
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
@ -51,9 +51,6 @@ class EngineEventHandler(tev.EventDispatch[Action]):
|
||||||
|
|
||||||
return action
|
return action
|
||||||
|
|
||||||
def ev_quit(self, event: tcod.event.Quit) -> Optional[Action]:
|
|
||||||
return ExitAction()
|
|
||||||
|
|
||||||
|
|
||||||
class GameOverEventHandler(tev.EventDispatch[Action]):
|
class GameOverEventHandler(tev.EventDispatch[Action]):
|
||||||
'''When the game is over (the hero dies, the player quits, etc), this event handler takes over.'''
|
'''When the game is over (the hero dies, the player quits, etc), this event handler takes over.'''
|
||||||
|
@ -61,6 +58,3 @@ class GameOverEventHandler(tev.EventDispatch[Action]):
|
||||||
def __init__(self, engine: 'Engine'):
|
def __init__(self, engine: 'Engine'):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.engine = engine
|
self.engine = engine
|
||||||
|
|
||||||
def ev_quit(self, event: tev.Quit) -> Optional[Action]:
|
|
||||||
return ExitAction()
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
'''Defines event handling mechanisms.'''
|
'''Defines event handling mechanisms.'''
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import NoReturn, TYPE_CHECKING
|
||||||
|
|
||||||
from tcod import event as tev
|
from tcod import event as tev
|
||||||
|
|
||||||
|
@ -42,6 +42,11 @@ class InterfaceEventHandler(tev.EventDispatch[bool]):
|
||||||
def ev_mousebuttonup(self, event: tev.MouseButtonUp) -> bool:
|
def ev_mousebuttonup(self, event: tev.MouseButtonUp) -> bool:
|
||||||
return self._handle_event(event)
|
return self._handle_event(event)
|
||||||
|
|
||||||
|
def ev_quit(self, event: tev.Quit) -> NoReturn:
|
||||||
|
# TODO: Maybe show a "do you want to quit?" alert?
|
||||||
|
# TODO: Probably inform the engine that we're shutting down.
|
||||||
|
raise SystemExit()
|
||||||
|
|
||||||
def _handle_event(self, event: tev.Event) -> bool:
|
def _handle_event(self, event: tev.Event) -> bool:
|
||||||
for handler in self._handlers:
|
for handler in self._handlers:
|
||||||
if handler and handler.dispatch(event):
|
if handler and handler.dispatch(event):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue