├── .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 |
5 |
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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | 1580218726439
36 |
37 |
38 | 1580218726439
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
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 |
--------------------------------------------------------------------------------