Menu
CoddyTech

Desarrollo de personajes de videojuegos

Parte de la sección Programación orientada a objetos del Journey de Python de Coddy. Lección 63 de 64.

challenge icon

Desafío

Intermedio

En este desafío, implementarás un sistema de personajes de RPG en varios archivos con una cobertura de pruebas exhaustiva.

  • character.py - Implementa la clase base Character
  • warrior.py - Implementa la subclase Warrior
  • mage.py - Implementa la subclase Mage
  • rogue.py - Implementa la subclase Rogue
  • ability.py - Implementa la clase Ability

Cada archivo contiene comentarios detallados TODO que guían tu implementación. Sigue estos comentarios para asegurarte de que tu código cumpla todos los requisitos.

Pruébalo tú mismo

from character import Character
from warrior import Warrior
from mage import Mage
from rogue import Rogue
from ability import Ability

# Gestor completo de casos de prueba que abarca todos los escenarios y casos límite
test_case = input()

if test_case == "character_creation":
    # Probar la creación de distintas clases de personajes
    warrior = Warrior("Aragorn", 1)
    mage = Mage("Gandalf", 1)
    rogue = Rogue("Legolas", 1)
    
    print(f"Warrior: {warrior.name}, HP: {warrior.health}, Mana: {warrior.mana}, Str: {warrior.strength}")
    print(f"Mage: {mage.name}, HP: {mage.health}, Mana: {mage.mana}, Int: {mage.intelligence}")
    print(f"Rogue: {rogue.name}, HP: {rogue.health}, Mana: {rogue.mana}, Agi: {rogue.agility}")

elif test_case == "character_levelup":
    # Probar la subida de nivel de distintas clases
    warrior = Warrior("Aragorn")
    mage = Mage("Gandalf")
    rogue = Rogue("Legolas")
    
    print("Before level up:")
    print(f"Warrior - Level: {warrior.level}, HP: {warrior.max_health}, Str: {warrior.strength}")
    print(f"Mage - Level: {mage.level}, Mana: {mage.max_mana}, Int: {mage.intelligence}")
    print(f"Rogue - Level: {rogue.level}, Agi: {rogue.agility}")
    
    warrior.level_up()
    mage.level_up()
    rogue.level_up()
    
    print("\nAfter level up:")
    print(f"Warrior - Level: {warrior.level}, HP: {warrior.max_health}, Str: {warrior.strength}")
    print(f"Mage - Level: {mage.level}, Mana: {mage.max_mana}, Int: {mage.intelligence}")
    print(f"Rogue - Level: {rogue.level}, Agi: {rogue.agility}")

elif test_case == "combat_basic":
    # Probar las mecánicas básicas de combate
    warrior = Warrior("Aragorn", 5)
    enemy = Character("Orc", 3)
    
    print(f"Initial HP - {warrior.name}: {warrior.health}, {enemy.name}: {enemy.health}")
    
    # El guerrero ataca al enemigo
    warrior.attack(enemy)
    print(f"After warrior attack - Enemy HP: {enemy.health}")
    
    # El enemigo contraataca
    enemy.attack(warrior)
    print(f"After enemy attack - Warrior HP: {warrior.health}")
    
    # Comprobar si sigue con vida
    print(f"Is warrior alive? {warrior.is_alive()}")
    print(f"Is enemy alive? {enemy.is_alive()}")

elif test_case == "class_specific_attacks":
    # Probar las implementaciones de ataque específicas de cada clase
    warrior = Warrior("Aragorn", 5)
    mage = Mage("Gandalf", 5)
    rogue = Rogue("Legolas", 5)
    
    target = Character("Training Dummy", 10)
    target.defense = 0  # Eliminar la defensa para comparar el daño sin interferencias
    
    # Restablecer la salud del objetivo entre ataques
    initial_health = target.health
    
    warrior.attack(target)
    warrior_damage = initial_health - target.health
    target.health = initial_health
    
    mage.attack(target)
    mage_damage = initial_health - target.health
    target.health = initial_health
    
    rogue.attack(target)
    rogue_damage = initial_health - target.health
    
    print(f"Warrior damage: {warrior_damage:.1f}")
    print(f"Mage damage: {mage_damage:.1f}")
    print(f"Rogue damage: {rogue_damage:.1f}")
    
    # Comprobar la regeneración de maná del mago
    initial_mana = mage.mana
    mage.attack(target)
    print(f"Mage mana before attack: {initial_mana}, after attack: {mage.mana}")

elif test_case == "abilities":
    # Probar el sistema de habilidades
    fireball = Ability("Fireball", 30, 25)
    slash = Ability("Slash", 15, 20)
    
    mage = Mage("Gandalf", 3)
    warrior = Warrior("Aragorn", 3)
    
    mage.learn_ability(fireball)
    warrior.learn_ability(slash)
    
    target = Character("Orc", 5)
    initial_health = target.health
    
    # Probar el uso de una habilidad por parte del mago
    print(f"Mage mana before: {mage.mana}")
    mage.use_ability(0, target)
    print(f"Mage mana after: {mage.mana}")
    print(f"Target health: {target.health}")
    
    target.health = initial_health
    
    # Probar el uso de una habilidad por parte del guerrero
    print(f"Warrior mana before: {warrior.mana}")
    warrior.use_ability(0, target)
    print(f"Warrior mana after: {warrior.mana}")
    print(f"Target health: {target.health}")
    
    # Probar qué ocurre cuando no hay suficiente maná
    mage.mana = 0
    mage.use_ability(0, target)

elif test_case == "damage_calculation":
    # Probar el cálculo del daño teniendo en cuenta la defensa
    warrior = Warrior("Aragorn", 5)
    
    low_defense = Character("Goblin", 3)
    low_defense.defense = 2
    
    high_defense = Character("Armored Knight", 3)
    high_defense.defense = 15
    
    # Atacar a un objetivo con poca defensa
    damage_to_low = warrior.attack(low_defense)
    
    # Atacar a un objetivo con mucha defensa
    damage_to_high = warrior.attack(high_defense)
    
    print(f"Damage to low defense target: {damage_to_low:.1f}")
    print(f"Damage to high defense target: {damage_to_high:.1f}")
    
    # Probar la regla del daño mínimo
    super_defense = Character("Impenetrable Shield", 1)
    super_defense.defense = 100
    damage_to_super = warrior.attack(super_defense)
    print(f"Damage to extremely high defense: {damage_to_super:.1f}")

elif test_case == "full_battle_simulation":
    # Probar una batalla completa entre personajes
    warrior = Warrior("Aragorn", 5)
    mage = Mage("Saruman", 5)
    
    fireball = Ability("Fireball", 30, 40)
    ice_spike = Ability("Ice Spike", 25, 35)
    cleave = Ability("Cleave", 20, 30)
    
    warrior.learn_ability(cleave)
    mage.learn_ability(fireball)
    mage.learn_ability(ice_spike)
    
    print(f"Battle begins: {warrior.name} vs {mage.name}")
    print(f"{warrior.name}: {warrior.health}/{warrior.max_health} HP, {warrior.mana}/{warrior.max_mana} Mana")
    print(f"{mage.name}: {mage.health}/{mage.max_health} HP, {mage.mana}/{mage.max_mana} Mana")
    
    round_num = 1
    while warrior.is_alive() and mage.is_alive():
        print(f"\n--- Round {round_num} ---")
        
        # Turno del guerrero
        if round_num % 3 == 0 and warrior.mana >= cleave.mana_cost:
            warrior.use_ability(0, mage)
        else:
            warrior.attack(mage)
        
        # Comprobar si el mago ha sido derrotado
        if not mage.is_alive():
            print(f"{mage.name} has been defeated!")
            break
        
        # Turno del mago
        if mage.mana >= fireball.mana_cost:
            mage.use_ability(0, warrior)
        else:
            mage.attack(warrior)
        
        # Comprobar si el guerrero ha sido derrotado
        if not warrior.is_alive():
            print(f"{warrior.name} has been defeated!")
            break
        
        print(f"Status: {warrior.name} ({warrior.health:.1f} HP, {warrior.mana} Mana) | {mage.name} ({mage.health:.1f} HP, {mage.mana} Mana)")
        round_num += 1
        
        # Límite para evitar bucles infinitos
        if round_num > 10:
            print("Battle exceeded 10 rounds and was called a draw.")
            break
    
    print("\nBattle Results:")
    print(f"{warrior.name}: {warrior.health:.1f}/{warrior.max_health} HP remaining")
    print(f"{mage.name}: {mage.health:.1f}/{mage.max_health} HP remaining")
    
    if warrior.is_alive() and not mage.is_alive():
        print(f"{warrior.name} wins!")
    elif mage.is_alive() and not warrior.is_alive():
        print(f"{mage.name} wins!")
    else:
        print("The battle ended in a draw!")

elif test_case == "inheritance_validation_test":
    # Validación exhaustiva de la herencia
    objects = []
    if 'Character' in locals():
        objects.append(Character('test_param'))
    if 'Warrior' in locals():
        objects.append(Warrior('test_param'))
    if 'Mage' in locals():
        objects.append(Mage('test_param'))
    if 'Rogue' in locals():
        objects.append(Rogue('test_param'))
    if 'Ability' in locals():
        objects.append(Ability('test_param', 10, 20))
    
    for obj in objects:
        print(f'{type(obj).__name__}:')
        print(f'  MRO: {[cls.__name__ for cls in type(obj).__mro__]}')
        print()

elif test_case == "method_overriding_test":
    # Probar el comportamiento de la sobrescritura de métodos
    print('Testing method overriding...')
    # Crear instancias y probar los métodos sobrescritos
    if 'Warrior' in locals():
        obj = Warrior('test')
        print(f'Warrior methods work correctly')
    if 'Mage' in locals():
        obj = Mage('test')
        print(f'Mage methods work correctly')
    if 'Rogue' in locals():
        obj = Rogue('test')
        print(f'Rogue methods work correctly')

elif test_case == "attribute_access_test":
    # Probar el acceso a los atributos
    print('Testing attribute access...')
    if 'Character' in locals():
        obj = Character('test')
        print(f'Character attributes accessible')
    if 'Warrior' in locals():
        obj = Warrior('test')
        print(f'Warrior attributes accessible')
    if 'Mage' in locals():
        obj = Mage('test')
        print(f'Mage attributes accessible')
    if 'Rogue' in locals():
        obj = Rogue('test')
        print(f'Rogue attributes accessible')
    if 'Ability' in locals():
        obj = Ability('test', 10, 20)
        print(f'Ability attributes accessible')

elif test_case == "boundary_conditions_test":
    # Probar las condiciones límite y los valores extremos
    print('Testing boundary conditions...')
    
    # Probar un personaje con 0 puntos de salud
    char = Character("Test", 1)
    char.health = 0
    print(f"Character at 0 HP is alive: {char.is_alive()}")
    
    # Probar un personaje con 1 punto de salud
    char2 = Character("Test2", 1)
    char2.health = 1
    print(f"Character at 1 HP is alive: {char2.is_alive()}")
    
    # Probar un índice de habilidad no válido (negativo)
    warrior = Warrior("Test", 1)
    result = warrior.use_ability(-1, char)
    print(f"Invalid negative ability index returns: {result}")
    
    # Probar un índice de habilidad no válido (demasiado alto)
    result = warrior.use_ability(999, char)
    print(f"Invalid high ability index returns: {result}")
    
    # Probar el daño mínimo (1) contra una defensa extremadamente alta
    attacker = Character("Attacker", 1)
    defender = Character("Defender", 1)
    defender.defense = 1000
    initial_hp = defender.health
    attacker.attack(defender)
    damage = initial_hp - defender.health
    print(f"Minimum damage dealt: {damage}")
    
    print('Boundary conditions test completed')

elif test_case == "error_handling_test":
    # Probar el manejo de errores y los casos de excepción
    print('Testing error handling...')
    
    # Probar el uso de una habilidad con maná insuficiente
    mage = Mage("TestMage", 1)
    ability = Ability("Expensive", 1000, 50)
    mage.learn_ability(ability)
    target = Character("Target", 1)
    result = mage.use_ability(0, target)
    print(f"Ability with insufficient mana returns: {result}")
    
    # Probar el uso de una habilidad sin haber aprendido ninguna
    warrior = Warrior("TestWarrior", 1)
    result = warrior.use_ability(0, target)
    print(f"Using non-existent ability returns: {result}")
    
    # Comprobar que la salud no sea negativa
    char = Character("Test", 1)
    char.take_damage(1000)
    print(f"Health after massive damage: {char.health}")
    
    print('Error handling test completed')

elif test_case == "polymorphic_behavior_test":
    # Probar el comportamiento polimórfico con distintos objetos
    print('Testing polymorphic behavior...')
    
    # Crear una lista de distintos tipos de personajes
    characters = [
        Character("Generic", 1),
        Warrior("WarriorTest", 1),
        Mage("MageTest", 1),
        Rogue("RogueTest", 1)
    ]
    
    # Comprobar que todos puedan tratarse como Character
    for char in characters:
        print(f"{char.name}: Type={type(char).__name__}, IsAlive={char.is_alive()}")
    
    # Probar las llamadas a métodos polimórficos
    target = Character("Target", 10)
    target.health = 1000  # Salud alta para sobrevivir
    
    for char in characters:
        damage = char.attack(target)
    
    print('Polymorphic behavior test completed')

elif test_case == "stress_test":
    # Prueba de estrés con múltiples objetos
    import time
    start_time = time.time()
    
    objects = []
    for i in range(50):
        try:
            objects.append(Character(f'test_{i}'))
        except:
            pass  # Gestionar los errores de creación sin interrumpir la ejecución
        try:
            objects.append(Warrior(f'test_{i}'))
        except:
            pass  # Gestionar los errores de creación sin interrumpir la ejecución
        try:
            objects.append(Mage(f'test_{i}'))
        except:
            pass  # Gestionar los errores de creación sin interrumpir la ejecución
        try:
            objects.append(Rogue(f'test_{i}'))
        except:
            pass  # Gestionar los errores de creación sin interrumpir la ejecución
        try:
            objects.append(Ability(f'test_{i}', 10, 20))
        except:
            pass  # Gestionar los errores de creación sin interrumpir la ejecución
    
    end_time = time.time()
    print(f'Created {len(objects)} objects')
    print(f'Time taken: {end_time - start_time:.4f} seconds')
    print('Stress test completed')

elif test_case == "comprehensive_validation":
    # Prueba de validación exhaustiva
    print('=== Comprehensive Validation Test ===')
    
    # Prueba 1: Creación básica de objetos
    print('1. Basic Object Creation:')
    success_count = 0
    classes = ['Character', 'Warrior', 'Mage', 'Rogue', 'Ability']
    
    try:
        obj = Character('test')
        success_count += 1
        print(f'   Character: Created successfully')
    except Exception as e:
        print(f'   Character: Creation failed - {e}')
    try:
        obj = Warrior('test')
        success_count += 1
        print(f'   Warrior: Created successfully')
    except Exception as e:
        print(f'   Warrior: Creation failed - {e}')
    try:
        obj = Mage('test')
        success_count += 1
        print(f'   Mage: Created successfully')
    except Exception as e:
        print(f'   Mage: Creation failed - {e}')
    try:
        obj = Rogue('test')
        success_count += 1
        print(f'   Rogue: Created successfully')
    except Exception as e:
        print(f'   Rogue: Creation failed - {e}')
    try:
        obj = Ability('test', 10, 20)
        success_count += 1
        print(f'   Ability: Created successfully')
    except Exception as e:
        print(f'   Ability: Creation failed - {e}')
    
    print(f'   Successfully created {success_count}/{len(classes)} classes')
    
    print('=== Validation Complete ===')

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de Python online