def start_game(config): # Loads game data, setups first map of the game then runs the main game loop. # Load all game data. tiles_data, generation_data, actor_data, item_data, animation_data = load_data( ) # Initialize map then generate a new map. current_map = Map(100, 100) start_x, start_y = generate_cave_map(current_map, generation_data, tiles_data, actor_data, item_data) # Initialize camera. camera = Camera(0, 0, config['camera_width'], config['camera_height'], 0, 0) # Spawn player. player_stats = { "hp": 100, "mp": 100, "starting_ap": 2, "max_ap": 10, "ap_recovery": 2, "base_damage": "1d4", "ac": 10, "hit": 4 } player = Actor(start_x, start_y, 'Player', '@', [255, 255, 255, 255]) player_inventory = Inventory(player) player.alive = Alive(player, player_stats, inventory=player_inventory) # Initialize FOV. fov = FOV(player, 5, current_map) under_mouse = None debug = False game_state = GameState.players_turn previous_state = None # Setup presets/containers for the game loop. actor_queue = PriorityQueue() actor_turns_left = False animations = [] no_block_animations = [] widgets = [] targeting_action = None terminal.refresh() while True: terminal.clear() if not debug: if current_map.tiles[player.x][player.y].is_stairs: player.x, player.y = generate_cave_map(current_map, generation_data, tiles_data, actor_data, item_data) current_map.depth += 1 render_all(player, current_map, fov, camera, under_mouse, animations, no_block_animations, widgets, targeting_action, game_state, config, animation_data) # Parse player input. action = handle_input(player, current_map, camera, fov, under_mouse, widgets, targeting_action, animations, no_block_animations, animation_data, game_state) under_mouse = get_under_mouse(player, current_map.tiles, current_map.actors, current_map.items, widgets, camera, game_state) # If an action was returned, complete that action. if isinstance(action, str): if action == 'restart': start_game(config) elif action == 'end-turn': if player.alive.check_in_combat(current_map.actors, fov): game_state = GameState.actors_turn elif action == 'toggle-inventory': if game_state == GameState.show_inventory: game_state = previous_state widgets = [] else: previous_state = game_state game_state = GameState.show_inventory fill_widgets(player, widgets, config, game_state) elif action == 'toggle-targeting': game_state = previous_state targeting_action = None elif action == 'toggle-map': if game_state == GameState.show_full_map: game_state = previous_state else: previous_state = game_state game_state = GameState.show_full_map elif action: if len(animations) == 0: if game_state == GameState.show_inventory: game_state = previous_state widgets = [] if action.item.targeting: previous_state = game_state game_state = GameState.targeting targeting_action = action elif game_state == GameState.targeting: game_state = previous_state targeting_action = None if game_state == GameState.players_turn: action.perform(animations, no_block_animations, animation_data) # Check if camera was moved, if it was, recalculate FOV. camera_moved = camera.move_camera(player.x, player.y, current_map) if camera_moved: fov.fov_recompute() # If player is in combat and out of ap, end the players turn. if player.alive.check_in_combat(current_map.actors, fov): if player.alive.get_ap(False) <= 0: game_state = GameState.actors_turn # Only continue if all animations have finished. if len(animations) == 0: # Go through all actors and let them take turns until # they are out of ap or decide not to take any actions. if game_state == GameState.actors_turn: # Fill the queue with actors that still need to take turns. if actor_queue.empty(): for actor in current_map.actors: if actor.alive and not actor.alive.turn_over and fov.in_fov( actor): actor_queue.put(actor, actor.alive.get_ap(False)) else: actor = actor_queue.get() if actor.alive: action = actor.alive.get_action( player, current_map, fov) if action: action.perform(animations, no_block_animations, animation_data) actor_turns_left = True else: actor.alive.turn_over = True # Player recovers ap at the end of the actors turn. if actor_queue.empty(): if not actor_turns_left: player.alive.recover_ap() game_state = GameState.players_turn for actor in current_map.actors: if actor.alive: actor.alive.turn_over = False actor_turns_left = False else: debug_render(player, current_map) # Parse player input. action = handle_input(player, current_map, camera) if action == 'restart': start_game(config) if action == 'debug': debug = not debug terminal.set("window: size='40x20', cellsize='24x24'") terminal.refresh()