numnastics/numnastics.py
2025-02-23 21:22:11 -05:00

154 lines
4.8 KiB
Python
Executable File

#!/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()