def get_names_under_mouse(mouse, entities, fov_map): (x, y) = (mouse.cx, mouse.cy) for entity in entities: if entity.x == x and entity.y == y and tc.map_is_in_fov( fov_map, entity.x, entity.y) and entity.fighter != None: names = [ entity.name for entity in entities if entity.x == x and entity.y == y and tc.map_is_in_fov(fov_map, entity.x, entity.y) ] names = ''.join(names) + ' ' + Mage.get_stats( entity) + Fighter.get_stats(entity) return names else: names = [ entity.name for entity in entities if entity.x == x and entity.y == y and tc.map_is_in_fov(fov_map, entity.x, entity.y) ] names = ', '.join(names) return names.capitalize()
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants): fov_recompute = True fov_map = initialize_fov(game_map) key = tc.Key() mouse = tc.Mouse() targeting_item = None visible_enemies = [] room_enemies_index = 0 room_enemies_length = 0 event = tc.event.get() while event != "QUIT": # while not tc.console_is_window_closed(): tc.sys_check_for_event(tc.EVENT_KEY_PRESS | tc.EVENT_MOUSE, key, mouse) if fov_recompute: recompute_fov(fov_map, player.x, player.y, constants['fov_radius'], constants['fov_light_walls'], constants['fov_algorithm']) render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], mouse, constants['colors'], game_state) fov_recompute = False tc.console_flush() clear_all(con, entities) action = handle_keys(key, game_state) mouse_action = handle_mouse(mouse) mouse_teleport_action = handle_mouse_teleport(mouse) move = action.get('move') wait = action.get('wait') pickup = action.get('pickup') show_inventory = action.get('show_inventory') drop_inventory = action.get('drop_inventory') inventory_index = action.get('inventory_index') ranged_index = action.get('ranged_index') take_stairs = action.get('take_stairs') level_up = action.get('level_up') show_character_screen = action.get('show_character_screen') exit = action.get('exit') fullscreen = action.get('fullscreen') god_mode = action.get('god_mode') show_help_menu = action.get('show_help_menu') close_help_menu = action.get('close_help_menu') cycle_target = action.get('cycle_target') cycle_target_right = action.get('right_target') cycle_target_left = action.get('left_target') poisoned = action.get('poisoned') burning = action.get('burning') reveal_map = action.get('reveal_map') decrease_limb_damage = action.get('decrease_limb_damage') increase_limb_damage = action.get('increase_limb_damage') teleport = action.get('teleport') mouse_teleport = mouse_teleport_action.get('mouse_teleport') ranged = action.get('ranged') spawn_enemy_at = action.get('spawn_enemy_at') left_click = mouse_action.get('left_click') right_click = mouse_action.get('right_click') player_turn_results = [] if move and game_state == GameStates.PLAYERS_TURN: dx, dy = move destination_x = player.x + dx destination_y = player.y + dy if not game_map.is_blocked(destination_x, destination_y): target = get_blocking_entities_at_location( entities, destination_x, destination_y) if target: attack_results = player.fighter.attack(target) player_turn_results.extend(attack_results) else: player.move(dx, dy) fov_recompute = True if player.fighter.turns_since_special <= 5: player.fighter.turns_since_special += 1 game_state = GameStates.ENEMY_TURN elif wait: if player.fighter.turns_since_special <= 5: player.fighter.turns_since_special += 1 game_state = GameStates.ENEMY_TURN elif pickup and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.item and entity.x == player.x and entity.y == player.y: pickup_results = player.inventory.add_item(entity) player_turn_results.extend(pickup_results) break else: message_log.add_message( Message('There is nothing here to pick up.', tc.yellow)) if show_inventory: previous_game_state = game_state game_state = GameStates.SHOW_INVENTORY if drop_inventory: previous_game_state = game_state game_state = GameStates.DROP_INVENTORY if show_help_menu: previous_game_state = game_state game_state = GameStates.SHOW_HELP_MENU if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len( player.inventory.items): item = player.inventory.items[inventory_index] if game_state == GameStates.SHOW_INVENTORY: player_turn_results.extend( player.inventory.use(item, entities=entities, fov_map=fov_map)) elif game_state == GameStates.DROP_INVENTORY: player_turn_results.extend(player.inventory.drop_item(item)) if ranged_index is not None and previous_game_state != GameStates.PLAYER_DEAD and ranged_index < len( player.inventory.items): item = player.inventory.items[ranged_index] if game_state == GameStates.RANGED: player_turn_results.extend( player.inventory.use(item, entities=entities, fov_map=fov_map)) if take_stairs and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y and entity.stairs.direction == 'down': entities = game_map.next_floor(player, message_log, constants) fov_map = initialize_fov(game_map) fov_recompute = True con.clear() break elif entity.stairs and entity.x == player.x and entity.y == player.y and entity.stairs.direction == 'up': entities = game_map.previous_floor(player, message_log, constants) fov_map = initialize_fov(game_map) fov_recompute = True con.clear() break elif entity.area and entity.x == player.x and entity.y == player.y: entities = game_map.load_area(player, message_log, constants) fov_map = initialize_fov(game_map) fov_recompute = True con.clear() break else: message_log.add_message( Message('There are no stairs here.', tc.yellow)) if cycle_target: previous_game_state = game_state game_state = GameStates.CYCLE_TARGET visible_enemies.clear() for entity in entities: if entity.ai != None: if tc.map_is_in_fov(fov_map, entity.x, entity.y): visible_enemies.append([ cycle_target_distance_to(player, entity), entity.x, entity.y, entity.name ]) if len(visible_enemies) != 0: con.default_fg = tc.black con.default_fg = tc.white con.print( int(constants['screen_width'] / 2), 1, 'Press RIGHT arrow or LEFT arrow key to cycle targets or ESCAPE to cancel targeting' .format(), (255, 255, 255), (0, 0, 0), 1, tc.CENTER) tc.console_blit(con, 0, 0, constants['screen_width'], constants['screen_height'], 0, 0, 0) visible_enemies.sort() room_enemies_length = len(visible_enemies) else: con.print( int(constants['screen_width'] / 2), 1, 'There are no enemies present! Press ESCAPE to cancel targeting' .format(), (255, 255, 255), (0, 0, 0), 1, tc.CENTER) if cycle_target_right: if len(visible_enemies) != 0: fov_recompute = True con.clear() con.default_fg = tc.black con.default_fg = tc.white con.print( int(constants['screen_width'] / 2), 1, 'Press RIGHT arrow or LEFT arrow key to cycle targets or ESCAPE to cancel targeting' .format(), (255, 255, 255), (0, 0, 0), 1, tc.CENTER) tc.console_blit(con, 0, 0, constants['screen_width'], constants['screen_height'], 0, 0, 0) con.draw_frame((visible_enemies[room_enemies_index][1]) - 1, (visible_enemies[room_enemies_index][2]) - 1, 3, 3, "", True, fg=tc.white, bg=tc.black) con.print((visible_enemies[room_enemies_index][1]) + 1, (visible_enemies[room_enemies_index][2]) - 2, '{0}'.format(visible_enemies[room_enemies_index][3]), (255, 255, 255), (0, 0, 0), 1, tc.CENTER) for entity in entities: if tc.map_is_in_fov(fov_map, entity.x, entity.y): if visible_enemies[room_enemies_index][ 3] == entity.name: names = entity.name names = names + ' ' + Mage.get_stats( entity) + Fighter.get_stats(entity) con.print( (visible_enemies[room_enemies_index][1]) + 1, (visible_enemies[room_enemies_index][2]) - 2, '{0}'.format(names, tc.white), (255, 255, 255), (0, 0, 0), 1, tc.CENTER) if room_enemies_index == room_enemies_length - 1: room_enemies_index = 0 else: room_enemies_index += 1 if cycle_target_left: if len(visible_enemies) != 0: fov_recompute = True con.clear() con.default_fg = tc.black con.default_fg = tc.white con.print( int(constants['screen_width'] / 2), 1, 'Press RIGHT arrow or LEFT arrow key to cycle targets or ESCAPE to cancel targeting' .format(), (255, 255, 255), (0, 0, 0), 1, tc.CENTER) tc.console_blit(con, 0, 0, constants['screen_width'], constants['screen_height'], 0, 0, 0) con.draw_frame((visible_enemies[room_enemies_index][1]) - 1, (visible_enemies[room_enemies_index][2]) - 1, 3, 3, "", True, fg=tc.white, bg=tc.black) con.print((visible_enemies[room_enemies_index][1]) + 1, (visible_enemies[room_enemies_index][2]) - 2, '{0}'.format(visible_enemies[room_enemies_index][3]), (255, 255, 255), (0, 0, 0), 1, tc.CENTER) for entity in entities: if tc.map_is_in_fov(fov_map, entity.x, entity.y): if visible_enemies[room_enemies_index][ 3] == entity.name: names = entity.name names = names + ' ' + Mage.get_stats( entity) + Fighter.get_stats(entity) con.print( (visible_enemies[room_enemies_index][1]) + 1, (visible_enemies[room_enemies_index][2]) - 2, '{0}'.format(names, tc.white), (255, 255, 255), (0, 0, 0), 1, tc.CENTER) if room_enemies_index == 0: room_enemies_index = room_enemies_length - 1 else: room_enemies_index -= 1 if god_mode: player.fighter.hp = 2500 if poisoned: if player.fighter.is_poisoned == False: player.fighter.is_poisoned = True player.fighter.poison_turns_remaining = 5 player.color = tc.green if burning: if player.fighter.is_burning == False: player.fighter.is_burning = True player.fighter.burning_turns_remaining = 5 player.color = tc.red if reveal_map: if constants['fov_radius'] == 8: constants['fov_radius'] = 250 for i in range(len(game_map.tiles)): for j in range(len(game_map.tiles[i])): if not game_map.tiles[i][j].blocked: game_map.tiles[i][j].explored = True game_map.tiles[i][j].block_sight = False fov_map = initialize_fov(game_map) fov_recompute = True con.default_fg = tc.black con.default_fg = tc.white for entity in entities: #ALL ENTITIES # con.draw_frame(entity.x - 1, entity.y - 1 , 3, 3, "", False, fg=tc.black, bg=tc.black) #ENEMIES ONLY if entity.ai != None: #ENEMY SEEING POWER con.draw_frame(entity.x - 1, entity.y - 1, 3, 3, "", False, fg=tc.black, bg=tc.black) elif constants['fov_radius'] != 8: constants['fov_radius'] = 8 fov_recompute = True con.clear() if spawn_enemy_at: mouse_x = mouse.cx mouse_y = mouse.cy spawn_enemy(mouse_x, mouse_y, entities, game_map.dungeon_level) if increase_limb_damage: player.fighter.take_limb_damge(randint(1, 12)) if decrease_limb_damage: player.fighter.heal(randint(1, 12)) if teleport: for entity in entities: if entity.name == "Stairs Down": player.x = entity.x player.y = entity.y + 1 if mouse_teleport: player.x = mouse.cx player.y = mouse.cy if ranged: previous_game_state = game_state game_state = GameStates.RANGED if level_up: if level_up == 'hp': player.fighter.base_max_hp += 20 player.fighter.hp += 20 elif level_up == 'str': player.fighter.base_strength += 1 elif level_up == 'def': player.fighter.base_defense += 1 game_state = previous_game_state if show_character_screen: previous_game_state = game_state game_state = GameStates.CHARACTER_SCREEN if game_state == GameStates.TARGETING: if left_click: target_x, target_y = left_click item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map, target_x=target_x, target_y=target_y) player_turn_results.extend(item_use_results) elif right_click: player_turn_results.append({'targeting_cancelled': True}) if exit: if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN, GameStates.RANGED, GameStates.TARGETING, GameStates.SHOW_TUTORIAL, GameStates.SHOW_HELP_MENU): game_state = previous_game_state elif game_state == GameStates.CYCLE_TARGET: game_state = previous_game_state con.clear() clear_all(con, entities) fov_map = initialize_fov(game_map) fov_recompute = True con.clear() elif game_state == GameStates.TARGETING: game_state = previous_game_state player_turn_results.append({'targeting_cancelled': True}) con.clear() clear_all(con, entities) fov_map = initialize_fov(game_map) fov_recompute = True con.clear() else: save_game(player, entities, game_map, message_log, game_state) return True if fullscreen: tc.console_set_fullscreen(not tc.console_is_fullscreen()) for player_turn_result in player_turn_results: message = player_turn_result.get('message') dead_entity = player_turn_result.get('dead') item_added = player_turn_result.get('item_added') item_consumed = player_turn_result.get('consumed') item_dropped = player_turn_result.get('item_dropped') equip = player_turn_result.get('equip') targeting = player_turn_result.get('targeting') targeting_cancelled = player_turn_result.get('targeting_cancelled') xp = player_turn_result.get('xp') god_mode = player_turn_result.get('god_mode') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) last_index = len(entities) pre_dead_name = dead_entity.name.replace('remains of ', '') if dead_entity.inventory != None: for items in dead_entity.inventory.items: items.x = dead_entity.x items.y = dead_entity.y entities.insert(last_index, items) message_log.add_message( Message('{0}'.format(pre_dead_name) + ' dropped' + ' {0}'.format(items.name))) message_log.add_message(message) if item_added: entities.remove(item_added) if item_consumed: game_state = GameStates.ENEMY_TURN if item_dropped: entities.append(item_dropped) if equip: equip_results = player.equipment.toggle_equip(equip) for equip_result in equip_results: equipped = equip_result.get('equipped') unequipped = equip_result.get('unequipped') failed = equip_result.get('failed') if equipped: message_log.add_message( Message('You equipped the {0}'.format( equipped.name))) if unequipped: message_log.add_message( Message('You unequipped the {0}'.format( unequipped.name))) if failed: message_log.add_message( Message( 'You failed to equip the {0} due to your injuries' .format(failed.name))) game_state = GameStates.ENEMY_TURN if targeting: previous_game_state = GameStates.PLAYERS_TURN game_state = GameStates.TARGETING targeting_item = targeting message_log.add_message(targeting_item.item.targeting_message) if targeting_cancelled: game_state = previous_game_state message_log.add_message(Message('Targeting cancelled')) if xp: leveled_up = player.level.add_xp(xp) message_log.add_message( Message('You gain {0} experience points.'.format(xp))) if leveled_up: previous_game_state = game_state game_state = GameStates.LEVEL_UP if game_state == GameStates.ENEMY_TURN: for entity in entities: if entity.ai: # #TRACK ENEMY SPECIAL TURNS # if tc.map_is_in_fov(fov_map, entity.x, entity.y): # print(entity.name + ":" + " " + str(entity.fighter.turns_since_special)) enemy_turn_results = entity.ai.take_turn( player, fov_map, game_map, entities) if entity.fighter.is_poisoned == True: message = entity.fighter.take_poison_damage() message_log.add_message(message) elif entity.fighter.is_burning == True: message = entity.fighter.take_burning_damage() message_log.add_message(message) for enemy_turn_result in enemy_turn_results: message = enemy_turn_result.get('message') dead_entity = enemy_turn_result.get('dead') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(dead_entity) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if game_state == GameStates.PLAYER_DEAD: break else: if player.fighter.is_poisoned == True: message = player.fighter.take_poison_damage() message_log.add_message(message) elif player.fighter.is_burning == True: message = player.fighter.take_burning_damage() message_log.add_message(message) game_state = GameStates.PLAYERS_TURN if game_state == GameStates.SHOW_TUTORIAL: action = handle_tutorial_menu(key) close_tutorial = action.get('close_tutorial') if close_tutorial: con.clear() clear_all(con, entities) fov_map = initialize_fov(game_map) fov_recompute = True con.clear() game_state = GameStates.PLAYERS_TURN if game_state == GameStates.SHOW_HELP_MENU: action = handle_help_menu(key) close_help_menu = action.get('close_help_menu') if close_help_menu: con.clear() clear_all(con, entities) fov_map = initialize_fov(game_map) fov_recompute = True con.clear() game_state = GameStates.PLAYERS_TURN