import kblibpub class c_joueur: def __init__(self, num_joueur, nbr_joueurs, points_objectif): self.num_joueur = num_joueur # mon numero de joueur self.nbr_joueurs = nbr_joueurs # nombre total de joueurs # informations de jeu collectees sur l'ensemble des joueurs self.infos_joueurs: list[kblibpub.c_infos_jeu] = [ i == num_joueur and kblibpub.c_infos_jeu_et_main( i, nbr_joueurs, points_objectif) or kblibpub.c_infos_jeu( i, nbr_joueurs, points_objectif ) for i in range(nbr_joueurs) ] # mes informations de jeu self.infos_joueur: kblibpub.c_infos_jeu_et_main = self.infos_joueurs[ num_joueur] # nom de l'IA self.nom_joueur = "42" # version de l'IA self.ver_joueur = "2.4" # nom de groupe (optionnel, pour les participants decidant de rejoindre un groupe) self.nom_groupe = "" # signature du groupe (a demander et recuperer aupres du chef de groupe) self.sig_groupe = "" # cri de victoire de l'IA self.msg_joueur = ( "What was the question ?" ) # Cartes déjà jouées self.cartes_jouees = [] # -------------------------------------------------- # DEBUT DES FONCTIONS NECESSITANT D'ETRE AMELIOREES # -------------------------------------------------- def decide_coup(self): """Decide du coup a jouer.""" # Coup à jouer coup = None # Ordre de priorité des actions : ordre_actions = [ self.pioche_si_vide, self.coup_fourré, self.pioche_si_possible, self.attaque_si_possible, self.defense_si_possible, self.demarrer_si_possible, self.botte_si_fin_de_partie, # TODO: Adapter au jeu en cours pour le 200 bornes self.joue_carte_puissante, self.jouer_carte_moins_puissante, self.botte_si_possible, self.defausse_carte_inutile, self.defausse_si_possible, ] # On itère sur les actions possibles jusqu'à ce qu'on en trouve une qui # marche for action in ordre_actions: coup = action() coup = coup and coup or None if coup: # Vérifie que le coup est valide if coup.invalide(self.nbr_joueurs) or\ self.infos_joueur.coup_invalide(coup) or \ self.infos_joueurs[coup.destination].\ coup_invalide(coup): self.infos_joueur.coup_invalide(coup) error = f"Coup invalide : {coup.to_str()}\n" error += f"Infos joueur : {self.infos_joueur.to_str()}\n" if coup.destination not in [ kblibpub.SABOT, self.num_joueur]: error += "Infos joueur destination : " error += self.infos_joueurs[coup.destination].to_str() error += "\n" # On inclut également le nom de la méthode qui a généré # l'erreur error += f"Erreur dans la méthode {action.__name__}" self.assert_custom(False, error) break return coup def cartes_restantes(self): """Retourne la liste des cartes qui ne sont pas sorties.""" # On initialise la liste de toutes les cartes pioche_r = [kblibpub.I_CAMION_CITERNE, kblibpub.I_VEHICULE_INCREVABLE, kblibpub.I_AS_VOLANT, kblibpub.I_VEHICULE_PRIORITAIRE] # cartes bottes, 1 de chaque pioche_r += [kblibpub.I_PANNE_ESSENCE, kblibpub.I_CREVAISON, kblibpub.I_ACCIDENT]*3 + [kblibpub.I_LIMITATION,]*4 + [kblibpub.I_FEU_ROUGE,]*5 # cartes d'attaque pioche_r += [kblibpub.I_POMPE_ESSENCE, kblibpub.I_ROUE_SECOURS, kblibpub.I_REPARATIONS, kblibpub.I_FIN_LIMITATION]*6 + [kblibpub.I_FEU_VERT,]*14 # cartes de parade pioche_r += [kblibpub.I_25_BORNES, kblibpub.I_50_BORNES, kblibpub.I_75_BORNES]*10 + [kblibpub.I_100_BORNES,]*12 + [kblibpub.I_200_BORNES,]*4 # Ensuite, on supprime toutes les cartes déjà sorties for carte in self.cartes_jouees: pioche_r.remove(carte) return pioche_r def cartes_restantes_type(self, carte_testee) -> int: """Retourne le nombre de cartes restantes d'un type (hors main)...""" # On récupère les cartes restantes cartes = self.cartes_restantes() # Ensuite, on supprime toutes les cartes de la main for carte in self.infos_joueur.main: cartes.remove(carte) # Ensuite, on compte le nombre de cartes correspondantes nombre = 0 for carte in cartes: if carte == carte_testee: nombre += 1 # Ensuite, on retourne le nombre de cartes du type return nombre def bornes_restantes_moyenne(self): """ Retourne le nombre de cartes bornes disponibles dans le sabot qui vont être piochées en moyenne. """ # On détermine les cartes restantes cartes_restantes = self.cartes_restantes() # Dictionnaire carte/bornes bornes = { kblibpub.I_200_BORNES: 200, kblibpub.I_100_BORNES: 100, kblibpub.I_75_BORNES: 75, kblibpub.I_50_BORNES: 50, kblibpub.I_25_BORNES: 25 } # Somme de toutes les cartes somme = 0 # On itére sur les cartes restantes for carte in cartes_restantes: if carte in bornes: somme += bornes[carte] # On retourne la somme divisée par deux # TODO: Prendre en compte les cartes dans la main de l'adversaire et # supprimer les notres return somme / 2 def tours_restants_adversaire_minimum(self, joueur): """ Retourne le nombre minimum de tours requis pour que l'adversaire gagne. Retourne False si l'adversaire ne peut pas gagner, """ # Liste des cartes bornes cartes_bornes = { 200: kblibpub.I_200_BORNES, 100: kblibpub.I_100_BORNES, 75: kblibpub.I_75_BORNES, 50: kblibpub.I_50_BORNES, 25: kblibpub.I_25_BORNES, } # Nombre de bornes restantes à parcourir bornes_restantes = self.infos_joueurs[joueur].bornes_arrivee -\ self.infos_joueurs[joueur].bornes tours = 0 for bornes, carte in cartes_bornes.items(): # On récupère le nombre de cartes disponibles cartes_disponibles = self.cartes_restantes_type(carte) # On itère sur le nombre de cartes présentes for _ in range(cartes_disponibles): if bornes_restantes >= bornes: tours += 1 bornes_restantes -= bornes else: break if bornes_restantes == 0: return tours # Si on n'est pas arrivé au bout, l'adversaire à probablement perdu return False def pari_allonge(self, bornes_arrivee): """Decide si on allonge ou non.""" # Tout d'abord, on regarde le nombre de tours restants # nbr_tours_restants = 106 - len(self.cartes_jouees) nbr_tours_restants = int(self.infos_joueur.nbr_cartes / self.nbr_joueurs) # On fixe la limite à 10 tours (moins de 10 tours, le risque est trop # grand) if nbr_tours_restants < 10: return False # # On regarde les cartes présentes dans la main # cartes_bornes = { # kblibpub.I_200_BORNES: 200, # kblibpub.I_100_BORNES: 100, # kblibpub.I_75_BORNES: 75, # kblibpub.I_50_BORNES: 50, # kblibpub.I_25_BORNES: 25, # } # # Nombre de bornes possibles avec les cartes en main # bornes_possibles = sum( # self.infos_joueur.main.count(carte) * value # for carte, value in cartes_bornes.items() # ) # On calcule les bornes restantes moyennes bornes_restantes_moyenne = self.bornes_restantes_moyenne() # TODO: Calculer en fonction du nombre de tours restants. # On adopte une strategie pessimiste quand aux cartes qui vont être piochées if bornes_restantes_moyenne >= (300 * 1.5): return True return False def joueur_attaque(self, num_joueur): """Retourne si le joueur est attaqué.""" if kblibpub.est_carte_attaque( self.infos_joueurs[num_joueur].carte_bataille()): return True if kblibpub.est_carte_attaque( self.infos_joueurs[num_joueur].carte_vitesse()): return True return False def pioche_si_vide(self): """ Pioche une carte si la main est vide. Retourne True si une carte a ete piochee, False sinon. Sert à éviter de planter quand la main est vide. """ if len(self.infos_joueur.main) == 0: return self.pioche_si_possible(force=True) def attaque_joueur_si_possible(self, joueur): """ Attaque un joueur si possible. Retourne True si une attaque a ete effectuee, False sinon. """ # # Si le joueur est déjà attaqué, on ne fait rien if self.joueur_attaque(joueur): return False # Si l'adversaire n'a rien sur la pile de bataille, on ne peut pas # attaquer if self.infos_joueurs[joueur].\ carte_bataille() is None: return False # L'ordre d'importance des attaques (Limitation est le moins utile) attaques_ordre = [ kblibpub.I_CREVAISON, kblibpub.I_PANNE_ESSENCE, kblibpub.I_ACCIDENT, kblibpub.I_FEU_ROUGE, kblibpub.I_LIMITATION, ] # On récupère les cartes d'attaque disponibles cartes_attaques_disponibles = [ carte for carte in self.infos_joueur.main if kblibpub.est_carte_attaque(carte) ] # On trie les cartes d'attaque disponibles par ordre d'importance cartes_attaques_disponibles.sort( key=lambda carte: attaques_ordre.index(carte)) # Si on n'a pas de cartes d'attaque, on ne fait rien if not cartes_attaques_disponibles: return False # On itère sur les cartes d'attaque disponibles jusqu'à ce qu'on en # trouve une qui marche for carte in cartes_attaques_disponibles: coup = kblibpub.c_coup( self.num_joueur, carte, joueur, ) # Si le coup n'est pas invalide, on le joue (invalide en cas de # botte) if not self.infos_joueurs[joueur].\ coup_invalide(coup): return coup def attaque_si_possible(self): """Attaque l'un des joueurs si possible.""" # On attaque le joueur qui peut gagner le plus rapidement joueur_tries = {} for joueur in range(self.nbr_joueurs): if joueur == self.num_joueur: continue # # On calcule les tours restants # tours_restants = self.tours_restants_adversaire_minimum(joueur) # # On crée la liste si elle n'existe pas # if tours_restants not in joueur_tries: # joueur_tries[tours_restants] = [] # # On ajoute le joueur dans la liste # joueur_tries[tours_restants].append(joueur) # On calcule le score score = self.infos_joueurs[joueur].points if score not in joueur_tries: joueur_tries[score] = [] # On ajoute le joueur dans la liste joueur_tries[score].append(joueur) # On trie le dictionnaire (possible depuis Python 3.7) joueur_tries = dict(reversed(sorted(joueur_tries.items()))) # On itère sur le dictionnaire for points in joueur_tries: # On itère sur les joueurs, vu qu'ils sont égaux # TODO: Prendre en compte les points for joueur in joueur_tries[points]: coup = self.attaque_joueur_si_possible(joueur) if coup: return coup return False def coup_fourré(self): """ Retourne le coup pour un coup fourré si possible """ # Si le joueur n'est pas attaqué, on ne fait rien if not self.joueur_attaque(self.num_joueur): return False # Dictionnaire des cartes de bottes par rapport aux cartes d'attaque cartes_bottes = { kblibpub.I_CREVAISON: ( kblibpub.I_VEHICULE_INCREVABLE,), kblibpub.I_PANNE_ESSENCE: ( kblibpub.I_CAMION_CITERNE,), kblibpub.I_ACCIDENT: ( kblibpub.I_AS_VOLANT,), kblibpub.I_FEU_ROUGE: ( kblibpub.I_VEHICULE_PRIORITAIRE,), kblibpub.I_LIMITATION: ( kblibpub.I_VEHICULE_PRIORITAIRE,), } # On récupère la carte d'attaque cartes_attaque = [ carte for carte in [self.infos_joueur.carte_bataille(), self.infos_joueur.carte_vitesse()] if kblibpub.est_carte_attaque(carte) ] # Tri des cartes d'attaque par ordre d'importance cartes_attaque.sort( key=lambda carte: list(cartes_bottes.keys()).index(carte) ) for carte_attaque in cartes_attaque: # On itère sur les cartes de botte for carte_defense in cartes_bottes[carte_attaque]: # Si on a une carte de botte, on la joue if carte_defense in self.infos_joueur.main: self.assert_custom(kblibpub.est_carte_botte( carte_defense), "Le coup fourré n'est pas une botte") return kblibpub.c_coup( self.num_joueur, carte_defense, self.num_joueur, ) # Si on n'a pas de carte de botte, on ne fait rien return False def defense_si_possible(self): """ Se defend contre une attaque si possible. Retourne True si une defense a ete effectuee, False sinon. """ # Obligation de piocher si notre main n'est pas pleine if len(self.infos_joueur.main) < self.taille_main: coup = self.pioche_si_possible() self.assert_custom(coup is not False, "Pas de carte à piocher") return coup # Si le joueur n'est pas attaqué, on ne fait rien if not self.joueur_attaque(self.num_joueur): return False # Dictionnaire des cartes de défense par rapport aux cartes d'attaque cartes_defense = { kblibpub.I_CREVAISON: ( kblibpub.I_VEHICULE_INCREVABLE, kblibpub.I_ROUE_SECOURS), kblibpub.I_PANNE_ESSENCE: ( kblibpub.I_CAMION_CITERNE, kblibpub.I_POMPE_ESSENCE), kblibpub.I_ACCIDENT: ( kblibpub.I_AS_VOLANT, kblibpub.I_REPARATIONS), kblibpub.I_FEU_ROUGE: ( kblibpub.I_VEHICULE_PRIORITAIRE, kblibpub.I_FEU_VERT), kblibpub.I_LIMITATION: ( kblibpub.I_VEHICULE_PRIORITAIRE, kblibpub.I_FIN_LIMITATION), } # On récupère la carte d'attaque cartes_attaque = [ carte for carte in [self.infos_joueurs[self.num_joueur].carte_bataille(), self.infos_joueurs[self.num_joueur].carte_vitesse()] if kblibpub.est_carte_attaque(carte) ] # Tri des cartes d'attaque par ordre d'importance cartes_attaque.sort( key=lambda carte: list(cartes_defense.keys()).index(carte) ) for carte_attaque in cartes_attaque: # On itère sur les cartes de défense for carte_defense in cartes_defense[carte_attaque]: # Si on a une carte de défense, on la joue if carte_defense in self.infos_joueur.main: self.assert_custom(not kblibpub.est_carte_botte( carte_defense), "Le coup fourré n'a pas été effectué " "par la bonne methode") return kblibpub.c_coup( self.num_joueur, carte_defense, self.num_joueur, ) # Si on n'a pas de carte de défense, on ne fait rien return False def demarrer_si_possible(self): """ Demarre si possible. Retourne True si une carte a ete jouee, False sinon. """ # Si on est attaqué, on ne fait rien if self.joueur_attaque(self.num_joueur): return False # Si on est en capacité de rouler, on ne fait rien if self.infos_joueur.vehicule_roulant(): return False # Si on a une carte de démarrage, on la joue if kblibpub.I_FEU_VERT in self.infos_joueur.main: return kblibpub.c_coup( self.num_joueur, kblibpub.I_FEU_VERT, self.num_joueur, ) # Si on n'a pas de carte de démarrage, on ne fait rien return False def peut_gagner(self) -> bool: """Retourne si le joueur peut finir la partie immediatement.""" # Liste des cartes bornes cartes_bornes = { 200: kblibpub.I_200_BORNES, 100: kblibpub.I_100_BORNES, 75: kblibpub.I_75_BORNES, 50: kblibpub.I_50_BORNES, 25: kblibpub.I_25_BORNES, } # Nombre de bornes restantes à parcourir bornes_restantes = self.infos_joueur.bornes_arrivee -\ self.infos_joueur.bornes if bornes_restantes not in cartes_bornes: return False if cartes_bornes[bornes_restantes] in self.infos_joueur.main: return True return False def botte_si_fin_de_partie(self): """ Jouer une botte en cas de fin de partie, plutôt que de terminer directement. """ if self.peut_gagner(): for joueur in range(self.nbr_joueurs): if joueur == self.num_joueur: continue tours_restants = self.tours_restants_adversaire_minimum(joueur) # Si l'adversaire ne peut pas gagner, on passe au suivant if not tours_restants: continue if tours_restants >= 1: return False return self.botte_si_possible() def joue_carte_puissante(self): """ Joue une carte puissante si possible. Retourne True si une carte a ete jouee, False sinon. """ # Si on est attaqué, on ne fait rien if self.joueur_attaque(self.num_joueur): return False # Si on n'est pas en capacité de rouler, on ne fait rien if not self.infos_joueur.vehicule_roulant(): return False # Liste des cartes puissantes cartes_puissantes = [ kblibpub.I_200_BORNES, ] # On joue la carte la plus puissante for carte in cartes_puissantes: if carte in self.infos_joueur.main: coup = kblibpub.c_coup( self.num_joueur, carte, self.num_joueur, ) # Si le coup n'est pas invalide, on le joue if coup.invalide(self.nbr_joueurs) or\ self.infos_joueur.coup_invalide(coup) or \ self.infos_joueurs[coup.destination].\ coup_invalide(coup): continue return coup return False def pioche_si_possible(self, force=False): """ Pioche une carte si possible. Retourne True si une carte a ete piochee, False sinon. """ if len(self.infos_joueur.main) < self.taille_main or force: # si on a moins de cartes en main, alors on peut tirer une carte du et la rajouter a sa main origine = kblibpub.SABOT return kblibpub.c_coup(origine, None, self.num_joueur) return False def jouer_carte_moins_puissante(self): """ Joue une carte moins puissante si possible. Retourne True si une carte a ete jouee, False sinon. """ # Si on est attaqué, on ne fait rien if self.joueur_attaque(self.num_joueur): return False # Si on n'est pas en capacité de rouler, on ne fait rien if not self.infos_joueur.vehicule_roulant(): return False # Liste des cartes moins puissantes cartes_moins_puissantes = [ kblibpub.I_100_BORNES, kblibpub.I_75_BORNES, kblibpub.I_50_BORNES, kblibpub.I_25_BORNES, ] # Si on a une carte limitation, on enlève le 100 bornes et le 75 bornes if kblibpub.I_LIMITATION in self.infos_joueur.main: cartes_moins_puissantes.remove(kblibpub.I_100_BORNES) cartes_moins_puissantes.remove(kblibpub.I_75_BORNES) # On joue la carte la plus puissante for carte in cartes_moins_puissantes: if carte in self.infos_joueur.main: coup = kblibpub.c_coup( self.num_joueur, carte, self.num_joueur, ) if coup.invalide(self.nbr_joueurs) or\ self.infos_joueur.coup_invalide(coup) or \ self.infos_joueurs[coup.destination].\ coup_invalide(coup): continue return coup return False def botte_si_possible(self): """ Joue une botte si possible. Retourne True si une carte a ete jouee, False sinon. """ # Liste des cartes de bottes cartes_bottes = [ kblibpub.I_VEHICULE_INCREVABLE, kblibpub.I_CAMION_CITERNE, kblibpub.I_AS_VOLANT, kblibpub.I_VEHICULE_PRIORITAIRE, ] # On joue la carte la plus puissante for carte in cartes_bottes: if carte in self.infos_joueur.main: return kblibpub.c_coup( self.num_joueur, carte, self.num_joueur, ) return False def cartes_inutiles(self): """ Retourne les cartes d'attaque et de défense qui sont inutiles à cause des bottes. """ # Liste des cartes inutiles cartes_inutiles = [] # On récupère les bottes des adversaire bottes_adversaires = [] for joueur in range(self.nbr_joueurs): bottes_adversaires.extend(self.infos_joueurs[joueur].bottes) # On itère sur nos cartes d'attaque for carte in self.infos_joueur.main: # Si la carte n'est pas une carte d'attaque, on ignore if not kblibpub.est_carte_attaque(carte): continue # Sinon, on cherche la botte pour botte = kblibpub.botte_pour(carte) # On s'assure que la botte existe self.assert_custom(botte, "La carte n'a pas de botte correspondante") # Si l'adversaire à déjà posé la botte, on la marque comme inutile if botte in bottes_adversaires: cartes_inutiles.append(carte) # On récupère nos bottes bottes_posées = self.infos_joueur.bottes # On itère sur nos cartes de défense for carte in self.infos_joueur.main: # Si la carte n'est pas une carte de défense, on ignore if carte not in kblibpub.cartes_parade(): continue # Sinon, on cherche la botte pour botte = kblibpub.botte_pour(carte) # On s'assure que la botte existe self.assert_custom(botte, "La carte n'a pas de botte correspondante") # Si on à déjà posé la botte, on la marque comme inutile if botte in bottes_posées: cartes_inutiles.append(carte) # On itère sur la défense for carte_defense in kblibpub.cartes_parade(): if carte_defense not in self.infos_joueur.main: continue # On obtient la carte d'attaque correspondante carte_attaque = kblibpub.attaque_pour(carte_defense) # S'il ne reste plus de carte correspondantes dans le sabot/chez # l'adversaire, elle est inutile if self.cartes_restantes_type(carte_attaque) == 0: cartes_inutiles.append(carte_defense) return cartes_inutiles def defausse_carte_inutile(self): """Défausse les cartes inutiles présentes dans le jeu.""" cartes_inutiles = self.cartes_inutiles() # Si des cartes inutiles sont présentes, on jette la première if len(cartes_inutiles) > 0: return kblibpub.c_coup( self.num_joueur, cartes_inutiles[0], kblibpub.SABOT, ) # Si on n'a aucune carte inutile, on ne fait rien return False def defausse_si_possible(self): """ Defausse une carte si necessaire. Retourne True si une carte a ete defaussee, False sinon. """ # TODO: Adapater aux pénalités en cours # Si on a des cartes de parade en double, on en defausse une cartes_parade = [ kblibpub.I_FIN_LIMITATION, kblibpub.I_ROUE_SECOURS, kblibpub.I_POMPE_ESSENCE, kblibpub.I_REPARATIONS, kblibpub.I_FEU_VERT, ] for carte in cartes_parade: if self.infos_joueur.main.count(carte) > 1: return kblibpub.c_coup( self.num_joueur, carte, kblibpub.SABOT, ) # Si on a des cartes d'attaque en double, on en defausse une cartes_attaque = [ kblibpub.I_LIMITATION, kblibpub.I_CREVAISON, kblibpub.I_PANNE_ESSENCE, kblibpub.I_ACCIDENT, kblibpub.I_FEU_ROUGE, ] for carte in cartes_attaque: if self.infos_joueur.main.count(carte) > 1: return kblibpub.c_coup( self.num_joueur, carte, kblibpub.SABOT, ) cartes_attaque_disponibles = [ carte for carte in self.infos_joueur.main if kblibpub.est_carte_attaque(carte) ] # Si on a plus de 2 cartes attaque, on defausse la permière if len(cartes_attaque_disponibles) > 2: # S'il y a une limitation, on la jette if kblibpub.I_LIMITATION in cartes_attaque_disponibles: return kblibpub.c_coup( self.num_joueur, kblibpub.I_LIMITATION, kblibpub.SABOT, ) return kblibpub.c_coup( self.num_joueur, cartes_attaque_disponibles[0], kblibpub.SABOT, ) cartes_parade_disponibles = [ carte for carte in self.infos_joueur.main if kblibpub.est_carte_parade(carte) ] # Si on a plus de 2 cartes de parade, on en defausse une if len(cartes_parade_disponibles) > 2: if kblibpub.I_FIN_LIMITATION in cartes_parade_disponibles: return kblibpub.c_coup( self.num_joueur, kblibpub.I_FIN_LIMITATION, kblibpub.SABOT, ) return kblibpub.c_coup( self.num_joueur, cartes_parade_disponibles[0], kblibpub.SABOT, ) # Sinon, on jette la plus petite carte de bornes cartes_bornes = [ kblibpub.I_200_BORNES, kblibpub.I_25_BORNES, kblibpub.I_50_BORNES, kblibpub.I_75_BORNES, kblibpub.I_100_BORNES, ] for carte in cartes_bornes: if carte in self.infos_joueur.main: return kblibpub.c_coup( self.num_joueur, carte, kblibpub.SABOT, ) self.assert_custom(False, "Aucune carte à défausser") # On défausse la première carte return kblibpub.c_coup( self.num_joueur, self.infos_joueur.main[0], kblibpub.SABOT ) def assert_custom(self, value, message=""): """ Fonction a utiliser à la place de assert pour pouvoir détecter les erreurs dans le code .""" # pass assert value, message # -------------------------------------------------- # FIN DES FONCTIONS NECESSITANT D'ETRE AMELIOREES # -------------------------------------------------- def id_str(self): return self.infos_joueur.id_str() + \ " {:s} v{:s}".format(self.nom_joueur, self.ver_joueur) def nouvelle_manche(self, nbr_cartes, taille_main, bornes_arrivee): self.taille_main = taille_main for infos_joueur in self.infos_joueurs: infos_joueur.nouvelle_manche( nbr_cartes, taille_main, bornes_arrivee) def fin_manche(self, bornes_joueurs, len_pioche): """ Cette fonction est appelee a la fin de chaque manche. Elle est utile pour reinitialiser les informations de jeu collectees sur l'ensemble des joueurs. """ # On réinitialise les cartes jouées self.cartes_jouees = [] for infos_joueur in self.infos_joueurs: infos_joueur.fin_manche(bornes_joueurs, len_pioche) def allonge(self, num_joueur, bornes_arrivee): # TODO: Optimiser le jeu en fonction des allonges des autres joueurs for infos_joueur in self.infos_joueurs: infos_joueur.allonge(num_joueur, bornes_arrivee) def traite_coup(self, coup: kblibpub.c_coup): """ Cette fonction est appelee pour chaque coup joue par un joueur. Elle nous sert notamment a mettre a jour les informations de jeu collectees sur l'ensemble des joueurs. (et à estimer les cartes restantes dans le sabot) """ # On ajoute la carte jouée à la liste des cartes jouées if coup.carte is not None and coup.origine != kblibpub.SABOT: self.cartes_jouees.append(coup.carte) for i in range(self.nbr_joueurs): self.infos_joueurs[i].traite_coup(coup) def rejoint_groupe(self, num_joueur, nom_groupe): self.infos_joueurs[num_joueur].nom_groupe = nom_groupe