359 lines
11 KiB
Python
359 lines
11 KiB
Python
"""
|
|
Corrigé du TP Pokémon Arena — Programmation Orientée Objet
|
|
"""
|
|
|
|
# =============================================================================
|
|
# Dictionnaire des faiblesses (Bonus Exercice 3)
|
|
# =============================================================================
|
|
|
|
FAIBLESSES = {
|
|
"Eau": ["Feu"],
|
|
"Feu": ["Plante"],
|
|
"Plante": ["Eau"],
|
|
"Electrik": ["Eau"],
|
|
"Roche": ["Eau", "Plante"]
|
|
}
|
|
|
|
|
|
# =============================================================================
|
|
# PARTIE 1 : Classe Pokemon
|
|
# =============================================================================
|
|
|
|
class Pokemon:
|
|
def __init__(self, nom, type_pokemon, niveau=1, pv_max=100, attaque=10):
|
|
"""
|
|
Constructeur de la classe Pokemon.
|
|
|
|
:param nom: (str) Nom du Pokémon
|
|
:param type_pokemon: (str) Type élémentaire
|
|
:param niveau: (int) Niveau du Pokémon
|
|
:param pv_max: (int) Points de vie maximum
|
|
:param attaque: (int) Puissance d'attaque
|
|
"""
|
|
self.nom = nom
|
|
self.type_pokemon = type_pokemon
|
|
self.niveau = niveau
|
|
self.pv_max = pv_max
|
|
self.pv = pv_max
|
|
self.attaque = attaque
|
|
|
|
def __repr__(self):
|
|
"""Représentation textuelle du Pokémon."""
|
|
return f"{self.nom} ({self.type_pokemon}) - Nv.{self.niveau} - {self.pv}/{self.pv_max} PV"
|
|
|
|
def est_ko(self):
|
|
"""
|
|
Vérifie si le Pokémon est KO.
|
|
|
|
:return: (bool) True si PV <= 0, False sinon
|
|
"""
|
|
return self.pv <= 0
|
|
|
|
def subir_degats(self, degats):
|
|
"""
|
|
Inflige des dégâts au Pokémon.
|
|
Les PV ne peuvent pas descendre en dessous de 0.
|
|
|
|
:param degats: (int) Nombre de dégâts subis
|
|
"""
|
|
self.pv = max(0, self.pv - degats)
|
|
|
|
def attaquer(self, cible):
|
|
"""
|
|
Attaque un autre Pokémon avec prise en compte des faiblesses.
|
|
|
|
:param cible: (Pokemon) Pokémon ciblé par l'attaque
|
|
"""
|
|
degats = self.attaque
|
|
|
|
# Vérifier si le type de la cible est faible contre notre type
|
|
if self.type_pokemon in FAIBLESSES:
|
|
if cible.type_pokemon in FAIBLESSES[self.type_pokemon]:
|
|
degats *= 2
|
|
print(f"C'est super efficace !")
|
|
|
|
print(f"{self.nom} attaque {cible.nom} et inflige {degats} dégâts !")
|
|
cible.subir_degats(degats)
|
|
|
|
def soigner(self, soin):
|
|
"""
|
|
Soigne le Pokémon.
|
|
Les PV ne peuvent pas dépasser pv_max.
|
|
|
|
:param soin: (int) Nombre de PV récupérés
|
|
"""
|
|
self.pv = min(self.pv_max, self.pv + soin)
|
|
|
|
|
|
# =============================================================================
|
|
# PARTIE 2 : Classe Dresseur
|
|
# =============================================================================
|
|
|
|
class Dresseur:
|
|
def __init__(self, nom):
|
|
"""
|
|
Constructeur de la classe Dresseur.
|
|
|
|
:param nom: (str) Nom du dresseur
|
|
"""
|
|
self.nom = nom
|
|
self.equipe = []
|
|
|
|
def ajouter_pokemon(self, pokemon):
|
|
"""
|
|
Ajoute un Pokémon à l'équipe si possible (max 6).
|
|
|
|
:param pokemon: (Pokemon) Pokémon à ajouter
|
|
:return: (bool) True si ajouté, False sinon
|
|
"""
|
|
if len(self.equipe) < 6:
|
|
self.equipe.append(pokemon)
|
|
return True
|
|
else:
|
|
print("L'équipe est complète (6 Pokémon maximum) !")
|
|
return False
|
|
|
|
def pokemon_disponibles(self):
|
|
"""
|
|
Renvoie la liste des Pokémon non KO.
|
|
|
|
:return: (list) Liste des Pokémon encore en état de combattre
|
|
"""
|
|
disponibles = []
|
|
for pokemon in self.equipe:
|
|
if not pokemon.est_ko():
|
|
disponibles.append(pokemon)
|
|
return disponibles
|
|
|
|
def premier_pokemon_dispo(self):
|
|
"""
|
|
Renvoie le premier Pokémon non KO.
|
|
|
|
:return: (Pokemon/None) Premier Pokémon dispo ou None
|
|
"""
|
|
for pokemon in self.equipe:
|
|
if not pokemon.est_ko():
|
|
return pokemon
|
|
return None
|
|
|
|
def tous_ko(self):
|
|
"""
|
|
Vérifie si tous les Pokémon sont KO.
|
|
|
|
:return: (bool) True si tous KO, False sinon
|
|
"""
|
|
for pokemon in self.equipe:
|
|
if not pokemon.est_ko():
|
|
return False
|
|
return True
|
|
|
|
def __repr__(self):
|
|
"""Représentation du dresseur."""
|
|
result = f"Dresseur {self.nom} - {len(self.equipe)} Pokémon"
|
|
for pokemon in self.equipe:
|
|
result += f"\n - {pokemon}"
|
|
return result
|
|
|
|
|
|
# =============================================================================
|
|
# PARTIE 3 : Classe Combat
|
|
# =============================================================================
|
|
|
|
class Combat:
|
|
def __init__(self, dresseur1, dresseur2):
|
|
"""
|
|
Constructeur de la classe Combat.
|
|
|
|
:param dresseur1: (Dresseur) Premier dresseur
|
|
:param dresseur2: (Dresseur) Second dresseur
|
|
"""
|
|
self.dresseur1 = dresseur1
|
|
self.dresseur2 = dresseur2
|
|
self.tour = 0
|
|
|
|
def afficher_etat(self):
|
|
"""Affiche l'état actuel du combat."""
|
|
print(f"\n{'='*40}")
|
|
print(f"Tour {self.tour}")
|
|
print(f"{'='*40}")
|
|
|
|
poke1 = self.dresseur1.premier_pokemon_dispo()
|
|
poke2 = self.dresseur2.premier_pokemon_dispo()
|
|
|
|
if poke1:
|
|
print(f"{self.dresseur1.nom}: {poke1.nom} ({poke1.pv}/{poke1.pv_max} PV)")
|
|
if poke2:
|
|
print(f"{self.dresseur2.nom}: {poke2.nom} ({poke2.pv}/{poke2.pv_max} PV)")
|
|
print()
|
|
|
|
def lancer_combat(self):
|
|
"""
|
|
Lance le combat tour par tour.
|
|
Chaque tour, les deux Pokémon actifs s'attaquent.
|
|
Quand un Pokémon est KO, le suivant prend sa place.
|
|
Le combat s'arrête quand un dresseur n'a plus de Pokémon.
|
|
"""
|
|
print(f"\n*** COMBAT : {self.dresseur1.nom} VS {self.dresseur2.nom} ***")
|
|
|
|
while not self.dresseur1.tous_ko() and not self.dresseur2.tous_ko():
|
|
self.tour += 1
|
|
self.afficher_etat()
|
|
|
|
# Récupérer les Pokémon actifs
|
|
poke1 = self.dresseur1.premier_pokemon_dispo()
|
|
poke2 = self.dresseur2.premier_pokemon_dispo()
|
|
|
|
# Le Pokémon 1 attaque
|
|
poke1.attaquer(poke2)
|
|
|
|
# Vérifier si Pokémon 2 est KO
|
|
if poke2.est_ko():
|
|
print(f"\n{poke2.nom} est KO !")
|
|
nouveau = self.dresseur2.premier_pokemon_dispo()
|
|
if nouveau:
|
|
print(f"{self.dresseur2.nom} envoie {nouveau.nom} !")
|
|
continue # Passer au tour suivant
|
|
|
|
# Le Pokémon 2 attaque
|
|
poke2.attaquer(poke1)
|
|
|
|
# Vérifier si Pokémon 1 est KO
|
|
if poke1.est_ko():
|
|
print(f"\n{poke1.nom} est KO !")
|
|
nouveau = self.dresseur1.premier_pokemon_dispo()
|
|
if nouveau:
|
|
print(f"{self.dresseur1.nom} envoie {nouveau.nom} !")
|
|
|
|
# Afficher le vainqueur
|
|
print(f"\n{'='*40}")
|
|
if self.dresseur1.tous_ko():
|
|
print(f"Tous les Pokémon de {self.dresseur1.nom} sont KO !")
|
|
print(f"*** {self.dresseur2.nom.upper()} REMPORTE LE COMBAT ! ***")
|
|
else:
|
|
print(f"Tous les Pokémon de {self.dresseur2.nom} sont KO !")
|
|
print(f"*** {self.dresseur1.nom.upper()} REMPORTE LE COMBAT ! ***")
|
|
print(f"{'='*40}")
|
|
|
|
|
|
# =============================================================================
|
|
# PARTIE 4 : Centre Pokémon
|
|
# =============================================================================
|
|
|
|
class CentrePokemon:
|
|
def __init__(self, ville):
|
|
"""
|
|
:param ville: (str) Ville où se trouve le centre
|
|
"""
|
|
self.ville = ville
|
|
|
|
def soigner_equipe(self, dresseur):
|
|
"""
|
|
Soigne tous les Pokémon d'un dresseur à 100% de leurs PV.
|
|
|
|
:param dresseur: (Dresseur) Dresseur dont l'équipe doit être soignée
|
|
"""
|
|
print(f"\n*** Centre Pokémon de {self.ville} ***")
|
|
print(f"Bienvenue {dresseur.nom} !")
|
|
print("Nous allons soigner vos Pokémon...")
|
|
|
|
for pokemon in dresseur.equipe:
|
|
pokemon.pv = pokemon.pv_max
|
|
|
|
print("Vos Pokémon sont en pleine forme !")
|
|
print("À bientôt !\n")
|
|
|
|
|
|
# =============================================================================
|
|
# BONUS : Classe Capacite
|
|
# =============================================================================
|
|
|
|
class Capacite:
|
|
def __init__(self, nom, puissance, type_capacite, pp_max):
|
|
"""
|
|
:param nom: (str) Nom de la capacité
|
|
:param puissance: (int) Puissance de base
|
|
:param type_capacite: (str) Type de la capacité
|
|
:param pp_max: (int) Nombre d'utilisations max
|
|
"""
|
|
self.nom = nom
|
|
self.puissance = puissance
|
|
self.type_capacite = type_capacite
|
|
self.pp_max = pp_max
|
|
self.pp = pp_max
|
|
|
|
def utiliser(self):
|
|
"""Utilise la capacité si PP disponibles."""
|
|
if self.pp > 0:
|
|
self.pp -= 1
|
|
return True
|
|
else:
|
|
print(f"{self.nom} : plus de PP !")
|
|
return False
|
|
|
|
def __repr__(self):
|
|
return f"{self.nom} ({self.type_capacite}) - {self.puissance} DMG - {self.pp}/{self.pp_max} PP"
|
|
|
|
|
|
# =============================================================================
|
|
# TESTS
|
|
# =============================================================================
|
|
|
|
if __name__ == "__main__":
|
|
print("=" * 50)
|
|
print("TEST DES CLASSES POKEMON")
|
|
print("=" * 50)
|
|
|
|
# Création des Pokémon
|
|
pikachu = Pokemon("Pikachu", "Electrik", 25, 80, 15)
|
|
dracaufeu = Pokemon("Dracaufeu", "Feu", 50, 150, 25)
|
|
tortank = Pokemon("Tortank", "Eau", 45, 140, 22)
|
|
onix = Pokemon("Onix", "Roche", 30, 120, 18)
|
|
racaillou = Pokemon("Racaillou", "Roche", 20, 80, 12)
|
|
|
|
print("\nPokémon créés :")
|
|
print(f" - {pikachu}")
|
|
print(f" - {dracaufeu}")
|
|
print(f" - {tortank}")
|
|
print(f" - {onix}")
|
|
print(f" - {racaillou}")
|
|
|
|
# Test des attaques avec faiblesses
|
|
print("\n--- Test attaque avec faiblesse ---")
|
|
print(f"Avant : {onix}")
|
|
tortank.attaquer(onix) # Eau bat Roche -> x2
|
|
print(f"Après : {onix}")
|
|
|
|
# Création des dresseurs
|
|
print("\n" + "=" * 50)
|
|
print("CREATION DES DRESSEURS")
|
|
print("=" * 50)
|
|
|
|
sacha = Dresseur("Sacha")
|
|
sacha.ajouter_pokemon(Pokemon("Pikachu", "Electrik", 25, 80, 15))
|
|
sacha.ajouter_pokemon(Pokemon("Dracaufeu", "Feu", 50, 150, 25))
|
|
sacha.ajouter_pokemon(Pokemon("Tortank", "Eau", 45, 140, 22))
|
|
|
|
pierre = Dresseur("Pierre")
|
|
pierre.ajouter_pokemon(Pokemon("Onix", "Roche", 30, 120, 18))
|
|
pierre.ajouter_pokemon(Pokemon("Racaillou", "Roche", 20, 80, 12))
|
|
|
|
print(f"\n{sacha}")
|
|
print(f"\n{pierre}")
|
|
|
|
# Lancement du combat
|
|
print("\n" + "=" * 50)
|
|
print("LANCEMENT DU COMBAT")
|
|
print("=" * 50)
|
|
|
|
combat = Combat(sacha, pierre)
|
|
combat.lancer_combat()
|
|
|
|
# Soins au Centre Pokémon
|
|
print("\n" + "=" * 50)
|
|
print("SOINS AU CENTRE POKEMON")
|
|
print("=" * 50)
|
|
|
|
centre = CentrePokemon("Argenta")
|
|
centre.soigner_equipe(sacha)
|
|
print(sacha)
|