├── .gitignore ├── .idea ├── PolyChess.iml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── CDC_polyChess0.pdf ├── Organisation des classes.pub ├── PolychessGanttFinal.mpp ├── README.md ├── Screenshots ├── CaptureChessInterface.PNG └── Reine blanche.png ├── chessboard.py ├── ia.py ├── main.py └── rules.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | main.py 106 | main.py 107 | -------------------------------------------------------------------------------- /.idea/PolyChess.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 1580218726439 36 | 43 | 44 | 45 | 46 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /CDC_polyChess0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paul-mathieu/PolyChess/d2d8cb34b338c778977304978036309bb129fb91/CDC_polyChess0.pdf -------------------------------------------------------------------------------- /Organisation des classes.pub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paul-mathieu/PolyChess/d2d8cb34b338c778977304978036309bb129fb91/Organisation des classes.pub -------------------------------------------------------------------------------- /PolychessGanttFinal.mpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paul-mathieu/PolyChess/d2d8cb34b338c778977304978036309bb129fb91/PolychessGanttFinal.mpp -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PolyChess 2 | Projet de création d'un jeu d'échec en Python 3 | 4 | # Objectif 5 | Ce dépot à pour but de créer un jeu d'échec. 6 | Le programme permet de jouer aux échecs et peut déplacer les pièces selon leur mouvements officels, dans un échiquier de 8x8 cases. Le programme permet de faire des parties entre 2 joueurs ou avec un joueur et une IA. 7 | 8 | `Voici la représentation de l'échiquier de base :` 9 | 10 | 11 | 12 | Avec des chiffres de 1 à 8 pour la hauteur et des lettres de A à H pour la largeur. 13 | 14 | `Voici la représentation console qu'on obtient lors de l'exécution du programme :` 15 | 16 | 17 | 18 | On ne peut jouer qu'à la version standard des échecs, il n'y a pas de variantes possible. 19 | 20 | # Fonctionnement 21 | 22 | Pour ceux qui ne connaissent pas le fonctionnement des échecs, en voici un rappel. 23 | Le jeu oppose un joueur aux pièces blanches contre un joueur aux pièces noires. Le but est de mettre en échec et mat le roi adverse (c'est à dire dans l'impossibilité de se déplacer sans être menacé), à l'aide de ses propres pièces. Les pièces peuvent se déplacer dans l'échiquier selon différentes règles. 24 | * Le Pion : il peut se déplacer uniquement en avant dans le sens des chriffres (vers la ligne 8 si le joueur à les pièces blanches et vers la ligne 1 si le joueur à les pièces noires). Le pion à trois déplacements possible. Le déplacement classique, il avance d'une case vers une case vide. Le Premier Déplacement, si le pion ne s'est pas encore déplacé, il peut avancer de 2 cases en passant par une case vide, et arrive sur une autre case vide. La Prise, le pion peut prendre une pièce adverse située en diagonale vers l'avant (exemple : un pion blanc situé en b2 (coordonnées de l'échiquier) peut prendre en a3 ou c3). À part pour le pion, toute les pièces ont un déplacement et une prise équivalente, autrement dit, un déplacement sur une pièce adverse est possible et il s'agit d'une prise. Voici leurs déplacements : 25 | * La Tour : elle n'a qu'un seul déplacement, en ligne droite jusqu'à une case vide, ou jusqu'à une pièce adverse dont elle prendra la position. Sans limite de nombre de cases. 26 | * Le Roi : c'est la pièce a protéger, elle peut se déplacer ou prendre sur toute ses cases adjacentes (jusqu'à 8 cases autour d'elle). 27 | * Le Fou : il se déplace en diagonale, sans limite de case. 28 | * La Dame : c'est la pièce la plus puissante, elle dispose à la fois des déplacements de la tour et du fou. 29 | * Le Cavalier : c'est la seule pièce du jeu qui peut passer par dessus les pièces (adverses comme alliées). Son déplacement s'effectue en forme de "L", soit de deux cases en ligne droite dans n'importe quel direction et d'une case dans une direction parallèle à cette dernière. Le cavalier peut avoir jusqu'à 8 choix possible. 30 | 31 | 32 | 33 | Il existe des déplacements spéciaux que le programme permet : 34 | * Le roque : il existe deux types de roque, le petit et le grand roque. Le petit roque consiste a déplacer le roi de deux cases vers la tour, et la tour de deux cases vers le roi, ce qui a pour conséquence de faire passer la tour par dessus le roi. Le grand roque est comme le petit, sauf que la tour se déplace de 3 cases. Il est possible d'effectuer un roque qu'une seule fois par partie. Un joueur peut roquer uniquement si la tour et le roi n'ont pas quitter leur position initial, de plus, les cases entre la tour et le roi doivent être inocupées. Le roi peut cependant avoir subis des échecs au préalable, du moment qu'il n'a pas bougé. 35 | * Prise en passant : elle concerne les pions. Si un pion adverse est situé sur la 5e rangée (ligne n4 ou n5 si le joueur est blanc ou noir) et qu'on avance un pion allié d'une colonne adjacente de 2 cases, jusqu'à rejoindre la rangée du pion adverse, ce dernier peut alors manger le pion adverse en se déplaçant en diagonale et ainsi se situer sur la case de même colonne que le pion allié et sur la rangée inférieur au pion allié. Cette action n'est possible que le coup immédiatement suivant le déplacement du pion allié. 36 | * Pion à l'arrivée (promotion) : Lorsqu'un pion rejoint la dernière rangée (la 8e pour les blancs et la 1ere pour les noirs) il se transforme en n'importe quel autre pièce alliée, sauf le roi, et dispose de toutes les propriétés de la pièce transformée. 37 | 38 | 39 | Le programme permet donc aux pièces de se déplacer uniquement selon leur déplacements expliqués précédemment. 40 | Pendant la partie, le programme permet le déplacement de pièces de manière classique mais est aussi capable de reconnaitre certaines situations et ainsi modifier les coups possibles. 41 | * Il peut détecter lorsque qu'un roi est en échec. Le programme empèche un joueur de se mettre en échec pendant son propre tour, ce qui a pour conséquence d'obliger un joueur à ne plus être en échec si son adversaire l'a mis en échec. Le déplacement d'une pièce doit donc remplir les conditions de déplacements classique ainsi que la non-mise en échec de son propre roi. 42 | * Le programme est capable de reconnaitre un échec et mat, ce qui signifie que le roi est mis en échec et que le joueur ne dispose d'aucun coup pour ne plus être en échec, il a donc perdu, le programme termine la partie 43 | 44 | * Cas où le programme annonce une partie nulle : 45 | * Le Pat : c'est lorsqu'un joueur n'est pas en échec mais il ne peut plus rien jouer, sans se mettre en échec par lui même. Le programme arrête alors aussi la partie : il n'y a pas de vainqueur. 46 | * Absence de matériel : les deux joueurs n'ont plus de pièces à part leur roi respectif. Cela fonctionne aussi si un joueur n'a plus qu'un roi et que l'autre n'a qu'un roi et un seul fou, ou un seul cavalier. En effet, il est impossible de mettre en échec et mat sans matériel, ou avec un seul fou ou cavalier. 47 | * Répétition : si une postition est répétée trois fois, la partie s'arrête. 48 | * Les 50 coups : si les joueurs jouent 50 coups sans déplacer un pion ou prendre une pièce adverse, la partie s'arrête. 49 | 50 | -------------------------------------------------------------------------------- /Screenshots/CaptureChessInterface.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paul-mathieu/PolyChess/d2d8cb34b338c778977304978036309bb129fb91/Screenshots/CaptureChessInterface.PNG -------------------------------------------------------------------------------- /Screenshots/Reine blanche.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paul-mathieu/PolyChess/d2d8cb34b338c778977304978036309bb129fb91/Screenshots/Reine blanche.png -------------------------------------------------------------------------------- /chessboard.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Thu Jan 9 08:28:34 2020 4 | 5 | @author: gourets 6 | """ 7 | 8 | # -*- coding: utf-8 -*- 9 | """ 10 | Created on Wed Jan 8 13:41:49 2020 11 | 12 | @author: ragueney 13 | """ 14 | 15 | """ 16 | 17 | 18 | """ 19 | 20 | 21 | 22 | from functools import reduce 23 | from rules import Piece 24 | import copy 25 | 26 | 27 | 28 | class Echiquier: 29 | 30 | 31 | def __init__(self): 32 | 33 | self.estEchec = {"blanc" : False, "noir" : False} 34 | 35 | self.positions = \ 36 | [Piece('Tour', 'noir'), 37 | Piece('Cavalier', 'noir'), 38 | Piece('Fou','noir'), 39 | Piece('Dame', 'noir'), 40 | Piece('Roi','noir'), 41 | Piece('Fou', 'noir'), 42 | Piece('Cavalier', 'noir'), 43 | Piece('Tour', 'noir')] + \ 44 | \ 45 | [Piece('Pion', 'noir')] * 8 + \ 46 | \ 47 | [Piece()] * 8 * 4 + \ 48 | \ 49 | [Piece('Pion', 'blanc')] * 8 + \ 50 | \ 51 | [Piece('Tour', 'blanc'), 52 | Piece('Cavalier', 'blanc'), 53 | Piece('Fou','blanc'), 54 | Piece('Dame', 'blanc'), 55 | Piece('Roi', 'blanc'), 56 | Piece('Fou', 'blanc'), 57 | Piece('Cavalier', 'blanc'), 58 | Piece('Tour', 'blanc')] 59 | 60 | # self.positions = \ 61 | # [Piece()] * 8 + \ 62 | # \ 63 | # [Piece('Tour', 'noir'), Piece('Cavalier', 'noir'), 64 | # Piece('Fou','noir'), 65 | # Piece('Dame', 'noir'), Piece('Roi','noir'), 66 | # Piece('Fou', 'noir'), 67 | # Piece('Cavalier', 'noir'), Piece('Tour', 'noir')] + \ 68 | # \ 69 | # [Piece()] * 8 * 4 + \ 70 | # \ 71 | # [Piece('Tour', 'blanc'), Piece('Cavalier', 'blanc'), 72 | # Piece('Fou','blanc'), 73 | # Piece('Dame', 'blanc'), Piece('Roi', 'blanc'), 74 | # Piece('Fou', 'blanc'), 75 | # Piece('Cavalier', 'blanc'), Piece('Tour', 'blanc')] + \ 76 | # \ 77 | # [Piece()] * 8 78 | # 79 | def get_piece(self, index): 80 | return self.positions[index] 81 | 82 | # def testCouleur(self, index): 83 | # index = self.nomCaseToIndex(position) 84 | # piece = self.get_piece(index) 85 | 86 | # return piece.couleur 87 | #============================================================================== 88 | # Construction de l'échiquier 89 | #============================================================================== 90 | 91 | def coordonnees(): 92 | return [lettre + str(chiffre) for chiffre in range(1,9) for lettre in ['A','B','C','D','E','F','G','H']] 93 | 94 | 95 | #============================================================================== 96 | # Affichage 97 | #============================================================================== 98 | #Methode qui affiche une representation schematique d'un echiquier dans la console. 99 | 100 | def afficher(self): 101 | 102 | lettres = reduce(lambda ele1, ele2 : ele1 + ele2, [" " + element + " " for element in ['A','B','C','D','E','F','G','H']]) 103 | interlignes = " " + reduce(lambda ele1, ele2 : ele1 + ele2, ["-" * 4 + " "] * 8) 104 | 105 | print(" " * 60 + "/") 106 | print(" ".join(["—","-"] * 15)) 107 | print(" " * 60 + "\\") 108 | 109 | print(" " + lettres) 110 | print(interlignes) 111 | 112 | numLigne = 8 113 | indexPosition = 0 114 | 115 | for piece in self.positions: 116 | 117 | # print(ligne) 118 | 119 | if indexPosition % 8 == 0: 120 | print(str(numLigne), end = " |") 121 | 122 | if piece.nom != piece.pieceVide: 123 | 124 | print(" " + piece.nomAffichage + " ", end = "|") 125 | 126 | else: 127 | 128 | print(" ", end = "|") 129 | 130 | 131 | if (indexPosition + 1) % 8 == 0: 132 | 133 | print(" " + str(numLigne)) 134 | 135 | print(interlignes) 136 | 137 | numLigne -= 1 138 | 139 | indexPosition += 1 140 | 141 | print(" " + lettres) 142 | 143 | 144 | 145 | # A B C D E F G H 146 | # ---- ---- ---- ---- ---- ---- ---- ---- 147 | # 8 | Tn | Cn | Fn | Dn | Rn | Fn | Cn | Tn | 8 148 | # ---- ---- ---- ---- ---- ---- ---- ---- 149 | # 7 | in | in | in | in | in | in | in | in | 7 150 | # ---- ---- ---- ---- ---- ---- ---- ---- 151 | # 6 | | | | | | | | | 6 152 | # ---- ---- ---- ---- ---- ---- ---- ---- 153 | # 5 | | | | | | | | | 5 154 | # ---- ---- ---- ---- ---- ---- ---- ---- 155 | # 4 | | | | | | | | | 4 156 | # ---- ---- ---- ---- ---- ---- ---- ---- 157 | # 3 | | | | | | | | | 3 158 | # ---- ---- ---- ---- ---- ---- ---- ---- 159 | # 2 | ib | ib | ib | ib | ib | ib | ib | ib | 2 160 | # ---- ---- ---- ---- ---- ---- ---- ---- 161 | # 1 | Tb | Cb | Fb | Db | Rb | Fb | Cb | Tb | 1 162 | # ---- ---- ---- ---- ---- ---- ---- ---- 163 | # A B C D E F G H 164 | 165 | 166 | 167 | #Permet de montrer les coups possibles au joueur. 168 | 169 | def afficherCoupsPossibles(self, nomCase): 170 | 171 | lettres = reduce(lambda ele1, ele2 : ele1 + ele2, [" " + element + " " for element in ['A','B','C','D','E','F','G','H']]) 172 | interlignes = " " + reduce(lambda ele1, ele2 : ele1 + ele2, ["-" * 4 + " "] * 8) 173 | 174 | coupsPossibles = self.listeCoupsPossibles(nomCase) 175 | 176 | couleur = self.positions[self.nomCaseToIndex(nomCase)].couleur 177 | couleurOpposee = 'noir' if couleur == 'blanc' else 'blanc' 178 | 179 | print(" " * 60 + "/") 180 | print(" ".join(["—","-"] * 15)) 181 | print(" " * 60 + "\\") 182 | 183 | print(" " + lettres) 184 | print(interlignes) 185 | 186 | numLigne = 8 187 | indexPosition = 0 188 | 189 | for piece in self.positions: 190 | 191 | # print(ligne) 192 | 193 | if indexPosition % 8 == 0: 194 | print(str(numLigne), end = " |") 195 | 196 | 197 | if indexPosition == self.nomCaseToIndex(nomCase): 198 | 199 | print("#" + piece.nomAffichage + "#", end = "|") 200 | 201 | elif indexPosition in coupsPossibles: 202 | 203 | if piece.couleur == couleurOpposee: 204 | 205 | print("<" + piece.nomAffichage + ">", end = "|") 206 | 207 | else: 208 | 209 | print(" <> ", end = "|") 210 | 211 | elif piece.nom != piece.pieceVide: 212 | 213 | print(" " + piece.nomAffichage + " ", end = "|") 214 | 215 | else: 216 | 217 | print(" ", end = "|") 218 | 219 | 220 | 221 | if (indexPosition + 1) % 8 == 0: 222 | 223 | print(" " + str(numLigne)) 224 | 225 | print(interlignes) 226 | 227 | numLigne -= 1 228 | 229 | indexPosition += 1 230 | 231 | print(" " + lettres) 232 | 233 | 234 | 235 | 236 | 237 | #============================================================================== 238 | # Déplacement 239 | #============================================================================== 240 | 241 | def deplacerPiece(self, nomCaseDepart, nomCaseArrivee): 242 | indexDep = self.nomCaseToIndex(nomCaseDepart) 243 | indexArr = self.nomCaseToIndex(nomCaseArrivee) 244 | 245 | # Petit roque noir 246 | if indexDep == 4 and indexArr == 6 and self.positions[4].nom == 'Roi' and indexArr in self.listeDesCoupsAvecEchecNoir(4) : 247 | self.positions[indexArr] = self.positions[indexDep] 248 | self.positions[indexDep] = Piece() 249 | self.positions[5] = self.positions[7] 250 | self.positions[7] = Piece() 251 | 252 | # Petit roque blanc 253 | if indexDep == 60 and indexArr == 62 and self.positions[60].nom == 'Roi' and indexArr in self.listeDesCoupsAvecEchecBlanc(60) : 254 | self.positions[indexArr] = self.positions[indexDep] 255 | self.positions[indexDep] = Piece() 256 | self.positions[61] = self.positions[63] 257 | self.positions[63] = Piece() 258 | 259 | # Grand roque noir 260 | if indexDep == 4 and indexArr == 2 and self.positions[4].nom == 'Roi' and indexArr in self.listeDesCoupsAvecEchecNoir(4) : 261 | self.positions[indexArr] = self.positions[indexDep] 262 | self.positions[indexDep] = Piece() 263 | self.positions[3] = self.positions[0] 264 | self.positions[0] = Piece() 265 | 266 | # Grand roque blanc 267 | if indexDep == 60 and indexArr == 58 and self.positions[60].nom == 'Roi' and indexArr in self.listeDesCoupsAvecEchecBlanc(60) : 268 | self.positions[indexArr] = self.positions[indexDep] 269 | self.positions[indexDep] = Piece() 270 | self.positions[59] = self.positions[56] 271 | self.positions[56] = Piece() 272 | 273 | if not self.positions[indexDep].pieceABouge: 274 | self.positions[indexDep].pieceABouge = True 275 | 276 | 277 | 278 | 279 | if indexArr in self.listeDesCoupsAvecEchecBlanc(indexDep) and self.get_piece(indexDep).couleur == 'blanc': 280 | self.positions[indexArr] = self.positions[indexDep] 281 | self.positions[indexDep] = Piece() 282 | 283 | 284 | if indexArr in self.listeDesCoupsAvecEchecNoir(indexDep) and self.get_piece(indexDep).couleur == 'noir': 285 | self.positions[indexArr] = self.positions[indexDep] 286 | self.positions[indexDep] = Piece() 287 | 288 | 289 | 290 | def deplacerPieceEnIndex(self, indexDepart, indexArrivee): 291 | if not self.positions[indexDepart].pieceABouge: 292 | self.positions[indexDepart].pieceABouge = True 293 | if indexArrivee in self.listeCoupsPossibles(self.indexToNomCase(indexDepart)): 294 | 295 | if not self.positions[indexDepart]: 296 | self.positions[indexDepart] = True 297 | 298 | self.positions[indexArrivee] = self.positions[indexDepart] 299 | self.positions[indexDepart] = Piece() 300 | 301 | def deplacementForce(self, indexDepart, indexArrivee): 302 | if not self.positions[indexDepart].pieceABouge: 303 | self.positions[indexDepart].pieceABouge = True 304 | self.positions[indexArrivee] = self.positions[indexDepart] 305 | self.positions[indexDepart] = Piece() 306 | 307 | 308 | def listeDesCoupsAvecEchecBlanc(self, index): 309 | 310 | listeDesCoupsPossibles = self.listeCoupsPossiblesEntreeIndex(index) 311 | listeDesCoupsAEnlever = [] 312 | 313 | echiquierTemporaire = self 314 | 315 | positionsPrecedentes = copy.copy(self.positions) 316 | positionsPrecedentes_liste = list(map(lambda x : (x.nom, x.couleur, x.pieceABouge), positionsPrecedentes)) 317 | 318 | 319 | 320 | for mouvement in listeDesCoupsPossibles: 321 | 322 | echiquierTemporaire.deplacementForce(index, mouvement) 323 | # if not echiquierTemporaire.isEchecBlanc(): 324 | # return listeDesCoupsPossibles 325 | 326 | if echiquierTemporaire.isEchecBlanc(): 327 | # echiquierTemporaire.afficher() 328 | listeDesCoupsAEnlever.append(mouvement) 329 | print(listeDesCoupsAEnlever) 330 | 331 | 332 | self.positions = [Piece(element[0], element[1], element[2]) for element in positionsPrecedentes_liste] 333 | 334 | 335 | return [index for index in listeDesCoupsPossibles if not index in listeDesCoupsAEnlever] 336 | 337 | def listeDesCoupsAvecEchecNoir(self, index): 338 | 339 | listeDesCoupsPossibles = self.listeCoupsPossiblesEntreeIndex(index) 340 | listeDesCoupsAEnlever = [] 341 | echiquierTemporaire = self 342 | positionsPrecedentes = copy.copy(self.positions) 343 | positionsPrecedentes_liste = list(map(lambda x : (x.nom, x.couleur, x.pieceABouge), positionsPrecedentes)) 344 | 345 | # if not self.isEchecNoir(): 346 | # return listeDesCoupsPossibles 347 | 348 | for mouvement in listeDesCoupsPossibles: 349 | 350 | echiquierTemporaire.deplacementForce(index, mouvement) 351 | if echiquierTemporaire.isEchecNoir(): 352 | listeDesCoupsAEnlever.append(mouvement) 353 | 354 | self.positions = [Piece(element[0], element[1], element[2]) for element in positionsPrecedentes_liste] 355 | 356 | return [index for index in listeDesCoupsPossibles if not index in listeDesCoupsAEnlever] 357 | 358 | def listeDesCoupsAvecVerif(self, index, couleur): 359 | if couleur == 'noir' : 360 | L = [] 361 | for k in self.listeDesCoupsAvecEchecNoir(index) : 362 | L.append(self.indexToNomCase(k)) 363 | return L 364 | else: 365 | L=[] 366 | for k in self.listeDesCoupsAvecEchecBlanc(index): 367 | L.append(self.indexToNomCase(k)) 368 | return L 369 | 370 | 371 | def listePiecesPouvantEtreDeplaceesFormatCaseAvecVerif(self, couleur): 372 | listCoupsPouvantEtreDeplacees=[] 373 | for element in self.listePiecesPouvantEtreDeplaceesFormatCase(couleur): 374 | if not self.listeDesCoupsAvecVerif(self.nomCaseToIndex(element),couleur) == []: 375 | listCoupsPouvantEtreDeplacees.append(element) 376 | return listCoupsPouvantEtreDeplacees 377 | #============================================================================== 378 | # Vérification déplacement dans la zone 379 | #============================================================================== 380 | 381 | def listeCoupsPossibles(self, nomCase): 382 | 383 | indexCase = self.nomCaseToIndex(nomCase) 384 | 385 | return self.listeCoupsPossiblesEntreeIndex(indexCase) 386 | 387 | 388 | def listeCoupsPossiblesEntreeIndex(self, indexCase): 389 | 390 | if self.positions[indexCase].nom == self.positions[indexCase].pieceVide: 391 | return [] 392 | 393 | if self.positions[indexCase].nom == 'Pion': 394 | return self.positions[indexCase].listeCoupsPossiblesPion(indexCase, self) 395 | 396 | if self.positions[indexCase].nom == 'Tour': 397 | return self.positions[indexCase].listeCoupsPossiblesTour(indexCase, self) 398 | 399 | if self.positions[indexCase].nom == 'Fou': 400 | return self.positions[indexCase].listeCoupsPossiblesFou(indexCase, self) 401 | 402 | if self.positions[indexCase].nom == 'Cavalier': 403 | return self.positions[indexCase].listeCoupsPossiblesCavalier(indexCase, self) 404 | 405 | if self.positions[indexCase].nom == 'Dame': 406 | return self.positions[indexCase].listeCoupsPossiblesDame(indexCase, self) 407 | 408 | if self.positions[indexCase].nom == 'Roi': 409 | return self.positions[indexCase].listeCoupsPossiblesRoi(indexCase, self) 410 | 411 | 412 | def listeCoupsPossiblesFormatCase(self, nomCase): 413 | 414 | return [self.indexToNomCase(index) for index in self.listeCoupsPossibles(nomCase)] 415 | 416 | 417 | def listePiecesPouvantEtreDeplacees(self, couleur): 418 | 419 | liste = [] 420 | 421 | for index in range(64): 422 | 423 | if self.positions[index].couleur == couleur: 424 | 425 | if len(self.listeCoupsPossibles(self.indexToNomCase(index))) > 0: 426 | 427 | liste.append(index) 428 | 429 | return liste 430 | 431 | def listePiecesPouvantEtreDeplaceesFormatCase(self, nomCase): 432 | 433 | return [self.indexToNomCase(index) for index in self.listePiecesPouvantEtreDeplacees(nomCase)] 434 | 435 | 436 | 437 | #============================================================================== 438 | # Fin du jeu 439 | #============================================================================== 440 | 441 | def isEchecBlanc(self): 442 | 443 | #on recupere la podsiton du roi blanc 444 | 445 | listePositionsRoi1 = [] 446 | index = 0 447 | for piece in self.positions: 448 | if piece.nom == 'Roi' and piece.couleur=='blanc': 449 | listePositionsRoi1.append(index) 450 | index += 1 451 | #si la liste des pieces menancant le roi n'est pas vide, alors il y a echec. 452 | if self.nombreDePiecesAdversesPouvantMangerLaPiece(listePositionsRoi1[0])!=0: 453 | return True 454 | else : 455 | return False 456 | 457 | 458 | def isEchecNoir(self): 459 | 460 | 461 | listePositionsRoi2 = [] 462 | index = 0 463 | for piece in self.positions: 464 | if piece.nom == 'Roi' and piece.couleur=='noir': 465 | listePositionsRoi2.append(index) 466 | index += 1 467 | 468 | if self.nombreDePiecesAdversesPouvantMangerLaPiece(listePositionsRoi2[0])!=0: 469 | return True 470 | else : 471 | return False 472 | 473 | 474 | 475 | 476 | 477 | # Si la piece est le roi blanc, qu'il est en echec et qu'il n'a plus de coup disponible, alors il y a echec et mat. 478 | def isEchecEtMatBlanc(self): 479 | for i in range(0,63): 480 | if self.get_piece(i).couleur == 'blanc' and self.listeDesCoupsAvecEchecBlanc(i) != []: 481 | return False 482 | return True 483 | 484 | def isEchecEtMatNoir(self): 485 | for i in range(0,63): 486 | if self.get_piece(i).couleur == 'noir' and self.listeDesCoupsAvecEchecNoir(i) != []: 487 | return False 488 | return True 489 | 490 | 491 | 492 | 493 | 494 | def couleurEchecEtMat(self): 495 | 496 | if not self.isEchecEtMat(): 497 | return None 498 | 499 | return 'blanc' if list(filter(lambda piece : piece.nom == 'Roi', self.positions))[0].couleur == 'noir' else 'noir' 500 | 501 | 502 | #============================================================================== 503 | # Autres fonctions 504 | #============================================================================== 505 | 506 | def nomCaseToIndex(self, nomCase): 507 | 508 | if not type(nomCase) is str: 509 | return 'erreur saisie' 510 | 511 | lettres = ['A','B','C','D','E','F','G','H'] 512 | lig, col = 8 - int(nomCase[1]), lettres.index(nomCase[0]) + 1 513 | 514 | return lig * 8 + col - 1 515 | 516 | def indexToNomCase(self, indexCase): 517 | 518 | return ['A','B','C','D','E','F','G','H'][indexCase % 8] + str(8 - indexCase // 8) 519 | 520 | #print("‎• or <>") 521 | 522 | def listeIndexMangeantLaPiece(self, indexPiece): 523 | listeIndex = [] 524 | 525 | for indexDepart in self.listePiecesPouvantEtreDeplacees(self.positions[indexPiece].couleurOpposee): 526 | 527 | for indexArrivee in self.listeCoupsPossiblesEntreeIndex(indexDepart): 528 | 529 | if indexArrivee == indexPiece: 530 | 531 | listeIndex.append(indexDepart) 532 | break 533 | 534 | 535 | return listeIndex 536 | 537 | 538 | def leDeplacementMangeUnePiece(self, indexArrivee): 539 | return self.positions[indexArrivee].couleur != self.positions[0].pieceVide 540 | 541 | 542 | 543 | def nombreDePiecesAdversesPouvantMangerLaPiece(self, index): 544 | return len(self.listeIndexMangeantLaPiece(index)) 545 | 546 | def petitRoqueNoirPossible(self): 547 | return self.positions[7].pieceABouge == False and self.positions[4].pieceABouge == False and self.positions[6].nom == self.positions[6].pieceVide and self.positions[5].nom == self.positions[5].pieceVide 548 | 549 | def grandRoqueNoirPossible(self): 550 | return self.positions[0].pieceABouge == False and self.positions[4].pieceABouge == False and self.positions[1].nom == self.positions[1].pieceVide and self.positions[2].nom == self.positions[2].pieceVide and self.positions[3].nom == self.positions[3].pieceVide 551 | 552 | def petitRoqueBlancPossible(self): 553 | return self.positions[60].pieceABouge == False and self.positions[63].pieceABouge == False and self.positions[61].nom == self.positions[61].pieceVide and self.positions[62].nom == self.positions[62].pieceVide 554 | 555 | 556 | def grandRoqueBlancPossible(self): 557 | return self.positions[60].pieceABouge == False and self.positions[56].pieceABouge == False and self.positions[59].nom == self.positions[59].pieceVide and self.positions[58].nom == self.positions[58].pieceVide and self.positions[57].nom == self.positions[57].pieceVide 558 | 559 | 560 | 561 | # def roiOuTourNoireABouge(self, indexCase): 562 | # if (self.positions[60].nom == 'Roi' and self.aBouge(60) == 0) or ((indexCase == 56 or indexCase== 63) and self.positions[indexCase].nom == 'Tour' and self.aBouge(56) == 0 and self.aBouge(63) == 0): 563 | # return 0 564 | # else: 565 | # return 1 566 | 567 | # def petitRoqueBlanc(self, indexPiece): 568 | # if self.positions[1].nom == self.positions[1].pieceVide and 569 | 570 | 571 | # ============================================================================= 572 | # fonction pour les calculs de points de l'IA 573 | # ============================================================================= 574 | 575 | #moins de points si la piece peut se faire manger 576 | def coefficientPointsSiPeutEtreMangee(self, indexArrivee): 577 | 578 | nbPiecePouvantManger = self.nombreDePiecesAdversesPouvantMangerLaPiece(indexArrivee) 579 | 580 | #si len = 0 581 | if nbPiecePouvantManger == 0: 582 | return 1 583 | 584 | #si len = 1 585 | if nbPiecePouvantManger == 1: 586 | return 1.5 587 | 588 | #si len > 1 589 | if nbPiecePouvantManger > 1 : 590 | return 1.5 + .2 * (nbPiecePouvantManger - 1) 591 | 592 | 593 | 594 | 595 | 596 | 597 | #moins de points si elle n'a aucune piece de la meme couleur autour 598 | def coefficientPointsSiPieceMemeCouleurProche(self, indexArrivee, couleur): 599 | 600 | pass 601 | 602 | -------------------------------------------------------------------------------- /ia.py: -------------------------------------------------------------------------------- 1 | """ 2 | #ia 3 | """ 4 | 5 | 6 | class IA: 7 | 8 | def __init__(self, echiquier, couleur): 9 | 10 | self.echiquier = echiquier 11 | 12 | self.couleur = couleur 13 | self.couleurOpposee = 'noir' if couleur == 'blanc' else 'blanc' 14 | 15 | self.valeurPieces = { 16 | ('Pion', self.couleur): -10, 17 | ('Tour', self.couleur): -50, 18 | ('Cavalier', self.couleur): -30, 19 | ('Fou', self.couleur): -30, 20 | ('Dame', self.couleur): -90, 21 | ('Roi', self.couleur): -900, 22 | ('Pion', self.couleurOpposee): 10, 23 | ('Tour', self.couleurOpposee): 50, 24 | ('Cavalier', self.couleurOpposee): 30, 25 | ('Fou', self.couleurOpposee): 30, 26 | ('Dame', self.couleurOpposee): 90, 27 | ('Roi', self.couleurOpposee): 900 28 | } 29 | 30 | def arbre_nFils_pProfondeur(self, n=5, echiquier=None, 31 | p=3, niveauActuel=0): 32 | 33 | """ 34 | Cette fonction permet d'optenir un TREE par recursivite. 35 | 36 | Elle renvoie les n meilleurs mouvements à realiser à partir 37 | d'un nombre de points. 38 | 39 | Le nombre de points est definit en fonction d'une valeur affectee 40 | à la piece ainsi qu'avec des points en moins si elle peut être 41 | mangée après le déplacement. 42 | 43 | Chaque mouvement contient une liste des n meilleurs mouvements 44 | suivants, si l'adversaire aurait joue le coups suivant rapportant 45 | le plus grand nombre de points. 46 | """ 47 | 48 | if echiquier == None: 49 | echiquier = self.echiquier 50 | 51 | listeMouvements = [] 52 | niveauActuel += 1 53 | 54 | # si le niveau actuel est le maximum souhaité (ici 5), on ne va pas plus profondement 55 | if not niveauActuel > 3: 56 | 57 | # ================================================================= 58 | # récupération des meilleurs mouvements 59 | # ================================================================= 60 | 61 | listeMouvements = self.listeTousMeilleursMouvements(echiquier, niveauActuel) 62 | 63 | # on garde les meilleures valeurs 64 | listeMouvements = listeMouvements[0:n] 65 | 66 | # ================================================================= 67 | # pour tous les n meilleurs mouvements 68 | # ================================================================= 69 | 70 | # ~~ (ajout pour chaque mouvements des n meilleurs ~~ 71 | # ~~ mouvements suivants) ~~ 72 | 73 | for mouvement in listeMouvements: 74 | if niveauActuel == 1: 75 | print(( 76 | echiquier.indexToNomCase(mouvement.indexDepart), 77 | echiquier.indexToNomCase(mouvement.indexArrivee) 78 | )) 79 | # le nouvel echiquier qui contiendra la piece deplacee 80 | echiquierTemp = echiquier 81 | 82 | # ============================================================= 83 | # l'IA joue 84 | # ============================================================= 85 | 86 | echiquierTemp.deplacerPieceEnIndex(mouvement.indexDepart, 87 | mouvement.indexArrivee) 88 | 89 | # ============================================================= 90 | # l'adversaire joue (théorie) 91 | # ============================================================= 92 | 93 | # le nouvel echiquier doit contenir le meilleur coup de l'adversaire 94 | meilleurCoupAdversaire = self.listeTousMeilleursMouvements(echiquierTemp, 95 | niveauActuel) 96 | # meilleur mouvement sans profondeur 97 | meilleurCoupAdversaire = meilleurCoupAdversaire[0] 98 | 99 | # modification de l'échiquier 100 | echiquierTemp.deplacerPieceEnIndex(meilleurCoupAdversaire.indexDepart, 101 | meilleurCoupAdversaire.indexArrivee) 102 | 103 | # ============================================================= 104 | # mouvements possibles ensuite (recursivite) 105 | # ============================================================= 106 | 107 | # variable avec les mouvements suivants 108 | listeMouvementsSuivants = self.arbre_nFils_pProfondeur(n, echiquierTemp, 109 | p, niveauActuel) 110 | 111 | # ajout des mouvements suivant le mouvement actuel 112 | mouvement.set_listeMouvementsSuivants(listeMouvementsSuivants) 113 | 114 | # print("_|_|_|_|_|_") 115 | # print(index) 116 | # print(echiquier.positions[0:3]) 117 | # print(echiquier.get_piece(index).nom) 118 | # print(echiquier.positions[index].couleur) 119 | # 120 | 121 | return listeMouvements 122 | 123 | def listeTousMeilleursMouvements(self, echiquier, niveauProfondeur): 124 | 125 | """ 126 | Cette fonction renvoie tous les déplacements possibles triés 127 | d'une couleur avec un obejet de la classe mouvement contenant : 128 | - l'index de la piece a deplacer 129 | - l'index d'arrivee de la piece a deplacer 130 | - les points affectes a la piece 131 | - le niveau de la profondeur du mouvement 132 | 133 | Cette fonction renvoie des objets Mouvement 134 | """ 135 | 136 | listeMouvements = [] 137 | 138 | # ~~~~ pour tous les mouvements de toutes les pieces ~~~~~~~~~~~~~~~ 139 | 140 | # ~~ (calcul des points pour chaque piece) ~~ 141 | 142 | # ===================================================================== 143 | # pour toutes les pieces de la couleur pouvant être déplacées 144 | # ===================================================================== 145 | 146 | # print(echiquier.listePiecesPouvantEtreDeplacees(couleur)) 147 | 148 | for index in echiquier.listePiecesPouvantEtreDeplacees(self.couleur): 149 | 150 | piece = echiquier.positions[index] 151 | 152 | # print(echiquier.listeDesCoupsAvecVerif(index, self.couleur)) 153 | 154 | # if self.couleur == 'noir': 155 | # listeCoupsPossibles = echiquier.listePiecesPouvantEtreDeplacees() 156 | # elif self.couleur == 'blanc': 157 | # listeCoupsPossibles = echiquier.listePiecesPouvantEtreDeplacees() 158 | # 159 | listeCoupsPossibles = echiquier.listePiecesPouvantEtreDeplacees(self.couleur) 160 | 161 | # pour tous les déplacements de la piece 162 | for indexArrivee in listeCoupsPossibles: 163 | valeurPiece = self.valeurPieces[(piece.nom, piece.couleur)] 164 | 165 | # moins de points si la piece peut se faire manger 166 | valeurPiece *= echiquier.coefficientPointsSiPeutEtreMangee(indexArrivee) 167 | 168 | # ou plus de points si la piece peut manger 169 | 170 | # moins de points si elle n'a aucune piece de la meme couleur autour 171 | # valeurPiece *= echiquier.coefficientPointsSiPieceMemeCouleurProche(indexArrivee, self.couleur) 172 | 173 | # ajout d'un nouveau mouvement à la liste 174 | listeMouvements.append(Mouvement(index, indexArrivee, valeurPiece, niveauProfondeur)) 175 | 176 | # ~~~~ Optimisation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 177 | 178 | # ~~ (tri en gardant les n avec les plus de ~~ 179 | # ~~ points ~~ 180 | 181 | # on trie les elements par points 182 | listeMouvements = self.trierMouvements(listeMouvements) 183 | 184 | return listeMouvements 185 | 186 | def meilleurMouvement(self, listeMouvements=None, niveau=0, niveauMax=None): 187 | 188 | """ 189 | Cette fonction retourne le meilleur mouvement a realiser d'apres 190 | le nombre de points qu'il rapporte 191 | 192 | Les points sont calcules de la maniere suivante : 193 | - points de chaque mouvement (niveau == 1) 194 | - points de chaque mouvement + moyenne des autres (niveau > 1) 195 | 196 | Le mouvement retourne est celui du niveau 1 donc le chemmin rapporte 197 | le plus de points 198 | """ 199 | 200 | # print(listeMouvements) 201 | # à l'initialisation 202 | if niveau == 0: 203 | listeMouvements = self.arbre_nFils_pProfondeur() 204 | # print('=====') 205 | 206 | # print(listeMouvements) 207 | 208 | if niveauMax is None: 209 | niveauMax = 0 210 | premier_fils = listeMouvements[0] 211 | while not premier_fils.listeMouvementsSuivants == None: 212 | premier_fils = premier_fils.listeMouvementsSuivants[0] 213 | niveauMax += 1 214 | 215 | multiplicateur_de_niveau = dict(map(lambda x: (x, 1 - (x / niveauMax + 1)), range(niveauMax + 1))) 216 | # print(multiplicateur_de_niveau) 217 | # ex pour niveauMax = 5 : {0: 1., 1: .8, 2: .6, 3: .4, 4: .2} 218 | 219 | maxPoints = 0 220 | 221 | for mouvement in listeMouvements: 222 | 223 | # si le meilleur chemin est sup à la valeur max 224 | 225 | # calcul des points pour ce mouvement avec le meilleur chemin 226 | # parmi ses enfants 227 | pointsNiveauActuel = mouvement.valeurPiece * multiplicateur_de_niveau[niveau] 228 | 229 | if not mouvement.listeMouvementsSuivants is None: 230 | # print('niveau actuel : ' + str(niveau)) 231 | pointsSuivants = self.meilleurMouvement( 232 | listeMouvements=mouvement.listeMouvementsSuivants, 233 | niveau=niveau + 1, 234 | niveauMax=niveauMax 235 | ).valeurPiece * multiplicateur_de_niveau[niveau + 1] 236 | else: 237 | pointsSuivants = 0 238 | 239 | calculPointsMouvement = pointsNiveauActuel + pointsSuivants 240 | 241 | if calculPointsMouvement >= maxPoints: 242 | meilleurMouvementTrouve = mouvement 243 | maxPoints = calculPointsMouvement 244 | 245 | return meilleurMouvementTrouve 246 | 247 | def trierMouvements(self, liste): 248 | 249 | if liste == []: 250 | return [] 251 | 252 | pivot = liste[0] 253 | liste1 = [] 254 | liste2 = [] 255 | 256 | for x in liste[1:]: 257 | 258 | if x.valeurPiece > pivot.valeurPiece: 259 | liste1.append(x) 260 | else: 261 | liste2.append(x) 262 | 263 | return self.trierMouvements(liste1) + [pivot] + self.trierMouvements(liste2) 264 | 265 | 266 | class Mouvement: 267 | """ 268 | une liste de mouvements est composee de : 269 | - un index de piece a deplacer 270 | - une valeur de déplacement 271 | - le numero de tour dans lequel le deplacement pourrait être réalise 272 | - le nombre de pieces adverses pouvant manger la piece actuelle 273 | - les mouvements suivant si il y en a 274 | """ 275 | 276 | def __init__(self, indexDepart, indexArrivee, valeurPiece, numeroDuTour): 277 | self.indexDepart = indexDepart 278 | self.indexArrivee = indexArrivee 279 | self.valeurPiece = valeurPiece 280 | self.numeroDuTour = numeroDuTour 281 | self.listeMouvementsSuivants = None 282 | 283 | def set_listeMouvementsSuivants(self, liste): 284 | self.listeMouvementsSuivants = liste 285 | 286 | def get_valeurPiece(self): 287 | return self.valeurPiece 288 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | """ 4 | 5 | import sys 6 | from chessboard import Echiquier 7 | #from rules import Piece 8 | from ia import IA 9 | import copy 10 | import time 11 | 12 | 13 | # ============================================================================= 14 | # Gestion de l'interface - boucle du moteur 15 | # ============================================================================= 16 | 17 | 18 | echiquier = Echiquier() 19 | #echiquier.afficher() 20 | 21 | 22 | text_polychess = [ 23 | " _____ _ _ ", 24 | " | __ \\ | | | | ", 25 | " | |__) |__ | |_ _ ___| |__ ___ ___ ___ ", 26 | " | ___/ _ \\| | | | |/ __| \'_ \\ / _ \\/ __/ __|", 27 | " | | | (_) | | |_| | (__| | | | __/\\__ \\__ \\", 28 | " |_| \\___/|_|\\__, |\___|_| |_|\\___||___/___/", 29 | " __/ | ", 30 | " |___/ ", 31 | ] 32 | 33 | text_polychess_2 = [ 34 | "██████╗ ██████╗ ██╗ ██╗ ██╗ ██████╗██╗ ██╗███████╗███████╗███████╗", 35 | "██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔════╝██║ ██║██╔════╝██╔════╝██╔════╝", 36 | "██████╔╝██║ ██║██║ ╚████╔╝ ██║ ███████║█████╗ ███████╗███████╗", 37 | "██╔═══╝ ██║ ██║██║ ╚██╔╝ ██║ ██╔══██║██╔══╝ ╚════██║╚════██║", 38 | "██║ ╚██████╔╝███████╗██║ ╚██████╗██║ ██║███████╗███████║███████║", 39 | "╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝"] 40 | 41 | 42 | 43 | # ============================================================================= 44 | # Fonctions 45 | # ============================================================================= 46 | 47 | print('\n '*3 + '\n '.join(text_polychess_2) + '\n'*3) 48 | 49 | def estUneCoordonnee(string): 50 | if not type(string) == str: 51 | return False 52 | 53 | if not len(string) == 2: 54 | return False 55 | 56 | if not string[0] in 'ABCDEFGH': 57 | return False 58 | 59 | if not string[1] in '12345678': 60 | return False 61 | 62 | return True 63 | 64 | def testCouleur(position): 65 | index = echiquier.nomCaseToIndex(position) 66 | piece = echiquier.get_piece(index) 67 | 68 | return piece.couleur 69 | 70 | 71 | # ============================================================================= 72 | # Fonction Pour Jouer 73 | # ============================================================================= 74 | 75 | #tourDuJoueur 76 | def tourDuJoueur (couleur): 77 | liste_aide_joueur = {1 : ( 78 | "Pour jouer", 79 | [ 80 | "jouer [coordonnées départ] [coordonnées arrivée]", 81 | "[coordonnées départ] [coordonnées arrivée]" 82 | ] 83 | ), 84 | 2 : ( 85 | "Pour connaitre les coups possibles", 86 | ["coups"] 87 | ), 88 | 3 : ( 89 | "Pour connaitre la liste des coups possibles d'une piece", 90 | ["piece"] 91 | ), 92 | 4 : ( 93 | "Pour afficher l'échiquier", 94 | ["afficher"] 95 | ), 96 | 5 : ( 97 | "Pour afficher l'échiquier avec les coups possibles d'une piece", 98 | ["afficher [coordonnées]"] 99 | ), 100 | 6 : ( 101 | "Pour quitter la partie", ["fin de partie"] 102 | ) 103 | } 104 | #aide_joueur sert à aider 105 | aide_joueur = "\n".join( 106 | [str(numero) 107 | + " - " 108 | + liste_aide_joueur[numero][0] 109 | + ", entrez : " 110 | + " ou ".join(liste_aide_joueur[numero][1]) 111 | + " ou " 112 | + str(numero) 113 | + [" [coordonnées départ] [coordonnées arrivée]" if numero == 1 else ""][0] 114 | + [" [coordonnées]" if numero == 3 else ""][0] 115 | + [" [coordonnées]" if numero == 5 else ""][0] for numero in liste_aide_joueur.keys()] 116 | ) + "\n\n" 117 | 118 | str_ne_plus_afficher_laide = "Pour ne plus afficher l'aide, entrez : fin aide\n\n" 119 | str_afficher_laide = "Pour afficher l'aide, entrez : aide\n\n" 120 | ne_plus_afficher_laide = False 121 | 122 | while True: 123 | print("Tour des " + couleur +"s") 124 | if ne_plus_afficher_laide: 125 | entree_joueur = input(str_afficher_laide) 126 | else: 127 | entree_joueur = input(aide_joueur + str_ne_plus_afficher_laide) 128 | 129 | #ne plus afficher l'aide 130 | if entree_joueur == 'fin aide': 131 | ne_plus_afficher_laide = True 132 | 133 | #C'est pour quitter la partie 134 | if entree_joueur in ['Brest', 'fin partie','6']: 135 | print('\n'*3 + 'Vous venez de quitter la partie. Le joueur ' + couleur + ' a abandonné') 136 | sys.exit() 137 | 138 | elif len(entree_joueur) == 0: 139 | pass 140 | 141 | #utile pour le debogage 142 | # elif 143 | 144 | # 2 - "Pour connaitre les pièces pouvant bouger" 145 | elif entree_joueur in liste_aide_joueur[2][1] + ['2']: 146 | 147 | print(', '.join(echiquier.listePiecesPouvantEtreDeplaceesFormatCase(couleur))) 148 | 149 | 150 | # 3 - "Pour connaitre la liste des coups possibles d'une piece" 151 | elif entree_joueur[:-3] in liste_aide_joueur[3][1] + ['3']: 152 | if testCouleur(entree_joueur[-2:])!= couleur: 153 | print("Case invalide") 154 | elif estUneCoordonnee(entree_joueur[-2:]): 155 | print(echiquier.listeCoupsPossiblesFormatCase(entree_joueur[-2:])) 156 | 157 | 158 | # 4 - "Pour afficher l'échiquier" 159 | elif entree_joueur in liste_aide_joueur[4][1] + ['4']: 160 | 161 | echiquier.afficher() 162 | 163 | # 5 - "Pour afficher l'échiquier avec les coups possibles d'une piece" 164 | elif entree_joueur[:-3] in liste_aide_joueur[5][1] + ['5']: 165 | if estUneCoordonnee(entree_joueur[-2:]): 166 | if testCouleur(entree_joueur[-2:])!= couleur: 167 | print("Case invalide") 168 | else: 169 | echiquier.afficherCoupsPossibles(entree_joueur[-2:]) 170 | 171 | 172 | # 1 - si il veut jouer 173 | elif entree_joueur[:-6] in [element[:-43] for element in liste_aide_joueur[1][1]] + ['1']: 174 | deplacement(entree_joueur , couleur ) 175 | break 176 | 177 | 178 | #Programme 179 | def deplacement(entree_joueur,couleur): 180 | valeurDeplacement = entree_joueur[-5:] 181 | while True : 182 | if entree_joueur in ['Brest', 'fin partie', '6']: 183 | print('\n'*3 + 'Vous venez de quitter la partie. Le joueur ' + couleur + ' a abandonné.') 184 | sys.exit() 185 | #on teste si l'entrée est bien un couple de coordonnées 186 | elif (estUneCoordonnee(valeurDeplacement[:2]) and estUneCoordonnee(valeurDeplacement[-2:])) and valeurDeplacement[2] == ' ' : 187 | #on teste si la pièce est de la bonne couleurJ 188 | if testCouleur(valeurDeplacement[:2]) == couleur: 189 | #on teste si la case a une pièce de la bonne couleur 190 | if valeurDeplacement[:2] in echiquier.listePiecesPouvantEtreDeplaceesFormatCase(couleur) : 191 | #On teste si la case d'arrivé est valide 192 | if valeurDeplacement[-2:] in echiquier.listeDesCoupsAvecVerif(echiquier.nomCaseToIndex(valeurDeplacement[:2]),couleur) : 193 | 194 | echiquier.deplacerPiece(valeurDeplacement[:2], valeurDeplacement[-2:]) 195 | 196 | break 197 | else: 198 | print('Cette pièce ne peut pas se déplacer sur cette case') 199 | else: 200 | print('Cette pièce ne peut pas bouger') 201 | else: 202 | print("La pièce choisie n'est pas " + [couleur + 'he' if couleur == 'blanc' else couleur + 'e'][0] ) 203 | else: 204 | print('Entrée invalide, entrez un déplacement valide') 205 | entree_joueur = input('') 206 | valeurDeplacement = entree_joueur[-5:] 207 | 208 | 209 | def tourIA(echiquier, couleur): 210 | 211 | ia = IA(echiquier, couleur) 212 | 213 | liste_positions = copy.copy(echiquier.positions) 214 | le_meilleur_mouvement = ia.meilleurMouvement() 215 | echiquier.positions = liste_positions 216 | 217 | echiquier.deplacementForce(le_meilleur_mouvement.indexDepart, le_meilleur_mouvement.indexArrivee) 218 | 219 | return echiquier 220 | 221 | #============================================================================== 222 | # Fonctions de JcJ ou JcIA 223 | #============================================================================== 224 | 225 | 226 | 227 | 228 | def jouerEnModeJcIA(): 229 | 230 | entree_joueur = '' 231 | while not entree_joueur in ['blanc', 'noir']: 232 | #Le programme demande si le joueur veut jouer les blanc ou les noires 233 | entree_joueur = input('blanc ou noir ? \n\n') 234 | 235 | 236 | #Cas où le joueur joue les blanc et L'IA joue les no 237 | if entree_joueur == 'blanc' : 238 | for numero_du_tour in range(50): 239 | 240 | #-- le joueur joue -- 241 | echiquier.afficher() 242 | tourDuJoueur('blanc') 243 | if echiquier.isEchecEtMatBlanc(): 244 | print("Vous avez gagné" ) 245 | break 246 | 247 | #-- l'ordinateur joue -- 248 | echiquier.afficher() 249 | tourIA(echiquier, 'noir') 250 | if echiquier.isEchecEtMatNoir(): 251 | print("Défaite" ) 252 | break 253 | 254 | #Cas où le joueur joue les noirs et l'IA joue les blancs 255 | elif entree_joueur == 'noir' : 256 | for numero_du_tour in range(50): 257 | 258 | #-- l'ordinateur joue -- 259 | echiquier.afficher() 260 | tourIA(echiquier, 'blanc') 261 | if echiquier.isEchecEtMat(): 262 | print("Vous avez gagné") 263 | break 264 | 265 | #-- le joueur joue -- 266 | echiquier.afficher() 267 | tourDuJoueur('noir') 268 | if echiquier.isEchecEtMat(): 269 | print("Défaite" ) 270 | break 271 | 272 | def jouerEnModeIAcIA(): 273 | echiquier = Echiquier() 274 | 275 | for numero_du_tour in range(50): 276 | 277 | #-- l'ordinateur joue -- 278 | echiquier = tourIA(echiquier, 'blanc') 279 | if echiquier.isEchecEtMatBlanc(): 280 | print("Défaite Blancs") 281 | break 282 | echiquier.afficher() 283 | 284 | # time.sleep(1) 285 | 286 | #-- l'ordinateur joue -- 287 | echiquier = tourIA(echiquier, 'noir') 288 | if echiquier.isEchecEtMatNoir(): 289 | print("Défaite Noirs") 290 | break 291 | echiquier.afficher() 292 | 293 | # time.sleep(1) 294 | 295 | return echiquier 296 | 297 | # print("Défaite") 298 | # break 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | #verification de fin de partie 308 | 309 | 310 | #-- l'IA joue -- 311 | #déplacement d'une piece 312 | 313 | 314 | #vérification de la fin de partie 315 | 316 | 317 | def jouerEnModeJcJ(): 318 | 319 | echiquier.afficher() 320 | 321 | 322 | for numero_du_tour in range(50): 323 | 324 | #-- le joueur joue -- 325 | 326 | #qu'est-ce qu'il veut faire ? 327 | tourDuJoueur('blanc') 328 | echiquier.afficher() 329 | 330 | 331 | if echiquier.isEchecEtMatBlanc(): 332 | print("Les blancs ont gagné" ) 333 | break 334 | 335 | 336 | tourDuJoueur('noir') 337 | echiquier.afficher() 338 | 339 | if echiquier.isEchecEtMatNoir(): 340 | print("Les noirs ont gagné" ) 341 | break 342 | 343 | 344 | 345 | 346 | modeDeJeu = input("Voulez vous jouez contre L'ordinateur (entrer : JcIA) ou contre un joueur (entrer : JcJ) ?\n\n") 347 | 348 | if modeDeJeu == "JcJ": 349 | jouerEnModeJcJ() 350 | 351 | elif modeDeJeu == "JcIA": 352 | jouerEnModeJcIA() 353 | 354 | 355 | 356 | 357 | 358 | 359 | #============================================================================== 360 | # Appel de l'échiquier 361 | #============================================================================== 362 | 363 | echiquier = Echiquier() 364 | # 365 | #print(echiquier.listeCoupsPossiblesFormatCase('C7')) 366 | #print(echiquier.listeCoupsPossiblesFormatCase('B7')) 367 | # 368 | ##echiquier.afficherCoupsPossibles('D7') 369 | # 370 | #echiquier.deplacerPiece('A2', 'A3') 371 | #echiquier.afficher() 372 | # 373 | #echiquier.deplacerPiece('C2', 'E4') 374 | #echiquier.afficher() 375 | # 376 | #echiquier.afficherCoupsPossibles('E4') 377 | # 378 | ##print(echiquier.listeDeplacementsPossibles('A6')) 379 | # 380 | ##print(echiquier.isEchecEtMat()) 381 | ##print(echiquier.couleurEchecEtMat()) 382 | 383 | 384 | 385 | #============================================================================== 386 | # Appel de l'IA 387 | #============================================================================== 388 | 389 | # 390 | #couleur = 'noir' 391 | ## 392 | ## 393 | #ia = IA(echiquier, 'noir') 394 | # 395 | #print(ia.meilleurMouvement(echiquier, couleur)) 396 | # 397 | #possibilites = ia.nMeilleursMouvementsPoints(5) 398 | # 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | #while not echiquier.isEchecEtMat(): 407 | # 408 | # #au joueur blanc de déplacer une pièce 409 | # 410 | # #à l'IA de jouer 411 | # 412 | # pass 413 | 414 | #une fois la boucle finie 415 | 416 | 417 | # ============================================================================= 418 | # Fonctions du main 419 | # ============================================================================= 420 | 421 | 422 | 423 | # 424 | #Fait jusqu'à présent (liste pas a jour) : 425 | # - classe Echiquier et classe Piece 426 | # - définition des pieces 427 | # - initialisation de l'échiquier 428 | # - gestion des déplacements dans l'échiquier 429 | # - vérification de l'échec et mat 430 | # 431 | #À faire bientôt : 432 | # - déplacements possibles (fait pour pion dans Piece() mais pas les autres 433 | # et ensuite compléter listeDeplacementsPossibles dans Echiquier()) 434 | # - affichage des déplacements possibles 435 | # 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | -------------------------------------------------------------------------------- /rules.py: -------------------------------------------------------------------------------- 1 | from functools import reduce 2 | 3 | 4 | class Piece: 5 | 6 | pieceVide = ' ' 7 | 8 | nomPiece = (pieceVide, 'Roi', 'Dame', 'Tour', 'Cavalier', 'Fou', 'Pion') 9 | 10 | valeurPiece = (0, 0, 9, 5, 3, 3, 1) 11 | 12 | tblDebordement = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14 | -1, 0, 1, 2, 3, 4, 5, 6, 7, -1, 15 | -1, 8, 9, 10, 11, 12, 13, 14, 15, -1, 16 | -1, 16, 17, 18, 19, 20, 21, 22, 23, -1, 17 | -1, 24, 25, 26, 27, 28, 29, 30, 31, -1, 18 | -1, 32, 33, 34, 35, 36, 37, 38, 39, -1, 19 | -1, 40, 41, 42, 43, 44, 45, 46, 47, -1, 20 | -1, 48, 49, 50, 51, 52, 53, 54, 55, -1, 21 | -1, 56, 57, 58, 59, 60, 61, 62, 63, -1, 22 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] 24 | 25 | 26 | #1 On donne un nom a chaque position de l'echiquier (de 0 a 63) 27 | 28 | 29 | # [-1]*10*2 + reduce(lambda ele1, ele2 : ele1 + ele2, [[-1] + [valeur for valeur in range(0 + ligne, 8 + ligne)] + [-1] for ligne in range(0,57, 8)]) + [-1]*10*2 30 | 31 | 32 | 33 | # => on utilise la valeur comme index de l'échiquier 34 | 35 | tblPlacement = [21, 22, 23, 24, 25, 26, 27, 28, 36 | 31, 32, 33, 34, 35, 36, 37, 38, 37 | 41, 42, 43, 44, 45, 46, 47, 48, 38 | 51, 52, 53, 54, 55, 56, 57, 58, 39 | 61, 62, 63, 64, 65, 66, 67, 68, 40 | 71, 72, 73, 74, 75, 76, 77, 78, 41 | 81, 82, 83, 84, 85, 86, 87, 88, 42 | 91, 92, 93, 94, 95, 96, 97, 98] 43 | 44 | #[21 + ligne + colonne for colonne in range(0, 71, 10) for ligne in range(8)] 45 | #Pour les noirs: 46 | #Pour avancer tout droit en avant on ajoute 10 par case (-10 en arriere) 47 | #Pour aller en diagonale a droite on ajoute 11 (-11 en arriere) 48 | #Pour aller en diagonale a gauche on ajoute 9 (-9 en arriere) 49 | 50 | #L'inverse pour les blancs. 51 | 52 | 53 | 54 | 55 | 56 | 57 | # => on utilise la valeur comme position de tblDebordement 58 | 59 | 60 | def __init__(self, nom = pieceVide, couleur = '', pieceABouge = False): 61 | 62 | self.nom = nom 63 | self.couleur = couleur 64 | self.couleurOpposee = 'noir' if self.couleur == 'blanc' else 'blanc' 65 | self.valeur = self.valeurPiece[self.nomPiece.index(nom)] 66 | 67 | self.setNomPiece() 68 | 69 | self.pieceABouge = pieceABouge 70 | 71 | 72 | #2 Constructeur de l'objet. Il correspond a une piece qui n'a pas encore de nom. 73 | # On appelera la fonction ci-dessous pour lui en atribuer un. 74 | 75 | 76 | 77 | 78 | def setNomPiece(self): 79 | 80 | """ 81 | 82 | Cette fonction utilise les attributs de la couleur du nom de la piece 83 | 84 | Elle créé un nouvel attribut pour l'affichage tel que : 85 | - i[col] pour un Pion 86 | - T[col] pour une Tour 87 | - C[col] pour un Cavalier 88 | - F[col] pour un Fou 89 | - R[col] pour un Roi 90 | - D[col] pour une Dame 91 | 92 | Chaque valeur est suivie de sa couleur 93 | 94 | """ 95 | 96 | 97 | if self.nom == self.pieceVide: 98 | self.nomAffichage = self.pieceVide 99 | 100 | elif self.nom == 'Pion': 101 | self.nomAffichage = 'i' + self.couleur[0].lower() 102 | 103 | else: 104 | self.nomAffichage = self.nom[0].upper() + self.couleur[0].lower() 105 | 106 | 107 | 108 | #============================================================================== 109 | # Coups possibles 110 | #============================================================================== 111 | 112 | 113 | 114 | 115 | 116 | #=========================== 117 | # Pion 118 | #=========================== 119 | 120 | def listeCoupsPossiblesPion(self, position, echiquier): 121 | #position va de 0 à 63 122 | 123 | 124 | listePossibilites = [] 125 | 126 | 127 | if self.couleur == 'blanc': 128 | 129 | #deplacement de 2 si il se trouve sur la ligne 1 --> -10 par case d'où -20 ici. 130 | #On utilise les deux listes definies au debut. 131 | 132 | if 48 <= position <= 55: 133 | positionE = self.tblDebordement[self.tblPlacement[position] - 20] 134 | # print(positionE) 135 | if echiquier.positions[positionE].nom == echiquier.positions[positionE].pieceVide: 136 | # print('---') 137 | listePossibilites.append(positionE) 138 | 139 | #manger haut droite. 140 | positionE = self.tblDebordement[self.tblPlacement[position] - 9] 141 | #Dans toutes les methodes, on va s'assurer que le deplacement ne va pas faire sortir la piece de l'echiquier 142 | if not positionE == -1: 143 | if echiquier.positions[positionE].couleur == 'noir': 144 | listePossibilites.append(positionE) 145 | 146 | #manger haut gauche 147 | positionE = self.tblDebordement[self.tblPlacement[position] - 11] 148 | if not positionE == -1: 149 | if echiquier.positions[positionE].couleur == 'noir': 150 | listePossibilites.append(positionE) 151 | 152 | positionE = self.tblDebordement[self.tblPlacement[position] - 10] 153 | if not positionE == -1 and echiquier.positions[positionE].nom == echiquier.positions[positionE].pieceVide: 154 | listePossibilites.append(positionE) 155 | 156 | 157 | 158 | else: 159 | 160 | 161 | #deplacement de 2 si il se trouve sur la ligne 6 162 | if 8 <= position <= 15: 163 | positionE = self.tblDebordement[self.tblPlacement[position] + 20] 164 | if echiquier.positions[positionE].nom == echiquier.positions[positionE].pieceVide: 165 | listePossibilites.append(positionE) 166 | 167 | #manger bas gauche 168 | positionE = self.tblDebordement[self.tblPlacement[position] + 9] 169 | if not positionE == -1: 170 | if echiquier.positions[positionE].couleur == 'blanc': 171 | listePossibilites.append(positionE) 172 | 173 | #manger bas droite 174 | positionE = self.tblDebordement[self.tblPlacement[position] + 11] 175 | if not positionE == -1: 176 | if echiquier.positions[positionE].couleur == 'blanc': 177 | listePossibilites.append(positionE) 178 | #deplacement classique du pion 179 | positionE = self.tblDebordement[self.tblPlacement[position] + 10] 180 | if not positionE == -1 and echiquier.positions[positionE].nom == echiquier.positions[positionE].pieceVide: 181 | listePossibilites.append(positionE) 182 | 183 | return listePossibilites 184 | 185 | 186 | 187 | #=========================== 188 | # Tour 189 | #=========================== 190 | 191 | 192 | 193 | def listeCoupsPossiblesTour(self, position, echiquier): 194 | deplacements = (-10, 10, -1, 1) #Deplacements horizontaux et verticaux dans les deux directions. 195 | couleurCaseOpposee = 'noir' if self.couleur == 'blanc' else 'blanc' 196 | 197 | 198 | listePossibilites = [] 199 | for deplacement in deplacements: 200 | 201 | multiplicateur = 1 202 | positionE = self.tblDebordement[self.tblPlacement[position] + deplacement] 203 | #Ici on utilise une boucle car la tour peut se deplacer d'autant de case qu'elle veut tant qu'elle n'arrive pas sur 204 | #une piece ou le bord de l'échiquier. Si c'est une piece adverse elle prend sa place, si c'est une pièce alliee 205 | #elle s'arrête devant. 206 | while not positionE == -1: 207 | 208 | if echiquier.positions[positionE].couleur == self.couleur: 209 | break 210 | 211 | if echiquier.positions[positionE].couleur == couleurCaseOpposee: 212 | 213 | listePossibilites.append(positionE) 214 | 215 | break 216 | 217 | elif echiquier.positions[positionE].nom == self.pieceVide: 218 | 219 | listePossibilites.append(positionE) 220 | 221 | 222 | multiplicateur += 1 223 | positionE = self.tblDebordement[self.tblPlacement[position] + deplacement * multiplicateur] 224 | 225 | 226 | return listePossibilites 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | #=========================== 235 | # Fou 236 | #=========================== 237 | 238 | 239 | def listeCoupsPossiblesFou(self, position, echiquier): 240 | deplacements = (-11, -9, 11, 9) #deplacements dans les deux diagonales, vers l'avant et vers l'arriere. 241 | 242 | couleurCaseOpposee = 'noir' if self.couleur == 'blanc' else 'blanc' 243 | listePossibilites = [] 244 | 245 | for deplacement in deplacements: 246 | 247 | multiplicateur = 1 248 | positionE = self.tblDebordement[self.tblPlacement[position] + deplacement] 249 | 250 | while not positionE == -1: 251 | 252 | if echiquier.positions[positionE].couleur == self.couleur: 253 | break 254 | 255 | if echiquier.positions[positionE].couleur == couleurCaseOpposee: 256 | 257 | listePossibilites.append(positionE) 258 | 259 | break 260 | 261 | elif echiquier.positions[positionE].nom == self.pieceVide: 262 | 263 | listePossibilites.append(positionE) 264 | 265 | 266 | multiplicateur += 1 267 | positionE = self.tblDebordement[self.tblPlacement[position] + deplacement * multiplicateur] 268 | 269 | 270 | return listePossibilites 271 | 272 | 273 | 274 | 275 | 276 | #=========================== 277 | # Cavalier 278 | #=========================== 279 | 280 | 281 | 282 | 283 | def listeCoupsPossiblesCavalier(self, position, echiquier): 284 | deplacements = (-12, -21, -19, -8, 12, 21, 19, 8) #Les differents types de "L". 285 | 286 | listePossibilites = [] 287 | 288 | for deplacement in deplacements: 289 | 290 | positionE = self.tblDebordement[self.tblPlacement[position] + deplacement] 291 | 292 | if not positionE == -1: 293 | if not echiquier.positions[positionE].couleur == self.couleur: 294 | 295 | listePossibilites.append(positionE) 296 | 297 | return listePossibilites 298 | 299 | 300 | 301 | 302 | 303 | #=========================== 304 | # Roi 305 | #=========================== 306 | 307 | 308 | def listeCoupsPossiblesRoi(self, position, echiquier): 309 | deplacements = (-11, -10, -9, -1, 1, 9, 10, 11) #deplacements dans toutes les directions 310 | 311 | listePossibilites = [] 312 | 313 | for deplacement in deplacements: 314 | 315 | positionE = self.tblDebordement[self.tblPlacement[position] + deplacement] 316 | 317 | if not positionE == -1: 318 | if not echiquier.positions[positionE].couleur == self.couleur: 319 | 320 | listePossibilites.append(positionE) 321 | 322 | if self.couleur == 'blanc' and position == 60 and echiquier.petitRoqueBlancPossible(): 323 | listePossibilites.append(62) 324 | 325 | if self.couleur == 'blanc' and position == 60 and echiquier.grandRoqueBlancPossible(): 326 | listePossibilites.append(58) 327 | 328 | if self.couleur == 'noir' and position == 4 and echiquier.petitRoqueNoirPossible(): 329 | listePossibilites.append(6) 330 | 331 | if self.couleur == 'noir' and position == 4 and echiquier.grandRoqueNoirPossible(): 332 | listePossibilites.append(2) 333 | 334 | return listePossibilites 335 | 336 | 337 | 338 | 339 | #=========================== 340 | # Dame 341 | #=========================== 342 | 343 | 344 | #La dame est la combinaison d'un fou et d'une tour. 345 | def listeCoupsPossiblesDame(self, position, echiquier): 346 | return self.listeCoupsPossiblesFou(position, echiquier) + self.listeCoupsPossiblesTour(position, echiquier) 347 | 348 | 349 | 350 | 351 | #============================================================================== 352 | # Fonction annexes 353 | #============================================================================== 354 | 355 | 356 | def isEmpty(self): 357 | 358 | """Returns TRUE or FALSE if this piece object is defined, 359 | As any square on board can have a piece on it, or not, 360 | we can set a null piece on a square.""" 361 | 362 | return self.nom == self.pieceVide 363 | --------------------------------------------------------------------------------