Write a Python application which implements a menu system for a retro-style video game console. The entire application will run in a Terminal emulator (TUI), and will use the Blessed library to format text on the Terminal. The application will be controlled using a joystick (eight direction keys, named UP, UPLEFT, LEFT, DOWNLEFT, etc.) and eight action buttons, here named A, B, C, D, E, F, G, H. The joystick and button hardware will appear to the system as a keyboard; the application settings should specify a mapping from these logical buttons to key names.

The application should have the following components:

  • Splash screen: On initialization, the program should run setup (described below), debugging (described below), and then display a splash screen.
  • Setup: First, validate the system settings. If any of the following fails, enter debugging mode:
    • Initialize the database if needed.
    • Ensure that the actual terminal window is at least as large as the specified screen size. Then iterate over each package in the specified “games” directory. Validate each for the following:
    • Has pyproject.toml.
    • Pyproject.toml has the following keys set:
      • project.scripts.play (script to run to play the game)
      • tool.retro.author (author name to display)
      • tool.retro.description (description to display)
      • tool.retro.result_file: “result.json”
    • In a subprocess run “poetry install” with the game directory as working directory. If there are any installation errors, fail validation. Collect all valid games.
  • Debugging: If the specified debug key is pressed during setup, enter debugging mode. Print out the list of all games found during setup, and the results of validation. Then enter the Terminal shell.
  • Game select screen: When the user pushes any key, the program should go into a game-selection interface, listing availalbe games on the left and displaying game details for the currently-selected game on the right. The player can press up/down to navigate the list of available games; this list will scroll if necessary. On the right, display the game name, the game author, the game description, the number of plays, and a list of the top ten high scores. If no keystrokes are entered within game_select_timeout, reeturn to the splash screen.
  • Play game: If a player presses A from the game select screen, play the selected game. Games are stored within the “games” directory; each game is a Python package. To run the game, use poetry. In a subprocess, invoke “poetry run play_game” with the game package as the working directory. If max_game_duration is set in the settings, automatically kill the game after the max duration. When the game ends, it will write the result to tool.retro.result_file. Increment the record of number of plays for this game. Try to this file and get “score”. If successful, enter “high score mode” if the score is one of the top ten scores for this game.
  • High score mode: Display a keyboard (which the player can navigate with the joystick), and allow the player to select three letters to use as their initials to add to high scores. Don’t allow words on the forbidden word list, if specified. Once the player has selected a name, return to the game select screen, showing the game just played, with high scores.

Store game plays and high scores in a sqlite database. Use SQLalchemy to specify the database schema.

Settings

  • screen_size (width, height) tuple specifying how many rows and columns to use.
  • debug_key (When pressed during startup, enter debug mode)
  • max_game_duration Games automatically exit after this time limit.
  • The mapping from key names to logical keys joystick (UP, UPLEFT, LEFT, DOWNLEFT, etc.) and eight action buttons, here named A, B, C, D, E, F, G, H.)
  • The games_dir directory, where to search for game packages.
  • forbidden_word_list: A text file containing naughty three-letter words which should not be allowed in high scores.
  • game_select_timeout: Default to one minute.

FOR STUDENTS

  1. Update pyproject.toml. The following keys should be set:
  • project.scripts.play (script to run to play the game)
  • tool.retro.author (author name to display)
  • tool.retro.description (description to display)
  • tool.retro.result_file: “result.json”
  1. Update your main game file to write the result after the game ends:
  from retro import Game
  from my_agent import Agent
  import json

  game = Game([Agent()], {"score": 0})
  game.play()
  with open("result.json") as result_file:
    json.dump(game.state)

Write a Python script which will iterate over a bunch of Python projects, convert them from Poetry to uv, and commit and push the changes.

The script will accept one argument, a directory path. the script needs an optional “dryrun” flag, which will describe what is to be done without doing it. The directory will contain numerous subdirectories. Iterate over the subdirectories, and only consider those whose names start with “lab”, “project”, or “problemset”. For each such directory:

  • Invoke a subprocess with that directory as working directory. Check that this is a git repo. (Otherwise, report an error and skip the directory.)
  • Check if there are any staged or unstaged changes. (If so, report an error and skip the directory)
  • Bump the project version to 5.0.0.
  • Run “uvx migrate-to-uv”
  • Add all changes to git (“git add .”)
  • Commit with message “migrate to uv”
  • Push the changes (“git push”)