fixes from part 6

This commit is contained in:
Tyrel Souza 2022-01-02 12:50:33 -05:00
parent ea986af048
commit 6e02cfcf13
8 changed files with 139 additions and 79 deletions

View File

@ -1,5 +1,5 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from typing import Optional, Tuple, TYPE_CHECKING
if TYPE_CHECKING:
from engine import Engine
@ -7,12 +7,20 @@ if TYPE_CHECKING:
class Action:
def perform(self, engine: Engine, entity: Entity) -> None:
def __init__(self, entity: Entity) -> None:
super().__init__()
self.entity = entity
@property
def engine(self) -> Engine:
return self.entity.gamemap.engine
def perform(self) -> None:
"""Perform this action with the objects needed to determine its scope.
`engine` is the scope this action is being performed in.
`self.engine` is the scope this action is being performed in.
`entity` is the object performing the action.
`self.entity` is the object performing the action.
This method must be overridden by Action subclasses.
"""
@ -20,48 +28,50 @@ class Action:
class EscapeAction(Action):
def perform(self, engine: Engine, entity: Entity) -> None:
def perform(self) -> None:
raise SystemExit()
class ActionWithDirection(Action):
def __init__(self, dx: int, dy: int):
super().__init__()
def __init__(self, entity: Entity, dx: int, dy: int):
super().__init__(entity)
self.dx = dx
self.dy = dy
def perform(self, engine: Engine, entity: Entity) -> None:
@property
def dest_xy(self) -> Tuple[int,int]:
return self.entity.x + self.dx, self.entity.y + self.dy
@property
def blocking_entity(self) -> Optional[Entity]:
return self.engine.game_map.get_blocking_entity_at_location(*self.dest_xy)
def perform(self) -> None:
raise NotImplementedError()
class MeleeAction(ActionWithDirection):
def perform(self, engine: Engine, entity: Entity) -> None:
dest_x = entity.x + self.dx
dest_y = entity.y + self.dy
target = engine.game_map.get_blocking_entity_at_location(dest_x, dest_y)
def perform(self) -> None:
target = self.blocking_entity
if not target:
return # no entity to blockj
print(f"You kick {target.name}, much to its annoyance")
class BumpAction(ActionWithDirection):
def perform(self, engine: Engine, entity: Entity) -> None:
dest_x = entity.x + self.dx
dest_y = entity.y + self.dy
if engine.game_map.get_blocking_entity_at_location(dest_x, dest_y):
return MeleeAction(self.dx, self.dy).perform(engine, entity)
else:
return MovementAction(self.dx, self.dy).perform(engine, entity)
class MovementAction(ActionWithDirection):
def perform(self, engine: Engine, entity: Entity) -> None:
dest_x = entity.x + self.dx
dest_y = entity.y + self.dy
def perform(self) -> None:
dest_x, dest_y = self.dest_xy
if not engine.game_map.in_bounds(dest_x, dest_y):
if not self.engine.game_map.in_bounds(dest_x, dest_y):
return # OOB
if not engine.game_map.tiles["walkable"][dest_x, dest_y]:
if not self.engine.game_map.tiles["walkable"][dest_x, dest_y]:
return # can't walk
if engine.game_map.get_blocking_entity_at_location(dest_x, dest_y):
if self.engine.game_map.get_blocking_entity_at_location(dest_x, dest_y):
return # Blocked
entity.move(self.dx, self.dy)
self.entity.move(self.dx, self.dy)
class BumpAction(ActionWithDirection):
def perform(self) -> None:
if self.blocking_entity:
return MeleeAction(self.entity, self.dx, self.dy).perform()
else:
return MovementAction(self.entity, self.dx, self.dy).perform()

View File

@ -1,34 +1,28 @@
from typing import Iterable, Any
from __future__ import annotations
from typing import TYPE_CHECKING
from tcod.context import Context
from tcod.console import Console
from tcod.map import compute_fov
from entity import Entity
from game_map import GameMap
from input_handlers import EventHandler
if TYPE_CHECKING:
from entity import Entity
from game_map import GameMap
class Engine:
def __init__(self, event_handler: EventHandler, game_map: GameMap, player: Entity):
self.event_handler = event_handler
game_map: GameMap
def __init__(self, player: Entity):
self.event_handler: EventHandler = EventHandler(self)
self.player = player
self.game_map = game_map
self.update_fov()
def handle_enemy_turns(self) -> None:
for entity in self.game_map.entities - {self.player}:
print(f'the {entity.name} wonders when it will move')
def handle_events(self, events: Iterable[Any]) -> None:
for event in events:
action = self.event_handler.dispatch(event)
if action is None:
continue
action.perform(self, self.player)
self.handle_enemy_turns()
self.update_fov()
def update_fov(self) -> None:
self.game_map.visible[:] = compute_fov(
self.game_map.tiles["transparent"],

View File

@ -1,7 +1,7 @@
from __future__ import annotations
import copy
from typing import Tuple, TypeVar, TYPE_CHECKING
from typing import Tuple, TypeVar, TYPE_CHECKING, Optional
if TYPE_CHECKING:
from game_map import GameMap
@ -14,7 +14,10 @@ class Entity:
A generic object to represent players, enemies, items, etc.
"""
gamemap: GameMap
def __init__(self,
gamemap: Optional[GameMap] = None,
x: int = 0,
y: int = 0,
char: str = "?",
@ -28,15 +31,28 @@ class Entity:
self.color = color
self.name = name
self.blocks_movement = blocks_movement
if gamemap:
self.gamemap = gamemap
gamemap.entities.add(self)
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
clone.gamemap = gamemap
gamemap.entities.add(clone)
return clone
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)
def move(self, dx: int, dy: int) -> None:
self.x += dx
self.y += dy

View File

@ -7,21 +7,38 @@ from tcod.console import Console
import tile_types
if TYPE_CHECKING:
from engine import Engine
from entity import Entity
class GameMap:
def __init__(self, width: int, height: int, entities: Iterable[Entity] = ()):
def __init__(self,
engine: Engine,
width: int,
height: int,
entities: Iterable[Entity] = ()
):
self.engine = engine
self.width, self.height = width, height
self.entities = set(entities)
self.tiles = np.full((width, height), fill_value=tile_types.wall, order="F")
self.visible = np.full((width, height), fill_value=False, order="F")
self.explored = np.full((width, height), fill_value=False, order="F")
self.visible = np.full(
(width, height), fill_value=False, order="F"
) # Tiles the player can currently see
self.explored = np.full(
(width, height), fill_value=False, order="F"
) # Tiles the player has seen before
def get_blocking_entity_at_location(self, location_x: int, location_y: int) -> Optiona9[Entity]:
def get_blocking_entity_at_location(
self, location_x: int, location_y: int
) -> Optional[Entity]:
for entity in self.entities:
if entity.blocks_movement and entity.x == location_x and entity.y == location_y:
if (
entity.blocks_movement
and entity.x == location_x
and entity.y == location_y
):
return entity
return None

View File

@ -1,11 +1,28 @@
from typing import Optional
from __future__ import annotations
from typing import Optional, TYPE_CHECKING
import tcod.event
from actions import Action, EscapeAction, BumpAction
if TYPE_CHECKING:
from engine import Engine
class EventHandler(tcod.event.EventDispatch[Action]):
def __init__(self, engine: Engine):
self.engine = engine
def handle_events(self) -> None:
for event in tcod.event.wait():
action = self.dispatch(event)
if action is None:
continue
action.perform()
self.engine.handle_enemy_turns()
self.engine.update_fov()
def ev_quit(self, event: tcod.event.Quit) -> Optional[Action]:
raise SystemExit()
@ -13,17 +30,18 @@ class EventHandler(tcod.event.EventDispatch[Action]):
action: Optional[Action] = None
key = event.sym
player = self.engine.player
if key == tcod.event.K_UP:
action = BumpAction(dx=0, dy=-1)
action = BumpAction(player, dx=0, dy=-1)
elif key == tcod.event.K_DOWN:
action = BumpAction(dx=0, dy=1)
action = BumpAction(player, dx=0, dy=1)
elif key == tcod.event.K_LEFT:
action = BumpAction(dx=-1, dy=0)
action = BumpAction(player, dx=-1, dy=0)
elif key == tcod.event.K_RIGHT:
action = BumpAction(dx=1, dy=0)
action = BumpAction(player, dx=1, dy=0)
elif key == tcod.event.K_ESCAPE:
action = EscapeAction()
action = EscapeAction(player)
return action

12
main.py
View File

@ -25,21 +25,20 @@ def main():
"dejavu10x10_gs_tc.png", 32, 8, tcod.tileset.CHARMAP_TCOD
)
event_handler = EventHandler()
player = copy.deepcopy(entity_factories.player)
engine = Engine(player=player)
game_map = generate_dungeon(
engine.game_map = generate_dungeon(
max_rooms=max_rooms,
room_min_size=room_min_size,
room_max_size=room_max_size,
map_width=map_width,
map_height=map_height,
max_monsters_per_room=max_monsters_per_room,
player=player,
engine=engine,
)
engine.update_fov()
engine = Engine(event_handler=event_handler, game_map=game_map, player=player)
with tcod.context.new_terminal(
screen_width,
@ -51,8 +50,7 @@ def main():
root_console = tcod.Console(screen_width, screen_height, order="F")
while True:
engine.render(console=root_console, context=context)
events = tcod.event.wait()
engine.handle_events(events)
engine.event_handler.handle_events()
if __name__ == "__main__":

View File

@ -10,7 +10,7 @@ import entity_factories
from game_map import GameMap
if TYPE_CHECKING:
from entity import Entity
from engine import Engine
class RectangularRoom:
@ -76,9 +76,10 @@ def generate_dungeon(
map_width: int,
map_height: int,
max_monsters_per_room: int,
player: Entity,
engine: Engine,
) -> GameMap:
dungeon = GameMap(map_width, map_height, entities=[player])
player = engine.player
dungeon = GameMap(engine, map_width, map_height, entities=[player])
rooms: List[RectangularRoom] = []
for room in range(max_rooms):
@ -96,7 +97,7 @@ def generate_dungeon(
if len(rooms) == 0:
# first room
player.x, player.y = new_room.center
player.place(*new_room.center, dungeon)
else:
for x, y in tunnel_between(rooms[-1].center, new_room.center):
dungeon.tiles[x, y] = tile_types.floor

28
tags
View File

@ -10369,10 +10369,12 @@ __index__ venv/lib/python3.10/site-packages/numpy/random/tests/test_random.py /^
__index__ venv/lib/python3.10/site-packages/numpy/typing/tests/data/pass/array_constructors.py /^ def __index__(self) -> int:$/;" m class:Index typeref:typename:int
__index__ venv/lib/python3.10/site-packages/numpy/typing/tests/data/pass/scalars.py /^ def __index__(self) -> int:$/;" m class:D typeref:typename:int
__index__ venv/lib/python3.10/site-packages/typing_extensions.py /^ def __index__(self) -> int:$/;" m class:SupportsIndex typeref:typename:int
__init__ actions.py /^ def __init__(self, dx: int, dy: int):$/;" m class:ActionWithDirection
__init__ engine.py /^ def __init__(self, event_handler: EventHandler, game_map: GameMap, player: Entity):$/;" m class:Engine
__init__ actions.py /^ def __init__(self, entity: Entity) -> None:$/;" m class:Action typeref:typename:None
__init__ actions.py /^ def __init__(self, entity: Entity, dx: int, dy: int):$/;" m class:ActionWithDirection
__init__ engine.py /^ def __init__(self, player: Entity):$/;" m class:Engine
__init__ entity.py /^ def __init__(self,$/;" m class:Entity
__init__ game_map.py /^ def __init__(self, width: int, height: int, entities: Iterable[Entity] = ()):$/;" m class:GameMap
__init__ game_map.py /^ def __init__(self,$/;" m class:GameMap
__init__ input_handlers.py /^ def __init__(self, engine: Engine):$/;" m class:EventHandler
__init__ procgen.py /^ def __init__(self, x: int, y: int, width: int, height: int):$/;" m class:RectangularRoom
__init__ venv/lib/python3.10/site-packages/black/handle_ipynb_magics.py /^ def __init__(self) -> None:$/;" m class:MagicFinder typeref:typename:None
__init__ venv/lib/python3.10/site-packages/black/handle_ipynb_magics.py /^ def __init__(self, cell_magic: Optional[CellMagic] = None) -> None:$/;" m class:CellMagicFinder typeref:typename:None
@ -17991,6 +17993,7 @@ blit_2x venv/lib/python3.10/site-packages/tcod/image.py /^ def blit_2x($/;" m
blit_rect venv/lib/python3.10/site-packages/tcod/image.py /^ def blit_rect($/;" m class:Image typeref:typename:None
block venv/lib/python3.10/site-packages/numpy/core/shape_base.py /^def block(arrays):$/;" f
block venv/lib/python3.10/site-packages/numpy/core/tests/test_shape_base.py /^ def block(self, request):$/;" m class:TestBlock
blocking_entity actions.py /^ def blocking_entity(self) -> Optional[Entity]:$/;" m class:ActionWithDirection typeref:typename:Optional[Entity]
blocksize venv/lib/python3.10/site-packages/pip/_vendor/distlib/_backport/tarfile.py /^ blocksize = 1024$/;" v class:ExFileObject
blocksize venv/lib/python3.10/site-packages/pip/_vendor/distlib/_backport/tarfile.py /^ blocksize = 16 * 1024$/;" v class:_BZ2Proxy
bltn_open venv/lib/python3.10/site-packages/pip/_vendor/distlib/_backport/tarfile.py /^bltn_open = open$/;" v
@ -20233,6 +20236,7 @@ description venv/lib/python3.10/site-packages/setuptools/command/upload_docs.py
description_of venv/lib/python3.10/site-packages/pip/_vendor/chardet/cli/chardetect.py /^def description_of(lines, name='stdin'):$/;" f
descriptors venv/lib/python3.10/site-packages/numpy/core/include/numpy/experimental_dtype_api.h /^ PyArray_Descr **descriptors;$/;" m struct:__anoncd93f9d90408 typeref:typename:PyArray_Descr **
dest_path venv/lib/python3.10/site-packages/pip/_internal/operations/install/wheel.py /^ dest_path = None # type: str$/;" v class:File
dest_xy actions.py /^ def dest_xy(self) -> Tuple[int,int]:$/;" m class:ActionWithDirection typeref:typename:Tuple[int,int]
det venv/lib/python3.10/site-packages/numpy/array_api/linalg.py /^def det(x: Array, \/) -> Array:$/;" f typeref:typename:Array
det venv/lib/python3.10/site-packages/numpy/dual.py /^det = linpkg.det$/;" v
det venv/lib/python3.10/site-packages/numpy/linalg/linalg.py /^def det(a):$/;" f
@ -20854,6 +20858,7 @@ endpoint venv/lib/python3.10/site-packages/numpy/random/tests/test_generator_mt1
endprogs venv/lib/python3.10/site-packages/blib2to3/pgen2/tokenize.py /^endprogs: Final = {$/;" v typeref:typename:Final
endswith venv/lib/python3.10/site-packages/numpy/core/defchararray.py /^ def endswith(self, suffix, start=0, end=None):$/;" m class:chararray
endswith venv/lib/python3.10/site-packages/numpy/core/defchararray.py /^def endswith(a, suffix, start=0, end=None):$/;" f
engine actions.py /^ def engine(self) -> Engine:$/;" m class:Action typeref:typename:Engine
english_capitalize venv/lib/python3.10/site-packages/numpy/core/_string_helpers.py /^def english_capitalize(s):$/;" f
english_lower venv/lib/python3.10/site-packages/numpy/core/_string_helpers.py /^def english_lower(s):$/;" f
english_upper venv/lib/python3.10/site-packages/numpy/core/_string_helpers.py /^def english_upper(s):$/;" f
@ -22352,7 +22357,7 @@ get_binary_stdin venv/lib/python3.10/site-packages/click/_compat.py /^def get_bi
get_binary_stdout venv/lib/python3.10/site-packages/click/_compat.py /^def get_binary_stdout() -> t.BinaryIO:$/;" f typeref:typename:t.BinaryIO
get_binary_stream venv/lib/python3.10/site-packages/click/__init__.py /^from .utils import get_binary_stream as get_binary_stream$/;" x nameref:unknown:get_binary_stream
get_binary_stream venv/lib/python3.10/site-packages/click/utils.py /^def get_binary_stream(name: "te.Literal['stdin', 'stdout', 'stderr']") -> t.BinaryIO:$/;" f typeref:typename:t.BinaryIO
get_blocking_entity_at_location game_map.py /^ def get_blocking_entity_at_location(self, location_x: int, location_y: int) -> Optiona9[Enti/;" m class:GameMap typeref:typename:Optiona9[Entity]
get_blocking_entity_at_location game_map.py /^ def get_blocking_entity_at_location($/;" m class:GameMap typeref:typename:Optional[Entity]
get_buffer venv/lib/python3.10/site-packages/click/_winconsole.py /^ def get_buffer(obj, writable=False):$/;" f
get_buffer venv/lib/python3.10/site-packages/click/_winconsole.py /^ get_buffer = None$/;" v
get_build_architecture venv/lib/python3.10/site-packages/numpy/distutils/misc_util.py /^def get_build_architecture():$/;" f
@ -23381,7 +23386,7 @@ handle_PermissionError venv/lib/python3.10/site-packages/black_primer/lib.py /^d
handle_display_options venv/lib/python3.10/site-packages/setuptools/_distutils/dist.py /^ def handle_display_options(self, option_order):$/;" m class:Distribution
handle_display_options venv/lib/python3.10/site-packages/setuptools/dist.py /^ def handle_display_options(self, option_order):$/;" m class:Distribution
handle_enemy_turns engine.py /^ def handle_enemy_turns(self) -> None:$/;" m class:Engine typeref:typename:None
handle_events engine.py /^ def handle_events(self, events: Iterable[Any]) -> None:$/;" m class:Engine typeref:typename:None
handle_events input_handlers.py /^ def handle_events(self) -> None:$/;" m class:EventHandler typeref:typename:None
handle_extra_path venv/lib/python3.10/site-packages/setuptools/_distutils/command/install.py /^ def handle_extra_path(self):$/;" m class:install
handle_extra_path venv/lib/python3.10/site-packages/setuptools/command/install.py /^ def handle_extra_path(self):$/;" m class:install
handle_line venv/lib/python3.10/site-packages/pip/_internal/req/req_file.py /^def handle_line($/;" f typeref:typename:Optional[ParsedRequirement]
@ -28063,12 +28068,12 @@ pending_deprecate venv/lib/python3.10/site-packages/tcod/_internal.py /^def pend
percent venv/lib/python3.10/site-packages/pip/_vendor/progress/__init__.py /^ def percent(self):$/;" m class:Progress
percentage venv/lib/python3.10/site-packages/pip/_vendor/distlib/util.py /^ def percentage(self):$/;" m class:Progress
percentile venv/lib/python3.10/site-packages/numpy/lib/function_base.py /^def percentile(a,$/;" f
perform actions.py /^ def perform(self, engine: Engine, entity: Entity) -> None:$/;" m class:Action typeref:typename:None
perform actions.py /^ def perform(self, engine: Engine, entity: Entity) -> None:$/;" m class:ActionWithDirection typeref:typename:None
perform actions.py /^ def perform(self, engine: Engine, entity: Entity) -> None:$/;" m class:BumpAction typeref:typename:None
perform actions.py /^ def perform(self, engine: Engine, entity: Entity) -> None:$/;" m class:EscapeAction typeref:typename:None
perform actions.py /^ def perform(self, engine: Engine, entity: Entity) -> None:$/;" m class:MeleeAction typeref:typename:None
perform actions.py /^ def perform(self, engine: Engine, entity: Entity) -> None:$/;" m class:MovementAction typeref:typename:None
perform actions.py /^ def perform(self) -> None:$/;" m class:Action typeref:typename:None
perform actions.py /^ def perform(self) -> None:$/;" m class:ActionWithDirection typeref:typename:None
perform actions.py /^ def perform(self) -> None:$/;" m class:BumpAction typeref:typename:None
perform actions.py /^ def perform(self) -> None:$/;" m class:EscapeAction typeref:typename:None
perform actions.py /^ def perform(self) -> None:$/;" m class:MeleeAction typeref:typename:None
perform actions.py /^ def perform(self) -> None:$/;" m class:MovementAction typeref:typename:None
perm venv/lib/python3.10/site-packages/numpy/core/include/numpy/ndarraytypes.h /^ npy_intp perm, stride;$/;" m struct:__anonbeb738b31808 typeref:typename:npy_intp
permutation_index venv/lib/python3.10/site-packages/setuptools/_vendor/more_itertools/more.py /^def permutation_index(element, iterable):$/;" f
permute_dims venv/lib/python3.10/site-packages/numpy/array_api/_manipulation_functions.py /^def permute_dims(x: Array, \/, axes: Tuple[int, ...]) -> Array:$/;" f typeref:typename:Array
@ -28134,6 +28139,7 @@ pkg_name venv/lib/python3.10/site-packages/numpy/distutils/npy_pkg_config.py /^
pkg_resources_distribution_for_wheel venv/lib/python3.10/site-packages/pip/_internal/utils/wheel.py /^def pkg_resources_distribution_for_wheel(wheel_zip, name, location):$/;" f
pkg_to_filename venv/lib/python3.10/site-packages/numpy/distutils/npy_pkg_config.py /^def pkg_to_filename(pkg_name):$/;" f
pkgname venv/lib/python3.10/site-packages/numpy/core/lib/npy-pkg-config/npymath.ini /^pkgname=numpy.core$/;" k section:variables
place entity.py /^ def place(self, x: int, y: int, gamemap: Optional[GameMap] = None) -> None:$/;" m class:Entity typeref:typename:None
place venv/lib/python3.10/site-packages/numpy/lib/function_base.py /^def place(arr, mask, vals):$/;" f
place_entities procgen.py /^def place_entities($/;" f typeref:typename:None
plainrep venv/lib/python3.10/site-packages/numpy/distutils/conv_template.py /^plainrep = re.compile(r"([^*]+)\\*(\\d+)")$/;" v