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)
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]
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]
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
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)
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
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
def __str__(self): desc = self.name.title() if CONFIG.get('debug'): desc += " " + str(self.point) desc += " " + str(self.uuid) return f"{desc}"
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
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
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()
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)
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}"
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}"
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
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
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
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
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 {}
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
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)
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'))
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()
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)