#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Numnastics - A number sorting puzzle game. The goal is to arrange numbers 1-9 in order by flipping sequences of numbers. """ import time import random from pygstormgames import pygstormgames from pyglet.window import key class Numnastics: """Main game class for Numnastics.""" def __init__(self): """Initialize the game.""" # Initialize game framework self.game = pygstormgames("Numnastics") self.currentIndex = 0 self.numberList = [] self.startTime = 0 self.tries = 0 self.playing = False def handle_game_input(self, keyInput): """Handle keyboard input during gameplay. Args: keyInput: Pyglet key symbol """ # Number keys (1-9) if key._1 <= keyInput <= key._9: number = str(keyInput - key.NUMBER_0) # Convert key code to string try: self.currentIndex = self.numberList.index(number) self.game.speech.speak(self.numberList[self.currentIndex]) except ValueError: self.currentIndex = -1 self.game.sound.play_sound('error') # Navigation elif keyInput in (key.LEFT, key.UP): if self.currentIndex > 0: self.currentIndex -= 1 self.game.speech.speak(self.numberList[self.currentIndex]) elif keyInput in (key.RIGHT, key.DOWN): if self.currentIndex < len(self.numberList) - 1: self.currentIndex += 1 self.game.speech.speak(self.numberList[self.currentIndex]) # Speak remaining sequence elif keyInput == key.SPACE: sequence = ' '.join(self.numberList[self.currentIndex:]) self.game.speech.speak(sequence) # Flip sequence elif keyInput == key.RETURN: if self.currentIndex != -1: # Reverse the subsequence from currentIndex to end reversedNumbers = self.numberList[self.currentIndex:] reversedNumbers.reverse() self.numberList[self.currentIndex:] = reversedNumbers self.tries += 1 self.game.sound.play_sound('flip') sequence = ' '.join(self.numberList[self.currentIndex:]) self.game.speech.speak(sequence) # Check for win condition if ''.join(self.numberList) == "123456789": self.game_won() return True # Exit to menu elif keyInput == key.ESCAPE: self.playing = False return True return False def game_won(self): """Handle win condition.""" self.playing = False endTime = round(time.time() - self.startTime, 2) minutes = int(endTime / 60) seconds = round(endTime % 60, 2) # Build victory message message = [f"Congratulations! You beat Numnastics in {self.tries} tries."] timeMsg = "minute" if minutes == 1 else "minutes" message.append(f"Your time was {minutes} {timeMsg} and {seconds} seconds.") # Display victory message self.game.display.display_text(message, self.game.speech) # Add score and play win sequence if self.game.scoreboard.check_high_score(): self.game.scoreboard.add_high_score() try: self.game.sound.cut_scene('win') except: pass def run(self): """Main game loop.""" while True: # Show main menu and handle selection choice = self.game.menu.game_menu() if choice == "play": self.start_game() def start_game(self): """Start a new game.""" self.playing = True self.currentIndex = 0 self.tries = 0 self.startTime = time.time() # Initialize shuffled numbers self.numberList = list("123456789") random.shuffle(self.numberList) # Stop menu music and speak initial sequence self.game.sound.pause_bgm() self.game.speech.speak(' '.join(self.numberList)) # Define valid keys for the game validKeys = [ key.ESCAPE, key.RETURN, key.SPACE, key.LEFT, key.RIGHT, key.UP, key.DOWN, key._1, key._2, key._3, key._4, key._5, key._6, key._7, key._8, key._9 ] while self.playing: keyPress, _ = self.game.wait(validKeys) if self.handle_game_input(keyPress): break if __name__ == "__main__": game = Numnastics() game.run()