2014-11-20 18:59:50 +01:00
|
|
|
CASES_COTE = 8
|
2014-11-21 10:00:27 +01:00
|
|
|
|
|
|
|
|
2014-11-20 18:59:50 +01:00
|
|
|
class LogiqueEchecs:
|
|
|
|
|
|
|
|
# grille = None
|
|
|
|
# joueur = True
|
|
|
|
|
2014-11-21 10:00:27 +01:00
|
|
|
def __init__(self):
|
2014-11-20 18:59:50 +01:00
|
|
|
self.grille = []
|
|
|
|
self.cGrille()
|
|
|
|
self.remplirGrille()
|
|
|
|
self.joueur = True
|
|
|
|
self.nvPartie()
|
|
|
|
|
|
|
|
@staticmethod
|
2014-11-21 10:00:27 +01:00
|
|
|
def eNoir(xD, yD): # TODO Peut être considérablement amélioré
|
2014-11-20 18:59:50 +01:00
|
|
|
i = 1
|
|
|
|
for x in range(0, CASES_COTE):
|
|
|
|
i += 1
|
|
|
|
for y in range(0, CASES_COTE):
|
|
|
|
i += 1
|
|
|
|
if x == xD and y == yD:
|
2014-11-21 10:00:27 +01:00
|
|
|
return i % 2
|
2014-11-20 18:59:50 +01:00
|
|
|
|
2014-11-21 10:00:27 +01:00
|
|
|
def cGrille(self):
|
2014-11-20 18:59:50 +01:00
|
|
|
for x in range(CASES_COTE):
|
|
|
|
colonne = []
|
|
|
|
for y in range(CASES_COTE):
|
|
|
|
colonne.append(0)
|
|
|
|
self.grille.append(colonne)
|
|
|
|
|
2014-11-21 10:00:27 +01:00
|
|
|
def remplirGrille(self):
|
2014-11-20 18:59:50 +01:00
|
|
|
speciales = [2, 3, 4, 6, 5, 4, 3, 2]
|
|
|
|
for i in range(0, 8):
|
|
|
|
self.grille[i][0] = speciales[i] + 10
|
|
|
|
self.grille[i][1] = 11
|
|
|
|
self.grille[i][6] = 1
|
|
|
|
self.grille[i][7] = speciales[i]
|
|
|
|
|
2014-11-21 10:00:27 +01:00
|
|
|
def nvPartie(self):
|
2014-11-20 18:59:50 +01:00
|
|
|
self.cGrille()
|
|
|
|
self.remplirGrille()
|
|
|
|
self.joueur = True
|
|
|
|
|
2014-11-21 10:00:27 +01:00
|
|
|
def cPion(self, x, y, piece):
|
2014-11-20 18:59:50 +01:00
|
|
|
"""
|
|
|
|
"""
|
|
|
|
self.grille[x][y] = piece
|
|
|
|
return True
|
|
|
|
|
2014-11-21 10:00:27 +01:00
|
|
|
def mvtPossible(self, x1, y1, x2, y2):
|
2014-11-20 18:59:50 +01:00
|
|
|
pion = self.grille[x1][y1]
|
|
|
|
if (pion >= 10 and self.joueur == False) or \
|
2014-11-21 10:00:27 +01:00
|
|
|
(pion < 10 and self.joueur == True):
|
2014-11-20 18:59:50 +01:00
|
|
|
if pion > 0 and self.grille[x2][y2] <= 0:
|
2014-11-21 10:00:27 +01:00
|
|
|
tPion = pion % 10
|
2014-11-20 18:59:50 +01:00
|
|
|
if tPion == 1:
|
|
|
|
if x1 == x2:
|
|
|
|
if self.joueur:
|
2014-11-21 10:00:27 +01:00
|
|
|
if y2 == y1 - 1:
|
2014-11-20 18:59:50 +01:00
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return -4
|
|
|
|
else:
|
2014-11-21 10:00:27 +01:00
|
|
|
if y2 == y1 + 1:
|
2014-11-20 18:59:50 +01:00
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return -4
|
|
|
|
else:
|
|
|
|
return -4
|
|
|
|
elif tPion == 6:
|
2014-11-21 10:00:27 +01:00
|
|
|
if x2 <= x1 + 1 and x2 >= x1 - 1 and y2 <= y1 + 1 and y2 >= y1 - 1 \
|
|
|
|
and (x1 != x2 or y1 != y2):
|
2014-11-20 18:59:50 +01:00
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return -4
|
|
|
|
else:
|
|
|
|
return -3
|
|
|
|
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return -2
|
|
|
|
else:
|
|
|
|
return -1
|
|
|
|
|
2014-11-21 10:00:27 +01:00
|
|
|
def dPion(self, x1, y1, x2, y2):
|
2014-11-20 18:59:50 +01:00
|
|
|
test = self.mvtPossible(x1, y1, x2, y2)
|
|
|
|
if test == True:
|
|
|
|
self.grille[x2][y2] = self.grille[x1][y1]
|
|
|
|
self.grille[x1][y1] = 0
|
|
|
|
# self.joueur = not self.joueur # DEBUG
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return test
|
|
|
|
|
|
|
|
# GUI
|
|
|
|
|
|
|
|
from tkinter import *
|
|
|
|
|
|
|
|
DECX = 0
|
|
|
|
DECY = 0
|
|
|
|
COTE_CASE = 50
|
|
|
|
MARGE_PIONS = 5
|
|
|
|
TEMPS_ANIM = 200
|
|
|
|
INTER_ANIM = 10
|
|
|
|
|
|
|
|
class PlateauTk:
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
|
|
self.fen = None
|
|
|
|
self.can = None
|
|
|
|
self.chaine = None
|
2014-11-21 10:00:27 +01:00
|
|
|
self.grilleDamier = []
|
|
|
|
self.imagesOriginales = []
|
|
|
|
self.imagesRedim = []
|
|
|
|
self.photos = []
|
|
|
|
self.grillePions = []
|
|
|
|
self.animations = []
|
|
|
|
|
|
|
|
self.dEtape = True
|
|
|
|
self.dx1 = -1
|
|
|
|
self.dy1 = -1
|
|
|
|
self.dx2 = -1
|
|
|
|
self.dy2 = -1
|
|
|
|
self.logique = LogiqueEchecs()
|
2014-11-20 18:59:50 +01:00
|
|
|
|
|
|
|
self.creerFen()
|
|
|
|
self.importerImages()
|
|
|
|
self.redimImages()
|
|
|
|
|
2014-11-21 10:00:27 +01:00
|
|
|
self.cDamier()
|
|
|
|
self.cGrille()
|
|
|
|
self.remplirGrille(self.logique.grille)
|
|
|
|
|
2014-11-20 18:59:50 +01:00
|
|
|
def creerFen(self):
|
|
|
|
self.fen = Tk()
|
|
|
|
self.fen.title("Jeu d'Échecs")
|
2014-11-21 10:00:27 +01:00
|
|
|
self.can = Canvas(self.fen, width=COTE_CASE * CASES_COTE,
|
|
|
|
height=COTE_CASE * CASES_COTE, bg="ivory")
|
2014-11-20 18:59:50 +01:00
|
|
|
self.can.grid(row=0, column=1, columnspan=3)
|
2014-11-21 10:00:27 +01:00
|
|
|
self.can.bind('<Button-1>', self.clic)
|
2014-11-20 18:59:50 +01:00
|
|
|
self.chaine = Label(self.fen, text="Aux blancs")
|
|
|
|
self.chaine.grid(row=2, column=2, padx=3, pady=3)
|
|
|
|
# Button(self.fen, text="Nv. Partie", command=f_nvPartie).grid(row=2, \
|
|
|
|
# column=1, padx=3, pady=3)
|
2014-11-21 10:00:27 +01:00
|
|
|
Button(self.fen, text="Quitter", command=self.fen.destroy).grid(row=2,
|
|
|
|
column=3, padx=3, pady=3)
|
2014-11-20 18:59:50 +01:00
|
|
|
|
|
|
|
def statut(self, texte, delai=0):
|
|
|
|
self.chaine.config(text=texte)
|
|
|
|
# TODO Timeout effacer si parametre / Liste
|
|
|
|
|
|
|
|
def importerImages(self):
|
|
|
|
for piece in range(0, 21):
|
|
|
|
nom = 'sprites/'
|
2014-11-21 10:00:27 +01:00
|
|
|
if piece % 10 == 1:
|
2014-11-20 18:59:50 +01:00
|
|
|
nom += 'pion'
|
2014-11-21 10:00:27 +01:00
|
|
|
elif piece % 10 == 2:
|
2014-11-20 18:59:50 +01:00
|
|
|
nom += 'tour'
|
2014-11-21 10:00:27 +01:00
|
|
|
elif piece % 10 == 3:
|
2014-11-20 18:59:50 +01:00
|
|
|
nom += 'cavalier'
|
2014-11-21 10:00:27 +01:00
|
|
|
elif piece % 10 == 4:
|
2014-11-20 18:59:50 +01:00
|
|
|
nom += 'fou'
|
2014-11-21 10:00:27 +01:00
|
|
|
elif piece % 10 == 5:
|
2014-11-20 18:59:50 +01:00
|
|
|
nom += 'dame'
|
2014-11-21 10:00:27 +01:00
|
|
|
elif piece % 10 == 6:
|
2014-11-20 18:59:50 +01:00
|
|
|
nom += 'roi'
|
|
|
|
else:
|
|
|
|
self.imagesOriginales.append('')
|
|
|
|
continue
|
|
|
|
if piece < 10:
|
|
|
|
nom += 'B'
|
|
|
|
else:
|
|
|
|
nom += 'N'
|
|
|
|
nom += '.gif'
|
|
|
|
self.imagesOriginales.append(PhotoImage(file=nom))
|
|
|
|
|
|
|
|
def redimImages(self):
|
2014-11-21 10:00:27 +01:00
|
|
|
sample = int(504 / (COTE_CASE - MARGE_PIONS))
|
2014-11-20 18:59:50 +01:00
|
|
|
for piece in range(0, 21):
|
|
|
|
if self.imagesOriginales[piece] != '':
|
2014-11-21 10:00:27 +01:00
|
|
|
self.imagesRedim.append(self.imagesOriginales[piece].
|
|
|
|
subsample(sample))
|
2014-11-20 18:59:50 +01:00
|
|
|
else:
|
|
|
|
self.imagesRedim.append('')
|
|
|
|
|
2014-11-21 10:00:27 +01:00
|
|
|
# Dessin
|
2014-11-20 18:59:50 +01:00
|
|
|
def cCase(self, x, y):
|
|
|
|
if LogiqueEchecs.eNoir(x, y):
|
|
|
|
couleur = '#D18B47'
|
|
|
|
else:
|
|
|
|
couleur = '#FFCE9E'
|
2014-11-21 10:00:27 +01:00
|
|
|
return self.can.create_rectangle(x * COTE_CASE, y * COTE_CASE,
|
|
|
|
(x + 1) * COTE_CASE, (y + 1) * COTE_CASE, fill=couleur)
|
2014-11-20 18:59:50 +01:00
|
|
|
|
|
|
|
def cDamier(self):
|
|
|
|
self.grilleDamier = []
|
|
|
|
for x in range(0, CASES_COTE):
|
|
|
|
colonne = []
|
|
|
|
for y in range(0, CASES_COTE):
|
|
|
|
colonne.append(self.cCase(x + DECX, y + DECY))
|
|
|
|
self.grilleDamier.append(colonne)
|
|
|
|
|
|
|
|
def cPion(self, x, y, piece):
|
|
|
|
if piece > 0:
|
2014-11-21 10:00:27 +01:00
|
|
|
self.grillePions[x][y] = self.can.create_image((x + .5) * COTE_CASE,
|
|
|
|
(y + .5) * COTE_CASE, image=self.imagesRedim[piece])
|
2014-11-20 18:59:50 +01:00
|
|
|
else:
|
|
|
|
self.grillePions[x][y] = False
|
|
|
|
|
|
|
|
def cGrille(self):
|
|
|
|
self.grillePions = []
|
2014-11-21 10:00:27 +01:00
|
|
|
for x in range(0, CASES_COTE): # Crée self.grillePions
|
2014-11-20 18:59:50 +01:00
|
|
|
colonne = []
|
|
|
|
for y in range(0, CASES_COTE):
|
|
|
|
colonne.append(False)
|
|
|
|
self.grillePions.append(colonne)
|
|
|
|
|
|
|
|
def remplirGrille(self, j_grilleF):
|
2014-11-21 10:00:27 +01:00
|
|
|
for x in range(0, CASES_COTE): # Remplis self.grillePions
|
2014-11-20 18:59:50 +01:00
|
|
|
for y in range(0, CASES_COTE):
|
2014-11-21 10:00:27 +01:00
|
|
|
self.cPion(x, y, j_grilleF[x][y])
|
|
|
|
|
|
|
|
# Interaction
|
|
|
|
def statutPrendre(self):
|
|
|
|
if self.logique.joueur:
|
|
|
|
joueur = 'blancs'
|
|
|
|
else:
|
|
|
|
joueur = 'noirs'
|
|
|
|
self.statut('Prendre (' + joueur + ')')
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def dPionAnimCoords(i):
|
|
|
|
x = i['x1'] + (i['x2']-i['x1']) * (i['avancement']/i['total'])
|
|
|
|
y = i['y1'] + (i['y2']-i['y1']) * (i['avancement']/i['total'])
|
|
|
|
return [x, y]
|
|
|
|
|
|
|
|
def dPionAnim(self):
|
|
|
|
animationsNv = []
|
|
|
|
for i in self.animations:
|
|
|
|
if i['avancement'] < i['total']:
|
|
|
|
coords = self.dPionAnimCoords(i)
|
|
|
|
self.can.coords(i['pion'], coords[0], coords[1])
|
|
|
|
i['avancement'] += INTER_ANIM
|
|
|
|
animationsNv.append(i)
|
|
|
|
else:
|
|
|
|
self.can.coords(i['pion'], i['x2'], i['y2'])
|
|
|
|
self.animations = animationsNv
|
|
|
|
if len(animationsNv):
|
|
|
|
self.fen.after(INTER_ANIM, self.dPionAnim)
|
|
|
|
|
|
|
|
def cdPionAnim(self, x1, y1, x2, y2, pion):
|
|
|
|
animation = {
|
|
|
|
'x1': x1,
|
|
|
|
'y1': y1,
|
|
|
|
'x2': x2,
|
|
|
|
'y2': y2,
|
|
|
|
'pion': pion,
|
|
|
|
'total': TEMPS_ANIM,
|
|
|
|
'avancement': 0
|
|
|
|
}
|
|
|
|
|
|
|
|
if not len(self.animations):
|
|
|
|
self.animations.append(animation)
|
|
|
|
self.dPionAnim()
|
|
|
|
else:
|
|
|
|
for i in self.animations:
|
|
|
|
if i['pion'] == pion: # Si une animation pour ce pion existe
|
|
|
|
# déjà, on la reprend et on la modifie
|
|
|
|
coords = self.dPionAnimCoords(i)
|
|
|
|
i['x1'] = coords[0]
|
|
|
|
i['y1'] = coords[1]
|
|
|
|
i['x2'] = x2
|
|
|
|
i['y2'] = y2
|
|
|
|
# i['total'] = i['total'] - i['avancement']
|
|
|
|
i['total'] = TEMPS_ANIM
|
|
|
|
i['avancement'] = 0
|
|
|
|
return
|
|
|
|
self.animations.append(animation)
|
|
|
|
|
|
|
|
|
|
|
|
def dPion(self, x1, y1, x2, y2):
|
|
|
|
test = self.logique.dPion(x1, y1, x2, y2)
|
|
|
|
if test == True:
|
|
|
|
self.grillePions[x2][y2], self.grillePions[x1][y1] = \
|
|
|
|
self.grillePions[x1][y1], False
|
|
|
|
self.cdPionAnim((x1 + .5) * COTE_CASE, (y1 + .5) * COTE_CASE, \
|
|
|
|
(x2 + .5) * COTE_CASE, (y2 + .5) * COTE_CASE, \
|
|
|
|
self.grillePions[x2][y2])
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
# TODO Messages corrects
|
|
|
|
self.statut('Impossible ! (' + str(test) + ')')
|
|
|
|
return False
|
|
|
|
|
|
|
|
def dClic(self, x, y):
|
|
|
|
# if not len(self.animations):
|
|
|
|
if self.dEtape:
|
|
|
|
self.dx1, self.dy1 = x, y
|
|
|
|
# TODO Colorer case
|
|
|
|
self.statut('Poser')
|
|
|
|
else:
|
|
|
|
self.dx2, self.dy2 = x, y
|
|
|
|
self.dPion(self.dx1, self.dy1, self.dx2, self.dy2)
|
|
|
|
self.statutPrendre()
|
|
|
|
self.dEtape = not self.dEtape
|
|
|
|
|
|
|
|
def clic(self, event):
|
|
|
|
x = event.x // COTE_CASE
|
|
|
|
y = event.y // COTE_CASE
|
|
|
|
self.dClic(x, y)
|
|
|
|
|
|
|
|
p = PlateauTk()
|
|
|
|
|
|
|
|
# TODO Un jeu (canvas) et un frontend (fenetre)
|