"""
C ' est joli, mais il y aurait moyen de factoriser pas mal de choses!
Note : 10 / 10
"""
import random
import cli
import time
import getkey
import sqlite3
class Animation :
""" class de gestion des animations du personnage """
def __init__ ( self , x , y , shape ) :
self . x = x
self . y = y
self . shape = shape
self . state = ' right '
def blink ( self , start_color , end_color ) :
""" Fait clignoter le calque """
self . layer = cli . Layer ( gui , self . x , self . y , self . shape [ 0 ] . split ( ' \n ' ) )
for i in range ( 8 ) :
self . layer . refresh ( )
if i % 2 == 0 :
self . display ( self . state , color = start_color )
else :
self . display ( self . state , color = end_color )
gui . display ( )
time . sleep ( 0.2 )
del self . layer
def display ( self , side , * * kwargs ) :
""" affiche le personnage """
self . state = side
if side == ' right ' :
cuted_shape = self . shape [ 0 ] . split ( ' \n ' )
else :
cuted_shape = self . shape [ 1 ] . split ( ' \n ' )
for i in range ( len ( cuted_shape ) ) :
for key , value in kwargs . items ( ) :
if key == ' color ' :
gui . draw ( cuted_shape [ i ] , self . x , self . y + i , color = value )
def move ( self , x , y , speed , * * kwargs ) :
""" le fait bouger selon x et y """
self . layer = cli . Layer ( gui , self . x , self . y , self . shape [ 0 ] . split ( ' \n ' ) )
colori = ' WHITE '
for key , value in kwargs . items ( ) :
if key == ' color ' :
colori = value
try :
direction = x / / abs ( x ) * speed
except :
direction = 1
for i in range ( 0 , x , direction ) :
self . x + = direction
self . layer . refresh ( )
self . layer . x + = direction
self . display ( self . state , color = colori )
gui . display ( )
time . sleep ( 0.3 )
try :
direction = y / / abs ( y ) * speed
except :
direction = 1
for i in range ( 0 , y , direction ) :
self . y + = direction
self . layer . refresh ( )
self . layer . y + = direction
self . display ( self . state , color = colori )
gui . display ( )
time . sleep ( 0.3 )
del self . layer
class Personnage ( Animation ) :
""" Class de base du personnage """
def __init__ ( self , nom , x , y , categorie , xp = 1 , bot = False ) :
self . bot = bot
if not self . bot :
conn = sqlite3 . connect ( ' bdd.db ' )
c = conn . cursor ( )
c . execute ( " SELECT * from Personnage join Categorie on Personnage.categorie=Categorie.name join Profil on Categorie.profil=Profil.name where Personnage.name = ? " , ( nom , ) )
data = c . fetchone ( )
if data is None :
c . execute ( " insert into Personnage(name, pdv, xp, max_pdv, potion, categorie) Values(?, ?, ?, ?, ?, ?) " , ( nom , " 20 " , str ( xp ) , " 20 " , " 2 " , categorie ) )
conn . commit ( )
c . execute ( " SELECT * from Personnage join Categorie on Personnage.categorie=Categorie.name join Profil on Categorie.profil=Profil.name where Personnage.name = ? " , ( nom , ) )
data = c . fetchone ( )
conn . close ( )
# Affectation du résultat de la requête aux attributs correspondants
self . nom = nom
self . pdv = data [ 1 ]
self . xp = data [ 2 ]
self . max_pdv = data [ 3 ]
self . weapon = data [ 7 ]
self . coef_attack = data [ 8 ]
self . coef_defense = data [ 9 ]
self . class_name = data [ 11 ] . split ( ' \n ' )
self . shape = [ data [ 13 ] . replace ( ' % ' , ' \n ' ) , data [ 14 ] . replace ( ' % ' , ' \n ' ) ]
self . potion = data [ 5 ]
else :
# récupération des attributs de la catégorie
conn = sqlite3 . connect ( ' bdd.db ' )
c = conn . cursor ( )
c . execute ( " SELECT * from Categorie join Profil on Categorie.profil=Profil.name where Categorie.name = ? " , ( categorie , ) )
data = c . fetchone ( )
conn . close ( )
self . nom = nom
self . pdv = 20
self . xp = xp
self . max_pdv = 20
self . weapon = data [ 1 ]
self . coef_attack = data [ 2 ]
self . coef_defense = data [ 3 ]
self . class_name = data [ 5 ] . split ( ' \n ' )
self . shape = [ data [ 7 ] . replace ( ' % ' , ' \n ' ) , data [ 8 ] . replace ( ' % ' , ' \n ' ) ]
self . potion = 2
self . x = x
self . y = y
super ( ) . __init__ ( self . x , self . y , self . shape )
def jet_attaque ( self ) :
return random . randint ( 1 , 20 ) + self . xp * self . coef_attack
def jet_defense ( self ) :
return random . randint ( 1 , 20 ) + self . xp * self . coef_defense
def change_xp ( self , nb_xp ) :
self . xp + = nb_xp
if not self . bot :
conn = sqlite3 . connect ( ' bdd.db ' )
c = conn . cursor ( )
c . execute ( " UPDATE Personnage SET xp=? where name=? " , ( self . xp , self . nom ) )
conn . commit ( )
c . close ( )
def change_pdv ( self , nb_pdv ) :
self . pdv + = nb_pdv
if not self . bot :
conn = sqlite3 . connect ( ' bdd.db ' )
c = conn . cursor ( )
c . execute ( " UPDATE Personnage SET pdv=? where name=? " , ( self . pdv , self . nom ) )
conn . commit ( )
c . close ( )
def change_max_pdv ( self , pdv ) :
self . max_pdv = pdv
if not self . bot :
conn = sqlite3 . connect ( ' bdd.db ' )
c = conn . cursor ( )
c . execute ( " UPDATE Personnage SET max_pdv=? where name=? " , ( self . max_pdv , self . nom ) )
conn . commit ( )
c . close ( )
def add_potion ( self ) :
""" Ajoute une potion à l ' invetaire et à la base de donnée """
self . potion + = 1
if not self . bot :
conn = sqlite3 . connect ( ' bdd.db ' )
c = conn . cursor ( )
c . execute ( " UPDATE Personnage SET potion=? WHERE name=? " , ( self . potion , self . nom ) )
c . close ( )
def remove_potion ( self ) :
""" Enlève une potion à l ' invetaire et à la base de donnée """
self . potion - = 1
if not self . bot :
conn = sqlite3 . connect ( ' bdd.db ' )
c = conn . cursor ( )
c . execute ( " UPDATE Personnage SET potion=? WHERE name=? " , ( self . potion , self . nom ) )
conn . commit ( )
c . close ( )
class App :
def __init__ ( self ) :
self . width = 120
self . height = 37
self . character = 0
self . potion_shape = """ _____
` . ___ , '
( ___ )
< >
) (
/ ` - . \\
/ \\
/ _ _ \\
: , ' `-. ' ` :
| |
: ;
\\ /
` . ___ . ' " " " .split( ' \n ' )
self . opponent = [ Personnage ( " Guerrier " , 80 , 45 , " guerrier " , 1 , True ) , Personnage ( " Voleur " , 80 , 45 , " voleur " , 1 , True ) , Personnage ( " Magicien " , 80 , 45 , " magicien " , 1 , True ) , Personnage ( " Elfe " , 80 , 45 , " elfe " , 1 , True ) ]
self . title = """ ██ ███████ ██ ██ ██████ ███████ ██████ ██████ ██ ███████
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ """ .split( ' \n ' )
def draw_arena ( self , ennemi , choice ) :
""" Dessine toute l ' arène et les joueur durant la phase jeu """
gui . wipe ( )
self . character . display ( ' right ' , color = ' BLUE ' )
self . opponent [ ennemi ] . display ( ' left ' , color = ' GREEN ' )
gui . draw_bar ( self . character . pdv * 100 / / self . character . max_pdv , 5 , 25 , 30 , color = ' RED ' )
gui . draw_bar ( self . character . xp * 100 / / 20 , 5 , 27 , 30 , color = ' GREEN ' )
gui . draw ( self . character . nom , 15 , 2 , weight = ' BOLD ' )
gui . draw ( str ( self . character . pdv ) , 38 , 25 , color = ' RED ' )
gui . draw ( str ( self . character . xp ) , 38 , 27 , color = ' GREEN ' )
gui . draw_bar ( self . opponent [ ennemi ] . pdv * 100 / / self . opponent [ ennemi ] . max_pdv , 75 , 25 , 30 , color = ' RED ' )
gui . draw_bar ( self . opponent [ ennemi ] . xp * 100 / / 20 , 75 , 27 , 30 , color = ' GREEN ' )
gui . draw ( self . opponent [ ennemi ] . nom , 90 , 2 )
gui . draw ( str ( self . opponent [ ennemi ] . pdv ) , 108 , 25 , color = ' RED ' )
gui . draw ( str ( self . opponent [ ennemi ] . xp ) , 108 , 27 , color = ' GREEN ' )
gui . draw ( ' ' . join ( [ ' _ ' for i in range ( self . width ) ] ) , 0 , 28 )
gui . draw ( ' Attaquer ' , 5 , 30 )
gui . draw ( ' Inventaire ' , 5 , 31 )
gui . draw ( ' Quiter ' , 5 , 32 )
gui . draw ( ' -> ' , 2 , 30 + choice )
gui . display ( )
def show_inventory ( self , position ) :
""" Dessine l ' inventaire """
gui . wipe ( )
gui . draw ( " Pressez échape pour sortir de l ' inventaire " , 45 , 0 )
gui . draw ( ' + ' + ' ' . join ( [ ' - ' for i in range ( self . width - 2 ) ] ) + ' + ' , 0 , 1 )
gui . draw ( ' + ' + ' ' . join ( [ ' - ' for i in range ( self . width - 2 ) ] ) + ' + ' , 0 , self . height - 2 )
for i in range ( 1 , self . height - 3 ) :
if i == 16 :
gui . draw ( ' ' . join ( [ ' + ' + ' ' . join ( [ ' - ' for j in range ( 29 ) ] ) for k in range ( 4 ) ] ) , 0 , 1 + i )
else :
gui . draw ( ' ' . join ( [ ' | ' + ' ' . join ( [ ' ' for j in range ( 29 ) ] ) for k in range ( 4 ) ] ) , 0 , 1 + i )
for j in range ( self . character . potion ) :
x = j % 4
y = j / / 4
if [ x , y ] == position :
color_fill = ' YELLOW '
else :
color_fill = ' WHITE '
gui . draw ( ' Cidre fermier ' , 30 * x + 10 , 17 * y + 2 , color = color_fill )
for i in range ( len ( self . potion_shape ) ) :
gui . draw ( self . potion_shape [ i ] , 30 * x + 6 , 17 * y + 3 + i , color = color_fill )
gui . display ( )
def combat ( self , ennemi ) :
""" Simule l ' attaque des joeurs """
# attaque du joueur
if self . character . jet_attaque ( ) > self . opponent [ ennemi ] . jet_defense ( ) :
self . opponent [ ennemi ] . change_pdv ( - 1 * random . randint ( 1 , 8 ) )
self . opponent [ ennemi ] . blink ( ' RED ' , ' GREEN ' )
# test si l'ennemi est mort
if self . opponent [ ennemi ] . pdv < = 0 :
self . opponent [ ennemi ] . move ( 40 , 0 , 4 )
self . character . change_xp ( 1 )
self . character . change_max_pdv ( self . character . max_pdv + 5 )
self . character . change_pdv ( round ( self . character . max_pdv * 0.2 ) )
if random . randint ( 0 , 5 ) == 0 :
self . character . add_potion ( )
ennemi = random . randint ( 0 , 3 )
cat = [ ' guerrier ' , ' elfe ' , ' magicien ' , ' voleur ' ]
self . opponent [ ennemi ] . __init__ ( self . opponent [ ennemi ] . nom , 120 , 5 , cat [ ennemi ] , random . randint ( max ( 1 , self . character . xp - 2 ) , self . character . xp + 1 ) , True )
self . opponent [ ennemi ] . change_max_pdv ( 20 + 5 * ( self . opponent [ ennemi ] . xp - 1 ) )
self . opponent [ ennemi ] . change_pdv ( self . opponent [ ennemi ] . max_pdv - self . opponent [ ennemi ] . pdv )
self . opponent [ ennemi ] . move ( - 40 , 0 , 4 )
return ennemi
else :
self . character . change_pdv ( - 1 * random . randint ( 1 , 4 ) )
self . character . blink ( ' RED ' , ' BLUE ' )
# test si le joueur est toujours en vie
if self . character . pdv < = 0 :
return None
# attaque de l'ennemi
if self . opponent [ ennemi ] . jet_attaque ( ) < self . character . jet_defense ( ) :
self . opponent [ ennemi ] . change_pdv ( - 1 * random . randint ( 1 , 4 ) )
self . opponent [ ennemi ] . blink ( ' RED ' , ' GREEN ' )
# test si l'ennemi est mort
if self . opponent [ ennemi ] . pdv < = 0 :
self . opponent [ ennemi ] . move ( 40 , 0 , 4 )
self . character . change_xp ( 1 )
self . character . change_max_pdv ( self . character . max_pdv + 5 )
self . character . change_pdv ( round ( self . character . max_pdv * 0.2 ) )
if random . randint ( 0 , 5 ) == 0 :
self . character . add_potion ( )
ennemi = random . randint ( 0 , 3 )
cat = [ ' guerrier ' , ' elfe ' , ' magicien ' , ' voleur ' ]
self . opponent [ ennemi ] . __init__ ( self . opponent [ ennemi ] . nom , 120 , 5 , cat [ ennemi ] , random . randint ( max ( self . character . xp - 3 , 1 ) , self . character . xp + 1 ) , True )
self . opponent [ ennemi ] . change_max_pdv ( 20 + 5 * ( self . opponent [ ennemi ] . xp - 1 ) )
self . opponent [ ennemi ] . change_pdv ( self . opponent [ ennemi ] . max_pdv - self . opponent [ ennemi ] . pdv )
self . opponent [ ennemi ] . move ( - 40 , 0 , 4 )
return ennemi
else :
self . character . change_pdv ( - 1 * random . randint ( 1 , 8 ) )
self . character . blink ( ' RED ' , ' BLUE ' )
# test si le joueur est toujours en vie
if self . character . pdv < = 0 :
return None
def play ( self ) :
""" Gère la phase de jeu """
gui . wipe ( )
self . character . move ( - 40 , 0 , 4 , color = ' BLUE ' )
ennemi = random . randint ( 0 , 3 )
self . opponent [ ennemi ] . xp = random . randint ( max ( 1 , self . character . xp - 3 ) , self . character . xp + 1 )
self . opponent [ ennemi ] . change_max_pdv ( 20 + 5 * ( self . opponent [ ennemi ] . xp - 1 ) )
self . opponent [ ennemi ] . pdv = self . opponent [ ennemi ] . max_pdv
self . opponent [ ennemi ] . move ( 0 , - 40 , 4 , color = ' GREEN ' )
choice = 0
while self . character . pdv > 0 :
self . draw_arena ( ennemi , choice )
while True :
key = getkey . getkey ( )
if key == getkey . keys . UP :
choice = abs ( ( choice - 1 ) % 3 )
break
elif key == getkey . keys . DOWN :
choice = abs ( ( choice + 1 ) % 3 )
break
elif key == getkey . keys . ENTER :
if choice == 0 :
# combat
result = self . combat ( ennemi )
if result != None :
ennemi = result
if choice == 1 :
# affichage de l'inventaire
position = [ 0 , 0 ]
while True :
self . show_inventory ( position )
key = getkey . getkey ( )
if key == getkey . keys . UP :
if position [ 1 ] > 0 :
position [ 1 ] - = 1
elif key == getkey . keys . DOWN :
if position [ 1 ] < 1 :
position [ 1 ] + = 1
elif key == getkey . keys . RIGHT :
if position [ 0 ] < 3 :
position [ 0 ] + = 1
elif key == getkey . keys . LEFT :
if position [ 0 ] > 0 :
position [ 0 ] - = 1
elif key == getkey . keys . ENTER :
if self . character . potion > 0 :
self . character . change_pdv ( round ( ( self . character . max_pdv - self . character . pdv ) * 0.5 ) )
if self . character . pdv > self . character . max_pdv :
self . character . change_pdv ( self . character . max_pdv - self . character . pdv )
self . character . remove_potion ( )
elif key == getkey . keys . ESCAPE :
break
if choice == 2 :
exit ( )
break
# le joueur à perdu
gui . wipe ( )
#suppression du joueur de la bdd
conn = sqlite3 . connect ( ' bdd.db ' )
c = conn . cursor ( )
c . execute ( " DELETE FROM Personnage where name=? " , ( self . character . nom , ) )
conn . commit ( )
c . close ( )
game_over = """
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █
""" .split( ' \n ' )
for i in range ( len ( game_over ) ) :
gui . draw ( game_over [ i ] , 60 - len ( game_over [ i ] ) / / 2 , 12 + i , color = ' RED ' )
gui . display ( )
def setting ( self , name , number_char ) :
""" permet de choisir son type de personnage """
gui . wipe ( )
characters = [ Personnage ( name , 0 , 5 , " guerrier " , 1 , True ) , Personnage ( name , 0 , 5 , " voleur " , 1 , True ) , Personnage ( name , 0 , 5 , " magicien " , 1 , True ) , Personnage ( name , 0 , 5 , " elfe " , 1 , True ) ]
for char in characters :
char . x = 60 - len ( char . shape [ 0 ] . split ( ' \n ' ) [ 0 ] ) / / 2
for i in range ( len ( characters [ number_char ] . class_name ) ) :
gui . draw ( characters [ number_char ] . class_name [ i ] , 60 - ( len ( characters [ number_char ] . class_name [ 0 ] ) / / 2 ) , 25 + i , color = ' RED ' , weight = ' BOLD ' )
for i in range ( 2 ) :
gui . draw ( ' / ' , 4 - i , 17 + i )
gui . draw ( ' \\ ' , 4 - i , 20 - i )
gui . draw ( ' \\ ' , - 4 + i , 17 + i )
gui . draw ( ' / ' , - 4 + i , 20 - i )
characters [ number_char ] . display ( ' right ' , color = ' BLUE ' )
gui . draw ( ' Utilisez les flèche pour changer de personnage puis appuyez sur entrée ' , 30 , 1 )
gui . display ( )
while True :
key = getkey . getkey ( )
if key == getkey . keys . RIGHT :
self . setting ( name , ( number_char + 1 ) % 4 )
break
elif key == getkey . keys . LEFT :
self . setting ( name , ( number_char - 1 ) % 4 )
break
elif key == getkey . keys . ENTER :
self . character = Personnage ( name , 0 , 5 , [ ' guerrier ' , ' voleur ' , ' magicien ' , ' elfe ' ] [ number_char ] )
self . character . x = 60 - len ( self . character . shape [ 0 ] . split ( ' \n ' ) [ 0 ] ) / / 2
del characters
self . play ( )
break
def menu ( self ) :
""" permet de choisir son nom """
for i in range ( len ( self . title ) ) :
gui . draw ( self . title [ i ] , 60 - len ( self . title [ 0 ] ) / / 2 , 10 + i )
gui . draw ( ' > ' , 40 , 30 , color = ' RED ' )
gui . draw ( ' Taper votre nom et presser entrée ' ,
41 , 30 , weight = ' BOLD ' )
gui . draw ( ' < ' , 76 , 30 , color = ' RED ' )
gui . display ( )
name = input ( ' => ' )
# test si le joueur à déjà joué
conn = sqlite3 . connect ( " bdd.db " )
c = conn . cursor ( )
c . execute ( " SELECT * from Personnage join Categorie on Personnage.categorie=Categorie.name join Profil on Categorie.profil=Profil.name where Personnage.name = ? " , ( name , ) )
data = c . fetchone ( )
c . close ( )
if data is None :
self . setting ( name , 0 )
else :
self . character = Personnage ( name , 0 , 5 , data [ 4 ] )
self . character . x = 60 - len ( self . character . shape [ 0 ] . split ( ' \n ' ) [ 0 ] ) / / 2
self . play ( )
app = App ( )
gui = cli . Cli ( width = app . width , height = app . height )
app . menu ( )