1
0

Reformat with black

This commit is contained in:
Timothy Warren 2022-02-08 10:00:28 -05:00
parent 142950e474
commit 8ceb5f0e5d
16 changed files with 171 additions and 230 deletions

View File

@ -61,10 +61,7 @@ class PickupAction(Action):
class ItemAction(Action): class ItemAction(Action):
def __init__( def __init__(
self, self, entity: Actor, item: Item, target_xy: Optional[Tuple[int, int]] = None
entity: Actor,
item: Item,
target_xy: Optional[Tuple[int, int]] = None
): ):
super().__init__(entity) super().__init__(entity)
self.item = item self.item = item
@ -101,8 +98,7 @@ class TakeStairsAction(Action):
if (self.entity.x, self.entity.y) == self.engine.game_map.downstairs_location: if (self.entity.x, self.entity.y) == self.engine.game_map.downstairs_location:
self.engine.game_world.generate_floor() self.engine.game_world.generate_floor()
self.engine.message_log.add_message( self.engine.message_log.add_message(
"You descent the staircase.", "You descent the staircase.", color.descend
color.descend
) )
else: else:
raise exceptions.Impossible("There are no stairs here.") raise exceptions.Impossible("There are no stairs here.")

View File

@ -13,7 +13,6 @@ if TYPE_CHECKING:
class BaseAI(Action): class BaseAI(Action):
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.
@ -52,10 +51,7 @@ class ConfusedEnemy(BaseAI):
""" """
def __init__( def __init__(
self, self, entity: Actor, previous_ai: Optional[BaseAI], turns_remaining: int
entity: Actor,
previous_ai: Optional[BaseAI],
turns_remaining: int
): ):
super().__init__(entity) super().__init__(entity)
@ -65,7 +61,9 @@ class ConfusedEnemy(BaseAI):
def perform(self) -> None: def perform(self) -> None:
# Rever the AI back to the original state if the effect has run its course. # Rever the AI back to the original state if the effect has run its course.
if self.turns_remaining <= 0: if self.turns_remaining <= 0:
self.engine.message_log.add_message(f"The {self.entity.name} is no longer confused.") self.engine.message_log.add_message(
f"The {self.entity.name} is no longer confused."
)
self.entity.ai = self.previous_ai self.entity.ai = self.previous_ai
else: else:
# Pick a random direction # Pick a random direction

View File

@ -11,7 +11,7 @@ from exceptions import Impossible
from input_handlers import ( from input_handlers import (
ActionOrHandler, ActionOrHandler,
AreaRangedAttackHandler, AreaRangedAttackHandler,
SingleRangedAttackHandler SingleRangedAttackHandler,
) )
if TYPE_CHECKING: if TYPE_CHECKING:
@ -46,8 +46,7 @@ class ConfusionConsumable(Consumable):
def get_action(self, consumer: Actor) -> SingleRangedAttackHandler: def get_action(self, consumer: Actor) -> SingleRangedAttackHandler:
self.engine.message_log.add_message( self.engine.message_log.add_message(
"Select a target location.", "Select a target location.", color.needs_target
color.needs_target
) )
return SingleRangedAttackHandler( return SingleRangedAttackHandler(
@ -90,7 +89,7 @@ class HealingConsumable(Consumable):
if amount_recovered > 0: if amount_recovered > 0:
self.engine.message_log.add_message( self.engine.message_log.add_message(
f"You consume the {self.parent.name}, and recover {amount_recovered} HP!", f"You consume the {self.parent.name}, and recover {amount_recovered} HP!",
color.health_recovered color.health_recovered,
) )
self.consume() self.consume()
else: else:
@ -104,8 +103,7 @@ class FireballDamageConsumable(Consumable):
def get_action(self, consumer: Actor) -> AreaRangedAttackHandler: def get_action(self, consumer: Actor) -> AreaRangedAttackHandler:
self.engine.message_log.add_message( self.engine.message_log.add_message(
"Select a target location.", "Select a target location.", color.needs_target
color.needs_target
) )
return AreaRangedAttackHandler( return AreaRangedAttackHandler(

View File

@ -13,10 +13,10 @@ class Equippable(BaseComponent):
parent: Item parent: Item
def __init__( def __init__(
self, self,
equipment_type: EquipmentType, equipment_type: EquipmentType,
power_bonus: int = 0, power_bonus: int = 0,
defense_bonus: int = 0, defense_bonus: int = 0,
): ):
self.equipment_type = equipment_type self.equipment_type = equipment_type

View File

@ -12,12 +12,12 @@ class Level(BaseComponent):
parent: Actor parent: Actor
def __init__( def __init__(
self, self,
current_level: int = 1, current_level: int = 1,
current_xp: int = 0, current_xp: int = 0,
level_up_base: int = 0, level_up_base: int = 0,
level_up_factor: int = 150, level_up_factor: int = 150,
xp_given: int = 0 xp_given: int = 0,
): ):
self.current_level = current_level self.current_level = current_level
self.current_xp = current_xp self.current_xp = current_xp

View File

@ -57,12 +57,12 @@ class Engine:
) )
render_functions.render_dungeon_level( render_functions.render_dungeon_level(
console, console, dungeon_level=self.game_world.current_floor, location=(0, 47)
dungeon_level=self.game_world.current_floor,
location=(0, 47)
) )
render_functions.render_names_at_mouse_location(console, x=21, y=44, engine=self) render_functions.render_names_at_mouse_location(
console, x=21, y=44, engine=self
)
def save_as(self, filename: str) -> None: def save_as(self, filename: str) -> None:
"""Save this Engine instance as a compressed file.""" """Save this Engine instance as a compressed file."""

View File

@ -26,15 +26,15 @@ class Entity:
parent: Union[GameMap, Inventory] parent: Union[GameMap, Inventory]
def __init__( def __init__(
self, self,
parent: Optional[GameMap] = None, parent: Optional[GameMap] = None,
x: int = 0, x: int = 0,
y: int = 0, y: int = 0,
char: str = "?", char: str = "?",
color: Tuple[int, int, int] = (255, 255, 255), color: Tuple[int, int, int] = (255, 255, 255),
name: str = "<Unnamed>", name: str = "<Unnamed>",
blocks_movement: bool = False, blocks_movement: bool = False,
render_order: RenderOrder = RenderOrder.CORPSE, render_order: RenderOrder = RenderOrder.CORPSE,
): ):
self.x = x self.x = x
self.y = y self.y = y
@ -87,17 +87,17 @@ class Entity:
class Actor(Entity): class Actor(Entity):
def __init__( def __init__(
self, self,
*, *,
x: int = 0, x: int = 0,
y: int = 0, y: int = 0,
char: str = "?", char: str = "?",
color: Tuple[int, int, int] = (255, 255, 255), color: Tuple[int, int, int] = (255, 255, 255),
name: str = "<Unamed>", name: str = "<Unamed>",
ai_cls: Type[BaseAI], ai_cls: Type[BaseAI],
fighter: Fighter, fighter: Fighter,
inventory: Inventory, inventory: Inventory,
level: Level level: Level,
): ):
super().__init__( super().__init__(
x=x, x=x,
@ -128,15 +128,15 @@ class Actor(Entity):
class Item(Entity): class Item(Entity):
def __init__( def __init__(
self, self,
*, *,
x: int = 0, x: int = 0,
y: int = 0, y: int = 0,
char: str = "?", char: str = "?",
color: Tuple[int, int, int] = (255, 255, 255), color: Tuple[int, int, int] = (255, 255, 255),
name: str = "<Unamed>", name: str = "<Unamed>",
consumable: Optional[Consumable] = None, consumable: Optional[Consumable] = None,
equippable: Optional[Equippable] = None, equippable: Optional[Equippable] = None,
): ):
super().__init__( super().__init__(
x=x, x=x,

View File

@ -15,11 +15,7 @@ if TYPE_CHECKING:
class GameMap: class GameMap:
def __init__( def __init__(
self, self, engine: Engine, width: int, height: int, entities: Iterable[Entity] = ()
engine: Engine,
width: int,
height: int,
entities: Iterable[Entity] = ()
): ):
self.engine = engine self.engine = engine
self.width, self.height = width, height self.width, self.height = width, height
@ -27,14 +23,10 @@ class GameMap:
self.tiles = np.full((width, height), fill_value=tile_types.wall, order="F") self.tiles = np.full((width, height), fill_value=tile_types.wall, order="F")
self.visible = np.full( self.visible = np.full(
(width, height), (width, height), fill_value=False, order="F"
fill_value=False,
order="F"
) # Tiles the player can currently see ) # Tiles the player can currently see
self.explored = np.full( self.explored = np.full(
(width, height), (width, height), fill_value=False, order="F"
fill_value=False,
order="F"
) # Tiles the player has seen before ) # Tiles the player has seen before
self.downstairs_location = (0, 0) self.downstairs_location = (0, 0)
@ -57,15 +49,13 @@ class GameMap:
yield from (entity for entity in self.entities if isinstance(entity, Item)) yield from (entity for entity in self.entities if isinstance(entity, Item))
def get_blocking_entity_at_location( def get_blocking_entity_at_location(
self, self, location_x: int, location_y: int
location_x: int,
location_y: int
) -> Optional[Entity]: ) -> Optional[Entity]:
for entity in self.entities: for entity in self.entities:
if ( if (
entity.blocks_movement entity.blocks_movement
and entity.x == location_x and entity.x == location_x
and entity.y == location_y and entity.y == location_y
): ):
return entity return entity
@ -92,7 +82,7 @@ class GameMap:
:param console: :param console:
:return: :return:
""" """
console.tiles_rgb[0: self.width, 0: self.height] = np.select( console.tiles_rgb[0 : self.width, 0 : self.height] = np.select(
condlist=[self.visible, self.explored], condlist=[self.visible, self.explored],
choicelist=[self.tiles["light"], self.tiles["dark"]], choicelist=[self.tiles["light"], self.tiles["dark"]],
default=tile_types.SHROUD, default=tile_types.SHROUD,
@ -106,10 +96,7 @@ class GameMap:
# Only print entities that are in the FOV # Only print entities that are in the FOV
if self.visible[entity.x, entity.y]: if self.visible[entity.x, entity.y]:
console.print( console.print(
x=entity.x, x=entity.x, y=entity.y, string=entity.char, fg=entity.color
y=entity.y,
string=entity.char,
fg=entity.color
) )
@ -119,15 +106,15 @@ class GameWorld:
""" """
def __init__( def __init__(
self, self,
*, *,
engine: Engine, engine: Engine,
map_width: int, map_width: int,
map_height: int, map_height: int,
max_rooms: int, max_rooms: int,
room_min_size: int, room_min_size: int,
room_max_size: int, room_max_size: int,
current_floor: int = 0 current_floor: int = 0,
): ):
self.engine = engine self.engine = engine

View File

@ -7,12 +7,7 @@ from typing import overload, Callable, Optional, Tuple, TYPE_CHECKING, Union
import tcod.event import tcod.event
import actions import actions
from actions import ( from actions import Action, BumpAction, PickupAction, WaitAction
Action,
BumpAction,
PickupAction,
WaitAction
)
import color import color
import exceptions import exceptions
@ -30,7 +25,6 @@ MOVE_KEYS = {
tcod.event.K_END: (-1, 1), tcod.event.K_END: (-1, 1),
tcod.event.K_PAGEUP: (1, -1), tcod.event.K_PAGEUP: (1, -1),
tcod.event.K_PAGEDOWN: (1, 1), tcod.event.K_PAGEDOWN: (1, 1),
# Numpad keys # Numpad keys
tcod.event.K_KP_1: (-1, 1), tcod.event.K_KP_1: (-1, 1),
tcod.event.K_KP_2: (0, 1), tcod.event.K_KP_2: (0, 1),
@ -40,7 +34,6 @@ MOVE_KEYS = {
tcod.event.K_KP_7: (-1, -1), tcod.event.K_KP_7: (-1, -1),
tcod.event.K_KP_8: (0, -1), tcod.event.K_KP_8: (0, -1),
tcod.event.K_KP_9: (1, -1), tcod.event.K_KP_9: (1, -1),
# Vi keys # Vi keys
tcod.event.K_h: (-1, 0), tcod.event.K_h: (-1, 0),
tcod.event.K_j: (0, 1), tcod.event.K_j: (0, 1),
@ -183,7 +176,9 @@ class AskUserEventHandler(EventHandler):
return self.on_exit() return self.on_exit()
def ev_mousebuttondown(self, event: tcod.event.MouseButtonDown) -> Optional[ActionOrHandler]: def ev_mousebuttondown(
self, event: tcod.event.MouseButtonDown
) -> Optional[ActionOrHandler]:
"""By default any mouse click exits this input handler.""" """By default any mouse click exits this input handler."""
return self.on_exit() return self.on_exit()
@ -221,20 +216,12 @@ class CharacterScreenEventHandler(AskUserEventHandler):
bg=(0, 0, 0), bg=(0, 0, 0),
) )
console.print( console.print(x + 1, y + 1, f"Level: {self.engine.player.level.current_level}")
x + 1, console.print(x + 1, y + 2, f"XP: {self.engine.player.level.current_xp}")
y + 1,
f"Level: {self.engine.player.level.current_level}"
)
console.print(
x + 1,
y + 2,
f"XP: {self.engine.player.level.current_xp}"
)
console.print( console.print(
x + 1, x + 1,
y + 3, y + 3,
f"XP for next Level: {self.engine.player.level.experience_to_next_level}" f"XP for next Level: {self.engine.player.level.experience_to_next_level}",
) )
console.print( console.print(
x=x + 1, y=y + 4, string=f"Attack: {self.engine.player.fighter.power}" x=x + 1, y=y + 4, string=f"Attack: {self.engine.player.fighter.power}"
@ -263,7 +250,7 @@ class LevelUpEventHandler(AskUserEventHandler):
title=self.TITLE, title=self.TITLE,
clear=True, clear=True,
fg=(255, 255, 255), fg=(255, 255, 255),
bg=(0, 0, 0) bg=(0, 0, 0),
) )
console.print(x + 1, 1, "Congratulations! You level up!") console.print(x + 1, 1, "Congratulations! You level up!")
@ -272,17 +259,17 @@ class LevelUpEventHandler(AskUserEventHandler):
console.print( console.print(
x=x + 1, x=x + 1,
y=4, y=4,
string=f"a) Constitution (+20 HP, from {self.engine.player.fighter.max_hp})" string=f"a) Constitution (+20 HP, from {self.engine.player.fighter.max_hp})",
) )
console.print( console.print(
x=x + 1, x=x + 1,
y=5, y=5,
string=f"b) Strength (+1 attack, from {self.engine.player.fighter.power})" string=f"b) Strength (+1 attack, from {self.engine.player.fighter.power})",
) )
console.print( console.print(
x=x + 1, x=x + 1,
y=6, y=6,
string=f"c) Agility (+1 defense, from {self.engine.player.fighter.defense})" string=f"c) Agility (+1 defense, from {self.engine.player.fighter.defense})",
) )
def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[ActionOrHandler]: def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[ActionOrHandler]:
@ -304,7 +291,9 @@ class LevelUpEventHandler(AskUserEventHandler):
return super().ev_keydown(event) return super().ev_keydown(event)
def ev_mousebuttondown(self, event: tcod.event.MouseButtonDown) -> Optional[ActionOrHandler]: def ev_mousebuttondown(
self, event: tcod.event.MouseButtonDown
) -> Optional[ActionOrHandler]:
""" """
Don't allow the player to click to exit the menu, like normal Don't allow the player to click to exit the menu, like normal
""" """
@ -443,7 +432,9 @@ class SelectIndexHandler(AskUserEventHandler):
return super().ev_keydown(event) return super().ev_keydown(event)
def ev_mousebuttondown(self, event: tcod.event.MouseButtonDown) -> Optional[ActionOrHandler]: def ev_mousebuttondown(
self, event: tcod.event.MouseButtonDown
) -> Optional[ActionOrHandler]:
"""Left click confirms a selection.""" """Left click confirms a selection."""
if self.engine.game_map.in_bounds(*event.tile): if self.engine.game_map.in_bounds(*event.tile):
if event.button == 1: if event.button == 1:
@ -468,9 +459,9 @@ class SingleRangedAttackHandler(SelectIndexHandler):
"""Handles targeting a single enemy. Only the enemy selected will be affected.""" """Handles targeting a single enemy. Only the enemy selected will be affected."""
def __init__( def __init__(
self, self,
engine: Engine, engine: Engine,
callback: Callable[[Tuple[int, int]], Optional[ActionOrHandler]] callback: Callable[[Tuple[int, int]], Optional[ActionOrHandler]],
): ):
super().__init__(engine) super().__init__(engine)
@ -487,10 +478,10 @@ class AreaRangedAttackHandler(SelectIndexHandler):
""" """
def __init__( def __init__(
self, self,
engine: Engine, engine: Engine,
radius: int, radius: int,
callback: Callable[[Tuple[int, int]], Optional[ActionOrHandler]] callback: Callable[[Tuple[int, int]], Optional[ActionOrHandler]],
): ):
super().__init__(engine) super().__init__(engine)
@ -507,8 +498,8 @@ class AreaRangedAttackHandler(SelectIndexHandler):
console.draw_frame( console.draw_frame(
x=x - self.radius - 1, x=x - self.radius - 1,
y=y - self.radius - 1, y=y - self.radius - 1,
width=self.radius ** 2, width=self.radius**2,
height=self.radius ** 2, height=self.radius**2,
fg=color.red, fg=color.red,
clear=False, clear=False,
) )
@ -527,7 +518,7 @@ class MainGameEventHandler(EventHandler):
player = self.engine.player player = self.engine.player
if key == tcod.event.K_PERIOD and modifier & ( if key == tcod.event.K_PERIOD and modifier & (
tcod.event.KMOD_LSHIFT | tcod.event.KMOD_RSHIFT tcod.event.KMOD_LSHIFT | tcod.event.KMOD_RSHIFT
): ):
return actions.TakeStairsAction(player) return actions.TakeStairsAction(player)
@ -598,12 +589,7 @@ class HistoryViewer(EventHandler):
# Draw a frame with a custom banner title. # Draw a frame with a custom banner title.
log_console.draw_frame(0, 0, log_console.width, log_console.height) log_console.draw_frame(0, 0, log_console.width, log_console.height)
log_console.print_box( log_console.print_box(
0, 0, 0, log_console.width, 1, "┤Message history├", alignment=tcod.CENTER
0,
log_console.width,
1,
"┤Message history├",
alignment=tcod.CENTER
) )
# Render the message log using the cursor parameter. # Render the message log using the cursor parameter.

15
main.py
View File

@ -21,20 +21,17 @@ def main() -> None:
screen_height = 50 screen_height = 50
tileset = tcod.tileset.load_tilesheet( tileset = tcod.tileset.load_tilesheet(
"dejavu10x10_gs_tc.png", "dejavu10x10_gs_tc.png", 32, 8, tcod.tileset.CHARMAP_TCOD
32,
8,
tcod.tileset.CHARMAP_TCOD
) )
handler: input_handlers.BaseEventHandler = setup_game.MainMenu() handler: input_handlers.BaseEventHandler = setup_game.MainMenu()
with tcod.context.new_terminal( with tcod.context.new_terminal(
screen_width, screen_width,
screen_height, screen_height,
tileset=tileset, tileset=tileset,
title="Yet Another Roguelike Tutorial", title="Yet Another Roguelike Tutorial",
vsync=True, vsync=True,
) as context: ) as context:
root_console = tcod.Console(screen_width, screen_height, order="F") root_console = tcod.Console(screen_width, screen_height, order="F")
try: try:

View File

@ -26,11 +26,7 @@ class MessageLog:
self.messages: List[Message] = [] self.messages: List[Message] = []
def add_message( def add_message(
self, self, text: str, fg: Tuple[int, int, int] = color.white, *, stack: bool = True
text: str,
fg: Tuple[int, int, int] = color.white,
*,
stack: bool = True
) -> None: ) -> None:
"""Add a message to this log. """Add a message to this log.
`text` is the message text, `fg` is the text color. `text` is the message text, `fg` is the text color.
@ -43,12 +39,12 @@ class MessageLog:
self.messages.append(Message(text, fg)) self.messages.append(Message(text, fg))
def render( def render(
self, self,
console: tcod.Console, console: tcod.Console,
x: int, x: int,
y: int, y: int,
width: int, width: int,
height: int, height: int,
) -> None: ) -> None:
"""Render this log over the given area. """Render this log over the given area.
`x`, `y`, `width`, `height` is the rectangular region to render onto `x`, `y`, `width`, `height` is the rectangular region to render onto
@ -60,21 +56,17 @@ class MessageLog:
def wrap(string: str, width: int) -> Iterable[str]: def wrap(string: str, width: int) -> Iterable[str]:
"""Return a wrapped text message.""" """Return a wrapped text message."""
for line in string.splitlines(): # Handle newlines in messages. for line in string.splitlines(): # Handle newlines in messages.
yield from textwrap.wrap( yield from textwrap.wrap(line, width, expand_tabs=True)
line,
width,
expand_tabs=True
)
@classmethod @classmethod
def render_messages( def render_messages(
cls, cls,
console: tcod.Console, console: tcod.Console,
x: int, x: int,
y: int, y: int,
width: int, width: int,
height: int, height: int,
messages: Reversible[Message], messages: Reversible[Message],
) -> None: ) -> None:
"""Render the messages provided. """Render the messages provided.
The `messages` are rendered starting at the last message and working The `messages` are rendered starting at the last message and working

View File

@ -40,24 +40,23 @@ enemy_chances: Dict[int, List[Tuple[Entity, int]]] = {
def get_max_value_for_floor( def get_max_value_for_floor(
max_value_by_floor: List[Tuple[int, int]], max_value_by_floor: List[Tuple[int, int]], floor: int
floor: int
) -> int: ) -> int:
current_value = 0 current_value = 0
for floor_minimum, value in max_value_by_floor: for floor_minimum, value in max_value_by_floor:
if floor_minimum > floor: if floor_minimum > floor:
break; break
else: else:
current_value = value; current_value = value
return current_value return current_value
def get_entities_at_random( def get_entities_at_random(
weighted_chances_by_floor: Dict[int, List[Tuple[Entity, int]]], weighted_chances_by_floor: Dict[int, List[Tuple[Entity, int]]],
number_of_entities: int, number_of_entities: int,
floor: int, floor: int,
) -> List[Entity]: ) -> List[Entity]:
entity_weighted_chances = {} entity_weighted_chances = {}
@ -75,9 +74,7 @@ def get_entities_at_random(
entity_weighted_chance_values = list(entity_weighted_chances.values()) entity_weighted_chance_values = list(entity_weighted_chances.values())
chosen_entities = random.choices( chosen_entities = random.choices(
entities, entities, weights=entity_weighted_chance_values, k=number_of_entities
weights=entity_weighted_chance_values,
k=number_of_entities
) )
return chosen_entities return chosen_entities
@ -105,17 +102,17 @@ class RectangularRoom:
def intersects(self, other: RectangularRoom) -> bool: def intersects(self, other: RectangularRoom) -> bool:
"""Return True if this room overlaps with another RectangularRoom.""" """Return True if this room overlaps with another RectangularRoom."""
return ( return (
self.x1 <= other.x2 self.x1 <= other.x2
and self.x2 >= other.x1 and self.x2 >= other.x1
and self.y1 <= other.y2 and self.y1 <= other.y2
and self.y2 >= other.y1 and self.y2 >= other.y1
) )
def place_entities( def place_entities(
room: RectangularRoom, room: RectangularRoom,
dungeon: GameMap, dungeon: GameMap,
floor_number: int, floor_number: int,
) -> None: ) -> None:
number_of_monsters = random.randint( number_of_monsters = random.randint(
0, get_max_value_for_floor(max_monsters_by_floor, floor_number) 0, get_max_value_for_floor(max_monsters_by_floor, floor_number)
@ -125,14 +122,10 @@ def place_entities(
) )
monsters: List[Entity] = get_entities_at_random( monsters: List[Entity] = get_entities_at_random(
enemy_chances, enemy_chances, number_of_monsters, floor_number
number_of_monsters,
floor_number
) )
items: List[Entity] = get_entities_at_random( items: List[Entity] = get_entities_at_random(
item_chances, item_chances, number_of_items, floor_number
number_of_items,
floor_number
) )
for entity in monsters + items: for entity in monsters + items:
@ -143,7 +136,9 @@ def place_entities(
entity.spawn(dungeon, x, y) entity.spawn(dungeon, x, y)
def tunnel_between(start: Tuple[int, int], end: Tuple[int, int]) -> Iterator[Tuple[int, int]]: def tunnel_between(
start: Tuple[int, int], end: Tuple[int, int]
) -> Iterator[Tuple[int, int]]:
"""Return an L-shaped tunnel between these two points.""" """Return an L-shaped tunnel between these two points."""
x1, y1 = start x1, y1 = start
x2, y2 = end x2, y2 = end
@ -163,12 +158,12 @@ def tunnel_between(start: Tuple[int, int], end: Tuple[int, int]) -> Iterator[Tup
def generate_dungeon( def generate_dungeon(
max_rooms: int, max_rooms: int,
room_min_size: int, room_min_size: int,
room_max_size: int, room_max_size: int,
map_width: int, map_width: int,
map_height: int, map_height: int,
engine: Engine, engine: Engine,
) -> GameMap: ) -> GameMap:
"""Generate a new dungeon map.""" """Generate a new dungeon map."""
player = engine.player player = engine.player

View File

@ -22,10 +22,10 @@ def get_names_at_location(x: int, y: int, game_map: GameMap) -> str:
def render_bar( def render_bar(
console: Console, console: Console,
current_value: int, current_value: int,
maximum_value: int, maximum_value: int,
total_width: int, total_width: int,
) -> None: ) -> None:
bar_width = int(float(current_value) / maximum_value * total_width) bar_width = int(float(current_value) / maximum_value * total_width)
@ -33,12 +33,7 @@ def render_bar(
if bar_width > 0: if bar_width > 0:
console.draw_rect( console.draw_rect(
x=0, x=0, y=45, width=bar_width, height=1, ch=1, bg=color.bar_filled
y=45,
width=bar_width,
height=1,
ch=1,
bg=color.bar_filled
) )
console.print( console.print(
@ -50,9 +45,7 @@ def render_bar(
def render_dungeon_level( def render_dungeon_level(
console: Console, console: Console, dungeon_level: int, location: Tuple[int, int]
dungeon_level: int,
location: Tuple[int, int]
) -> None: ) -> None:
""" """
Render the level the player is currently on, at the given location. Render the level the player is currently on, at the given location.
@ -63,10 +56,7 @@ def render_dungeon_level(
def render_names_at_mouse_location( def render_names_at_mouse_location(
console: Console, console: Console, x: int, y: int, engine: Engine
x: int,
y: int,
engine: Engine
) -> None: ) -> None:
mouse_x, mouse_y = engine.mouse_location mouse_x, mouse_y = engine.mouse_location

View File

@ -44,8 +44,7 @@ def new_game() -> Engine:
engine.update_fov() engine.update_fov()
engine.message_log.add_message( engine.message_log.add_message(
"Hello and welcome, adventurer, to yet another dungeon!", "Hello and welcome, adventurer, to yet another dungeon!", color.welcome_text
color.welcome_text
) )
return engine return engine
@ -83,11 +82,9 @@ class MainMenu(input_handlers.BaseEventHandler):
) )
menu_width = 24 menu_width = 24
for i, text in enumerate([ for i, text in enumerate(
"[N] Play a new game", ["[N] Play a new game", "[C] Continue last game", "[Q] Quit"]
"[C] Continue last game", ):
"[Q] Quit"
]):
console.print( console.print(
console.width // 2, console.width // 2,
console.height // 2 - 2 + i, console.height // 2 - 2 + i,
@ -98,7 +95,9 @@ class MainMenu(input_handlers.BaseEventHandler):
bg_blend=tcod.BKGND_ALPHA(64), bg_blend=tcod.BKGND_ALPHA(64),
) )
def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[input_handlers.BaseEventHandler]: def ev_keydown(
self, event: tcod.event.KeyDown
) -> Optional[input_handlers.BaseEventHandler]:
if event.sym in (tcod.event.K_q, tcod.event.K_ESCAPE): if event.sym in (tcod.event.K_q, tcod.event.K_ESCAPE):
raise SystemExit() raise SystemExit()
elif event.sym == tcod.event.K_c: elif event.sym == tcod.event.K_c:

View File

@ -7,7 +7,10 @@ graphic_dt = np.dtype(
[ [
("ch", np.int32), # Unicode codepoint. ("ch", np.int32), # Unicode codepoint.
("fg", "3B"), # 3 unsigned bytes, for RGB colors. ("fg", "3B"), # 3 unsigned bytes, for RGB colors.
("bg", "3B",) (
"bg",
"3B",
),
] ]
) )
@ -23,11 +26,11 @@ tile_dt = np.dtype(
def new_tile( def new_tile(
*, # Enforce the use of keywords, so that parameter order doesn't matter *, # Enforce the use of keywords, so that parameter order doesn't matter
walkable: int, walkable: int,
transparent: int, transparent: int,
dark: Tuple[int, Tuple[int, int, int], Tuple[int, int, int]], dark: Tuple[int, Tuple[int, int, int], Tuple[int, int, int]],
light: Tuple[int, Tuple[int, int, int], Tuple[int, int, int]] light: Tuple[int, Tuple[int, int, int], Tuple[int, int, int]]
) -> np.ndarray: ) -> np.ndarray:
"""Helper function for defining individual tile types""" """Helper function for defining individual tile types"""
return np.array((walkable, transparent, dark, light), dtype=tile_dt) return np.array((walkable, transparent, dark, light), dtype=tile_dt)