diff --git a/.gitignore b/.gitignore index e8d832f..cec742b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ .venv/ __pycache__/ - *.pyc + +*.log + Map/*.json **/*pkl* diff --git a/classes/GameBoard.py b/classes/GameBoard.py index c7fa33d..0ec52bb 100644 --- a/classes/GameBoard.py +++ b/classes/GameBoard.py @@ -1,30 +1,78 @@ from classes.SavedState import SavedState import my_helpers.myPickle as my_pickle -import os +from simple_term_menu import TerminalMenu +from tabulate import tabulate +import logging +import sys, os, re +LOGGING = logging.getLogger(__name__) class GameBoard: def __init__(self, config:dict, save_state_file:dict, map_file:dict): self.config = config self.save_state_file = save_state_file self.map_file = map_file - def create_character(self, player_config:dict): - name = input("Enter Character Name: ") + def make_dict_list_into_table(self, dict_list:dict, change_by_key=None, ignore_keys:list[str]=[]): + dict_keys = list(dict_list.keys()) + keys = list(dict_list[dict_keys[0]].keys()) + table = [dict_keys] - species = list(player_config["species"].keys()) - print(species) + for key in keys: + row = [] + if not key in ignore_keys: + row.append(key) + for element in dict_list.values(): + if change_by_key != None: + element[key] = change_by_key(key, element) - types = [ x["name"] for x in player_config["types"] ] - print(types) + row.append(element[key]) + table.append(row) - species_selected = player_config["species"]["Gnoll"] - species_selected["name"] = "Gnoll" + return tabulate(table, headers='firstrow', tablefmt='grid') + + def change_character_key(self, key, element): + if key == "fixed_type": + if not element[key]: + return None + + return element[key] + + def print_story(self, story:str): + print(story) + + def create_character(self, player_config:dict, message:str): + self.print_story(message) + while True: + try: + characte_name = input("Enter Character Name: ") + if re.match("[a-zA-Z]", characte_name): + break + except KeyboardInterrupt as e: + LOGGING.debug(e) + sys.exit(1) + + print(self.make_dict_list_into_table(player_config["species"], change_by_key=lambda key, element: self.change_character_key(key, element))) + select_species = list(player_config["species"].keys()) + m = TerminalMenu(select_species, title='Select a Species') + selection = m.show() + + characte_species = player_config["species"][select_species[selection]] + characte_species["name"] = select_species[selection] + + if not characte_species["fixed_type"]: + types = [ x["name"] for x in player_config["types"] ] + m = TerminalMenu(types, title='Select a Type') + selection = m.show() + + characte_type = (types[selection]) + else: + characte_type = characte_species["fixed_type"] return { - "name": name, - "species": species_selected, - "type": types + "name": characte_name, + "species": characte_species, + "type": characte_type } def find_save_state(self): @@ -32,27 +80,63 @@ class GameBoard: saved_state:SavedState = self.load_from_file(self.save_state_file) else: saved_state = SavedState() - player = self.create_character(self.config["player"]) + player = self.create_character(self.config["player"], self.config["create_character_message"]) saved_state.add_player(player) self.save_to_file(saved_state, self.save_state_file) + print() self.map = self.load_from_file(self.map_file) self.saved_state = saved_state return saved_state def load_from_file(self, file_options): + LOGGING.debug(f"Loading from file: {file_options}") if os.path.exists(file_options["path"]): with open(file_options["path"], "rb") as f: data = my_pickle.load(f, file_options['compression'], None) + LOGGING.debug(f"Loaded {data}") return data else: raise FileNotFoundError(f"Could not load map file: {file_options['path']}") def save_to_file(self, obj, file_options): + LOGGING.debug(f"Saving Object {obj} To file: {file_options}") os.makedirs(os.path.dirname(file_options["path"]), exist_ok=True) with open(file_options["path"], "wb") as f: my_pickle.dump(obj, f, file_options['compression'], None) - def get_world(self): - return self.map[self.saved_state.story_position]["World"][self.saved_state.story_world_index] \ No newline at end of file + def by_the_place(self): + is_by_a_place = self.saved_state.get_place() + LOGGING.debug(is_by_a_place) + if is_by_a_place: + return self.map[self.saved_state.get_chapter()]["Places"][is_by_a_place] + + return self.map[self.saved_state.get_chapter()]["World"][self.saved_state.get_story_moves()] + + def replace_keyword_into_place_story(self, place:dict): + story:str = place['story'] + story.replace("SPECIES", self.saved_state.get_player().get_species_name()) + story.replace("CHARACTER_NAME", self.saved_state.get_player().get_name()) + + return story + + def user_input(self): + while True: + try: + place = self.by_the_place() + LOGGING.debug(place) + + print(self.replace_keyword_into_place_story(place)) + print() + choice = input(f"{place['name']} || What do you like to do? ") + if choice != None: + break + + LOGGING.debug(choice) + self.check_user_input(choice) + except KeyboardInterrupt: + break + + def check_user_input(self, choice:str): + pass diff --git a/classes/MapObject/Home.py b/classes/MapObject/Home.py new file mode 100644 index 0000000..8f62515 --- /dev/null +++ b/classes/MapObject/Home.py @@ -0,0 +1,4 @@ + +class Home: + def __init__(self): + self.items = [] diff --git a/classes/Player.py b/classes/Player.py index b3dfb43..9b9d257 100644 --- a/classes/Player.py +++ b/classes/Player.py @@ -1,3 +1,6 @@ +import logging + +LOGGING = logging.getLogger(__name__) class Player: def __init__(self, name:str, type:dict, species:dict): self.name = name @@ -9,6 +12,12 @@ class Player: def get_inventory(self): return self.inventory + def get_species_name(self): + return self.species['name'] + + def get_name(self): + return self.name + def attack(self): pass diff --git a/classes/SavedState.py b/classes/SavedState.py index 30306e9..0f9eefa 100644 --- a/classes/SavedState.py +++ b/classes/SavedState.py @@ -1,13 +1,19 @@ +import logging + from classes.Player import Player from classes.MapObject.Home import Home +LOGGING = logging.getLogger(__name__) class SavedState: def __init__(self, story_position:str="The Beginning"): self.home = Home() - self.story_position = story_position - self.story_world_index = 0 + self.story = { + "chapter": story_position, + "story_moves": 0, + "place": None + } def add_player(self, player:dict): self.player = Player(player["name"], player["type"], player["species"]) @@ -17,3 +23,15 @@ class SavedState: def get_player(self): return self.player + + def get_chapter(self): + return self.story["chapter"] + + def get_story_moves(self): + return self.story["story_moves"] + + def get_place(self): + return self.story["place"] + + def __str__(self): + return f"{self.__class__.__name__} | Home: {self.home}\nStory: {self.story}" \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 9b40642..953950a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,7 @@ +adventurelib==1.2.1 cffi==1.15.1 cryptography==40.0.2 pip-autoremove==0.10.0 pycparser==2.21 +simple-term-menu==1.6.1 +tabulate==0.9.0 diff --git a/run.py b/run.py index 1ac913a..9653eb0 100644 --- a/run.py +++ b/run.py @@ -1,12 +1,18 @@ from classes.GameBoard import GameBoard from json import load as json_load -import lzma +import logging +import lzma, os if __name__ == '__main__': with open("config.json", "r") as f: CONFIG = json_load(f) + if CONFIG["logging"]["enabled"]: + os.makedirs(CONFIG['logging']['file']['path'], exist_ok=True) + logging.basicConfig(filename=f"{CONFIG['logging']['file']['path']}/{CONFIG['logging']['file']['name']}", encoding='utf-8', level=logging.DEBUG) + LOGGING = logging.getLogger(__name__) + SAVE_STATE_FILE = { "path": f"{CONFIG['save_file']['path']}/{CONFIG['save_file']['filename']}", "compression": lzma, @@ -19,8 +25,7 @@ if __name__ == '__main__': } game_board = GameBoard(CONFIG, SAVE_STATE_FILE, MAP_FILE) - saved_state = game_board.find_save_state() + game_board.find_save_state() + game_board.user_input() - print("Story Pos:", game_board.get_world()) - print(game_board.map) - print(saved_state.get_player()) + game_board.save_to_file(game_board.saved_state, game_board.save_state_file)