Beispiel #1
0
def handle_keys(key):
    # if key is None:
    #     if terminal.has_input():
    #         key = terminal.read()

        if key == terminal.TK_H or key == terminal.TK_KP_4 or key == terminal.TK_LEFT:
            return {"move": Point(-1, 0)}
        elif key == terminal.TK_L or key == terminal.TK_KP_6 or key == terminal.TK_RIGHT:
            return {"move": Point(1, 0)}
        elif key == terminal.TK_K or key == terminal.TK_KP_8 or key == terminal.TK_UP:
            return {"move": Point(0, -1)}
        elif key == terminal.TK_J or key == terminal.TK_KP_2 or key == terminal.TK_DOWN:
            return {"move": Point(0, 1)}
        elif key == terminal.TK_Y or key == terminal.TK_KP_7:
            return {"move": Point(-1, -1)}
        elif key == terminal.TK_U or key == terminal.TK_KP_9:
            return {"move": Point(1, -1)}
        elif key == terminal.TK_B or key == terminal.TK_KP_1:
            return {"move": Point(-1, 1)}
        elif key == terminal.TK_N or key == terminal.TK_KP_3:
            return {"move": Point(1, 1)}
        elif key == terminal.TK_PERIOD or key == terminal.TK_KP_0 or key == terminal.TK_KP_PERIOD:
            return {"move": Point(0, 0)}
        elif key == terminal.TK_ESCAPE or key == terminal.TK_CLOSE:
            return {"exit": True}
        elif key == terminal.TK_R:
            return {"rebuild": True}

        return {}
Beispiel #2
0
    def __init__(self, player: Entity, width: int = None, height: int = None):
        if width is None:
            width: int = CAMERA_WIDTH
        if height is None:
            height: int = CAMERA_HEIGHT

        super(Camera, self).__init__(position=Point(0, 0),
                                     width=width,
                                     height=height)
        self.center = player.position
        self.player: Entity = player
        self._fov_update: bool = True
        self.ui_panel: Panel = Panel(position=Point(0, 0),
                                     width=width,
                                     height=height - 5)
Beispiel #3
0
 def points(self) -> Set[Point]:
     points: Set[Point] = set()
     for i in range(self.height):
         for j in range(self.width):
             point: Point = Point(x=j, y=i)
             points.add(point)
     return points
Beispiel #4
0
    def new_game(cls) -> Game:
        game = cls()
        game.map_generator: Optional[MapGenerator] = MapGenerator(
            map_width=CONSTANTS.map_width, map_height=CONSTANTS.map_height)
        game.current_state: Optional[GameStates] = GameStates.PLAYER_TURN
        game.previous_state: Optional[GameStates] = GameStates.PLAYER_TURN

        fighter_component: Fighter = Fighter(
            hp=CONSTANTS.player_hp,
            defense=CONSTANTS.player_defense,
            power=CONSTANTS.player_power,
        )
        inventory_component: Inventory = Inventory(capacity=26)
        level_component = Level()
        equipment_component = Equipment()
        player: Optional[Entity] = Entity(position=Point(0, 0),
                                          char="@",
                                          color=Colors.WHITE,
                                          name="Player",
                                          blocks=True,
                                          render_order=RenderLayer.ACTOR,
                                          fighter=fighter_component,
                                          inventory=inventory_component,
                                          level=level_component,
                                          equipment=equipment_component)
        game.player: Optional[Entity] = player
        game.entities: Optional[List[Entity]] = [player]

        equippable_component = Equippable(slot=EquipmentSlots.MAIN_HAND,
                                          power_bonus=2)
        dagger = Entity(position=Point(0, 0),
                        char="-",
                        color=Colors.SKY,
                        name="Dagger",
                        equippable=equippable_component)
        game.player.inventory.add_item(dagger)
        game.player.equipment.toggle_equip(dagger)

        game.message_log: Optional[MessageLog] = MessageLog(
            x=CONSTANTS.message_x,
            width=CONSTANTS.message_width,
            height=CONSTANTS.message_height,
        )
        game.game_running: bool = True
        game.camera: Optional[Camera] = Camera(player=game.player)

        return game
Beispiel #5
0
 def __iter__(self) -> Iterator["camera_view"]:
     camera_view = namedtuple("camera_view", ["x", "y", "map_point"])
     for i in range(self.height):
         for j in range(self.width):
             view = camera_view(x=j,
                                y=i,
                                map_point=Point(x=self.x + j, y=self.y + i))
             yield view
Beispiel #6
0
def initialize_fov(game_map: GameMap):

    for y in range(game_map.height):
        for x in range(game_map.width):
            point = Point(x, y)
            tile: Tile = game_map.tile(point)
            assert game_map.transparent[x, y] == tile.transparent
            assert game_map.walkable[x, y] == tile.walkable
Beispiel #7
0
 def center(self) -> Point:
     x = round(self.width / 2, 0)
     y = round(self.height / 2, 0)
     return Point(int(x), int(y))
Beispiel #8
0
 def bottom_right(self) -> Point:
     return Point(self.x + self.width - 1, self.y + self.height - 1)
Beispiel #9
0
 def bottom_left(self) -> Point:
     return Point(self.x, self.y + self.height - 1)
Beispiel #10
0
 def top_right(self, value: Point):
     if value != self.top_right:
         self.position = Point(value.x - self.width, value.y)
Beispiel #11
0
 def top_right(self) -> Point:
     return Point(self.x + self.width - 1, self.y)
Beispiel #12
0
def player() -> Entity:
    e: Entity = Entity(position=Point(x=3, y=3), char="@", color=Color.WHITE)
    return e
Beispiel #13
0
def play_game(game: Game):

    game.fov_map: tcod.map.Map = initialize_fov(game.game_map)

    game.game_state: GameStates = GameStates.PLAYER_TURN
    game.previous_state: GameStates = game.game_state

    game.camera: Camera = Camera(player=game.player,
                                 width=CONSTANTS.camera_width,
                                 height=CONSTANTS.camera_height)
    game.camera.fov_update: bool = True

    targeting_item: Optional[Entity] = None

    mouse_position: Point = Point(x=blt.state(blt.TK_MOUSE_X) // 2,
                                  y=blt.state(blt.TK_MOUSE_Y) // 2)

    while game.game_running:
        if game.camera.fov_update:
            recompute_fov(
                fov_map=game.fov_map,
                point=game.player.position,
                radius=CONSTANTS.fov_radius,
                light_walls=CONSTANTS.fov_light_walls,
                algorithm=CONSTANTS.fov_algorithm,
            )

        render_all(
            entities=game.entities,
            player=game.player,
            game_map=game.game_map,
            fov_map=game.fov_map,
            camera=game.camera,
            message_log=game.message_log,
            ui_panel=CONSTANTS.ui_panel,
            bar_width=CONSTANTS.bar_width,
            mouse_position=mouse_position,
            game_state=game.game_state,
        )

        game.camera.fov_update = False

        if blt.has_input():
            terminal_input: int = blt.read()
            mouse_position: Point = Point(x=blt.state(blt.TK_MOUSE_X) // 2,
                                          y=blt.state(blt.TK_MOUSE_Y) // 2)

            action: dict = handle_keys(key=terminal_input,
                                       game_state=game.game_state)
            mouse_action: dict = handle_mouse(key=terminal_input)

            movement: Optional[Point] = action.get("move")
            wait: bool = action.get("wait", False)
            pickup: bool = action.get("pickup", False)
            show_inventory: bool = action.get("show_inventory", False)
            drop_inventory: bool = action.get("drop_inventory", False)
            inventory_index: Optional[int] = action.get("inventory_index")
            take_stairs: bool = action.get("take_stairs", False)
            level_up: str = action.get("level_up")
            show_character_screen: bool = action.get("show_character_screen",
                                                     False)
            exit_action: bool = action.get("exit", False)

            left_click: Point = mouse_action.get("left_click")
            right_click: Point = mouse_action.get("right_click")

            player_turn_results: List = []

            if movement and game.game_state == GameStates.PLAYER_TURN:
                destination = game.player.position + movement

                if not game.game_map.is_blocked(destination):
                    target = get_blocking_entities_at_location(
                        entities=game.entities, destination=destination)

                    if target:
                        attack_results = game.player.fighter.attack(
                            target=target)
                        player_turn_results.extend(attack_results)
                    else:
                        game.player.move(movement)
                        game.camera.recenter()

                    game.change_state(GameStates.ENEMY_TURN)
            elif wait:
                game.change_state(GameStates.ENEMY_TURN)
            elif pickup and game.game_state == GameStates.PLAYER_TURN:
                for entity in game.entities:
                    if entity.item and entity.position == game.player.position:
                        pickup_results = game.player.inventory.add_item(entity)
                        player_turn_results.extend(pickup_results)

                        break
                else:
                    game.message_log.add_message(
                        Message("There is nothing here to pick up."))

            if show_inventory:
                game.change_state(GameStates.SHOW_INVENTORY)

            if drop_inventory:
                game.change_state(GameStates.DROP_INVENTORY)

            if (inventory_index is not None
                    and game.previous_state != GameStates.PLAYER_DEAD
                    and inventory_index < len(game.player.inventory.items)):
                item = game.player.inventory.items[inventory_index]

                if game.game_state == GameStates.SHOW_INVENTORY:
                    player_turn_results.extend(
                        game.player.inventory.use(item,
                                                  entities=game.entities,
                                                  fov_map=game.fov_map))
                elif game.game_state == GameStates.DROP_INVENTORY:
                    player_turn_results.extend(
                        game.player.inventory.drop_item(item))

            if take_stairs and game.game_state == GameStates.PLAYER_TURN:
                for entity in game.entities:
                    if entity.stairs and entity.position == game.player.position:
                        game.next_floor()
                        game.fov_map = initialize_fov(game.game_map)
                        game.camera.fov_update = True

                        break

                else:
                    game.message_log.add_message(
                        Message("There are no stairs here.", Colors.YELLOW))

            if level_up:
                if level_up == "hp":
                    game.player.fighter.base_max_hp += 20
                    game.player.fighter.hp += 20
                elif level_up == "str":
                    game.player.fighter.base_power += 1
                elif level_up == "dex":
                    game.player.fighter.base_defense += 1

                game.change_state(game.previous_state)

            if show_character_screen:
                game.change_state(GameStates.CHARACTER_SCREEN)

            if game.game_state == GameStates.TARGETING:
                if left_click:
                    target_position: Point = game.camera.map_point(left_click)

                    item_use_results = game.player.inventory.use(
                        targeting_item,
                        entities=game.entities,
                        fov_map=game.fov_map,
                        target_position=target_position,
                    )
                    player_turn_results.extend(item_use_results)
                elif right_click:
                    player_turn_results.append({"targeting_cancelled": True})

            if exit_action:
                if game.game_state in (GameStates.SHOW_INVENTORY,
                                       GameStates.DROP_INVENTORY,
                                       GameStates.CHARACTER_SCREEN):
                    game.change_state(GameStates.PLAYER_TURN)
                elif game.game_state == GameStates.TARGETING:
                    player_turn_results.append({"targeting_cancelled": True})
                else:
                    game.save_game()
                    game.game_running = False

            for player_turn_result in player_turn_results:
                message: Optional[Message] = player_turn_result.get("message")
                dead_entity: Optional[Entity] = player_turn_result.get("dead")
                item_added: Optional[Entity] = player_turn_result.get(
                    "item_added")
                item_consumed: Optional[Entity] = player_turn_result.get(
                    "consumed")
                item_dropped: Optional[Entity] = player_turn_result.get(
                    "item_dropped")
                equip: Optional[Entity] = player_turn_result.get("equip")
                targeting: Optional[Entity] = player_turn_result.get(
                    "targeting")
                xp: Optional[int] = player_turn_result.get("xp")
                targeting_cancelled: bool = player_turn_result.get(
                    "targeting_cancelled", False)

                if message:
                    game.message_log.add_message(message)

                if targeting_cancelled:
                    game.game_state = game.previous_state

                    game.message_log.add_message(
                        Message("Targeting cancelled"))

                if xp:
                    leveled_up = game.player.level.add_xp(xp=xp)
                    game.message_log.add_message(
                        Message(f"You gain {xp} experience points."))

                    if leveled_up:
                        game.message_log.add_message(
                            Message(
                                f"Your battle skills grow stronger! You reached level {game.player.level.current_level}!",
                                Colors.YELLOW))
                        game.change_state(GameStates.LEVEL_UP)

                if dead_entity:
                    if dead_entity == game.player:
                        message = kill_player(player=dead_entity)
                        game.change_state(GameStates.PLAYER_DEAD)
                    else:
                        message = kill_monster(monster=dead_entity)

                    game.message_log.add_message(message)

                if item_added:
                    game.entities.remove(item_added)

                    game.change_state(GameStates.ENEMY_TURN)
                    game.camera.fov_update = True

                if item_consumed:
                    game.change_state(GameStates.ENEMY_TURN)

                if targeting:
                    game.change_state(GameStates.TARGETING)

                    targeting_item: Entity = targeting

                    game.message_log.add_message(
                        targeting_item.item.targeting_message)

                if item_dropped:
                    game.entities.append(item_dropped)

                    game.change_state(GameStates.ENEMY_TURN)

                if equip:
                    equip_results = game.player.equipment.toggle_equip(equip)

                    for equip_result in equip_results:
                        equipped: Optional[Entity] = equip_result.get(
                            "equipped")
                        dequipped: Optional[Entity] = equip_result.get(
                            "dequipped")

                        if equipped:
                            game.message_log.add_message(
                                Message(f"You equipped the {equipped.name}"))

                        if dequipped:
                            game.message_log.add_message(
                                Message(f"You dequipped the {dequipped.name}"))

                    game.change_state(GameStates.ENEMY_TURN)

            if game.game_state == GameStates.ENEMY_TURN:
                for entity in game.entities:
                    if entity.ai:
                        enemy_turn_results = entity.ai.take_turn(
                            target=game.player,
                            fov_map=game.fov_map,
                            game_map=game.game_map,
                            entities=game.entities,
                        )

                        for enemy_turn_result in enemy_turn_results:
                            message: Optional[Message] = enemy_turn_result.get(
                                "message")
                            dead_entity = enemy_turn_result.get("dead")

                            if message:
                                game.message_log.add_message(message)

                            if dead_entity:
                                if dead_entity == game.player:
                                    message = kill_player(player=dead_entity)
                                    game.change_state(GameStates.PLAYER_DEAD)
                                else:
                                    message = kill_monster(monster=dead_entity)
                                game.message_log.add_message(message)
                                if game.game_state == GameStates.PLAYER_DEAD:
                                    break
                else:
                    game.change_state(GameStates.PLAYER_TURN)
Beispiel #14
0
    def view(self) -> dict:
        view = {}
        for x, y, point in iter(self):
            view[point] = Point(x, y)

        return view
Beispiel #15
0
 def offset(self) -> Point:
     return Point(self.x_offset, self.y_offset)
Beispiel #16
0
 def top_left(self) -> Point:
     return Point(self.x, self.y)
Beispiel #17
0
 def position(self) -> Point:
     return Point(self.x - self.x_offset, self.y - self.y_offset)
Beispiel #18
0
def goblin() -> Entity:
    e: Entity = Entity(position=Point(x=5, y=5),
                       char="g",
                       color=Color.LIGHT_GREEN)
    return e
Beispiel #19
0
 def map_points(self) -> Set[Point]:
     return {
         Point(x=j, y=i)
         for i in range(self.top, self.bottom + 1)
         for j in range(self.left, self.right + 1)
     }
Beispiel #20
0
 def x(self, value: int):
     new_position = Point(self.x + value, self.y)
     self.position = new_position
Beispiel #21
0
 def y(self, value):
     new_position = Point(self.x, self.y + value)
     self.position = new_position
Beispiel #22
0
 def __iter__(self):
     for i in range(self.height):
         for j in range(self.width):
             yield Point(x=self.x + j, y=self.y + i)
Beispiel #23
0
 def camera_view(self):
     view_point = namedtuple("view_point", ["x", "y", "map_point"])
     for row, i in enumerate(range(self.top, self.bottom)):
         for col, j in enumerate(range(self.left, self.right)):
             yield view_point(x=col, y=row, map_point=Point(x=j, y=i))