325 lines
13 KiB
Python
325 lines
13 KiB
Python
import config.constants
|
|
import typing
|
|
import pygame
|
|
|
|
import logic.player
|
|
import logic.keyboardTools
|
|
import logic.generate
|
|
import logic.rewriter_sok
|
|
|
|
import solver.solver
|
|
import solver.pathNotFoundException
|
|
|
|
import map.entity_mapper as entity_mapper
|
|
import map.mapper as mapper
|
|
|
|
import interface.goback
|
|
|
|
|
|
class State:
|
|
quit = False
|
|
next_state = False
|
|
state_go_back = False
|
|
versus = None
|
|
do_generate_levels = False
|
|
dicGen = {"1": [8, 8, 2, 3, 1], "2": [9, 9, 3, 4, 2], "3": [10, 10, 4, 5, 2], "4": [15, 15, 6, 7, 2], "5": [
|
|
17, 17, 7, 8, 2], "6": [18, 18, 8, 9, 1], "7": [20, 20, 6, 7, 2], "8": [25, 25, 7, 8, 3], "9": [30, 30, 7, 10, 4]}
|
|
|
|
difficulty: typing.Union[str, None] = None
|
|
level: typing.Union[int, str, None] = None
|
|
players: typing.List[logic.player.Player] = []
|
|
|
|
situations = ('select_difficult', 'select_level', 'select_versus_mode', 'game')
|
|
situation = 0
|
|
|
|
inputs = {
|
|
"option_menu_difficulty": logic.keyboardTools.KeyboardTools.get_keys_event_from_choices(['g']),
|
|
"difficulty": logic.keyboardTools.KeyboardTools.get_keys_event_from_choices(['a', 'b', 'c', 'e']),
|
|
"levels": {
|
|
'a': logic.keyboardTools.KeyboardTools.get_keys_event_from_range(1, 9),
|
|
'b': logic.keyboardTools.KeyboardTools.get_keys_event_from_range(1, 3),
|
|
'c': logic.keyboardTools.KeyboardTools.get_keys_event_from_range(4, 6),
|
|
'e': logic.keyboardTools.KeyboardTools.get_keys_event_from_range(7, 9)
|
|
},
|
|
"versus": logic.keyboardTools.KeyboardTools.get_keys_event_from_choices(['a', 'b']),
|
|
}
|
|
|
|
@classmethod
|
|
def inputs_checker(cls, event, valid_inputs):
|
|
"""Check if the key the player press is valid or not"""
|
|
for valid_input in valid_inputs:
|
|
if event.key == getattr(pygame, valid_input) \
|
|
or (getattr(event, "unicode", None) and event.unicode.lower() == logic.keyboardTools.KeyboardTools.get_str_from_keyboard_event(valid_input).lower()):
|
|
return True
|
|
return False
|
|
|
|
@classmethod
|
|
def analizer(cls, events: list, textes=None):
|
|
"""Analize the events and modify the state class's variables in consequence"""
|
|
for event in events:
|
|
if event.type == pygame.QUIT:
|
|
cls.quit = True
|
|
elif event.type == pygame.KEYDOWN:
|
|
if event.key == pygame.K_ESCAPE:
|
|
cls.state_go_back = True
|
|
else:
|
|
if not cls.analizer_menu(event):
|
|
cls.analizer_game(event)
|
|
elif event.type == pygame.MOUSEBUTTONUP:
|
|
cls.analizer_menu_mouse(event, textes)
|
|
elif event.type == config.constants.COMPUTER_EVENT:
|
|
cls.analizer_game_from_computer()
|
|
|
|
@classmethod
|
|
def get_letter_pointed_from_mouse(cls, event, textes, attr):
|
|
"""Change the variables "state_go_back" and "next_state" according to what the mouse is pointing at"""
|
|
for texte in textes:
|
|
if texte.rect.collidepoint(event.pos):
|
|
if isinstance(texte, interface.goback.GoBack):
|
|
cls.state_go_back = True
|
|
break
|
|
elif ':' in texte.texte:
|
|
command = texte.texte.split(":")[0].lower().strip()
|
|
command_pygame_key = logic.keyboardTools.KeyboardTools.get_keys_event_from_choices([command])[0]
|
|
if command_pygame_key in cls.inputs["option_menu_difficulty"]:
|
|
cls.do_generate_levels = True
|
|
else:
|
|
setattr(cls, attr, command)
|
|
cls.next_state = True
|
|
break
|
|
|
|
@classmethod
|
|
def analizer_menu_mouse(cls, event, textes):
|
|
"""Enable the player to choose a level and a game difficulty in the menu with the mouse pointer"""
|
|
if cls.situations[cls.situation][:6] != "select":
|
|
return False
|
|
|
|
if cls.difficulty is None:
|
|
cls.get_letter_pointed_from_mouse(event, textes, "difficulty")
|
|
elif cls.level is None:
|
|
for texte in textes:
|
|
if texte.rect.collidepoint(event.pos):
|
|
if isinstance(texte, interface.goback.GoBack):
|
|
cls.state_go_back = True
|
|
break
|
|
elif ':' in texte.texte:
|
|
try:
|
|
integer = int(texte.texte.split(":")[0].strip().lower()[-1])
|
|
cls.level = integer
|
|
cls.next_state = True
|
|
except ValueError:
|
|
pass
|
|
except IndexError:
|
|
pass
|
|
elif cls.versus is None:
|
|
cls.get_letter_pointed_from_mouse(event, textes, "versus")
|
|
|
|
return True
|
|
|
|
@classmethod
|
|
def get_unicode_letter_for_situation(cls, event, input_sector, attr):
|
|
"""Return the unicode of a given letter and make the 'next_state' variable True """
|
|
if cls.inputs_checker(event, cls.inputs[input_sector]):
|
|
integer = logic.keyboardTools.KeyboardTools.check_integer_keyboard(
|
|
event.unicode)
|
|
if integer is None:
|
|
if event.unicode.isalpha():
|
|
setattr(cls, attr, event.unicode.lower())
|
|
cls.next_state = True
|
|
|
|
@classmethod
|
|
def analizer_menu(cls, event):
|
|
"""Movidifed the State class considering what the player choose in the menu interface"""
|
|
if cls.situations[cls.situation][:6] != "select":
|
|
return False
|
|
if cls.difficulty is None:
|
|
if cls.inputs_checker(event, cls.inputs["option_menu_difficulty"]):
|
|
cls.do_generate_levels = True
|
|
else:
|
|
cls.get_unicode_letter_for_situation(event, "difficulty", "difficulty")
|
|
elif cls.level is None:
|
|
if cls.inputs_checker(event, cls.inputs['levels'][cls.difficulty]):
|
|
integer = logic.keyboardTools.KeyboardTools.check_integer_keyboard(
|
|
event.unicode)
|
|
if integer is not None:
|
|
cls.level = integer
|
|
cls.next_state = True
|
|
elif cls.versus is None:
|
|
cls.get_unicode_letter_for_situation(event, "versus", "versus")
|
|
return True
|
|
|
|
@classmethod
|
|
def generate_grids_for_levels(cls):
|
|
"""Call the Generate class to create a random level according to the parameters we
|
|
decided for each level difficulty (in the dicGen dictionnary)"""
|
|
i = 1
|
|
while i <= 9:
|
|
grid = logic.generate.Generate.gridGen(
|
|
cls.dicGen[str(i)][0],
|
|
cls.dicGen[str(i)][1],
|
|
cls.dicGen[str(i)][2],
|
|
cls.dicGen[str(i)][3],
|
|
cls.dicGen[str(i)][4])
|
|
|
|
_mapper = mapper.Mapper("", grid)
|
|
_player = logic.player.Player(entity_mapper.EntityMapper(_mapper, i, initsprites=False))
|
|
_solver = solver.solver.Solver(_player)
|
|
|
|
try:
|
|
_solver.get_full_path()
|
|
yield grid
|
|
except solver.pathNotFoundException.Path_not_found_exception:
|
|
i -= 1
|
|
|
|
i += 1
|
|
|
|
@classmethod
|
|
def generate_levels(cls):
|
|
"""Call the Overwrite class to erase all the levels existing and replace them by random generated levels"""
|
|
overwriter = logic.rewriter_sok.Overwrite()
|
|
grids = [grid for grid in cls.generate_grids_for_levels()]
|
|
for i, grid in enumerate(grids, start=1):
|
|
overwriter.writer(grid, str(i))
|
|
cls.do_generate_levels = False
|
|
|
|
@classmethod
|
|
def analizer_game(cls, event):
|
|
"""This fonction analize all the player's actions during a game and act consequently"""
|
|
if cls.situations[cls.situation] != "game":
|
|
return False
|
|
|
|
for player in cls.players:
|
|
cls.game_traitment(player)
|
|
if player.inputs:
|
|
valid_inputs = logic.keyboardTools.KeyboardTools.get_keys_event_from_choices(
|
|
player.inputs)
|
|
if cls.inputs_checker(event, valid_inputs):
|
|
player.player_analizer(event)
|
|
if cls.versus == "a" and event.key == pygame.K_o and player.entity_mapper.position == 1:
|
|
player.restart_player_game()
|
|
|
|
if cls.versus == "a" and any((player.had_moved for player in cls.players)):
|
|
cls.analizer_game_from_computer()
|
|
if cls.players[0].interrupt and not cls.players[1].interrupt:
|
|
pygame.time.set_timer(config.constants.COMPUTER_EVENT, 500)
|
|
|
|
if all((player.interrupt for player in cls.players)):
|
|
cls.next_state = True
|
|
return True
|
|
|
|
@classmethod
|
|
def analizer_game_from_computer(cls):
|
|
"""All the computer to finish the game alone if the player beats him"""
|
|
if cls.situations[cls.situation] != "game":
|
|
return False
|
|
|
|
cls.game_traitment(cls.players[1])
|
|
cls.players[1].move_from_full_path()
|
|
|
|
if cls.players[0].interrupt:
|
|
if all((player.interrupt for player in cls.players)):
|
|
cls.next_state = True
|
|
|
|
return True
|
|
|
|
@classmethod
|
|
def go_back(cls):
|
|
"""Make the game one step back """
|
|
cls.leave_situation(-1)
|
|
if cls.situation < 0:
|
|
cls.situation = 0
|
|
cls.quit = True
|
|
|
|
if not cls.situations[cls.situation] == "select_versus_mode":
|
|
cls.state_go_back = False
|
|
|
|
@classmethod
|
|
def leave_situation(cls, direction):
|
|
"""Change the situation variable 'situation' to change the 'cls.situations[cls.situations]' value.
|
|
Also impact the 'level', 'difficulty', and 'versus' vraibles"""
|
|
if cls.situations[cls.situation] == "select_level":
|
|
if direction == -1:
|
|
cls.level = None
|
|
cls.difficulty = None
|
|
elif cls.situations[cls.situation] == "select_versus_mode":
|
|
if direction == -1:
|
|
cls.versus = None
|
|
cls.level = None
|
|
elif cls.situations[cls.situation] == "game":
|
|
for player in cls.players:
|
|
player.entity_mapper.sprites.empty()
|
|
cls.players.clear()
|
|
|
|
if cls.versus == "a":
|
|
pygame.time.set_timer(config.constants.COMPUTER_EVENT, 0)
|
|
|
|
if direction == 1:
|
|
cls.level = None
|
|
cls.difficulty = None
|
|
cls.versus = None
|
|
|
|
if direction == -1:
|
|
cls.situation -= 1
|
|
else:
|
|
cls.situation = (cls.situation + 1) % len(cls.situations)
|
|
|
|
@classmethod
|
|
def generate_players(cls):
|
|
""""""
|
|
for player in cls.players:
|
|
player.entity_mapper.sprites.empty()
|
|
cls.players.clear()
|
|
|
|
if cls.difficulty == "a" and cls.level is not None:
|
|
grid = logic.generate.Generate.gridGen(
|
|
cls.dicGen[str(cls.level)][0],
|
|
cls.dicGen[str(cls.level)][1],
|
|
cls.dicGen[str(cls.level)][2],
|
|
cls.dicGen[str(cls.level)][3],
|
|
cls.dicGen[str(cls.level)][4]
|
|
)
|
|
|
|
_mapper = mapper.Mapper("", grid)
|
|
elif cls.level is not None:
|
|
_mapper = mapper.Mapper("level" + str(cls.level) + ".sok")
|
|
|
|
if cls.level is not None:
|
|
for i in range(2):
|
|
_player = logic.player.Player(
|
|
entity_mapper.EntityMapper(_mapper, i))
|
|
cls.players.append(_player)
|
|
|
|
@classmethod
|
|
def select_game_traitment(cls):
|
|
""""""
|
|
cls.generate_players()
|
|
if cls.versus == "a" and cls.players:
|
|
while True:
|
|
cls.players[1].inputs = []
|
|
_solver = solver.solver.Solver(cls.players[1])
|
|
if cls.difficulty == "a":
|
|
try:
|
|
_solver.get_full_path()
|
|
break
|
|
except solver.pathNotFoundException.Path_not_found_exception:
|
|
cls.generate_players()
|
|
continue
|
|
else:
|
|
try:
|
|
_solver.get_full_path()
|
|
break
|
|
except solver.pathNotFoundException.Path_not_found_exception:
|
|
cls.next_state = True
|
|
|
|
cls.next_state = True
|
|
|
|
@classmethod
|
|
def game_traitment(cls, player):
|
|
"""Reset the player statuts"""
|
|
if player.restarted:
|
|
player.restarted = False
|
|
if player.full_path_temoin:
|
|
player.full_path = player.full_path_temoin[:]
|
|
|
|
player.reset_status()
|