1
0
python-roguelike/game_map.py

144 lines
4.1 KiB
Python
Raw Normal View History

from __future__ import annotations
2022-01-10 13:21:17 -05:00
from typing import Iterable, Iterator, Optional, TYPE_CHECKING
2022-01-06 13:27:15 -05:00
import numpy as np # type: ignore
2022-01-06 11:41:34 -05:00
from tcod.console import Console
from entity import Actor, Item
2022-01-06 11:41:34 -05:00
import tile_types
if TYPE_CHECKING:
from engine import Engine
from entity import Entity
2022-01-06 13:27:15 -05:00
2022-01-06 11:41:34 -05:00
class GameMap:
def __init__(
2022-02-08 10:00:28 -05:00
self, engine: Engine, width: int, height: int, entities: Iterable[Entity] = ()
):
self.engine = engine
2022-01-06 13:27:15 -05:00
self.width, self.height = width, height
2022-01-07 15:52:53 -05:00
self.entities = set(entities)
2022-01-06 13:27:15 -05:00
self.tiles = np.full((width, height), fill_value=tile_types.wall, order="F")
2022-01-06 11:41:34 -05:00
self.visible = np.full(
2022-02-08 10:00:28 -05:00
(width, height), fill_value=False, order="F"
) # Tiles the player can currently see
self.explored = np.full(
2022-02-08 10:00:28 -05:00
(width, height), fill_value=False, order="F"
) # Tiles the player has seen before
2022-01-07 14:18:47 -05:00
self.downstairs_location = (0, 0)
2022-01-12 13:45:52 -05:00
@property
def gamemap(self) -> GameMap:
return self
2022-01-10 13:21:17 -05:00
@property
def actors(self) -> Iterator[Actor]:
"""Iterate over this map's living actors."""
yield from (
entity
for entity in self.entities
if isinstance(entity, Actor) and entity.is_alive
)
@property
def items(self) -> Iterator[Item]:
yield from (entity for entity in self.entities if isinstance(entity, Item))
def get_blocking_entity_at_location(
2022-02-08 10:00:28 -05:00
self, location_x: int, location_y: int
) -> Optional[Entity]:
2022-01-07 15:52:53 -05:00
for entity in self.entities:
if (
2022-02-08 10:00:28 -05:00
entity.blocks_movement
and entity.x == location_x
and entity.y == location_y
):
2022-01-07 15:52:53 -05:00
return entity
return None
2022-01-10 13:21:17 -05:00
def get_actor_at_location(self, x: int, y: int) -> Optional[Actor]:
for actor in self.actors:
if actor.x == x and actor.y == y:
return actor
return None
2022-01-06 11:41:34 -05:00
def in_bounds(self, x: int, y: int) -> bool:
2022-01-06 13:27:15 -05:00
"""Return True if x and y are inside the bounds of the map."""
2022-01-06 11:41:34 -05:00
return 0 <= x < self.width and 0 <= y < self.height
def render(self, console: Console):
2022-01-07 14:18:47 -05:00
"""
Renders the map.
If a tile is in the "visible" array, then draw it with the "light" colors.
If it isn't, but it's in the "explored" array, then draw it with the "dark" colors.
Otherwise, the default is "SHROUD".
:param console:
:return:
"""
2022-02-08 10:00:28 -05:00
console.tiles_rgb[0 : self.width, 0 : self.height] = np.select(
2022-01-07 14:18:47 -05:00
condlist=[self.visible, self.explored],
choicelist=[self.tiles["light"], self.tiles["dark"]],
default=tile_types.SHROUD,
2022-01-07 14:18:47 -05:00
)
2022-01-10 14:09:31 -05:00
entities_sorted_for_rendering = sorted(
self.entities, key=lambda x: x.render_order.value
)
for entity in entities_sorted_for_rendering:
# Only print entities that are in the FOV
if self.visible[entity.x, entity.y]:
2022-01-10 14:09:31 -05:00
console.print(
2022-02-08 10:00:28 -05:00
x=entity.x, y=entity.y, string=entity.char, fg=entity.color
2022-01-10 14:09:31 -05:00
)
class GameWorld:
"""
Holds the settings for the GameMap, and generates new maps when moving down the stairs.
"""
def __init__(
2022-02-08 10:00:28 -05:00
self,
*,
engine: Engine,
map_width: int,
map_height: int,
max_rooms: int,
room_min_size: int,
room_max_size: int,
current_floor: int = 0,
):
self.engine = engine
self.map_width = map_width
self.map_height = map_height
self.max_rooms = max_rooms
self.room_min_size = room_min_size
self.room_max_size = room_max_size
self.current_floor = current_floor
def generate_floor(self) -> None:
from procgen import generate_dungeon
self.current_floor += 1
self.engine.game_map = generate_dungeon(
max_rooms=self.max_rooms,
room_min_size=self.room_min_size,
room_max_size=self.room_max_size,
map_width=self.map_width,
map_height=self.map_height,
engine=self.engine,
)