[Echecs] Ajout de documentation

This commit is contained in:
Geoffrey Frogeye 2014-12-14 00:47:49 +01:00
parent 87635bb8a6
commit 9c10044275
4 changed files with 258 additions and 77 deletions

View file

@ -15,25 +15,35 @@ python app.py
(en supposant que `python` est dans la variable d'environnement `path` (ou `$PATH` sous Windows) et point vers l'éxecutable de Python 3)
##Fonctions non-implémentées
##Objectifs non-réalisés
###Règles des échecs
###Objectifs de TP
* Implémenter le jeu d'échecs entier
Le jeu d'échec n'est pas totalement implémenté, voici la liste non-exhaustive des règles qui ne sont pas implémentées
* Le Roque
* La promotion du pion
* Prise en passant
* Détection du "pat" (le joueur ne pouvant pas jouer est considéré comme perdant, même s'il n'est pas en échec)
###Consignes de TP
* Pouvoir choisir entre jeu de dame et jeu d'échecs
Le jeu de dame n'est pas implémenté, cependant les autres classes sont compatibles avec lui car il suffit de changer la classe Logique**** utilisée.
Le jeu de dame n'est pas implémenté, bien qu'il ne soit nécessaire de ne modifier aucune partie du code déjà existant.
* Redimensionnement de la fenêtre
Il suffirait d'appeler PlateauTk.redimCan(min(xMax, yMax)) à chaque redimensionnement de la fenêtre. Cependant j'ai un peu de mal à comprendre comment fonctionne Tk.
* Documentation et tests
###Objectifs personnels
Étant donné que les fonctions sont plutôt expliquables d'elle-même par leur nom, que je suis seul à travailler sur ce projet, et que j'ai passé pas mal de temps à découper les fonctions, elles ne sont ni documentées ni testées.
* Qualité du code
Bien que le code fonctionne, soit plutôt flexible, relativement documenté et utilise la notion d'objet, il est loin d'être irréprochable. Certaines fonctions font probablement plus de calcul que nécessaire, la création de certaines variables pourraient être évité. L'ajout de plus de constante au lieu de valeurs arbitraire contribuerait à la lisibilité du code. Certaines instructions ne sont probablement pas sémantiquement correcte.
* Originalité
Le jeu actuel ne possède aucun point fort (au contraire) qui pourrait le démarquer des jeux d'Échecs existant. Très peu d'utilisateurs pourraient l'utiliser dans une optique autre que le développement ou le test.
Les commentaires affublés d'une marque `TODO` signifient qu'une

View file

@ -5,3 +5,9 @@ from guiTk import FenetreTk
if __name__ == '__main__':
# p = PlateauTk(LogiqueEchecs())
f = FenetreTk()
# TODO pion → piece Quand nécessaire
# TODO mvtSansEchec → depl
# TODO Entrée / Sortie ?
# TODO Doctest
# TODO cls au lieu de self quand nécessaires

View file

@ -2,35 +2,41 @@ from tkinter import *
from logique import LogiqueEchecs
class PlateauTk:
"""
Plateau de jeu de damier en canvas Tk
"""
RATIO_PCE_CASE = .95
TEMPS_ANIM = 200
INTER_ANIM = 10
RATIO_PCE_CASE = .95 # Place que prend la pièce sur la case
TEMPS_ANIM = 200 # Temps en ms d'une animation
INTER_ANIM = 10 # Temps en ms entre deux actualisations d'animation
COTE_TOUT_DEFAUT = 500
COTE_TOUT_DEFAUT = 500 # Coté par défaut du plateau
def __init__(self, fen, can, statut, logique):
"""
Constructeur de PlateauTk
"""
self.can = can
self.fen = fen
self.statut = statut
self.chaine = None
self.grilleDamier = []
self.imagesOriginales = {}
self.imagesRedim = {}
self.photos = []
self.grillePions = []
self.animations = []
self.can = can # Canvas
self.fen = fen # Fenêtre Tk (nécessaire pour lancer un timeout pour l'animation)
self.statut = statut # Fonction qui envoie un message à l'utilisateur
self.grilleDamier = [] # Tableau contenant les références aux cases du damier
self.grillePions = [] # Tableau contenant les références aux pièces
self.photos = [] # Liste contenant les différentes photos utilisées (afin qu'elles ne soient pas recyclées)
self.imagesOriginales = {} # Dictionnaire associant chaque pièce à son image originale
self.imagesRedim = {} # Dictionnaire associant chaque pièce à son image redimensionnée
self.animations = [] # Liste contenant les animations en cours
self.dEtape = True
self.dx1 = -1
self.dy1 = -1
self.dx2 = -1
self.dy2 = -1
self.mvtsPossibles = []
self.logique = logique
self.dEtape = True # Étape du déplacement (True : prendre la pièce, False : poser la pièce)
self.dx1 = -1 # Coordonnées X de la pièce sélectionnée
self.dy1 = -1 # Coordonnées Y de la pièce sélectionnée
self.dx2 = -1 # Coordonnées X de la destination
self.dy2 = -1 # Coordonnées Y de la destination
self.mvtsPossibles = [] # Liste des mouvements possibles pour la pièce sélectionnée
self.coteCase = 0 # Coté d'une case
self.logique = logique # Logique du jeu
self.coteCase = 0
self.importerImages()
self.redimCan(self.COTE_TOUT_DEFAUT)
@ -39,6 +45,9 @@ class PlateauTk:
self.statutPrendre()
def redimCan(self, cote):
"""
Redimensionne le plateau de jeu
"""
self.can.delete(ALL)
self.coteCase = cote // self.logique.CASES_COTE
cote = self.logique.CASES_COTE * self.coteCase
@ -52,6 +61,9 @@ class PlateauTk:
def nomPiece(self, piece):
"""
Renvoi le nom de fichier de la pièce donnée
"""
tPiece = self.logique.tPiece(piece)
if tPiece == self.logique.PCE_PION:
return 'pion'
@ -68,20 +80,32 @@ class PlateauTk:
else:
return False
def importerImage(self, piece, couleur):
def importerImage(self, piece, couleur): # TODO piece stocke déjà la couleur
"""
Importe l'image de la pièce donnée
"""
nom = 'sprites/'+self.nomPiece(piece)+couleur+'.gif'
self.imagesOriginales.update({piece:PhotoImage(file=nom)})
def importerImages(self):
"""
Importe les images des pièces du jeu
"""
for piece in self.logique.BLANCS:
self.importerImage(piece, 'B')
for piece in self.logique.NOIRS:
self.importerImage(piece, 'N')
def redimImage(self, piece, sample):
"""
Redimensionne l'image de la pièce donnée
"""
self.imagesRedim.update({piece:self.imagesOriginales[piece].subsample(sample)})
def redimImages(self):
"""
Redimensionne l'image des pièces du jeu
"""
sample = int(504 // (self.coteCase * self.RATIO_PCE_CASE)) # TODO S'en sort pour être toujours plus grand
for piece in self.logique.BLANCS:
self.redimImage(piece, sample)
@ -90,7 +114,10 @@ class PlateauTk:
# Dessin
@staticmethod
def caseCouleur(blanc, contexte):
def caseCouleur(blanc, contexte=0):
"""
Retourne la couleur hexadécimale de la case de couleur et de contexte donnée
"""
if contexte == 1: # Sélectionné
return '#a0cefe' if blanc else '#478bd1'
elif contexte == 2: # Possible / Victoire
@ -101,21 +128,33 @@ class PlateauTk:
return '#ffce9e' if blanc else '#d18b47'
def cCase(self, x, y):
"""
Crée la case aux coordonnées données
"""
couleur = self.caseCouleur(self.logique.eCaseBlanche(x, y), 0)
return self.can.create_rectangle(x * self.coteCase, y * self.coteCase, (x + 1) * self.coteCase, (y + 1) * self.coteCase)
def coulCase(self, x, y, contexte):
def coulCase(self, x, y, contexte=0):
"""
Colorie la case aux coordonnées données selon le contexte donné
"""
couleur = self.caseCouleur(self.logique.eCaseBlanche(x, y), contexte)
self.can.itemconfig(self.grilleDamier[x][y], fill=couleur, outline=couleur)
def coulDamier(self):
def coulDamier(self, contexte=0):
"""
Colorie toutes les cases selon le contexte donné
"""
for x in range(0, self.logique.CASES_COTE):
for y in range(0, self.logique.CASES_COTE):
self.coulCase(x, y, 0)
self.coulCase(x, y, contexte)
def cDamier(self):
"""
Génère le damier
"""
self.grilleDamier = []
for x in range(0, self.logique.CASES_COTE):
for x in range(0, self.logique.CASES_COTE): # TODO Peut être amélioré
colonne = []
for y in range(0, self.logique.CASES_COTE):
colonne.append(self.cCase(x, y))
@ -123,12 +162,18 @@ class PlateauTk:
self.coulDamier()
def cPion(self, x, y, piece):
if piece > 0:
"""
Crée la pièce aux coordonnées données
"""
if self.logique.ePiece(piece):
self.grillePions[x][y] = self.can.create_image((x + .5) * self.coteCase, (y + .5) * self.coteCase, image=self.imagesRedim[piece])
else:
self.grillePions[x][y] = False
def cGrille(self):
"""
Crée le tableau contenant les images de pièces
"""
self.grillePions = []
for x in range(0, self.logique.CASES_COTE): # Crée self.grillePions
colonne = []
@ -137,12 +182,18 @@ class PlateauTk:
self.grillePions.append(colonne)
def remplirGrille(self, j_grilleF):
"""
Remplis la grille des images de pièce selon la grille des pièces logiques.
"""
for x in range(0, self.logique.CASES_COTE): # Remplis self.grillePions
for y in range(0, self.logique.CASES_COTE):
self.cPion(x, y, j_grilleF[x][y])
# Interaction
def nomJoueur(self, joueur, pluriel=True):
"""
Retourne le nom du joueur donné
"""
if joueur == self.logique.BLANC:
nom = 'blanc'
elif joueur == self.logique.NOIR:
@ -154,15 +205,25 @@ class PlateauTk:
return nom
def statutPrendre(self):
self.statut('Prendre (' + self.nomJoueur(self.logique.joueur) + ')')
"""
Change le statut indiquant au joueur en cours de jouer.
"""
self.statut('Aux ' + self.nomJoueur(self.logique.joueur, pluriel=True) + ' de sélectionner une pièce.')
@staticmethod
def animationDCoords(i):
"""
Retourne les coordonnées auxquelles doit se placer une pièce en cours d'animation
"""
# TODO Faire autre chose qu'une animation linéaire constante
x = i['x1'] + (i['x2']-i['x1']) * (i['avancement']/i['total'])
y = i['y1'] + (i['y2']-i['y1']) * (i['avancement']/i['total'])
return [x, y]
def animation(self):
"""
Effectue les changements graphique nécessaire à la création d'une image d'animation.
"""
animationsNv = []
for i in self.animations:
if i['avancement'] < i['total']:
@ -183,22 +244,29 @@ class PlateauTk:
elif i['type'] == 'c':
self.coulCase(i['x'], i['y'], 0)
self.animations = animationsNv
if len(animationsNv):
self.fen.after(self.INTER_ANIM, self.animation)
if len(animationsNv): # Si il y aura encore des animations à faire
self.fen.after(self.INTER_ANIM, self.animation) # On prévoit une image (boucle)
def animer(self, animation):
"""
Ajoute une animation à la liste des animations en cours, et lance
la fonction animation() si la boucle n'est déjà pas lancée.
"""
etaitVide = len(self.animations) < 1
self.animations.append(animation)
if etaitVide:
self.animation()
def animerD(self, x1, y1, x2, y2, pion):
"""
Ajoute une animation pour un déplacment de pion
"""
if len(self.animations):
for i in self.animations:
if i['type'] == 'd' and i['pion'] == pion:
# Si une animation pour ce pion existe déjà, on la reprend et on la modifie
coords = self.animationDCoords(i)
i['x1'] = coords[0]
i['x1'] = coords[0] # TODO Simplifier avec update()
i['y1'] = coords[1]
i['x2'] = x2
i['y2'] = y2
@ -220,7 +288,10 @@ class PlateauTk:
self.can.tag_raise(pion) # Mise au premier plan
self.animer(animation)
def animerF(self, pion): # Pion fade-out
def animerF(self, pion):
"""
Ajoute une animation pour la suppression d'un pion
"""
animation = {
'pion': pion,
'type': 'f',
@ -230,6 +301,9 @@ class PlateauTk:
self.animer(animation)
def animerC(self, x ,y):
"""
Ajoute une animation pour l'effacement de la surbrillance d'une case
"""
animation = {
'type': 'c',
'x': x,
@ -240,18 +314,25 @@ class PlateauTk:
self.animer(animation)
def victoire(self):
"""
Indique à l'utilisateur la victoire et décore le plateau pour l'occasion
"""
self.statut('Victoire des ' + self.nomJoueur(self.logique.victorieux) + ' !')
self.coulDamier()
for x in range(0, self.logique.CASES_COTE):
for y in range(0, self.logique.CASES_COTE):
pion = self.logique.grille[x][y]
if pion > 0:
if self.logique.ePiece(pion):
if self.logique.ePionNoir(pion) ^ self.logique.victorieux:
self.coulCase(x, y, 2)
else:
self.coulCase(x, y, 3)
def dPion(self, x1, y1, x2, y2):
"""
Déplace le pion aux coordonnées 1 aux coordonnées 2.
(Vérifie la possibilité du mouvement et crée les animations nécessaires)
"""
test = self.logique.dPion(x1, y1, x2, y2)
if test['valide'] == True: # Si déplacement possible
for s in test['supprimer']:
@ -268,6 +349,9 @@ class PlateauTk:
return test['valide']
def dClic(self, x, y):
"""
Réagit en fonction d'un clic sur une case aux coordonnées données
"""
if not self.logique.partieFinie:
if self.dEtape: # Prendre
self.dx1, self.dy1 = x, y
@ -296,26 +380,38 @@ class PlateauTk:
self.animerC(self.dx2, self.dy2)
def clic(self, event):
if event.x in range(0, self.coteCase * self.logique.CASES_COTE) and event.y in range(0, self.coteCase * self.logique.CASES_COTE):
"""
Réagit en fonction d'un clic
"""
# if event.x in range(0, self.coteCase * self.logique.CASES_COTE) and event.y in range(0, self.coteCase * self.logique.CASES_COTE):
self.dClic(event.x // self.coteCase, event.y // self.coteCase)
class FenetreTk:
"""
Fenêtre pour jouer à des jeux sur damier
"""
PLACEHOLDER_DIMENSIONS = 300
PLACEHOLDER_DIMENSIONS = 300 # Coté du canvas vide du début
def __init__(self):
"""
Constructeur de FenetreTk
"""
self.fen = None
self.can = None
self.chaine = ''
self.fen = None # Objet Fenêtre
self.can = None # Objet Canvas
self.chaine = None # Objet Label de statut
self.plateau = None
self.plateau = None # Plateau de jeu
self.creerFen()
self.fen.mainloop()
def creerFen(self):
"""
Crée la fenêtre et ses éléments
"""
self.fen = Tk()
self.fen.title("Jeu de plateau")
self.can = Canvas(self.fen, width=self.PLACEHOLDER_DIMENSIONS, height=self.PLACEHOLDER_DIMENSIONS, bg="ivory")
@ -326,8 +422,17 @@ class FenetreTk:
Button(self.fen, text="Quitter", command=self.fen.destroy).grid(row=2, column=3, padx=3, pady=3)
def statut(self, texte, delai=0):
"""
Change le message affiché.
"""
self.chaine.config(text=texte)
# TODO Timeout effacer si parametre / Liste
# TODO Messages permanents et messages temporaires
# (exemple permanent : "Aux blancs de jouer", exemple
# temporaire "Vous ne pouvez pas jouer ici !")
def nvPartie(self):
"""
Démarre une nouvelle partie.
"""
del self.plateau
self.plateau = PlateauTk(self.fen, self.can, self.statut, LogiqueEchecs())

View file

@ -5,36 +5,50 @@ class Logique:
Logique des jeux sur damier
"""
PCE_VIDE = 0
BLANC = True
NOIR = False
PCE_VIDE = 0 # Valeur à mettre sur la grille quand il n'y a pas de pièce
BLANC = True # Valeur correspondant au joueur blanc
NOIR = False # Valeur correspondant au joueur noir
@staticmethod
def eCaseBlanche(xD, yD):
return xD % 2 == yD % 2
def eCaseBlanche(x, y):
"""
Indique si la case aux coordonnées indiquée est blanche.
"""
return x % 2 == y % 2
def cGrille(self):
for x in range(self.CASES_COTE):
"""
Crée le tableau self.grille.
"""
for x in range(self.CASES_COTE): # TODO Peut être amélioré
colonne = []
for y in range(self.CASES_COTE):
colonne.append(self.PCE_VIDE)
self.grille.append(colonne)
def cPion(self, x, y, piece):
self.grille[x][y] = piece
return True
def ePionBlanc(self, pion):
"""
Indique si la pièce est une pièce blanche.
"""
return pion in self.BLANCS
def ePionNoir(self, pion):
"""
Indique si la pièce est une pièce noire.
"""
return pion in self.NOIRS
def ePiece(self, piece):
"""
Indique si la pièce est une pièce.
"""
# return piece != self.PCE_VIDE
return self.ePionBlanc(piece) or self.ePionNoir(piece)
def tPiece(self, piece):
"""
Retourne le type de pièce de la pièce donnée.
"""
if self.ePionBlanc(piece):
return piece - self.DECALAGE_BLANCS
elif self.ePionNoir(piece):
@ -43,6 +57,9 @@ class Logique:
return self.PCE_VIDE
def aSonTour(self, pion):
"""
Indique si la pièce donnée a le droit de jouer.
"""
return (self.ePionNoir(pion) and self.joueur == self.NOIR) or \
(self.ePionBlanc(pion) and self.joueur == self.BLANC)
@ -52,9 +69,9 @@ class LogiqueEchecs(Logique):
Logique du jeu d'Échecs
"""
CASES_COTE = 8
CASES_COTE = 8 # Cases de coté
# Pièces
# Type de pièces
PCE_PION = 1
PCE_TOUR = 2
PCE_CAVALIER = 3
@ -62,14 +79,14 @@ class LogiqueEchecs(Logique):
PCE_DAME = 5
PCE_ROI = 6
DECALAGE_BLANCS = 0
DECALAGE_NOIRS = 10
DECALAGE_BLANCS = 0 # Valeur à partir de laquelle sont compris les pièces blanches
DECALAGE_NOIRS = 10 # Valeur à partir de laquelle sont compris les pièces noires
BLANCS = range(DECALAGE_BLANCS+PCE_PION, DECALAGE_BLANCS+PCE_ROI+1)
NOIRS = range(DECALAGE_NOIRS+PCE_PION, DECALAGE_NOIRS+PCE_ROI+1)
BLANCS = range(DECALAGE_BLANCS+PCE_PION, DECALAGE_BLANCS+PCE_ROI+1) # Intervalle contenant les pièces blancs
NOIRS = range(DECALAGE_NOIRS+PCE_PION, DECALAGE_NOIRS+PCE_ROI+1) # Intervalle contenant les pièces noirs
# Codes du mouvement
# Codes d'erreur de mouvement
MVT_INCONNU = 'Cause inconnue'
MVT_OK = 'Valide'
MVT_ROQUE = 'Roque'
@ -82,15 +99,20 @@ class LogiqueEchecs(Logique):
MVT_ECHEC = 'Échec au roi'
def __init__(self):
self.grille = []
"""
Constructeur de LogiqueEchecs
"""
self.grille = [] # Grille de jeu
self.cGrille()
self.remplirGrille()
self.joueur = self.BLANC
self.joueur = self.BLANC # Premier joueur
self.partieFinie = False
self.victorieux = None
def remplirGrille(self):
"""
Remplis la grille avec les pièces nécessaire à une nouvelle partie.
"""
speciales = [self.PCE_TOUR, self.PCE_CAVALIER, self.PCE_FOU, self.PCE_ROI, self.PCE_DAME]
speciales += speciales[2::-1]
for i in range(0, 8):
@ -100,6 +122,9 @@ class LogiqueEchecs(Logique):
self.grille[i][7] = self.DECALAGE_BLANCS + speciales[i]
def mvtPossibleSansEchecPion(self, x1, y1, x2, y2):
"""
Vérifie si le déplacement est possible pour un pion.
"""
if x1 == x2 and self.grille[x2][y2] <= 0: # Avance
if self.joueur:
if y2 == y1 - 1:
@ -132,6 +157,9 @@ class LogiqueEchecs(Logique):
return self.MVT_N_AUTORISE
def mvtPossibleSansEchecTour(self, x1, y1, x2, y2):
"""
Vérifie si le déplacement est possible pour une tour.
"""
if y1 == y2:
sens = (x2-x1)//abs(x2-x1)
for x in range(x1+sens, x2, sens):
@ -147,6 +175,9 @@ class LogiqueEchecs(Logique):
return self.MVT_OK
def mvtPossibleSansEchecFou(self, x1, y1, x2, y2):
"""
Vérifie si le déplacement est possible pour un fou.
"""
if abs(x2-x1) == abs(y2-y1):
sensX = (x2-x1)//abs(x2-x1)
sensY = (y2-y1)//abs(y2-y1)
@ -168,12 +199,18 @@ class LogiqueEchecs(Logique):
return self.MVT_N_AUTORISE
def mvtPossibleSansEchecCavalier(self, x1, y1, x2, y2):
"""
Vérifie si le déplacement est possible pour un cavalier.
"""
if (abs(x2-x1) == 2 and abs(y2-y1) == 1) or (abs(y2-y1) == 2 and abs(x2-x1) == 1):
return self.MVT_OK
else:
return self.MVT_N_AUTORISE
def mvtPossibleSansEchec(self, x1, y1, x2, y2):
def mvtPossibleSansEchec(self, x1, y1, x2, y2): # TODO Utiliser la gestion d'erreurs ?
"""
Vérifie si le déplacement est possible.
"""
pion = self.grille[x1][y1]
if self.aSonTour(pion):
if (x1 != x2 or y1 != y2):
@ -212,12 +249,18 @@ class LogiqueEchecs(Logique):
return self.MVT_INCONNU
def mvtPossible(self, x1, y1, x2, y2):
"""
Vérifie si le mouvement est possible.
Contrairement aux fonctions de vérification de déplacement, celle-ci
vérifie si le mouvement est réalisable si le roi est en échec.
"""
test = self.mvtPossibleSansEchec(x1, y1, x2, y2)
if test == self.MVT_OK:
# On copie la partie actuelle pour tester le mouvement et vérifier l'échec
copie = copy.deepcopy(self);
copie.dPionSansEchec(x1, y1, x2, y2)
mvtsPossiblesTousAdverses = []
# On cherche la position du roi
pionRoi = self.PCE_ROI + self.DECALAGE_BLANCS if self.joueur else self.DECALAGE_NOIRS
roi = [-1, -1]
for x in range(0, self.CASES_COTE):
@ -225,7 +268,7 @@ class LogiqueEchecs(Logique):
mvtsPossiblesTousAdverses += copie.mvtsPossiblesSansEchec(x, y)
if copie.grille[x][y] == pionRoi:
roi = [x, y]
if roi in mvtsPossiblesTousAdverses:
if roi in mvtsPossiblesTousAdverses: # Si le roi peut être sauté au tour adverse
return self.MVT_ECHEC
else:
return test
@ -233,6 +276,9 @@ class LogiqueEchecs(Logique):
return test
def mvtsPossiblesSansEchec(self, x1, y1):
"""
Donne la liste des déplacements possible pour la pièce donnée.
"""
tableau = []
for x2 in range(0, self.CASES_COTE):
for y2 in range(0, self.CASES_COTE):
@ -241,6 +287,9 @@ class LogiqueEchecs(Logique):
return tableau
def mvtsPossibles(self, x1, y1):
"""
Donne la liste des mouvements possible pour la pièce donnée.
"""
tableau = []
for x2 in range(0, self.CASES_COTE):
for y2 in range(0, self.CASES_COTE):
@ -249,6 +298,11 @@ class LogiqueEchecs(Logique):
return tableau
def dPionSansEchec(self, x1, y1, x2, y2):
"""
Déplace le pion aux coordonnées 1 données aux coordonnées 2 données.
Ne vérifie pas si le mouvement peut conduire à une prise illégale du roi.
(Est utilisé dans pour cette détection)
"""
test = self.mvtPossibleSansEchec(x1, y1, x2, y2)
if test == self.MVT_OK:
self.grille[x1][y1], self.grille[x2][y2] = self.PCE_VIDE, self.grille[x1][y1]
@ -256,9 +310,11 @@ class LogiqueEchecs(Logique):
def vEchecMat(self):
"""
Vérifie si le joueur actuel est en échec et mat et prend les mesures nécessiares.
(Ici vrai en cas de "pat")
Vérifie si le joueur actuel est en échec et mat et déclenche
éventuellement la victoire
(Le "pat" est considiéré comme une victoire)
"""
# Vérifications si aucun mouvement pour aucune pièce n'est possible
for x in range(0, self.CASES_COTE):
for y in range(0, self.CASES_COTE):
if len(self.mvtsPossibles(x, y)) > 0:
@ -268,6 +324,10 @@ class LogiqueEchecs(Logique):
return True
def dPion(self, x1, y1, x2, y2):
"""
Déplace le pion aux coordonnées 1 données aux coordonnées 2 données.
Renvoie les détails du mouvement.
"""
test = self.mvtPossible(x1, y1, x2, y2)
retour = {
'valide': False,