2021-11-02 17:40:54 +01:00
import yaml
from yaml . loader import SafeLoader
2021-11-03 10:23:37 +01:00
from colorama import Fore , Back , Style
2022-01-25 17:16:07 +01:00
import re
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-01-25 17:16:07 +01:00
from time import sleep
2022-02-04 19:35:38 +01:00
from os import system , path , mkdir
2021-11-02 17:40:54 +01:00
2022-02-04 19:35:38 +01:00
class Game : # the game class keeps information about the loaded game
2021-11-26 22:13:30 +01:00
def __init__ ( self , data : dict ) :
self . name = data [ " meta " ] [ " name " ]
self . author = data [ " meta " ] [ " creator " ]
2021-11-02 17:40:54 +01:00
self . current = " start "
self . nodes = { }
2022-01-26 16:07:31 +01:00
self . inventory = [ ]
2022-02-04 19:35:38 +01:00
self . save = SaveManager ( )
self . id = data [ " meta " ] [ " id " ]
2021-11-26 22:13:30 +01:00
for k in data [ " game " ] :
self . nodes . update ( { k : data [ " game " ] [ k ] } )
2021-11-02 17:40:54 +01:00
2022-02-04 19:35:38 +01:00
def main_menu ( self ) : # displays the main menu
l = self . save . load ( )
if not l :
# New game
print ( self . name )
print ( f " A game by { self . author } " )
print ( " " )
print ( " 1 - Start " )
print ( " 2 - Options " )
print ( " 0 - Quit " )
2022-02-23 19:28:50 +01:00
selection = self . make_selection ( 3 )
system ( " cls||clear " )
if ( selection == 1 ) : # start new game
self . print_text ( )
elif ( selection == 2 ) :
self . settings_menu ( )
elif ( selection == 0 ) :
print ( " Quitting " )
exit ( )
2022-02-04 19:35:38 +01:00
else : # Display continue
print ( self . name )
print ( f " A game by { self . author } " )
print ( " " )
print ( " 1 - Continue " )
print ( " 2 - New game " )
print ( " 3 - Options " )
print ( " 0 - Quit " )
selection = self . make_selection ( 3 )
system ( " cls||clear " )
if ( selection == 1 ) :
self . current = self . save . currentPrompt
self . inventory = self . save . inventory
self . print_text ( )
elif ( selection == 2 ) :
self . print_text ( )
2022-02-23 19:28:50 +01:00
elif ( selection == 3 ) :
self . settings_menu ( )
elif ( selection == 0 ) :
2022-02-04 19:35:38 +01:00
print ( " Quitting " )
exit ( )
def settings_menu ( self ) : # displays the settings menu
2022-02-27 12:02:46 +01:00
print ( " Options " )
2022-02-04 19:35:38 +01:00
print ( " " )
print ( " 1 - Language " )
print ( " 0 - Back " )
selection = self . make_selection ( 1 )
if ( selection == 1 ) :
print ( " Language " )
print ( " " )
print ( " 1 - English " )
print ( " 2 - Czech " )
print ( " 0 - Back " )
selection = self . make_selection ( 2 )
system ( " cls||clear " )
if ( selection == 1 ) :
with open ( " ./saves/lang " , " w " ) as f :
f . write ( " en " )
elif ( selection == 2 ) :
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 ( )
2022-02-04 19:35:38 +01:00
def make_selection ( self , length = 0 ) - > int : # this method makes sure a valid selection is made and returns the selection as a number
2022-02-27 12:02:46 +01:00
# TODO: replace with selection by keyboard(?)
2022-02-04 19:35:38 +01:00
l = length # sets the length
if ( l == 0 ) : # if no length was set, we get it from nodes
2022-02-23 19:28:50 +01:00
l = len ( self . nodes [ self . current ] [ " actions " ] ) - 1
2022-01-26 16:07:31 +01:00
y = False
selection = 0
# TODO: Check for "has_item"
2022-02-23 19:28:50 +01:00
while y == False : # while the selection is not correct
2022-01-26 16:07:31 +01:00
try :
2022-02-23 19:28:50 +01:00
selection = int ( input ( " Make a selection (number): " ) ) # ask for selection
except ValueError : # handle wrong input type
2022-01-26 16:07:31 +01:00
print ( " Not a number selection " )
2022-02-23 19:28:50 +01:00
if ( selection > l or selection < 0 ) : # if the number is bigger than the length or smaller than 0, print error
2022-01-26 16:07:31 +01:00
print ( " Invalid selection " )
else :
2022-02-23 19:28:50 +01:00
y = True # else return the selection
2022-01-26 16:07:31 +01:00
return selection
2021-11-02 17:40:54 +01:00
2022-02-04 19:35:38 +01:00
def print_text ( self ) : # Prints out the current prompt
2022-02-23 19:28:50 +01:00
system ( " cls||clear " )
2022-01-25 17:16:07 +01:00
animated = re . search ( r " (?! { ).+(?=}) " , self . nodes [ self . current ] [ " text " ] ) # find the animated text
if ( animated != None ) :
self . print_animated ( animated . group ( 0 ) )
2022-01-25 17:30:09 +01:00
self . nodes [ self . current ] [ " text " ] = self . nodes [ self . current ] [ " text " ] . replace ( " { " + animated . group ( 0 ) + " } " , " " ) # remove the animated text from the text prompt
2021-12-16 10:12:00 +01:00
print ( self . parse_colors ( self . nodes [ self . current ] [ " text " ] ) )
2021-11-02 17:40:54 +01:00
print ( " " )
ostring = " "
2021-11-26 22:13:30 +01:00
if ( " actions " in self . nodes [ self . current ] . keys ( ) ) :
for i , option in enumerate ( self . nodes [ self . current ] [ " actions " ] ) :
ostring + = f " { i } - { self . nodes [ option ] [ ' description ' ] } \n "
print ( ostring )
2022-01-26 16:07:31 +01:00
sel = self . make_selection ( )
2022-02-23 19:28:50 +01:00
if " add_item " in self . nodes [ self . current ] : # if there is an add_inventory key in the node,
2022-01-26 16:07:31 +01:00
# add item to inventory
self . inventory . append ( self . nodes [ self . current ] [ " add_inventory " ] )
self . current = self . nodes [ self . current ] [ " actions " ] [ sel ]
2022-02-23 19:28:50 +01:00
self . save . currentPrompt = self . current # save the current prompt
2022-01-25 17:16:07 +01:00
self . print_text ( )
2022-02-04 19:35:38 +01:00
def print_animated ( self , animid ) : # prinst the first found occurence of an ascii animation
2022-01-26 09:23:30 +01:00
animation = AsciiAnimation ( )
animation . load_ascii ( animid )
2022-01-26 09:25:24 +01:00
for frame in animation . frames :
2022-01-25 17:30:09 +01:00
system ( " cls||clear " )
2022-01-25 17:16:07 +01:00
print ( frame )
2022-01-26 09:25:24 +01:00
sleep ( animation . speed )
2022-01-25 17:30:09 +01:00
print ( )
2022-01-25 17:16:07 +01:00
2022-02-04 19:35:38 +01:00
def parse_colors ( self , text : str ) - > str : # Converts color codes into terminal colors
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
2021-11-26 22:13:30 +01:00
newText + = Fore . RESET # reset color at the end of the text
return newText
2021-11-03 10:23:37 +01:00
2021-11-02 17:40:54 +01:00
2022-02-04 19:35:38 +01:00
def load ( file_path ) : # starts to load the game from YAML
lang = " en "
if not ( path . exists ( " ./saves/lang " ) ) :
mkdir ( " ./saves " )
with open ( " ./saves/lang " , " w " ) as f :
f . write ( " en " )
else :
with open ( " ./saves/lang " , " r " ) as f :
lang = f . read ( )
if lang == " cz " :
lang = " cz "
2021-11-26 22:13:30 +01:00
try :
with open ( file_path ) as f :
data = yaml . load ( f , Loader = SafeLoader )
g = Game ( data )
2022-02-04 19:35:38 +01:00
g . lang = lang
2021-11-26 22:13:30 +01:00
return g
except Exception as e :
2021-12-16 10:12:00 +01:00
print ( f " { Back . RED } { Fore . WHITE } An exception has occured while loading the game from the YAML file: { Fore . RESET } { Back . RESET } " )
2021-11-26 22:13:30 +01:00
print ( e )
2022-01-26 09:23:30 +01:00
return None