コード例 #1
0
ファイル: menus.py プロジェクト: kmonaghan/rogue
def menu(con, header, options):
    if len(options) > 26:
        raise ValueError('Cannot have a menu with more than 26 options.')

    # calculate total height for the header (after auto-wrap) and one line per option
    header_height = tcod.console_get_height_rect(
        con, 0, 0, width, CONFIG.get('full_screen_height'), header)
    height = len(options) + header_height

    # create an off-screen console that represents the menu's window
    window = tcod.console_new(width, height)

    # print the header, with auto-wrap
    tcod.console_set_default_foreground(window, tcod.white)
    tcod.console_print_rect_ex(window, 0, 0, width, height, tcod.BKGND_NONE,
                               tcod.LEFT, header)

    # print all the options
    y = header_height
    letter_index = ord('a')
    for option_text, color in options:
        tcod.console_set_default_foreground(window, color)
        text = '(' + chr(letter_index) + ') ' + option_text
        tcod.console_print_ex(window, 0, y, tcod.BKGND_NONE, tcod.LEFT, text)
        y += 1
        letter_index += 1

    # blit the contents of "window" to the root console
    x = int(CONFIG.get('full_screen_width') // 2 - width // 2)
    y = int(CONFIG.get('full_screen_height') // 2 - height // 2)
    tcod.console_blit(window, 0, 0, width, height, 0, x, y, 1.0, 0.7)
コード例 #2
0
    def debug_actions(self, action, action_value):
        if action == InputTypes.DEBUG_ON:
            CONFIG.update({'debug': True})
            self.update_fov()

        if action == InputTypes.DEBUG_OFF:
            CONFIG.update({'debug': False})
            self.update_fov()
コード例 #3
0
ファイル: pathfinding.py プロジェクト: kmonaghan/rogue
def get_path_to(game_map,
                start: Tuple[int, int],
                destination: Tuple[int, int],
                routing_avoid=None,
                blocking_entity_cost=10,
                blocking_entity=None) -> List[Tuple[int, int]]:
    """Calculate the cost of moving into a node.
    The base cost of a walkable node is 1. If there is a blocking entity, this
    is increased by blocking_entity_cost. If avoid_entity is passed through, the
    nodes within a radius of 2 have their cost increased by a factor of five and
    nodes within a radius of 1 are increased by a factor of 10.

    Parameters
    ----------
    game_map: GameMap

    start: Tuple(int, int)
        Where the path will start.

    destination: Tuple(int, int)
        Where the path should end.

    target_points: List[(int, int)]

    routing_avoid: List[RoutingOptions]
      Dungeon features to avoid in the path.

    blocking_entity_cost: int
      The cost to try and move through a node with a blocking entity. Set to 0
      if entities should be always avoided.

    blocking_entity: (int, int)
        Position of an entity that will block any attempt to pass it

    Returns
    -------
    path: List[Tuple[int, int]]
      Return a list of all the nodes between the start node and destination node.
    """
    cost = create_walkable_cost(game_map,
                                routing_avoid=routing_avoid,
                                blocking_entity_cost=blocking_entity_cost,
                                blocking_entity=blocking_entity)
    #start point needs to be passable.
    cost[start[0], start[1]] = 1

    graph = tcod.path.SimpleGraph(cost=cost,
                                  cardinal=CONFIG.get('cardinal_cost'),
                                  diagonal=CONFIG.get('diagonal_cost'))

    pathfinder = tcod.path.Pathfinder(graph)

    pathfinder.add_root(start)  # Start position.

    # Compute the path to the destination and remove the starting point.
    path: List[List[int]] = pathfinder.path_to(destination)[1:].tolist()
    # Convert from List[List[int]] to List[Tuple[int, int]].
    return [(index[0], index[1]) for index in path]
コード例 #4
0
ファイル: pathfinding.py プロジェクト: kmonaghan/rogue
def move_to_radius_of_target(game_map,
                             source,
                             target,
                             radius,
                             routing_avoid=None):
    """Calculate the cost of moving into a node.
    The base cost of a walkable node is 1. If there is a blocking entity, this
    is increased by blocking_entity_cost. If avoid_entity is passed through, the
    nodes within a radius of 2 have their cost increased by a factor of five and
    nodes within a radius of 1 are increased by a factor of 10.

    Parameters
    ----------
    game_map: GameMap

    source: Tuple(int, int)
        Where the path will start.

    target: Tuple(int, int)
        Where the path should end.

    target_points: List[(int, int)]

    routing_avoid: List[RoutingOptions]
      Dungeon features to avoid in the path.

    Returns
    -------
    path: List[Tuple[int, int]]
      Return a list of all the nodes between the start node and destination node.
    """
    cost = create_walkable_cost(game_map, routing_avoid)
    dist = tcod.path.maxarray(game_map.current_level.walkable.shape,
                              dtype=np.int32)

    move_options = np.zeros(cost.shape, dtype=np.int8)
    walkable = game_map.current_level.make_walkable_array(
        routing_avoid=routing_avoid).astype(np.int)
    move_options[target[0] - radius:target[0] + radius + 1,
                 target[1] - radius:target[1] + radius +
                 1] = walkable[target[0] - radius:target[0] + radius + 1,
                               target[1] - radius:target[1] + radius + 1]
    move_options[target[0] - radius + 1:target[0] + radius,
                 target[1] - radius + 1:target[1] + radius] = 0

    dist[np.where(move_options == 1)] = 0

    tcod.path.dijkstra2d(dist, cost, CONFIG.get('cardinal_cost'),
                         CONFIG.get('diagonal_cost'))

    path = tcod.path.hillclimb2d(dist, source, True, True)[1:].tolist()

    # Convert from List[List[int]] to List[Tuple[int, int]].
    return [(index[0], index[1]) for index in path]
コード例 #5
0
ファイル: menus.py プロジェクト: kmonaghan/rogue
def ingame_menu(title, header, options):
    con = tcod.console.Console(CONFIG.get('map_width'),
                               CONFIG.get('info_panel_y'), 'F')

    header_height = con.get_height_rect(1, 1, con.width - 2, 10, header) + 1
    con.draw_frame(
        0,
        0,
        con.width,
        con.height,
        title,
        False,
        fg=tcod.white,
        bg=tcod.black,
    )

    con.print_box(
        1,
        2,
        con.width - 2,
        header_height,
        header,
        fg=tcod.white,
        bg=None,
        alignment=tcod.LEFT,
    )

    con.draw_rect(1, header_height + 1, con.width - 2, 1, ord('_'), tcod.white)

    current_y = header_height + 3
    letter_index = ord('a')
    for option_text, color in options:
        text = '(' + chr(letter_index) + ') ' + option_text
        letter_index += 1
        text_height = con.get_height_rect(1, current_y, con.width - 2, 10,
                                          text)

        con.print_box(
            1,
            current_y,
            con.width - 2,
            text_height,
            text,
            fg=color,
            bg=None,
            alignment=tcod.LEFT,
        )

        current_y = current_y + text_height

    return con
コード例 #6
0
ファイル: menus.py プロジェクト: kmonaghan/rogue
def main_menu(con, background_image):
    #tcod.image_blit_2x(background_image, 0, 0, 0)

    tcod.console_set_default_foreground(0, tcod.light_yellow)
    tcod.console_print_ex(0, int(CONFIG.get('full_screen_width') // 2),
                          int(CONFIG.get('full_screen_height') / 2) - 4,
                          tcod.BKGND_NONE, tcod.CENTER,
                          CONFIG.get('window_title'))
    tcod.console_print_ex(0, int(CONFIG.get('full_screen_width') // 2),
                          int(CONFIG.get('full_screen_height') - 2),
                          tcod.BKGND_NONE, tcod.CENTER, 'By Karl Monaghan')

    menu(con, '', [['Play a new game', tcod.white],
                   ['Continue last game', tcod.white], ['Quit', tcod.white]],
         24)
コード例 #7
0
    def update_fov(self):
        self.game_map.current_level.compute_fov(
            self.player.x,
            self.player.y,
            algorithm=self.player.fov.fov_algorithm,
            radius=self.player.fov.fov_radius,
            light_walls=self.player.fov.fov_light_walls)

        if self.player.sleep:
            self.game_map.current_level.npc_fov = tcod.map.compute_fov(
                self.game_map.current_level.transparent,
                pov=(self.player.x, self.player.y),
                algorithm=tcod.FOV_RESTRICTIVE,
                light_walls=True,
                radius=10)

        else:
            self.game_map.current_level.npc_fov = self.game_map.current_level.fov

        if not CONFIG.get('debug'):
            where_fov = np.where(self.game_map.current_level.fov[:])
            self.game_map.current_level.explored[where_fov] = True
        else:
            self.game_map.current_level.fov[:] = True
            self.game_map.current_level.explored[:] = True
コード例 #8
0
ファイル: game_map.py プロジェクト: kmonaghan/rogue
    def generate_layout(self, map_width, map_height, player):
        #return self.generate_test_layout(map_width, map_height, player)

        attempts = 0

        boss_chance = randint(0, 3) + self.dungeon_level

        while attempts < CONFIG.get('map_generation_attempts'):
            try:
                if (self.dungeon_level == 1):
                    dm = levelOneGenerator(map_width, map_height)
                else:
                    if (boss_chance >= 6):
                        dm = bossLevelGenerator(map_width, map_height,
                                                player.x, player.y)
                    else:
                        dm = levelGenerator(map_width, map_height, player.x,
                                            player.y)
                break
            except MapError as e:
                logging.info(f"===Map generation failed=== {e}")
                attempts = attempts + 1
                dm = None

        if not dm:
            raise MapGenerationFailedError

        self.current_level = LevelMap(dm.grid, dm.rooms)
        self.current_level.dungeon_level = self.dungeon_level
コード例 #9
0
ファイル: entity.py プロジェクト: kmonaghan/rogue
    def __str__(self):
        desc = self.name.title()

        if CONFIG.get('debug'):
            desc += " " + str(self.point)
            desc += " " + str(self.uuid)

        return f"{desc}"
コード例 #10
0
ファイル: pathfinding.py プロジェクト: kmonaghan/rogue
def calculate_dijkstra(game_map,
                       target_points=None,
                       routing_avoid=None,
                       blocking_entity_cost=10,
                       avoid_entity=None):
    """Calculate the cost of moving into a node.
    The base cost of a walkable node is 1. If there is a blocking entity, this
    is increased by blocking_entity_cost. If avoid_entity is passed through, the
    nodes within a radius of 2 have their cost increased by a factor of five and
    nodes within a radius of 1 are increased by a factor of 10.

    Parameters
    ----------
    game_map: GameMap object

    target_points: List[(int, int)]

    routing_avoid: List[RoutingOptions]
      Dungeon features to avoid in the path.

    blocking_entity_cost: int
      The cost to try and move through a node with a blocking entity. Set to 0
      if entities should be always avoided.

    avoid_entity: Entity
      An entity than imposes a repelling effect and increases the cost of
      passing near it.

    Returns
    -------
    dist: ndarray
      Return the computed distance of all nodes on a 2D Dijkstra grid.
    """
    cost = create_walkable_cost(game_map, routing_avoid, blocking_entity_cost,
                                avoid_entity)
    dist = tcod.path.maxarray(game_map.current_level.walkable.shape,
                              dtype=np.int32)

    for x, y in target_points:
        dist[x, y] = 0

    tcod.path.dijkstra2d(dist, cost, CONFIG.get('cardinal_cost'),
                         CONFIG.get('diagonal_cost'))

    return dist
コード例 #11
0
ファイル: render_functions.py プロジェクト: kmonaghan/rogue
def get_names_under_mouse(x, y, current_level):
    if not current_level.within_bounds(x, y):
        return ''

    location_description = f"{x}, {y}"

    if (current_level.explored[x, y] or CONFIG.get('debug')):
        location_description = location_description + ' ' + current_level.tiles[
            x, y]['name']

    if (current_level.fov[x, y] or CONFIG.get('debug')):
        names = [
            str(entity)
            for entity in current_level.entities.get_entities_in_position((x,
                                                                           y))
        ]
        names = ', '.join(names)
        location_description = location_description + ' ' + names

    return location_description
コード例 #12
0
    def start_fresh_game(self):
        logging.basicConfig(
            filename=
            f'{resource_path("log")}/{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.log',
            filemode='w',
            format='%(asctime)s - %(message)s',
            datefmt='%d-%b-%y %H:%M:%S',
            level=CONFIG.get('logging_level'))

        pubsub.pubsub = pubsub.PubSub()

        self.message_log = MessageLog(CONFIG.get('message_width'),
                                      CONFIG.get('message_height'))
        pubsub.pubsub.subscribe(
            pubsub.Subscription(self.message_log, pubsub.PubSubTypes.MESSAGE,
                                pubsub.add_to_messages))

        self.player = create_player()

        self.game_map = GameMap()
        self.game_map.create_floor(self.player)

        self.start_game()
コード例 #13
0
    def ev_keydown(self, event: tcod.event.KeyDown):
        #---------------------------------------------------------------------
        # Get key input from the self.player.
        #---------------------------------------------------------------------
        input_result = handle_keys(event, self.game_state)

        if (len(input_result) == 0):
            if CONFIG.get('debug'):
                #logging.info("No corresponding result for key press.")
                pass
            return

        action, action_value = unpack_single_key_dict(input_result)
        self.process_turn(action, action_value)
コード例 #14
0
ファイル: character.py プロジェクト: kmonaghan/rogue
    def __str__(self):
        desc = super().__str__()

        desc += self.species_describe()

        if self.level:
            desc += " (Level " + str(self.level.current_level) + ")"

        if CONFIG.get('debug'):
            if self.offence:
                desc += " O:" + str(self.offence.power)
            if self.defence:
                desc += " D:" + str(self.defence.defence)

        return f"{desc}"
コード例 #15
0
ファイル: character.py プロジェクト: kmonaghan/rogue
    def __repr__(self):
        desc = self.name.title()

        desc += self.species_describe()

        if self.level:
            desc += " (Level " + str(self.level.current_level) + ")"

        if CONFIG.get('debug'):
            if self.offence:
                desc += " O:" + str(self.offence.power)
            if self.defence:
                desc += " D:" + str(self.defence.defence)
            desc += " " + str(self.point)
            desc += " " + str(self.uuid)

        return f"{desc}"
コード例 #16
0
 def __init__(self):
     self.recompute = True
     self.game_map = None
     self.map_console = tcod.console.Console(CONFIG.get('map_width'),
                                             CONFIG.get('map_height'), 'F')
     self.info_console = tcod.console.Console(
         CONFIG.get('map_width'), CONFIG.get('info_panel_height'), 'F')
     self.message_console = tcod.console.Console(
         CONFIG.get('map_width'), CONFIG.get('message_panel_height'), 'F')
     self.menu_console = tcod.console.Console(CONFIG.get('map_width'),
                                              CONFIG.get('map_height'), 'F')
     self.game_state = GameStates.PLAYER_TURN
     self.previous_game_state = None
     self.message_log = None
     self.motion = tcod.event.MouseMotion()
     self.lbut = self.mbut = self.rbut = 0
     self.quest_request = None
     self.using_item = None
     self.last_debug_entity = None
コード例 #17
0
ファイル: game_map.py プロジェクト: kmonaghan/rogue
    def generate_test_layout(self, map_width, map_height, player):
        attempts = 0

        while attempts < CONFIG.get('map_generation_attempts'):
            try:
                dm = arena(map_width, map_height)
                #dm = levelGenerator(map_width, map_height, player.x, player.y)

                break
            except MapError as e:
                logging.info(f"===Map generation failed=== {e}")
                attempts = attempts + 1
                dm = None

        if not dm:
            raise MapGenerationFailedError

        self.current_level = LevelMap(dm.grid, dm.rooms)
        self.current_level.dungeon_level = self.dungeon_level
コード例 #18
0
    def render(self, console: Console) -> None:
        """
        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".
        """
        console.tiles_rgb[:] = np.select(
            condlist=[self.fov, self.explored],
            choicelist=[self.tiles["light"], self.tiles["dark"]],
            default=SHROUD)

        if not CONFIG.get('debug'):
            where_fov = np.where(self.fov[:])
        else:
            where_fov = np.where(self.tiles[:])
            self.render_debug(console)

        always_visible = self.entities.find_all_visible()
        for entity in always_visible:
            if self.explored[entity.x, entity.y]:
                console.print(entity.x,
                              entity.y,
                              entity.display_char,
                              fg=entity.display_color)

        for idx, x in enumerate(where_fov[0]):
            y = where_fov[1][idx]
            current_entities = self.entities.get_entities_in_position((x, y))
            entities_in_render_order = sorted(
                current_entities,
                key=lambda x: x.render_order.value,
                reverse=True)
            for entity in entities_in_render_order:
                if not entity.invisible:
                    console.print(entity.x,
                                  entity.y,
                                  entity.display_char,
                                  fg=entity.display_color)
                    break
            entities_in_render_order.clear()
            entity = None
コード例 #19
0
ファイル: menus.py プロジェクト: kmonaghan/rogue
def character_screen(player):
    options = [
        'Level: {0}'.format(player.level.current_level),
        'Experience: {0}'.format(player.level.current_xp),
        'Experience to Level: {0}'.format(
            player.level.experience_to_next_level),
        'Maximum HP: {0}'.format(player.health.max_hp),
        'Attack: {0}'.format(player.offence.power),
        'Defence: {0}'.format(player.defence.defence),
    ]

    height = len(options) + 2

    con = tcod.console.Console(CONFIG.get('map_width'), height, 'F')

    con.draw_frame(
        0,
        0,
        con.width,
        con.height,
        'Character Profile',
        False,
        fg=tcod.white,
        bg=tcod.black,
    )

    con.print_box(
        1,
        1,
        con.width - 2,
        len(options),
        '\n'.join(options),
        fg=tcod.white,
        bg=None,
        alignment=tcod.LEFT,
    )

    return con
コード例 #20
0
ファイル: input_handlers.py プロジェクト: kmonaghan/rogue
def handle_player_turn_keys(event):
    # Movement keys
    if event.sym == tcod.event.K_UP or event.sym == ord('k'):
        return {InputTypes.MOVE: (0, -1)}
    elif event.sym == tcod.event.K_DOWN or event.sym == ord('j'):
        return {InputTypes.MOVE: (0, 1)}
    elif event.sym == tcod.event.K_LEFT or event.sym == ord('h'):
        return {InputTypes.MOVE: (-1, 0)}
    elif event.sym == tcod.event.K_RIGHT or event.sym == ord('l'):
        return {InputTypes.MOVE: (1, 0)}
    elif event.sym == ord('y'):
        return {InputTypes.MOVE: (-1, -1)}
    elif event.sym == ord('u'):
        return {InputTypes.MOVE: (1, -1)}
    elif event.sym == ord('b'):
        return {InputTypes.MOVE: (-1, 1)}
    elif event.sym == ord('n'):
        return {InputTypes.MOVE: (1, 1)}
    elif event.sym == ord('z'):
        return {InputTypes.WAIT: True}
    elif event.sym == ord('s'):
        return {InputTypes.SLEEP: True}
    elif event.sym == ord(']'):
        return {InputTypes.DEBUG_ON: True}
    elif event.sym == ord('['):
        return {InputTypes.DEBUG_OFF: False}

    if event.sym == ord('g'):
        return {InputTypes.PICKUP: True}

    elif event.sym == ord('i'):
        return {InputTypes.INVENTORY_USE: True}

    elif event.sym == ord('d'):
        return {InputTypes.INVENTORY_DROP: True}

    elif event.sym == ord('e'):
        return {InputTypes.INVENTORY_EXAMINE: True}

    elif event.sym == ord('q'):
        return {InputTypes.QUEST_LIST: True}

    elif event.sym == ord(',') or event.sym == ord('.'):
        return {InputTypes.TAKE_STAIRS: True}

    elif event.sym == ord('c'):
        return {InputTypes.CHARACTER_SCREEN: True}

    elif event.sym == tcod.event.K_ESCAPE:
        # Exit the game
        return {InputTypes.EXIT: True}

    if CONFIG.get('debug') and event.sym == ord('r'):
        return {InputTypes.RELOAD_LEVEL: True}

    if CONFIG.get('debug') and event.sym == ord('o'):
        return {InputTypes.SHOW_DIJKSTRA_PLAYER: True}

    if CONFIG.get('debug') and event.sym == ord('p'):
        return {InputTypes.SHOW_DIJKSTRA_FLEE: True}

    if CONFIG.get('debug') and event.sym == ord('x'):
        return {InputTypes.DOWN_LEVEL: True}

    # No key was pressed
    return {}
コード例 #21
0
def create_player():
    #create object representing the player
    health_component = Health(30)

    player = Character(None,
                       '@',
                       'player',
                       COLORS.get('player'),
                       death=PlayerDeath(),
                       health=health_component,
                       species=Species.PLAYER,
                       act_energy=4)

    player.add_component(Offence(base_power=6), 'offence')
    player.add_component(Defence(defence=6), 'defence')
    player.add_component(Level(), 'level')
    player.add_component(FOV(), 'fov')

    #initial equipment: a dagger
    dagger = equipment.create_weapon('dagger')

    player.inventory.add_item(dagger)
    player.equipment.toggle_equip(dagger)

    armour = equipment.create_armour('leather shirt')
    player.inventory.add_item(armour)
    player.equipment.toggle_equip(armour)

    if CONFIG.get('debug'):
        player.level.random_level_up(30)
        weapon = equipment.random_magic_weapon()
        player.inventory.add_item(weapon)
        player.equipment.toggle_equip(weapon)

        armour = equipment.random_armour()
        #equipment.add_damage_aura(armour)
        player.inventory.add_item(armour)
        player.equipment.toggle_equip(armour)

        ring = equipment.random_ring()
        player.inventory.add_item(ring)
        player.equipment.toggle_equip(ring)

        potion = equipment.healing_potion()
        player.inventory.add_item(potion)

        potion2 = equipment.power_potion()
        potion2.identifiable.identified = True
        player.inventory.add_item(potion2)

        potion3 = equipment.defence_potion()
        potion3.identifiable.identified = True
        player.inventory.add_item(potion3)

        potion4 = equipment.speed_potion()
        potion4.identifiable.identified = True
        player.inventory.add_item(potion4)

        scroll1 = equipment.lighting_scroll()
        scroll1.identifiable.identified = True
        player.inventory.add_item(scroll1)

        scroll2 = equipment.fireball_scroll()
        scroll2.identifiable.identified = True
        player.inventory.add_item(scroll2)

        scroll3 = equipment.confusion_scroll()
        scroll3.identifiable.identified = True
        player.inventory.add_item(scroll3)

        scroll4 = equipment.identify_scroll()
        scroll4.identifiable.identified = True
        player.inventory.add_item(scroll4)

        scroll5 = equipment.speed_scroll()
        scroll5.identifiable.identified = True
        player.inventory.add_item(scroll5)

        scroll6 = equipment.teleport_scroll()
        scroll6.identifiable.identified = True
        player.inventory.add_item(scroll6)

        scroll7 = equipment.map_scroll()
        scroll7.identifiable.identified = True
        player.inventory.add_item(scroll7)

        scroll8 = equipment.chain_lightning_scroll()
        scroll8.identifiable.identified = True
        player.inventory.add_item(scroll8)

    pubsub.pubsub.subscribe(
        pubsub.Subscription(player, pubsub.PubSubTypes.EARNEDXP,
                            earn_quest_xp))

    return player
コード例 #22
0
ファイル: game_map.py プロジェクト: kmonaghan/rogue
    def create_floor(self, player):
        self.down_stairs = None
        self.up_stairs = None

        self.make_map(CONFIG.get('map_width'), CONFIG.get('map_height'),
                      player)
コード例 #23
0
    def on_draw(self):
        #---------------------------------------------------------------------
        # Recompute the player's field of view.
        #---------------------------------------------------------------------
        self.update_fov()

        #---------------------------------------------------------------------
        # Render and display the dungeon and its inhabitates.
        #---------------------------------------------------------------------
        self.game_map.current_level.render(self.map_console)

        if not CONFIG.get('debug'):
            self.game_map.current_level.render_torch(
                self.player.x, self.player.y, self.player.fov.fov_radius,
                self.map_console)

        if CONFIG.get('debug') and self.game_map.current_level.within_bounds(
                self.motion.tile.x, self.motion.tile.y):
            for entity in self.game_map.current_level.entities.get_entities_in_position(
                (self.motion.tile.x, self.motion.tile.y)):
                if entity.movement:
                    dijkstra = calculate_dijkstra(self.game_map,
                                                  [(entity.x, entity.y)],
                                                  avoid_entity=self.player)
                    self.game_map.current_level.render_dijkstra(
                        dijkstra, self.map_console)

                    if entity.ai:
                        path = entity.ai.tree.namespace.get("path")
                        target = entity.ai.tree.namespace.get("target")
                        if path or target:
                            self.game_map.current_level.render_entity_detail(
                                path, target, self.map_console)
                    if not (entity == self.last_debug_entity):
                        entity.debug()
                        self.last_debug_entity = entity

        #---------------------------------------------------------------------
        # Render infomation panels.
        #---------------------------------------------------------------------
        render_info_console(self.info_console, self.player, self.game_map)
        render_message_console(self.message_console, self.message_log)

        #---------------------------------------------------------------------
        # Blit the subconsoles to the main console and flush all rendering.
        #---------------------------------------------------------------------
        root_console.clear(fg=COLORS.get('console_background'))

        self.map_console.blit(root_console, 0, 0, 0, 0, self.map_console.width,
                              self.map_console.height)

        under_mouse_text = get_names_under_mouse(self.motion.tile.x,
                                                 self.motion.tile.y,
                                                 self.game_map.current_level)
        text_height = root_console.get_height_rect(1, 0,
                                                   root_console.width - 2, 10,
                                                   under_mouse_text)

        root_console.print_box(
            1,
            CONFIG.get('info_panel_y') - text_height - 1,
            root_console.width - 2,
            text_height,
            under_mouse_text,
            fg=tcod.white,
            bg=None,
            alignment=tcod.LEFT,
        )

        self.info_console.blit(root_console, 0, CONFIG.get('info_panel_y'), 0,
                               0, CONFIG.get('full_screen_width'),
                               CONFIG.get('info_panel_height'))
        self.message_console.blit(root_console, 0,
                                  CONFIG.get('message_panel_y'), 0, 0,
                                  CONFIG.get('full_screen_width'),
                                  CONFIG.get('message_panel_height'))

        if self.game_state in MENU_STATES:
            #---------------------------------------------------------------------
            # Render any menus.
            #---------------------------------------------------------------------
            exclude = []
            if self.using_item:
                exclude.append(self.using_item)

            self.menu_console = render_menu_console(self.game_state,
                                                    self.player,
                                                    self.quest_request,
                                                    exclude)

            self.menu_console.blit(root_console, 0, 0, 0, 0,
                                   CONFIG.get('full_screen_width'),
                                   CONFIG.get('full_screen_height'))
コード例 #24
0
def main():
    global current_game, root_console

    equipment.import_armour()
    equipment.import_weapons()

    tcod.console_set_custom_font(
        resource_path(CONFIG.get('font')),
        CONFIG.get('font_type') | tcod.FONT_TYPE_GREYSCALE,
    )

    root_console = tcod.console_init_root(CONFIG.get('full_screen_width'),
                                          CONFIG.get('full_screen_height'),
                                          CONFIG.get('window_title'),
                                          False,
                                          order='F',
                                          vsync=False)

    current_game.start_fresh_game()

    while True:
        root_console.clear(fg=COLORS.get('console_background'))

        if current_game.game_state == GameStates.GAME_EXIT:
            raise SystemExit()
        '''
                if show_main_menu:
                    root_console.clear(fg=(255, 255, 255))

                    main_menu(root_console, main_menu_background_image, CONFIG.get('full_screen_width'),
                              CONFIG.get('full_screen_height'))

                    if show_load_error_message:
                        message_box(map_console, 'No saved game to load', 50, CONFIG.get('full_screen_width'), constants['screen_height'])

                    tcod.console_flush()

                    action = handle_keys(key, GameStates.GAME_START)

                    if len(action) > 0:
                        result_type, result_data = unpack_single_key_dict(action)
                        if show_load_error_message and (result_type == InputTypes.GAME_LOAD):
                            show_load_error_message = False
                        elif result_type == InputTypes.GAME_NEW:
                            player, game_map, message_log, game_state = get_game_variables(constants)
                            game_map.create_floor(player)

                            show_main_menu = False
                        elif result_type == InputTypes.GAME_LOAD:
                            try:
                                player, game_map, message_log, game_state, pubsub.pubsub = load_game()
                                show_main_menu = False
                            except FileNotFoundError:
                                show_load_error_message = True
                        elif result_type == InputTypes.GAME_EXIT:
                            break
        '''
        #if self.game_state == GameStates.GAME_START:
        #    main_menu.on_draw()
        #else:
        current_game.on_draw()
        tcod.console_flush()

        #Uncomment the following line to take a screenshot each turn
        #tcod.sys_save_screenshot()

        if (current_game.game_state == GameStates.ENEMY_TURN
                or current_game.game_state == GameStates.PLAYER_SLEEP):
            current_game.process_turn(None, None)
        else:
            handle_events()
コード例 #25
0
    def process_turn(self, action, action_value):
        player_turn_results = []

        if self.game_actions(action, action_value):
            return

        if self.change_state_action(action, action_value):
            return

        self.debug_actions(action, action_value)

        self.quest_actions(action, action_value)

        if action == InputTypes.EXIT:
            if self.game_state in CANCEL_STATES:
                self.game_state = self.previous_game_state
                self.using_item = None
                if self.game_state == GameStates.QUEST_ONBOARDING:
                    player_turn_results.append(
                        {ResultTypes.QUEST_CANCELLED: True})
            else:
                self.previous_game_state = self.game_state
                self.game_state = GameStates.GAME_PAUSED
                return

        if (action == InputTypes.TARGETING
                and self.game_state == GameStates.TARGETING):
            target_x, target_y = action_value

            player_turn_results.extend(
                self.using_item.usable.use(game_map=self.game_map,
                                           user=self.player,
                                           target_x=target_x,
                                           target_y=target_y))

        if (action == InputTypes.INVENTORY_INDEX
                and self.previous_game_state != GameStates.GAME_OVER
                and action_value < len(self.player.inventory.items)):

            items = self.player.inventory.items.copy()

            if self.using_item:
                items.remove(self.using_item)

            item = items[action_value]

            if self.game_state == GameStates.INVENTORY_USE:
                if item.usable:
                    self.using_item = item
                    player_turn_results.extend(
                        item.usable.use(self.game_map, self.player))
                else:
                    player_turn_results.extend([{ResultTypes.EQUIP: item}])

            elif self.game_state == GameStates.INVENTORY_SELECT:
                player_turn_results.extend(
                    self.using_item.usable.use(self.game_map, self.player,
                                               item))
                self.using_item = None
            elif self.game_state == GameStates.INVENTORY_DROP:
                player_turn_results.extend(
                    self.player.inventory.drop_item(item))
            elif self.game_state == GameStates.INVENTORY_EXAMINE:
                player_turn_results.extend(
                    self.player.inventory.examine_item(item))

        self.process_results_stack(self.player, player_turn_results)

        pubsub.pubsub.process_queue(self.game_map)

        #-------------------------------------------------------------------
        # Player takes their turn.
        #-------------------------------------------------------------------
        if (self.game_state == GameStates.PLAYER_TURN
                or self.game_state == GameStates.PLAYER_SLEEP):
            self.player_actions(action, action_value)

        if (self.game_state in INPUT_STATES
                or self.game_state == GameStates.GAME_OVER):
            return

        #-------------------------------------------------------------------
        # NPCs take their turns.
        #-------------------------------------------------------------------
        self.npc_actions()

        self.player.energy.increase_energy()
        if self.player.energy.can_act:
            if self.player.sleep:
                self.game_state = GameStates.PLAYER_SLEEP
            else:
                if not self.game_state in INPUT_STATES:
                    self.game_state = GameStates.PLAYER_TURN
        else:
            if not self.game_state in INPUT_STATES:
                self.game_state = GameStates.ENEMY_TURN

        if not self.game_state == GameStates.PLAYER_TURN:
            sleep(CONFIG.get('time_between_enemy_turns'))

        #---------------------------------------------------------------------
        # And done...so broadcast a tick
        #---------------------------------------------------------------------
        pubsub.pubsub.add_message(pubsub.Publish(None,
                                                 pubsub.PubSubTypes.TICK))

        pubsub.pubsub.process_queue(self.game_map)