from Outils.Moteur_de_jeu.Pathfinding import * from Outils.Moteur_de_jeu.Barriere import * from Outils.Moteur_de_jeu.Coup import * def suppr (t, a) : #Elric et Baptiste 09/2016 """ On supprime tout les elements valant a dans le tableau t """ for i in t : if i == a : t.remove(i) """ Conventions : - Les coordonnées vont de 0 à lg - 1 horizontalement et ht - 1 verticalement - L'origine des axes est en haut à gauche - Le barycentre d'une barrière est reperé par les coordonnées de la case en haut à gauche --- --- |ici| | ---B--- B = milieu de la barrière | | | --- --- - Le joueur 0 commence sur la ligne 0, le joueur 1 sur la ligne ht - 1 - D'accord ici """ class Plateau : # Jovian : 18 octobre 2016 """ On dispose des méthodes suivantes : .copie(self) .joueur_sur_case(self, num, x, y) .cases_voisines(self, x, y) .cases_accessibles(self, x, y) .cases_accessibles_depuis(self, x, y, num) .cases_accessibles_joueur(self, num) .point_libre(plateau, x, y) .point_barrieres_possibles(self, x, y) .rangee_desiree(self, num) .barriere_possible(self, barriere) .liste_barrieres_possibles(plateau, num) .liste_coups_possibles(self, num) .executer_coup(self, coup, num) .gagnant(self) .longueur_chemin(self, num) .barrieres_adjacentes .pions_voisins .bord_adjacent .contact (self,num) """ def __init__(self, lg, ht, nombre_barrieres) : # Quentin 06/10/2016 self.pions = [[(lg-1)//2, 0], [(lg-1)//2, ht - 1]] self.barrieres_restantes = [nombre_barrieres, nombre_barrieres] self.liste_barrieres = [] self.lg = lg self.ht = ht self.tour = 0 # Joueur dont c'est le tour def copie(self) : #Quentin 06/10/2016 """ Retourne un nouveau plateau, copie de celui passé en paramètre. """ nouveau = Plateau(self.lg, self.ht, 0) nouveau.pions = [list(self.pions[0]),list(self.pions[1])] nouveau.barrieres_restantes = list(self.barrieres_restantes) nouveau.liste_barrieres = list(self.liste_barrieres) nouveau.tour = self.tour return nouveau def copie_complete(self) : """ Copie également les barrières """ nouveau = Plateau(self.lg, self.ht, 0) nouveau.pions = [list(self.pions[0]),list(self.pions[1])] nouveau.barrieres_restantes = list(self.barrieres_restantes) for b in self.liste_barrieres : nouveau.liste_barrieres.append(b.copie()) nouveau.tour = self.tour return nouveau def joueur_sur_case(self, num, x, y) : #Elric et Baptiste 10/2016 """ Retourne True si le joueur num est sur la case (x,y) """ return self.pions[num] == [x,y] def cases_accessibles_depuis(self, x0, y0, num) : #Elric et Baptiste, 11/10 """Cases accessibles depuis la case (x0, y0) par le joueur num s'il était placé sur cette case. Prend en compte la possibilité de saut et les barrières.""" liste = cases_accessibles(self, x0, y0) for c in liste : (x, y) = c if self.joueur_sur_case(1-num, x, y) :#Si l'adversaire est présent sur une case voisine, suppr(liste,c) liste2 = cases_accessibles(self, x, y) for i in liste2 : liste.append(i) suppr(liste,(x0,y0)) return liste def cases_accessibles_joueur(self, num) : #Quentin 06/10/2016 """ Cases accessibles par le joueur num depuis la case où il est réellement placé """ return self.cases_accessibles_depuis(self.pions[num][0], self.pions[num][1], num) def point_libre(self, x, y) : #Elric et Baptiste 09/2016 """ Retourne une chaîne de caractères correspondant aux barrières pouvant être placées en (x, y) "" : aucune "h" : horizontale "v" : verticale "vh" : les deux """ b = self.liste_barrieres t = ["v", "h"] for bar in b : if bar.x == x-1 and bar.y == y and bar.orientation == "h" : suppr (t, "h") elif bar.x == x+1 and bar.y == y and bar.orientation == "h" : suppr (t, "h") elif bar.x == x and bar.y == y-1 and bar.orientation == "v" : suppr (t, "v") if bar.x == x and bar.y == y+1 and bar.orientation == "v" : suppr (t, "v") elif bar.x == x and bar.y == y : t = [] while len(t) < 2 : t.append(" ") return(t[0] + t[1]) def pourri_chemin (self , t ) : """ prend un plateau et un chemin en entrée retourne la liste des barrières permettant de pourrir le chemin entré """ n = len(t) tab = [] for k in range (n - 1) : x1 = t[k][0] x2 = t[k+1][0] y1 = t[k][1] y2 = t[k+1][1] if x1 == x2 : if y1 == y2 + 1 : tab.append ( Barriere("h", x1, y2) ) tab.append (Barriere("h", x1 - 1, y2) ) else: tab.append ( Barriere("h", x1, y1) ) tab.append ( Barriere("h", x1 - 1, y1) ) else : if x1 == x2 + 1 : tab.append ( Barriere("v", x1 - 1, y1 - 1) ) tab.append ( Barriere("v", x1 - 1, y1) ) else : tab.append ( Barriere("v", x1, y1 ) ) tab.append ( Barriere("v", x1, y1 - 1) ) return tab def point_barrieres_possibles(self, x, y) : #Elric et Baptiste 09/2016 """Retourne la liste des barrières pouvant être placées en (x, y)""" p = self.point_libre(x, y) if " " == p : return [] elif p == "h " : return [Barriere("h", x, y)] elif p == "v " : return [Barriere("v", x, y)] else : return [Barriere("h", x, y), Barriere("v", x, y)] def rangee_desiree(self, num) : #Quentin 04/10/2016 """ Retourne la rangée que doit atteindre le joueur num """ return (self.ht - 1)*(1 - num) def barriere_possible (self, barriere) : # Jovian 18/10/16 : optimisation """ Permet de savoir si une barrière peut être placée sans isoler un pion du bord qu'il cherche à atteindre. Argument self : le plateau qui lance la méthode. Argument barriere : objet barrière supposée posable sans collision. Retour : un booléen qui retourne True si la barrière est valide. """ # Si la barrière a moins de deux contacts, elle ne peut pas fermer de contour. Il n'est donc pas nécessaire de la vérifier. if self.nombre_contacts(barriere) < 2 : return True # Mise en place de la barrière pour l'expérience self.liste_barrieres.append( barriere ) # Pathfinding joueur A joueurA = self.pions[0] trajetA = path_finding( self, joueurA[0], joueurA[1], self.rangee_desiree(0) ) if trajetA == [] : # Arrivée non joignable dans ce cas self.liste_barrieres.pop() return False # Pathfinding joueur B joueurB = self.pions[1] trajetB = path_finding( self, joueurB[0], joueurB[1], self.rangee_desiree(1) ) if trajetB == [] : # Arrivée non joignable dans ce cas self.liste_barrieres.pop() return False # L'arrivée est joignable self.liste_barrieres.pop() return True ## def liste_barrieres_possibles (self) : #Elric et Baptiste 04/10/2016 #accélération Elric 25/11 ## """ ## Retourne la liste de toutes les barrières pouvant être placées ce tour-ci en tenant compte de toutes les contraintes existantes. ## """ ## ## if self.barrieres_restantes[self.tour] == 0 : ## return [] ## tab = [] ## ## for y in range (self.ht - 1) : ## for x in range (self.lg - 1) : ## bar = self.point_barrieres_possibles (x, y) ## for i in bar : ## if self.barriere_possible (i) : ## tab.append(i) ## ## ## """joueurA = self.pions[0] ## trajetA = path_finding( self, joueurA[0], joueurA[1], self.rangee_desiree(0) ) ## t = self.pourri_chemin(trajetA) ## joueurB = self.pions[1] ## trajetB = path_finding( self, joueurB[0], joueurB[1], self.rangee_desiree(1) ) ## ## t += self.pourri_chemin(trajetB) ## ## for i in t : ## if self.barriere_possible (i) : ## tab.append(i)""" ## ## return tab def liste_barrieres_possibles (self) : #Elric et Baptiste 04/10/2016 #accélération Elric 25/11 """ Retourne la liste de toutes les barrières pouvant être placées ce tour-ci en tenant compte de toutes les contraintes existantes. """ if self.barrieres_restantes[self.tour] == 0 : return [] tab = [] joueurA = self.pions[0] trajetA = path_finding( self, joueurA[0], joueurA[1], self.rangee_desiree(0) ) t = self.pourri_chemin(trajetA) joueurB = self.pions[1] trajetB = path_finding( self, joueurB[0], joueurB[1], self.rangee_desiree(1) ) t += self.pourri_chemin(trajetB) for x in range ( self.lg -1): for y in range (self.ht -1) : bar = self.point_barrieres_possibles( x, y) for i in bar : if i in t : if self.barriere_possible (i) : tab.append(i) else : tab.append(i) return tab def liste_coups_possibles(self) : """ Liste des coups possibles à disposition du joueur actuel """ t = [] mouvements = self.cases_accessibles_joueur(self.tour) barrieres = self.liste_barrieres_possibles() #On met les mouvements for m in mouvements : t.append(Coup("M",case = m)) # On met les barrières for b in barrieres : t.append(Coup("B",barriere = b)) return t def executer_coup(self, coup) : #Quentin 06/10/2016 """ Exécute un coup de la part du joueur dont c'est le tour""" if coup.type == "M" : self.pions[self.tour][0] = coup.case[0] self.pions[self.tour][1] = coup.case[1] else : self.liste_barrieres.append(coup.barriere) self.barrieres_restantes[self.tour] -= 1 self.tour = 1 - self.tour def gagnant(self) : """ Détermine si un plateau correpsond à une partie terminée. Retourne : > -1 si la partie est toujours en cours > le numéro du gagannt sinon """ if self.pions[0][1] == self.rangee_desiree(0) : return 0 elif self.pions[1][1] == self.rangee_desiree(1) : return 1 else : return -1 def chemin(self,num) : return path_finding(self, self.pions[num][0], self.pions[num][1], self.rangee_desiree(num)) def longueur_chemin(self, num) : # Quentin 08/11/2016 """ Retourne la longueur du chemin le plus court entre un joueur et le bord recherché """ return len( path_finding(self, self.pions[num][0], self.pions[num][1], self.rangee_desiree(num)) ) - 1 def bord_adjacent (self, bar) : # Elric, 09/11/2016 """ Prend un barrière en entrée, et retourne le tableau contenant les bords la touchant RETOURNE un tableau de booléens """ if bar.orientation == "h" : return [bar.x == 0, False, bar.x == self.lg - 2] else : return [bar.y == 0, False, bar.y == self.ht - 2] def pions_voisins(self, bar) : # Elric, 19/11/2016 """ Prend une barrière en entrée, donne s'il y a un pion qui colle la barrière ou pas. RETOURNE un booléen """ position1 = self.pions[0] position2 = self.pions[1] t = [[bar.x,bar.y] , [bar.x + 1 , bar.y + 1] , [bar.x , bar.y + 1 ] , [bar.x +1, bar.y ]] return ( position1 in t or position2 in t ) def barrieres_adjacentes(self, bar) : """ Prend une barrière en entrée, et retourne le tableau contenant les barrières la touchant """ if bar.orientation == "h" : b1 = Barriere ("v", bar.x, bar.y + 1) b2 = Barriere ("v", bar.x - 1, bar.y + 1) b3 = Barriere ("v", bar.x + 1, bar.y + 1) b4 = Barriere ("v", bar.x, bar.y - 1) b5 = Barriere ("v", bar.x + 1, bar.y - 1) b6 = Barriere ("v", bar.x - 1, bar.y - 1) b7 = Barriere ("h", bar.x - 2, bar.y) b8 = Barriere ("h", bar.x + 2, bar.y) b9 = Barriere ("v", bar.x - 1, bar.y) b10 = Barriere ("v", bar.x + 1, bar.y) t = [b1, b2, b3, b4, b5, b6, b7, b8, b9, b10 ] res = [] for a in self.liste_barrieres : if a in t : res.append(a) else : b1 = Barriere ("v", bar.x, bar.y + 2) b2 = Barriere ("v", bar.x, bar.y - 2) b3 = Barriere ("h", bar.x + 1, bar.y + 1) b4 = Barriere ("h", bar.x + 1, bar.y - 1) b5 = Barriere ("h", bar.x + 1, bar.y) b6 = Barriere ("h", bar.x - 1, bar.y - 1) b7 = Barriere ("h", bar.x - 1, bar.y) b8 = Barriere ("h", bar.x - 1, bar.y + 1) b9 = Barriere ("h", bar.x , bar.y - 1) b10 = Barriere ("h", bar.x , bar.y + 1) res = [] t = [b1, b2, b3, b4, b5, b6, b7, b8, b9, b10 ] for a in self.liste_barrieres : if a in t : res.append(a) return res def barrieres_adjacentes_precis(self, b0) : # Quentin 15/11/2016 """ b0 est une barrière, qui peut être vue comme un triplet de trois noeuds. Cette fonction retourne la liste des barrières et des bords (représentés par des None) qui touchent chaque noeud, sous forme d'un tableau de tableaux. Le sens de lecture est de gauche à droite si b0 est horizontale, et de haut en bas si b0 est verticale. """ tab_final = [[],[],[]] if b0.orientation == "h" : tab_potentiel = [[Barriere ("v", b0.x - 1, b0.y - 1), Barriere ("v", b0.x - 1, b0.y), Barriere ("v", b0.x - 1, b0.y + 1), Barriere ("h", b0.x - 2, b0.y)], [Barriere ("v", b0.x, b0.y - 1), Barriere ("v", b0.x, b0.y + 1)], [Barriere ("v", b0.x + 1, b0.y - 1), Barriere ("v", b0.x + 1, b0.y), Barriere ("v", b0.x + 1, b0.y + 1), Barriere ("h", b0.x + 2, b0.y)]] if b0.x == 0 : tab_final[0].append(None) if b0.x == self.lg - 2 : tab_final[2].append(None) else : tab_potentiel = [[Barriere ("h", b0.x - 1, b0.y - 1), Barriere ("h", b0.x, b0.y - 1), Barriere ("h", b0.x + 1, b0.y - 1), Barriere ("v", b0.x, b0.y - 2)], [Barriere ("h", b0.x - 1, b0.y), Barriere ("h", b0.x + 1, b0.y)], [Barriere ("h", b0.x - 1, b0.y + 1), Barriere ("h", b0.x, b0.y + 1), Barriere ("h", b0.x + 1, b0.y + 1), Barriere ("v", b0.x, b0.y + 2)]] if b0.y == 0 : tab_final[0].append(None) if b0.y == self.ht - 2 : tab_final[2].append(None) for b in self.liste_barrieres : for i in range(3) : if b in tab_potentiel[i] : tab_final[i].append(b) return tab_final def nombre_contacts(self, b) : """ Retourne le nombre de noeuds de la barrière b ayant un contact avec une barrière du plateau """ tab = self.barrieres_adjacentes_precis(b) nb = 0 for i in range(3) : if tab[i] != [] : nb += 1 return nb def contact (self, x, y) :#Elric, 25/11 """ Si une barrière touche le pion num. C'est un booléen """ for i in self.liste_barrieres : if (i.x == x and i.y == y ) or (i.x == x-1 and i.y == y ) or (i.x == x and i.y == y-1 ) or (i.x == x-1 and i.y == y-1 ) : return True return False