improvements and stuff you know

This commit is contained in:
Dominic DiTaranto 2025-08-28 17:24:30 -04:00
parent a19d8a5cda
commit 74bb1a6bf6
2 changed files with 195 additions and 83 deletions

226
main.py
View file

@ -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')

52
maps.py
View file

@ -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
'''