Refactor events into their own package
Most of the existing actions are game actions (they control the player character) so they live in actions.game. Eventually, there will be modules for different kinds of actions that only apply to, e.g. modal UI.
This commit is contained in:
parent
46af8863b1
commit
ae1c7f5ce2
6 changed files with 114 additions and 90 deletions
4
erynrl/actions/__init__.py
Normal file
4
erynrl/actions/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
|
from .action import Action
|
||||||
|
from .result import ActionResult
|
45
erynrl/actions/action.py
Normal file
45
erynrl/actions/action.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
|
from ..object import Actor
|
||||||
|
from .result import ActionResult
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ..engine import Engine
|
||||||
|
|
||||||
|
class Action:
|
||||||
|
'''An action that an Entity should perform.'''
|
||||||
|
|
||||||
|
def __init__(self, actor: Optional[Actor] = None):
|
||||||
|
self.actor = actor
|
||||||
|
|
||||||
|
def perform(self, engine: 'Engine') -> ActionResult:
|
||||||
|
'''Perform this action.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
engine : Engine
|
||||||
|
The game engine
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
ActionResult
|
||||||
|
A result object reflecting how the action was handled, and what follow-up actions, if any, are needed to
|
||||||
|
complete the action.
|
||||||
|
'''
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def failure(self) -> ActionResult:
|
||||||
|
'''Create an ActionResult indicating failure with no follow-up'''
|
||||||
|
return ActionResult(self, success=False)
|
||||||
|
|
||||||
|
def success(self) -> ActionResult:
|
||||||
|
'''Create an ActionResult indicating success with no follow-up'''
|
||||||
|
return ActionResult(self, success=True)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f'{self.__class__.__name__} for {self.actor!s}'
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'{self.__class__.__name__}({self.actor!r})'
|
|
@ -18,96 +18,24 @@ Action : Base class of all actions
|
||||||
WaitAction
|
WaitAction
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from typing import Optional, TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from . import items
|
from .. import items
|
||||||
from . import log
|
from .. import log
|
||||||
from .geometry import Direction
|
from ..geometry import Direction
|
||||||
from .object import Actor, Item
|
from ..object import Actor, Item
|
||||||
|
from .action import Action
|
||||||
|
from .result import ActionResult
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .engine import Engine
|
from ..engine import Engine
|
||||||
|
|
||||||
class ActionResult:
|
|
||||||
'''The result of an Action.
|
|
||||||
|
|
||||||
`Action.perform()` returns an instance of this class to inform the caller of the result
|
|
||||||
|
|
||||||
Attributes
|
|
||||||
----------
|
|
||||||
action : Action
|
|
||||||
The Action that was performed
|
|
||||||
success : bool, optional
|
|
||||||
True if the action succeeded
|
|
||||||
done : bool, optional
|
|
||||||
True if the action is complete, and no follow-up action is needed
|
|
||||||
alternate : Action, optional
|
|
||||||
An alternate action to perform if this action failed
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, action: 'Action', *,
|
|
||||||
success: Optional[bool] = None,
|
|
||||||
done: Optional[bool] = None,
|
|
||||||
alternate: Optional['Action'] = None):
|
|
||||||
self.action = action
|
|
||||||
self.alternate = alternate
|
|
||||||
|
|
||||||
if success is not None:
|
|
||||||
self.success = success
|
|
||||||
elif alternate:
|
|
||||||
self.success = False
|
|
||||||
else:
|
|
||||||
self.success = True
|
|
||||||
|
|
||||||
if done is not None:
|
|
||||||
self.done = done
|
|
||||||
elif self.success:
|
|
||||||
self.done = True
|
|
||||||
else:
|
|
||||||
self.done = not alternate
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f'{self.__class__.__name__}({self.action!r}, success={self.success}, done={self.done}, alternate={self.alternate!r})'
|
|
||||||
|
|
||||||
class Action:
|
|
||||||
'''An action that an Entity should perform.'''
|
|
||||||
|
|
||||||
def __init__(self, actor: Optional[Actor]):
|
|
||||||
self.actor = actor
|
|
||||||
|
|
||||||
def perform(self, engine: 'Engine') -> ActionResult:
|
|
||||||
'''Perform this action.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
engine : Engine
|
|
||||||
The game engine
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
ActionResult
|
|
||||||
A result object reflecting how the action was handled, and what follow-up actions, if any, are needed to
|
|
||||||
complete the action.
|
|
||||||
'''
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def failure(self) -> ActionResult:
|
|
||||||
'''Create an ActionResult indicating failure with no follow-up'''
|
|
||||||
return ActionResult(self, success=False)
|
|
||||||
|
|
||||||
def success(self) -> ActionResult:
|
|
||||||
'''Create an ActionResult indicating success with no follow-up'''
|
|
||||||
return ActionResult(self, success=True)
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f'{self.__class__.__name__} for {self.actor!s}'
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f'{self.__class__.__name__}({self.actor!r})'
|
|
||||||
|
|
||||||
class ExitAction(Action):
|
class ExitAction(Action):
|
||||||
'''Exit the game.'''
|
'''Exit the game.'''
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(None)
|
||||||
|
|
||||||
def perform(self, engine: 'Engine') -> ActionResult:
|
def perform(self, engine: 'Engine') -> ActionResult:
|
||||||
raise SystemExit()
|
raise SystemExit()
|
||||||
|
|
47
erynrl/actions/result.py
Normal file
47
erynrl/actions/result.py
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Optional
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .action import Action
|
||||||
|
|
||||||
|
class ActionResult:
|
||||||
|
'''The result of an Action.
|
||||||
|
|
||||||
|
`Action.perform()` returns an instance of this class to inform the caller of the result
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
action : Action
|
||||||
|
The Action that was performed
|
||||||
|
success : bool, optional
|
||||||
|
True if the action succeeded
|
||||||
|
done : bool, optional
|
||||||
|
True if the action is complete, and no follow-up action is needed
|
||||||
|
alternate : Action, optional
|
||||||
|
An alternate action to perform if this action failed
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, action: 'Action', *,
|
||||||
|
success: Optional[bool] = None,
|
||||||
|
done: Optional[bool] = None,
|
||||||
|
alternate: Optional['Action'] = None):
|
||||||
|
self.action = action
|
||||||
|
self.alternate = alternate
|
||||||
|
|
||||||
|
if success is not None:
|
||||||
|
self.success = success
|
||||||
|
elif alternate:
|
||||||
|
self.success = False
|
||||||
|
else:
|
||||||
|
self.success = True
|
||||||
|
|
||||||
|
if done is not None:
|
||||||
|
self.done = done
|
||||||
|
elif self.success:
|
||||||
|
self.done = True
|
||||||
|
else:
|
||||||
|
self.done = not alternate
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'{self.__class__.__name__}({self.action!r}, success={self.success}, done={self.done}, alternate={self.alternate!r})'
|
|
@ -7,7 +7,8 @@ import numpy as np
|
||||||
import tcod
|
import tcod
|
||||||
|
|
||||||
from . import log
|
from . import log
|
||||||
from .actions import Action, BumpAction, WaitAction
|
from .actions import Action
|
||||||
|
from .actions.game import BumpAction, WaitAction
|
||||||
from .components import Component
|
from .components import Component
|
||||||
from .geometry import Direction, Point
|
from .geometry import Direction, Point
|
||||||
from .object import Entity
|
from .object import Entity
|
||||||
|
|
|
@ -7,7 +7,8 @@ from typing import Optional, TYPE_CHECKING
|
||||||
import tcod
|
import tcod
|
||||||
|
|
||||||
from . import log
|
from . import log
|
||||||
from .actions import Action, ExitAction, RegenerateRoomsAction, BumpAction, WaitAction
|
from .actions.action import Action
|
||||||
|
from .actions.game import ExitAction, RegenerateRoomsAction, BumpAction, WaitAction
|
||||||
from .geometry import Direction, Point
|
from .geometry import Direction, Point
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
@ -46,7 +47,7 @@ class EventHandler(tcod.event.EventDispatch[Action]):
|
||||||
self.engine.process_input_action(action)
|
self.engine.process_input_action(action)
|
||||||
|
|
||||||
def ev_quit(self, event: tcod.event.Quit) -> Optional[Action]:
|
def ev_quit(self, event: tcod.event.Quit) -> Optional[Action]:
|
||||||
return ExitAction(self.engine.hero)
|
return ExitAction()
|
||||||
|
|
||||||
class MainGameEventHandler(EventHandler):
|
class MainGameEventHandler(EventHandler):
|
||||||
'''
|
'''
|
||||||
|
@ -80,7 +81,7 @@ class MainGameEventHandler(EventHandler):
|
||||||
case tcod.event.KeySym.y:
|
case tcod.event.KeySym.y:
|
||||||
action = BumpAction(hero, Direction.NorthWest)
|
action = BumpAction(hero, Direction.NorthWest)
|
||||||
case tcod.event.KeySym.ESCAPE:
|
case tcod.event.KeySym.ESCAPE:
|
||||||
action = ExitAction(hero)
|
action = ExitAction()
|
||||||
case tcod.event.KeySym.SPACE:
|
case tcod.event.KeySym.SPACE:
|
||||||
action = RegenerateRoomsAction(hero)
|
action = RegenerateRoomsAction(hero)
|
||||||
case tcod.event.KeySym.PERIOD:
|
case tcod.event.KeySym.PERIOD:
|
||||||
|
@ -100,11 +101,9 @@ class GameOverEventHandler(EventHandler):
|
||||||
def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
|
def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
|
||||||
action: Optional[Action] = None
|
action: Optional[Action] = None
|
||||||
|
|
||||||
hero = self.engine.hero
|
|
||||||
|
|
||||||
sym = event.sym
|
sym = event.sym
|
||||||
match sym:
|
match sym:
|
||||||
case tcod.event.KeySym.ESCAPE:
|
case tcod.event.KeySym.ESCAPE:
|
||||||
action = ExitAction(hero)
|
action = ExitAction()
|
||||||
|
|
||||||
return action
|
return action
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue