286 lines
9.9 KiB
Python
286 lines
9.9 KiB
Python
import copy
|
|
|
|
class Logique:
|
|
"""
|
|
Logique des jeux sur damier
|
|
"""
|
|
|
|
PCE_VIDE = 0
|
|
BLANC = True
|
|
NOIR = False
|
|
|
|
@staticmethod
|
|
def eCaseBlanche(xD, yD):
|
|
return xD % 2 == yD % 2
|
|
|
|
def cGrille(self):
|
|
for x in range(self.CASES_COTE):
|
|
colonne = []
|
|
for y in range(self.CASES_COTE):
|
|
colonne.append(self.PCE_VIDE)
|
|
self.grille.append(colonne)
|
|
|
|
def cPion(self, x, y, piece):
|
|
self.grille[x][y] = piece
|
|
return True
|
|
|
|
def ePionBlanc(self, pion):
|
|
return pion in self.BLANCS
|
|
|
|
def ePionNoir(self, pion):
|
|
return pion in self.NOIRS
|
|
|
|
def ePiece(self, piece):
|
|
# return piece != self.PCE_VIDE
|
|
return self.ePionBlanc(piece) or self.ePionNoir(piece)
|
|
|
|
def tPiece(self, piece):
|
|
if self.ePionBlanc(piece):
|
|
return piece - self.DECALAGE_BLANCS
|
|
elif self.ePionNoir(piece):
|
|
return piece - self.DECALAGE_NOIRS
|
|
else:
|
|
return self.PCE_VIDE
|
|
|
|
def aSonTour(self, pion):
|
|
return (self.ePionNoir(pion) and self.joueur == self.NOIR) or \
|
|
(self.ePionBlanc(pion) and self.joueur == self.BLANC)
|
|
|
|
|
|
class LogiqueEchecs(Logique):
|
|
"""
|
|
Logique du jeu d'Échecs
|
|
"""
|
|
|
|
CASES_COTE = 8
|
|
|
|
# Pièces
|
|
PCE_PION = 1
|
|
PCE_TOUR = 2
|
|
PCE_CAVALIER = 3
|
|
PCE_FOU = 4
|
|
PCE_DAME = 5
|
|
PCE_ROI = 6
|
|
|
|
DECALAGE_BLANCS = 0
|
|
DECALAGE_NOIRS = 10
|
|
|
|
BLANCS = range(DECALAGE_BLANCS+PCE_PION, DECALAGE_BLANCS+PCE_ROI+1)
|
|
NOIRS = range(DECALAGE_NOIRS+PCE_PION, DECALAGE_NOIRS+PCE_ROI+1)
|
|
|
|
|
|
# Codes du mouvement
|
|
MVT_INCONNU = 'Cause inconnue'
|
|
MVT_OK = 'Valide'
|
|
MVT_ROQUE = 'Roque'
|
|
MVT_SELECTION = 'Mauvais tour'
|
|
MVT_SUR_PLACE = 'Immobile'
|
|
MVT_SAUT_AMI = 'Saut ami'
|
|
MVT_PION_INC = 'Pion inconnu'
|
|
MVT_N_AUTORISE = 'Non-autorisé'
|
|
MVT_OBSTRUCTION = 'Pion en chemin'
|
|
MVT_ECHEC = 'Échec au roi'
|
|
|
|
def __init__(self):
|
|
|
|
self.grille = []
|
|
self.cGrille()
|
|
self.remplirGrille()
|
|
self.joueur = self.BLANC
|
|
self.partieFinie = False
|
|
self.victorieux = None
|
|
|
|
def remplirGrille(self):
|
|
speciales = [self.PCE_TOUR, self.PCE_CAVALIER, self.PCE_FOU, self.PCE_ROI, self.PCE_DAME]
|
|
speciales += speciales[4::-1]
|
|
for i in range(0, 8):
|
|
self.grille[i][0] = self.DECALAGE_NOIRS + speciales[i]
|
|
self.grille[i][1] = self.DECALAGE_NOIRS + self.PCE_PION
|
|
self.grille[i][6] = self.DECALAGE_BLANCS + self.PCE_PION
|
|
self.grille[i][7] = self.DECALAGE_BLANCS + speciales[i]
|
|
|
|
def mvtPossibleSansEchecPion(self, x1, y1, x2, y2):
|
|
if x1 == x2 and self.grille[x2][y2] <= 0: # Avance
|
|
if self.joueur:
|
|
if y2 == y1 - 1:
|
|
return self.MVT_OK
|
|
elif y1 == 6 and y2 == 4 and self.grille[x1][5] == 0:
|
|
return self.MVT_OK
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
else:
|
|
if y2 == y1 + 1:
|
|
return self.MVT_OK
|
|
elif y1 == 1 and y2 == 3 and self.grille[x1][2] == 0:
|
|
return self.MVT_OK
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
elif abs(x1-x2) == 1: # Saut
|
|
if self.joueur:
|
|
if y2 == y1 - 1 and \
|
|
self.ePionNoir(self.grille[x2][y2]):
|
|
return self.MVT_OK
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
else:
|
|
if y2 == y1 + 1 and \
|
|
self.ePionBlanc(self.grille[x2][y2]):
|
|
return self.MVT_OK
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
|
|
def mvtPossibleSansEchecTour(self, x1, y1, x2, y2):
|
|
if y1 == y2:
|
|
sens = (x2-x1)//abs(x2-x1)
|
|
for x in range(x1+sens, x2, sens):
|
|
if self.ePiece(self.grille[x][y1]):
|
|
return self.MVT_OBSTRUCTION
|
|
elif x1 == x2:
|
|
sens = (y2-y1)//abs(y2-y1)
|
|
for y in range(y1+sens, y2, sens):
|
|
if self.ePiece(self.grille[x1][y]):
|
|
return self.MVT_OBSTRUCTION
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
return self.MVT_OK
|
|
|
|
def mvtPossibleSansEchecFou(self, x1, y1, x2, y2):
|
|
if abs(x2-x1) == abs(y2-y1):
|
|
sensX = (x2-x1)//abs(x2-x1)
|
|
sensY = (y2-y1)//abs(y2-y1)
|
|
x = x1
|
|
y = y1
|
|
dist = 0
|
|
distTot = abs(x2-x1)
|
|
while dist < distTot:
|
|
dist += 1
|
|
x += sensX
|
|
y += sensY
|
|
if self.ePiece(self.grille[x][y]):
|
|
if dist == distTot:
|
|
return self.MVT_OK # Saut
|
|
else:
|
|
return self.MVT_OBSTRUCTION
|
|
return self.MVT_OK # Vide
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
|
|
def mvtPossibleSansEchecCavalier(self, x1, y1, x2, y2):
|
|
if (abs(x2-x1) == 2 and abs(y2-y1) == 1) or (abs(y2-y1) == 2 and abs(x2-x1) == 1):
|
|
return self.MVT_OK
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
|
|
def mvtPossibleSansEchec(self, x1, y1, x2, y2):
|
|
pion = self.grille[x1][y1]
|
|
if self.aSonTour(pion):
|
|
if (x1 != x2 or y1 != y2):
|
|
if not self.aSonTour(self.grille[x2][y2]):
|
|
tPion = self.tPiece(pion)
|
|
if tPion == self.PCE_PION: # Pion
|
|
return self.mvtPossibleSansEchecPion(x1, y1, x2, y2)
|
|
elif tPion == self.PCE_TOUR: # Tour
|
|
return self.mvtPossibleSansEchecTour(x1, y1, x2, y2)
|
|
elif tPion == self.PCE_CAVALIER:
|
|
return self.mvtPossibleSansEchecCavalier(x1, y1, x2, y2)
|
|
elif tPion == self.PCE_FOU:
|
|
return self.mvtPossibleSansEchecFou(x1, y1, x2, y2)
|
|
elif tPion == self.PCE_DAME:
|
|
tour = self.mvtPossibleSansEchecTour(x1, y1, x2, y2)
|
|
fou = self.mvtPossibleSansEchecFou(x1, y1, x2, y2)
|
|
if tour == self.MVT_OK or fou == self.MVT_OK:
|
|
return self.MVT_OK
|
|
elif tour == self.MVT_OBSTRUCTION or fou == self.MVT_OBSTRUCTION:
|
|
return self.MVT_OBSTRUCTION
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
elif tPion == self.PCE_ROI:
|
|
if abs(x2-x1) <= 1 and abs(y2-y1) <= 1:
|
|
return self.MVT_OK
|
|
else:
|
|
return self.MVT_N_AUTORISE
|
|
else:
|
|
return self.MVT_PION_INC
|
|
else:
|
|
return self.MVT_SAUT_AMI
|
|
else:
|
|
return self.MVT_SUR_PLACE
|
|
else:
|
|
return self.MVT_SELECTION
|
|
return self.MVT_INCONNU
|
|
|
|
def mvtPossible(self, x1, y1, x2, y2):
|
|
test = self.mvtPossibleSansEchec(x1, y1, x2, y2)
|
|
if test == self.MVT_OK:
|
|
# On copie la partie actuelle pour tester le mouvement et vérifier l'échec
|
|
copie = copy.deepcopy(self);
|
|
copie.dPionSansEchec(x1, y1, x2, y2)
|
|
mvtsPossiblesTousAdverses = []
|
|
pionRoi = self.PCE_ROI + self.DECALAGE_BLANCS if self.joueur else self.DECALAGE_NOIRS
|
|
roi = [-1, -1]
|
|
for x in range(0, self.CASES_COTE):
|
|
for y in range(0, self.CASES_COTE):
|
|
mvtsPossiblesTousAdverses += copie.mvtsPossiblesSansEchec(x, y)
|
|
if copie.grille[x][y] == pionRoi:
|
|
roi = [x, y]
|
|
if roi in mvtsPossiblesTousAdverses:
|
|
return self.MVT_ECHEC
|
|
else:
|
|
return test
|
|
else:
|
|
return test
|
|
|
|
def mvtsPossiblesSansEchec(self, x1, y1):
|
|
tableau = []
|
|
for x2 in range(0, self.CASES_COTE):
|
|
for y2 in range(0, self.CASES_COTE):
|
|
if self.mvtPossibleSansEchec(x1, y1, x2, y2) == self.MVT_OK:
|
|
tableau.append([x2, y2])
|
|
return tableau
|
|
|
|
def mvtsPossibles(self, x1, y1):
|
|
tableau = []
|
|
for x2 in range(0, self.CASES_COTE):
|
|
for y2 in range(0, self.CASES_COTE):
|
|
if self.mvtPossible(x1, y1, x2, y2) == self.MVT_OK:
|
|
tableau.append([x2, y2])
|
|
return tableau
|
|
|
|
def dPionSansEchec(self, x1, y1, x2, y2):
|
|
test = self.mvtPossibleSansEchec(x1, y1, x2, y2)
|
|
if test == self.MVT_OK:
|
|
self.grille[x1][y1], self.grille[x2][y2] = self.PCE_VIDE, self.grille[x1][y1]
|
|
self.joueur = not self.joueur
|
|
|
|
def vEchecMat(self):
|
|
"""
|
|
Vérifie si le joueur actuel est en échec et mat et prend les mesures nécessiares.
|
|
(Ici vrai en cas de "pat")
|
|
"""
|
|
for x in range(0, self.CASES_COTE):
|
|
for y in range(0, self.CASES_COTE):
|
|
if len(self.mvtsPossibles(x, y)) > 0:
|
|
return False
|
|
self.partieFinie = True
|
|
self.victorieux = not self.joueur
|
|
return True
|
|
|
|
def dPion(self, x1, y1, x2, y2):
|
|
test = self.mvtPossible(x1, y1, x2, y2)
|
|
retour = {
|
|
'valide': False,
|
|
'message': test,
|
|
'deplacer': [], # Pions à déplacer
|
|
'supprimer': [], # Pions à supprimer
|
|
}
|
|
if test == self.MVT_OK:
|
|
retour['valide'] = True
|
|
if self.ePiece(self.grille[x2][y2]):
|
|
retour['supprimer'].append([x2, y2])
|
|
retour['deplacer'].append([x1, y1, x2, y2])
|
|
self.grille[x1][y1], self.grille[x2][y2] = self.PCE_VIDE, self.grille[x1][y1]
|
|
self.joueur = not self.joueur
|
|
self.vEchecMat()
|
|
return retour |