diff --git a/S1/Echecs/app.py b/S1/Echecs/app.py old mode 100644 new mode 100755 index d654f27..fd0e8a1 --- a/S1/Echecs/app.py +++ b/S1/Echecs/app.py @@ -1,5 +1,8 @@ +#! /usr/bin/env python3 + from logique import LogiqueEchecs from guiTk import PlateauTk -p = PlateauTk(LogiqueEchecs()) +if __name__ == '__main__': + p = PlateauTk(LogiqueEchecs()) diff --git a/S1/Echecs/guiTk.py b/S1/Echecs/guiTk.py index 87dfa37..7e34539 100644 --- a/S1/Echecs/guiTk.py +++ b/S1/Echecs/guiTk.py @@ -15,8 +15,8 @@ class PlateauTk: self.can = None self.chaine = None self.grilleDamier = [] - self.imagesOriginales = [] - self.imagesRedim = [] + self.imagesOriginales = {} + self.imagesRedim = {} self.photos = [] self.grillePions = [] self.animations = [] @@ -58,58 +58,62 @@ class PlateauTk: self.chaine.config(text=texte) # TODO Timeout effacer si parametre / Liste + def nomPiece(self, piece): + tPiece = self.logique.tPiece(piece) + if tPiece == self.logique.PCE_PION: + return 'pion' + elif tPiece == self.logique.PCE_TOUR: + return 'tour' + elif tPiece == self.logique.PCE_CAVALIER: + return 'cavalier' + elif tPiece == self.logique.PCE_FOU: + return 'fou' + elif tPiece == self.logique.PCE_DAME: + return 'dame' + elif tPiece == self.logique.PCE_ROI: + return 'roi' + else: + return False + + def importerImage(self, piece, couleur): + nom = 'sprites/'+self.nomPiece(piece)+couleur+'.gif' + self.imagesOriginales.update({piece:PhotoImage(file=nom)}) + + def importerImages(self): - for piece in range(0, 21): - nom = 'sprites/' - if piece % 10 == 1: - nom += 'pion' - elif piece % 10 == 2: - nom += 'tour' - elif piece % 10 == 3: - nom += 'cavalier' - elif piece % 10 == 4: - nom += 'fou' - elif piece % 10 == 5: - nom += 'dame' - elif piece % 10 == 6: - nom += 'roi' - else: - self.imagesOriginales.append('') - continue - if piece < 10: - nom += 'B' - else: - nom += 'N' - nom += '.gif' - self.imagesOriginales.append(PhotoImage(file=nom)) + 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): + self.imagesRedim.update({piece:self.imagesOriginales[piece].subsample(sample)}) def redimImages(self): sample = int(504 / (PlateauTk.COTE_CASE - PlateauTk.MARGE_PIONS)) - for piece in range(0, 21): - if self.imagesOriginales[piece] != '': - self.imagesRedim.append(self.imagesOriginales[piece]. - subsample(sample)) - else: - self.imagesRedim.append('') + for piece in self.logique.BLANCS: + self.redimImage(piece, sample) + for piece in self.logique.NOIRS: + self.redimImage(piece, sample) # Dessin @staticmethod def caseCouleur(blanc, contexte): if contexte == 1: # Sélectionné return '#a0cefe' if blanc else '#478bd1' - elif contexte == 2: # Possible + elif contexte == 2: # Possible / Victoire return '#bafea0' if blanc else '#6ed147' - elif contexte == 3: # Impossible + elif contexte == 3: # Impossible / Défaite return '#fea0ab' if blanc else '#d14758' else: # Normal return '#ffce9e' if blanc else '#d18b47' def cCase(self, x, y): - couleur = self.caseCouleur(not self.logique.eNoir(x, y), 0) + couleur = self.caseCouleur(self.logique.eCaseBlanche(x, y), 0) return self.can.create_rectangle(x * PlateauTk.COTE_CASE, y * PlateauTk.COTE_CASE, (x + 1) * PlateauTk.COTE_CASE, (y + 1) * PlateauTk.COTE_CASE) def coulCase(self, x, y, contexte): - couleur = self.caseCouleur(not self.logique.eNoir(x, y), contexte) + couleur = self.caseCouleur(self.logique.eCaseBlanche(x, y), contexte) self.can.itemconfig(self.grilleDamier[x][y], fill=couleur, outline=couleur) def coulDamier(self): @@ -147,12 +151,13 @@ class PlateauTk: self.cPion(x, y, j_grilleF[x][y]) # Interaction - @staticmethod - def nomJoueur(joueur, pluriel=True): - if joueur: + def nomJoueur(self, joueur, pluriel=True): + if joueur == self.logique.BLANCS: nom = 'blanc' - else: + elif joueur == self.logique.NOIRS: nom = 'noir' + else: + nom = 'inconnu' if pluriel: nom += 's' return nom @@ -283,7 +288,7 @@ class PlateauTk: self.coulCase(i[0], i[1], 2) self.statut('Poser') self.dEtape = not self.dEtape - else: # Si pas pssible jouer + else: # Si pas possible de jouer self.coulCase(self.dx1, self.dy1, 3) self.animerC(self.dx1, self.dy1) else: # Poser diff --git a/S1/Echecs/logique.py b/S1/Echecs/logique.py index 5a4d331..c2f43dc 100644 --- a/S1/Echecs/logique.py +++ b/S1/Echecs/logique.py @@ -1,9 +1,75 @@ import copy -class LogiqueEchecs: +class Logique: + """ + Logique des jeux sur damier + """ + + PCE_VIDE = 0 + BLANC = True + NOIR = False + + @staticmethod + def eCaseBlanche(xD, yD): + return xD % 2 == yD % 2 + + def cGrille(self): + for x in range(self.CASES_COTE): + 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): + return pion in self.BLANCS + + def ePionNoir(self, pion): + return pion in self.NOIRS + + def ePiece(self, piece): + # return piece != self.PCE_VIDE + return self.ePionBlanc(piece) or self.ePionNoir(piece) + + def tPiece(self, piece): + if self.ePionBlanc(piece): + return piece - self.DECALAGE_BLANCS + elif self.ePionNoir(piece): + return piece - self.DECALAGE_NOIRS + else: + return self.PCE_VIDE + + def aSonTour(self, pion): + return (self.ePionNoir(pion) and self.joueur == self.NOIR) or \ + (self.ePionBlanc(pion) and self.joueur == self.BLANC) + + +class LogiqueEchecs(Logique): + """ + Logique du jeu d'Échecs + """ CASES_COTE = 8 + # Pièces + PCE_PION = 1 + PCE_TOUR = 2 + PCE_CAVALIER = 3 + PCE_FOU = 4 + PCE_DAME = 5 + PCE_ROI = 6 + + DECALAGE_BLANCS = 0 + DECALAGE_NOIRS = 10 + + BLANCS = range(DECALAGE_BLANCS+PCE_PION, DECALAGE_BLANCS+PCE_ROI+1) + NOIRS = range(DECALAGE_NOIRS+PCE_PION, DECALAGE_NOIRS+PCE_ROI+1) + + + # Codes du mouvement MVT_INCONNU = 'Cause inconnue' MVT_OK = 'Valide' MVT_ROQUE = 'Roque' @@ -20,94 +86,65 @@ class LogiqueEchecs: self.grille = [] self.cGrille() self.remplirGrille() - self.joueur = True + self.joueur = self.BLANC self.partieFinie = False self.victorieux = None - @staticmethod - def eNoir(xD, yD): - return xD % 2 != yD % 2 - - def cGrille(self): - for x in range(LogiqueEchecs.CASES_COTE): - colonne = [] - for y in range(LogiqueEchecs.CASES_COTE): - colonne.append(0) - self.grille.append(colonne) - def remplirGrille(self): - speciales = [2, 3, 4, 6, 5, 4, 3, 2] + speciales = [self.PCE_TOUR, self.PCE_CAVALIER, self.PCE_FOU, self.PCE_ROI, self.PCE_DAME] + speciales += speciales[4::-1] for i in range(0, 8): - self.grille[i][0] = speciales[i] + 10 - self.grille[i][1] = 11 - self.grille[i][6] = 1 - self.grille[i][7] = speciales[i] - - def cPion(self, x, y, piece): - """ - """ - self.grille[x][y] = piece - return True - - @staticmethod - def ePionBlanc(pion): - return pion in range(1, 7) - - @staticmethod - def ePionNoir(pion): - return pion in range(11, 17) - - - def aSonTour(self, pion): - return (self.ePionNoir(pion) and self.joueur == False) or \ - (self.ePionBlanc(pion) and self.joueur == True) + self.grille[i][0] = self.DECALAGE_NOIRS + speciales[i] + self.grille[i][1] = self.DECALAGE_NOIRS + self.PCE_PION + self.grille[i][6] = self.DECALAGE_BLANCS + self.PCE_PION + self.grille[i][7] = self.DECALAGE_BLANCS + speciales[i] def mvtPossibleSansEchecPion(self, x1, y1, x2, y2): if x1 == x2 and self.grille[x2][y2] <= 0: # Avance if self.joueur: if y2 == y1 - 1: - return LogiqueEchecs.MVT_OK + return self.MVT_OK elif y1 == 6 and y2 == 4 and self.grille[x1][5] == 0: - return LogiqueEchecs.MVT_OK + return self.MVT_OK else: - return LogiqueEchecs.MVT_N_AUTORISE + return self.MVT_N_AUTORISE else: if y2 == y1 + 1: - return LogiqueEchecs.MVT_OK + return self.MVT_OK elif y1 == 1 and y2 == 3 and self.grille[x1][2] == 0: - return LogiqueEchecs.MVT_OK + return self.MVT_OK else: - return LogiqueEchecs.MVT_N_AUTORISE + return self.MVT_N_AUTORISE elif abs(x1-x2) == 1: # Saut if self.joueur: if y2 == y1 - 1 and \ self.ePionNoir(self.grille[x2][y2]): - return LogiqueEchecs.MVT_OK + return self.MVT_OK else: - return LogiqueEchecs.MVT_N_AUTORISE + return self.MVT_N_AUTORISE else: if y2 == y1 + 1 and \ self.ePionBlanc(self.grille[x2][y2]): - return LogiqueEchecs.MVT_OK + return self.MVT_OK else: - return LogiqueEchecs.MVT_N_AUTORISE + return self.MVT_N_AUTORISE else: - return LogiqueEchecs.MVT_N_AUTORISE + return self.MVT_N_AUTORISE def mvtPossibleSansEchecTour(self, x1, y1, x2, y2): if y1 == y2: sens = (x2-x1)//abs(x2-x1) for x in range(x1+sens, x2, sens): - if self.grille[x][y1] > 0: - return LogiqueEchecs.MVT_OBSTRUCTION + if self.ePiece(self.grille[x][y1]): + return self.MVT_OBSTRUCTION elif x1 == x2: sens = (y2-y1)//abs(y2-y1) for y in range(y1+sens, y2, sens): - if self.grille[x1][y] > 0: - return LogiqueEchecs.MVT_OBSTRUCTION + if self.ePiece(self.grille[x1][y]): + return self.MVT_OBSTRUCTION else: - return LogiqueEchecs.MVT_N_AUTORISE - return LogiqueEchecs.MVT_OK + return self.MVT_N_AUTORISE + return self.MVT_OK def mvtPossibleSansEchecFou(self, x1, y1, x2, y2): if abs(x2-x1) == abs(y2-y1): @@ -121,77 +158,75 @@ class LogiqueEchecs: dist += 1 x += sensX y += sensY - if self.grille[x][y] > 0: + if self.ePiece(self.grille[x][y]): if dist == distTot: - return LogiqueEchecs.MVT_OK # Saut + return self.MVT_OK # Saut else: - return LogiqueEchecs.MVT_OBSTRUCTION - return LogiqueEchecs.MVT_OK # Vide + return self.MVT_OBSTRUCTION + return self.MVT_OK # Vide else: - return LogiqueEchecs.MVT_N_AUTORISE + return self.MVT_N_AUTORISE def mvtPossibleSansEchecCavalier(self, x1, y1, x2, y2): if (abs(x2-x1) == 2 and abs(y2-y1) == 1) or (abs(y2-y1) == 2 and abs(x2-x1) == 1): - return LogiqueEchecs.MVT_OK + return self.MVT_OK else: - return LogiqueEchecs.MVT_N_AUTORISE + return self.MVT_N_AUTORISE def mvtPossibleSansEchec(self, x1, y1, x2, y2): pion = self.grille[x1][y1] if self.aSonTour(pion): if (x1 != x2 or y1 != y2): if not self.aSonTour(self.grille[x2][y2]): - tPion = pion % 10 - if tPion == 1: # Pion + tPion = self.tPiece(pion) + if tPion == self.PCE_PION: # Pion return self.mvtPossibleSansEchecPion(x1, y1, x2, y2) - elif tPion == 2: # Tour + elif tPion == self.PCE_TOUR: # Tour return self.mvtPossibleSansEchecTour(x1, y1, x2, y2) - elif tPion == 3: # Cavalier + elif tPion == self.PCE_CAVALIER: return self.mvtPossibleSansEchecCavalier(x1, y1, x2, y2) - elif tPion == 4: # Fou + elif tPion == self.PCE_FOU: return self.mvtPossibleSansEchecFou(x1, y1, x2, y2) - elif tPion == 5: # Dame + elif tPion == self.PCE_DAME: tour = self.mvtPossibleSansEchecTour(x1, y1, x2, y2) fou = self.mvtPossibleSansEchecFou(x1, y1, x2, y2) - if tour == LogiqueEchecs.MVT_OK or fou == LogiqueEchecs.MVT_OK: - return LogiqueEchecs.MVT_OK - elif tour == LogiqueEchecs.MVT_OBSTRUCTION or fou == LogiqueEchecs.MVT_OBSTRUCTION: - return LogiqueEchecs.MVT_OBSTRUCTION + if tour == self.MVT_OK or fou == self.MVT_OK: + return self.MVT_OK + elif tour == self.MVT_OBSTRUCTION or fou == self.MVT_OBSTRUCTION: + return self.MVT_OBSTRUCTION else: - return LogiqueEchecs.MVT_N_AUTORISE - elif tPion == 6: # Roi + return self.MVT_N_AUTORISE + elif tPion == self.PCE_ROI: if abs(x2-x1) <= 1 and abs(y2-y1) <= 1: - return LogiqueEchecs.MVT_OK + return self.MVT_OK else: - return LogiqueEchecs.MVT_N_AUTORISE + return self.MVT_N_AUTORISE else: - return LogiqueEchecs.MVT_PION_INC + return self.MVT_PION_INC else: - return LogiqueEchecs.MVT_SAUT_AMI + return self.MVT_SAUT_AMI else: - return LogiqueEchecs.MVT_SUR_PLACE + return self.MVT_SUR_PLACE else: - return LogiqueEchecs.MVT_SELECTION - return LogiqueEchecs.MVT_INCONNU + return self.MVT_SELECTION + return self.MVT_INCONNU def mvtPossible(self, x1, y1, x2, y2): test = self.mvtPossibleSansEchec(x1, y1, x2, y2) - if test == LogiqueEchecs.MVT_OK: + 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 = [] - pionRoi = 6 - if not self.joueur: - pionRoi += 10 + pionRoi = self.PCE_ROI + self.DECALAGE_BLANCS if self.joueur else self.DECALAGE_NOIRS roi = [-1, -1] - for x in range(0, LogiqueEchecs.CASES_COTE): - for y in range(0, LogiqueEchecs.CASES_COTE): + for x in range(0, self.CASES_COTE): + for y in range(0, self.CASES_COTE): mvtsPossiblesTousAdverses += copie.mvtsPossiblesSansEchec(x, y) if copie.grille[x][y] == pionRoi: roi = [x, y] if roi in mvtsPossiblesTousAdverses: - return LogiqueEchecs.MVT_ECHEC + return self.MVT_ECHEC else: return test else: @@ -199,33 +234,33 @@ class LogiqueEchecs: def mvtsPossiblesSansEchec(self, x1, y1): tableau = [] - for x2 in range(0, LogiqueEchecs.CASES_COTE): - for y2 in range(0, LogiqueEchecs.CASES_COTE): - if self.mvtPossibleSansEchec(x1, y1, x2, y2) == LogiqueEchecs.MVT_OK: + for x2 in range(0, self.CASES_COTE): + for y2 in range(0, self.CASES_COTE): + if self.mvtPossibleSansEchec(x1, y1, x2, y2) == self.MVT_OK: tableau.append([x2, y2]) return tableau def mvtsPossibles(self, x1, y1): tableau = [] - for x2 in range(0, LogiqueEchecs.CASES_COTE): - for y2 in range(0, LogiqueEchecs.CASES_COTE): - if self.mvtPossible(x1, y1, x2, y2) == LogiqueEchecs.MVT_OK: + for x2 in range(0, self.CASES_COTE): + for y2 in range(0, self.CASES_COTE): + if self.mvtPossible(x1, y1, x2, y2) == self.MVT_OK: tableau.append([x2, y2]) return tableau def dPionSansEchec(self, x1, y1, x2, y2): test = self.mvtPossibleSansEchec(x1, y1, x2, y2) - if test == LogiqueEchecs.MVT_OK: - self.grille[x1][y1], self.grille[x2][y2] = 0, self.grille[x1][y1] + if test == self.MVT_OK: + self.grille[x1][y1], self.grille[x2][y2] = self.PCE_VIDE, self.grille[x1][y1] self.joueur = not self.joueur def vEchecMat(self): """ Vérifie si le joueur actuel est en échec et mat et prend les mesures nécessiares. - (CÀD Le joueur actuel ne peut effectuer aucun mouvement) + (Ici vrai en cas de "pat") """ - for x in range(0, LogiqueEchecs.CASES_COTE): - for y in range(0, LogiqueEchecs.CASES_COTE): + for x in range(0, self.CASES_COTE): + for y in range(0, self.CASES_COTE): if len(self.mvtsPossibles(x, y)) > 0: return False self.partieFinie = True @@ -240,12 +275,12 @@ class LogiqueEchecs: 'deplacer': [], # Pions à déplacer 'supprimer': [], # Pions à supprimer } - if test == LogiqueEchecs.MVT_OK: + if test == self.MVT_OK: retour['valide'] = True - if self.grille[x2][y2] > 0: + if self.ePiece(self.grille[x2][y2]): retour['supprimer'].append([x2, y2]) retour['deplacer'].append([x1, y1, x2, y2]) - self.grille[x1][y1], self.grille[x2][y2] = 0, self.grille[x1][y1] + self.grille[x1][y1], self.grille[x2][y2] = self.PCE_VIDE, self.grille[x1][y1] self.joueur = not self.joueur self.vEchecMat() return retour \ No newline at end of file