import os import time import pygame from os.path import isdir, join from libstormgames import speak def get_available_games(): """Get list of available game directories in levels folder. Returns: list: List of game directory names """ try: return [d for d in os.listdir("levels") if isdir(join("levels", d))] except FileNotFoundError: return [] def selection_menu(sounds, *options): """Display level selection menu. Args: sounds (dict): Dictionary of loaded sound effects *options: Variable number of menu options Returns: str: Selected option or None if cancelled """ loop = True pygame.mixer.stop() i = 0 j = -1 # Clear any pending events pygame.event.clear() speak("Select an adventure") time.sleep(1.0) while loop: if i != j: speak(options[i]) j = i pygame.event.pump() event = pygame.event.wait() if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: return None if event.key == pygame.K_DOWN and i < len(options) - 1: i = i + 1 try: sounds['menu-move'].play() except: pass if event.key == pygame.K_UP and i > 0: i = i - 1 try: sounds['menu-move'].play() except: pass if event.key == pygame.K_HOME and i != 0: i = 0 try: sounds['menu-move'].play() except: pass if event.key == pygame.K_END and i != len(options) - 1: i = len(options) - 1 try: sounds['menu-move'].play() except: pass if event.key == pygame.K_RETURN: try: sounds['menu-select'].play() time.sleep(sounds['menu-select'].get_length()) except: pass return options[i] elif event.type == pygame.QUIT: return None pygame.event.pump() event = pygame.event.clear() time.sleep(0.001) def select_game(sounds): """Display game selection menu and return chosen game. Args: sounds (dict): Dictionary of loaded sound effects Returns: str: Selected game directory name or None if cancelled """ availableGames = get_available_games() if not availableGames: speak("No games found in levels directory!") return None # Convert directory names to display names (replace underscores with spaces) menuOptions = [game.replace("_", " ") for game in availableGames] choice = selection_menu(sounds, *menuOptions) if choice is None: return None # Convert display name back to directory name if needed gameDir = choice.replace(" ", "_") if gameDir not in availableGames: gameDir = choice # Use original if conversion doesn't match return gameDir def get_level_path(gameDir, levelNum): """Get full path to level JSON file. Args: gameDir (str): Game directory name levelNum (int): Level number Returns: str: Full path to level JSON file """ return os.path.join("levels", gameDir, f"{levelNum}.json")