This repository has been archived on 2022-12-03. You can view files and clone it, but cannot push or open issues or pull requests.
texty/lib/game.py

225 lines
11 KiB
Python
Raw Permalink Normal View History

2021-11-02 17:40:54 +01:00
import yaml
from yaml.loader import SafeLoader
2022-03-24 18:20:39 +01:00
from colorama import Fore, Back
2022-01-25 17:16:07 +01:00
import re
2022-05-04 10:16:30 +02:00
from lib.item import Item
2022-03-24 18:20:39 +01:00
2022-04-05 11:59:11 +02:00
from lib.menu import HasItemDialogue, MenuManager
2022-02-04 19:35:38 +01:00
from .save import SaveManager
2022-01-26 09:23:30 +01:00
from .ascii import AsciiAnimation
2022-05-02 11:32:40 +02:00
from .fight import *
2022-01-25 17:16:07 +01:00
from time import sleep
2022-03-24 18:20:39 +01:00
from os import system
2021-11-02 17:40:54 +01:00
2022-05-04 14:26:32 +02:00
class Game: # Hlavní třída, uchovává údaje o hře
2022-05-04 10:16:30 +02:00
def __init__(self,data:dict,lang):
2022-05-04 14:26:32 +02:00
self.name = data["meta"]["name"] # Název hry
self.author = data["meta"]["creator"] # Název tvůrce
self.current = "start" # Aktuální node
self.nodes = {} # Seznam všech
self.inventory = [] # Hráčův inventář
self.id = data["meta"]["id"] # "Unikátní" ID hry
self.lang = lang # Řetězce pro vybraný jazyk
self.save = SaveManager(self.id,self.lang) # Systém ukládání
self.equipped = {"weapon":None,"armor":None} # Předměty vybavené hráčem
self.enemies = {} # Seznam všech nepřátel
2022-04-19 12:36:05 +02:00
if "equippable" in data["meta"].keys():
2022-05-04 14:26:32 +02:00
self.equippable = [] # Předměty, které si hráč může vybavit
2022-04-19 12:36:05 +02:00
for item in data["meta"]["equippable"]:
name = list(item.keys())[0]
if "def" in item[name].keys() and "atk" in item[name].keys():
2022-05-04 14:26:32 +02:00
self.equippable.append(Item(item[name]["name"],item[name]["atk"],item[name]["def"]))
2022-04-19 12:36:05 +02:00
elif "def" in item[name].keys():
2022-05-04 14:26:32 +02:00
self.equippable.append(Item(name=item[name]["name"],defense=item[name]["def"]))
2022-04-19 12:36:05 +02:00
elif "atk" in item[name].keys():
2022-05-04 14:26:32 +02:00
self.equippable.append(Item(item[name]["name"],item[name]["atk"]))
if("starter" in item[name].keys()): # Pokud je starter, přidáme hráčí na začátku do inventáře
2022-04-19 12:36:05 +02:00
if item[name]["starter"]:
2022-05-16 15:56:11 +02:00
i = next((x for x in self.equippable if x.name == item[name]["name"])) # V případě, že nenalezne předmět, vrací None
2022-04-19 12:36:05 +02:00
self.inventory.append(i)
self.equipped[i.type] = i
self.save.equipped[i.type]
2022-05-02 11:32:40 +02:00
if "enemies" in data["meta"].keys():
2022-05-04 14:26:32 +02:00
# Načte nepřátele
2022-05-02 11:32:40 +02:00
for en in data["meta"]["enemies"]:
name = list(en.keys())[0]
self.enemies[name] = {"name":en["name"],"hp":en["hp"],"attacks":en["attacks"],"def":en["def"]}
2022-05-04 14:26:32 +02:00
for k in data["game"]: # načte všechny nody
2021-11-26 22:13:30 +01:00
self.nodes.update({k:data["game"][k]})
2021-11-02 17:40:54 +01:00
2022-05-04 14:26:32 +02:00
def main_menu(self): # Zobrazí hlavní menu
2022-02-04 19:35:38 +01:00
l = self.save.load()
if not l:
2022-05-04 14:26:32 +02:00
# V případě nové hry
2022-03-24 18:20:39 +01:00
m = MenuManager([self.lang['start'],self.lang['options'],self.lang['quit']],f"{self.name}\n{self.lang['game_by'].replace('$author',self.author)}")
selection = m.selected
2022-02-23 19:28:50 +01:00
system("cls||clear")
2022-05-04 14:26:32 +02:00
if(selection == 0): # Začít
2022-02-23 19:28:50 +01:00
self.print_text()
2022-05-04 14:26:32 +02:00
elif(selection == 1): # Nastavení
2022-02-23 19:28:50 +01:00
self.settings_menu()
2022-05-04 14:26:32 +02:00
elif(selection == 2): # Vypnout
2022-03-23 14:22:12 +01:00
print(self.lang['quitting'])
2022-02-23 19:28:50 +01:00
exit()
2022-05-04 14:26:32 +02:00
else: # V případě uložené hry zobrazí "Pokračovat"
m = MenuManager([self.lang['continue'],self.lang['new_game'],self.lang['options'],self.lang['quit']],f"{self.name}\n{self.lang['game_by'].replace('$author',self.author)}")
2022-03-24 18:20:39 +01:00
selection = m.selected
2022-02-04 19:35:38 +01:00
system("cls||clear")
2022-03-24 18:20:39 +01:00
if(selection == 0):
2022-02-04 19:35:38 +01:00
self.current = self.save.currentPrompt
self.inventory = self.save.inventory
self.equipped = self.save.equipped
2022-02-04 19:35:38 +01:00
self.print_text()
2022-03-24 18:20:39 +01:00
elif(selection == 1):
2022-02-04 19:35:38 +01:00
self.print_text()
2022-03-24 18:20:39 +01:00
elif(selection == 2):
2022-02-23 19:28:50 +01:00
self.settings_menu()
2022-03-24 18:20:39 +01:00
elif(selection == 3):
print(self.lang['quitting'])
2022-02-04 19:35:38 +01:00
exit()
2022-05-04 14:26:32 +02:00
def settings_menu(self): # Zobrazí nastavení
2022-03-24 18:20:39 +01:00
m = MenuManager([self.lang['lang'],self.lang['back']],self.lang['options'])
selection = m.selected
if(selection == 0):
m = MenuManager(["English","Česky",self.lang['back']],self.lang['lang'])
selection = m.selected
2022-02-04 19:35:38 +01:00
system("cls||clear")
2022-03-24 18:20:39 +01:00
if(selection == 0):
2022-02-04 19:35:38 +01:00
with open("./saves/lang","w") as f:
f.write("en")
2022-03-24 18:20:39 +01:00
elif(selection == 1):
2022-02-04 19:35:38 +01:00
with open("./saves/lang","w") as f:
f.write("cz")
self.settings_menu()
2022-02-23 19:28:50 +01:00
else:
self.main_menu()
2021-11-02 17:40:54 +01:00
2022-05-04 14:26:32 +02:00
def print_text(self): # Zobrazí hráči aktuální node
2022-02-23 19:28:50 +01:00
system("cls||clear")
2022-05-04 14:26:32 +02:00
if "add_item" in self.nodes[self.current].keys(): # V případě, že máme přidat hráči věc do inventáře
2022-04-06 09:42:47 +02:00
item = self.nodes[self.current]['add_item']
2022-05-04 14:26:32 +02:00
for i in self.equippable:
if i.name == item: # Pokud lze vybavit, změnit na instanci třídy Item
item = i
2022-04-06 10:03:21 +02:00
if item not in self.inventory:
self.inventory.append(item)
print(self.inventory)
system("clear||cls")
print(f"{self.lang['acquire'].replace('$item',f'{Fore.CYAN}{item}{Fore.RESET}')}")
sleep(3)
system("clear||cls")
2022-05-04 14:26:32 +02:00
animated = re.search(r"(?!{).+(?=})",self.nodes[self.current]["text"]) # Hledá kód pro vložení animovaného textu
2022-01-25 17:16:07 +01:00
if(animated != None):
self.print_animated(animated.group(0))
2022-05-04 14:26:32 +02:00
self.nodes[self.current]["text"] = self.nodes[self.current]["text"].replace("{"+animated.group(0)+"}","") # Odstraní kód z textu
2021-11-26 22:13:30 +01:00
if("actions" in self.nodes[self.current].keys()):
2022-05-04 14:26:32 +02:00
actions_desc = [] # uchovává text nodu, abychom jej nemuseli hledat v MenuManager
need_item = [] # pomáhá implementovat kontrolu potřebného předmětu
2022-03-24 18:20:39 +01:00
for option in self.nodes[self.current]["actions"]:
try:
actions_desc.append(self.nodes[option]["description"])
2022-04-05 11:59:11 +02:00
if "has_item" in self.nodes[option].keys():
need_item.append(self.nodes[option]["has_item"])
else:
need_item.append(None)
2022-04-06 10:03:21 +02:00
except Exception:
2022-03-24 18:20:39 +01:00
print(f"{Back.RED}{Fore.WHITE}{self.lang['no_action'].replace('$action',option)}{Fore.RESET}")
exit(1)
2022-04-05 11:59:11 +02:00
m = ""
2022-04-06 10:03:21 +02:00
actions_desc.extend([self.lang['inventory'],self.lang['quit']])
2022-05-04 14:26:32 +02:00
if(all(element == None for element in need_item) is False): # Pokud platí, musíme zkontrolovat, jestli hráč má předmět
2022-04-06 10:03:21 +02:00
need_item.extend([None, None])
2022-04-06 09:42:47 +02:00
m = HasItemDialogue(actions_desc,self.parse_colors(self.nodes[self.current]["text"]),self.inventory,need_item)
2022-05-04 14:26:32 +02:00
while need_item[m.selected] != None and all(element not in self.inventory for element in need_item[m.selected]): # Opakovat, dokud uživatel nevybere platný výběr
2022-04-06 09:42:47 +02:00
m = HasItemDialogue(actions_desc,self.parse_colors(self.nodes[self.current]["text"]),self.inventory,need_item)
2022-04-17 19:02:11 +02:00
if m.selected <= len(actions_desc)-3 and "has_item" in self.nodes[self.nodes[self.current]["actions"][m.selected]].keys():
2022-04-12 15:16:38 +02:00
for item in need_item[m.selected]:
self.inventory.remove(item)
2022-05-02 11:32:40 +02:00
elif "fight" in self.nodes[self.current].keys():
2022-05-04 14:26:32 +02:00
# Spustí boj
enemy = self.enemies[self.nodes[self.current]["fight"]] # Získá info o nepříteli
2022-05-04 10:16:30 +02:00
m = FightHandler(self.nodes[self.current]["text"],enemy["name"],enemy["hp"],enemy["def"],enemy["attacks"],self.lang,self.equipped,self.inventory)
input()
while m.hp > 0 and m.my > 0:
m.show()
2022-05-04 14:26:32 +02:00
m.rebind() # Znovu nastavuje klávesy, kvůli MenuManageru uvnitř show_inventory, který je maže
2022-05-02 11:32:40 +02:00
input()
2022-05-04 10:16:30 +02:00
system("cls||clear")
keyboard.remove_all_hotkeys()
self.equipped = m.equipped
self.save.equipped = m.equipped
2022-05-04 10:16:30 +02:00
if m.hp < 1:
2022-05-04 14:26:32 +02:00
# Nepřítel byl poražen
2022-05-04 10:16:30 +02:00
print(self.lang["defeated"].replace("$enemy",enemy["name"]))
2022-05-04 14:26:32 +02:00
sleep(3)
self.current = self.nodes[self.current]["actions"][0] # Přesune na první akci
2022-05-04 10:16:30 +02:00
self.print_text()
else:
# Hráč byl poražen
2022-05-04 10:16:30 +02:00
print(self.lang["defeat"].replace("$enemy",enemy["name"]))
2022-05-04 14:26:32 +02:00
sleep(3)
2022-05-04 10:16:30 +02:00
self.print_text()
2022-05-16 15:59:06 +02:00
return
2022-04-05 11:59:11 +02:00
else:
2022-04-06 09:42:47 +02:00
m = MenuManager(actions_desc,self.parse_colors(self.nodes[self.current]["text"]))
2022-03-24 18:20:39 +01:00
sel = m.selected
2022-05-04 14:26:32 +02:00
if(sel == len(actions_desc)-2): # Zobrazit inventář
2022-04-06 10:03:21 +02:00
self.show_inventory()
2022-05-04 14:26:32 +02:00
elif (sel == len(actions_desc)-1): # Uložit a ukončit
self.save.currentPrompt = self.current
2022-04-06 10:03:21 +02:00
self.save.inventory = self.inventory
self.save.save()
exit(0)
else:
self.current = self.nodes[self.current]["actions"][sel]
self.print_text()
2022-03-24 18:20:39 +01:00
else:
print(self.parse_colors(self.nodes[self.current]["text"]))
print("")
2022-01-25 17:16:07 +01:00
2022-05-04 14:26:32 +02:00
def show_inventory(self): # Zobrazí hráčův inventář
2022-04-06 10:03:21 +02:00
if len(self.inventory) == 0:
2022-04-19 12:36:05 +02:00
MenuManager([self.lang["return"]],f" {self.lang['inside_inv']} \n")
2022-04-06 10:03:21 +02:00
else:
s = ""
2022-05-16 15:56:11 +02:00
op = []
items = []
2022-04-06 10:03:21 +02:00
for i,item in enumerate(self.inventory):
2022-05-04 14:26:32 +02:00
if type(item) is Item: # Pokud je předmět třídy Item, zobrazit zda-li je vybaven nebo ne
if self.equipped["weapon"] == item or self.equipped["armor"] == item:
op.append(f"- {item.name} | {self.lang['equipped']}")
2022-05-04 10:16:30 +02:00
else:
2022-05-04 14:26:32 +02:00
op.append(f"- {item.name}")
2022-05-16 15:56:11 +02:00
items.append(item)
2022-04-06 10:03:21 +02:00
else:
2022-05-04 14:26:32 +02:00
if(i == len(self.inventory)): # poslední, nepřidávat newline
2022-05-04 10:16:30 +02:00
s += f"- {item}"
else:
s += f"- {item}\n"
2022-05-16 15:56:11 +02:00
items.append(None)
op.append(self.lang["return"])
2022-05-04 14:26:32 +02:00
m = MenuManager(op,f" {self.lang['inside_inv']} \n{s}")
if(m.selected != len(op)-1):
# Vybavit
2022-05-16 15:56:11 +02:00
i = items[m.selected]
2022-05-04 14:26:32 +02:00
self.equipped[i.type] = i
self.save.equipped[i.type] = i
2022-04-06 10:03:21 +02:00
self.print_text()
2022-05-04 14:26:32 +02:00
def print_animated(self,animid): # Zobrazí animaci
2022-01-26 09:23:30 +01:00
animation = AsciiAnimation()
animation.load_ascii(animid)
animation.play()
2022-01-25 17:30:09 +01:00
print()
2022-01-25 17:16:07 +01:00
2022-05-04 14:26:32 +02:00
def parse_colors(self,text:str) -> str: # Převádí kód na barvy v terminálu
2021-12-02 11:20:39 +01:00
newText = text.replace("&b",Fore.CYAN).replace("&c",Fore.RED).replace("&e", Fore.YELLOW).replace("&a",Fore.GREEN).replace("&9",Fore.BLUE).replace("&r",Fore.RESET).replace("&f",Fore.WHITE).replace("&5",Fore.MAGENTA).replace("\n",Fore.RESET + "\n") # replace color codes and newlines with colorama
2022-05-04 14:26:32 +02:00
newText += Fore.RESET # resetovat na konci
2021-11-26 22:13:30 +01:00
return newText
2022-05-04 14:26:32 +02:00
def load(file_path,lang): # Načte hru z YAML souboru
2022-05-16 15:56:11 +02:00
with open(file_path) as f:
data = yaml.load(f,Loader=SafeLoader)
g = Game(data,lang)
return g