154 lines
4.8 KiB
Python
154 lines
4.8 KiB
Python
|
#!/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()
|