From 74bb1a6bf604183a087f8defbd6962eb8850dded Mon Sep 17 00:00:00 2001 From: Dominic DiTaranto Date: Thu, 28 Aug 2025 17:24:30 -0400 Subject: [PATCH] improvements and stuff you know --- main.py | 226 +++++++++++++++++++++++++++++++++++++------------------- maps.py | 52 +++++++++++-- 2 files changed, 195 insertions(+), 83 deletions(-) diff --git a/main.py b/main.py index 1d896ac..dfaa63d 100644 --- a/main.py +++ b/main.py @@ -2,27 +2,42 @@ import os from pynput import keyboard -from maps import levels, logo +from maps import levels, logo, lose, win, help -# TODO: reset option with point loss -# TODO: actually give points -# TODO: only allow 3 resets then gameover -# TODO: win + loss screens (just simple text under map or something) -# TODO: ^^ maybe cute emojis for win and loss screens -# TODO: Create more maps -STATS = { - 'lives': 3, - 'points': 0, - 'total_moves': 0, - 'level_moves': {} -} +class Game: + def __init__(self): + self.map_instance = None + self.level = 0 + self.lives = 3 + self.points = 0 + self.total_moves = 0 + self.level_moves = {} + + def initialize_level(self): + self.map_instance = Map() + self.map_instance.generate_map_array() + self.loop() + + def loop(self): + while self.map_instance.break_condition: + self.map_instance.display() + self.map_instance.wait_for_input() + self.map_instance.check_win_condition() + + self.initialize_level() + + def handle_points(self, points): + self.points += points + if self.points + points < 0: + self.points = 0 class Map: - def __init__(self, level=1): - self.level = level - self.level_map = levels[self.level - 1] + def __init__(self): + self.level = g.level + self.level_map = levels[self.level][0] + self.level_par = levels[self.level][1] self.map_array = [] self.storage_locations = [] @@ -33,10 +48,14 @@ class Map: self.previous_element = ' ' self.win = False + self.lose = False self.break_condition = True + self.total_win = g.level + 1 == len(levels) + self.final_points_given = False + def generate_map_array(self): - STATS['level_moves'][self.level] = 0 + g.level_moves[self.level] = 0 level_array = self.level_map.split('\n') @@ -58,60 +77,82 @@ class Map: self.map_array.append(row_elements) def display(self): + if self.total_win and self.win and not self.final_points_given: + self.final_points_given = True + g.handle_points(self.calculate_points()) + os.system('clear') for storage_location in self.storage_locations: if self.map_array[storage_location[0]][storage_location[1]] == ' ': self.map_array[storage_location[0]][storage_location[1]] = '.' print(logo) - print(f' lvl: {self.level} | mvs: {STATS["level_moves"][self.level]} | pts: {STATS["points"]}') - for row in self.map_array: - print('\t', ''.join(row)) - - if self.win: - print('\n\n NICE! Press [w] to continue!') + print(f'lvl: {g.level} | mvs: {g.level_moves[self.level]} | pts: {g.points} | lives: {g.lives}') + + if self.lose: + print(lose) + elif self.total_win and self.win: + print(win) else: - print('\n\n h = ← | j = ↓ | k = ↑ | l = →') + for row in self.map_array: + print('\t', ''.join(row)) + + if self.total_win: + print('\n\n Press [r] to to play again or [q] to quit') + elif self.win: + print('\n\n NICE! Press [w] to continue!') + elif self.lose: + print('\n\n Press [r] to retry') + else: + print('\n\npress [r] to reset the map') def on_release(self, key): self.listener = None if 'char' in dir(key): - if key.char == 'h': - self.move('left') - if key.char == 'l': - self.move('right') - if key.char == 'j': - self.move('down') - if key.char == 'k': - self.move('up') - if self.win: - if key.char == 'w': - self.break_condition = False + if key.char == 'q': + self.quit() + if key.char == '?': + os.system('clear') + print(help) + response = input('Back to the game? Press any key to contiue: ') + os.system('clear') + + if (self.total_win and self.win) or self.lose: + if key.char == 'r': + self.retry() + else: + if key.char == 'h' or key.char == '4': + self.move('left') + if key.char == 'l' or key.char == '6': + self.move('right') + if key.char == 'j' or key.char == '2': + self.move('down') + if key.char == 'k' or key.char == '8': + self.move('up') + if key.char == 'y' or key.char == '7': + self.move('up left') + if key.char == 'u' or key.char == '9': + self.move('up right') + if key.char == 'b' or key.char == '1': + self.move('down left') + if key.char == 'n' or key.char == '3': + self.move('down right') + if key.char == 'r': + self.reset_level() + if self.win: + if key.char == 'w': + self.win_level() return False def wait_for_input(self): - with keyboard.Listener(on_release=self.on_release) as self.listener: + with keyboard.Listener(on_press=self.on_release) as self.listener: self.listener.join() def move(self, direction): - STATS['level_moves'][self.level] += 1 - STATS['total_moves'] += 1 + g.level_moves[self.level] += 1 + g.total_moves += 1 - tmp_player_x = self.player_x - tmp_player_y = self.player_y - - if direction == 'right' or direction == 'left': - - if direction == 'right': - tmp_player_x += 1 - else: - tmp_player_x -= 1 - - if direction == 'up' or direction == 'down': - if direction == 'down': - tmp_player_y += 1 - else: - tmp_player_y -= 1 + tmp_player_x, tmp_player_y = self.calculate_future_position(self.player_x, self.player_y, direction) future_position = self.map_array[tmp_player_y][tmp_player_x] @@ -128,22 +169,23 @@ class Map: self.player_x = tmp_player_x self.player_y = tmp_player_y + def calculate_future_position(self, x, y, direction): + dir_list = direction.split(' ') + + if 'right' in dir_list: + x += 1 + elif 'left' in dir_list: + x -= 1 + + if 'down' in dir_list: + y += 1 + elif 'up' in dir_list: + y -= 1 + + return x, y + def push_boulder(self, tmp_player_y, tmp_player_x, direction): - tmp_boulder_x = tmp_player_x - tmp_boulder_y = tmp_player_y - - if direction == 'right' or direction == 'left': - - if direction == 'right': - tmp_boulder_x += 1 - else: - tmp_boulder_x -= 1 - - if direction == 'up' or direction == 'down': - if direction == 'down': - tmp_boulder_y += 1 - else: - tmp_boulder_y -= 1 + tmp_boulder_x, tmp_boulder_y = self.calculate_future_position(tmp_player_x, tmp_player_y, direction) future_position = self.map_array[tmp_boulder_y][tmp_boulder_x] @@ -161,14 +203,46 @@ class Map: if (yidx, xidx) not in self.storage_locations: self.win = False + def win_level(self): + if not self.total_win: + g.handle_points(self.calculate_points()) + g.level += 1 + self.break_condition = False + + def calculate_points(self): + multiplier = 1 + penality = 0 + + if g.level_moves[g.level] < self.level_par: + multiplier = 1.5 + elif g.level_moves[g.level] == self.level_par: + multiplier = 1.2 + elif g.level_moves[g.level] > self.level_par: + penality = (g.level_moves[g.level] - self.level_par) * 0.1 + + return (10 - penality) * multiplier + + def reset_level(self): + g.lives -= 1 + g.handle_points(-3.5) + if g.lives <= 0: + self.lose = True + else: + self.break_condition = False + + def retry(self): + global g + g = Game() + g.initialize_level() + + def quit(self): + os.system('clear') + response = input('Are you sure you want to quit? [Y/N]: ')[-1] + if response.lower() == 'y': + os.system('clear') + os._exit(1) if __name__ == '__main__': - for level in range(len(levels)): - m = Map(level + 1) - m.generate_map_array() - while m.break_condition: - m.display() - m.wait_for_input() - m.check_win_condition() - + g = Game() + g.initialize_level() os.system('clear') diff --git a/maps.py b/maps.py index 2d477bd..5c5113d 100644 --- a/maps.py +++ b/maps.py @@ -1,8 +1,4 @@ -logo = ''' -█▀█ █▄█ █▀ █▀█ █▄▀ █▀█ █▄▄ ▄▀█ █▄░█ -█▀▀ ░█░ ▄█ █▄█ █░█ █▄█ █▄█ █▀█ █░▀█ -''' - +level_1_par = 8 level_1 = ''' ############# # # @@ -11,6 +7,7 @@ level_1 = ''' ############# ''' +level_2_par = 18 level_2 = ''' ############# #. # @@ -19,8 +16,49 @@ level_2 = ''' ############# ''' +level_3_par = 27 +level_3 = ''' +############# +# ####### +#@ 00 . # +# . # +################### +''' + levels = [ - level_1, - level_2 + (level_1, level_1_par), + (level_2, level_2_par), + (level_3, level_3_par), ] +logo = ''' +█▀█ █▄█ █▀ █▀█ █▄▀ █▀█ █▄▄ ▄▀█ █▄░█ +█▀▀ ░█░ ▄█ █▄█ █░█ █▄█ █▄█ █▀█ █░▀█ +''' + +lose = ''' +█▄█ █▀█ █░█   █░░ █▀█ █▀ █▀▀ +░█░ █▄█ █▄█   █▄▄ █▄█ ▄█ ██▄ +''' + +win = ''' +█▄█ █▀█ █░█   █░█░█ █ █▄░█ +░█░ █▄█ █▄█   ▀▄▀▄▀ █ █░▀█ +''' + +help = r''' +Welcome to PYSOKOBAN! +The object of the game is to move all of the boulders to specific storage +positions in the shortest amount of moves possible. + + KEY MOVEMENT ++===========================================+ +|_symbol_|_meaning_|| y k u | 7 8 9 | +| @ | you || \ | / | \ | / | +| # | wall || h- . -l | 4- . -6 | +| 0 | boulder || / | \ | / | \ | +| . | storage || b j n | 1 2 3 | ++===========================================+ + +If you like my stuff visit my website: https://domdit.com +'''